diff --git a/sc2/AUTHORS b/sc2/AUTHORS new file mode 100644 index 000000000..e9627af9e --- /dev/null +++ b/sc2/AUTHORS @@ -0,0 +1,13 @@ +# This AUTHORS file is used as input for cvs2cl. +# Lines beginning with (whitespaces plus) # and lines that do not have +# colons in them are always ignored. Other lines are in the form +# name : expansion +# Quote marks stripped. Leading spaces not allowed. +# cvs2cl will detect if you have a realname, +# and will retain the username if not. + +# Programming: + +# Additional programming: +mudry: Mudrony László + diff --git a/sc2/COPYING b/sc2/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/sc2/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/sc2/ChangeLog b/sc2/ChangeLog new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/HACKING b/sc2/HACKING new file mode 100644 index 000000000..36865c323 --- /dev/null +++ b/sc2/HACKING @@ -0,0 +1,30 @@ +If you modify the sources or get them from the CVS repository, +you may need the following programs in addition to those listed in INSTALL: + +CVS - Concurrent Versions System + http://www.loria.fr/~molli/cvs-index.html + http://www.cvshome.org + Debian package: cvs + +GNU Autoconf + http://www.gnu.org/software/autoconf/autoconf.html + Debian package: autoconf + +GNU Automake - a Makefile generator + http://www.gnu.org/software/automake/ + Debian package: automake + +GNU Libtool - generic shared library support + http://www.gnu.org/software/libtool/ + ftp://ftp.gnu.org/pub/gnu/libtool/ + Debian package: libtool + +If you find these aren't enough, or if you know the names +of the corresponding RPM etc. packages, please report to +. + +For the CVS repository see sc2.sourceforge.net. + +(Note: this file was written by Mudry , +and is a straight copy of the FSCP one.) + diff --git a/sc2/INSTALL b/sc2/INSTALL new file mode 100644 index 000000000..87954b654 --- /dev/null +++ b/sc2/INSTALL @@ -0,0 +1,42 @@ +To build The Urquan Masters, you need at least the following software: + +GCC - GNU C Compiler + http://gcc.gnu.org/ + Debian package: gcc + +GNU Make + ftp://ftp.gnu.org/ + Debian package: make + +Additionally, The Urquan Masters requires the following libraries: + +OpenGL v1.2 + http://www.xfree86.org/ + Debian package: xlibmesa-dev OR nvidia-glx OR + XFree86 4.x comes with Mesa, which is a clone. + Note: Mesa is a software emulation. For enjoyable results + you will need hardware accelerated OpenGL (GLX). + These usally conflict with mesa (can result in X server crash) + +SDL v1.2 + The Simple Direct-Media Layer + A fairly good multiplatform low level graphics library. + Homepage: www.libsdl.org + Debian package: libsdl1.2-dev (and various runtime debs) + +SDL-image + An image loading library used with SDL. + Homepage: http://www.libsdl.org/projects/SDL_image/ + Download: http://www.libsdl.org/projects/SDL_image/release/ + +SDL-mixer + A sound mixing library used with SDL. + Homepage: http://www.libsdl.org/projects/SDL_mixer/ + Download: http://www.libsdl.org/projects/SDL_mixer/release/ + + +If you find these aren't enough, or if you know the names +of the corresponding RPM etc. packages, please report to + or visit +http://sourceforge.net/projects/sc2 + diff --git a/sc2/INSTALL.generic b/sc2/INSTALL.generic new file mode 100644 index 000000000..666ffd9f8 --- /dev/null +++ b/sc2/INSTALL.generic @@ -0,0 +1,226 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for variables by setting +them in the environment. You can do that on the command line like this: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Environment Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it cannot guess the host type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the host +platform (i.e., that on which the generated programs will eventually be +run) with `--host=TYPE'. In this case, you should also specify the +build platform with `--build=TYPE', because, in this case, it may not +be possible to guess the build platform (it sometimes involves +compiling and running simple test programs, and this can't be done if +the compiler is a cross compiler). + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Environment Variables +===================== + + Variables not defined in a site shell script can be set in the +environment passed to configure. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/sc2/Makefile.am b/sc2/Makefile.am new file mode 100644 index 000000000..8c1d0b2d4 --- /dev/null +++ b/sc2/Makefile.am @@ -0,0 +1,7 @@ + +SUBDIRS = src + +ACLOCAL_AMFLAGS = + +EXTRA_DIST = # config.rpath mkinstalldirs + diff --git a/sc2/NEWS b/sc2/NEWS new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/README b/sc2/README new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/configure.ac b/sc2/configure.ac new file mode 100644 index 000000000..283a8aa5c --- /dev/null +++ b/sc2/configure.ac @@ -0,0 +1,205 @@ +# autoconf master file. Mudry +# Read README.ac! + +# Process this file with autoconf to produce a configure script. + +# Initialize autoconf +AC_PREREQ(2.50) +AC_INIT(src/starcon2.c) + +# Detect the canonical host and target build environment +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +# Define package name and version here. This should be the only place +# where the actual version number appears! Use the PACKAGE and VERSION +# varaibles/defines elsewhere. +AM_INIT_AUTOMAKE(sc2, 0.1) + +# Make current date available for our tools +ISODATE=`date +%Y-%m-%d` +AC_SUBST(ISODATE) + +# This allows "--enable-maintainer-mode" +AM_MAINTAINER_MODE + +# -------------------------------------------------------------------------- + +# Configurables + +CFLAGS="$CFLAGS -g" +CPPFLAGS="$CPPFLAGS -g" + +# These defines seem to be missing, and they are added here as a workaround. + +AC_DEFINE(SAFE_X, (0), [If know what it is it for tell me]) +AC_DEFINE(SAFE_Y, (0), [If know what it is it for tell me]) + +# -------------------------------------------------------------------------- + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_RANLIB + +# Checks for typedefs, structures, and compiler characteristics. +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_HEADER_STDC +#AC_CHECK_TYPES(int8_t) +AC_C_BIGENDIAN +AC_C_CONST +AC_C_INLINE +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_EXEEXT + +# Checks for library functions. +# AC_FUNC_ALLOCA +# AC_FUNC_MALLOC +AC_CHECK_FUNCS([strupr]) + +# -------------------------------------------------------------------------- + +# This section checks for special libs, as SDL and OpenGL + +# Checks for misc libs +#AC_CHECK_LIB([m], [sin]) +#AC_CHECK_LIB([ltdl], [lt_dlopen]) +#AC_CHECK_LIB([SDL_image],[IMG_Load]) +#AC_CHECK_LIB([SGE],[sge_tt_textout]) + +# Check for SDL +SDL_VERSION=1.2.2 +SMPEG_VERSION=0.4.0 +AM_PATH_SDL($SDL_VERSION, , AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])) +AM_PATH_SMPEG($SMPEG_VERSION, , AC_MSG_ERROR([*** smpeg version $SMPEG_VERSION not found!])) +AC_CHECK_LIB(SDL_mixer, main, , AC_MSG_ERROR(Your system is missing libSDL_mixer!),`sdl-config --libs`) +AC_CHECK_LIB(SDL_image, main, , AC_MSG_ERROR(Your system is missing libSDL_image!),`sdl-config --libs`) +AC_CHECK_LIB(smpeg, main, , AC_MSG_ERROR(Your system is missing libsmpeg!),`smpeg-config --libs`) +AC_CHECK_HEADERS(SDL/SDL_image.h, , AC_MSG_ERROR(Your system is missing SDL_image.h!)) +AC_CHECK_HEADERS(SDL/SDL_mixer.h, , AC_MSG_ERROR(Your system is missing SDL_mixer.h!)) + +# Select platform dependent OpenGL libs.. (tweak your patform here) +case "$target" in + *-*-linux-gnu*) + SYS_GL_LIBS="-lGL" + ;; + *-*-cygwin* | *-*-mingw32*) + SYS_GL_LIBS="-lopengl32" + SYS_GL_CFLAGS="-DGL_VERSION_1_2" + ;; + *-*-beos*) + SYS_GL_LIBS="-lGL" + ;; + *-*-darwin*) + SYS_GL_LIBS="" + ;; + *) + if test x$have_x = xyes; then + CFLAGS="$CFLAGS $X_CFLAGS" + SYS_GL_LIBS="$X_LIBS -lGL" + else + SYS_GL_LIBS="-lGL" + fi + ;; +esac + +# Check for OpenGL +AC_MSG_CHECKING(for OpenGL support) +have_opengl=no +AC_TRY_COMPILE([ + #if defined(__APPLE__) && defined(__MACH__) + #include + #else + #include + #endif +],[ +],[ +have_opengl=yes +]) +AC_MSG_RESULT($have_opengl) +GL_LIBS=$SYS_GL_LIBS +AC_SUBST(GL_LIBS) + +# Figure out which math library to use +case "$target" in + *-*-linux-gnu*) + MATHLIB="" + ;; + *-*-cygwin* | *-*-mingw32*) + MATHLIB="" + ;; + *-*-beos*) + MATHLIB="" + ;; + *-*-darwin*) + MATHLIB="" + ;; + *) + MATHLIB="-lm" + AC_PATH_X + AC_PATH_XTRA + if test x$have_x = xyes; then + CFLAGS="$CFLAGS $X_CFLAGS" + fi + ;; +esac +AC_SUBST(MATHLIB) + +# -------------------------------------------------------------------------- + +# This section is optional but contains suggested features such as libtool +# and gettext support. + +# Libtool support +AM_DISABLE_SHARED +AM_PROG_LIBTOOL + +# Use this if we going to use dlopen (dynamic modules) +# LIBADD_DL=-dlopen + +# Internationalization support +# AM_GNU_GETTEXT + +# supported languages: +# ALL_LINGUAS="" + +# Set PACKAGE_LOCALE_DIR in config.h. +if test "x${prefix}" = "xNONE"; then + AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${ac_default_prefix}/${DATADIRNAME}/locale$", "Locale files") +else + AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${prefix}/${DATADIRNAME}/locale", "Locale files") +fi + +# -------------------------------------------------------------------------- + +# Output configuration + +AM_CONFIG_HEADER(config.h) + +# "intl/Makefile po/Makefile.in m4/Makefile" is added when +# autogen.sh runs. + +AC_CONFIG_FILES([ + Makefile + src/Makefile + src/sc2code/Makefile + src/sc2code/libs/Makefile + src/sc2code/libs/decomp/Makefile + src/sc2code/libs/memory/Makefile + src/sc2code/libs/strings/Makefile + src/sc2code/libs/resource/Makefile + src/sc2code/libs/math/Makefile + src/sc2code/libs/input/Makefile + src/sc2code/libs/sound/Makefile + src/sc2code/libs/graphics/Makefile + src/sc2code/libs/video/Makefile + src/sc2code/planets/Makefile + src/sc2code/ships/Makefile + src/sc2code/comm/Makefile +]) + +AC_OUTPUT + diff --git a/sc2/src/Makefile.am b/sc2/src/Makefile.am new file mode 100644 index 000000000..06a1c94bb --- /dev/null +++ b/sc2/src/Makefile.am @@ -0,0 +1,20 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +SUBDIRS = sc2code + +CFLAGS = -Wall + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +bin_PROGRAMS = sc2 + +sc2_SOURCES = SDL_wrapper.c port.c starcon2.c trackplayer.c +sc2_LDADD = sc2code/libsc2.la @SDL_LIBS@ @GL_LIBS@ @SMPEG_LIBS@ +noinst_HEADERS = SDL_wrapper.h + diff --git a/sc2/src/SDL_wrapper.c b/sc2/src/SDL_wrapper.c new file mode 100644 index 000000000..b840a1db5 --- /dev/null +++ b/sc2/src/SDL_wrapper.c @@ -0,0 +1,1953 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/****************************************** + + Star Control II: 3DO => SDL Port + + Copyright Toys for Bob, 2002 + + 3DO_wrapper.cpp programmer: Chris Nelson + +*******************************************/ + +// + +#include "libs/graphics/gfxintrn.h" +#include "libs/input/inpintrn.h" +#include "SDL_wrapper.h" + +//#if SDL_BYTEORDER == SDL_BIG_ENDIAN + +#define NUMBER_OF_PLUTVALS 32 +#define NUMBER_OF_PLUT_UINT32s (NUMBER_OF_PLUTVALS >> 1) +#define GET_VAR_PLUT(i) (_varPLUTs + (i) * NUMBER_OF_PLUT_UINT32s) +DWORD* _varPLUTs; //Not a function +PDISPLAY_INTERFACE _pCurDisplay; //Not a function. Probably has to be initialized... + +void (*mask_func_array[]) + (PRECT pClipRect, PRIMITIVEPTR PrimPtr) + = { 0 }; + +//Status: Implemented! +DWORD +GetTimeCounter () //I wonder if it's ms, ticks, or seconds... +{ + DWORD ret; + + ret = (DWORD) (SDL_GetTicks () * ONE_SECOND / 1000.0); + return (ret); +} + +void +BatchGraphics (void) +{ +} + +void +UnbatchGraphics (void) +{ +} + +//Status: Unimplemented +DWORD +XFormColorMap (COLORMAPPTR colormap, SIZE time) + // Not sure what the time's supposed to mean... +{ + // printf ("Unimplemented function activated: XFormColorMap()\n"); + return (GetTimeCounter () + time); +} + +static volatile int continuity_break; + +void +FlushGraphics (void) +{ + continuity_break = 1; +} + +void +DrawFromExtraScreen (PRECT r) //No scaling? +{ + RECT locRect; + TFB_DrawCommand* DC; + + if (!r) + { + locRect.corner.x = locRect.corner.y = 0; + locRect.extent.width = SCREEN_WIDTH; + locRect.extent.height = SCREEN_HEIGHT; + r = &locRect; + } + + DC=HMalloc(sizeof(TFB_DrawCommand)); + + DC->Type = TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER; + DC->x = r->corner.x; + DC->y = r->corner.y; + DC->w = r->extent.width; + DC->h = r->extent.height; + + TFB_EnqueueDrawCommand (DC); +} + +void +SetGraphicUseOtherExtra (int other) //Could this possibly be more cryptic?!? :) +{ +} + +void +LoadIntoExtraScreen (PRECT r) //like a glTexture? +{ + RECT locRect; + TFB_DrawCommand *DC; + + if (!r) + { + locRect.corner.x = locRect.corner.y = 0; + locRect.extent.width = SCREEN_WIDTH; + locRect.extent.height = SCREEN_HEIGHT; + r = &locRect; + } + +// printf ("LoadIntoExtraScreen (%d, %d, {%d, %d})\n", r->corner.x, r->corner.y, r->extent.width, r->extent.height); + DC = HMalloc (sizeof (TFB_DrawCommand)); + + DC->Type = TFB_DRAWCOMMANDTYPE_COPYBACKBUFFERTOOTHERBUFFER; + DC->x = r->corner.x; + DC->y = r->corner.y; + DC->w = r->extent.width; + DC->h = r->extent.height; + DC->image = 0; + + TFB_EnqueueDrawCommand (DC); +} + +void +SetGraphicGrabOther (int grab_other) +{ +} + +//Status: Unimplemented +void +ScreenTransition (int TransType, PRECT pRect) //TransType==3 +{ + //printf ("Unimplemented function activated: ScreenTransition()\n"); +} + +//Status: Unimplemented +UNICODE +KBDToUNICODE (UNICODE SK_in) + //This one'll probably require a big table. Arg. +{ + return (SK_in); +} + +//Status: Unimplemented +BOOLEAN +SetColorMap (COLORMAPPTR map) + //There's also a macro for thing in appglue.h... Hmm... +{ + BOOLEAN ret; + + //printf("Unimplemented function activated: SetColorMap()\n"); + ret = TRUE; + return (ret); +} + +//Status: Unimplemented +void +StopSound() + // So does this stop ALL sound? How about music? +{ + Mix_HaltChannel (-1); +} + +//Status: Ignored +BOOLEAN +UninitInput () // Looks like it'll be empty +{ + BOOLEAN ret; + + // printf("Unimplemented function activated: UninitInput()\n"); + ret = TRUE; + return (ret); +} + +static DRAWABLE +alloc_image (COUNT NumFrames, DRAWABLE_TYPE DrawableType, CREATE_FLAGS + flags, SIZE width, SIZE height) +{ + DWORD data_byte_count; + DRAWABLE Drawable; + + data_byte_count = 0; + if (flags & WANT_MASK) + data_byte_count += (DWORD) SCAN_WIDTH (width) * height; + if ((flags & WANT_PIXMAP) && DrawableType == RAM_DRAWABLE) + { + width = ((width << 1) + 3) & ~3; + data_byte_count += (DWORD) width * height; + } + + Drawable = AllocDrawable (NumFrames, data_byte_count * NumFrames); + if (Drawable) + { + if (DrawableType == RAM_DRAWABLE) + { + COUNT i; + DWORD data_offs; + DRAWABLEPTR DrawablePtr; + FRAMEPTR F; + + data_offs = sizeof (*F) * NumFrames; + DrawablePtr = LockDrawable (Drawable); + for (i = 0, F = &DrawablePtr->Frame[0]; i < NumFrames; ++i, ++F) + { + F->DataOffs = data_offs; + data_offs += data_byte_count - sizeof (*F); + } + UnlockDrawable (Drawable); + } + } + + return (Drawable); +} + +static int gscale; + +static void +blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ + TFB_Image *img; + PFRAME_DESC SrcFramePtr; + + SrcFramePtr = (PFRAME_DESC)PrimPtr->Object.Stamp.frame; + if (SrcFramePtr->DataOffs == 0) + { + printf ("Non-existent image to blt()\n"); + return; + } + + img = (TFB_Image *) ((BYTE *) SrcFramePtr + SrcFramePtr->DataOffs); + + if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) + { + TFB_DrawCommand *DrawCommand; + + DrawCommand = HMalloc (sizeof (TFB_DrawCommand)); + if (DrawCommand) + { + DrawCommand->Type = TFB_DRAWCOMMANDTYPE_IMAGE; + DrawCommand->x = pClipRect->corner.x - + GetFrameHotX (_CurFramePtr); + DrawCommand->y = pClipRect->corner.y - + GetFrameHotY (_CurFramePtr); + DrawCommand->w = img->SurfaceSDL->clip_rect.w; + DrawCommand->h = img->SurfaceSDL->clip_rect.h; + if (gscale) + { + DrawCommand->x += (GetFrameHotX (SrcFramePtr) * + ((1 << 8) - gscale)) >> 8; + DrawCommand->y += (GetFrameHotY (SrcFramePtr) * + ((1 << 8) - gscale)) >> 8; + DrawCommand->w = (DrawCommand->w * gscale) >> 8; + DrawCommand->h = (DrawCommand->h * gscale) >> 8; + } + DrawCommand->image = img; //TFB_Image + if (GetPrimType (PrimPtr) == STAMPFILL_PRIM) + { + DWORD c32k; + + c32k = GetPrimColor (PrimPtr) >> 8; // shift out color index + DrawCommand->r = (c32k >> (10 - (8 - 5))) & 0xF8; + DrawCommand->g = (c32k >> (5 - (8 - 5))) & 0xF8; + DrawCommand->b = (c32k << (8 - 5)); + } + + DrawCommand->Qualifier = (TYPE_GET (GetFrameParentDrawable ( + SrcFramePtr)->FlagsAndIndex) >> FTYPE_SHIFT) & + MAPPED_TO_DISPLAY; + + TFB_EnqueueDrawCommand(DrawCommand); + } + } + else + { + SDL_Rect SDL_SrcRect, SDL_DstRect; + + SDL_SrcRect.x = (short) img->SurfaceSDL->clip_rect.x; + SDL_SrcRect.y = (short) img->SurfaceSDL->clip_rect.y; + SDL_SrcRect.w = (short) img->SurfaceSDL->clip_rect.w; + SDL_SrcRect.h = (short) img->SurfaceSDL->clip_rect.h; + + SDL_DstRect.x = (short) pClipRect->corner.x - + GetFrameHotX (_CurFramePtr) + SDL_SrcRect.x; + SDL_DstRect.y = (short) pClipRect->corner.y - + GetFrameHotY (_CurFramePtr) + SDL_SrcRect.y; + + SDL_BlitSurface ( + img->SurfaceSDL, // src + &SDL_SrcRect, // src rect + ((TFB_Image *) ((BYTE *) _CurFramePtr + + _CurFramePtr->DataOffs))->SurfaceSDL, + &SDL_DstRect // dst rect + ); + } +} + +static void +fillrect_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ + BYTE r, g, b; + DWORD c32k; + + c32k = GetPrimColor (PrimPtr) >> 8; //shift out color index + r = (c32k >> (10 - (8 - 5))) & 0xF8; + g = (c32k >> (5 - (8 - 5))) & 0xF8; + b = (c32k << (8 - 5)); + + if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) + { + TFB_DrawCommand *DrawCommand; + + DrawCommand = HMalloc (sizeof (TFB_DrawCommand)); + if (DrawCommand) + { + DrawCommand->Type = TFB_DRAWCOMMANDTYPE_RECTANGLE; + DrawCommand->x = pClipRect->corner.x - GetFrameHotX (_CurFramePtr); + DrawCommand->y = pClipRect->corner.y - GetFrameHotY (_CurFramePtr); + DrawCommand->w = pClipRect->extent.width; + DrawCommand->h = pClipRect->extent.height; + DrawCommand->r = r; + DrawCommand->g = g; + DrawCommand->b = b; + + if (gscale && GetPrimType (PrimPtr) != POINT_PRIM) + { + DrawCommand->w = (DrawCommand->w * gscale) >> 8; + DrawCommand->h = (DrawCommand->h * gscale) >> 8; + DrawCommand->x += (pClipRect->extent.width - + DrawCommand->w) >> 1; + DrawCommand->y += (pClipRect->extent.height - + DrawCommand->h) >> 1; + } + + TFB_EnqueueDrawCommand(DrawCommand); + } + } + else + { + SDL_Rect SDLRect; + SDL_Surface *surf; + + surf = ((TFB_Image *) ((BYTE *) _CurFramePtr + + _CurFramePtr->DataOffs))->SurfaceSDL; + + SDLRect.x = (short) (pClipRect->corner.x - + GetFrameHotX (_CurFramePtr)); + SDLRect.y = (short) (pClipRect->corner.y - + GetFrameHotY (_CurFramePtr)); + SDLRect.w = (short) pClipRect->extent.width; + SDLRect.h = (short) pClipRect->extent.height; + + SDL_FillRect (surf, &SDLRect, SDL_MapRGB (surf->format, r, g, b)); + } +} + +static void +cmap_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ +// printf ("Unimplemented function activated: cmap_blt()\n"); +} + +static void +line_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ + float x1,y1,x2,y2; + BYTE r, g, b; + DWORD c32k; + + c32k = GetPrimColor (PrimPtr) >> 8; // shift out color index + r = (c32k >> (10 - (8 - 5))) & 0xF8; + g = (c32k >> (5 - (8 - 5))) & 0xF8; + b = (c32k << (8 - 5)); + + x1=PrimPtr->Object.Line.first.x - GetFrameHotX (_CurFramePtr); + y1=PrimPtr->Object.Line.first.y - GetFrameHotY (_CurFramePtr); + x2=PrimPtr->Object.Line.second.x - GetFrameHotX (_CurFramePtr); + y2=PrimPtr->Object.Line.second.y - GetFrameHotY (_CurFramePtr); + + if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) + { + TFB_DrawCommand *DC; + + DC = HMalloc (sizeof (TFB_DrawCommand)); + + DC->Type = TFB_DRAWCOMMANDTYPE_LINE; + DC->x = x1; + DC->y = y1; + DC->w = x2; + DC->h = y2; + DC->r = r; + DC->g = g; + DC->b = b; + + TFB_EnqueueDrawCommand(DC); + } + else + { + } +} + +static void +read_screen (PRECT lpRect, FRAMEPTR DstFramePtr) +{ + if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) != SCREEN_DRAWABLE + || TYPE_GET (DstFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE + || !(TYPE_GET (GetFrameParentDrawable (DstFramePtr) + ->FlagsAndIndex) + & ((DWORD) MAPPED_TO_DISPLAY << FTYPE_SHIFT))) + { + printf("Unimplemented function activated: read_screen()\n"); + } + else + { + TFB_DrawCommand* DC; + + DC = HMalloc(sizeof(TFB_DrawCommand)); + + DC->Type = TFB_DRAWCOMMANDTYPE_COPYBACKBUFFERTOOTHERBUFFER; + DC->x = lpRect->corner.x; + DC->y = lpRect->corner.y; + DC->w = lpRect->extent.width; + DC->h = lpRect->extent.height; + DC->image = (TFB_Image *) ((BYTE *) DstFramePtr + + DstFramePtr->DataOffs); + + TFB_EnqueueDrawCommand (DC); + } +} + +void (*func_array[]) (PRECT pClipRect, PRIMITIVEPTR PrimPtr) = +{ + fillrect_blt, + blt, + blt, + line_blt, + _text_blt, + cmap_blt, + _rect_blt, + fillrect_blt, + _fillpoly_blt, + _fillpoly_blt, +}; + +static DISPLAY_INTERFACE DisplayInterface = +{ + WANT_MASK, + + 16, // SCREEN_DEPTH, + 320, + 240, + + alloc_image, + read_screen, + + func_array, +}; + +void +LoadDisplay (PDISPLAY_INTERFACE *pDisplay) +{ + *pDisplay = &DisplayInterface; +} + +static TFB_DrawCommandQueue *DrawCommandQueue; +static void *ExtraScreen; + +//Status: Not entirely unimplemented! +BOOLEAN +InitGraphics (int argc, char* argv[], COUNT KbytesRequired) + // Kbytes should only matter if we wanted to port Starcon2 to the + // hand-helds... +{ + BOOLEAN ret; + + LoadDisplay (&_pCurDisplay); + mem_init (); + ActivateDisplay (); + + DrawCommandQueue = TFB_DrawCommandQueue_Create (); + + ExtraScreen = HMalloc (ScreenWidthActual * ScreenHeightActual * 4); + ret = TRUE; + return (ret); +} + +// Status: Unimplemented +void +UninitGraphics () // Also probably empty +{ + HFree (DrawCommandQueue); + + HFree (ExtraScreen); + mem_uninit (); +} + +// Status: Unimplemented +void +UninitSound () //Maybe I should call StopSound() first? +{ + //printf("Unimplemented function activated: UninitSound()\n"); +} + +// Status: Ignored +void +UninitVideo () //empty +{ + // printf("Unimplemented function activated: UninitVideo()\n"); +} + +static int _music_volume = (MAX_VOLUME + 1) >> 1; + +// Status: Unimplemented +void +SetMusicVolume(COUNT Volume) //Volume calibration... [0,255]? +{ + Mix_VolumeMusic ((_music_volume = Volume) * SDL_MIX_MAXVOLUME / + MAX_VOLUME); +} + +static TASK FadeTask; +static SIZE TTotal; +static SIZE volume_end; + +static int +fade_task (void *data) +{ + SIZE TDelta, volume_beg; + DWORD StartTime, CurTime; + + volume_beg = _music_volume; + StartTime = CurTime = GetTimeCounter (); + do + { + CurTime = SleepTask (CurTime + 1); + if ((TDelta = (SIZE) (CurTime - StartTime)) > TTotal) + TDelta = TTotal; + + SetMusicVolume ((COUNT) (volume_beg + (SIZE) + ((long) (volume_end - volume_beg) * TDelta / TTotal))); + } while (TDelta < TTotal); + + FadeTask = 0; + return (1); +} + +DWORD +FadeMusic (BYTE end_vol, SIZE TimeInterval) +{ + DWORD TimeOut; + + if (FadeTask) + { + volume_end = _music_volume; + TTotal = 1; + do + TaskSwitch (); + while (FadeTask); + TaskSwitch (); + } + + if ((TTotal = TimeInterval) <= 0) + TTotal = 1; /* prevent divide by zero and negative fade */ + volume_end = end_vol; + + if (TTotal > 1 && (FadeTask = AddTask (fade_task, 0))) + { + TimeOut = GetTimeCounter () + TTotal + 1; + } + else + { + SetMusicVolume (end_vol); + TimeOut = GetTimeCounter (); + } + + return (TimeOut); +} + +//Status: Unimplemented +void +FlushColorXForms() //Not entirely sure what's done here. CLUT stuff? +{ +// printf ("Unimplemented function activated: FlushColorXForms()\n"); +} + +//Status: Unimplemented +BOOLEAN +SoundPlaying() +{ + return (Mix_Playing (-1) != 0); +} + +//Status: Unimplemented +void +VidStop() // At least this one makes sense. +{ + // printf ("Unimplemented function activated: VidStop()\n"); +} + +//Status: Unimplemented +MEM_HANDLE +VidPlaying() // Easy enough. +{ + MEM_HANDLE ret; + + //printf("Unimplemented function activated: VidPlaying()\n"); + ret = 0; + return (ret); +} + +//Status: Unimplemented +VIDEO_TYPE +VidPlay (VIDEO_REF VidRef, char *loopname, BOOLEAN uninit) + // uninit? when done, I guess. +{ + VIDEO_TYPE ret; + ret = 0; + +// printf("Unimplemented function activated: VidPlay()\n"); + return (ret); +} + +int +GetSoundData(char* data) //Returns the data size. +{ + int ret; + + printf("Unimplemented function activated: GetSoundData()\n"); + ret = 0; + return (ret); +} + +// Status: Unimplemented +int +GetSoundInfo(int* length, int* offset) + // Umm... How does it know which sound? +{ + int ret; + + printf ("Unimplemented function activated: GetSoundInfo()\n"); + ret = 0; + return (ret); +} + +// Status: Unimplemented +BOOLEAN +ChannelPlaying(COUNT WhichChannel) + // SDL will have a nice interface for this, I hope. +{ + // printf("Unimplemented function activated: ChannelPlaying()\n"); + return ((BOOLEAN) Mix_Playing (WhichChannel)); +} + +// Status: Unimplemented +void +SetGraphicScale (int scale) + //Calibration... +{ + gscale = scale; +} + +// Status: Unimplemented +void +PlayChannel( + COUNT channel, + PVOID sample, + COUNT sample_length, + COUNT loop_begin, + COUNT loop_length, + unsigned char priority +) // This one's important. +{ + Mix_Chunk* Chunk; + + Chunk=*(Mix_Chunk**)sample; + Mix_PlayChannel ( + channel, //-1 would be easiest + Chunk, + 0 + ); +} + +//Status: Unimplemented +void +StopChannel(COUNT channel, unsigned char Priority) // Easy w/ SDL. +{ + Mix_HaltChannel (channel); +} + +// Status: Maybe Implemented +PBYTE +GetSampleAddress (SOUND sound) + // I might be prototyping this wrong, type-wise. +{ + return ((PBYTE)GetSoundAddress (sound)); +} + +// Status: Unimplemented +COUNT +GetSampleLength (SOUND sound) +{ + COUNT ret; + Mix_Chunk *Chunk; + + Chunk = (Mix_Chunk *) sound; + ret = 0; // Chunk->alen; + +// printf ("Maybe Implemented function activated: GetSampleLength()\n"); + return(ret); +} + +// Status: Unimplemented +void +SetChannelRate (COUNT channel, DWORD rate_hz, unsigned char priority) + // in hz +{ +// printf ("Unimplemented function activated: SetChannelRate()\n"); +} + +// Status: Unimplemented +COUNT +GetSampleRate (SOUND sound) +{ + COUNT ret; + +// printf("Unimplemented function activated: GetSampleRate()\n"); + ret=0; + return(ret); +} + +// Status: Unimplemented +void +SetChannelVolume (COUNT channel, COUNT volume, BYTE priority) + // I wonder what this whole priority business is... + // I can probably ignore it. +{ +// printf ("Unimplemented function activated: SetChannelVolume()\n"); +} + +static UNICODE PauseKey; +static UNICODE ExitKey; +static UNICODE OtherKey; + +static BOOLEAN (* PauseFunc) (void); + +// Status: Unimplemented +extern BOOLEAN +InitInput (UNICODE Pause, UNICODE Exit, BOOLEAN (*PFunc) (void)) +//Be careful with this one. +{ + PauseKey = Pause; + ExitKey = Exit; + + // Find a unique byte ID not equal to PauseKey, ExitKey, or 0. + OtherKey = 1; + while (OtherKey == PauseKey || OtherKey == ExitKey) + OtherKey++; + + PauseFunc = PFunc; + + return (TRUE); +} + +INPUT_STATE +AnyButtonPress (BOOLEAN DetectSpecial) +{ + int i; + + if (DetectSpecial) + { + if (KeyDown (PauseKey) && PauseFunc && (*PauseFunc) ()) + ; + } + + for (i = 0; i < sizeof (KeyboardDown) / sizeof (KeyboardDown[0]); ++i) + { + if (KeyboardDown[i]) + return (DEVICE_BUTTON1); + } +#if 0 + for (i = 0; i < JOYSTICKS_AVAIL; i++) + if (read_joystick (i)) + return (DEVICE_BUTTON1); +#endif + + return (0); +} + +// Status: Ignored +BOOLEAN +InitVideo (BOOLEAN useCDROM) //useCDROM doesn't really apply to us... +{ + BOOLEAN ret; + +// printf("Unimplemented function activated: InitVideo()\n"); + ret = TRUE; + return (ret); +} + +//Status: Ignored +BOOLEAN +InitSound (int argc, char* argv[]) + // Odd things to pass the InitSound function... +{ + BOOLEAN ret; + +// printf("Unimplemented function activated: InitSound()\n"); + ret = TRUE; + return (ret); +} + +// Status: Unimplemented +void +SetGraphicStrength (int numerator, int denominator) + // I just hope numerator always = denominator... +{ +// printf("Unimplemented function activated: SetGrahicsStrength()\n"); +} + +// Status: Unimplemented +UNICODE +KeyHit () // Does this clear the top of a queue, or just read it? +{ + int i; + + for (i = 0; i < sizeof (KeyboardDown) / sizeof (KeyboardDown[0]); ++i) + { + if (KeyboardDown[i]) + { + if (i == SDLK_RETURN) + return ('\n'); + else if (i >= 256) + { + switch (i) + { + case SDLK_KP_ENTER: + return ('\n'); + case SDLK_KP4: + case SDLK_LEFT: + return (SK_LF_ARROW); + case SDLK_KP6: + case SDLK_RIGHT: + return (SK_RT_ARROW); + case SDLK_KP8: + case SDLK_UP: + return (SK_UP_ARROW); + case SDLK_KP2: + case SDLK_DOWN: + return (SK_DN_ARROW); + case SDLK_KP7: + case SDLK_HOME: + return (SK_HOME); + case SDLK_KP9: + case SDLK_PAGEUP: + return (SK_PAGE_UP); + case SDLK_KP1: + case SDLK_END: + return (SK_END); + case SDLK_KP3: + case SDLK_PAGEDOWN: + return (SK_PAGE_DOWN); + case SDLK_KP0: + case SDLK_INSERT: + return (SK_INSERT); + case SDLK_KP_PERIOD: + case SDLK_DELETE: + return (SK_DELETE); + case SDLK_KP_PLUS: + return (SK_KEYPAD_PLUS); + case SDLK_KP_MINUS: + return (SK_KEYPAD_MINUS); + case SDLK_LSHIFT: + return (SK_LF_SHIFT); + case SDLK_RSHIFT: + return (SK_RT_SHIFT); + case SDLK_LCTRL: + case SDLK_RCTRL: + return (SK_CTL); + case SDLK_LALT: + case SDLK_RALT: + return (SK_ALT); + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + case SDLK_F11: + case SDLK_F12: + return ((UNICODE) ((i - SDLK_F1) + SK_F1)); + } + continue; + } + + return ((UNICODE) i); + } + } + + return (0); +} + +//Status: Unimplemented +int +KeyDown (UNICODE which_scan) + // This might use SK_* stuff, of just plain old chars +{ + int i; + + i = which_scan; + if (i == '\n') + { + if (KeyboardDown[SDLK_KP_ENTER]) + return (1); + i = SDLK_RETURN; + } + else if (i >= 128) + { + switch (i) + { + case SK_LF_ARROW: + if (KeyboardDown[SDLK_KP4]) + return (1); + i = SDLK_LEFT; + break; + case SK_RT_ARROW: + if (KeyboardDown[SDLK_KP6]) + return (1); + i = SDLK_RIGHT; + break; + case SK_UP_ARROW: + if (KeyboardDown[SDLK_KP8]) + return (1); + i = SDLK_UP; + break; + case SK_DN_ARROW: + if (KeyboardDown[SDLK_KP2]) + return (1); + i = SDLK_DOWN; + break; + case SK_HOME: + if (KeyboardDown[SDLK_KP7]) + return (1); + i = SDLK_HOME; + break; + case SK_PAGE_UP: + if (KeyboardDown[SDLK_KP9]) + return (1); + i = SDLK_PAGEUP; + break; + case SK_END: + if (KeyboardDown[SDLK_KP1]) + return (1); + i = SDLK_END; + break; + case SK_PAGE_DOWN: + if (KeyboardDown[SDLK_KP3]) + return (1); + i = SDLK_PAGEDOWN; + break; + case SK_INSERT: + if (KeyboardDown[SDLK_KP0]) + return (1); + i = SDLK_INSERT; + break; + case SK_DELETE: + if (KeyboardDown[SDLK_KP_PERIOD]) + return (1); + i = SDLK_DELETE; + break; + case SK_KEYPAD_PLUS: + i = SDLK_KP_PLUS; + break; + case SK_KEYPAD_MINUS: + i = SDLK_KP_MINUS; + break; + case SK_LF_SHIFT: + i = SDLK_LSHIFT; + break; + case SK_RT_SHIFT: + i = SDLK_RSHIFT; + break; + case SK_CTL: + if (KeyboardDown[SDLK_LCTRL]) + return (1); + i = SDLK_RCTRL; + break; + case SK_ALT: + if (KeyboardDown[SDLK_LALT]) + return (1); + i = SDLK_RALT; + break; + case SK_F1: + case SK_F2: + case SK_F3: + case SK_F4: + case SK_F5: + case SK_F6: + case SK_F7: + case SK_F8: + case SK_F9: + case SK_F10: + case SK_F11: + case SK_F12: + i = (i - SK_F1) + SDLK_F1; + } + } + + return (KeyboardDown[i]); +} + +// Status: Unimplemented +BOOLEAN +BatchColorMap (COLORMAPPTR ColorMapPtr) + // Batch... I wonder what that verb means in this context? + // SvdB: I don't think it is a verb. +{ + BOOLEAN ret; + +// printf("Unimplemented function activated: BatchColorMap()\n"); + ret = TRUE; + return (ret); +} + +// Status: Unimplemented +BOOLEAN +_image_intersect (PIMAGE_BOX box1, PIMAGE_BOX box2, PRECT rect) + // This is a biggie. +{ + BOOLEAN ret; + +// printf ("Unimplemented function activated: _image_intersect()\n"); + ret = TRUE; + return (ret); +} + +// Status: Unimplemented +INPUT_STATE +_get_serial_keyboard_state (INPUT_REF ref, INPUT_STATE InputState) + // I hope these are defined somewhere... +{ + Uint16 key; + extern Uint16 GetUNICODEKey (void); + + if ((key = GetUNICODEKey ()) == '\r') + key = '\n'; + SetInputUNICODE (&InputState, key); + SetInputDevType (&InputState, KEYBOARD_DEVICE); + + return (InputState); +} + +// Status: Unimplemented +INPUT_STATE +_get_joystick_keyboard_state (INPUT_REF InputRef, INPUT_STATE InputState) + // see line above. +{ + SBYTE dx, dy; + BYTEPTR KeyEquivalentPtr; + + KeyEquivalentPtr = GetInputDeviceKeyEquivalentPtr (InputRef); + dx = (SBYTE)(KeyDown (KeyEquivalentPtr[1]) - + KeyDown (KeyEquivalentPtr[0])); + SetInputXComponent (&InputState, dx); + + KeyEquivalentPtr += 2; + dy = (SBYTE)(KeyDown (KeyEquivalentPtr[1]) - + KeyDown (KeyEquivalentPtr[0])); + SetInputYComponent (&InputState, dy); + + KeyEquivalentPtr += 2; + if (KeyDown (*KeyEquivalentPtr++)) + InputState |= DEVICE_BUTTON1; + if (KeyDown (*KeyEquivalentPtr++)) + InputState |= DEVICE_BUTTON2; + if (KeyDown (*KeyEquivalentPtr++)) + InputState |= DEVICE_BUTTON3; + + if (KeyDown (*KeyEquivalentPtr++)) + InputState |= DEVICE_LEFTSHIFT; + if (KeyDown (*KeyEquivalentPtr++)) + InputState |= DEVICE_RIGHTSHIFT; + + if (InputState) + SetInputDevType (&InputState, JOYSTICK_DEVICE); + + return (InputState); +} + +/* +// Status: Implemented +INPUT_STATE +_get_joystick_state (INPUT_REF ref, INPUT_STATE InputState) + // consistant, at least. +{ +// printf ("Half-implemented function activated: _get_joystick_state()\n"); + + if (KeyboardStroke[SDLK_LEFT]) + { + SetInputXComponent (&InputState, -1); +// printf ("LEFT!\n"); + KeyboardStroke[SDLK_LEFT] = FALSE; + } + if (KeyboardStroke[SDLK_RIGHT]) + { + SetInputXComponent (&InputState, 1); +// printf ("RIGHT!\n"); + KeyboardStroke[SDLK_RIGHT] = FALSE; + } + + if (KeyboardStroke[SDLK_UP]) + { + SetInputYComponent (&InputState, -1); +// printf ("UP!\n"); + KeyboardStroke[SDLK_UP] = FALSE; + } + if (KeyboardStroke[SDLK_DOWN]) + { + SetInputYComponent (&InputState, 1); +// printf ("DOWN!\n"); + KeyboardStroke[SDLK_DOWN] = FALSE; + } + + if (KeyboardStroke[ControlA]) + { + InputState |= DEVICE_BUTTON1; +// printf("BUTTON1!\n"); + KeyboardStroke[ControlA]=FALSE; + } + if (KeyboardStroke[ControlB]) + { + InputState |= DEVICE_BUTTON2; +// printf ("BUTTON2!\n"); + KeyboardStroke[ControlB] = FALSE; + } + if (KeyboardStroke[ControlC]) + { + InputState |= DEVICE_BUTTON3; +// printf ("BUTTON3!\n"); + KeyboardStroke[ControlC] = FALSE; + } + if (KeyboardStroke[ControlX]) + { + InputState |= DEVICE_EXIT; +// printf ("BUTTONX!\n"); + KeyboardStroke[ControlX] = FALSE; + } + if (KeyboardStroke[ControlStart]) + { + InputState |= DEVICE_PAUSE; +// printf ("CONTROLSTART!\n"); + KeyboardStroke[ControlStart] = FALSE; + } + if (KeyboardStroke[ControlLeftShift]) + { + InputState |= DEVICE_LEFTSHIFT; +// printf ("LEFTSHIFT!\n"); + KeyboardStroke[ControlLeftShift] = FALSE; + } + if (KeyboardStroke[ControlRightShift]) + { + InputState |= DEVICE_RIGHTSHIFT; +// printf ("RIGHTSHIFT!\n"); + KeyboardStroke[ControlRightShift] = FALSE; + } + + return (InputState); +} +*/ + +INPUT_STATE +_get_joystick_state (INPUT_REF ref, INPUT_STATE InputState) + // consistant, at least. +{ +#if 0 + if (ref == JoystickInput[1] && 0) + { + //printf ("ref\n"); + + return(0); + } + +// printf ("Half-implemented function activated: _get_joystick_state()\n"); + + if (KeyboardDown[SDLK_LEFT]) + { + SetInputXComponent (&InputState, -1); + //printf ("LEFT!\n"); + } + if (KeyboardDown[SDLK_RIGHT]) + { + SetInputXComponent (&InputState, 1); + //printf ("RIGHT!\n"); + } + + if (KeyboardDown[SDLK_UP]) + { + SetInputYComponent (&InputState, -1); + //printf ("UP!\n"); + } + if (KeyboardDown[SDLK_DOWN]) + { + SetInputYComponent (&InputState, 1); + //printf ("DOWN!\n"); + } + + if (KeyboardDown[ControlA]) + { + InputState |= DEVICE_BUTTON1; + //printf ("BUTTON1!\n"); + } + if (KeyboardDown[ControlB]) + { + InputState |= DEVICE_BUTTON2; + //printf ("BUTTON2!\n"); + } + if (KeyboardDown[ControlC]) + { + InputState |= DEVICE_BUTTON3; + //printf ("BUTTON3!\n"); + } + if (KeyboardDown[ControlX]) + { + InputState |= DEVICE_EXIT; + //printf ("BUTTONX!\n"); + } + if (KeyboardDown[ControlStart]) + { + InputState |= DEVICE_PAUSE; + //printf ("CONTROLSTART!\n"); + } + if (KeyboardDown[ControlLeftShift]) + { + InputState |= DEVICE_LEFTSHIFT; + //printf ("LEFTSHIFT!\n"); + } + if (KeyboardDown[ControlRightShift]) + { + InputState |= DEVICE_RIGHTSHIFT; + //printf ("RIGHTSHIFT!\n"); + } +#endif + + return (InputState); +} + +// Status: Ignored - The keyboard will serve as the joystick, thus a port is always open. +BOOLEAN +_joystick_port_active(COUNT port) //SDL handles this nicely. +{ + printf ("Unimplemented function activated: _joystick_port_active()\n"); + return (0); +} + +INPUT_STATE +_get_pause_exit_state (void) +{ + INPUT_STATE InputState; + + InputState = 0; + if (KeyDown (PauseKey)) + { + if (PauseFunc && (*PauseFunc) ()) + ; + } + else if (KeyDown (ExitKey)) + { + InputState = DEVICE_EXIT; + } +#if 0 + for (i = 0; i < JOYSTICKS_AVAIL; i++) + { + DWORD joy; + + joy = read_joystick (i); + if (joy & ControlStart) // pause + { + if (PauseFunc && (*PauseFunc) ()) +// while (KeyDown (PauseKey)) + ; + } + else if (joy & ControlX) // exit + { +// while (KeyDown (ExitKey)) +// TaskSwitch (); + + InputState = DEVICE_EXIT; + } + } +#endif + + return (InputState); +} + +DWORD +SleepTask (DWORD wake_time) +{ + DWORD t; + + t = GetTimeCounter (); + if (wake_time <= t) + SDL_Delay (0); + else + SDL_Delay ((wake_time - t) * 1000 / ONE_SECOND); + + return (GetTimeCounter ()); +} + +VIDEO_REF +_init_video_file(PVOID pStr) +{ + VIDEO_REF ret; + + printf ("Unimplemented function activated: _init_video_file()\n"); + ret = 0; + return (ret); +} + +// Draw Command Queue Stuff +TFB_DrawCommandQueue* +TFB_DrawCommandQueue_Create() +{ + TFB_DrawCommandQueue* myQueue; + + myQueue = (TFB_DrawCommandQueue*) HMalloc( + sizeof(TFB_DrawCommandQueue)); + + myQueue->Back = 0; + myQueue->Front = 0; + myQueue->Size = 0; + + return (myQueue); +} + +void +TFB_DrawCommandQueue_Push (TFB_DrawCommandQueue* myQueue, + TFB_DrawCommand* Command) +{ + TFB_DrawCommandNode* NewNode; + + NewNode = (TFB_DrawCommandNode*) HMalloc (sizeof (TFB_DrawCommandNode)); + NewNode->Command = Command; + NewNode->Behind = NewNode; + + if (myQueue->Size == 0) + { + NewNode->Ahead = NewNode; + myQueue->Front = NewNode; + } + else + { + NewNode->Ahead = myQueue->Back; + myQueue->Back->Behind = NewNode; + } + + myQueue->Back=NewNode; + myQueue->Size++; +} + +TFB_DrawCommand * +TFB_DrawCommandQueue_Pop (TFB_DrawCommandQueue *myQueue) +{ + TFB_DrawCommand *ReturnMe; + TFB_DrawCommandNode *NextFront; + + if (myQueue->Size == 0) + return (0); + + ReturnMe = myQueue->Front->Command; + NextFront = myQueue->Front->Behind; + HFree (myQueue->Front); + if (myQueue->Size == 1) + { + myQueue->Front=0; + myQueue->Back=0; + } + else + { + myQueue->Front=NextFront; + myQueue->Front->Ahead=myQueue->Front; + } + + myQueue->Size--; + + return (ReturnMe); +} + +void +TFB_DeallocateDrawCommand (TFB_DrawCommand* Command) +{ + HFree(Command); +} + +// + +DWORD +SetSemaphore (SEMAPHORE *sem) +{ + SDL_SemWait (*sem); + return (GetTimeCounter ()); +} + +void +ClearSemaphore (SEMAPHORE *sem) +{ + SDL_SemPost (*sem); +} + +TASK +AddTask (TASK_FUNC arg1, COUNT arg2) +{ + return (SDL_CreateThread ((int (*)(void *)) arg1, NULL)); +} + +void +DeleteTask (TASK T) +{ + SDL_KillThread (T); +} + +static int Next2Power (int in) +{ + int c; + for(c = 1; c <= in ; c *= 2) + ; + + return(c); +} + +TFB_Image* TFB_LoadImage (SDL_Surface *img) +{ + TFB_Image* myImage; + + myImage = (TFB_Image*) HMalloc (sizeof (TFB_Image)); + + // Create a new SDL Image + + if (img->format->BytesPerPixel < 4) + { + SDL_Surface *new_surf; + + new_surf = SDL_CreateRGBSurface ( + SDL_SWSURFACE, + img->clip_rect.w, + img->clip_rect.h, + 32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 + ); + if (new_surf) + { + SDL_Rect SDL_DstRect; + + SDL_DstRect.x = SDL_DstRect.y = 0; + /* + SDL_FillRect ( + new_surf, + &SDL_DstRect, + SDL_MapRGBA(new_surf->format, 1, 1, 1, .5) + ); + */ + SDL_BlitSurface ( + img, // src + &img->clip_rect, // src rect + new_surf, // dst + &SDL_DstRect // dst rect + ); + + new_surf->clip_rect.x = new_surf->clip_rect.y = 0; + new_surf->clip_rect.w = img->clip_rect.w; + new_surf->clip_rect.h = img->clip_rect.h; + + SDL_FreeSurface (img); + img = new_surf; + } + } + myImage->SurfaceSDL=img; + + // Figure out glTexture* Variables + + myImage->glTextureW = Next2Power (myImage->SurfaceSDL->clip_rect.w); + myImage->glTextureH = Next2Power (myImage->SurfaceSDL->clip_rect.h); + + myImage->glTexture = 0; + + return(myImage); +} + +void +TFB_FreeImage (TFB_Image *img) +{ + if (img) + { + TFB_DrawCommand* DC; + + DC = HMalloc (sizeof (TFB_DrawCommand)); + + DC->Type = TFB_DRAWCOMMANDTYPE_DELETEIMAGE; + DC->image = img; + + TFB_EnqueueDrawCommand (DC); + } +} + +void +TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand) +{ + if (TFB_DEBUG_HALT) + { + return; + } + + if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER + && TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) + { + static RECT scissor_rect; + + // Set the clipping region. + if (scissor_rect.corner.x != _pCurContext->ClipRect.corner.x + || scissor_rect.corner.y != _pCurContext->ClipRect.corner.y + || scissor_rect.extent.width != + _pCurContext->ClipRect.extent.width + || scissor_rect.extent.height != + _pCurContext->ClipRect.extent.height) + { + // Enqueue command to set the glScissor spec + + TFB_DrawCommand* DC; + + scissor_rect = _pCurContext->ClipRect; + + DC = HMalloc (sizeof (TFB_DrawCommand)); + + DC->Type = scissor_rect.extent.width + ? (DC->x = scissor_rect.corner.x, + DC->y=scissor_rect.corner.y, + DC->w=scissor_rect.extent.width, + DC->h=scissor_rect.extent.height), + TFB_DRAWCOMMANDTYPE_SCISSORENABLE + : TFB_DRAWCOMMANDTYPE_SCISSORDISABLE; + + TFB_EnqueueDrawCommand(DC); + } + } + + TFB_DrawCommandQueue_Push (DrawCommandQueue, DrawCommand); +} + +void +TFB_FlushGraphics () //Only call from main thread!! +{ +#define NUM_FLUSH_PASSES 1 + int semval, pass; + TFB_DrawCommandQueue DCQ_Copy, DCQ_Swap; + Uint32 this_flush; + static Uint32 last_flush = 0; + + this_flush = SDL_GetTicks (); + if (this_flush - last_flush < 1000 / 100) + return; + + semval = SDL_SemTryWait (GraphicsSem); + if (semval != 0 && !continuity_break) + return; + + continuity_break = 0; + if (DrawCommandQueue == 0 || DrawCommandQueue->Size == 0) + { + if (semval == 0) + SDL_SemPost (GraphicsSem); + return; + } + + last_flush = this_flush; + + DCQ_Copy = *DrawCommandQueue; + DrawCommandQueue->Back = 0; + DrawCommandQueue->Front = 0; + DrawCommandQueue->Size = 0; + DCQ_Swap = *DrawCommandQueue; + if (semval == 0) + SDL_SemPost (GraphicsSem); + + glDrawBuffer (GL_BACK); + for (pass = 0; pass < NUM_FLUSH_PASSES; ++pass) + { + while (DCQ_Copy.Size > 0) + { + TFB_DrawCommand* DC; + + DC = TFB_DrawCommandQueue_Pop (&DCQ_Copy); + + if (DC == 0) + { + printf ("Woah there coyboy! Trouble with TFB_Queues...\n"); + continue; + } + + switch (DC->Type) + { + case TFB_DRAWCOMMANDTYPE_IMAGE: + if (DC->image==0) + { + printf ("Error!!! Bad Image!\n"); + } + else + { + int vx, vy; + float y0, y1; + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + + // + + glLoadIdentity (); + if (DC->Qualifier != MAPPED_TO_DISPLAY) + { + glOrtho (0,ScreenWidth,ScreenHeight, 0, -1, 1); + vx = DC->x; + vy = DC->y; + y0 = 0; + y1 = DC->image->SurfaceSDL->clip_rect.h / + DC->image->glTextureH; + } + else + { + glOrtho (0, ScreenWidthActual, + ScreenHeightActual, 0, -1, 1); + vx = DC->x * ScreenWidthActual / ScreenWidth; + vy = DC->y * ScreenHeightActual / ScreenHeight; + y0 = DC->image->SurfaceSDL->clip_rect.h / + DC->image->glTextureH; + y1 = 0; + } + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + vx += DC->image->SurfaceSDL->clip_rect.x; + vy += DC->image->SurfaceSDL->clip_rect.y; + if (DC->image->glTexture) + { + glBindTexture (GL_TEXTURE_2D,DC->image->glTexture); + } + else + { + //Load Image into glTexture + + glGenTextures(1, &(DC->image->glTexture)); + glBindTexture(GL_TEXTURE_2D, DC->image->glTexture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, DC->image->SurfaceSDL->w); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +// glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D // Make a blank texture + ( + GL_TEXTURE_2D, + 0, + GL_RGBA, // All incoming SDL_Surfaces must have an alpha channel + DC->image->glTextureW, + DC->image->glTextureH, + 0, + GL_RGBA, // All glTextures will have an alpha channel + GL_UNSIGNED_BYTE, + 0 // Valid in OpenGL 1.1 or later + ); + SDL_LockSurface(DC->image->SurfaceSDL); + glTexSubImage2D ( + GL_TEXTURE_2D, // Must be GL_TEXTURE_2D + 0, // Level of detail number (mipmapping) + DC->image->SurfaceSDL->clip_rect.x, // X + DC->image->SurfaceSDL->clip_rect.y, // Y + DC->image->SurfaceSDL->clip_rect.w, // Width + DC->image->SurfaceSDL->clip_rect.h, // Height + GL_RGBA, // Format + GL_UNSIGNED_BYTE, // Type + DC->image->SurfaceSDL->pixels // Pixels + ); + SDL_UnlockSurface(DC->image->SurfaceSDL); + } + glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glColor4f (1,1,1,1); + glBegin (GL_QUADS); + + glTexCoord2f (0,y0); + glVertex2i (vx, vy); + + glTexCoord2f (0,y1); + glVertex2i (vx, vy + DC->h); + + glTexCoord2f (DC->image->SurfaceSDL->clip_rect.w / DC->image->glTextureW, y1); + glVertex2i (vx + DC->w, vy + DC->h); + + glTexCoord2f (DC->image->SurfaceSDL->clip_rect.w / DC->image->glTextureW, y0); + glVertex2i (vx + DC->w, vy); + + glEnd (); + glDisable (GL_BLEND); + glDisable (GL_TEXTURE_2D); + + // + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + } + break; + case TFB_DRAWCOMMANDTYPE_LINE: + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + + glLoadIdentity (); + glOrtho (0, ScreenWidth, ScreenHeight, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + // + + glColor3f ((float) DC->r / 255.0, (float) DC->g / 255.0, + (float) DC->b / 255.0); + glBegin (GL_LINES); + { + glVertex2f (DC->x,DC->y); + glVertex2f (DC->w,DC->h); + } + glEnd (); + + // + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + break; + case TFB_DRAWCOMMANDTYPE_RECTANGLE: + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + + // + + glLoadIdentity (); + glOrtho (0, ScreenWidth, ScreenHeight, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glBegin (GL_QUADS); + { + glColor3f (((float) DC->r) / 255.0, + ((float) DC->g) / 255.0, + ((float) DC->b) / 255.0); + glVertex2i (DC->x , DC->y + DC->h); + glVertex2i (DC->x , DC->y ); + glVertex2i (DC->x + DC->w, DC->y ); + glVertex2i (DC->x + DC->w, DC->y + DC->h); + } + glEnd (); + + // + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + break; + case TFB_DRAWCOMMANDTYPE_SCISSORENABLE: + { + int x; + int y; + int w; + int h; + + x = DC->x * ScreenWidthActual / ScreenWidth; + y = (ScreenHeight - (DC->y + DC->h)) * + ScreenHeightActual / ScreenHeight; + w = DC->w * ScreenWidthActual / ScreenWidth; + h = DC->h * ScreenHeightActual / ScreenHeight; + + glEnable (GL_SCISSOR_TEST); + glScissor (x, y, w, h); + break; + } + case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE: + glDisable (GL_SCISSOR_TEST); + break; + case TFB_DRAWCOMMANDTYPE_COPYBACKBUFFERTOOTHERBUFFER: + if (pass == 0) + { + int x, y, w, h; + void *pixels; + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + + glOrtho(0, ScreenWidth,ScreenHeight, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glRasterPos2d (0,0); + + x = DC->x * ScreenWidthActual / ScreenWidth; + y = (ScreenHeight - (DC->y + DC->h)) * + ScreenHeightActual / ScreenHeight; + w = DC->w * ScreenWidthActual / ScreenWidth; + h = DC->h * ScreenHeightActual / ScreenHeight; + if (DC->image == 0) + { + glPixelStorei (GL_PACK_ROW_LENGTH, + ScreenWidthActual); + glPixelStorei (GL_PACK_SKIP_PIXELS, x); + glPixelStorei (GL_PACK_SKIP_ROWS, y); + pixels = ExtraScreen; + } + else + { + SDL_LockSurface (DC->image->SurfaceSDL); + + glPixelStorei (GL_PACK_ROW_LENGTH, + DC->image->SurfaceSDL->w); + glPixelStorei (GL_PACK_SKIP_PIXELS, 0); + glPixelStorei (GL_PACK_SKIP_ROWS, 0); + pixels = DC->image->SurfaceSDL->pixels; // Pixels + } + + glReadBuffer (GL_BACK); +// glFlush (); +//glFinish (); + glReadPixels (x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, + pixels); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); + + if (DC->image) + { + SDL_UnlockSurface (DC->image->SurfaceSDL); + } + else + { + glPixelStorei (GL_PACK_SKIP_ROWS, 0); + glPixelStorei (GL_PACK_SKIP_PIXELS, 0); + } + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + } + break; + case TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER: + { + int x, y, w, h; + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + glOrtho (0, ScreenWidth, ScreenHeight, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glRasterPos2d (DC->x, DC->y + DC->h); + + x = DC->x * ScreenWidthActual / ScreenWidth; + y = (ScreenHeight - (DC->y + DC->h)) * + ScreenHeightActual / ScreenHeight; + w = DC->w * ScreenWidthActual / ScreenWidth; + h = DC->h * ScreenHeightActual / ScreenHeight; + + glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidthActual); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei (GL_UNPACK_SKIP_ROWS, y); + glDrawPixels (w, h, GL_RGBA, GL_UNSIGNED_BYTE, + ExtraScreen); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + break; + } + case TFB_DRAWCOMMANDTYPE_DELETEIMAGE: + if (pass == NUM_FLUSH_PASSES - 1) + { + SDL_FreeSurface (DC->image->SurfaceSDL); + if (DC->image->glTexture) + glDeleteTextures (1, &(DC->image->glTexture)); + HFree (DC->image); + } + break; + } + + if (pass == NUM_FLUSH_PASSES - 1) + TFB_DeallocateDrawCommand (DC); + else + TFB_DrawCommandQueue_Push (&DCQ_Swap, DC); + } + + if (pass == 0) + { + GLboolean ScissorMode; + + glGetBooleanv (GL_SCISSOR_TEST, &ScissorMode); + + glFlush (); + SDL_GL_SwapBuffers (); +// glFlush(); +#if NUM_FLUSH_PASSES > 1 + DCQ_Copy = DCQ_Swap; +#else + glReadBuffer (GL_FRONT); + glDrawBuffer (GL_BACK); + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + + glOrtho (0, ScreenWidthActual, ScreenHeightActual, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glDisable (GL_SCISSOR_TEST); + glRasterPos2d (0, ScreenHeightActual - .1); + // Re "-.1": All values 0 < x < .5 work. Strange!! + + glCopyPixels (0, 0, ScreenWidthActual, ScreenHeightActual, + GL_COLOR); + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + + if (ScissorMode) + { + glEnable (GL_SCISSOR_TEST); + } +#endif + } + } +} diff --git a/sc2/src/SDL_wrapper.h b/sc2/src/SDL_wrapper.h new file mode 100644 index 000000000..0bec2fa48 --- /dev/null +++ b/sc2/src/SDL_wrapper.h @@ -0,0 +1,304 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +/**************************************** + + Star Control II: 3DO => SDL Port + + Copyright Toys for Bob, 2002 + + 3DO_wrapper.h programmer: Chris Nelson + +*****************************************/ + +//This file will supply every function that Starcon2 expects of the 3DO, via SDL. + +#ifndef THREEDO_WRAPPER_H +#define THREEDO_WRAPPER_H + +#include "./gl.h" +#include "SDL.h" +#include "smpeg.h" +#include "SDL_mixer.h" +#include "SDL_thread.h" +#include "SDL_image.h" + +#include +#include + +#include "starcon.h" +#include "libs/gfxlib.h" +#include "libs/vidlib.h" +#include + +//#defines + +#define Stream FILE +#define MEMTYPE_ANY 1 + +//SDL Stuff + +void InitSDL(); +int Starcon2Main (void *); + +//Graphics Stuff + +void LoadIntoExtraScreen (PRECT r); +void DrawFromExtraScreen (PRECT r); +void SetGraphicStrength (int numer, int denom); +void SetGraphicGrabOther (int grab_other); +void SetGraphicScale (int scale); +void SetGraphicUseOtherExtra (int other); +void *GetScreenBitmap (); +void ScreenTransition (int transition, PRECT pRect); +void ScreenOrigin (FRAME Display, COORD sx, COORD sy); + +extern float FrameRate; +extern int FrameRateTickBase; + +//Image + Drawing Stuff + +typedef struct tfb_image +{ + SDL_Surface *SurfaceSDL; + Uint32 glTexture; + float glTextureW; + float glTextureH; +} TFB_Image; + +TFB_Image *TFB_LoadImage (SDL_Surface *img); +void TFB_FreeImage (TFB_Image *img); + +enum +{ + TFB_DRAWCOMMANDTYPE_LINE, + TFB_DRAWCOMMANDTYPE_RECTANGLE, + TFB_DRAWCOMMANDTYPE_IMAGE, + TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER, + + TFB_DRAWCOMMANDTYPE_SCISSORENABLE, + TFB_DRAWCOMMANDTYPE_SCISSORDISABLE, + TFB_DRAWCOMMANDTYPE_COPYBACKBUFFERTOOTHERBUFFER, + TFB_DRAWCOMMANDTYPE_DELETEIMAGE, +}; + +typedef struct tfb_drawcommand +{ + int Type; + int x; + int y; + int w; + int h; + TFB_Image *image; // only used for image draw type + int r; // RGB only used for rect draw types + int g; + int b; + int Qualifier; +} TFB_DrawCommand; + +// Queue Stuff + +typedef struct tfb_drawcommandnode +{ + TFB_DrawCommand *Command; + void *Ahead; + void *Behind; +} TFB_DrawCommandNode; + +typedef struct tfb_drawcommandqueue +{ + TFB_DrawCommandNode *Front; + TFB_DrawCommandNode *Back; + int Size; +} TFB_DrawCommandQueue; + +TFB_DrawCommandQueue *TFB_DrawCommandQueue_Create (); + +void TFB_DrawCommandQueue_Push (TFB_DrawCommandQueue* myQueue, + TFB_DrawCommand* Command); + +TFB_DrawCommand *TFB_DrawCommandQueue_Pop (TFB_DrawCommandQueue* myQueue); + +void TFB_DeallocateDrawCommand (TFB_DrawCommand* Command); + +// End Queue Stuff + +extern TFB_DrawCommandQueue *DrawCommandQueue; + +// The TFB_Enqueue* functions are necessary, because only the main thread can +// draw to the OpenGL window. +void TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand); +void TFB_FlushGraphics (); //Only call from main thread!! + +//Sound Stuff + +//Track player Stuff + +void ResumeTrack(); +void PauseTrack(); +COUNT PlayingTrack(); +void JumpTrack(int abort); +void FastForward(); +void FastReverse(); +void StopTrack(); +void SpliceTrack(UNICODE *filespec, UNICODE *textspec); +int GetSoundData(char *data); +int GetSoundInfo (int *len, int *offs); + +extern SEMAPHORE _MemorySem; +// Non-Volitile RAM Stuff + +// CD Stuff + +int CD_get_drive(); // Returns 0 +unsigned int CD_get_volsize(); // Returns 0 + +// IO Stuff + +// Multi-tasking Stuff + +// CCB Stuff + +typedef struct +{ + int ccb_Flags; + int ccb_HDX; + int ccb_HDY; + int ccb_HDDX; + int ccb_HDDY; + int ccb_VDX; + int ccb_VDY; + int ccb_PIXC; + void* ccb_SourcePtr; + unsigned int* ccb_PLUTPtr; + int ccb_Width; + int ccb_Height; + int ccb_PRE0; + int ccb_PRE1; + void* ccb_NextPtr; + int ccb_XPos; + int ccb_YPos; +} CCB; + +// Geez, I hope these #defines work out... + +#define CCB_SPABS (1 << 0) +#define CCB_PPABS (1 << 1) +#define CCB_YOXY (1 << 2) +#define CCB_ACW (1 << 3) +#define CCB_ACCW (1 << 4) +#define CCB_LDSIZE (1 << 5) +#define CCB_CCBPRE (1 << 6) +#define CCB_LDPRS (1 << 7) +#define CCB_LDPPMP (1 << 8) +#define CCB_ACE (1 << 9) +#define CCB_LCE (1 << 10) +#define CCB_PLUTPOS (1 << 11) +#define CCB_BGND (1 << 12) +#define CCB_NPABS (1 << 13) +#define CCB_PACKED (1 << 14) +#define CCB_LDPLUT (1 << 15) +#define CCB_LAST (1 << 16) +#define CCB_USEAV (1 << 17) + +#define PPMP_0_SHIFT 0 // ? +#define PPMP_1_SHIFT 1 // ? + +#define PPMPC_MS_PIN (1 << 0) +#define PPMPC_MS_CCB (1 << 1) +#define PPMPC_SF_8 (1 << 2) +#define PPMPC_MF_8 (1 << 3) +#define PPMPC_MF_SHIFT 3 +#define PPMPC_1S_PDC (1 << 4) +#define PPMPC_2S_CFBD (1 << 5) +#define PPMPC_2D_1 (1 << 6) +#define PPMPC_MF_6 (1 << 7) +#define PPMPC_2S_0 (1 << 8) +#define PPMPC_1S_CFBD (1 << 9) +#define PPMPC_MF_2 (1 << 10) +#define PPMPC_SF_2 (1 << 11) +#define PPMPC_2S_PDC (1 << 12) +#define PPMPC_MF_1 (1 << 13) +#define PPMPC_SF_16 (1 << 14) + +#define PRE0_LITERAL (1 << 0) +#define PRE0_VCNT_PREFETCH (1 << 1) +#define PRE0_VCNT_SHIFT 1 +#define PRE0_VCNT_MASK (1 << 1) +#define PRE0_BPP_8 (1 << 2) +#define PRE0_BPP_SHIFT 2 +#define PRE0_BPP_16 (1 << 3) +#define PRE0_BGND (1 << 4) +#define PRE0_LINEAR (1 << 5) +#define PRE0_SKIPX_MASK 0 +#define PRE0_SKIPX_SHIFT 0 +#define PRE0_BPP_1 (1 << 6) +#define PRE1_TLLSB_PDC0 (1 << 7) +#define PRE1_TLHPCNT_PREFETCH (1 << 7) +#define PRE1_TLHPCNT_SHIFT 7 +#define PRE1_TLHPCNT_MASK (1 << 7) +#define PRE1_WOFFSET_PREFETCH (1 << 8) +#define PRE1_WOFFSET10_SHIFT (1 << 9) +#define PRE1_WOFFSET8_SHIFT (1 << 10) + +// Cel Stuff + +void add_cel(CCB* cel); +void add_cels(CCB* first, CCB* last); +void myMapCel(CCB* myCCB, POINT Points[4]); +int _ThreeDO_batch_cels(int unknown); +CCB *ParseCel(CCB*,unsigned int); + +// Misc Stuff + +#define SqrtF16 sqrt +#define Atan2F16 atan2 +#define CosF16 cos +#define SinF16 sin + +#define CelData void + +// Unknown Stuff + +void OpenMathFolio(); + +extern int ScreenWidth; +extern int ScreenHeight; +extern int ScreenWidthActual; +extern int ScreenHeightActual; + +extern Uint8 KeyboardDown[512]; + +extern UBYTE ControlA; +extern UBYTE ControlB; +extern UBYTE ControlC; +extern UBYTE ControlX; +extern UBYTE ControlStart; +extern UBYTE ControlLeftShift; +extern UBYTE ControlRightShift; + +extern void *HMalloc (Uint32 size); +extern void HFree (void *p); +extern void *HCalloc (Uint32 size); +extern void *HRealloc (void *p, Uint32 size); + +extern int TFB_DEBUG_HALT; + +#endif // THREEDO_WRAPPER_H diff --git a/sc2/src/gl.h b/sc2/src/gl.h new file mode 100644 index 000000000..532166b5f --- /dev/null +++ b/sc2/src/gl.h @@ -0,0 +1,45 @@ +#ifdef WIN32 + +/* To avoid including windows.h, + Win32's needs APIENTRY and WINGDIAPI defined properly. */ + +#pragma warning (disable:4244) /* Disable bogus conversion warnings. */ + +#ifndef APIENTRY +#define GLUT_APIENTRY_DEFINED +#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +#define APIENTRY __stdcall +#else +#define APIENTRY +#endif +#endif + +/* This is from Win32's */ +#ifndef CALLBACK +#if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +#define CALLBACK __stdcall +#else +#define CALLBACK +#endif +#endif + +/* This is from Win32's and */ +#ifndef WINGDIAPI +#define GLUT_WINGDIAPI_DEFINED +#define WINGDIAPI __declspec(dllimport) +#endif + +/* This is from Win32's */ +#ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif + +#include "GL/glu.h" + +#else /* !defined(WIN32) */ + +#include "GL/glu.h" + +#endif + diff --git a/sc2/src/msvc++/Starcon2.dsp b/sc2/src/msvc++/Starcon2.dsp new file mode 100644 index 000000000..e41989cf0 --- /dev/null +++ b/sc2/src/msvc++/Starcon2.dsp @@ -0,0 +1,2919 @@ +# Microsoft Developer Studio Project File - Name="Starcon2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Starcon2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Starcon2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Starcon2.mak" CFG="Starcon2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Starcon2 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Starcon2 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=snCl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Starcon2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D SAFE_X=0 /D SAFE_Y=0 /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=snBsc.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=snLink.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_mixer.lib smpeg.lib opengl32.lib glu32.lib /nodefaultlib:"msvcrtd.lib" /nologo /subsystem:console /machine:I386 /out:"../../Content/Starcon2.exe" + +!ELSEIF "$(CFG)" == "Starcon2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D SAFE_X=0 /D SAFE_Y=0 /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=snBsc.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo /o"Starcon2.bsc" +LINK32=snLink.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_mixer.lib smpeg.lib opengl32.lib glu32.lib /nodefaultlib:"msvcrt.lib" /nologo /subsystem:console /debug /machine:I386 /out:"../../Content/Starcon2Debug.exe" /pdbtype:sept +# SUBTRACT LINK32 /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "Starcon2 - Win32 Release" +# Name "Starcon2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "3DO Code" + +# PROP Default_Filter "" +# Begin Group "libs" + +# PROP Default_Filter "" +# Begin Group "decomp" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\decomp\lzdecode.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\decomp\lzencode.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\decomp\lzh.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\decomp\update.c +# End Source File +# End Group +# Begin Group "graphics" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\boxint.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\clipline.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\context.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\context.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\display.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\drawable.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\drawable.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\filegfx.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\font.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\font.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\frame.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\getbody.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\gfxintrn.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\intersec.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\line.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\loaddisp.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\makepoly.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\map.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\pixmap.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\poly.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\rect.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\resgfx.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\stamp.c +# End Source File +# End Group +# Begin Group "input" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\input\inpintrn.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\input\input.c +# End Source File +# End Group +# Begin Group "math" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\math\fastrand.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\math\mthintrn.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\math\random.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\math\random.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\math\sqrt.c +# End Source File +# End Group +# Begin Group "memory" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\memory\w_memlib.c +# End Source File +# End Group +# Begin Group "resource" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\resource\DIRECT.C +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\filecntl.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\getres.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\index.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\loadres.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\resdata.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\resinit.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\resintrn.h +# End Source File +# End Group +# Begin Group "sound" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\sound\fileinst.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sound\modfuncs.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sound\play.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sound\redbook.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sound\resinst.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sound\sndintrn.h +# End Source File +# End Group +# Begin Group "strings" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\strings\getstr.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\strings\sfileins.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\strings\sresins.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\strings\strings.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\strings\strintrn.h +# End Source File +# End Group +# Begin Group "video" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\libs\video\vfileins.c +# End Source File +# End Group +# Begin Source File + +SOURCE=..\sc2code\libs\compiler.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\declib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\errlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\gfxlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\inplib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\mathlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\memlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\reslib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\sndlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\strlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\timlib.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\vargs.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\vidlib.h +# End Source File +# End Group +# Begin Group "comm" + +# PROP Default_Filter "" +# Begin Group "arilou.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\arilouc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\arilou\strings.h +# End Source File +# End Group +# Begin Group "blackur.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\blackurc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\blackur\strings.h +# End Source File +# End Group +# Begin Group "chmmr.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\chmmrc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\chmmr\strings.h +# End Source File +# End Group +# Begin Group "comandr.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\comandr.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\comandr\strings.h +# End Source File +# End Group +# Begin Group "druuge.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\druugec.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\druuge\strings.h +# End Source File +# End Group +# Begin Group "ilwrath.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\ilwrathc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\ilwrath\strings.h +# End Source File +# End Group +# Begin Group "melnorm.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\melnorm.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\melnorm\strings.h +# End Source File +# End Group +# Begin Group "mycon.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\myconc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\mycon\strings.h +# End Source File +# End Group +# Begin Group "orz.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\orz\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\orzc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\orz\strings.h +# End Source File +# End Group +# Begin Group "pkunk.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\pkunkc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\pkunk\strings.h +# End Source File +# End Group +# Begin Group "rebel.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\rebel\rebel.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\rebel\strings.h +# End Source File +# End Group +# Begin Group "shofixt.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\shofixt.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\shofixt\strings.h +# End Source File +# End Group +# Begin Group "slyhome.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\slyhome.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyhome\strings.h +# End Source File +# End Group +# Begin Group "slyland.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\slyland.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\slyland\strings.h +# End Source File +# End Group +# Begin Group "spahome.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\spahome\spahome.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spahome\strings.h +# End Source File +# End Group +# Begin Group "spathi.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\spathic.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\spathi\strings.h +# End Source File +# End Group +# Begin Group "starbas.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\starbas\starbas.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\starbas\strings.h +# End Source File +# End Group +# Begin Group "supox.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\supox\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\supox\supoxc.c +# End Source File +# End Group +# Begin Group "syreen.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\syreen\syreenc.c +# End Source File +# End Group +# Begin Group "talkpet.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\talkpet\talkpet.c +# End Source File +# End Group +# Begin Group "thradd.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\thradd\thraddc.c +# End Source File +# End Group +# Begin Group "umgah.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\umgah\umgahc.c +# End Source File +# End Group +# Begin Group "urquan.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\urquan\urquanc.c +# End Source File +# End Group +# Begin Group "utwig.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\utwig\utwigc.c +# End Source File +# End Group +# Begin Group "vux.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\vux\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\vux\vuxc.c +# End Source File +# End Group +# Begin Group "yehat.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\yehat\yehatc.c +# End Source File +# End Group +# Begin Group "zoqfot.comm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\strings.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm\zoqfot\zoqfotc.c +# End Source File +# End Group +# End Group +# Begin Group "planets" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\planets\calc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\cargo.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\devices.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\elemdata.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genburv.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genchmmr.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gencol.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gendru.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genilw.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genmel.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genmyc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genorz.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genpet.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genpku.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genrain.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gensam.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genshof.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gensly.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gensol.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genspa.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gensup.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gensyr.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genthrad.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\gentopo.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genutw.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genvault.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genvux.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genwreck.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genyeh.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\genzoq.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\lander.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\lander.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\lifeform.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\orbits.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\oval.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\pl_stuff.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\plandata.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\planets.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\planets.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\plangen.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\planmap.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\planscan.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\pstarmap.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\report.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\roster.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\scan.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\scan.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\solarsys.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\sundata.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\planets\surface.c +# End Source File +# End Group +# Begin Group "ships" + +# PROP Default_Filter "" +# Begin Group "androsyn" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\androsyn.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\androsyn\restypes.h +# End Source File +# End Group +# Begin Group "arilou" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\arilou.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\arilou\restypes.h +# End Source File +# End Group +# Begin Group "blackurq" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\blackurq.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\blackurq\restypes.h +# End Source File +# End Group +# Begin Group "chenjesu" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\chenjesu.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chenjesu\restypes.h +# End Source File +# End Group +# Begin Group "chmmr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\chmmr.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\chmmr\restypes.h +# End Source File +# End Group +# Begin Group "druuge" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\druuge.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\druuge\restypes.h +# End Source File +# End Group +# Begin Group "human" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\human\human.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\human\restypes.h +# End Source File +# End Group +# Begin Group "ilwrath" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\ilwrath.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\ilwrath\restypes.h +# End Source File +# End Group +# Begin Group "lastbat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\lastbat.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\lastbat\restypes.h +# End Source File +# End Group +# Begin Group "melnorme" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\melnorme.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\melnorme\restypes.h +# End Source File +# End Group +# Begin Group "mmrnmhrm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\mmrnmhrm.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mmrnmhrm\restypes.h +# End Source File +# End Group +# Begin Group "mycon" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\mycon.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\mycon\restypes.h +# End Source File +# End Group +# Begin Group "orz" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\orz\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\orz.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\orz\restypes.h +# End Source File +# End Group +# Begin Group "pkunk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\pkunk.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\pkunk\restypes.h +# End Source File +# End Group +# Begin Group "probe" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\probe\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\probe.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\probe\restypes.h +# End Source File +# End Group +# Begin Group "shofixti" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\shofixti\shofixti.c +# End Source File +# End Group +# Begin Group "sis_ship" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\sis_ship\sis_ship.c +# End Source File +# End Group +# Begin Group "slylandr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\slylandr\slylandr.c +# End Source File +# End Group +# Begin Group "spathi" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\spathi\spathi.c +# End Source File +# End Group +# Begin Group "supox" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\supox\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\supox\supox.c +# End Source File +# End Group +# Begin Group "syreen" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\syreen\syreen.c +# End Source File +# End Group +# Begin Group "thradd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\thradd\thradd.c +# End Source File +# End Group +# Begin Group "umgah" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\umgah\umgah.c +# End Source File +# End Group +# Begin Group "urquan" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\urquan\urquan.c +# End Source File +# End Group +# Begin Group "utwig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\utwig\utwig.c +# End Source File +# End Group +# Begin Group "vux" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\vux\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\vux\vux.c +# End Source File +# End Group +# Begin Group "yehat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\yehat\yehat.c +# End Source File +# End Group +# Begin Group "zoqfot" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\icode.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ships\zoqfot\zoqfot.c +# End Source File +# End Group +# End Group +# Begin Source File + +SOURCE=..\sc2code\appglue.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\battle.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\border.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\build.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\build.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\cleanup.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\clock.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\clock.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\coderes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\collide.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\collide.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\comm.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\commglue.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\commglue.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\confirm.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\credits.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\cyborg.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\demo.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\demo.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\displist.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\displist.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\dummy.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\element.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\encount.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\encount.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\fmv.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\galaxy.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\gameinp.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\gameopt.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\gendef.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\getchar.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\globdata.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\globdata.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\gravity.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\gravwell.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\grpinfo.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\hyper.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\hyper.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\igfxres.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\imusicre.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\init.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\intel.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\intel.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\intro.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ipdisp.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ires_ind.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\istrtab.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\load.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\loadship.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\master.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\melee.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\melee.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\misc.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\nameref.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\oscill.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\outfit.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\pickmele.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\pickship.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\plandata.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\process.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\races.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\resinst.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\respkg.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\restart.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\restypes.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\save.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\settings.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\setup.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\ship.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\shipstat.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\shipyard.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\sis.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\sis.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\sounds.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\starbase.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\starbase.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\starcon.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\starcon.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\starmap.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\state.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\state.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\status.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\tactrans.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\trans.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\units.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\utils.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\velocity.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\velocity.h +# End Source File +# Begin Source File + +SOURCE=..\sc2code\weapon.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\weapon.h +# End Source File +# End Group +# Begin Group "NeoStarcon2 Wrappers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\SDL_wrapper.c +# End Source File +# Begin Source File + +SOURCE=..\SDL_wrapper.h +# End Source File +# Begin Source File + +SOURCE=..\starcon2.c +# End Source File +# Begin Source File + +SOURCE=..\trackplayer.c +# End Source File +# Begin Source File + +SOURCE=..\port.c +# End Source File +# Begin Source File + +SOURCE=..\port.h +# End Source File +# Begin Source File + +SOURCE=..\gl.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/sc2/src/msvc++/Starcon2.dsw b/sc2/src/msvc++/Starcon2.dsw new file mode 100644 index 000000000..29d7a319d --- /dev/null +++ b/sc2/src/msvc++/Starcon2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Starcon2"=".\Starcon2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/sc2/src/port.c b/sc2/src/port.c new file mode 100644 index 000000000..15f960899 --- /dev/null +++ b/sc2/src/port.c @@ -0,0 +1,41 @@ +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/* + * This file contains definitions that might be included in one system, but + * omited in another. + * + * Created by Serge van den Boom + */ + +#include +#include + +#ifndef HAVE_STRUPR +char * +strupr(char *str) +{ + char *ptr; + + ptr = str; + while (*ptr) + { + *ptr = toupper (*ptr); + ptr++; + } + return str; +} +#endif + diff --git a/sc2/src/port.h b/sc2/src/port.h new file mode 100644 index 000000000..9842b7ca7 --- /dev/null +++ b/sc2/src/port.h @@ -0,0 +1,13 @@ +#ifdef WIN32 +#define HAVE_STRICMP +#define HAVE_STRUPR +#endif + +#ifndef HAVE_STRICMP +#define stricmp strcasecmp +#endif + +#ifndef HAVE_STRUPR +char *strupr(char *str); +#endif + diff --git a/sc2/src/sc2code/Makefile.am b/sc2/src/sc2code/Makefile.am new file mode 100644 index 000000000..d68be665d --- /dev/null +++ b/sc2/src/sc2code/Makefile.am @@ -0,0 +1,49 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +SUBDIRS = ships libs planets comm + +# We build the core SC2 code as a static library. + +CFLAGS = -W -Wall + +INCLUDES = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs \ + @SDL_CFLAGS@ @SMPEG_CFLAGS@ + +noinst_LTLIBRARIES = libsc2.la + +libsc2_la_SOURCES = \ + battle.c border.c build.c cleanup.c clock.c collide.c comm.c \ + commglue.c confirm.c credits.c cyborg.c demo.c displist.c \ + dummy.c encount.c fmv.c galaxy.c gameinp.c gameopt.c gendef.c \ + getchar.c globdata.c gravity.c gravwell.c grpinfo.c hyper.c \ + init.c intel.c intro.c ipdisp.c load.c loadship.c master.c \ + melee.c misc.c oscill.c outfit.c pickmele.c pickship.c \ + plandata.c process.c restart.c save.c settings.c setup.c \ + ship.c shipstat.c shipyard.c sis.c starbase.c starcon.c \ + starmap.c state.c status.c tactrans.c trans.c utils.c \ + velocity.c weapon.c + +libsc2_la_LIBADD = \ + ships/libships.la planets/libplanets.la \ + comm/libcomm.la \ + libs/liblibs.la + +noinst_HEADERS = \ + appglue.h build.h clock.h coderes.h collide.h commglue.h demo.h \ + displist.h element.h encount.h globdata.h hyper.h ifontres.h \ + igfxres.h ikey_con.h imusicre.h intel.h ires_ind.h isndres.h \ + istrtab.h melee.h nameref.h races.h resinst.h respkg.h \ + restypes.h sis.h sounds.h starbase.h starcon.h state.h \ + units.h velocity.h weapon.h + +#noinst_PROGRAMS = sndtest + +#sndtest_SOURCES = test.c +#sndtest_LDADD = libsc2.a + diff --git a/sc2/src/sc2code/appglue.h b/sc2/src/sc2code/appglue.h new file mode 100644 index 000000000..dd0c63f8d --- /dev/null +++ b/sc2/src/sc2code/appglue.h @@ -0,0 +1,27 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _APPGLUE_H +#define _APPGLUE_H + +#include "vargs.h" + +extern DWORD race_glue (COUNT selector, vararg_dcl args, ...); + +#endif /* _APPGLUE_H */ + diff --git a/sc2/src/sc2code/battle.c b/sc2/src/sc2code/battle.c new file mode 100644 index 000000000..95d7c1ee4 --- /dev/null +++ b/sc2/src/sc2code/battle.c @@ -0,0 +1,249 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "SDL_wrapper.h" +//#include "starcon.h" + +QUEUE disp_q; +SIZE battle_counter; + +static void +ProcessInput (void) +{ + BOOLEAN CanRunAway; + + CanRunAway = (BOOLEAN)( + (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER + || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + && GET_GAME_STATE (STARBASE_AVAILABLE) + && !GET_GAME_STATE (BOMB_CARRIER) + ); + for (cur_player = NUM_SIDES - 1; cur_player >= 0; --cur_player) + { + HSTARSHIP hBattleShip, hNextShip; + + for (hBattleShip = GetHeadLink (&race_q[cur_player]); + hBattleShip != 0; hBattleShip = hNextShip) + { + INPUT_STATE InputState; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&race_q[cur_player], hBattleShip); + hNextShip = _GetSuccLink (StarShipPtr); + + if (StarShipPtr->hShip) + { + CyborgDescPtr = StarShipPtr; + + InputState = GetInputState (PlayerInput[cur_player]); +#if CREATE_JOURNAL + JournalInput (InputState); +#endif /* CREATE_JOURNAL */ + if (InputState & DEVICE_EXIT) + InputState = ConfirmExit (); + +#ifdef TESTING +if ((InputState & DEVICE_BUTTON3) + && LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) +{ + COUNT i; + + for (i = ARILOU_SHIP; i <= BLACK_URQUAN_SHIP; ++i) + ActivateStarShip (i, SPHERE_TRACKING); + while (GLOBAL (GameClock.tick_count) > 1) + ClockTick (); +} +#endif /* TESTING */ + + CyborgDescPtr->ship_input_state = 0; + if (CyborgDescPtr->RaceDescPtr->ship_info.crew_level) + { + if (GetInputXComponent (InputState) < 0) + CyborgDescPtr->ship_input_state |= LEFT; + else if (GetInputXComponent (InputState) > 0) + CyborgDescPtr->ship_input_state |= RIGHT; + if (GetInputYComponent (InputState) < 0 + || (InputState & DEVICE_BUTTON1)) + CyborgDescPtr->ship_input_state |= THRUST; + if (InputState & (DEVICE_BUTTON2 | DEVICE_RIGHTSHIFT)) + CyborgDescPtr->ship_input_state |= WEAPON; + if (InputState & (DEVICE_BUTTON3 | DEVICE_LEFTSHIFT)) + CyborgDescPtr->ship_input_state |= SPECIAL; + + if (CanRunAway + && cur_player == 0 + && ((PlayerControl[cur_player] & HUMAN_CONTROL) + || (InputState = GetInputState (NormalInput))) + && (InputState & (DEVICE_BUTTON2 | DEVICE_RIGHTSHIFT)) + == (DEVICE_BUTTON2 | DEVICE_RIGHTSHIFT)) + { + ELEMENTPTR ElementPtr; + + LockElement (StarShipPtr->hShip, &ElementPtr); + if (GetPrimType (&DisplayArray[ElementPtr->PrimIndex]) == STAMP_PRIM + && ElementPtr->life_span == NORMAL_LIFE + && !(ElementPtr->state_flags & FINITE_LIFE) + && ElementPtr->mass_points != MAX_SHIP_MASS * 10) + { + extern void flee_preprocess (PELEMENT + ElementPtr); + + battle_counter -= MAKE_WORD (1, 0); + + ElementPtr->turn_wait = 3; + ElementPtr->thrust_wait = MAKE_BYTE (4, 0); + ElementPtr->preprocess_func = flee_preprocess; + ElementPtr->mass_points = MAX_SHIP_MASS * 10; + ZeroVelocityComponents (&ElementPtr->velocity); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + + SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2E)); + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMPFILL_PRIM); + + CyborgDescPtr->ship_input_state = 0; + } + UnlockElement (StarShipPtr->hShip); + } + } + } + + UnlockStarShip (&race_q[cur_player], hBattleShip); + } + } + + if (GLOBAL (CurrentActivity) & (CHECK_LOAD | CHECK_ABORT)) + GLOBAL (CurrentActivity) &= ~IN_BATTLE; +} + +#if DEMO_MODE || CREATE_JOURNAL +DWORD BattleSeed; +#endif /* DEMO_MODE */ + +static MUSIC_REF BattleRef; + +void +BattleSong (BOOLEAN DoPlay) +{ + if (BattleRef == 0) + { + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + BattleRef = LoadMusicInstance (BATTLE_MUSIC); + else if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + BattleRef = LoadMusicInstance (HYPERSPACE_MUSIC); + else + BattleRef = LoadMusicInstance (QUASISPACE_MUSIC); + } + + if (DoPlay) + PlayMusic (BattleRef, TRUE, 1); +} + +void +FreeBattleSong (void) +{ + DestroyMusic (BattleRef); + BattleRef = 0; +} + +BOOLEAN +Battle (void) +{ + SIZE num_ships; + extern SIZE InitShips (void); + void UninitShips (void); + + SetSemaphore (&GraphicsSem); + + SetResourceIndex (hResIndex); + +#if !(DEMO_MODE || CREATE_JOURNAL) + SeedRandom (GetTimeCounter ()); +#else /* DEMO_MODE */ + if (BattleSeed == 0) + BattleSeed = Random (); + SeedRandom (BattleSeed); + BattleSeed = Random (); /* get next battle seed */ +#endif /* DEMO_MODE */ + + BattleSong (FALSE); + + num_ships = InitShips (); + if (num_ships) + { + DWORD NextTime; +BOOLEAN first_time; + + GLOBAL (CurrentActivity) |= IN_BATTLE; + battle_counter = MAKE_WORD ( + CountLinks (&race_q[0]), + CountLinks (&race_q[1]) + ); + + while (num_ships--) + { + if (!GetNextStarShip (NULL_PTR, num_ships)) + goto AbortBattle; + } + + BattleSong (TRUE); + NextTime = 0; +first_time = (BOOLEAN)(LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE); + do + { + extern UWORD nth_frame; + +BatchGraphics (); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + SeedUniverse (); + RedrawQueue (TRUE); +if (first_time) +{ + RECT r; + + first_time = FALSE; + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); +} +UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + if (nth_frame) + TaskSwitch (); + else + NextTime = SleepTask (NextTime + BATTLE_FRAME_RATE); + ProcessInput (); + SetSemaphore (&GraphicsSem); + } while (GLOBAL (CurrentActivity) & IN_BATTLE); + +AbortBattle: + StopMusic (); + StopSound (); + } + + UninitShips (); + FreeBattleSong (); + + ClearSemaphore (&GraphicsSem); + + return (num_ships < 0); +} + diff --git a/sc2/src/sc2code/border.c b/sc2/src/sc2code/border.c new file mode 100644 index 000000000..57a6a6a68 --- /dev/null +++ b/sc2/src/sc2code/border.c @@ -0,0 +1,194 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +InitSISContexts (void) +{ + RECT r; + + SetContext (StatusContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + SetContext (SpaceContext); + SetContextFGFrame (Screen); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + SetContextClipRect (&r); +} + +void +DrawSISFrame (void) +{ + RECT r; + + SetSemaphore (&GraphicsSem); + SetContext (ScreenContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + BatchGraphics (); + { + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; + r.extent.height = SIS_ORG_Y - 1; + DrawFilledRectangle (&r); + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SIS_ORG_X - 1; + r.extent.height = SIS_ORG_Y + SIS_SCREEN_HEIGHT + 1; + DrawFilledRectangle (&r); + r.corner.x = 0; + r.corner.y = r.extent.height; + r.extent.width = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; + r.extent.height = SCREEN_HEIGHT - SIS_ORG_Y + SIS_SCREEN_HEIGHT; + DrawFilledRectangle (&r); + r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH - r.corner.x; + r.extent.height = SCREEN_HEIGHT; + DrawFilledRectangle (&r); + + r.corner.x = SIS_ORG_X - 1; + r.corner.y = SIS_ORG_Y - 1; + r.extent.width = SIS_SCREEN_WIDTH + 2; + r.extent.height = SIS_SCREEN_HEIGHT + 2; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, BLACK_COLOR); + + r.corner.y = 0; + r.extent.height = SIS_ORG_Y; + + r.corner.x = SIS_ORG_X; + r.extent.width = SIS_SCREEN_WIDTH - 69; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xE), 0x54), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x1, 0x1C), 0x4E), + TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + + r.extent.width = 57; + r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xE), 0x54), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x1, 0x1C), 0x4E), + TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = SAFE_X + SPACE_WIDTH - 1; + r.corner.y = 0; + r.extent.width = 1; + r.extent.height = SCREEN_HEIGHT; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH; + r.corner.y = SAFE_Y + 139; + DrawPoint (&r.corner); + r.corner.x = SCREEN_WIDTH - 1; + DrawPoint (&r.corner); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.y = 1; + r.extent.width = 1; + r.extent.height = SAFE_Y + 7; + r.corner.x = SIS_ORG_X - 1; + DrawFilledRectangle (&r); + r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57 - 1; + DrawFilledRectangle (&r); + + r.corner.x = 0; + r.corner.y = SCREEN_HEIGHT - 1; + r.extent.width = SAFE_X + SPACE_WIDTH - 1; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH - 2; + r.corner.y = 0; + r.extent.width = 1; + r.extent.height = SCREEN_HEIGHT - 1; + DrawFilledRectangle (&r); + r.corner.x = SCREEN_WIDTH - 1; + r.corner.y = 0; + r.extent.width = 1; + r.extent.height = SAFE_Y + 139; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH; + r.corner.y = SCREEN_HEIGHT - 1; + r.extent.width = SCREEN_WIDTH - r.corner.x; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = SCREEN_WIDTH - 1; + r.corner.y = SAFE_Y + 140; + r.extent.width = 1; + r.extent.height = (SCREEN_HEIGHT - 1) - r.corner.y; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.y = 1; + r.extent.width = 1; + r.extent.height = SAFE_Y + 7; + r.corner.x = SIS_ORG_X + (SIS_SCREEN_WIDTH - 69); + DrawFilledRectangle (&r); + r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH; + ++r.extent.height; + DrawFilledRectangle (&r); + r.corner.y = 0; + r.extent.width = (SAFE_X + SPACE_WIDTH - 2) - r.corner.x; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = 0; + r.extent.width = SIS_ORG_X - r.corner.x; + DrawFilledRectangle (&r); + r.corner.x = SIS_ORG_X + (SIS_SCREEN_WIDTH - 69); + r.extent.width = (SIS_ORG_X + SIS_SCREEN_WIDTH - 57) - r.corner.x; + DrawFilledRectangle (&r); + + r.corner.x = 0; + r.corner.y = 1; + r.extent.width = 1; + r.extent.height = (SCREEN_HEIGHT - 1) - r.corner.y; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH; + r.corner.y = 0; + r.extent.width = 1; + r.extent.height = SAFE_Y + 139; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH + 1; + r.corner.y = SAFE_Y + 139; + r.extent.width = STATUS_WIDTH - 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = SAFE_X + SPACE_WIDTH; + r.corner.y = SAFE_Y + 140; + r.extent.width = 1; + r.extent.height = SCREEN_HEIGHT - r.corner.y; + DrawFilledRectangle (&r); + } + + InitSISContexts (); + ClearSISRect (DRAW_SIS_DISPLAY); + UnbatchGraphics (); + + ClearSemaphore (&GraphicsSem); +} + diff --git a/sc2/src/sc2code/build.c b/sc2/src/sc2code/build.c new file mode 100644 index 000000000..4b81bf70c --- /dev/null +++ b/sc2/src/sc2code/build.c @@ -0,0 +1,416 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +HSTARSHIP +Build (PQUEUE pQueue, DWORD RaceResIndex, COUNT which_player, BYTE + captains_name_index) +{ + HSTARSHIP hNewShip; + + if ((hNewShip = AllocStarShip (pQueue)) != 0) + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (pQueue, hNewShip); + memset (StarShipPtr, 0, GetLinkSize (pQueue)); + + StarShipPtr->RaceResIndex = RaceResIndex; + OwnStarShip (StarShipPtr, which_player, captains_name_index); + + UnlockStarShip (pQueue, hNewShip); + PutQueue (pQueue, hNewShip); + } + + return (hNewShip); +} + +HSTARSHIP +GetStarShipFromIndex (PQUEUE pShipQ, COUNT Index) +{ + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (pShipQ); + Index > 0 && hStarShip; hStarShip = hNextShip, --Index) + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (pShipQ, hStarShip); + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (pShipQ, hStarShip); + } + + return (hStarShip); +} + +COUNT +ActivateStarShip (COUNT which_ship, SIZE state) +{ + HSTARSHIP hStarShip, hNextShip; + + hStarShip = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), which_ship + ); + if (hStarShip) + { + switch (state) + { + case SPHERE_TRACKING: + case SPHERE_KNOWN: + { + EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + if (state == SPHERE_KNOWN) + which_ship = StarShipPtr->ShipInfo.known_strength; + else if (StarShipPtr->ShipInfo.actual_strength == 0) + { + if (!(StarShipPtr->ShipInfo.ship_flags + & (GOOD_GUY | BAD_GUY))) + which_ship = 0; + } + else if (StarShipPtr->ShipInfo.known_strength == 0 + && StarShipPtr->ShipInfo.actual_strength != (COUNT)~0) + { + StarShipPtr->ShipInfo.known_strength = 1; + StarShipPtr->ShipInfo.known_loc = + StarShipPtr->ShipInfo.loc; + } + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + return (which_ship); + } + case ESCORT_WORTH: + which_ship = 0; + case ESCORTING_FLAGSHIP: + { + COUNT ShipCost[] = + { + RACE_SHIP_COST + }; + + for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); + hStarShip; hStarShip = hNextShip) + { + BYTE ship_type; + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + if (state == ESCORT_WORTH) + which_ship += ShipCost[GET_RACE_ID (StarShipPtr)]; + else + ship_type = GET_RACE_ID (StarShipPtr); + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + if (state != ESCORT_WORTH + && (COUNT)ship_type == which_ship) + return (1); + } + + return (state == ESCORTING_FLAGSHIP ? 0 : which_ship); + } + case FEASIBILITY_STUDY: + return (MAX_BUILT_SHIPS + - CountLinks (&GLOBAL (built_ship_q))); + default: + { + SHIP_FRAGMENTPTR StarShipPtr; + + if (state <= 0) + { + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + if (state == CHECK_ALLIANCE) + { + state = StarShipPtr->ShipInfo.ship_flags + & (GOOD_GUY | BAD_GUY); + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + return ((COUNT)state); + } + else if (StarShipPtr->ShipInfo.ship_flags + & (GOOD_GUY | BAD_GUY)) + { + StarShipPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + if (state == 0) + StarShipPtr->ShipInfo.ship_flags |= GOOD_GUY; + else + { + StarShipPtr->ShipInfo.ship_flags |= BAD_GUY; + if (which_ship == ORZ_SHIP) + { + BOOLEAN ShipRemoved; + + ShipRemoved = FALSE; + for (hStarShip = GetHeadLink ( + &GLOBAL (built_ship_q + )); hStarShip; hStarShip = hNextShip) + { + BOOLEAN RemoveShip; + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + RemoveShip = (BOOLEAN)( + GET_RACE_ID (StarShipPtr) == ORZ_SHIP + ); + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + + if (RemoveShip) + { + ShipRemoved = TRUE; + + RemoveQueue ( + &GLOBAL (built_ship_q), + hStarShip + ); + FreeStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + } + } + + if (ShipRemoved) + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (UNDEFINED_DELTA, + UNDEFINED_DELTA, UNDEFINED_DELTA); + ClearSemaphore (&GraphicsSem); + } + } + } + } + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + else + { + BYTE which_window; + COUNT i; + + which_window = 0; + for + ( + i = 0; + + i < (COUNT)state + && + ( + hStarShip = CloneShipFragment + ( + (COUNT)which_ship, + (PQUEUE)(&GLOBAL (built_ship_q)), + (BYTE) + ( + ( + which_ship == SPATHI_SHIP && + GET_GAME_STATE (FOUND_PLUTO_SPATHI) + ) == 1 ? 1 : 0 + ) + ) + ); + + i++ + ) + { + HSTARSHIP hOldShip; + + RemoveQueue ( + &GLOBAL (built_ship_q), + hStarShip + ); + + while ((hOldShip = GetStarShipFromIndex ( + &GLOBAL (built_ship_q), + which_window++ + ))) + { + BYTE win_loc; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hOldShip + ); + win_loc = GET_GROUP_LOC (StarShipPtr); + UnlockStarShip ( + &GLOBAL (built_ship_q), hOldShip + ); + if (which_window <= win_loc) + break; + } + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + SET_GROUP_LOC (StarShipPtr, which_window - 1); + if (which_ship == SPATHI_SHIP + && GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) + { + OwnStarShip (StarShipPtr, + GOOD_GUY, + NAME_OFFSET + NUM_CAPTAINS_NAMES); + } + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + InsertQueue ( + &GLOBAL (built_ship_q), + hStarShip, hOldShip + ); + } + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (UNDEFINED_DELTA, + UNDEFINED_DELTA, UNDEFINED_DELTA); + ClearSemaphore (&GraphicsSem); + return (i); + } + break; + } + } + + return (1); + } + + return (0); +} + +COUNT +GetIndexFromStarShip (PQUEUE pShipQ, HSTARSHIP hStarShip) +{ + COUNT Index; + + Index = 0; + while (hStarShip != GetHeadLink (pShipQ)) + { + HSTARSHIP hNextShip; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (pShipQ, hStarShip); + hNextShip = _GetPredLink (StarShipPtr); + UnlockStarShip (pShipQ, hStarShip); + + hStarShip = hNextShip; + ++Index; + } + + return (Index); +} + +BYTE +NameCaptain (PQUEUE pQueue, STARSHIPPTR StarShipPtr) +{ + BYTE name_index; + HSTARSHIP hStarShip; + + do + { + HSTARSHIP hNextShip; + + name_index = PickCaptainName (); + for (hStarShip = GetHeadLink (pQueue); hStarShip; hStarShip = hNextShip) + { + STARSHIPPTR TestShipPtr; + + TestShipPtr = LockStarShip (pQueue, hStarShip); + hNextShip = _GetSuccLink (TestShipPtr); + if (TestShipPtr->RaceResIndex == StarShipPtr->RaceResIndex) + { + BOOLEAN SameName; + + if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) + SameName = (BOOLEAN)( + name_index == TestShipPtr->captains_name_index + ); + else + SameName = (BOOLEAN)( + name_index == StarShipCaptain (TestShipPtr) + ); + + if (SameName) + { + UnlockStarShip (pQueue, hStarShip); + break; + } + } + UnlockStarShip (pQueue, hStarShip); + } + } while (hStarShip); + + return (name_index); +} + +HSTARSHIP +CloneShipFragment (COUNT index, PQUEUE pDstQueue, BYTE crew_level) +{ + HSTARSHIP hStarShip, hBuiltShip; + SHIP_FRAGMENTPTR TemplatePtr; + + if ((hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), index)) == 0) + return (0); + + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + hBuiltShip = + Build (pDstQueue, + TemplatePtr->RaceResIndex, + TemplatePtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY), + (BYTE)(index == SAMATRA_SHIP ? + 0 : NameCaptain (pDstQueue, (STARSHIPPTR)TemplatePtr))); + if (hBuiltShip) + { + SHIP_FRAGMENTPTR ShipFragPtr; + + ShipFragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pDstQueue, hBuiltShip); + ShipFragPtr->ShipInfo = TemplatePtr->ShipInfo; + if (crew_level) + ShipFragPtr->ShipInfo.crew_level = crew_level; + ShipFragPtr->ShipInfo.energy_level = 0; + ShipFragPtr->ShipInfo.ship_flags = 0; + ShipFragPtr->ShipInfo.var1 = ShipFragPtr->ShipInfo.var2 = 0; + ShipFragPtr->ShipInfo.loc.x = ShipFragPtr->ShipInfo.loc.y = 0; + SET_RACE_ID (ShipFragPtr, (BYTE)index); + UnlockStarShip (pDstQueue, hBuiltShip); + } + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + + return (hBuiltShip); +} + diff --git a/sc2/src/sc2code/build.h b/sc2/src/sc2code/build.h new file mode 100644 index 000000000..cfcc665f5 --- /dev/null +++ b/sc2/src/sc2code/build.h @@ -0,0 +1,72 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _BUILD_H +#define _BUILD_H + +#define CREW_XOFFS 4 +#define ENERGY_XOFFS 52 +#define GAUGE_YOFFS (SHIP_INFO_HEIGHT - 10) +#define UNIT_WIDTH 2 +#define UNIT_HEIGHT 1 +#define STAT_WIDTH (1 + UNIT_WIDTH + 1 + UNIT_WIDTH + 1) + +#define NAME_OFFSET 5 +#define NUM_CAPTAINS_NAMES 16 + +#define OwnStarShip(S,p,n) \ + (S)->RaceDescPtr = (RACE_DESCPTR)MAKE_DWORD(p, n) +#define StarShipCaptain(S) \ + (BYTE)HIWORD ((S)->RaceDescPtr) +#define StarShipPlayer(S) \ + (COUNT)LOWORD ((S)->RaceDescPtr) +#define PickCaptainName() (((COUNT)Random () \ + & (NUM_CAPTAINS_NAMES - 1)) \ + + NAME_OFFSET) + +extern HSTARSHIP Build (PQUEUE pQueue, DWORD RaceResIndex, COUNT + which_player, BYTE captains_name_index); +extern HSTARSHIP CloneShipFragment (COUNT index, PQUEUE pDstQueue, BYTE + crew_level); +extern HSTARSHIP GetStarShipFromIndex (PQUEUE pShipQ, COUNT Index); +extern BYTE NameCaptain (PQUEUE pQueue, STARSHIPPTR StarShipPtr); + +#define CHECK_ALLIANCE -2 +#define ESCORT_WORTH 9995 +#define SPHERE_KNOWN 9996 +#define SPHERE_TRACKING 9997 +#define ESCORTING_FLAGSHIP 9998 +#define FEASIBILITY_STUDY 9999 + +extern COUNT ActivateStarShip (COUNT which_ship, SIZE state); +extern COUNT GetIndexFromStarShip (PQUEUE pShipQ, HSTARSHIP hStarShip); + +extern MEM_HANDLE load_ship (STARSHIPPTR StarShipPtr, BOOLEAN + LoadBattleData); +extern void free_ship (STARSHIPPTR StarShipPtr, BOOLEAN FreeBattleData); + +extern void DrawCrewFuelString (COORD y, SIZE state); +extern void ClearShipStatus (COORD y); +extern void OutlineShipStatus (COORD y); +extern void InitShipStatus (STARSHIPPTR StarShipPtr, PRECT pClipRect); +extern void DeltaStatistics (STARSHIPPTR StarShipPtr, SIZE crew_delta, + SIZE energy_delta); +extern void DrawBattleCrewAmount (BOOLEAN CountPlayer); + +#endif /* _BUILD_H */ + diff --git a/sc2/src/sc2code/cleanup.c b/sc2/src/sc2code/cleanup.c new file mode 100644 index 000000000..7fdfd1e88 --- /dev/null +++ b/sc2/src/sc2code/cleanup.c @@ -0,0 +1,106 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "libs/vidlib.h" + +//Added by Chris + +void FreeSC2Data (void); + +void FreeLanderData (void); + +void FreeIPData (void); + +void FreeMasterShipList (void); + +void UninitSpace (void); + +void FreeHyperData (void); + +//End Added by Chris + +void +FreeKernel (void) +{ + extern void UninitPlayerInput (void); + + UninitKernel (TRUE); + UninitContexts (); + + UNINIT_INSTANCES (); + UninitResourceSystem (); + + UninitPlayerInput (); + + DestroyDrawable (ReleaseDrawable (Screen)); + DestroyContext (ReleaseContext (ScreenContext)); + + UninitVideo (); + UninitSound (); + UninitGraphics (); +} + +void +UninitContexts (void) +{ + UninitQueue (&disp_q); + + DestroyContext (ReleaseContext (OffScreenContext)); + DestroyContext (ReleaseContext (SpaceContext)); + DestroyContext (ReleaseContext (StatusContext)); +} + +void +UninitKernel (BOOLEAN ships) +{ + extern FRAME status; + + UninitSpace (); + + DestroySound (ReleaseSound (MenuSounds)); + DestroyFont (ReleaseFont (MicroFont)); + DestroyStringTable (ReleaseStringTable (GameStrings)); + DestroyDrawable (ReleaseDrawable (status)); + DestroyDrawable (ReleaseDrawable (ActivityFrame)); + DestroyFont (ReleaseFont (TinyFont)); + DestroyFont (ReleaseFont (StarConFont)); + + UninitQueue (&race_q[0]); + UninitQueue (&race_q[1]); + + if (ships) + FreeMasterShipList (); + + ActivityFrame = 0; +} + +void UninitGameKernel () +{ + if (ActivityFrame) + { + FreeSC2Data (); + FreeLanderData (); + FreeIPData (); + FreeHyperData (); + + UninitKernel (FALSE); + UninitContexts (); + } +} + diff --git a/sc2/src/sc2code/clock.c b/sc2/src/sc2code/clock.c new file mode 100644 index 000000000..5c153857f --- /dev/null +++ b/sc2/src/sc2code/clock.c @@ -0,0 +1,341 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +#define IsLeapYear(yi) (!((yi) & 3) && (((yi) % 100) || ((yi) % 400))) + +int clock_task_func(void* blah) +{ + BOOLEAN LastPilot; + DWORD LastTime; + BYTE days_in_month[12] = + { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + }; + COUNT cycle_index, delay_count; + COLOR cycle_tab[] = + { + BUILD_COLOR (MAKE_RGB15 (0xA, 0x14, 0x18), 0x5B), + BUILD_COLOR (MAKE_RGB15 (0x6, 0x10, 0x16), 0x5C), + BUILD_COLOR (MAKE_RGB15 (0x3, 0xE, 0x14), 0x5D), + BUILD_COLOR (MAKE_RGB15 (0x2, 0xC, 0x11), 0x5E), + BUILD_COLOR (MAKE_RGB15 (0x1, 0xB, 0xF), 0x5F), + BUILD_COLOR (MAKE_RGB15 (0x1, 0x9, 0xD), 0x60), + BUILD_COLOR (MAKE_RGB15 (0x0, 0x7, 0xB), 0x61), + }; +#define NUM_CYCLES (sizeof (cycle_tab) / sizeof (cycle_tab[0])) +#define NUM_DELAYS 9 + + LastPilot = FALSE; + LastTime = 0; + cycle_index = delay_count = 0; + while (GLOBAL (GameClock).day_in_ticks == 0) + TaskSwitch (); + for (;;) + { + BOOLEAN OnAutoPilot; + DWORD TimeIn; + + /* use semaphore so that time passage + * can be halted. (e.g. during battle + * or communications) + */ + TimeIn = SetSemaphore (&GLOBAL (GameClock).clock_sem); + + if (GLOBAL (GameClock).tick_count <= 0 + && (GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks) > 0) + { + if (GLOBAL (GameClock).month_index == 2) + { + if (IsLeapYear (GLOBAL (GameClock).year_index)) + days_in_month[1] = 29; /* leap year */ + else + days_in_month[1] = 28; + } + + if (++GLOBAL (GameClock).day_index > days_in_month[GLOBAL (GameClock).month_index - 1]) + { + GLOBAL (GameClock).day_index = 1; + if (++GLOBAL (GameClock).month_index > 12) + { + GLOBAL (GameClock).month_index = 1; + ++GLOBAL (GameClock).year_index; + } + } + + SetSemaphore (&GraphicsSem); + DrawStatusMessage (NULL_PTR); + { + HEVENT hEvent; + + while ((hEvent = GetHeadEvent ())) + { + EVENTPTR EventPtr; + + LockEvent (hEvent, &EventPtr); + + if (GLOBAL (GameClock).day_index != EventPtr->day_index + || GLOBAL (GameClock).month_index != EventPtr->month_index + || GLOBAL (GameClock).year_index != EventPtr->year_index) + { + UnlockEvent (hEvent); + break; + } + RemoveEvent (hEvent); + EventHandler (EventPtr->func_index); + + UnlockEvent (hEvent); + FreeEvent (hEvent); + } + } + ClearSemaphore (&GraphicsSem); + } + + OnAutoPilot = (BOOLEAN)( + (GLOBAL (autopilot.x) != ~0 + && GLOBAL (autopilot.y) != ~0) + || GLOBAL_SIS (FuelOnBoard) == 0 + ); + if (OnAutoPilot || OnAutoPilot != LastPilot) + { + COUNT num_ticks; + + num_ticks = (COUNT)(SetSemaphore (&GraphicsSem) - LastTime); + if (!OnAutoPilot) + { + DrawSISMessage (NULL_PTR); + cycle_index = delay_count = 0; + } + else if (delay_count > num_ticks) + { + delay_count -= num_ticks; + } + else + { + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT) + && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) + { + CONTEXT OldContext; + + OldContext = SetContext (OffScreenContext); + SetContextForeGroundColor (cycle_tab[cycle_index]); + DrawSISMessage ((UNICODE *)~0L); + SetContext (OldContext); + } + + cycle_index = (cycle_index + 1) % NUM_CYCLES; + delay_count = NUM_DELAYS; + } + ClearSemaphore (&GraphicsSem); + + LastPilot = OnAutoPilot; + LastTime += num_ticks; + } + + ClearSemaphore (&GLOBAL (GameClock).clock_sem); + SleepTask (TimeIn + 1); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +BOOLEAN +InitGameClock (void) +{ + if (!InitQueue (&GLOBAL (GameClock.event_q), NUM_EVENTS, sizeof (EVENT))) + return (FALSE); + + GLOBAL (GameClock.month_index) = 2; + GLOBAL (GameClock.day_index) = 17; + GLOBAL (GameClock.year_index) = START_YEAR; /* Feb 17, START_YEAR */ + GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks = 0; + SuspendGameClock (); + if ((GLOBAL (GameClock.clock_task) = + AddTask (clock_task_func, 2048)) == 0) + return (FALSE); + + return (TRUE); +} + +BOOLEAN +UninitGameClock (void) +{ + if (GLOBAL (GameClock.clock_task)) + { + if (!GameClockRunning ()) + ResumeGameClock (); + + SetSemaphore (&GLOBAL (GameClock.clock_sem)); + DeleteTask (GLOBAL (GameClock.clock_task)); + ClearSemaphore (&GLOBAL (GameClock.clock_sem)); + + GLOBAL (GameClock.clock_task) = 0; + } + + UninitQueue (&GLOBAL (GameClock.event_q)); + + return (TRUE); +} + +void +SuspendGameClock (void) +{ + SetSemaphore (&GLOBAL (GameClock.clock_sem)); + GLOBAL (GameClock.TimeCounter) = 0; +} + +void +ResumeGameClock (void) +{ + GLOBAL (GameClock.TimeCounter) = GetTimeCounter (); + ClearSemaphore (&GLOBAL (GameClock.clock_sem)); +} + +BOOLEAN +GameClockRunning (void) +{ + return ((BOOLEAN)(GLOBAL (GameClock.TimeCounter) != 0)); +} + +void +SetGameClockRate (COUNT seconds_per_day) +{ + SIZE new_day_in_ticks, new_tick_count; + +//if (GLOBAL (GameClock.clock_sem)) printf ("%u\n", GLOBAL (GameClock.clock_sem)); + SetSemaphore (&GLOBAL (GameClock.clock_sem)); + new_day_in_ticks = (SIZE)(seconds_per_day * (ONE_SECOND / 5)); + if (GLOBAL (GameClock.day_in_ticks) == 0) + new_tick_count = new_day_in_ticks; + else if (GLOBAL (GameClock.tick_count) <= 0) + new_tick_count = 0; + else if ((new_tick_count = (SIZE)((DWORD)GLOBAL (GameClock.tick_count) + * new_day_in_ticks / GLOBAL (GameClock.day_in_ticks))) == 0) + new_tick_count = 1; + GLOBAL (GameClock.day_in_ticks) = new_day_in_ticks; + GLOBAL (GameClock.tick_count) = new_tick_count; + ClearSemaphore (&GLOBAL (GameClock.clock_sem)); +} + +BOOLEAN +ValidateEvent (EVENT_TYPE type, PCOUNT pmonth_index, PCOUNT pday_index, + PCOUNT pyear_index) +{ + COUNT month_index, day_index, year_index; + + month_index = *pmonth_index; + day_index = *pday_index; + year_index = *pyear_index; + if (type == RELATIVE_EVENT) + { + BYTE days_in_month[12] = + { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + }; + + month_index += GLOBAL (GameClock.month_index) - 1; + year_index += GLOBAL (GameClock.year_index) + (month_index / 12); + month_index = (month_index % 12) + 1; + if (IsLeapYear (year_index)) + days_in_month[1] = 29; /* leap year */ + + day_index += GLOBAL (GameClock.day_index); + while (day_index > days_in_month[month_index - 1]) + { + day_index -= days_in_month[month_index - 1]; + if (++month_index > 12) + { + month_index = 1; + ++year_index; + if (IsLeapYear (year_index)) + days_in_month[1] = 29; /* leap year */ + else + days_in_month[1] = 28; + } + } + + *pmonth_index = month_index; + *pday_index = day_index; + *pyear_index = year_index; + } + + return (!(year_index < GLOBAL (GameClock.year_index) + || (year_index == GLOBAL (GameClock.year_index) + && (month_index < GLOBAL (GameClock.month_index) + || (month_index == GLOBAL (GameClock.month_index) + && day_index < GLOBAL (GameClock.day_index)))))); +} + +HEVENT +AddEvent (EVENT_TYPE type, COUNT month_index, COUNT day_index, COUNT + year_index, BYTE func_index) +{ + HEVENT hNewEvent; + + if (type == RELATIVE_EVENT + && month_index == 0 + && day_index == 0 + && year_index == 0) + EventHandler (func_index); + else if (ValidateEvent (type, &month_index, &day_index, &year_index) + && (hNewEvent = AllocEvent ())) + { + EVENTPTR EventPtr; + + LockEvent (hNewEvent, &EventPtr); + EventPtr->day_index = (BYTE)day_index; + EventPtr->month_index = (BYTE)month_index; + EventPtr->year_index = year_index; + EventPtr->func_index = func_index; + UnlockEvent (hNewEvent); + + { + HEVENT hEvent, hSuccEvent; + for (hEvent = GetHeadEvent (); hEvent != 0; hEvent = hSuccEvent) + { + LockEvent (hEvent, &EventPtr); + if (year_index < EventPtr->year_index + || (year_index == EventPtr->year_index + && (month_index < EventPtr->month_index + || (month_index == EventPtr->month_index + && day_index < EventPtr->day_index)))) + { + UnlockEvent (hEvent); + break; + } + + hSuccEvent = GetSuccEvent (EventPtr); + UnlockEvent (hEvent); + } + + InsertEvent (hNewEvent, hEvent); + } + + return (hNewEvent); + } + + return (0); +} + +SIZE +ClockTick (void) +{ + return (--GLOBAL (GameClock.tick_count)); +} + diff --git a/sc2/src/sc2code/clock.h b/sc2/src/sc2code/clock.h new file mode 100644 index 000000000..2e49e8715 --- /dev/null +++ b/sc2/src/sc2code/clock.h @@ -0,0 +1,115 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CLOCK_H +#define _CLOCK_H + +#define START_YEAR 2155 + +enum +{ + ARILOU_ENTRANCE_EVENT = 0, + ARILOU_EXIT_EVENT, + HYPERSPACE_ENCOUNTER_EVENT, + KOHR_AH_VICTORIOUS_EVENT, + ADVANCE_PKUNK_MISSION, + ADVANCE_THRADD_MISSION, + ZOQFOT_DISTRESS_EVENT, + ZOQFOT_DEATH_EVENT, + SHOFIXTI_RETURN_EVENT, + ADVANCE_UTWIG_SUPOX_MISSION, + KOHR_AH_GENOCIDE_EVENT, + SPATHI_SHIELD_EVENT, + ADVANCE_ILWRATH_MISSION, + ADVANCE_MYCON_MISSION, + ARILOU_UMGAH_CHECK, + YEHAT_REBEL_EVENT, + SLYLANDRO_RAMP_UP, + SLYLANDRO_RAMP_DOWN, + + NUM_EVENTS +}; + +#define UPDATE_DAY (1 << 0) +#define UPDATE_MONTH (1 << 1) +#define UPDATE_YEAR (1 << 2) + +typedef struct +{ + BYTE day_index, month_index; + COUNT year_index; + SIZE tick_count, day_in_ticks; + void *clock_sem; + TASK clock_task; + DWORD TimeCounter; + + QUEUE event_q; +} CLOCK_STATE; +typedef CLOCK_STATE *PCLOCK_STATE; + +typedef QUEUE_HANDLE HEVENT; + +typedef struct event +{ + HEVENT pred, succ; + + BYTE day_index, month_index; + COUNT year_index; + BYTE func_index; +} EVENT; +typedef EVENT *PEVENT; + +typedef enum +{ + ABSOLUTE_EVENT = 0, + RELATIVE_EVENT +} EVENT_TYPE; + +#define EVENTPTR PEVENT + +#define AllocEvent() AllocLink (&GLOBAL (GameClock.event_q)) +#define PutEvent(h) PutQueue (&GLOBAL (GameClock.event_q), h) +#define InsertEvent(h,i) InsertQueue (&GLOBAL (GameClock.event_q), h, i) +#define GetHeadEvent() GetHeadLink (&GLOBAL (GameClock.event_q)) +#define GetTailEvent() GetTailLink (&GLOBAL (GameClock.event_q)) +#define LockEvent(h,eptr) *(eptr) = (EVENTPTR)LockLink (&GLOBAL (GameClock.event_q), h) +#define UnlockEvent(h) UnlockLink (&GLOBAL (GameClock.event_q), h) +#define RemoveEvent(h) RemoveQueue (&GLOBAL (GameClock.event_q), h) +#define FreeEvent(h) FreeLink (&GLOBAL (GameClock.event_q), h) +#define GetPredEvent(l) _GetPredLink (l) +#define GetSuccEvent(l) _GetSuccLink (l) + + /* rates are in seconds per game day */ +#define HYPERSPACE_CLOCK_RATE 5 +#define INTERPLANETARY_CLOCK_RATE 30 + +extern BOOLEAN InitGameClock (void); +extern BOOLEAN UninitGameClock (void); +extern void SuspendGameClock (void); +extern void ResumeGameClock (void); +extern BOOLEAN GameClockRunning (void); +extern void SetGameClockRate (COUNT seconds_per_day); +extern BOOLEAN ValidateEvent (EVENT_TYPE type, PCOUNT pmonth_index, + PCOUNT pday_index, PCOUNT pyear_index); +extern HEVENT AddEvent (EVENT_TYPE type, COUNT month_index, COUNT + day_index, COUNT year_index, BYTE func_index); +extern void EventHandler (BYTE selector); +extern SIZE ClockTick (void); + +#endif /* _CLOCK_H */ + diff --git a/sc2/src/sc2code/coderes.h b/sc2/src/sc2code/coderes.h new file mode 100644 index 000000000..22296e306 --- /dev/null +++ b/sc2/src/sc2code/coderes.h @@ -0,0 +1,46 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CODERES_H +#define _CODERES_H + +#include "reslib.h" +#include "vargs.h" + +typedef DWORD (*GLUEFUNC) (COUNT selector, vararg_dcl args, ...); + +extern MEM_HANDLE LoadCodeResFile (PSTR pStr); +extern BOOLEAN InstallCodeResType (COUNT code_type); +extern MEM_HANDLE LoadCodeResInstance (RESOURCE res); +extern PVOID CaptureCodeRes (MEM_HANDLE hCode, PVOID pData, PVOID + *ppLocData, GLUEFUNC glue_func); +extern MEM_HANDLE ReleaseCodeRes (PVOID CodeRef); +extern BOOLEAN DestroyCodeRes (MEM_HANDLE hCode); + +typedef struct +{ + MEM_HANDLE hCode; + UWORD size; +} CODE_REF; +typedef CODE_REF *PCODE_REF; + +#define ORG_OFFSET (((sizeof (CODE_REF) + (PARAGRAPH_SIZE - 1)) \ + / PARAGRAPH_SIZE) * PARAGRAPH_SIZE) + +#endif /* _CODERES_H */ + diff --git a/sc2/src/sc2code/collide.c b/sc2/src/sc2code/collide.c new file mode 100644 index 000000000..f0a0faea6 --- /dev/null +++ b/sc2/src/sc2code/collide.c @@ -0,0 +1,175 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +/* #define DEBUG */ + +void +collide (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1) +{ + SIZE speed; + SIZE dx0, dy0, dx1, dy1, dx_rel, dy_rel; + SIZE TravelAngle0, TravelAngle1, ImpactAngle0, ImpactAngle1; + SIZE RelTravelAngle, Directness; + + dx_rel = ElementPtr0->next.location.x + - ElementPtr1->next.location.x; + dy_rel = ElementPtr0->next.location.y + - ElementPtr1->next.location.y; + ImpactAngle0 = ARCTAN (dx_rel, dy_rel); + ImpactAngle1 = NORMALIZE_ANGLE (ImpactAngle0 + HALF_CIRCLE); + + GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); + TravelAngle0 = GetVelocityTravelAngle (&ElementPtr0->velocity); + GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); + TravelAngle1 = GetVelocityTravelAngle (&ElementPtr1->velocity); + dx_rel = dx0 - dx1; + dy_rel = dy0 - dy1; + RelTravelAngle = ARCTAN (dx_rel, dy_rel); + speed = square_root ((long)dx_rel * dx_rel + (long)dy_rel * dy_rel); + + Directness = NORMALIZE_ANGLE (RelTravelAngle - ImpactAngle0); + if (Directness <= QUADRANT || Directness >= HALF_CIRCLE + QUADRANT) + /* shapes just scraped each other but still collided, + * they will collide again unless we fudge it. + */ + { + Directness = HALF_CIRCLE; + ImpactAngle0 = TravelAngle0 + HALF_CIRCLE; + ImpactAngle1 = TravelAngle1 + HALF_CIRCLE; + } + +#ifdef DEBUG +printf ("Centers: <%d, %d> <%d, %d>\n", +ElementPtr0->next.location.x, ElementPtr0->next.location.y, +ElementPtr1->next.location.x, ElementPtr1->next.location.y); +printf ("RelTravelAngle : %d, ImpactAngles <%d, %d>\n", +RelTravelAngle, ImpactAngle0, ImpactAngle1); +#endif /* DEBUG */ + + if (ElementPtr0->next.location.x == ElementPtr0->current.location.x + && ElementPtr0->next.location.y == ElementPtr0->current.location.y + && ElementPtr1->next.location.x == ElementPtr1->current.location.x + && ElementPtr1->next.location.y == ElementPtr1->current.location.y) + { + if (ElementPtr0->state_flags & ElementPtr1->state_flags & DEFY_PHYSICS) + { + ImpactAngle0 = TravelAngle0 + (HALF_CIRCLE - OCTANT); + ImpactAngle1 = TravelAngle1 + (HALF_CIRCLE - OCTANT); + ZeroVelocityComponents (&ElementPtr0->velocity); + ZeroVelocityComponents (&ElementPtr1->velocity); + } + ElementPtr0->state_flags |= (DEFY_PHYSICS | COLLISION); + ElementPtr1->state_flags |= (DEFY_PHYSICS | COLLISION); +#ifdef DEBUG +printf ("No movement before collision -- <(%d, %d) = %d, (%d, %d) = %d>\n", +dx0, dy0, ImpactAngle0 - OCTANT, dx1, dy1, ImpactAngle1 - OCTANT); +#endif /* DEBUG */ + } + + { + SIZE mass0, mass1; + long scalar; + + mass0 = ElementPtr0->mass_points /* << 2 */; + mass1 = ElementPtr1->mass_points /* << 2 */; + scalar = (long)SINE (Directness, speed << 1) * (mass0 * mass1); + + if (!GRAVITY_MASS (ElementPtr0->mass_points + 1)) + { + if (ElementPtr0->state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + if (!(ElementPtr0->state_flags & DEFY_PHYSICS)) + { + if (ElementPtr0->turn_wait < COLLISION_TURN_WAIT) + ElementPtr0->turn_wait += COLLISION_TURN_WAIT; + if (ElementPtr0->thrust_wait < COLLISION_THRUST_WAIT) + ElementPtr0->thrust_wait += COLLISION_THRUST_WAIT; + } + } + + speed = (SIZE)(scalar / ((long)mass0 * (mass0 + mass1))); + DeltaVelocityComponents (&ElementPtr0->velocity, + COSINE (ImpactAngle0, speed), + SINE (ImpactAngle0, speed)); + + GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); + if (dx0 < 0) + dx0 = -dx0; + if (dy0 < 0) + dy0 = -dy0; + + if (VELOCITY_TO_WORLD (dx0 + dy0) < SCALED_ONE) + SetVelocityComponents (&ElementPtr0->velocity, + COSINE (ImpactAngle0, + WORLD_TO_VELOCITY (SCALED_ONE) - 1), + SINE (ImpactAngle0, + WORLD_TO_VELOCITY (SCALED_ONE) - 1)); + } + + if (!GRAVITY_MASS (ElementPtr1->mass_points + 1)) + { + if (ElementPtr1->state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + if (!(ElementPtr1->state_flags & DEFY_PHYSICS)) + { + if (ElementPtr1->turn_wait < COLLISION_TURN_WAIT) + ElementPtr1->turn_wait += COLLISION_TURN_WAIT; + if (ElementPtr1->thrust_wait < COLLISION_THRUST_WAIT) + ElementPtr1->thrust_wait += COLLISION_THRUST_WAIT; + } + } + + speed = (SIZE)(scalar / ((long)mass1 * (mass0 + mass1))); + DeltaVelocityComponents (&ElementPtr1->velocity, + COSINE (ImpactAngle1, speed), + SINE (ImpactAngle1, speed)); + + GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); + if (dx1 < 0) + dx1 = -dx1; + if (dy1 < 0) + dy1 = -dy1; + + if (VELOCITY_TO_WORLD (dx1 + dy1) < SCALED_ONE) + SetVelocityComponents (&ElementPtr1->velocity, + COSINE (ImpactAngle1, + WORLD_TO_VELOCITY (SCALED_ONE) - 1), + SINE (ImpactAngle1, + WORLD_TO_VELOCITY (SCALED_ONE) - 1)); + } +#ifdef DEBUG +GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); +GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); +printf ("After: <%d, %d> <%d, %d>\n\n", +dx0, dy0, dx1, dy1); +#endif /* DEBUG */ + } +} + diff --git a/sc2/src/sc2code/collide.h b/sc2/src/sc2code/collide.h new file mode 100644 index 000000000..1821a33a9 --- /dev/null +++ b/sc2/src/sc2code/collide.h @@ -0,0 +1,61 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _COLLIDE_H +#define _COLLIDE_H + +#define COLLISION_TURN_WAIT 1 +#define COLLISION_THRUST_WAIT 3 + +#define SKIP_COLLISION (NONSOLID | DISAPPEARING) +#define CollidingElement(e) \ + (!((e)->state_flags & SKIP_COLLISION)) +#define CollisionPossible(e0,e1) \ + (CollidingElement (e0) \ + && (!(((e1)->state_flags & (e0)->state_flags) & COLLISION) \ + && ((!(((e1)->state_flags & (e0)->state_flags) & IGNORE_SIMILAR) \ + || (e1)->pParent != (e0)->pParent)) \ + && ((e1)->mass_points || (e0)->mass_points))) + +#define InitIntersectStartPoint(eptr) \ +{ \ + (eptr)->IntersectControl.IntersectStamp.origin.x = \ + WORLD_TO_DISPLAY ((eptr)->current.location.x); \ + (eptr)->IntersectControl.IntersectStamp.origin.y = \ + WORLD_TO_DISPLAY ((eptr)->current.location.y); \ +} + +#define InitIntersectEndPoint(eptr) \ +{ \ + (eptr)->IntersectControl.EndPoint.x = \ + WORLD_TO_DISPLAY ((eptr)->next.location.x); \ + (eptr)->IntersectControl.EndPoint.y = \ + WORLD_TO_DISPLAY ((eptr)->next.location.y); \ +} + +#define InitIntersectFrame(eptr) \ +{ \ + (eptr)->IntersectControl.IntersectStamp.frame = \ + SetEquFrameIndex ((eptr)->next.image.farray[0], \ + (eptr)->next.image.frame); \ +} + +extern void collide (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1); + +#endif /* _COLLIDE_H */ + diff --git a/sc2/src/sc2code/comm.c b/sc2/src/sc2code/comm.c new file mode 100644 index 000000000..a501706e8 --- /dev/null +++ b/sc2/src/sc2code/comm.c @@ -0,0 +1,1944 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "SDL_wrapper.h" +#include "starcon.h" +#include "commglue.h" + +void InitOscilloscope (Sint32 x, Sint32 y, Sint32 width, Sint32 height, + void *f); +void SetSliderImage (void *f); +void InitSlider (Sint32 x, Sint32 y, Sint32 width, Sint32 height, + Sint32 bwidth, Sint32 bheight, void *f); +void Oscilloscope (Sint32 grab_data); +void Slider (void); + + +#define MAX_RESPONSES 8 +#define BACKGROUND_VOL (MAX_VOLUME >> 1) +#define FOREGROUND_VOL MAX_VOLUME + +#define SLIDER_Y 107 +#define SLIDER_HEIGHT 15 + +// #define DEBUG + +LOCDATA CommData; +int cur_comm; +UNICODE shared_phrase_buf[256]; + +typedef struct encounter_state +{ + BOOLEAN (*InputFunc) (INPUT_STATE InputState, struct encounter_state + *pES); + COUNT MenuRepeatDelay; + + COUNT Initialized; + BYTE num_responses, cur_response, top_response; + struct + { + RESPONSE_REF response_ref; + TEXT response_text; + RESPONSE_FUNC response_func; + } response_list[MAX_RESPONSES]; + + TASK AnimTask; + + COUNT phrase_buf_index; + UNICODE phrase_buf[512]; +} ENCOUNTER_STATE; +typedef ENCOUNTER_STATE *PENCOUNTER_STATE; + +enum +{ + UP_DIR, + DOWN_DIR, + NO_DIR +}; +enum +{ + PICTURE_ANIM, + COLOR_ANIM +}; +typedef struct +{ + COUNT Alarm; + BYTE Direction, FramesLeft; + BYTE AnimType; + union + { + FRAME CurFrame; + COLORMAP CurCMap; + } AnimObj; +} SEQUENCE, *PSEQUENCE; + +static PENCOUNTER_STATE pCurInputState; +enum +{ + DONE_SUBTITLE, + NEXT_SUBTITLE, + READ_SUBTITLE, + SPACE_SUBTITLE, + WAIT_SUBTITLE, +}; +static int subtitle_state = DONE_SUBTITLE; + + +static COORD +add_text (int status, PTEXT pTextIn) +{ + COUNT maxchars, numchars; + TEXT locText; + PTEXT pText; + SIZE leading; + UNICODE ch, *pStr; + SIZE text_width; + + BatchGraphics (); + + maxchars = (COUNT)~0; + if (status == 1) + { + text_width = CommData.AlienTextWidth; + SetContextFont (CommData.AlienFont); + GetContextFontLeading (&leading); + + pText = pTextIn; + } + else if (GetContextFontLeading (&leading), status <= -4) + { + text_width = SIS_SCREEN_WIDTH - (TEXT_X_OFFS << 2); + + pText = pTextIn; + } + else + { + text_width = SIS_SCREEN_WIDTH - (TEXT_X_OFFS << 2); + + switch (status) + { + case -3: + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + break; + case -2: + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + break; + case -1: + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1A, 0x1A, 0x1A), 0x12)); + break; + } + + maxchars = pTextIn->CharCount; + locText = *pTextIn; + locText.baseline.x -= 8; + locText.CharCount = 1; + ch = '*'; + locText.pStr = &ch; + DrawText (&locText); + + locText = *pTextIn; + pText = &locText; + pText->baseline.y -= leading; + } + + numchars = 0; + pStr = pText->pStr; + + do + { + pText->pStr = pStr; + pText->CharCount = 1; + pText->baseline.y += leading; + + { + BOOLEAN eot; + RECT r, old_r; + COUNT OldCount; + + GetContextClipRect (&r); + eot = FALSE; + do + { + old_r = r; + OldCount = pText->CharCount; + while (!(eot = (BOOLEAN)( + (ch = *++pStr) == '\0' + || ch == '\n' + || ch == '\r' + || (COUNT)(pStr - pText->pStr) >= maxchars + )) && ch != ' ') + ; + pText->CharCount = pStr - pText->pStr; + TextRect (pText, &r, NULL_PTR); + } while (!eot && r.extent.width < text_width); + + if (r.extent.width >= text_width) + { + pText->CharCount = OldCount; + r = old_r; + } + + if (maxchars -= pText->CharCount) + --maxchars; + numchars += pText->CharCount; + + if (status <= 0) + { + if (pText->baseline.y < SIS_SCREEN_HEIGHT) + DrawText (pText); + + pStr = pText->pStr + pText->CharCount; + if(status < -4 && pText->baseline.y >= -status - 10) + { + ++pStr; + break; + } + } + else + { + SetContextForeGroundColor (CommData.AlienTextBColor); + + --pText->baseline.x; + DrawText (pText); + + ++pText->baseline.x; + --pText->baseline.y; + DrawText (pText); + + ++pText->baseline.x; + ++pText->baseline.y; + DrawText (pText); + + --pText->baseline.x; + ++pText->baseline.y; + DrawText (pText); + + SetContextForeGroundColor (CommData.AlienTextFColor); + + --pText->baseline.y; + DrawText (pText); + + pStr = pText->pStr + pText->CharCount; + } + } + } while ((ch = *pStr++) != '\0' && ch != '\n' && ch != '\r' && maxchars); + pText->pStr = pStr; + + UnbatchGraphics (); + return (pText->baseline.y); +} + +static void +DrawSISComWindow (void) +{ + CONTEXT OldContext; + + if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) + { + RECT r; + + OldContext = SetContext (SpaceContext); + + r.corner.x = 0; + r.corner.y = SLIDER_Y + SLIDER_HEIGHT; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + + SetContext (OldContext); + } +#ifdef NEVER + else + { +#define NUM_CREDITS 5 + BYTE j; + TEXT t; + STRING OldStrings; + extern STRING CreditStrings; + + t.baseline.x = SCREEN_WIDTH >> 1; + t.baseline.y = RADAR_Y - 5; + t.align = ALIGN_CENTER; + + OldContext = SetContext (ScreenContext); + + OldStrings = SetRelStringTableIndex (CreditStrings, -NUM_CREDITS); + SetContextFont (MicroFont); + BatchGraphics (); + for (j = 0; j < NUM_CREDITS; ++j) + { + SetContextForeGroundColor (BLACK_COLOR); + t.pStr = (UNICODE *)GetStringAddress (OldStrings); + t.CharCount = GetStringLength (OldStrings); + OldStrings = SetRelStringTableIndex (OldStrings, 1); + DrawText (&t); + SetContextForeGroundColor (WHITE_COLOR); + t.pStr = (PBYTE)GetStringAddress (CreditStrings); + t.CharCount = GetStringLength (CreditStrings); + CreditStrings = SetRelStringTableIndex (CreditStrings, 1); + DrawText (&t); + + if (j) + t.baseline.y += 12; + else + { + t.baseline.y += 16; + SetContextFont (StarConFont); + } + } + UnbatchGraphics (); + + SetContext (OldContext); + } +#endif /* NEVER */ +} + +static void +DrawAlienFrame (FRAME aframe, PSEQUENCE pSeq) +{ + COUNT i; + STAMP s; + ANIMATION_DESCPTR ADPtr; + + s.origin.x = -SAFE_X; + s.origin.y = 0; + if ((s.frame = CommData.AlienFrame) == 0) + s.frame = aframe; + + BatchGraphics (); + DrawStamp (&s); + ADPtr = &CommData.AlienAmbientArray[i = CommData.NumAnimations]; + while (i--) + { + --ADPtr; + + if (!(ADPtr->AnimFlags & ANIM_MASK)) + { + s.frame = SetAbsFrameIndex ( + s.frame, + ADPtr->StartIndex + ); + DrawStamp (&s); + ADPtr->AnimFlags |= ANIM_DISABLED; + } + else if (pSeq) + { + if (pSeq->AnimType == PICTURE_ANIM) + { + s.frame = pSeq->AnimObj.CurFrame; + DrawStamp (&s); + } + --pSeq; + } + } + if (aframe && CommData.AlienFrame && aframe != CommData.AlienFrame) + { + s.frame = aframe; + DrawStamp (&s); + } + UnbatchGraphics (); +} + +static struct +{ + COLORMAPPTR CMapPtr; + SIZE Ticks; + TASK XFormTask; +} TaskControl; + +static BOOLEAN ColorChange; +static BOOLEAN volatile XFormFlush; +static COUNT volatile NumXFormTasks; + +int xform_PLUT_task(void* blah) +{ + COLORMAPPTR CurMapPtr; + TASK T; + + while ((T = TaskControl.XFormTask) == 0) + TaskSwitch (); + TaskControl.XFormTask = 0; + CurMapPtr = TaskControl.CMapPtr; + + { + SIZE TDelta, TTotal; + DWORD CurTime; + + TTotal = TaskControl.Ticks; + TaskControl.CMapPtr = 0; + CurTime = GetTimeCounter (); + do + { +#define NUMBER_OF_PLUTVALS 32 +#define NUMBER_OF_PLUT_UINT32s (NUMBER_OF_PLUTVALS >> 1) +#define PLUT_BYTE_SIZE (sizeof (DWORD) * NUMBER_OF_PLUT_UINT32s) + BYTE i; + DWORD StartTime; + DWORD *pCurCMap; + COLORMAPPTR ColorMapPtr; + extern DWORD *_varPLUTs; + + StartTime = CurTime; + CurTime = SleepTask (GetTimeCounter () + 2); + if (XFormFlush || (TDelta = (SIZE)(CurTime - StartTime)) > TTotal) + TDelta = TTotal; + + ColorMapPtr = CurMapPtr; + pCurCMap = (DWORD *)((BYTE *)_varPLUTs + (*ColorMapPtr * PLUT_BYTE_SIZE)); + ColorMapPtr += 2; + i = NUMBER_OF_PLUT_UINT32s; +if (_varPLUTs) + do + { + SIZE c0, c1; + DWORD v0, v1, val; + + v0 = *pCurCMap; + v1 = MAKE_DWORD ( + MAKE_WORD (ColorMapPtr[3], ColorMapPtr[2]), + MAKE_WORD (ColorMapPtr[1], ColorMapPtr[0]) + ); + ColorMapPtr += sizeof (DWORD); + + c0 = (v0 >> (10 + 16)) & 0x1F; + c1 = (v1 >> (10 + 16)) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (c0 & 0x1F) | (1 << 5); + + c0 = (v0 >> (5 + 16)) & 0x1F; + c1 = (v1 >> (5 + 16)) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (val << 5) | (c0 & 0x1F); + + c0 = (v0 >> (0 + 16)) & 0x1F; + c1 = (v1 >> (0 + 16)) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (val << 5) | (c0 & 0x1F); + + c0 = (v0 >> 10) & 0x1F; + c1 = (v1 >> 10) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (val << (5 + 1)) | (c0 & 0x1F) | (1 << 5); + + c0 = (v0 >> 5) & 0x1F; + c1 = (v1 >> 5) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (val << 5) | (c0 & 0x1F); + + c0 = (v0 >> 0) & 0x1F; + c1 = (v1 >> 0) & 0x1F; + c0 += ((c1 - c0) * TDelta) / TTotal; + val = (val << 5) | (c0 & 0x1F); + + *pCurCMap++ = val; + } while (--i); + + ColorChange = TRUE; + + } while (TTotal -= TDelta); + } + + --NumXFormTasks; + DeleteTask (T); + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +void +FlushPLUTXForms (void) +{ + if (NumXFormTasks) + { + XFormFlush = TRUE; + do + TaskSwitch (); + while (NumXFormTasks); + XFormFlush = FALSE; + } +} + +DWORD +XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) +{ + if (ColorMapPtr) + { + DWORD TimeOut; + + FlushPLUTXForms (); + + TaskControl.CMapPtr = ColorMapPtr; + if ((TaskControl.Ticks = TimeInterval) <= 0) + TaskControl.Ticks = 1; /* prevent divide by zero and negative fade */ + if + ( + TimeInterval == 0 || + ( + TaskControl.XFormTask = AddTask + ( + xform_PLUT_task, 1024 + ) + ) == 0 + ) + { + SetColorMap (ColorMapPtr); + ColorChange = TRUE; + TimeOut = GetTimeCounter (); + } + else + { + do + TaskSwitch (); + while (TaskControl.CMapPtr); + + ++NumXFormTasks; + TimeOut = GetTimeCounter () + TaskControl.Ticks + 1; + } + TaskControl.CMapPtr = 0; + + return (TimeOut); + } + + return (0); +} + +static void +RefreshResponses (PENCOUNTER_STATE pES) +{ + COORD y; + BYTE response; + SIZE leading; + STAMP s; + + SetContext (SpaceContext); + GetContextFontLeading (&leading); + BatchGraphics (); + + DrawSISComWindow (); + y = SLIDER_Y + SLIDER_HEIGHT + 1; + for (response = pES->top_response; response < pES->num_responses; ++response) + { + pES->response_list[response].response_text.baseline.x = TEXT_X_OFFS + 8; + pES->response_list[response].response_text.baseline.y = y + leading; + pES->response_list[response].response_text.align = ALIGN_LEFT; + if (response == pES->cur_response) + y = add_text (-1, &pES->response_list[response].response_text); + else + y = add_text (-2, &pES->response_list[response].response_text); + } + + if (pES->top_response) + { + s.origin.y = SLIDER_Y + SLIDER_HEIGHT + 1; + s.frame = SetAbsFrameIndex (ActivityFrame, 6); + } + else if (y > SIS_SCREEN_HEIGHT) + { + s.origin.y = SIS_SCREEN_HEIGHT - 2; + s.frame = SetAbsFrameIndex (ActivityFrame, 7); + } + else + s.frame = 0; + if (s.frame) + { + RECT r; + + GetFrameRect (s.frame, &r); + s.origin.x = SIS_SCREEN_WIDTH - r.extent.width - 1; + DrawStamp (&s); + } + + UnbatchGraphics (); +} + +static void +FeedbackPlayerPhrase (UNICODE *pStr) +{ + SetContext (SpaceContext); + + BatchGraphics (); + DrawSISComWindow (); + if (pStr[0]) + { + TEXT ct; + + ct.baseline.x = SIS_SCREEN_WIDTH >> 1; + ct.baseline.y = SLIDER_Y + SLIDER_HEIGHT + 13; + ct.align = ALIGN_CENTER; + ct.CharCount = (COUNT)~0; + ct.pStr = GAME_STRING (FEEDBACK_STRING_BASE); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xC, 0x1F), 0x48)); + DrawText (&ct); + ct.baseline.y += 16; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x12, 0x14, 0x4F), 0x44)); + ct.pStr = pStr; + add_text (-4, &ct); + } + UnbatchGraphics (); +} + +static void +SetUpSequence (PSEQUENCE pSeq) +{ + COUNT i; + ANIMATION_DESCPTR ADPtr; + + pSeq = &pSeq[i = CommData.NumAnimations]; + ADPtr = &CommData.AlienAmbientArray[i]; + while (i--) + { + --ADPtr; + --pSeq; + + if (ADPtr->AnimFlags & COLORXFORM_ANIM) + pSeq->AnimType = COLOR_ANIM; + else + pSeq->AnimType = PICTURE_ANIM; + pSeq->Direction = UP_DIR; + pSeq->FramesLeft = ADPtr->NumFrames; + if (pSeq->AnimType == COLOR_ANIM) + pSeq->AnimObj.CurCMap = SetAbsColorMapIndex ( + CommData.AlienColorMap, + ADPtr->StartIndex + ); + else + pSeq->AnimObj.CurFrame = SetAbsFrameIndex ( + CommData.AlienFrame, + ADPtr->StartIndex + ); + + if (ADPtr->AnimFlags & RANDOM_ANIM) + { + if (pSeq->AnimType == COLOR_ANIM) + pSeq->AnimObj.CurCMap = + SetRelColorMapIndex (pSeq->AnimObj.CurCMap, + (COUNT)Random () % pSeq->FramesLeft); + else + pSeq->AnimObj.CurFrame = + SetRelFrameIndex (pSeq->AnimObj.CurFrame, + (COUNT)Random () % pSeq->FramesLeft); + } + else if (ADPtr->AnimFlags & YOYO_ANIM) + { + --pSeq->FramesLeft; + if (pSeq->AnimType == COLOR_ANIM) + pSeq->AnimObj.CurCMap = + SetRelColorMapIndex (pSeq->AnimObj.CurCMap, 1); + else + pSeq->AnimObj.CurFrame = + IncFrameIndex (pSeq->AnimObj.CurFrame); + } + + pSeq->Alarm = + ADPtr->BaseRestartRate + + ((COUNT)Random () + % (ADPtr->RandomRestartRate + 1)) + + 1; + } +} + +static void +UpdateSpeechGraphics (BOOLEAN Initialize) +{ + CONTEXT OldContext; + + if (Initialize) + { + RECT r, sr; + FRAME f; + + InitOscilloscope (0, 0, RADAR_WIDTH, RADAR_HEIGHT, + SetAbsFrameIndex (ActivityFrame, 9)); + f = SetAbsFrameIndex (ActivityFrame, 2); + GetFrameRect (f, &r); + SetSliderImage (f); + f = SetAbsFrameIndex (ActivityFrame, 5); + GetFrameRect (f, &sr); + InitSlider (0, SLIDER_Y, SIS_SCREEN_WIDTH, sr.extent.height, + r.extent.width, r.extent.height, f); + } + + OldContext = SetContext (RadarContext); + Oscilloscope (!Initialize); + SetContext (SpaceContext); + Slider (); + SetContext (OldContext); +} + +int ambient_anim_task(void* blah) +{ + SIZE TalkAlarm; + FRAME TalkFrame; + COUNT i; + DWORD LastTime; + FRAME CommFrame; + register PPRIMITIVE pBatch; + SEQUENCE Sequencer[MAX_ANIMATIONS]; + PSEQUENCE pSeq; + ANIMATION_DESCPTR ADPtr; + DWORD ActiveMask; +DWORD LastOscillTime; + + while ((CommFrame = CommData.AlienFrame) == 0) + TaskSwitch (); + + SetSemaphore (&GraphicsSem); + memset ((PSTR)&DisplayArray[0], 0, sizeof (DisplayArray)); + SetUpSequence (Sequencer); + ClearSemaphore (&GraphicsSem); + + ActiveMask = 0; + TalkAlarm = 0; + TalkFrame = 0; + LastTime = GetTimeCounter (); +LastOscillTime = LastTime; + for (;;) + { + BOOLEAN Change, CanTalk; + DWORD CurTime, ElapsedTicks; + + SleepTask (LastTime + 1); + + CurTime = SetSemaphore (&GraphicsSem); + ElapsedTicks = CurTime - LastTime; + LastTime = CurTime; + + Change = FALSE; + i = CommData.NumAnimations; + if (CommData.AlienFrame) + CanTalk = TRUE; + else + { + i = 0; + CanTalk = FALSE; + } + + pBatch = &DisplayArray[MAX_ANIMATIONS + 1]; + pSeq = &Sequencer[i]; + ADPtr = &CommData.AlienAmbientArray[i]; + while (i--) + { + --ADPtr; + --pSeq; + if (ADPtr->AnimFlags & ANIM_DISABLED) + continue; + else if (pSeq->Direction == NO_DIR) + { + if (!(ADPtr->AnimFlags + & CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)) + pSeq->Direction = UP_DIR; + } + else if ((DWORD)pSeq->Alarm > ElapsedTicks) + pSeq->Alarm -= (COUNT)ElapsedTicks; + else + { + if (!(ActiveMask & ADPtr->BlockMask) + && (--pSeq->FramesLeft + || ((ADPtr->AnimFlags & YOYO_ANIM) + && pSeq->Direction == UP_DIR))) + { + ActiveMask |= 1L << i; + pSeq->Alarm = + ADPtr->BaseFrameRate + + ((COUNT)Random () + % (ADPtr->RandomFrameRate + 1)) + + 1; + } + else + { + ActiveMask &= ~(1L << i); + pSeq->Alarm = + ADPtr->BaseRestartRate + + ((COUNT)Random () + % (ADPtr->RandomRestartRate + 1)) + + 1; + if (ActiveMask & ADPtr->BlockMask) + continue; + } + + if (pSeq->AnimType == COLOR_ANIM) + { + XFormPLUT ( + GetColorMapAddress (pSeq->AnimObj.CurCMap), + pSeq->Alarm - 1 + ); + } + else + { + Change = TRUE; + --pBatch; + SetPrimNextLink (pBatch, (pBatch - &DisplayArray[0]) + 1); + SetPrimType (pBatch, STAMP_PRIM); +pBatch->Object.Stamp.origin.x = -SAFE_X; + pBatch->Object.Stamp.frame = pSeq->AnimObj.CurFrame; + } + + if (pSeq->FramesLeft == 0) + { + pSeq->FramesLeft = (BYTE)(ADPtr->NumFrames - 1); + + if (pSeq->Direction == DOWN_DIR) + pSeq->Direction = UP_DIR; + else if (ADPtr->AnimFlags & YOYO_ANIM) + pSeq->Direction = DOWN_DIR; + else + { + ++pSeq->FramesLeft; + if (pSeq->AnimType == COLOR_ANIM) + pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( + pSeq->AnimObj.CurCMap, + -pSeq->FramesLeft + ); + else + pSeq->AnimObj.CurFrame = SetRelFrameIndex ( + pSeq->AnimObj.CurFrame, + -pSeq->FramesLeft + ); + } + } + + if (ADPtr->AnimFlags & RANDOM_ANIM) + { + if (pSeq->AnimType == COLOR_ANIM) + pSeq->AnimObj.CurCMap = + SetAbsColorMapIndex (pSeq->AnimObj.CurCMap, + ADPtr->StartIndex + + ((COUNT)Random () + % ADPtr->NumFrames)); + else + pSeq->AnimObj.CurFrame = + SetAbsFrameIndex (pSeq->AnimObj.CurFrame, + ADPtr->StartIndex + + ((COUNT)Random () + % ADPtr->NumFrames)); + } + else if (pSeq->AnimType == COLOR_ANIM) + { + if (pSeq->Direction == UP_DIR) + pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( + pSeq->AnimObj.CurCMap, 1 + ); + else + pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( + pSeq->AnimObj.CurCMap, -1 + ); + } + else + { + if (pSeq->Direction == UP_DIR) + pSeq->AnimObj.CurFrame = + IncFrameIndex (pSeq->AnimObj.CurFrame); + else + pSeq->AnimObj.CurFrame = + DecFrameIndex (pSeq->AnimObj.CurFrame); + } + } + + if (pSeq->AnimType == PICTURE_ANIM + && (ADPtr->AnimFlags + & CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING) + && pSeq->Direction != NO_DIR) + { + COUNT index; + + CanTalk = FALSE; + if (!(pSeq->Direction != UP_DIR + || (index = GetFrameIndex (pSeq->AnimObj.CurFrame)) > + ADPtr->StartIndex + 1 + || (index == ADPtr->StartIndex + 1 + && (ADPtr->AnimFlags & CIRCULAR_ANIM)))) + pSeq->Direction = NO_DIR; + } + } + + ADPtr = &CommData.AlienTalkDesc; + if (CanTalk + && ADPtr->NumFrames + && (ADPtr->AnimFlags & WAIT_TALKING) + && !(CommData.AlienTransitionDesc.AnimFlags & PAUSE_TALKING)) + { + if ((long)TalkAlarm > (long)ElapsedTicks) + TalkAlarm -= (SIZE)ElapsedTicks; + else + { + BYTE AFlags; + SIZE FrameRate; + + if (TalkAlarm > 0) + TalkAlarm = 0; + else + TalkAlarm = -1; + + AFlags = ADPtr->AnimFlags; + if (!(AFlags & (TALK_INTRO | TALK_DONE))) + { + FrameRate = + ADPtr->BaseFrameRate + + ((COUNT)Random () + % (ADPtr->RandomFrameRate + 1)); + if (TalkAlarm < 0 + || GetFrameIndex (TalkFrame) == + ADPtr->StartIndex) + { + TalkFrame = SetAbsFrameIndex (CommFrame, + ADPtr->StartIndex + 1 + + ((COUNT)Random () + % (ADPtr->NumFrames - 1))); + FrameRate += + ADPtr->BaseRestartRate + + ((COUNT)Random () + % (ADPtr->RandomRestartRate + 1)); + } + else + { + TalkFrame = SetAbsFrameIndex (CommFrame, + ADPtr->StartIndex); + if (ADPtr->AnimFlags & PAUSE_TALKING) + { + if (!(CommData.AlienTransitionDesc.AnimFlags + & TALK_DONE)) + { + CommData.AlienTransitionDesc.AnimFlags |= + PAUSE_TALKING; + ADPtr->AnimFlags &= + ~PAUSE_TALKING; + } + else if (CommData.AlienTransitionDesc.NumFrames) + ADPtr->AnimFlags |= + TALK_DONE; + else + ADPtr->AnimFlags &= + ~(WAIT_TALKING | PAUSE_TALKING); + + FrameRate = 0; + } + } + } + else + { + ADPtr = &CommData.AlienTransitionDesc; + if (AFlags & TALK_INTRO) + { + FrameRate = + ADPtr->BaseFrameRate + + ((COUNT)Random () + % (ADPtr->RandomFrameRate + 1)); + if (TalkAlarm < 0) + TalkFrame = SetAbsFrameIndex (CommFrame, + ADPtr->StartIndex); + else + TalkFrame = IncFrameIndex (TalkFrame); + + if ((BYTE)(GetFrameIndex (TalkFrame) + - ADPtr->StartIndex + 1) == + ADPtr->NumFrames) + CommData.AlienTalkDesc.AnimFlags &= ~TALK_INTRO; + } + else /* if (AFlags & TALK_DONE) */ + { + FrameRate = + ADPtr->BaseFrameRate + + ((COUNT)Random () + % (ADPtr->RandomFrameRate + 1)); + if (TalkAlarm < 0) + TalkFrame = SetAbsFrameIndex (CommFrame, + ADPtr->StartIndex + + ADPtr->NumFrames + - 1); + else + TalkFrame = DecFrameIndex (TalkFrame); + + if (GetFrameIndex (TalkFrame) == + ADPtr->StartIndex) + { + CommData.AlienTalkDesc.AnimFlags &= + ~(PAUSE_TALKING | TALK_DONE); + if (ADPtr->AnimFlags & TALK_INTRO) + CommData.AlienTalkDesc.AnimFlags &= ~WAIT_TALKING; + else + { + ADPtr->AnimFlags |= + PAUSE_TALKING; + ADPtr->AnimFlags &= ~TALK_DONE; + } + FrameRate = 0; + } + } + } + + Change = TRUE; + --pBatch; + SetPrimNextLink (pBatch, (pBatch - &DisplayArray[0]) + 1); + SetPrimType (pBatch, STAMP_PRIM); +pBatch->Object.Stamp.origin.x = -SAFE_X; + pBatch->Object.Stamp.frame = TalkFrame; + + TalkAlarm = FrameRate; + } + } + + if (Change |= ColorChange) + { + CONTEXT OldContext; + + OldContext = SetContext (TaskContext); + + if (ColorChange) + { + FRAME F; + + F = CommData.AlienFrame; + CommData.AlienFrame = CommFrame; + DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]); + CommData.AlienFrame = F; + ColorChange = FALSE; + } + else + { + COUNT StartIndex; + + SetPrimNextLink (&DisplayArray[MAX_ANIMATIONS], END_OF_LIST); + + StartIndex = pBatch - &DisplayArray[0]; + DrawBatch (&DisplayArray[0], StartIndex, 0); + Change = FALSE; + } + + if (subtitle_state >= SPACE_SUBTITLE) + { + TEXT t; + + t = CommData.AlienTextTemplate; + add_text (1, &t); + } + + SetContext (OldContext); + } +if (LastOscillTime + (ONE_SECOND / 32) < CurTime) +{ + LastOscillTime = CurTime; + UpdateSpeechGraphics (FALSE); +} + ClearSemaphore (&GraphicsSem); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static BOOLEAN +SpewPhrases (COUNT wait_track) +{ + BOOLEAN ContinuityBreak; + DWORD TimeIn; + COUNT which_track; + INPUT_STATE InputState; + FRAME F; + + TimeIn = GetTimeCounter (); + + ContinuityBreak = FALSE; + F = CommData.AlienFrame; + if (wait_track == 0) + { + wait_track = which_track = (COUNT)~0; + InputState = 0; + goto Rewind; + } + + if (!(which_track = PlayingTrack ())) + { + // initial start of player + if (wait_track == 1 || wait_track == (COUNT)~0) + { + ResumeTrack (); + ClearSemaphore (&GraphicsSem); + do + { + TaskSwitch (); + SetSemaphore (&GraphicsSem); + which_track = PlayingTrack (); + ClearSemaphore (&GraphicsSem); + } while (!which_track); + SetSemaphore (&GraphicsSem); + } + } + else if (which_track <= wait_track) + ResumeTrack (); + + do + { + ClearSemaphore (&GraphicsSem); + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 64)); +#if DEMO_MODE || CREATE_JOURNAL + InputState = 0; +#else /* !(DEMO_MODE || CREATE_JOURNAL) */ + InputState = GetInputState (NormalInput); +#endif + if (InputState & DEVICE_EXIT) + InputState = ConfirmExit (); + + SetSemaphore (&GraphicsSem); + if (InputState & (DEVICE_BUTTON2 | DEVICE_EXIT)) + { + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); + JumpTrack (TRUE); + CommData.AlienFrame = F; + return (FALSE); + } + + if (which_track) + { + if (GetInputXComponent (InputState) > 0) + { + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3)); + FastForward (); + ContinuityBreak = TRUE; + CommData.AlienFrame = 0; + } + else if (GetInputXComponent (InputState) < 0) + { +Rewind: + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4)); + FastReverse (); + ContinuityBreak = TRUE; + CommData.AlienFrame = 0; + } + else if (ContinuityBreak) + { + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2)); + if ((which_track = PlayingTrack ()) + && which_track <= wait_track) + ResumeTrack (); + ContinuityBreak = FALSE; + } + else if (which_track == wait_track + || wait_track == (COUNT)~0) + CommData.AlienFrame = F; + } + } while (ContinuityBreak + || ((which_track = PlayingTrack ()) && which_track <= wait_track)); + + CommData.AlienFrame = F; + + if (wait_track == (COUNT)~0) + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); + + return (TRUE); +} + +void +AlienTalkSegue (COUNT wait_track) +{ + if ((GLOBAL (CurrentActivity) & CHECK_ABORT) + || (CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO)) + return; + + SetSemaphore (&GraphicsSem); + + if (!pCurInputState->Initialized) + { + SetColorMap (GetColorMapAddress (CommData.AlienColorMap)); + DrawAlienFrame (CommData.AlienFrame, NULL_PTR); +UpdateSpeechGraphics (TRUE); + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE + || (!GET_GAME_STATE (PLAYER_HYPNOTIZED) + && !GET_GAME_STATE (CHMMR_EMERGING) + && GET_GAME_STATE (CHMMR_BOMB_STATE) != 2 + && (pMenuState == 0 || !GET_GAME_STATE (MOONBASE_ON_SHIP) + || GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)))) + { +RECT r; + +if (pMenuState == 0) +{ + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); +} +else +{ + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + ScreenTransition (3, &r); +} +UnbatchGraphics (); + } + else + { + BYTE clut_buf[] = {FadeAllToColor}; + +UnbatchGraphics (); + if (GET_GAME_STATE (MOONBASE_ON_SHIP) + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2); + else if (GET_GAME_STATE (CHMMR_EMERGING)) + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2); + else + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 5); + } + pCurInputState->Initialized = TRUE; + + PlayMusic ((MUSIC_REF)CommData.AlienSong, TRUE, 1); + SetMusicVolume (BACKGROUND_VOL); + + { + DWORD TimeOut; + + TimeOut = GetTimeCounter () + (ONE_SECOND >> 1); +/* if (CommData.NumAnimations) */ + pCurInputState->AnimTask = AddTask (ambient_anim_task, 3072); + + ClearSemaphore (&GraphicsSem); + SleepTask (TimeOut); + SetSemaphore (&GraphicsSem); + } + + LastActivity &= ~CHECK_LOAD; + } + +if (wait_track == (COUNT)~0 || CommData.AlienTalkDesc.NumFrames) +{ + if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO)) + { + CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO; + if (CommData.AlienTransitionDesc.NumFrames) + CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO; + } + + CommData.AlienTransitionDesc.AnimFlags &= ~PAUSE_TALKING; + if (CommData.AlienTalkDesc.NumFrames) + CommData.AlienTalkDesc.AnimFlags |= WAIT_TALKING; + + while (CommData.AlienTalkDesc.AnimFlags & TALK_INTRO) + { + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + SetSemaphore (&GraphicsSem); + } +} + + if (!SpewPhrases (wait_track) || wait_track == (COUNT)~0) + FadeMusic (FOREGROUND_VOL, ONE_SECOND); + else + CommData.AlienTransitionDesc.AnimFlags &= ~TALK_INTRO; + +if (wait_track == (COUNT)~0 || CommData.AlienTalkDesc.NumFrames) +{ + CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; + if ((CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)) + CommData.AlienTalkDesc.AnimFlags |= PAUSE_TALKING; +} + + ClearSemaphore (&GraphicsSem); + + do + TaskSwitch (); + while (CommData.AlienTalkDesc.AnimFlags & PAUSE_TALKING); +} + +static BOOLEAN +DoCommunication (INPUT_STATE InputState, PENCOUNTER_STATE pES) +{ + if (!(CommData.AlienTransitionDesc.AnimFlags & (TALK_INTRO | TALK_DONE))) + AlienTalkSegue ((COUNT)~0); + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + ; + else if (pES->num_responses == 0) + { + DWORD TimeIn, TimeOut; + + TimeOut = FadeMusic (0, ONE_SECOND * 3) + 2; + TimeIn = GetTimeCounter (); + do + { + TimeIn = SleepTask (TimeIn + 1); + if (GetInputXComponent (GetInputState (NormalInput)) < 0) + { + FadeMusic (BACKGROUND_VOL, ONE_SECOND); + SetSemaphore (&GraphicsSem); + SpewPhrases (0); + ClearSemaphore (&GraphicsSem); + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + break; + TimeOut = FadeMusic (0, ONE_SECOND * 2) + 2; + TimeIn = GetTimeCounter (); + } + } while (TimeIn <= TimeOut); + } + else + { + BYTE response; + + if (pES->top_response == (BYTE)~0) + { + pES->top_response = 0; + SetSemaphore (&GraphicsSem); + RefreshResponses (pES); + ClearSemaphore (&GraphicsSem); + } + + if (InputState & DEVICE_BUTTON1) + { + pES->phrase_buf_index = + pES->response_list[pES->cur_response].response_text.CharCount; + wstrncpy (pES->phrase_buf, + pES->response_list[pES->cur_response].response_text.pStr, + pES->phrase_buf_index); + pES->phrase_buf[pES->phrase_buf_index++] = '\0'; + + SetSemaphore (&GraphicsSem); + FeedbackPlayerPhrase (pES->phrase_buf); + StopTrack (); + SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2)); + ClearSemaphore (&GraphicsSem); + + FadeMusic (BACKGROUND_VOL, ONE_SECOND); + + CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); + pES->num_responses = 0; + (*pES->response_list[pES->cur_response].response_func) + (pES->response_list[pES->cur_response].response_ref); + } + else + { + response = pES->cur_response; + if (GetInputXComponent (InputState) < 0) + { + FadeMusic (BACKGROUND_VOL, ONE_SECOND); + SetSemaphore (&GraphicsSem); + FeedbackPlayerPhrase (pES->phrase_buf); + SpewPhrases (0); + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + RefreshResponses (pES); + FadeMusic (FOREGROUND_VOL, ONE_SECOND); + } + ClearSemaphore (&GraphicsSem); + } + else if (GetInputYComponent (InputState) < 0) + response = (BYTE)((response + (BYTE)(pES->num_responses - 1)) + % pES->num_responses); + else if (GetInputYComponent (InputState) > 0) + response = (BYTE)((BYTE)(response + 1) + % pES->num_responses); + + if (response != pES->cur_response) + { + COORD y; + + SetSemaphore (&GraphicsSem); + BatchGraphics (); + add_text (-2, &pES->response_list[pES->cur_response].response_text); + + pES->cur_response = response; + + y = add_text (-1, &pES->response_list[pES->cur_response].response_text); + if (response < pES->top_response) + { + pES->top_response = 0; + RefreshResponses (pES); + } + else if (y > SIS_SCREEN_HEIGHT) + { + pES->top_response = response; + RefreshResponses (pES); + } + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + } + } + + return (TRUE); + } + + SetSemaphore (&GraphicsSem); + + if (pES->AnimTask) + { + DeleteTask (pES->AnimTask); + pES->AnimTask = 0; + } + CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); + + SetContext (SpaceContext); + DestroyContext (ReleaseContext (TaskContext)); + TaskContext = 0; + + ClearSemaphore (&GraphicsSem); + + FlushPLUTXForms (); + ColorChange = FALSE; + + FlushColorXForms (); + StopMusic (); + StopSound (); + StopTrack (); + SleepTask (FadeMusic (FOREGROUND_VOL, 0) + 2); + + return (FALSE); +} + +void +DoResponsePhrase (RESPONSE_REF R, RESPONSE_FUNC response_func, + UNICODE *ConstructStr) +{ + PENCOUNTER_STATE pES = pCurInputState; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return; + + if (pES->num_responses == 0) + { + pES->cur_response = 0; + pES->top_response = (BYTE)~0; + } + + pES->response_list[pES->num_responses].response_ref = R; + if ((pES->response_list[pES->num_responses].response_text.pStr = ConstructStr)) + pES->response_list[pES->num_responses].response_text.CharCount = wstrlen (ConstructStr); + else + { + STRING locString; + + locString = SetAbsStringTableIndex (CommData.ConversationPhrases, R - 1); + pES->response_list[pES->num_responses].response_text.pStr = + (UNICODE *)GetStringAddress (locString); + pES->response_list[pES->num_responses].response_text.CharCount = + GetStringLength (locString); +//#define BVT_PROBLEM +#ifdef BVT_PROBLEM +if (pES->response_list[pES->num_responses].response_text.pStr[ + pES->response_list[pES->num_responses].response_text.CharCount - 1 + ] == '\0') + --pES->response_list[pES->num_responses].response_text.CharCount; +#endif /* BVT_PROBLEM */ + } + pES->response_list[pES->num_responses].response_func = response_func; + ++pES->num_responses; +} + +static void +HailAlien (void) +{ + MEM_HANDLE hOldIndex; + ENCOUNTER_STATE ES; + FONT PlayerFont, OldFont; + + pCurInputState = &ES; + memset (pCurInputState, 0, sizeof (*pCurInputState)); + + ES.InputFunc = DoCommunication; + hOldIndex = SetResourceIndex (hResIndex); + PlayerFont = CaptureFont (LoadGraphic (PLAYER_FONT)); + SetResourceIndex (hOldIndex); + + CommData.AlienFrame = CaptureDrawable ( + LoadGraphicInstance ((RESOURCE)CommData.AlienFrame) + ); + CommData.AlienFont = CaptureFont ( + LoadGraphic ((RESOURCE)CommData.AlienFont) + ); + CommData.AlienColorMap = CaptureColorMap ( + LoadColorMapInstance ((RESOURCE)CommData.AlienColorMap) + ); + CommData.AlienSong = LoadMusicInstance ((RESOURCE)CommData.AlienSong); + CommData.ConversationPhrases = CaptureStringTable ( + LoadStringTableInstance ((RESOURCE)CommData.ConversationPhrases) + ); + + ES.phrase_buf_index = 1; + ES.phrase_buf[0] = '\0'; + + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + OldFont = SetContextFont (PlayerFont); + + { + RECT r; + + TaskContext = CaptureContext (CreateContext ()); + SetContext (TaskContext); + SetContextFGFrame (Screen); + GetFrameRect (CommData.AlienFrame, &r); + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + +BatchGraphics (); + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + r.corner.x = (SCREEN_WIDTH - SIS_SCREEN_WIDTH) >> 1; + SetContextClipRect (&r); + } + else + { + r.corner.x = SIS_ORG_X; + SetContextClipRect (&r); + + if (pMenuState == 0) + { + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings ((BYTE)~0, (BYTE)~0); + SetSemaphore (&GraphicsSem); + } + else /* in starbase */ + { + ClearSemaphore (&GraphicsSem); + DrawSISFrame (); + SetSemaphore (&GraphicsSem); + if (GET_GAME_STATE (STARBASE_AVAILABLE)) + { + DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 1)); + DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE + 0)); + } + else + { + DrawSISMessage (NULL_PTR); + DrawSISTitle (GLOBAL_SIS (PlanetName)); + } + } + } + + DrawSISComWindow (); + } + + ClearSemaphore (&GraphicsSem); + + LastActivity |= CHECK_LOAD; /* prevent spurious input */ + (*CommData.init_encounter_func) (); + DoInput ((PVOID)&ES); + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + (*CommData.uninit_encounter_func) (); + + SetSemaphore (&GraphicsSem); + + DestroyStringTable (ReleaseStringTable (CommData.ConversationPhrases)); + DestroyMusic ((MUSIC_REF)CommData.AlienSong); + DestroyColorMap (ReleaseColorMap (CommData.AlienColorMap)); + DestroyFont (ReleaseFont (CommData.AlienFont)); + DestroyDrawable (ReleaseDrawable (CommData.AlienFrame)); + + SetContext (SpaceContext); + SetContextFont (OldFont); + DestroyFont (ReleaseFont (PlayerFont)); + + CommData.ConversationPhrases = 0; + pCurInputState = 0; +} + +COUNT +InitCommunication (RESOURCE which_comm) +{ + COUNT status; + MEM_HANDLE hOldIndex, hIndex; + LOCDATAPTR LocDataPtr; + + SetSemaphore (&GraphicsSem); + + if (LastActivity & CHECK_LOAD) + { + LastActivity &= ~CHECK_LOAD; + if (which_comm != COMMANDER_CONVERSATION) + { + if (LOBYTE (LastActivity) == 0) + { + ClearSemaphore (&GraphicsSem); + DrawSISFrame (); + SetSemaphore (&GraphicsSem); + } + else + { + ClearSISRect (DRAW_SIS_DISPLAY); + RepairSISBorder (); + } + DrawSISMessage (NULL_PTR); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + DrawHyperCoords ( + GLOBAL (ShipStamp.origin) + ); + else if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) + DrawHyperCoords (CurStarDescPtr->star_pt); + else + DrawSISTitle (GLOBAL_SIS (PlanetName)); + } + } + + if (which_comm == 0) + status = URQUAN_PROBE_SHIP, which_comm = URQUAN_CONVERSATION; + else + { + if (which_comm == (RESOURCE) YEHAT_REBEL_CONVERSATION) + status = YEHAT_REBEL_SHIP, which_comm = YEHAT_CONVERSATION; + else if (((status = GET_PACKAGE (which_comm) + - GET_PACKAGE (ARILOU_CONVERSATION) + + ARILOU_SHIP) >= YEHAT_REBEL_SHIP)) + status = HUMAN_SHIP; /* conversation exception, set to self */ + ActivateStarShip (status, SPHERE_TRACKING); + + if (which_comm == ORZ_CONVERSATION + || (which_comm == TALKING_PET_CONVERSATION + && (!GET_GAME_STATE (TALKING_PET_ON_SHIP) + || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE)) + || (which_comm != CHMMR_CONVERSATION + && which_comm != SYREEN_CONVERSATION + ))//&& (ActivateStarShip (status, CHECK_ALLIANCE) & BAD_GUY))) + BuildBattle (1); + } + + hOldIndex = SetResourceIndex (hResIndex); + if ((hIndex = OpenResourceIndexInstance (which_comm)) == 0) + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + LocDataPtr = 0; + } + else + { + SetResourceIndex (hIndex); + + LocDataPtr = (LOCDATAPTR)init_race ( + status != YEHAT_REBEL_SHIP ? which_comm : YEHAT_REBEL_CONVERSATION + ); + if (LocDataPtr) + CommData = *LocDataPtr; + } + + ClearSemaphore (&GraphicsSem); + + if (GET_GAME_STATE (BATTLE_SEGUE) == 0) + status = HAIL; + else if ((status = InitEncounter ()) == HAIL && LocDataPtr) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + status = ATTACK; + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + + SetSemaphore (&GraphicsSem); + + if (status == HAIL) + { + cur_comm = which_comm; + HailAlien (); + cur_comm = 0; + } + else if (LocDataPtr) + (*CommData.uninit_encounter_func) (); + + SetResourceIndex (hOldIndex); + CloseResourceIndex (hIndex); + + ClearSemaphore (&GraphicsSem); + + status = 0; + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE + && (GLOBAL (glob_flags) & CYBORG_ENABLED)) + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); + status = (GET_GAME_STATE (BATTLE_SEGUE) + && GetHeadLink (&GLOBAL (npc_built_ship_q))); + if (status) + { + BuildBattle (0); + EncounterBattle (); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + } + + UninitEncounter (); + + return (status); +} + +void +RaceCommunication (void) +{ + COUNT i, status; + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + RESOURCE RaceComm[] = + { + RACE_COMMUNICATION + }; + extern ACTIVITY NextActivity; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + ReinitQueue (&GLOBAL (npc_built_ship_q)); + CloneShipFragment (SAMATRA_SHIP, &GLOBAL (npc_built_ship_q), 0); + InitCommunication (TALKING_PET_CONVERSATION); + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) + { + GLOBAL (CurrentActivity) = WON_LAST_BATTLE; + } + return; + } + /* going into talking pet conversation */ + else if (NextActivity & CHECK_LOAD) + { + BYTE ec; + + ec = GET_GAME_STATE (ESCAPE_COUNTER); + + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) + InitCommunication (SPATHI_CONVERSATION); + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == 0) + InitCommunication (TALKING_PET_CONVERSATION); + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & ((1 << 4) | (1 << 5))) + InitCommunication (ILWRATH_CONVERSATION); + else + InitCommunication (CHMMR_CONVERSATION); + if (GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) + { + NextActivity = GLOBAL (CurrentActivity) & ~START_ENCOUNTER; + if (LOBYTE (NextActivity) == IN_INTERPLANETARY) + NextActivity |= START_INTERPLANETARY; + GLOBAL (CurrentActivity) |= CHECK_LOAD; /* fake a load game */ + } + + SET_GAME_STATE (ESCAPE_COUNTER, ec); + return; + } + else if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + ReinitQueue (&GLOBAL (npc_built_ship_q)); + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) >= 2) + { + InitCommunication (ARILOU_CONVERSATION); + return; + } + else + { + COUNT NumShips; + HENCOUNTER hEncounter; + ENCOUNTERPTR EncounterPtr; + + hEncounter = GetHeadEncounter (); + LockEncounter (hEncounter, &EncounterPtr); + + NumShips = LONIBBLE (EncounterPtr->SD.Index); + for (i = 0; i < NumShips; ++i) + { + CloneShipFragment ( + EncounterPtr->SD.Type, + &GLOBAL (npc_built_ship_q), 0 + ); + } + + CurStarDescPtr = (STAR_DESCPTR)&EncounterPtr->SD; + UnlockEncounter (hEncounter); + } + } + + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + i = GET_RACE_ID (FragPtr); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + + status = InitCommunication (RaceComm[i]); + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + return; + + if (i == CHMMR_SHIP) + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) + { + /* if used destruct code in interplanetary */ + if (i == SLYLANDRO_SHIP && status == 0) + ReinitQueue (&GLOBAL (npc_built_ship_q)); + } + else + { + PEXTENDED_STAR_DESC pESD; + + pESD = (PEXTENDED_STAR_DESC)CurStarDescPtr; + if (pESD) + { + BYTE i, NumShips; + + NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q)); + pESD->Index = MAKE_BYTE ( + NumShips, HINIBBLE (pESD->Index) + ); + pESD->Index |= ENCOUNTER_REFORMING; + if (status == 0) + pESD->Index |= ONE_SHOT_ENCOUNTER; + + for (i = 0; i < NumShips; ++i) + { + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR TemplatePtr; + + hStarShip = GetStarShipFromIndex ( + &GLOBAL (npc_built_ship_q), i + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + pESD->ShipList[i] = TemplatePtr->ShipInfo; + pESD->ShipList[i].var1 = GET_RACE_ID (TemplatePtr); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + + ReinitQueue (&GLOBAL (npc_built_ship_q)); + CurStarDescPtr = 0; + } + } +} + +int +do_subtitles (UNICODE *pStr) +{ + static DWORD TimeOut; + + if (pStr == 0) + return (subtitle_state = NEXT_SUBTITLE); + else if (pStr == (void *)~0) + { + if (subtitle_state <= NEXT_SUBTITLE) + return (subtitle_state); + TimeOut = 0; + subtitle_state = WAIT_SUBTITLE; + } + + switch (subtitle_state) + { + static DWORD silence_length; +#define MODERATE_SPEED 16 + static BYTE speed_array[] = + { + 0, + 12, + MODERATE_SPEED, + 24, + 32, + }; + + case NEXT_SUBTITLE: + { + UNICODE ch; + COUNT numchars; + static UNICODE alien_phrase_buf[4096]; + + CommData.AlienTextTemplate.pStr = alien_phrase_buf; + numchars = 0; + do + { + ++numchars; + if (((ch = *pStr++) == '\n' || ch == '\r') + && !ispunct (pStr[-2]) + && !isspace (pStr[-2])) + { + *CommData.AlienTextTemplate.pStr++ = '.'; + *CommData.AlienTextTemplate.pStr++ = '.'; + *CommData.AlienTextTemplate.pStr++ = '.'; + *CommData.AlienTextTemplate.pStr++ = ch; + *CommData.AlienTextTemplate.pStr++ = '.'; + *CommData.AlienTextTemplate.pStr++ = '.'; + ch = '.'; + numchars += 6; + } + } while ((*CommData.AlienTextTemplate.pStr++ = ch)); + CommData.AlienTextTemplate.pStr = alien_phrase_buf; + CommData.AlienTextTemplate.CharCount = 0; +#if 0 + if (pES->phrase_buf_index >= 4 && CommData.AlienTextTemplate.pStr[-4] == '\r') + { + CommData.AlienTextTemplate.pStr -= 3; + CommData.AlienTextTemplate.pStr[-1] = '\n'; + } + pES->phrase_buf_index += numchars - 1; +#endif + } + /* fall through */ + case READ_SUBTITLE: + { + DWORD talk_length; + TEXT t; + BYTE read_speed; + CONTEXT OldContext; + + CommData.AlienTextTemplate.pStr += CommData.AlienTextTemplate.CharCount; + t = CommData.AlienTextTemplate; + + OldContext = SetContext (TaskContext); + add_text (1, &t); + SetContext (OldContext); + + CommData.AlienTextTemplate.CharCount = t.pStr - CommData.AlienTextTemplate.pStr; + + read_speed = speed_array[GLOBAL (glob_flags) & READ_SPEED_MASK]; + talk_length = ONE_SECOND * CommData.AlienTextTemplate.CharCount / MODERATE_SPEED; + if (read_speed) + { + silence_length = ONE_SECOND + * (CommData.AlienTextTemplate.CharCount + MODERATE_SPEED) / read_speed; + if (silence_length < talk_length) + talk_length = silence_length; + silence_length -= talk_length; + } + TimeOut = GetTimeCounter () + talk_length; + subtitle_state = SPACE_SUBTITLE; + break; + } + case SPACE_SUBTITLE: + if (GetTimeCounter () < TimeOut) + break; + TimeOut += silence_length; + subtitle_state = WAIT_SUBTITLE; + /* fall through */ + case WAIT_SUBTITLE: + if (speed_array[GLOBAL (glob_flags) & READ_SPEED_MASK] == 0 || GetTimeCounter () >= TimeOut) + { + if (CommData.AlienTextTemplate.pStr[CommData.AlienTextTemplate.CharCount - 1] == '\n') + subtitle_state = READ_SUBTITLE; + else + subtitle_state = DONE_SUBTITLE; + ColorChange = TRUE; + } + case DONE_SUBTITLE: + break; + } + + return (subtitle_state); +} diff --git a/sc2/src/sc2code/comm/Makefile.am b/sc2/src/sc2code/comm/Makefile.am new file mode 100644 index 000000000..d27b0c5db --- /dev/null +++ b/sc2/src/sc2code/comm/Makefile.am @@ -0,0 +1,30 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +RACES = \ + arilou blackur chmmr comandr druuge ilwrath melnorm mycon orz pkunk \ + rebel shofixt slyhome slyland spahome spathi starbas supox syreen \ + talkpet thradd umgah urquan utwig vux yehat zoqfot + +EXTRA_DIRS = $(RACES) + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libcomm.la +libcomm_la_LIBADD = $(patsubst %.c, %.lo, $(wildcard */*.c)) +libcomm_la_SOURCES = dummy.c + +%.lo: %.c + $(COMPILE) -c $< -o $@ + +clean: clean-am + rm -f */*.{o,lo} + +distclean: distclean-am + rm -f */*.{o,lo} + diff --git a/sc2/src/sc2code/comm/arilou/arilou.res b/sc2/src/sc2code/comm/arilou/arilou.res new file mode 100644 index 000000000..55ad99385 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/arilou.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/arilou + +PACKAGE ARILOU_PACKAGE arilou.con + GFXRES ARILOU_PMAP_ANIM arilou.ani + FONTRES ARILOU_FONT arilou.fon + MUSICRES ARILOU_MUSIC arilou.mod + STRTAB ARILOU_CONVERSATION_PHRASES arilou.txt + diff --git a/sc2/src/sc2code/comm/arilou/arilouc.c b/sc2/src/sc2code/comm/arilou/arilouc.c new file mode 100644 index 000000000..6d79f3d9c --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/arilouc.c @@ -0,0 +1,833 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/arilou/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/arilou/strings.h" + +static LOCDATA arilou_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)ARILOU_PMAP_ANIM, /* AlienFrame */ + (FONT)ARILOU_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + ARILOU_MUSIC, /* AlienSong */ + ARILOU_CONVERSATION_PHRASES, /* PlayerPhrases */ + 20, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 1) | (1L << 16) + }, + { + 13, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 0) | (1L << 16) + }, + { + 22, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1L << 16) + }, + { + 31, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4) + }, + { + 40, /* StartIndex */ + 10, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 3) + }, + { + 50, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 7) + }, + { + 59, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 67, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5) + }, + { + 76, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 9) + }, + { + 85, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 8) + }, + { + 94, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 103, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 13) + }, + { + 112, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 121, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 11) + }, + { + 129, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1L << 15) + }, + { + 138, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 14) + }, + { + 146, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 0) | (1 << 1) | (1 << 2) + }, + { + 155, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 157, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 159, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM | WAIT_TALKING,/* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye_angry_space)) + NPCPhrase (GOODBYE_ANGRY_SPACE); + else if (PLAYER_SAID (R, bye_friendly_space)) + NPCPhrase (GOODBYE_FRIENDLY_SPACE); + else if (PLAYER_SAID (R, bye_friendly_homeworld)) + NPCPhrase (GOODBYE_FRDLY_HOMEWORLD); + else if (PLAYER_SAID (R, lets_fight)) + NPCPhrase (NO_FIGHT); + else if (PLAYER_SAID (R, bug_eyed_fruitcakes)) + { + NPCPhrase (WE_NEVER_FRIENDS); + + SET_GAME_STATE (ARILOU_MANNER, 2); + } + else if (PLAYER_SAID (R, best_if_i_killed_you)) + { + NPCPhrase (WICKED_HUMAN); + + SET_GAME_STATE (ARILOU_MANNER, 2); + } +} + +static void +ArilouHome (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[4]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; + if (PLAYER_SAID (R, confused_by_hello)) + NPCPhrase (CONFUSED_RESPONSE); + else if (PLAYER_SAID (R, happy_by_hello)) + NPCPhrase (HAPPY_RESPONSE); + else if (PLAYER_SAID (R, miffed_by_hello)) + NPCPhrase (MIFFED_RESPONSE); + else if (PLAYER_SAID (R, ok_lets_be_friends)) + NPCPhrase (NO_ALLY_BUT_MUCH_GIVE); + else if (PLAYER_SAID (R, what_about_war)) + { + NPCPhrase (ABOUT_WAR); + + SET_GAME_STATE (ARILOU_STACK_1, 1); + } + else if (PLAYER_SAID (R, what_about_urquan)) + { + NPCPhrase (ABOUT_URQUAN); + + SET_GAME_STATE (ARILOU_STACK_1, 2); + } + else if (PLAYER_SAID (R, tell_arilou_about_tpet)) + { + NPCPhrase (BAD_NEWS_ABOUT_TPET); + + LastStack = 1; + SET_GAME_STATE (ARILOU_STACK_2, 1); + } + else if (PLAYER_SAID (R, what_do_about_tpet)) + { + NPCPhrase (DANGEROUS_BUT_USEFUL); + + LastStack = 1; + SET_GAME_STATE (ARILOU_STACK_2, 2); + } + else if (PLAYER_SAID (R, learned_about_umgah)) + { + if (GET_GAME_STATE (ARILOU_CHECKED_UMGAH) != 2) + NPCPhrase (NO_NEWS_YET); + else + { + NPCPhrase (UMGAH_UNDER_COMPULSION); + + LastStack = 1; + } + + DISABLE_PHRASE (learned_about_umgah); + } + else if (PLAYER_SAID (R, umgah_acting_weird)) + { + NPCPhrase (WELL_GO_CHECK); + + SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 1); + AddEvent (RELATIVE_EVENT, 0, 10, 0, ARILOU_UMGAH_CHECK); + DISABLE_PHRASE (umgah_acting_weird); + } + else if (PLAYER_SAID (R, what_do_now)) + { + NPCPhrase (GO_FIND_OUT); + + SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 3); + } + else if (PLAYER_SAID (R, what_did_on_earth)) + { + NPCPhrase (DID_THIS); + + LastStack = 2; + SET_GAME_STATE (ARILOU_STACK_3, 1); + } + else if (PLAYER_SAID (R, why_did_this)) + { + NPCPhrase (IDF_PARASITES); + + LastStack = 2; + SET_GAME_STATE (ARILOU_STACK_3, 2); + } + else if (PLAYER_SAID (R, tell_more)) + { + NPCPhrase (NOT_NOW); + + LastStack = 2; + SET_GAME_STATE (ARILOU_STACK_3, 3); + } + else if (PLAYER_SAID (R, what_give_me)) + { + NPCPhrase (ABOUT_PORTAL); + + LastStack = 3; + SET_GAME_STATE (KNOW_ARILOU_WANT_WRECK, 1); + + R = about_portal_again; + DISABLE_PHRASE (what_give_me); + } + else if (PLAYER_SAID (R, what_about_tpet)) + { + NPCPhrase (ABOUT_TPET); + + SET_GAME_STATE (ARILOU_STACK_4, 1); + } + else if (PLAYER_SAID (R, about_portal_again)) + { + NPCPhrase (PORTAL_AGAIN); + + DISABLE_PHRASE (about_portal_again); + } + else if (PLAYER_SAID (R, got_it)) + { + if (GET_GAME_STATE (ARILOU_HOME_VISITS) == 1) + NPCPhrase (CLEVER_HUMAN); + NPCPhrase (GIVE_PORTAL); + + SET_GAME_STATE (PORTAL_KEY_ON_SHIP, 0); + SET_GAME_STATE (PORTAL_SPAWNER, 1); + SET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 1); + } +#ifdef NEVER + else if (PLAYER_SAID (R, got_tpet)) + { + NPCPhrase (OK_GOT_TPET); + + SET_GAME_STATE (ARILOU_STACK_2, 1); + } +#endif /* NEVER */ + + switch (GET_GAME_STATE (ARILOU_STACK_1)) + { + case 0: + pStr[0] = what_about_war; + break; + case 1: + pStr[0] = what_about_urquan; + break; + } + if (GET_GAME_STATE (TALKING_PET)) + { +#ifdef NEVER + if (GET_GAME_STATE (ARILOU_STACK_2) == 0) + pStr[1] = got_tpet; +#endif /* NEVER */ + } + else + { + if (GET_GAME_STATE (TALKING_PET_VISITS)) + { + switch (GET_GAME_STATE (ARILOU_STACK_2)) + { + case 0: + pStr[1] = tell_arilou_about_tpet; + break; + case 1: + pStr[1] = what_do_about_tpet; + break; + } + } + else if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) + { + if (!GET_GAME_STATE (ARILOU_CHECKED_UMGAH)) + pStr[1] = umgah_acting_weird; + else if (PHRASE_ENABLED (learned_about_umgah) && PHRASE_ENABLED (umgah_acting_weird)) + pStr[1] = learned_about_umgah; + else if (GET_GAME_STATE (ARILOU_CHECKED_UMGAH) == 2) + pStr[1] = what_do_now; + } + } + switch (GET_GAME_STATE (ARILOU_STACK_3)) + { + case 0: + pStr[2] = what_did_on_earth; + break; + case 1: + pStr[2] = why_did_this; + break; + case 2: + pStr[2] = tell_more; + break; + } + if (!GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) + pStr[3] = what_give_me; + else if (!GET_GAME_STATE (ARILOU_STACK_4)) + pStr[3] = what_about_tpet; + + if (pStr[LastStack]) + Response (pStr[LastStack], ArilouHome); + for (i = 0; i < 4; ++i) + { + if (i != LastStack && pStr[i]) + Response (pStr[i], ArilouHome); + } + + if (GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) + { + if (GET_GAME_STATE (PORTAL_KEY_ON_SHIP)) + Response (got_it, ArilouHome); + else if (PHRASE_ENABLED (about_portal_again) && !GET_GAME_STATE (PORTAL_SPAWNER)) + Response (about_portal_again, ArilouHome); + } + if (GET_GAME_STATE (ARILOU_MANNER) != 3) + Response (best_if_i_killed_you, ExitConversation); + Response (bye_friendly_homeworld, ExitConversation); +} + +static void +AngryHomeArilou (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, invaders_from_mars)) + { + NPCPhrase (HAD_OUR_REASONS); + + DISABLE_PHRASE (invaders_from_mars); + } + else if (PLAYER_SAID (R, why_should_i_trust)) + { + NPCPhrase (TRUST_BECAUSE); + + DISABLE_PHRASE (why_should_i_trust); + } + else if (PLAYER_SAID (R, what_about_interference)) + { + NPCPhrase (INTERFERENCE_NECESSARY); + + DISABLE_PHRASE (what_about_interference); + } + else if (PLAYER_SAID (R, i_just_like_to_leave)) + { + NPCPhrase (SORRY_NO_LEAVE); + + DISABLE_PHRASE (i_just_like_to_leave); + } + + if (PHRASE_ENABLED (invaders_from_mars)) + Response (invaders_from_mars, AngryHomeArilou); + else + { + Response (bug_eyed_fruitcakes, ExitConversation); + } + if (PHRASE_ENABLED (why_should_i_trust)) + Response (why_should_i_trust, AngryHomeArilou); + else if (PHRASE_ENABLED (what_about_interference)) + Response (what_about_interference, AngryHomeArilou); + Response (ok_lets_be_friends, ArilouHome); + Response (i_just_like_to_leave, AngryHomeArilou); +} + +static void +AngrySpaceArilou (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, im_sorry)) + { + NPCPhrase (APOLOGIZE_AT_HOMEWORLD); + + DISABLE_PHRASE (im_sorry); + } + + Response (lets_fight, ExitConversation); + if (PHRASE_ENABLED (im_sorry)) + { + Response (im_sorry, AngrySpaceArilou); + } + Response (bye_angry_space, ExitConversation); +} + +static void +FriendlySpaceArilou (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, confused_by_hello)) + NPCPhrase (CONFUSED_RESPONSE); + else if (PLAYER_SAID (R, happy_by_hello)) + NPCPhrase (HAPPY_RESPONSE); + else if (PLAYER_SAID (R, miffed_by_hello)) + NPCPhrase (MIFFED_RESPONSE); + else if (PLAYER_SAID (R, whats_up_1) + || PLAYER_SAID (R, whats_up_2)) + { + NumVisits = GET_GAME_STATE (ARILOU_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_2); + } + else if (PLAYER_SAID (R, why_you_here)) + { + NPCPhrase (LEARN_THINGS); + + SET_GAME_STATE (ARILOU_STACK_5, 1); + } + else if (PLAYER_SAID (R, what_things)) + { + NPCPhrase (THESE_THINGS); + + SET_GAME_STATE (ARILOU_STACK_5, 2); + } + else if (PLAYER_SAID (R, why_do_it)) + { + NPCPhrase (DO_IT_BECAUSE); + + SET_GAME_STATE (ARILOU_STACK_5, 3); + } + else if (PLAYER_SAID (R, give_me_info_1) + || PLAYER_SAID (R, give_me_info_2)) + { + NumVisits = GET_GAME_STATE (ARILOU_HINTS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ARILOU_HINTS_1); + break; + case 1: + NPCPhrase (ARILOU_HINTS_2); + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) + { + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); + } + break; + case 2: + NPCPhrase (ARILOU_HINTS_3); + SET_GAME_STATE (KNOW_URQUAN_STORY, 1); + SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1) + break; + case 3: + NPCPhrase (ARILOU_HINTS_4); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_HINTS, NumVisits); + + DISABLE_PHRASE (give_me_info_2); + } + + switch (GET_GAME_STATE (ARILOU_STACK_5)) + { + case 0: + Response (why_you_here, FriendlySpaceArilou); + break; + case 1: + Response (what_things, FriendlySpaceArilou); + break; + case 2: + Response (why_do_it, FriendlySpaceArilou); + break; + } + if (PHRASE_ENABLED (whats_up_2)) + { + if (GET_GAME_STATE (ARILOU_INFO) == 0) + Response (whats_up_1, FriendlySpaceArilou); + else + Response (whats_up_2, FriendlySpaceArilou); + } + if (PHRASE_ENABLED (give_me_info_2)) + { + if (GET_GAME_STATE (ARILOU_HINTS) == 0) + Response (give_me_info_1, FriendlySpaceArilou); + else + Response (give_me_info_2, FriendlySpaceArilou); + } + Response (bye_friendly_space, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits, Manner; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + else if (!GET_GAME_STATE (MET_ARILOU)) + { + RESPONSE_FUNC RespFunc; + + NPCPhrase (INIT_HELLO); + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + RespFunc = (RESPONSE_FUNC)FriendlySpaceArilou; + } + else + { + RespFunc = (RESPONSE_FUNC)ArilouHome; + SET_GAME_STATE (ARILOU_HOME_VISITS, 1); + } + Response (confused_by_hello, RespFunc); + Response (happy_by_hello, RespFunc); + Response (miffed_by_hello, RespFunc); + SET_GAME_STATE (MET_ARILOU, 1); + goto ExitIntro; + } + + Manner = GET_GAME_STATE (ARILOU_MANNER); + if (Manner == 2) + { + NumVisits = GET_GAME_STATE (ARILOU_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_GOODBYE_1); + break; + case 1: + NPCPhrase (HOSTILE_GOODBYE_2); + break; + case 2: + NPCPhrase (HOSTILE_GOODBYE_3); + break; + case 3: + NPCPhrase (HOSTILE_GOODBYE_4); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (Manner == 1) + { + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) + { + NPCPhrase (INIT_ANGRY_HWLD_HELLO); + SET_GAME_STATE (ARILOU_HOME_VISITS, 1); + + AngryHomeArilou ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (ARILOU_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ANGRY_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (ANGRY_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_VISITS, NumVisits); + + AngrySpaceArilou ((RESPONSE_REF)0); + } + } + else + { + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + NumVisits = GET_GAME_STATE (ARILOU_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (FRIENDLY_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (FRIENDLY_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (FRIENDLY_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (FRIENDLY_SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_VISITS, NumVisits); + + FriendlySpaceArilou ((RESPONSE_REF)0); + } + else + { + if (!GET_GAME_STATE (PORTAL_SPAWNER) + && GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) + { + NumVisits = GET_GAME_STATE (NO_PORTAL_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (GOT_PART_YET_1); + break; + case 1: + NPCPhrase (GOT_PART_YET_1); + --NumVisits; + break; + } + SET_GAME_STATE (NO_PORTAL_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (ARILOU_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (FRDLY_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (FRDLY_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (FRDLY_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (FRDLY_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ARILOU_HOME_VISITS, NumVisits); + } + + ArilouHome ((RESPONSE_REF)0); + } + } +ExitIntro: + ; +} + +static COUNT +uninit_arilou (void) +{ + BYTE Manner; + + if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && (Manner = GET_GAME_STATE (ARILOU_MANNER)) != 2) + { + SET_GAME_STATE (ARILOU_MANNER, 1); + if (Manner != 1) + { + SET_GAME_STATE (ARILOU_VISITS, 0); + SET_GAME_STATE (ARILOU_HOME_VISITS, 0); + } + } + + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1 + && GET_GAME_STATE (ARILOU_HOME_VISITS) <= 1) + { + SET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 1); + SET_GAME_STATE (UMGAH_VISITS, 0); + SET_GAME_STATE (UMGAH_HOME_VISITS, 0); + + if (GET_GAME_STATE (ARILOU_MANNER) < 2) + { + SET_GAME_STATE (ARILOU_MANNER, 3); + } + } + + return (0); +} + +LOCDATAPTR +init_arilou_comm (void) +{ + LOCDATAPTR retval; + + arilou_desc.init_encounter_func = Intro; + arilou_desc.uninit_encounter_func = uninit_arilou; + + arilou_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + arilou_desc.AlienTextTemplate.baseline.y = 0; + arilou_desc.AlienTextTemplate.align = ALIGN_CENTER; + arilou_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1 + || GET_GAME_STATE (ARILOU_MANNER) == 3 + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &arilou_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/arilou/ifontres.h b/sc2/src/sc2code/comm/arilou/ifontres.h new file mode 100644 index 000000000..8be085a85 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/ifontres.h @@ -0,0 +1,3 @@ +#define ARILOU_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/arilou/igfxres.h b/sc2/src/sc2code/comm/arilou/igfxres.h new file mode 100644 index 000000000..7ec7c8fb5 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/igfxres.h @@ -0,0 +1,3 @@ +#define ARILOU_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/arilou/imusicre.h b/sc2/src/sc2code/comm/arilou/imusicre.h new file mode 100644 index 000000000..9d6f296d2 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/imusicre.h @@ -0,0 +1,3 @@ +#define ARILOU_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/arilou/istrtab.h b/sc2/src/sc2code/comm/arilou/istrtab.h new file mode 100644 index 000000000..568360c07 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/istrtab.h @@ -0,0 +1,3 @@ +#define ARILOU_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/arilou/resinst.h b/sc2/src/sc2code/comm/arilou/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/arilou/respkg.h b/sc2/src/sc2code/comm/arilou/respkg.h new file mode 100644 index 000000000..05f1c78ce --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/respkg.h @@ -0,0 +1,5 @@ +enum +{ + ARILOU_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/arilou/restypes.h b/sc2/src/sc2code/comm/arilou/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/arilou/strings.h b/sc2/src/sc2code/comm/arilou/strings.h new file mode 100644 index 000000000..aa72b5ec3 --- /dev/null +++ b/sc2/src/sc2code/comm/arilou/strings.h @@ -0,0 +1,123 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + INIT_HELLO, + confused_by_hello, + CONFUSED_RESPONSE, + happy_by_hello, + HAPPY_RESPONSE, + miffed_by_hello, + MIFFED_RESPONSE, + FRIENDLY_SPACE_HELLO_1, + FRIENDLY_SPACE_HELLO_2, + FRIENDLY_SPACE_HELLO_3, + FRIENDLY_SPACE_HELLO_4, + FRDLY_HOMEWORLD_HELLO_1, + FRDLY_HOMEWORLD_HELLO_2, + FRDLY_HOMEWORLD_HELLO_3, + FRDLY_HOMEWORLD_HELLO_4, + whats_up_1, + whats_up_2, + GENERAL_INFO_1, + GENERAL_INFO_2, + GENERAL_INFO_3, + GENERAL_INFO_4, + why_you_here, + LEARN_THINGS, + what_things, + THESE_THINGS, + why_do_it, + DO_IT_BECAUSE, + give_me_info_1, + ARILOU_HINTS_1, + give_me_info_2, + ARILOU_HINTS_2, + ARILOU_HINTS_3, + ARILOU_HINTS_4, + bye_friendly_space, + GOODBYE_FRIENDLY_SPACE, + GOT_PART_YET_1, + GOT_PART_YET_2, + INIT_ANGRY_HWLD_HELLO, + invaders_from_mars, + HAD_OUR_REASONS, + bug_eyed_fruitcakes, + WE_NEVER_FRIENDS, + ok_lets_be_friends, + NO_ALLY_BUT_MUCH_GIVE, + why_should_i_trust, + TRUST_BECAUSE, + what_about_interference, + INTERFERENCE_NECESSARY, + i_just_like_to_leave, + SORRY_NO_LEAVE, + what_about_war, + ABOUT_WAR, + what_about_urquan, + ABOUT_URQUAN, + best_if_i_killed_you, + WICKED_HUMAN, + what_did_on_earth, + DID_THIS, + why_did_this, + IDF_PARASITES, + tell_more, + NOT_NOW, + umgah_acting_weird, + learned_about_umgah, + WELL_GO_CHECK, + NO_NEWS_YET, + UMGAH_UNDER_COMPULSION, + what_do_now, + GO_FIND_OUT, + tell_arilou_about_tpet, + BAD_NEWS_ABOUT_TPET, + what_do_about_tpet, + DANGEROUS_BUT_USEFUL, + what_give_me, + ABOUT_PORTAL, + what_about_tpet, + ABOUT_TPET, + about_portal_again, + PORTAL_AGAIN, + got_it, + CLEVER_HUMAN, + GIVE_PORTAL, + bye_friendly_homeworld, + GOODBYE_FRDLY_HOMEWORLD, + HOSTILE_GOODBYE_1, + HOSTILE_GOODBYE_2, + HOSTILE_GOODBYE_3, + HOSTILE_GOODBYE_4, + ANGRY_SPACE_HELLO_1, + ANGRY_SPACE_HELLO_2, + lets_fight, + NO_FIGHT, + im_sorry, + APOLOGIZE_AT_HOMEWORLD, + bye_angry_space, + GOODBYE_ANGRY_SPACE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/blackur/blackur.res b/sc2/src/sc2code/comm/blackur/blackur.res new file mode 100644 index 000000000..7834a7f46 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/blackur.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/blackur + +PACKAGE BLACKURQ_PACKAGE blackur.con + GFXRES BLACKURQ_PMAP_ANIM blackur.ani + FONTRES BLACKURQ_FONT blackur.fon + MUSICRES BLACKURQ_MUSIC blackur.mod + STRTAB BLACKURQ_CONVERSATION_PHRASES blackur.txt + diff --git a/sc2/src/sc2code/comm/blackur/blackurc.c b/sc2/src/sc2code/comm/blackur/blackurc.c new file mode 100644 index 000000000..cb756f76a --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/blackurc.c @@ -0,0 +1,547 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/blackur/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/blackur/strings.h" + +static LOCDATA blackurq_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)BLACKURQ_PMAP_ANIM, /* AlienFrame */ + (FONT)BLACKURQ_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + BLACKURQ_MUSIC, /* AlienSong */ + BLACKURQ_CONVERSATION_PHRASES, /* PlayerPhrases */ + 8, /* NumAnimations */ + { + { + 7, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 13, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 20, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 23, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 26, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 29, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, 0, /* RestartRate */ + }, + { + 33, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 38, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 1, /* StartIndex */ + 2, /* NumFrames */ + 0, /* AnimFlags */ + 20, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 2, /* StartIndex */ + 5, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + BYTE NumVisits; + + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye)) + { + if (GET_GAME_STATE (KOHR_AH_BYES) == 0) + NPCPhrase (GOODBYE_AND_DIE); + else + NPCPhrase (DIE_HUMAN /* GOODBYE_AND_DIE_2 */); + + SET_GAME_STATE (KOHR_AH_BYES, 1); + } + else if (PLAYER_SAID (R, guess_thats_all)) + NPCPhrase (THEN_DIE); + else if (PLAYER_SAID (R, what_are_you_hovering_over)) + { + NPCPhrase (BONE_PILE); + + SET_GAME_STATE (KOHR_AH_INFO, 1); + } + else if (PLAYER_SAID (R, you_sure_are_creepy)) + { + NPCPhrase (YES_CREEPY); + + SET_GAME_STATE (KOHR_AH_INFO, 2); + } + else if (PLAYER_SAID (R, stop_that_gross_blinking)) + { + NPCPhrase (DIE_HUMAN); + + SET_GAME_STATE (KOHR_AH_INFO, 3); + } + else if (PLAYER_SAID (R, threat_1) + || PLAYER_SAID (R, threat_2) + || PLAYER_SAID (R, threat_3) + || PLAYER_SAID (R, threat_4)) + { + NumVisits = GET_GAME_STATE (KOHR_AH_REASONS); + switch (NumVisits++) + { + case 0: + NPCPhrase (RESISTANCE_IS_USELESS_1); + break; + case 1: + NPCPhrase (RESISTANCE_IS_USELESS_2); + break; + case 2: + NPCPhrase (RESISTANCE_IS_USELESS_3); + break; + case 3: + NPCPhrase (RESISTANCE_IS_USELESS_4); + --NumVisits; + break; + } + SET_GAME_STATE (KOHR_AH_REASONS, NumVisits); + } + else if (PLAYER_SAID (R, plead_1) + || PLAYER_SAID (R, plead_2) + || PLAYER_SAID (R, plead_3) + || PLAYER_SAID (R, plead_4)) + { + NumVisits = GET_GAME_STATE (KOHR_AH_PLEAD); + switch (NumVisits++) + { + case 0: + NPCPhrase (PLEADING_IS_USELESS_1); + break; + case 1: + NPCPhrase (PLEADING_IS_USELESS_2); + break; + case 2: + NPCPhrase (PLEADING_IS_USELESS_3); + break; + case 3: + NPCPhrase (PLEADING_IS_USELESS_4); + --NumVisits; + break; + } + SET_GAME_STATE (KOHR_AH_PLEAD, NumVisits); + } + else if (PLAYER_SAID (R, why_kill_all_1) + || PLAYER_SAID (R, why_kill_all_2) + || PLAYER_SAID (R, why_kill_all_3) + || PLAYER_SAID (R, why_kill_all_4)) + { + NumVisits = GET_GAME_STATE (KOHR_AH_REASONS); + switch (NumVisits++) + { + case 0: + NPCPhrase (KILL_BECAUSE_1); + break; + case 1: + NPCPhrase (KILL_BECAUSE_2); + break; + case 2: + NPCPhrase (KILL_BECAUSE_3); + break; + case 3: + NPCPhrase (KILL_BECAUSE_4); + --NumVisits; + break; + } + SET_GAME_STATE (KOHR_AH_REASONS, NumVisits); + } + else if (PLAYER_SAID (R, please_dont_kill_1) + || PLAYER_SAID (R, please_dont_kill_2) + || PLAYER_SAID (R, please_dont_kill_3) + || PLAYER_SAID (R, please_dont_kill_4)) + { + NumVisits = GET_GAME_STATE (KOHR_AH_PLEAD); + switch (NumVisits++) + { + case 0: + NPCPhrase (WILL_KILL_1); + break; + case 1: + NPCPhrase (WILL_KILL_2); + break; + case 2: + NPCPhrase (WILL_KILL_3); + break; + case 3: + NPCPhrase (WILL_KILL_4); + --NumVisits; + break; + } + SET_GAME_STATE (KOHR_AH_PLEAD, NumVisits); + } + else if (PLAYER_SAID (R, bye_frenzy_1) + || PLAYER_SAID (R, bye_frenzy_2) + || PLAYER_SAID (R, bye_frenzy_3) + || PLAYER_SAID (R, bye_frenzy_4)) + { + NumVisits = GET_GAME_STATE (KOHR_AH_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GOODBYE_AND_DIE_FRENZY_1); + break; + case 1: + NPCPhrase (GOODBYE_AND_DIE_FRENZY_2); + break; + case 2: + NPCPhrase (GOODBYE_AND_DIE_FRENZY_3); + break; + case 3: + NPCPhrase (GOODBYE_AND_DIE_FRENZY_4); + --NumVisits; + break; + } + SET_GAME_STATE (KOHR_AH_INFO, NumVisits); + } +} + +static void +Frenzy (RESPONSE_REF R) +{ + switch (GET_GAME_STATE (KOHR_AH_REASONS)) + { + case 0: + Response (why_kill_all_1, CombatIsInevitable); + break; + case 1: + Response (why_kill_all_2, CombatIsInevitable); + break; + case 2: + Response (why_kill_all_3, CombatIsInevitable); + break; + case 3: + Response (why_kill_all_4, CombatIsInevitable); + break; + } + switch (GET_GAME_STATE (KOHR_AH_PLEAD)) + { + case 0: + Response (please_dont_kill_1, CombatIsInevitable); + break; + case 1: + Response (please_dont_kill_2, CombatIsInevitable); + break; + case 2: + Response (please_dont_kill_3, CombatIsInevitable); + break; + case 3: + Response (please_dont_kill_4, CombatIsInevitable); + break; + } + switch (GET_GAME_STATE (KOHR_AH_INFO)) + { + case 0: + Response (bye_frenzy_1, CombatIsInevitable); + break; + case 1: + Response (bye_frenzy_2, CombatIsInevitable); + break; + case 2: + Response (bye_frenzy_3, CombatIsInevitable); + break; + case 3: + Response (bye_frenzy_4, CombatIsInevitable); + break; + } +} + +static void +KohrAhStory (RESPONSE_REF R) +{ + //PTR_DESC PtrDesc; + + if (PLAYER_SAID (R, key_phrase)) + { + NPCPhrase (RESPONSE_TO_KEY_PHRASE); + + SET_GAME_STATE (KNOW_KOHR_AH_STORY, 2); + } + else if (PLAYER_SAID (R, why_do_you_destroy)) + { + NPCPhrase (WE_WERE_SLAVES); + + DISABLE_PHRASE (why_do_you_destroy); + } + else if (PLAYER_SAID (R, relationship_with_urquan)) + { + NPCPhrase (WE_ARE_URQUAN_TOO); + + DISABLE_PHRASE (relationship_with_urquan); + } + else if (PLAYER_SAID (R, what_about_culture)) + { + NPCPhrase (BONE_GARDENS); + + DISABLE_PHRASE (what_about_culture); + } + else if (PLAYER_SAID (R, how_leave_me_alone)) + { + NPCPhrase (YOU_DIE); + + DISABLE_PHRASE (how_leave_me_alone); + } + + if (PHRASE_ENABLED (why_do_you_destroy)) + Response (why_do_you_destroy, KohrAhStory); + if (PHRASE_ENABLED (relationship_with_urquan)) + Response (relationship_with_urquan, KohrAhStory); + if (PHRASE_ENABLED (what_about_culture)) + Response (what_about_culture, KohrAhStory); + if (PHRASE_ENABLED (how_leave_me_alone)) + Response (how_leave_me_alone, KohrAhStory); + Response (guess_thats_all, CombatIsInevitable); +} + +static void +DieHuman (RESPONSE_REF R) +{ + switch (GET_GAME_STATE (KOHR_AH_REASONS)) + { + case 0: + Response (threat_1, CombatIsInevitable); + break; + case 1: + Response (threat_2, CombatIsInevitable); + break; + case 2: + Response (threat_3, CombatIsInevitable); + break; + case 3: + Response (threat_4, CombatIsInevitable); + break; + } + if (GET_GAME_STATE (KNOW_KOHR_AH_STORY) == 1) + { + Response (key_phrase, KohrAhStory); + } + switch (GET_GAME_STATE (KOHR_AH_INFO)) + { + case 0: + Response (what_are_you_hovering_over, CombatIsInevitable); + break; + case 1: + Response (you_sure_are_creepy, CombatIsInevitable); + break; + case 2: + Response (stop_that_gross_blinking, CombatIsInevitable); + break; + } + switch (GET_GAME_STATE (KOHR_AH_PLEAD)) + { + case 0: + Response (plead_1, CombatIsInevitable); + break; + case 1: + Response (plead_2, CombatIsInevitable); + break; + case 2: + Response (plead_3, CombatIsInevitable); + break; + case 3: + Response (plead_4, CombatIsInevitable); + break; + } + Response (bye, CombatIsInevitable); +} + +static void +Intro (void) +{ + BYTE b0, b1, b2, b3; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (KOHR_AH_KILLED_ALL)) + { + NPCPhrase (GAME_OVER_DUDE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (!GET_GAME_STATE (KOHR_AH_SENSES_EVIL) + && GET_GAME_STATE (TALKING_PET_ON_SHIP)) + { + NPCPhrase (SENSE_EVIL); + SET_GAME_STATE (KOHR_AH_SENSES_EVIL, 1); + } + + b0 = GET_GAME_STATE (SAMATRA_GRPOFFS0); + b1 = GET_GAME_STATE (SAMATRA_GRPOFFS1); + b2 = GET_GAME_STATE (SAMATRA_GRPOFFS2); + b3 = GET_GAME_STATE (SAMATRA_GRPOFFS3); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && GLOBAL (BattleGroupRef) + && GLOBAL (BattleGroupRef) == MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + )) + { + NPCPhrase (HELLO_SAMATRA); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (KOHR_AH_VISITS); + if (GET_GAME_STATE (KOHR_AH_FRENZY)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (WE_KILL_ALL_1); + break; + case 1: + NPCPhrase (WE_KILL_ALL_2); + break; + case 2: + NPCPhrase (WE_KILL_ALL_3); + break; + case 3: + NPCPhrase (WE_KILL_ALL_4); + --NumVisits; + break; + } + + Frenzy ((RESPONSE_REF)0); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AND_DIE_1); + break; + case 1: + NPCPhrase (HELLO_AND_DIE_2); + break; + case 2: + NPCPhrase (HELLO_AND_DIE_3); + break; + case 3: + NPCPhrase (HELLO_AND_DIE_4); + --NumVisits; + break; + } + + DieHuman ((RESPONSE_REF)0); + } + SET_GAME_STATE (KOHR_AH_VISITS, NumVisits); + } +ExitIntro: + ; +} + +static COUNT +uninit_blackurq (void) +{ + return (0); +} + +LOCDATAPTR +init_blackurq_comm (void) +{ + LOCDATAPTR retval; + + blackurq_desc.init_encounter_func = Intro; + blackurq_desc.uninit_encounter_func = uninit_blackurq; + + blackurq_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + blackurq_desc.AlienTextTemplate.baseline.y = 0; + blackurq_desc.AlienTextTemplate.align = ALIGN_CENTER; + blackurq_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (!GET_GAME_STATE (KOHR_AH_KILLED_ALL) + && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + retval = &blackurq_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/blackur/ifontres.h b/sc2/src/sc2code/comm/blackur/ifontres.h new file mode 100644 index 000000000..19d2d5b52 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/ifontres.h @@ -0,0 +1,3 @@ +#define BLACKURQ_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/blackur/igfxres.h b/sc2/src/sc2code/comm/blackur/igfxres.h new file mode 100644 index 000000000..94ae096c5 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/igfxres.h @@ -0,0 +1,3 @@ +#define BLACKURQ_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/blackur/imusicre.h b/sc2/src/sc2code/comm/blackur/imusicre.h new file mode 100644 index 000000000..ae4af88d5 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/imusicre.h @@ -0,0 +1,3 @@ +#define BLACKURQ_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/blackur/istrtab.h b/sc2/src/sc2code/comm/blackur/istrtab.h new file mode 100644 index 000000000..69de384bb --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/istrtab.h @@ -0,0 +1,3 @@ +#define BLACKURQ_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/blackur/resinst.h b/sc2/src/sc2code/comm/blackur/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/blackur/respkg.h b/sc2/src/sc2code/comm/blackur/respkg.h new file mode 100644 index 000000000..4a32eb808 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/respkg.h @@ -0,0 +1,5 @@ +enum +{ + BLACKURQ_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/blackur/restypes.h b/sc2/src/sc2code/comm/blackur/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/blackur/strings.h b/sc2/src/sc2code/comm/blackur/strings.h new file mode 100644 index 000000000..8173a4003 --- /dev/null +++ b/sc2/src/sc2code/comm/blackur/strings.h @@ -0,0 +1,102 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + SENSE_EVIL, + HELLO_AND_DIE_1, + HELLO_AND_DIE_2, + HELLO_AND_DIE_3, + HELLO_AND_DIE_4, + HELLO_AND_DIE_5, + HELLO_AND_DIE_6, + HELLO_AND_DIE_7, + HELLO_AND_DIE_8, + HELLO_SAMATRA, + WE_KILL_ALL_1, + WE_KILL_ALL_2, + WE_KILL_ALL_3, + WE_KILL_ALL_4, + why_kill_all_1, + why_kill_all_2, + why_kill_all_3, + why_kill_all_4, + KILL_BECAUSE_1, + KILL_BECAUSE_2, + KILL_BECAUSE_3, + KILL_BECAUSE_4, + please_dont_kill_1, + WILL_KILL_1, + please_dont_kill_2, + WILL_KILL_2, + please_dont_kill_3, + WILL_KILL_3, + please_dont_kill_4, + WILL_KILL_4, + bye_frenzy_1, + bye_frenzy_2, + bye_frenzy_3, + bye_frenzy_4, + GOODBYE_AND_DIE_FRENZY_1, + GOODBYE_AND_DIE_FRENZY_2, + GOODBYE_AND_DIE_FRENZY_3, + GOODBYE_AND_DIE_FRENZY_4, + threat_1, + RESISTANCE_IS_USELESS_1, + threat_2, + RESISTANCE_IS_USELESS_2, + threat_3, + RESISTANCE_IS_USELESS_3, + threat_4, + RESISTANCE_IS_USELESS_4, + key_phrase, + RESPONSE_TO_KEY_PHRASE, + why_do_you_destroy, + WE_WERE_SLAVES, + relationship_with_urquan, + WE_ARE_URQUAN_TOO, + what_about_culture, + BONE_GARDENS, + how_leave_me_alone, + YOU_DIE, + guess_thats_all, + THEN_DIE, + what_are_you_hovering_over, + BONE_PILE, + you_sure_are_creepy, + YES_CREEPY, + stop_that_gross_blinking, + DIE_HUMAN, + plead_1, + PLEADING_IS_USELESS_1, + plead_2, + PLEADING_IS_USELESS_2, + plead_3, + PLEADING_IS_USELESS_3, + plead_4, + PLEADING_IS_USELESS_4, + bye, + GOODBYE_AND_DIE, + GAME_OVER_DUDE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/chmmr/chmmr.res b/sc2/src/sc2code/comm/chmmr/chmmr.res new file mode 100644 index 000000000..6da01e827 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/chmmr.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/chmmr + +PACKAGE CHMMR_PACKAGE chmmr.con + GFXRES CHMMR_PMAP_ANIM chmmr.ani + FONTRES CHMMR_FONT chmmr.fon + MUSICRES CHMMR_MUSIC chmmr.mod + STRTAB CHMMR_CONVERSATION_PHRASES chmmr.txt + STRTAB CHMMR_COLOR_MAP chmmr.ct diff --git a/sc2/src/sc2code/comm/chmmr/chmmrc.c b/sc2/src/sc2code/comm/chmmr/chmmrc.c new file mode 100644 index 000000000..b070d3927 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/chmmrc.c @@ -0,0 +1,558 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/chmmr/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/chmmr/strings.h" + +static LOCDATA chmmr_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)CHMMR_PMAP_ANIM, /* AlienFrame */ + (FONT)CHMMR_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + (COLORMAP)CHMMR_COLOR_MAP, /* AlienColorMap */ + CHMMR_MUSIC, /* AlienSong */ + CHMMR_CONVERSATION_PHRASES, /* PlayerPhrases */ + 6, /* NumAnimations */ + { + { + 12, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 17, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 27, /* StartIndex */ + 20, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 47, /* StartIndex */ + 14, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 61, /* StartIndex */ + 24, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 11, /* NumFrames */ + 0, /* AnimFlags */ + 1, 0, /* FrameRate */ + 1, 0, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye)) + NPCPhrase (GOODBYE); + else if (PLAYER_SAID (R, bye_shielded)) + NPCPhrase (GOODBYE_SHIELDED); + else if (PLAYER_SAID (R, bye_after_bomb)) + NPCPhrase (GOODBYE_AFTER_BOMB); + else if (PLAYER_SAID (R, proceed)) + { + BYTE i; + + NPCPhrase (TAKE_2_WEEKS); + + ActivateStarShip (CHMMR_SHIP, 0); + + SET_GAME_STATE (CHMMR_HOME_VISITS, 0); + SET_GAME_STATE (CHMMR_STACK, 0); + SET_GAME_STATE (CHMMR_BOMB_STATE, 2); + SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); + GLOBAL_SIS (ResUnits) = 1000000L; + GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; + GLOBAL_SIS (CrewEnlisted) = 0; + GLOBAL_SIS (NumLanders) = 0; + GLOBAL (ModuleCost[PLANET_LANDER]) = 0; + GLOBAL (ModuleCost[STORAGE_BAY]) = 0; + GLOBAL_SIS (TotalElementMass) = 0; + for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) + GLOBAL_SIS (ElementAmounts[i]) = 0; + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + GLOBAL_SIS (DriveSlots[i]) = FUSION_THRUSTER; + for (i = 0; i < NUM_JET_SLOTS; ++i) + GLOBAL_SIS (JetSlots[i]) = TURNING_JETS; + for (i = NUM_BOMB_MODULES; i < NUM_MODULE_SLOTS; ++i) + GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; + GLOBAL_SIS (ModuleSlots[0]) = BOMB_MODULE_4; + GLOBAL_SIS (ModuleSlots[1]) = BOMB_MODULE_5; + GLOBAL_SIS (ModuleSlots[2]) = BOMB_MODULE_3; + GLOBAL_SIS (ModuleSlots[3]) = BOMB_MODULE_1; + GLOBAL_SIS (ModuleSlots[4]) = BOMB_MODULE_0; + GLOBAL_SIS (ModuleSlots[5]) = BOMB_MODULE_1; + GLOBAL_SIS (ModuleSlots[6]) = BOMB_MODULE_3; + GLOBAL_SIS (ModuleSlots[7]) = BOMB_MODULE_4; + GLOBAL_SIS (ModuleSlots[8]) = BOMB_MODULE_5; + GLOBAL_SIS (ModuleSlots[9]) = BOMB_MODULE_2; + +#define EARTH_INDEX 2 /* earth is 3rd planet --> 3 - 1 = 2 */ + GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); + GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); + GLOBAL (ShipStamp.frame) = + (FRAME)MAKE_DWORD (1, EARTH_INDEX + 1); + /* Magic numbers for Earth */ + GLOBAL (ip_location.x) = -725; + GLOBAL (ip_location.y) = 597; + GLOBAL (ShipStamp.origin.x) = 71; + GLOBAL (ShipStamp.origin.y) = 97; + } +} + +static void +NotReady (RESPONSE_REF R) +{ + if (R == 0) + NPCPhrase (RETURN_WHEN_READY); + else if (PLAYER_SAID (R, further_assistance)) + { + NPCPhrase (NO_FURTHER_ASSISTANCE); + + DISABLE_PHRASE (further_assistance); + } + else if (PLAYER_SAID (R, tech_help)) + { + NPCPhrase (USE_OUR_SHIPS_BEFORE); + + ActivateStarShip (CHMMR_SHIP, 0); + } + else if (PLAYER_SAID (R, where_weapon)) + { + NPCPhrase (PRECURSOR_WEAPON); + + DISABLE_PHRASE (where_weapon); + } + else if (PLAYER_SAID (R, where_distraction)) + { + NPCPhrase (PSYCHIC_WEAPONRY); + + DISABLE_PHRASE (where_distraction); + } + + if (!(ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) + Response (tech_help, NotReady); + else if (PHRASE_ENABLED (further_assistance)) + Response (further_assistance, NotReady); + if (PHRASE_ENABLED (where_weapon) && !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + Response (where_weapon, NotReady); + if (PHRASE_ENABLED (where_distraction) && !GET_GAME_STATE (TALKING_PET_ON_SHIP)) + Response (where_distraction, NotReady); + Response (bye, ExitConversation); +} + +static void +ImproveBomb (RESPONSE_REF R) +{ + if (R == 0) + NPCPhrase (WE_WILL_IMPROVE_BOMB); + else if (PLAYER_SAID (R, what_now)) + { + NPCPhrase (MODIFY_VESSEL); + + DISABLE_PHRASE (what_now); + } + else if (PLAYER_SAID (R, wont_hurt_my_ship)) + { + NPCPhrase (WILL_DESTROY_IT); + + DISABLE_PHRASE (wont_hurt_my_ship); + } + else if (PLAYER_SAID (R, bummer_about_my_ship)) + { + NPCPhrase (DEAD_SILENCE); + + DISABLE_PHRASE (bummer_about_my_ship); + } + else if (PLAYER_SAID (R, other_assistance)) + { + NPCPhrase (USE_OUR_SHIPS_AFTER); + + ActivateStarShip (CHMMR_SHIP, 0); + } + + if (PHRASE_ENABLED (what_now)) + Response (what_now, ImproveBomb); + else if (PHRASE_ENABLED (wont_hurt_my_ship)) + Response (wont_hurt_my_ship, ImproveBomb); + else if (PHRASE_ENABLED (bummer_about_my_ship)) + Response (bummer_about_my_ship, ImproveBomb); + if (!(ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) + Response (other_assistance, ImproveBomb); + Response (proceed, ExitConversation); +} + +static void +ChmmrFree (RESPONSE_REF R) +{ + if (R == 0 + || PLAYER_SAID (R, i_am_captain0) + || PLAYER_SAID (R, i_am_savior) + || PLAYER_SAID (R, i_am_silly)) + { + NPCPhrase (WHY_HAVE_YOU_FREED_US); + AlienTalkSegue ((COUNT)~0); + SET_GAME_STATE (CHMMR_EMERGING, 0); + + Response (serious_1, ChmmrFree); + Response (serious_2, ChmmrFree); + Response (silly, ChmmrFree); + } + else + { + NPCPhrase (WILL_HELP_ANALYZE_LOGS); + + if (GET_GAME_STATE (AWARE_OF_SAMATRA)) + NPCPhrase (YOU_KNOW_SAMATRA); + else + { + NPCPhrase (DONT_KNOW_ABOUT_SAMATRA); + + SET_GAME_STATE (AWARE_OF_SAMATRA, 1); + } + + if (GET_GAME_STATE (TALKING_PET_ON_SHIP)) + NPCPhrase (HAVE_TALKING_PET); + else + NPCPhrase (NEED_DISTRACTION); + + if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + NPCPhrase (HAVE_BOMB); + else + NPCPhrase (NEED_WEAPON); + + if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) + || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + NotReady ((RESPONSE_REF)0); + else + ImproveBomb ((RESPONSE_REF)0); + } +} + +static void ChmmrShielded (RESPONSE_REF R); + +static void +ChmmrAdvice (RESPONSE_REF R) +{ + BYTE AdviceLeft; + + if (PLAYER_SAID (R, need_advice)) + NPCPhrase (WHAT_ADVICE); + else if (PLAYER_SAID (R, how_defeat_urquan)) + { + NPCPhrase (DEFEAT_LIKE_SO); + + SET_GAME_STATE (CHMMR_BOMB_STATE, 1); + DISABLE_PHRASE (how_defeat_urquan); + } + else if (PLAYER_SAID (R, what_about_tpet)) + { + NPCPhrase (SCARY_BUT_USEFUL); + + DISABLE_PHRASE (what_about_tpet); + } + else if (PLAYER_SAID (R, what_about_bomb)) + { + NPCPhrase (ABOUT_BOMB); + + DISABLE_PHRASE (what_about_bomb); + } + else if (PLAYER_SAID (R, what_about_sun_device)) + { + NPCPhrase (ABOUT_SUN_DEVICE); + + DISABLE_PHRASE (what_about_sun_device); + } + else if (PLAYER_SAID (R, what_about_samatra)) + { + NPCPhrase (ABOUT_SUN_DEVICE); + + DISABLE_PHRASE (what_about_samatra); + } + + AdviceLeft = 0; + if (PHRASE_ENABLED (how_defeat_urquan)) + { + Response (how_defeat_urquan, ChmmrAdvice); + AdviceLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_tpet) && GET_GAME_STATE (TALKING_PET_ON_SHIP)) + { + Response (what_about_tpet, ChmmrAdvice); + AdviceLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_bomb) && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + { + Response (what_about_bomb, ChmmrAdvice); + AdviceLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_sun_device) && GET_GAME_STATE (SUN_DEVICE_ON_SHIP)) + { + Response (what_about_sun_device, ChmmrAdvice); + AdviceLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_samatra) && GET_GAME_STATE (AWARE_OF_SAMATRA)) + { + Response (what_about_samatra, ChmmrAdvice); + AdviceLeft = TRUE; + } + Response (enough_advice, ChmmrShielded); + + if (!AdviceLeft) + DISABLE_PHRASE (need_advice); +} + +static void +ChmmrShielded (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, find_out_whats_up)) + { + NPCPhrase (HYBRID_PROCESS); + + DISABLE_PHRASE (find_out_whats_up); + } + else if (PLAYER_SAID (R, need_help)) + { + NPCPhrase (CANT_HELP); + + SET_GAME_STATE (CHMMR_STACK, 1); + } + else if (PLAYER_SAID (R, why_no_help)) + { + NPCPhrase (LONG_TIME); + + SET_GAME_STATE (CHMMR_STACK, 2); + } + else if (PLAYER_SAID (R, what_if_more_energy)) + { + NPCPhrase (DANGER_TO_US); + + SET_GAME_STATE (CHMMR_STACK, 3); + } + else if (PLAYER_SAID (R, enough_advice)) + NPCPhrase (OK_ENOUGH_ADVICE); + + switch (GET_GAME_STATE (CHMMR_STACK)) + { + case 0: + Response (need_help, ChmmrShielded); + break; + case 1: + Response (why_no_help, ChmmrShielded); + break; + case 2: + Response (what_if_more_energy, ChmmrShielded); + break; + } + if (PHRASE_ENABLED (find_out_whats_up)) + Response (find_out_whats_up, ChmmrShielded); + if (PHRASE_ENABLED (need_advice)) + { + Response (need_advice, ChmmrAdvice); + } + Response (bye_shielded, ExitConversation); +} + +static void +AfterBomb (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_up_after_bomb)) + { + if (GET_GAME_STATE (CHMMR_STACK)) + NPCPhrase (GENERAL_INFO_AFTER_BOMB_2); + else + { + NPCPhrase (GENERAL_INFO_AFTER_BOMB_1); + + SET_GAME_STATE (CHMMR_STACK, 1); + } + + DISABLE_PHRASE (whats_up_after_bomb); + } + else if (PLAYER_SAID (R, what_do_after_bomb)) + { + NPCPhrase (DO_AFTER_BOMB); + + DISABLE_PHRASE (what_do_after_bomb); + } + + if (PHRASE_ENABLED (whats_up_after_bomb)) + Response (whats_up_after_bomb, AfterBomb); + if (PHRASE_ENABLED (what_do_after_bomb)) + Response (what_do_after_bomb, AfterBomb); + Response (bye_after_bomb, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) + { + NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AFTER_BOMB_1); + break; + case 1: + NPCPhrase (HELLO_AFTER_BOMB_2); + break; + } + SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); + + AfterBomb ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (CHMMR_UNLEASHED)) + { + if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) + || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + NotReady ((RESPONSE_REF)0); + else + { + NPCPhrase (YOU_ARE_READY); + + ImproveBomb ((RESPONSE_REF)0); + } + } + else + { + NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); + if (!GET_GAME_STATE (CHMMR_EMERGING)) + { + CommData.AlienColorMap = SetAbsColorMapIndex ( + CommData.AlienColorMap, 1 + ); + switch (NumVisits++) + { + case 0: + NPCPhrase (WHY_YOU_HERE_1); + break; + case 1: + NPCPhrase (WHY_YOU_HERE_2); + break; + case 2: + NPCPhrase (WHY_YOU_HERE_3); + break; + case 3: + NPCPhrase (WHY_YOU_HERE_4); + --NumVisits; + break; + } + + ChmmrShielded ((RESPONSE_REF)0); + } + else + { + NPCPhrase (WE_ARE_FREE); + + if (NumVisits) + { + ChmmrFree ((RESPONSE_REF)0); + NumVisits = 0; + } + else + { + NPCPhrase (WHO_ARE_YOU); + + construct_response (shared_phrase_buf, + i_am_captain0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + i_am_captain1, + GLOBAL_SIS (ShipName), + i_am_captain2, + 0); + DoResponsePhrase (i_am_captain0, ChmmrFree, shared_phrase_buf); + Response (i_am_savior, ChmmrFree); + Response (i_am_silly, ChmmrFree); + } + + SET_GAME_STATE (CHMMR_UNLEASHED, 1); + } + SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); + } +} + +static COUNT +uninit_chmmr (void) +{ + return (0); +} + +LOCDATAPTR +init_chmmr_comm (void) +{ + LOCDATAPTR retval; + + chmmr_desc.init_encounter_func = Intro; + chmmr_desc.uninit_encounter_func = uninit_chmmr; + + chmmr_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + chmmr_desc.AlienTextTemplate.baseline.y = 0; + chmmr_desc.AlienTextTemplate.align = ALIGN_CENTER; + chmmr_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &chmmr_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/chmmr/ifontres.h b/sc2/src/sc2code/comm/chmmr/ifontres.h new file mode 100644 index 000000000..db6ecfd8c --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/ifontres.h @@ -0,0 +1,3 @@ +#define CHMMR_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/chmmr/igfxres.h b/sc2/src/sc2code/comm/chmmr/igfxres.h new file mode 100644 index 000000000..5b0eb8760 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/igfxres.h @@ -0,0 +1,3 @@ +#define CHMMR_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/chmmr/imusicre.h b/sc2/src/sc2code/comm/chmmr/imusicre.h new file mode 100644 index 000000000..f4616a7b2 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/imusicre.h @@ -0,0 +1,3 @@ +#define CHMMR_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/chmmr/istrtab.h b/sc2/src/sc2code/comm/chmmr/istrtab.h new file mode 100644 index 000000000..a2b1f9080 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/istrtab.h @@ -0,0 +1,4 @@ +#define CHMMR_CONVERSATION_PHRASES 0x00200004L +#define CHMMR_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/chmmr/resinst.h b/sc2/src/sc2code/comm/chmmr/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/chmmr/respkg.h b/sc2/src/sc2code/comm/chmmr/respkg.h new file mode 100644 index 000000000..07016c957 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/respkg.h @@ -0,0 +1,5 @@ +enum +{ + CHMMR_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/chmmr/restypes.h b/sc2/src/sc2code/comm/chmmr/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/chmmr/strings.h b/sc2/src/sc2code/comm/chmmr/strings.h new file mode 100644 index 000000000..6fe3ae9a8 --- /dev/null +++ b/sc2/src/sc2code/comm/chmmr/strings.h @@ -0,0 +1,105 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + WHY_YOU_HERE_1, + WHY_YOU_HERE_2, + WHY_YOU_HERE_3, + WHY_YOU_HERE_4, + find_out_whats_up, + HYBRID_PROCESS, + need_help, + CANT_HELP, + why_no_help, + LONG_TIME, + what_if_more_energy, + DANGER_TO_US, + need_advice, + WHAT_ADVICE, + how_defeat_urquan, + DEFEAT_LIKE_SO, + what_about_tpet, + SCARY_BUT_USEFUL, + what_about_bomb, + ABOUT_BOMB, + what_about_sun_device, + ABOUT_SUN_DEVICE, + what_about_samatra, + ABOUT_SAMATRA, + enough_advice, + OK_ENOUGH_ADVICE, + bye_shielded, + GOODBYE_SHIELDED, + WE_ARE_FREE, + WHO_ARE_YOU, + i_am_captain0, + i_am_captain1, + i_am_captain2, + i_am_savior, + i_am_silly, + WHY_HAVE_YOU_FREED_US, + serious_1, + serious_2, + silly, + WILL_HELP_ANALYZE_LOGS, + YOU_KNOW_SAMATRA, + DONT_KNOW_ABOUT_SAMATRA, + NEED_DISTRACTION, + HAVE_TALKING_PET, + NEED_WEAPON, + HAVE_BOMB, + RETURN_WHEN_READY, + YOU_ARE_READY, + further_assistance, + NO_FURTHER_ASSISTANCE, + tech_help, + USE_OUR_SHIPS_BEFORE, + where_weapon, + PRECURSOR_WEAPON, + where_distraction, + PSYCHIC_WEAPONRY, + what_now, + WE_WILL_IMPROVE_BOMB, + MODIFY_VESSEL, + wont_hurt_my_ship, + WILL_DESTROY_IT, + bummer_about_my_ship, + DEAD_SILENCE, + other_assistance, + USE_OUR_SHIPS_AFTER, + proceed, + TAKE_2_WEEKS, + HELLO_AFTER_BOMB_1, + HELLO_AFTER_BOMB_2, + whats_up_after_bomb, + GENERAL_INFO_AFTER_BOMB_1, + GENERAL_INFO_AFTER_BOMB_2, + what_do_after_bomb, + DO_AFTER_BOMB, + bye_after_bomb, + GOODBYE_AFTER_BOMB, + bye, + GOODBYE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/comandr/comandr.c b/sc2/src/sc2code/comm/comandr/comandr.c new file mode 100644 index 000000000..28b3c1cd6 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/comandr.c @@ -0,0 +1,670 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/comandr/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/comandr/strings.h" + +static LOCDATA commander_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)COMMANDER_PMAP_ANIM, /* AlienFrame */ + (FONT)COMMANDER_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ + COMMANDER_COLOR_MAP, /* AlienColorMap */ + COMMANDER_MUSIC, /* AlienSong */ + COMMANDER_CONVERSATION_PHRASES, /* PlayerPhrases */ + 3, /* NumAnimations */ + { + { /* Blink */ + 1, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Running light */ + 10, /* StartIndex */ + 30, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + ONE_SECOND * 2, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM | COLORXFORM_ANIM,/* AnimFlags */ + 0, 4, /* FrameRate */ + 0, 8, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 4, /* StartIndex */ + 6, /* NumFrames */ + 0, /* AnimFlags */ + 12, 8, /* FrameRate */ + 14, 10, /* RestartRate */ + }, +}; + +static void +ByeBye (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, ok_i_will_get_radios)) + NPCPhrase (THANKS_FOR_HELPING); + else if (PLAYER_SAID (R, well_go_get_them_now)) + NPCPhrase (GLAD_WHEN_YOU_COME_BACK); + else if (PLAYER_SAID (R, we_will_take_care_of_base)) + { + NPCPhrase (GOOD_LUCK_WITH_BASE); + + SET_GAME_STATE (WILL_DESTROY_BASE, 1); + } + else if (PLAYER_SAID (R, take_care_of_base_again)) + NPCPhrase (GOOD_LUCK_AGAIN); + else if (PLAYER_SAID (R, base_was_abandoned) + || PLAYER_SAID (R, i_lied_it_was_abandoned)) + { + NPCPhrase (IT_WAS_ABANDONED); + NPCPhrase (HERE_COMES_ILWRATH); + + SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); + } + else if (PLAYER_SAID (R, oh_yes_big_fight)) + { + NPCPhrase (IM_GLAD_YOU_WON); + NPCPhrase (HERE_COMES_ILWRATH); + + SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); + } + else if (PLAYER_SAID (R, i_cant_talk_about_it)) + { + NPCPhrase (IM_SURE_IT_WAS_DIFFICULT); + NPCPhrase (HERE_COMES_ILWRATH); + + SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); + } + else if (PLAYER_SAID (R, cook_their_butts) + || PLAYER_SAID (R, overthrow_evil_aliens) + || PLAYER_SAID (R, annihilate_those_monsters)) + { + //PTR_DESC PtrDesc; + + SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 0); + + if (PLAYER_SAID (R, cook_their_butts)) + NPCPhrase (COOK_BUTTS); + else if (PLAYER_SAID (R, overthrow_evil_aliens)) + NPCPhrase (OVERTHROW_ALIENS); + else /* if (R == annihilate_those_monsters) */ + NPCPhrase (KILL_MONSTERS); + + construct_response (shared_phrase_buf, + name_40, + (vararg_dcl)GLOBAL_SIS (CommanderName), + name_41, + 0); + + NPCPhrase (THIS_MAY_SEEM_SILLY); + + Response (name_1, ByeBye); + Response (name_2, ByeBye); + Response (name_3, ByeBye); + DoResponsePhrase (name_40, ByeBye, shared_phrase_buf); + + SET_GAME_STATE (STARBASE_AVAILABLE, 1); + } + else + { + if (PLAYER_SAID (R, name_1)) + { + NPCPhrase (OK_THE_NAFS); + + SET_GAME_STATE (NEW_ALLIANCE_NAME, 0); + } + else if (PLAYER_SAID (R, name_2)) + { + NPCPhrase (OK_THE_CAN); + + SET_GAME_STATE (NEW_ALLIANCE_NAME, 1); + } + else if (PLAYER_SAID (R, name_3)) + { + NPCPhrase (OK_THE_UFW); + + SET_GAME_STATE (NEW_ALLIANCE_NAME, 2); + } + else /* if (PLAYER_SAID (R, name_4)) */ + { + NPCPhrase (OK_THE_NAME_IS_EMPIRE0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (OK_THE_NAME_IS_EMPIRE1); + + SET_GAME_STATE (NEW_ALLIANCE_NAME, 3); + } + + NPCPhrase (STARBASE_WILL_BE_READY); + } +} + +static void +NoRadioactives (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, yes_this_is_supply_ship)) + { + NPCPhrase (ABOUT_TIME); + + Response (i_lied, NoRadioactives); + Response (plumb_out, NoRadioactives); + } + else + { + if (PLAYER_SAID (R, where_can_i_get_radios)) + { + NPCPhrase (RADIOS_ON_MERCURY); + + DISABLE_PHRASE (where_can_i_get_radios); + } + else if (PLAYER_SAID (R, no_but_well_help0)) + NPCPhrase (THE_WHAT_FROM_WHERE); + else if (PLAYER_SAID (R, what_slave_planet) + || PLAYER_SAID (R, i_lied)) + NPCPhrase (DONT_KNOW_WHO_YOU_ARE); + else if (PLAYER_SAID (R, plumb_out)) + NPCPhrase (WHAT_KIND_OF_IDIOT); + else if (PLAYER_SAID (R, i_lost_my_lander)) + { + NPCPhrase (HERE_IS_A_NEW_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (LANDERS_LOST, 1); + } + else if (PLAYER_SAID (R, i_lost_another_lander)) + { + NPCPhrase (HERE_IS_ANOTHER_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + } + else if (PLAYER_SAID (R, need_fuel)) + { + NPCPhrase (GIVE_FUEL); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); + } + else if (PLAYER_SAID (R, need_fuel_again)) + { + NPCPhrase (GIVE_FUEL_AGAIN); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + } + + if (GLOBAL_SIS (NumLanders) == 0) + { + if (GET_GAME_STATE (LANDERS_LOST)) + Response (i_lost_another_lander, NoRadioactives); + else + Response (i_lost_my_lander, NoRadioactives); + } + if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) + { + if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) + Response (need_fuel_again, NoRadioactives); + else + Response (need_fuel, NoRadioactives); + } + Response (ok_i_will_get_radios, ByeBye); + if (PHRASE_ENABLED (where_can_i_get_radios)) + { + Response (where_can_i_get_radios, NoRadioactives); + } + } +} + +static void +AskAfterRadios (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, i_lost_my_lander)) + { + NPCPhrase (HERE_IS_A_NEW_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (LANDERS_LOST, 1); + } + else if (PLAYER_SAID (R, i_lost_another_lander)) + { + NPCPhrase (HERE_IS_ANOTHER_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + } + else if (PLAYER_SAID (R, need_fuel)) + { + NPCPhrase (GIVE_FUEL); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); + } + else if (PLAYER_SAID (R, need_fuel_again)) + { + NPCPhrase (GIVE_FUEL_AGAIN); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + } + else if (PLAYER_SAID (R, where_get_radios)) + { + NPCPhrase (RADIOS_ON_MERCURY); + + DISABLE_PHRASE (where_get_radios); + } + + { + if (GLOBAL_SIS (NumLanders) == 0) + { + if (GET_GAME_STATE (LANDERS_LOST)) + Response (i_lost_another_lander, AskAfterRadios); + else + Response (i_lost_my_lander, AskAfterRadios); + } + if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) + { + if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) + Response (need_fuel_again, AskAfterRadios); + else + Response (need_fuel, AskAfterRadios); + } + Response (well_go_get_them_now, ByeBye); + if (PHRASE_ENABLED (where_get_radios)) + { + Response (where_get_radios, AskAfterRadios); + } + } +} + +static void +BaseDestroyed (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_fought_them)) + { + NPCPhrase (YOU_REALLY_FOUGHT_BASE); + + Response (oh_yes_big_fight, ByeBye); + Response (i_lied_it_was_abandoned, ByeBye); + Response (i_cant_talk_about_it, ByeBye); + } + else + { + if (PLAYER_SAID (R, we_are_here_to_help)) + { + NPCPhrase (BASE_ON_MOON); + } + else + { + NPCPhrase (DEALT_WITH_BASE_YET); + } + + Response (base_was_abandoned, ByeBye); + Response (we_fought_them, BaseDestroyed); + } +} + +static void +TellMoonBase (RESPONSE_REF R) +{ + if (R == 0) + { + NPCPhrase (DEALT_WITH_BASE_YET); + } + else if (PLAYER_SAID (R, i_lost_my_lander)) + { + NPCPhrase (HERE_IS_A_NEW_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (LANDERS_LOST, 1); + } + else if (PLAYER_SAID (R, i_lost_another_lander)) + { + NPCPhrase (HERE_IS_ANOTHER_LANDER); + ++GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + DeltaSISGauges (4, 0, 0); + ClearSemaphore (&GraphicsSem); + } + else if (PLAYER_SAID (R, need_fuel)) + { + NPCPhrase (GIVE_FUEL); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); + } + else if (PLAYER_SAID (R, need_fuel_again)) + { + NPCPhrase (GIVE_FUEL_AGAIN); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + } + else if (PLAYER_SAID (R, we_are_here_to_help)) + { + NPCPhrase (BASE_ON_MOON); + } + else if (GET_GAME_STATE (STARBASE_YACK_STACK1) == 0) + { + NPCPhrase (ABOUT_BASE); + + SET_GAME_STATE (STARBASE_YACK_STACK1, 1); + } + else + { + NPCPhrase (ABOUT_BASE_AGAIN); + } + + if (GLOBAL_SIS (NumLanders) == 0) + { + if (GET_GAME_STATE (LANDERS_LOST)) + Response (i_lost_another_lander, TellMoonBase); + else + Response (i_lost_my_lander, TellMoonBase); + } + if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) + { + if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) + Response (need_fuel_again, TellMoonBase); + else + Response (need_fuel, TellMoonBase); + } + if (GET_GAME_STATE (WILL_DESTROY_BASE) == 0) + Response (we_will_take_care_of_base, ByeBye); + else + Response (take_care_of_base_again, ByeBye); + if (GET_GAME_STATE (STARBASE_YACK_STACK1) == 0) + Response (tell_me_about_base, TellMoonBase); + else + Response (tell_me_again, TellMoonBase); +} + +static void RevealSelf (RESPONSE_REF R); + +static void +TellProbe (RESPONSE_REF R) +{ + NPCPhrase (THAT_WAS_PROBE); + DISABLE_PHRASE (what_was_red_thing); + + Response (it_went_away, RevealSelf); + Response (we_destroyed_it, RevealSelf); + Response (what_probe, RevealSelf); +} + +static void +RevealSelf (RESPONSE_REF R) +{ + BYTE i, stack; + + stack = 0; + if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (THATS_IMPOSSIBLE); + + DISABLE_PHRASE (we_are_vindicator0); + } + else if (PLAYER_SAID (R, our_mission_was_secret)) + { + NPCPhrase (ACKNOWLEDGE_SECRET); + + DISABLE_PHRASE (our_mission_was_secret); + } + else if (PLAYER_SAID (R, first_give_info)) + { + NPCPhrase (ASK_AWAY); + + stack = 1; + DISABLE_PHRASE (first_give_info); + } + else if (PLAYER_SAID (R, whats_this_starbase)) + { + NPCPhrase (STARBASE_IS); + + stack = 1; + DISABLE_PHRASE (whats_this_starbase); + } + else if (PLAYER_SAID (R, what_about_earth)) + { + NPCPhrase (HAPPENED_TO_EARTH); + + stack = 1; + DISABLE_PHRASE (what_about_earth); + } + else if (PLAYER_SAID (R, where_are_urquan)) + { + NPCPhrase (URQUAN_LEFT); + + stack = 1; + DISABLE_PHRASE (where_are_urquan); + } + else if (PLAYER_SAID (R, it_went_away)) + NPCPhrase (DEEP_TROUBLE); + else if (PLAYER_SAID (R, we_destroyed_it)) + NPCPhrase (GOOD_NEWS); + else if (PLAYER_SAID (R, what_probe)) + NPCPhrase (SURE_HOPE); + + for (i = 0; i < 2; ++i, stack ^= 1) + { + if (stack == 1) + { + if (PHRASE_ENABLED (first_give_info)) + Response (first_give_info, RevealSelf); + else if (PHRASE_ENABLED (whats_this_starbase)) + Response (whats_this_starbase, RevealSelf); + else if (PHRASE_ENABLED (what_about_earth)) + Response (what_about_earth, RevealSelf); + else if (PHRASE_ENABLED (where_are_urquan)) + Response (where_are_urquan, RevealSelf); + else if (PHRASE_ENABLED (what_was_red_thing)) + { + Response (what_was_red_thing, TellProbe); + } + } + else + { + if (PHRASE_ENABLED (we_are_vindicator0)) + { + construct_response (shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0); + DoResponsePhrase (we_are_vindicator0, RevealSelf, shared_phrase_buf); + } + else if (PHRASE_ENABLED (our_mission_was_secret)) + Response (our_mission_was_secret, RevealSelf); + else + { + if (GET_GAME_STATE (MOONBASE_DESTROYED) == 0) + Response (we_are_here_to_help, TellMoonBase); + else + Response (we_are_here_to_help, BaseDestroyed); + } + } + } +} + +static void +GiveRadios (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_will_transfer_now)) + { + SET_GAME_STATE (RADIOACTIVES_PROVIDED, 1); + + NPCPhrase (FUEL_UP0); + NPCPhrase (FUEL_UP1); + + AlienTalkSegue (1); + SetSemaphore (&GraphicsSem); + CommData.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED; + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), 0); + ClearSemaphore (&GraphicsSem); + AlienTalkSegue ((COUNT)~0); + + RevealSelf (NULL_PTR); + } + else + { + if (PLAYER_SAID (R, what_will_you_give_us)) + NPCPhrase (MESSAGE_GARBLED_1); + else if (PLAYER_SAID (R, before_radios_we_need_info)) + NPCPhrase (MESSAGE_GARBLED_2); + + Response (we_will_transfer_now, GiveRadios); + Response (what_will_you_give_us, GiveRadios); + Response (before_radios_we_need_info, GiveRadios); + } +} + +static void +Intro (void) +{ + if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)) + { + NPCPhrase (VERY_IMPRESSIVE); + + Response (cook_their_butts, ByeBye); + Response (overthrow_evil_aliens, ByeBye); + Response (annihilate_those_monsters, ByeBye); + } + else if (GET_GAME_STATE (STARBASE_VISITED)) + { + if (GET_GAME_STATE (RADIOACTIVES_PROVIDED)) + { + if (GET_GAME_STATE (MOONBASE_DESTROYED) == 0) + { + TellMoonBase (NULL_PTR); + } + else + { + BaseDestroyed (NULL_PTR); + } + } + else + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + NPCPhrase (DO_YOU_HAVE_RADIO_THIS_TIME); + + if (GLOBAL_SIS (ElementAmounts[RADIOACTIVE])) + GiveRadios (NULL_PTR); + else + AskAfterRadios (NULL_PTR); + } + } + else /* first visit */ + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + + SET_GAME_STATE (STARBASE_VISITED, 1); + + NPCPhrase (ARE_YOU_SUPPLY_SHIP); + if (GLOBAL_SIS (ElementAmounts[RADIOACTIVE])) + GiveRadios (NULL_PTR); + else + { + construct_response ( + shared_phrase_buf, + no_but_well_help0, + (vararg_dcl)GLOBAL_SIS (ShipName), + no_but_well_help1, + 0 + ); + DoResponsePhrase (no_but_well_help0, NoRadioactives, shared_phrase_buf); + Response (yes_this_is_supply_ship, NoRadioactives); + Response (what_slave_planet, NoRadioactives); + } + } +} + +static COUNT +uninit_commander (void) +{ + return (0); +} + +LOCDATAPTR +init_commander_comm () +{ + LOCDATAPTR retval; + + commander_desc.init_encounter_func = Intro; + commander_desc.uninit_encounter_func = uninit_commander; + + if (GET_GAME_STATE (RADIOACTIVES_PROVIDED)) + commander_desc.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED; + + commander_desc.AlienTextWidth = 143; + commander_desc.AlienTextTemplate.baseline.x = 164; + commander_desc.AlienTextTemplate.baseline.y = 20; + commander_desc.AlienTextTemplate.align = ALIGN_CENTER; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &commander_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/comandr/comandr.res b/sc2/src/sc2code/comm/comandr/comandr.res new file mode 100644 index 000000000..f5634dcb1 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/comandr.res @@ -0,0 +1,15 @@ +INCLUDE ../../star3do.typ + +PATH comm/comandr +PACKAGE COMMANDER_PACKAGE comandr.con + GFXRES COMMANDER_PMAP_ANIM comandr.ani + FONTRES COMMANDER_FONT comandr.fon + MUSICRES COMMANDER_MUSIC comandr.mod + STRTAB COMMANDER_COLOR_MAP comandr.ct + +PACKAGE COMMANDER_PHRASE_PACKAGE comandr.con + STRTAB COMMANDER_CONVERSATION_PHRASES comandr.txt + +PATH comm/starbas +PACKAGE STARBASE_PHRASE_PACKAGE comandr.con + STRTAB STARBASE_CONVERSATION_PHRASES starbas.txt diff --git a/sc2/src/sc2code/comm/comandr/ifontres.h b/sc2/src/sc2code/comm/comandr/ifontres.h new file mode 100644 index 000000000..11a74bd01 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/ifontres.h @@ -0,0 +1,3 @@ +#define COMMANDER_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/comandr/igfxres.h b/sc2/src/sc2code/comm/comandr/igfxres.h new file mode 100644 index 000000000..c7322a2cc --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/igfxres.h @@ -0,0 +1,3 @@ +#define COMMANDER_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/comandr/imusicre.h b/sc2/src/sc2code/comm/comandr/imusicre.h new file mode 100644 index 000000000..3d4c697dd --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/imusicre.h @@ -0,0 +1,3 @@ +#define COMMANDER_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/comandr/istrtab.h b/sc2/src/sc2code/comm/comandr/istrtab.h new file mode 100644 index 000000000..0cdbf93a6 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/istrtab.h @@ -0,0 +1,5 @@ +#define COMMANDER_COLOR_MAP 0x00200004L +#define COMMANDER_CONVERSATION_PHRASES 0x00400104L +#define STARBASE_CONVERSATION_PHRASES 0x00600204L + + diff --git a/sc2/src/sc2code/comm/comandr/resinst.h b/sc2/src/sc2code/comm/comandr/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/comandr/respkg.h b/sc2/src/sc2code/comm/comandr/respkg.h new file mode 100644 index 000000000..557c6a935 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/respkg.h @@ -0,0 +1,7 @@ +enum +{ + COMMANDER_PACKAGE = 1, + COMMANDER_PHRASE_PACKAGE, + STARBASE_PHRASE_PACKAGE +}; + diff --git a/sc2/src/sc2code/comm/comandr/restypes.h b/sc2/src/sc2code/comm/comandr/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/comandr/strings.h b/sc2/src/sc2code/comm/comandr/strings.h new file mode 100644 index 000000000..5a32434e1 --- /dev/null +++ b/sc2/src/sc2code/comm/comandr/strings.h @@ -0,0 +1,126 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + GLAD_WHEN_YOU_COME_BACK, + GIVE_FUEL, + GIVE_FUEL_AGAIN, + ARE_YOU_SUPPLY_SHIP, + DO_YOU_HAVE_RADIO_THIS_TIME, + HERE_IS_ANOTHER_LANDER, + THE_WHAT_FROM_WHERE, + ABOUT_TIME, + MESSAGE_GARBLED_1, + MESSAGE_GARBLED_2, + HERE_IS_A_NEW_LANDER, + THIS_MAY_SEEM_SILLY, + OK_THE_NAFS, + OK_THE_CAN, + OK_THE_UFW, + OK_THE_NAME_IS_EMPIRE0, + OK_THE_NAME_IS_EMPIRE1, + FUEL_UP0, + FUEL_UP1, + WHAT_KIND_OF_IDIOT, + DONT_KNOW_WHO_YOU_ARE, + THATS_IMPOSSIBLE, + ASK_AWAY, + RADIOS_ON_MERCURY, + THANKS_FOR_HELPING, + STARBASE_IS, + HAPPENED_TO_EARTH, + URQUAN_LEFT, + BASE_ON_MOON, + ACKNOWLEDGE_SECRET, + ABOUT_BASE, + GOOD_LUCK_WITH_BASE, + DEALT_WITH_BASE_YET, + HERE_COMES_ILWRATH, + VERY_IMPRESSIVE, + IT_WAS_ABANDONED, + YOU_REALLY_FOUGHT_BASE, + IM_GLAD_YOU_WON, + IM_SURE_IT_WAS_DIFFICULT, + THAT_WAS_PROBE, + DEEP_TROUBLE, + GOOD_NEWS, + SURE_HOPE, + ABOUT_BASE_AGAIN, + COOK_BUTTS, + OVERTHROW_ALIENS, + KILL_MONSTERS, + GOOD_LUCK_AGAIN, + STARBASE_WILL_BE_READY, + + overthrow_evil_aliens, + annihilate_those_monsters, + cook_their_butts, + where_get_radios, + well_go_get_them_now, + we_will_transfer_now, + what_will_you_give_us, + before_radios_we_need_info, + no_but_well_help0, + no_but_well_help1, + yes_this_is_supply_ship, + what_slave_planet, + i_lied, + plumb_out, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + first_give_info, + we_must_go_now, + where_can_i_get_radios, + ok_i_will_get_radios, + whats_this_starbase, + what_about_earth, + where_are_urquan, + our_mission_was_secret, + we_are_here_to_help, + tell_me_about_base, + we_will_take_care_of_base, + tell_me_again, + base_was_abandoned, + we_fought_them, + oh_yes_big_fight, + i_lied_it_was_abandoned, + i_cant_talk_about_it, + name_1, + name_2, + name_3, + name_40, + name_41, + i_lost_my_lander, + i_lost_another_lander, + need_fuel, + need_fuel_again, + what_was_red_thing, + it_went_away, + we_destroyed_it, + what_probe, + take_care_of_base_again, + goodbye_commander, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/druuge/druuge.res b/sc2/src/sc2code/comm/druuge/druuge.res new file mode 100644 index 000000000..562295fec --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/druuge.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/druuge + +PACKAGE DRUUGE_PACKAGE druuge.con + GFXRES DRUUGE_PMAP_ANIM druuge.ani + FONTRES DRUUGE_FONT druuge.fon + MUSICRES DRUUGE_MUSIC druuge.mod + STRTAB DRUUGE_CONVERSATION_PHRASES druuge.txt + diff --git a/sc2/src/sc2code/comm/druuge/druugec.c b/sc2/src/sc2code/comm/druuge/druugec.c new file mode 100644 index 000000000..fe98fa672 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/druugec.c @@ -0,0 +1,903 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/druuge/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/druuge/strings.h" + +static LOCDATA druuge_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)DRUUGE_PMAP_ANIM, /* AlienFrame */ + (FONT)DRUUGE_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + DRUUGE_MUSIC, /* AlienSong */ + DRUUGE_CONVERSATION_PHRASES, /* PlayerPhrases */ + 11, + { + { + 5, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + { + 9, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + { + 13, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + { + 19, /* StartIndex */ + 3, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 25, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 28, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 31, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 33, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM + | WAIT_TALKING, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND * 7, ONE_SECOND * 3,/* RestartRate */ + }, + { + 40, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 36, 0, /* FrameRate */ + 36, 0, /* RestartRate */ + }, + { + 44, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 24, 0, /* FrameRate */ + 24, 0, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 4, /* NumFrames */ + 0, /* AnimFlags */ + 8, 8, /* FrameRate */ + 10, 10, /* RestartRate */ + }, +}; + +static COUNT SlaveryCount = 0; + +static void +ExitConversation (Response) +RESPONSE_REF Response; +{ + if (PLAYER_SAID (Response, bye)) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + if (SlaveryCount) + { + UWORD PreviousSlaves; + + PreviousSlaves = MAKE_WORD ( + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) + ); + SlaveryCount += PreviousSlaves; + if (SlaveryCount > 250 && PreviousSlaves <= 250) + { + if (PreviousSlaves > 100) + GLOBAL (CrewCost) += (22 - 7); + else + GLOBAL (CrewCost) += 22; + } + else if (SlaveryCount > 100 && PreviousSlaves <= 100) + GLOBAL (CrewCost) += 7; + + SET_GAME_STATE (CREW_SOLD_TO_DRUUGE0, LOBYTE (SlaveryCount)); + SET_GAME_STATE (CREW_SOLD_TO_DRUUGE1, HIBYTE (SlaveryCount)); + } + + switch (GET_GAME_STATE (DRUUGE_HOME_VISITS)) + { + case 1: + NPCPhrase (BYE_FROM_TRADE_WORLD_1); + break; + default: + NPCPhrase (BYE_FROM_TRADE_WORLD_2); + break; + } + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + NPCPhrase (GOODBYE_FROM_BOMB_PLANET); + else + NPCPhrase (GOODBYE_FROM_SPACE); + } + else /* if (Response == then_we_take_bomb) */ + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + + NPCPhrase (FIGHT_FOR_BOMB); + } +} + +static void TradeWorld (RESPONSE_REF Response); + +static void +Buy (RESPONSE_REF Response) +{ + if (PLAYER_SAID (Response, want_to_buy) + || PLAYER_SAID (Response, im_ready_to_buy)) + { + NPCPhrase (READY_TO_SELL); + if (!GET_GAME_STATE (ROSY_SPHERE)) + NPCPhrase (HAVE_SPHERE); + if (!GET_GAME_STATE (ARTIFACT_2_ON_SHIP)) + NPCPhrase (HAVE_ART_1); + if (!GET_GAME_STATE (ARTIFACT_3_ON_SHIP)) + NPCPhrase (HAVE_ART_2); + NPCPhrase (SHIPS_AND_FUEL); + + SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 3); + } + else if (PLAYER_SAID (Response, buy_druuge_ship)) + { +#define SHIP_CREW_COST 100 + if (GLOBAL_SIS (CrewEnlisted) < SHIP_CREW_COST) + NPCPhrase (NOT_ENOUGH_CREW); + else if (ActivateStarShip (DRUUGE_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (NOT_ENOUGH_ROOM); + else + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-SHIP_CREW_COST, 0, 0); + ClearSemaphore (&GraphicsSem); + SlaveryCount += SHIP_CREW_COST; + ActivateStarShip (DRUUGE_SHIP, 1); + + NPCPhrase (BOUGHT_SHIP); + } + } +#define ARTIFACT_CREW_COST 100 + else if (PLAYER_SAID (Response, buy_rosy_sphere)) + { + if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) + NPCPhrase (NOT_ENOUGH_CREW); + else + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); + ClearSemaphore (&GraphicsSem); + SlaveryCount += ARTIFACT_CREW_COST; + SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); + SET_GAME_STATE (ROSY_SPHERE, 1); + + NPCPhrase (BOUGHT_SPHERE); + } + } + else if (PLAYER_SAID (Response, buy_art_1)) + { + if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) + NPCPhrase (NOT_ENOUGH_CREW); + else + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); + ClearSemaphore (&GraphicsSem); + SlaveryCount += ARTIFACT_CREW_COST; + SET_GAME_STATE (ARTIFACT_2_ON_SHIP, 1); + + NPCPhrase (BOUGHT_ART_1); + } + } + else if (PLAYER_SAID (Response, buy_art_2)) + { + if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) + NPCPhrase (NOT_ENOUGH_CREW); + else + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); + ClearSemaphore (&GraphicsSem); + SlaveryCount += ARTIFACT_CREW_COST; + SET_GAME_STATE (ARTIFACT_3_ON_SHIP, 1); + + NPCPhrase (BOUGHT_ART_2); + } + } + else if (PLAYER_SAID (Response, buy_fuel)) + { +#define FUEL_CREW_COST 10 + if (GLOBAL_SIS (CrewEnlisted) < FUEL_CREW_COST) + NPCPhrase (NOT_ENOUGH_CREW); + else + { + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-FUEL_CREW_COST, + FUEL_CREW_COST * FUEL_TANK_SCALE, 0); + ClearSemaphore (&GraphicsSem); + SlaveryCount += FUEL_CREW_COST; + + NPCPhrase (BOUGHT_FUEL); + } + } + + Response (buy_druuge_ship, Buy); + if (!GET_GAME_STATE (ROSY_SPHERE)) + Response (buy_rosy_sphere, Buy); + if (!GET_GAME_STATE (ARTIFACT_2_ON_SHIP)) + Response (buy_art_1, Buy); + if (!GET_GAME_STATE (ARTIFACT_3_ON_SHIP)) + Response (buy_art_2, Buy); + Response (buy_fuel, Buy); + Response (done_buying, TradeWorld); +} + +static void Sell (RESPONSE_REF R); + +static RESPONSE_REF LastResponse = 0; + +static void +Trade (RESPONSE_REF R) +{ + if (!PLAYER_SAID (R, whats_the_sphere_again)) + { + NPCPhrase (TRADE_FOR_SPHERE); + LastResponse = R; + } + else + { + NPCPhrase (SPHERE_IS); + + DISABLE_PHRASE (whats_the_sphere_again); + } + + Response (no_way, Sell); + Response (way, Sell); + if (PHRASE_ENABLED (whats_the_sphere_again)) + { + Response (whats_the_sphere_again, Trade); + } +} + +static void +DoTransaction (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, sell_maidens)) + { + SET_GAME_STATE (MAIDENS_ON_SHIP, 0); + } + else if (PLAYER_SAID (R, sell_fragments)) + { + BYTE num_frags; + + if (GET_GAME_STATE (EGG_CASE0_ON_SHIP)) + { + SET_GAME_STATE (EGG_CASE0_ON_SHIP, 0); + } + else if (GET_GAME_STATE (EGG_CASE1_ON_SHIP)) + { + SET_GAME_STATE (EGG_CASE1_ON_SHIP, 0); + } + else if (GET_GAME_STATE (EGG_CASE2_ON_SHIP)) + { + SET_GAME_STATE (EGG_CASE2_ON_SHIP, 0); + } + + num_frags = GET_GAME_STATE (FRAGMENTS_BOUGHT) + 1; + SET_GAME_STATE (FRAGMENTS_BOUGHT, num_frags); + } + else if (PLAYER_SAID (R, sell_caster)) + { + SET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 0); + } + else if (PLAYER_SAID (R, sell_spawner)) + { + SET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 0); + } + + if (!GET_GAME_STATE (ROSY_SPHERE) + && GET_GAME_STATE (ROSY_SPHERE_ON_SHIP)) + { + SET_GAME_STATE (ROSY_SPHERE, 1); + } + else + { + BYTE trade_gas; + BYTE ship_slots, ships_to_trade; + + trade_gas = 0; + ships_to_trade = 0; + ship_slots = ActivateStarShip (DRUUGE_SHIP, FEASIBILITY_STUDY); + if (PLAYER_SAID (R, sell_maidens)) + { + NPCPhrase (BOUGHT_MAIDENS); + ships_to_trade = 6; + } + else if (PLAYER_SAID (R, sell_fragments)) + { + NPCPhrase (BOUGHT_FRAGMENTS); + ships_to_trade = 1; + } + else if (PLAYER_SAID (R, sell_caster)) + { + NPCPhrase (BOUGHT_CASTER); + ships_to_trade = 0; + trade_gas = 1; + } + else if (PLAYER_SAID (R, sell_spawner)) + { + NPCPhrase (BOUGHT_SPAWNER); + ships_to_trade = 3; + trade_gas = 1; + } + + NPCPhrase (YOU_GET); + if (ships_to_trade) + { + ActivateStarShip (DRUUGE_SHIP, ships_to_trade); + + if (ship_slots >= ships_to_trade) + NPCPhrase (DEAL_FOR_STATED_SHIPS); + else if (ship_slots == 0) + NPCPhrase (DEAL_FOR_NO_SHIPS); + else + NPCPhrase (DEAL_FOR_LESS_SHIPS); + + if (trade_gas) + NPCPhrase (YOU_ALSO_GET); + } + + if (trade_gas) + { + BYTE slot; + COUNT f; + DWORD capacity; + + capacity = FUEL_RESERVE; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) + { + COUNT volume; + + volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; + capacity += volume; + } + } while (slot--); + capacity -= GLOBAL_SIS (FuelOnBoard); + f = (COUNT)((capacity + (FUEL_TANK_SCALE >> 1)) / FUEL_TANK_SCALE); + + SetSemaphore (&GraphicsSem); + while (capacity > 0x3FFFL) + { + DeltaSISGauges (0, 0x3FFF, 0); + capacity -= 0x3FFF; + } + DeltaSISGauges (0, (SIZE)capacity, 0); + ClearSemaphore (&GraphicsSem); + + NPCPhrase (FUEL0); + NPCPhrase (-(int)f); + NPCPhrase (FUEL1); + + if (f >= 250) + NPCPhrase (HIDEOUS_DEAL); + else if (f >= 100) + NPCPhrase (BAD_DEAL); + else if (f >= 50) + NPCPhrase (FAIR_DEAL); + else if (f >= 10) + NPCPhrase (GOOD_DEAL); + else + NPCPhrase (FINE_DEAL); + } + } +} + +static void +Sell (RESPONSE_REF Response) +{ + RESPONSE_FUNC RespFunc; + + if (PLAYER_SAID (Response, want_to_sell)) + NPCPhrase (READY_TO_BUY); + else if (PLAYER_SAID (Response, no_way) + || PLAYER_SAID (Response, way)) + { + if (PLAYER_SAID (Response, no_way)) + NPCPhrase (OK_REGULAR_DEAL); + else + { + NPCPhrase (OK_HERES_SPHERE); + + SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); + } + + DoTransaction (LastResponse); + } + else if (PLAYER_SAID (Response, sell_maidens) + || PLAYER_SAID (Response, sell_fragments) + || PLAYER_SAID (Response, sell_caster) + || PLAYER_SAID (Response, sell_spawner)) + { + DoTransaction (Response); + } + + if (!GET_GAME_STATE (ROSY_SPHERE)) + RespFunc = (RESPONSE_FUNC)Trade; + else + RespFunc = (RESPONSE_FUNC)Sell; + if (GET_GAME_STATE (MAIDENS_ON_SHIP)) + Response (sell_maidens, RespFunc); + if ((GET_GAME_STATE (EGG_CASE0_ON_SHIP) + || GET_GAME_STATE (EGG_CASE1_ON_SHIP) + || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) + && GET_GAME_STATE (FRAGMENTS_BOUGHT) < 2) + Response (sell_fragments, RespFunc); + if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP)) + Response (sell_caster, RespFunc); + if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP)) + Response (sell_spawner, RespFunc); + Response (done_selling, TradeWorld); +} + +static void +ExplainSlaveTrade (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, want_to_buy)) + NPCPhrase (WE_SELL_FOR_CREW); + else if (PLAYER_SAID (R, isnt_this_slave_trading)) + { + NPCPhrase (NO_SLAVE_TRADE); + + SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 1); + } + else if (PLAYER_SAID (R, what_do_with_crew)) + { + NPCPhrase (HAVE_FUN); + + SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 2); + } + + switch (GET_GAME_STATE (KNOW_DRUUGE_SLAVERS)) + { + case 0: + Response (isnt_this_slave_trading, ExplainSlaveTrade); + break; + case 1: + Response (what_do_with_crew, ExplainSlaveTrade); + break; + } + Response (i_will_never_trade_crew, TradeWorld); + Response (im_ready_to_buy, Buy); +} + +static void +TradeWorld (RESPONSE_REF Response) +{ + if (PLAYER_SAID (Response, whats_up_at_trade_world)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (DRUUGE_HOME_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GEN_INFO_AT_TRADE_WORLD_1); + break; + case 1: + NPCPhrase (GEN_INFO_AT_TRADE_WORLD_2); + break; + case 2: + NPCPhrase (GEN_INFO_AT_TRADE_WORLD_3); + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) + { + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); + } + break; + case 3: + NPCPhrase (GEN_INFO_AT_TRADE_WORLD_4); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_HOME_INFO, NumVisits); + DISABLE_PHRASE (whats_up_at_trade_world); + } + else if (PLAYER_SAID (Response, done_selling)) + NPCPhrase (OK_DONE_SELLING); + else if (PLAYER_SAID (Response, done_buying)) + NPCPhrase (OK_DONE_BUYING); + else if (PLAYER_SAID (Response, i_will_never_trade_crew)) + NPCPhrase (YOUR_LOSS); + + if (PHRASE_ENABLED (whats_up_at_trade_world)) + { + Response (whats_up_at_trade_world, TradeWorld); + } + Response (want_to_sell, Sell); + if (GET_GAME_STATE (KNOW_DRUUGE_SLAVERS) == 3) + Response (want_to_buy, Buy); + else + Response (want_to_buy, ExplainSlaveTrade); + Response (bye, ExitConversation); +} + +static void +BombAmbush (RESPONSE_REF Response) +{ + if (PLAYER_SAID (Response, whats_up_at_bomb_planet)) + { + NPCPhrase (GEN_INFO_AT_BOMB_PLANET); + SET_GAME_STATE (BOMB_VISITS, 2); + } + else if (PLAYER_SAID (Response, we_get_bomb)) + { + NPCPhrase (NOT_GET_BOMB); + SET_GAME_STATE (BOMB_VISITS, 3); + } + + switch (GET_GAME_STATE (BOMB_VISITS)) + { + case 1: + Response (whats_up_at_bomb_planet, BombAmbush); + break; + case 2: + Response (we_get_bomb, BombAmbush); + break; + default: + Response (then_we_take_bomb, ExitConversation); + break; + } + Response (bye, ExitConversation); +} + +static void +Space (RESPONSE_REF Response) +{ + if (PLAYER_SAID (Response, whats_up_in_space)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (DRUUGE_SPACE_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_IN_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_IN_SPACE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_IN_SPACE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_IN_SPACE_4); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_SPACE_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_in_space); + } + + if (PHRASE_ENABLED (whats_up_in_space)) + { + Response (whats_up_in_space, Space); + } + Response (bye, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (DRUUGE_MANNER)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (DRUUGE_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HSTL_TRADE_WORLD_HELLO_1); + break; + case 1: + NPCPhrase (HSTL_TRADE_WORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (DRUUGE_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_VISITS, NumVisits); + } + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + { + NumVisits = GET_GAME_STATE (DRUUGE_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INITIAL_TRADE_WORLD_HELLO); + break; + case 1: + NPCPhrase (SSQ_TRADE_WORLD_HELLO_1); + break; + case 2: + NPCPhrase (SSQ_TRADE_WORLD_HELLO_2); + break; + case 3: + NPCPhrase (SSQ_TRADE_WORLD_HELLO_3); + break; + case 4: + NPCPhrase (SSQ_TRADE_WORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_HOME_VISITS, NumVisits); + } + if (GET_GAME_STATE (ATTACKED_DRUUGE) + && !GET_GAME_STATE (DRUUGE_DISCLAIMER)) + { +// NPCPhrase (HOSTILE_TRADE); + SET_GAME_STATE (DRUUGE_DISCLAIMER, 1); + } + if (GET_GAME_STATE (MAIDENS_ON_SHIP) + && !GET_GAME_STATE (SCANNED_MAIDENS)) + { + NPCPhrase (SCAN_MAIDENS); + SET_GAME_STATE (SCANNED_MAIDENS, 1); + } + if ((GET_GAME_STATE (EGG_CASE0_ON_SHIP) + || GET_GAME_STATE (EGG_CASE1_ON_SHIP) + || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) + && !GET_GAME_STATE (SCANNED_FRAGMENTS)) + { + if (GET_GAME_STATE (FRAGMENTS_BOUGHT) < 2) + NPCPhrase (SCAN_FRAGMENTS); + else + NPCPhrase (ENOUGH_FRAGMENTS); + SET_GAME_STATE (SCANNED_FRAGMENTS, 1); + } + if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP) + && !GET_GAME_STATE (SCANNED_CASTER)) + { + NPCPhrase (SCAN_DRUUGE_CASTER); + SET_GAME_STATE (SCANNED_CASTER, 1); + } + if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP) + && !GET_GAME_STATE (SCANNED_SPAWNER)) + { + NPCPhrase (SCAN_ARILOU_SPAWNER); + SET_GAME_STATE (SCANNED_SPAWNER, 1); + } + + TradeWorld ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + if (GET_GAME_STATE (BOMB_VISITS)) + NPCPhrase (SUBSEQ_BOMB_WORLD_HELLO); + else + { + NPCPhrase (INIT_BOMB_WORLD_HELLO); + SET_GAME_STATE (BOMB_VISITS, 1); + } + + BombAmbush ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (ATTACKED_DRUUGE)) + { + NumVisits = GET_GAME_STATE (DRUUGE_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + NumVisits = 0; + if (GetHeadLink (&GLOBAL (built_ship_q)) == 0) + { + for (NumVisits = 0; NumVisits < NUM_MODULE_SLOTS; ++NumVisits) + { + BYTE which_module; + + which_module = GLOBAL_SIS (ModuleSlots[NumVisits]); + if (which_module >= GUN_WEAPON + && which_module <= CANNON_WEAPON) + { + NumVisits = 0; + break; + } + } + } + + if (NumVisits) + { + NumVisits = GET_GAME_STATE (DRUUGE_SALVAGE); + switch (NumVisits++) + { + case 0: + NPCPhrase (SALVAGE_YOUR_SHIP_1); + break; + case 1: + NPCPhrase (SALVAGE_YOUR_SHIP_2); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_SALVAGE, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + NumVisits = GET_GAME_STATE (DRUUGE_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_SPACE_HELLO); + break; + case 1: + NPCPhrase (SUBSEQUENT_SPACE_HELLO); + --NumVisits; + break; + } + SET_GAME_STATE (DRUUGE_VISITS, NumVisits); + + Space ((RESPONSE_REF)0); + } + } +ExitIntro: + ; +} + +static COUNT +uninit_druuge (void) +{ + if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && !GET_GAME_STATE (DRUUGE_MANNER)) + { + if (!GET_GAME_STATE (ATTACKED_DRUUGE)) + { + SET_GAME_STATE (ATTACKED_DRUUGE, 1); + SET_GAME_STATE (DRUUGE_VISITS, 0); + } + } + + return (0); +} + +LOCDATAPTR +init_druuge_comm (void) +{ + LOCDATAPTR retval; + + druuge_desc.init_encounter_func = Intro; + druuge_desc.uninit_encounter_func = uninit_druuge; + + druuge_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + druuge_desc.AlienTextTemplate.baseline.y = 64; + druuge_desc.AlienTextTemplate.align = ALIGN_CENTER; + druuge_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if ((GET_GAME_STATE (DRUUGE_MANNER) == 0 + && (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &druuge_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/druuge/ifontres.h b/sc2/src/sc2code/comm/druuge/ifontres.h new file mode 100644 index 000000000..b0c917887 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/ifontres.h @@ -0,0 +1,3 @@ +#define DRUUGE_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/druuge/igfxres.h b/sc2/src/sc2code/comm/druuge/igfxres.h new file mode 100644 index 000000000..078ff3041 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/igfxres.h @@ -0,0 +1,3 @@ +#define DRUUGE_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/druuge/imusicre.h b/sc2/src/sc2code/comm/druuge/imusicre.h new file mode 100644 index 000000000..7977059d8 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/imusicre.h @@ -0,0 +1,3 @@ +#define DRUUGE_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/druuge/istrtab.h b/sc2/src/sc2code/comm/druuge/istrtab.h new file mode 100644 index 000000000..a8c3fc94d --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/istrtab.h @@ -0,0 +1,3 @@ +#define DRUUGE_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/druuge/resinst.h b/sc2/src/sc2code/comm/druuge/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/druuge/respkg.h b/sc2/src/sc2code/comm/druuge/respkg.h new file mode 100644 index 000000000..348018d7a --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/respkg.h @@ -0,0 +1,5 @@ +enum +{ + DRUUGE_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/druuge/restypes.h b/sc2/src/sc2code/comm/druuge/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/druuge/strings.h b/sc2/src/sc2code/comm/druuge/strings.h new file mode 100644 index 000000000..2567f39f7 --- /dev/null +++ b/sc2/src/sc2code/comm/druuge/strings.h @@ -0,0 +1,131 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + AMBUSH_IS_FIRST_HELLO, + INIT_BOMB_WORLD_HELLO, + SUBSEQ_BOMB_WORLD_HELLO, + whats_up_at_bomb_planet, + GEN_INFO_AT_BOMB_PLANET, + we_get_bomb, + NOT_GET_BOMB, + then_we_take_bomb, + FIGHT_FOR_BOMB, + GOODBYE_FROM_BOMB_PLANET, + NOT_ENOUGH_ROOM, + TRADE_FOR_SPHERE, + no_way, + OK_REGULAR_DEAL, + way, + OK_HERES_SPHERE, + whats_the_sphere_again, + SPHERE_IS, + WE_SELL_FOR_CREW, + i_will_never_trade_crew, + YOUR_LOSS, + isnt_this_slave_trading, + NO_SLAVE_TRADE, + what_do_with_crew, + HAVE_FUN, + im_ready_to_buy, + THIS_FOR_SALE, + HAVE_SPHERE, + HAVE_ART_2, + HAVE_ART_1, + SHIPS_AND_FUEL, + BOUGHT_SHIP, + BOUGHT_FUEL, + BOUGHT_ART_2, + BOUGHT_ART_1, + BOUGHT_SPHERE, + repeat_what_to_sell, + INIT_SPACE_HELLO, + SUBSEQUENT_SPACE_HELLO, + whats_up_in_space, + GENERAL_INFO_IN_SPACE_1, + GENERAL_INFO_IN_SPACE_2, + GENERAL_INFO_IN_SPACE_3, + GENERAL_INFO_IN_SPACE_4, + GOODBYE_FROM_SPACE, + HSTL_TRADE_WORLD_HELLO_1, + HSTL_TRADE_WORLD_HELLO_2, + HOSTILE_SPACE_HELLO_1, + HOSTILE_SPACE_HELLO_2, + INITIAL_TRADE_WORLD_HELLO, + SSQ_TRADE_WORLD_HELLO_1, + SSQ_TRADE_WORLD_HELLO_2, + SSQ_TRADE_WORLD_HELLO_3, + SSQ_TRADE_WORLD_HELLO_4, + whats_up_at_trade_world, + GEN_INFO_AT_TRADE_WORLD_1, + GEN_INFO_AT_TRADE_WORLD_2, + GEN_INFO_AT_TRADE_WORLD_3, + GEN_INFO_AT_TRADE_WORLD_4, + SCAN_MAIDENS, + SCAN_FRAGMENTS, + SCAN_DRUUGE_CASTER, + SCAN_ARILOU_SPAWNER, + ENOUGH_FRAGMENTS, + READY_TO_BUY, + READY_TO_SELL, + BYE_FROM_TRADE_WORLD_1, + BYE_FROM_TRADE_WORLD_2, + NOT_ENOUGH_CREW, + EXCHANGE_MADE, + OK_DONE_BUYING, + OK_DONE_SELLING, + bye, + want_to_sell, + want_to_buy, + buy_druuge_ship, + buy_fuel, + buy_art_1, + buy_art_2, + buy_rosy_sphere, + done_buying, + done_selling, + sell_maidens, + sell_caster, + sell_fragments, + sell_spawner, + BOUGHT_MAIDENS, + BOUGHT_FRAGMENTS, + BOUGHT_CASTER, + YOU_GET, + YOU_ALSO_GET, + BOUGHT_SPAWNER, + SALVAGE_YOUR_SHIP_1, + SALVAGE_YOUR_SHIP_2, + DEAL_FOR_STATED_SHIPS, + DEAL_FOR_LESS_SHIPS, + DEAL_FOR_NO_SHIPS, + FUEL0, + FUEL1, + HIDEOUS_DEAL, + BAD_DEAL, + FAIR_DEAL, + GOOD_DEAL, + FINE_DEAL, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/dummy.c b/sc2/src/sc2code/comm/dummy.c new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/src/sc2code/comm/ilwrath/ifontres.h b/sc2/src/sc2code/comm/ilwrath/ifontres.h new file mode 100644 index 000000000..5df16803b --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/ifontres.h @@ -0,0 +1,3 @@ +#define ILWRATH_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/ilwrath/igfxres.h b/sc2/src/sc2code/comm/ilwrath/igfxres.h new file mode 100644 index 000000000..b02bc773c --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/igfxres.h @@ -0,0 +1,3 @@ +#define ILWRATH_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/ilwrath/ilwrath.res b/sc2/src/sc2code/comm/ilwrath/ilwrath.res new file mode 100644 index 000000000..af3009eaf --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/ilwrath.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/ilwrath + +PACKAGE ILWRATH_PACKAGE ilwrath.con + GFXRES ILWRATH_PMAP_ANIM ilwrath.ani + FONTRES ILWRATH_FONT ilwrath.fon + MUSICRES ILWRATH_MUSIC ilwrath.mod + STRTAB ILWRATH_CONVERSATION_PHRASES ilwrath.txt + diff --git a/sc2/src/sc2code/comm/ilwrath/ilwrathc.c b/sc2/src/sc2code/comm/ilwrath/ilwrathc.c new file mode 100644 index 000000000..d01884e5d --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/ilwrathc.c @@ -0,0 +1,624 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/ilwrath/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/ilwrath/strings.h" + +static LOCDATA ilwrath_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)ILWRATH_PMAP_ANIM, /* AlienFrame */ + (FONT)ILWRATH_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + ILWRATH_MUSIC, /* AlienSong */ + ILWRATH_CONVERSATION_PHRASES, /* PlayerPhrases */ + 4, /* NumAnimations */ + { + { + 6, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 11, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 16, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 21, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 5, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +CombatIsInevitable (Response) +RESPONSE_REF Response; +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (Response, you_are_weak)) + NPCPhrase (STRENGTH_NOT_ALL); + else if (PLAYER_SAID (Response, slay_by_thousands)) + NPCPhrase (NO_SLAY_BY_THOUSANDS); + else if (PLAYER_SAID (Response, ease_up)) + NPCPhrase (NO_EASE_UP); + else if (PLAYER_SAID (Response, bye_space)) + NPCPhrase (GOODBYE_AND_DIE_SPACE); + else if (PLAYER_SAID (Response, bye_homeworld)) + NPCPhrase (GOODBYE_AND_DIE_HOMEWORLD); + else if (PLAYER_SAID (Response, want_peace)) + NPCPhrase (NO_PEACE); + else if (PLAYER_SAID (Response, want_alliance)) + NPCPhrase (NO_ALLIANCE); + else if (PLAYER_SAID (Response, but_evil_is_defined)) + NPCPhrase (DONT_CONFUSE_US); + else if (PLAYER_SAID (Response, bye_gods)) + { + NPCPhrase (GOODBYE_GODS); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + if (PLAYER_SAID (Response, whats_up)) + { + NPCPhrase (GENERAL_INFO); + Response (bye, CombatIsInevitable); + } + else if (PLAYER_SAID (Response, whats_up_space_1) + || PLAYER_SAID (Response, whats_up_space_2) + || PLAYER_SAID (Response, whats_up_space_3) + || PLAYER_SAID (Response, whats_up_space_4) + || PLAYER_SAID (Response, whats_up_space_5)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (ILWRATH_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_SPACE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_SPACE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_SPACE_4); + break; + case 4: + NPCPhrase (GENERAL_INFO_SPACE_5); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_INFO, NumVisits); + } + else + { + if (PLAYER_SAID (Response, bye)) + NPCPhrase (GOODBYE_AND_DIE); + else if (PLAYER_SAID (Response, where_you_come_from)) + NPCPhrase (CAME_FROM); + if (PLAYER_SAID (Response, it_will_be_a_pleasure)) + NPCPhrase (WHO_BLASTS_WHO); + if (PLAYER_SAID (Response, surrender)) + NPCPhrase (NO_SURRENDER); + if (PLAYER_SAID (Response, be_reasonable)) + NPCPhrase (NOT_REASONABLE); + } +} + +static void IlwrathHome (RESPONSE_REF R); + +static void +IlwrathGods (RESPONSE_REF R) +{ + BYTE GodsLeft; + + GodsLeft = FALSE; + if (PLAYER_SAID (R, want_info_on_gods)) + NPCPhrase (SO_MUCH_TO_KNOW); + else if (PLAYER_SAID (R, when_start_worship)) + { + NPCPhrase (LONG_AGO); + + DISABLE_PHRASE (when_start_worship); + } + else if (PLAYER_SAID (R, any_good_gods)) + { + NPCPhrase (KILLED_GOOD_GODS); + + DISABLE_PHRASE (any_good_gods); + } + else if (PLAYER_SAID (R, how_talk_with_gods)) + { + NPCPhrase (CHANNEL_44); + + DISABLE_PHRASE (how_talk_with_gods); + } + else if (PLAYER_SAID (R, why_44)) + { + NPCPhrase (BECAUSE_44); + + DISABLE_PHRASE (why_44); + } + + if (PHRASE_ENABLED (when_start_worship)) + { + Response (when_start_worship, IlwrathGods); + GodsLeft = TRUE; + } + if (PHRASE_ENABLED (any_good_gods)) + { + Response (any_good_gods, IlwrathGods); + GodsLeft = TRUE; + } + if (PHRASE_ENABLED (how_talk_with_gods)) + { + Response (how_talk_with_gods, IlwrathGods); + GodsLeft = TRUE; + } + else if (PHRASE_ENABLED (why_44)) + { + Response (why_44, IlwrathGods); + GodsLeft = TRUE; + } + Response (enough_gods, IlwrathHome); + + if (!GodsLeft) + DISABLE_PHRASE (want_info_on_gods); +} + +static void +IlwrathInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + + InfoLeft = FALSE; + if (PLAYER_SAID (R, want_info_on_ilwrath)) + NPCPhrase (WHAT_ABOUT_ILWRATH); + else if (PLAYER_SAID (R, what_about_physio)) + { + NPCPhrase (ABOUT_PHYSIO); + + DISABLE_PHRASE (what_about_physio); + } + else if (PLAYER_SAID (R, what_about_history)) + { + NPCPhrase (ABOUT_HISTORY); + + DISABLE_PHRASE (what_about_history); + } + else if (PLAYER_SAID (R, what_about_culture)) + { + NPCPhrase (ABOUT_CULTURE); + + DISABLE_PHRASE (what_about_culture); + } + else if (PLAYER_SAID (R, what_about_urquan)) + { + NPCPhrase (URQUAN_TOO_NICE); + + DISABLE_PHRASE (what_about_urquan); + } + else if (PLAYER_SAID (R, are_you_evil)) + { + NPCPhrase (OF_COURSE_WERE_EVIL); + + DISABLE_PHRASE (are_you_evil); + } + + if (PHRASE_ENABLED (what_about_physio)) + { + Response (what_about_physio, IlwrathInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_history)) + { + Response (what_about_history, IlwrathInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_culture)) + { + Response (what_about_culture, IlwrathInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_urquan)) + { + Response (what_about_urquan, IlwrathInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (are_you_evil)) + { + Response (are_you_evil, IlwrathInfo); + InfoLeft = TRUE; + } + else + { + Response (but_evil_is_defined, CombatIsInevitable); + InfoLeft = TRUE; + } + Response (enough_ilwrath, IlwrathHome); + + if (!InfoLeft) + DISABLE_PHRASE (want_info_on_ilwrath); +} + +static void +IlwrathHome (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (ILWRATH_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_HOME_HELLO); + break; + case 1: + NPCPhrase (SUBSEQUENT_HOME_HELLO); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_HOME_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, enough_gods)) + NPCPhrase (OK_ENOUGH_GODS); + else if (PLAYER_SAID (R, enough_ilwrath)) + NPCPhrase (OK_ENOUGH_ILWRATH); + + if (PHRASE_ENABLED (want_info_on_gods)) + { + Response (want_info_on_gods, IlwrathGods); + } + if (PHRASE_ENABLED (want_info_on_ilwrath)) + { + Response (want_info_on_ilwrath, IlwrathInfo); + } + Response (want_peace, CombatIsInevitable); + Response (want_alliance, CombatIsInevitable); + Response (bye_homeworld, CombatIsInevitable); +} + +static void GodsSpeak (RESPONSE_REF R); + +static void +GodsOrder (RESPONSE_REF R) +{ + BYTE OrdersLeft; + + OrdersLeft = FALSE; + if (PLAYER_SAID (R, other_divine_orders)) + NPCPhrase (WHAT_ORDERS); + else if (PLAYER_SAID (R, say_warship)) + { + NPCPhrase (OK_WARSHIP); + + DISABLE_PHRASE (say_warship); + } + else if (PLAYER_SAID (R, say_dwe)) + { + NPCPhrase (OK_DWE); + + DISABLE_PHRASE (say_dwe); + } + else if (PLAYER_SAID (R, say_youboo)) + { + NPCPhrase (OK_YOUBOO); + + DISABLE_PHRASE (say_youboo); + } + else if (PLAYER_SAID (R, say_dillrat)) + { + NPCPhrase (OK_DILRAT); + + DISABLE_PHRASE (say_dillrat); + } + + if (PHRASE_ENABLED (say_warship)) + { + Response (say_warship, GodsOrder); + OrdersLeft = TRUE; + } + if (PHRASE_ENABLED (say_dwe)) + { + Response (say_dwe, GodsOrder); + OrdersLeft = TRUE; + } + if (PHRASE_ENABLED (say_youboo)) + { + Response (say_youboo, GodsOrder); + OrdersLeft = TRUE; + } + if (PHRASE_ENABLED (say_dillrat)) + { + Response (say_dillrat, GodsOrder); + OrdersLeft = TRUE; + } + Response (enough_orders, GodsSpeak); + + if (!OrdersLeft) + DISABLE_PHRASE (other_divine_orders); +} + +static void +GodsSpeak (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (R == 0) + { + if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) + NPCPhrase (GLORIOUS_WORSHIP); + else if (GET_GAME_STATE (ILWRATH_DECEIVED)) + NPCPhrase (ON_WAY); + else + { + NumVisits = GET_GAME_STATE (ILWRATH_GODS_SPOKEN); + switch (NumVisits++) + { + case 0: + NPCPhrase (ILWRATH_BELIEVE); + break; + case 1: + NPCPhrase (GODS_RETURN_1); + break; + case 2: + NPCPhrase (GODS_RETURN_2); + break; + case 3: + NPCPhrase (GODS_RETURN_3); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_GODS_SPOKEN, NumVisits); + } + } + else if (PLAYER_SAID (R, go_kill_thraddash)) + { + NPCPhrase (OK_KILL_THRADDASH); + + SET_GAME_STATE (ILWRATH_DECEIVED, 1); + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_ILWRATH_MISSION); + } + else if (PLAYER_SAID (R, worship_us)) + { + NumVisits = GET_GAME_STATE (ILWRATH_WORSHIP); + switch (NumVisits++) + { + case 0: + NPCPhrase (WE_WORSHIP_1); + break; + case 1: + NPCPhrase (WE_WORSHIP_2); + break; + case 2: + NPCPhrase (WE_WORSHIP_3); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_WORSHIP, NumVisits); + + DISABLE_PHRASE (worship_us); + } + else if (PLAYER_SAID (R, enough_orders)) + NPCPhrase (NEVER_ENOUGH); + + if (!GET_GAME_STATE (ILWRATH_DECEIVED)) + Response (go_kill_thraddash, GodsSpeak); + if (PHRASE_ENABLED (worship_us)) + Response (worship_us, GodsSpeak); + if (PHRASE_ENABLED (other_divine_orders)) + { + Response (other_divine_orders, GodsOrder); + } + Response (bye_gods, CombatIsInevitable); +} + +static void +IlwrathSpace (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (R == 0) + { + NumVisits = GET_GAME_STATE (ILWRATH_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_HELLO_SPACE); + break; + case 1: + NPCPhrase (SUBSEQUENT_HELLO_SPACE_1); + break; + case 2: + NPCPhrase (SUBSEQUENT_HELLO_SPACE_2); + break; + case 3: + NPCPhrase (SUBSEQUENT_HELLO_SPACE_3); + break; + case 4: + NPCPhrase (SUBSEQUENT_HELLO_SPACE_4); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_VISITS, NumVisits); + } + + NumVisits = GET_GAME_STATE (ILWRATH_INFO); + switch (NumVisits) + { + case 0: + Response (whats_up_space_1, CombatIsInevitable); + break; + case 1: + Response (whats_up_space_2, CombatIsInevitable); + break; + case 2: + Response (whats_up_space_3, CombatIsInevitable); + break; + case 3: + Response (whats_up_space_4, CombatIsInevitable); + break; + case 4: + Response (whats_up_space_5, CombatIsInevitable); + break; + } + Response (you_are_weak, CombatIsInevitable); + Response (slay_by_thousands, CombatIsInevitable); + Response (ease_up, CombatIsInevitable); + Response (bye_space, CombatIsInevitable); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)) + { + NPCPhrase (SEND_MESSAGE); + + Response (where_you_come_from, CombatIsInevitable); + Response (it_will_be_a_pleasure, CombatIsInevitable); + Response (surrender, CombatIsInevitable); + Response (be_reasonable, CombatIsInevitable); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + IlwrathHome ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (ILWRATH_CHMMR_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_CHMMR_HELLO); + break; + case 1: + NPCPhrase (SUBSEQUENT_CHMMR_HELLO); + --NumVisits; + break; + } + SET_GAME_STATE (ILWRATH_CHMMR_VISITS, NumVisits); + + Response (whats_up, CombatIsInevitable); + Response (bye, CombatIsInevitable); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 5)) + { + if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) + NPCPhrase (BIG_FUN); + else if (GET_GAME_STATE (ILWRATH_DECEIVED)) + NPCPhrase (FAST_AS_CAN); + else + NPCPhrase (JUST_GRUNTS); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 4)) + { + GodsSpeak ((RESPONSE_REF)0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) + NPCPhrase (HAPPY_FIGHTING_THRADDASH); + else if (GET_GAME_STATE (ILWRATH_DECEIVED)) + NPCPhrase (ON_WAY_TO_THRADDASH); + else + IlwrathSpace ((RESPONSE_REF)0); + } +} + +static COUNT +uninit_ilwrath (void) +{ + return (0); +} + +LOCDATAPTR +init_ilwrath_comm (void) +{ + LOCDATAPTR retval; + + ilwrath_desc.init_encounter_func = Intro; + ilwrath_desc.uninit_encounter_func = uninit_ilwrath; + + ilwrath_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + ilwrath_desc.AlienTextTemplate.baseline.y = 64; + ilwrath_desc.AlienTextTemplate.align = ALIGN_CENTER; + ilwrath_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER) + || (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) + & ((1 << 4) | (1 << 5))) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &ilwrath_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/ilwrath/imusicre.h b/sc2/src/sc2code/comm/ilwrath/imusicre.h new file mode 100644 index 000000000..946580acb --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/imusicre.h @@ -0,0 +1,3 @@ +#define ILWRATH_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/ilwrath/istrtab.h b/sc2/src/sc2code/comm/ilwrath/istrtab.h new file mode 100644 index 000000000..e9ba01564 --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/istrtab.h @@ -0,0 +1,3 @@ +#define ILWRATH_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/ilwrath/resinst.h b/sc2/src/sc2code/comm/ilwrath/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/ilwrath/respkg.h b/sc2/src/sc2code/comm/ilwrath/respkg.h new file mode 100644 index 000000000..8f0b77e23 --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/respkg.h @@ -0,0 +1,5 @@ +enum +{ + ILWRATH_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/ilwrath/restypes.h b/sc2/src/sc2code/comm/ilwrath/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/ilwrath/strings.h b/sc2/src/sc2code/comm/ilwrath/strings.h new file mode 100644 index 000000000..546923bee --- /dev/null +++ b/sc2/src/sc2code/comm/ilwrath/strings.h @@ -0,0 +1,135 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + NEVER_ENOUGH, + OK_WARSHIP, + OK_DWE, + OK_YOUBOO, + OK_DILRAT, + BIG_FUN, + FAST_AS_CAN, + GLORIOUS_WORSHIP, + ON_WAY, + GODS_RETURN_1, + GODS_RETURN_2, + GODS_RETURN_3, + JUST_GRUNTS, + GRUNTS_AGAIN, + WHAT_ORDERS, + WE_WORSHIP_1, + WE_WORSHIP_2, + WE_WORSHIP_3, + SUBSEQUENT_CHMMR_HELLO, + INIT_CHMMR_HELLO, + OK_ENOUGH_ILWRATH, + OK_ENOUGH_GODS, + SEND_MESSAGE, + CAME_FROM, + WHO_BLASTS_WHO, + NO_SURRENDER, + NOT_REASONABLE, + SUBSEQUENT_HOME_HELLO, + GENERAL_INFO, + GOODBYE_AND_DIE, + DECEIVERS, + NO_PEACE, + NO_ALLIANCE, + ILWRATH_BELIEVE, + OK_KILL_THRADDASH, + GOODBYE_GODS, + INIT_HELLO_SPACE, + SUBSEQUENT_HELLO_SPACE_1, + SUBSEQUENT_HELLO_SPACE_2, + SUBSEQUENT_HELLO_SPACE_3, + SUBSEQUENT_HELLO_SPACE_4, + GENERAL_INFO_SPACE_1, + GENERAL_INFO_SPACE_2, + GENERAL_INFO_SPACE_3, + GENERAL_INFO_SPACE_4, + GENERAL_INFO_SPACE_5, + STRENGTH_NOT_ALL, + NO_SLAY_BY_THOUSANDS, + NO_EASE_UP, + GOODBYE_AND_DIE_SPACE, + INIT_HOME_HELLO, + GOODBYE_AND_DIE_HOMEWORLD, + SO_MUCH_TO_KNOW, + LONG_AGO, + KILLED_GOOD_GODS, + CHANNEL_44, + BECAUSE_44, + WHAT_ABOUT_ILWRATH, + ABOUT_PHYSIO, + ABOUT_HISTORY, + ABOUT_CULTURE, + ABOUT_URQUAN, + URQUAN_TOO_NICE, + OF_COURSE_WERE_EVIL, + DONT_CONFUSE_US, + ON_WAY_TO_THRADDASH, + HAPPY_FIGHTING_THRADDASH, + + say_warship, + say_dwe, + say_youboo, + say_dillrat, + enough_orders, + other_divine_orders, + worship_us, + bye_gods, + enough_ilwrath, + enough_gods, + where_you_come_from, + it_will_be_a_pleasure, + be_reasonable, + surrender, + whats_up, + bye, + want_peace, + want_alliance, + go_kill_thraddash, + whats_up_space_1, + whats_up_space_2, + whats_up_space_3, + whats_up_space_4, + whats_up_space_5, + you_are_weak, + slay_by_thousands, + ease_up, + bye_space, + bye_homeworld, + want_info_on_gods, + when_start_worship, + any_good_gods, + how_talk_with_gods, + why_44, + want_info_on_ilwrath, + what_about_physio, + what_about_history, + what_about_culture, + what_about_urquan, + are_you_evil, + but_evil_is_defined, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/melnorm/ifontres.h b/sc2/src/sc2code/comm/melnorm/ifontres.h new file mode 100644 index 000000000..d902a7e90 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/ifontres.h @@ -0,0 +1,3 @@ +#define MELNORME_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/melnorm/igfxres.h b/sc2/src/sc2code/comm/melnorm/igfxres.h new file mode 100644 index 000000000..529c2d5a0 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/igfxres.h @@ -0,0 +1,3 @@ +#define MELNORME_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/melnorm/imusicre.h b/sc2/src/sc2code/comm/melnorm/imusicre.h new file mode 100644 index 000000000..7d18836d6 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/imusicre.h @@ -0,0 +1,3 @@ +#define MELNORME_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/melnorm/istrtab.h b/sc2/src/sc2code/comm/melnorm/istrtab.h new file mode 100644 index 000000000..91d4ecd20 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/istrtab.h @@ -0,0 +1,4 @@ +#define MELNORME_CONVERSATION_PHRASES 0x00200004L +#define MELNORME_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/melnorm/melnorm.c b/sc2/src/sc2code/comm/melnorm/melnorm.c new file mode 100644 index 000000000..041519047 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/melnorm.c @@ -0,0 +1,1763 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/melnorm/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/melnorm/strings.h" + +//Added by Chris + +void DrawCargoStrings (BYTE OldElement, BYTE NewElement); + +//End Added by Chris + +#define NUM_HISTORY_ITEMS 9 +#define NUM_EVENT_ITEMS 8 +#define NUM_ALIEN_RACE_ITEMS 16 +#define NUM_TECH_ITEMS 13 + +static LOCDATA melnorme_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)MELNORME_PMAP_ANIM, /* AlienFrame */ + (FONT)MELNORME_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + MELNORME_COLOR_MAP, /* AlienColorMap */ + MELNORME_MUSIC, /* AlienSong */ + MELNORME_CONVERSATION_PHRASES, /* PlayerPhrases */ + 4, /* NumAnimations */ + { + { + 6, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND * 4, ONE_SECOND * 4,/* RestartRate */ + (1 << 1), /* BlockMask */ + }, + { + 11, /* StartIndex */ + 9, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND * 4, ONE_SECOND * 4,/* RestartRate */ + (1 << 0), /* BlockMask */ + }, + { + 20, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 5, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void DoFirstMeeting (RESPONSE_REF R); + +static COUNT +ShipWorth (void) +{ + BYTE i; + SBYTE crew_pods; + COUNT worth; + + worth = GLOBAL_SIS (NumLanders) + * GLOBAL (ModuleCost[PLANET_LANDER]); + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + if (GLOBAL_SIS (DriveSlots[i]) < EMPTY_SLOT) + worth += GLOBAL (ModuleCost[FUSION_THRUSTER]); + } + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + if (GLOBAL_SIS (JetSlots[i]) < EMPTY_SLOT) + worth += GLOBAL (ModuleCost[TURNING_JETS]); + } + + crew_pods = -(SBYTE)( + (GLOBAL_SIS (CrewEnlisted) + CREW_POD_CAPACITY - 1) + / CREW_POD_CAPACITY + ); + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + BYTE which_module; + + which_module = GLOBAL_SIS (ModuleSlots[i]); + if (which_module < BOMB_MODULE_0 + || which_module != CREW_POD + || ++crew_pods > 0) + { + worth += GLOBAL (ModuleCost[i]); + } + } + + return (worth); +} + +static COUNT rescue_fuel = 0; +static SIS_STATE SIS_copy = +{ + 0, +}; + +static BOOLEAN +StripShip (COUNT fuel_required) +{ + BYTE i, which_module; + SBYTE crew_pods; + + SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 0); + + crew_pods = -(SBYTE)( + (GLOBAL_SIS (CrewEnlisted) + CREW_POD_CAPACITY - 1) + / CREW_POD_CAPACITY + ); + if (fuel_required == 0) + { + GlobData.SIS_state = SIS_copy; + SetSemaphore (&GraphicsSem); + DeltaSISGauges (UNDEFINED_DELTA, rescue_fuel, UNDEFINED_DELTA); + ClearSemaphore (&GraphicsSem); + } + else if (fuel_required == (COUNT)~0) + { + GLOBAL_SIS (NumLanders) = 0; + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + GLOBAL_SIS (DriveSlots[i]) = EMPTY_SLOT + 0; + for (i = 0; i < NUM_JET_SLOTS; ++i) + GLOBAL_SIS (JetSlots[i]) = EMPTY_SLOT + 1; + if (GLOBAL_SIS (FuelOnBoard) > FUEL_RESERVE) + GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; + GLOBAL_SIS (TotalBioMass) = 0; + GLOBAL_SIS (TotalElementMass) = 0; + for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) + GLOBAL_SIS (ElementAmounts[i]) = 0; + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + which_module = GLOBAL_SIS (ModuleSlots[i]); + if (which_module < BOMB_MODULE_0 + && (which_module != CREW_POD + || ++crew_pods > 0)) + GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; + } + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); + ClearSemaphore (&GraphicsSem); + } + else if (fuel_required) + { + SBYTE bays; + BYTE num_searches, beg_mod, end_mod; + COUNT worth, total; + BYTE module_count[BOMB_MODULE_0]; + BYTE slot; + DWORD capacity; + + SIS_copy = GlobData.SIS_state; + for (i = PLANET_LANDER; i < BOMB_MODULE_0; ++i) + module_count[i] = 0; + + capacity = FUEL_RESERVE; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (SIS_copy.ModuleSlots[slot] == FUEL_TANK + || SIS_copy.ModuleSlots[slot] == HIGHEFF_FUELSYS) + { + COUNT volume; + + volume = SIS_copy.ModuleSlots[slot] == FUEL_TANK + ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; + capacity += volume; + } + } while (slot--); + if (fuel_required > capacity) + fuel_required = capacity; + + bays = -(SBYTE)( + (SIS_copy.TotalElementMass + STORAGE_BAY_CAPACITY - 1) + / STORAGE_BAY_CAPACITY + ); + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + which_module = SIS_copy.ModuleSlots[i]; + if (which_module == CREW_POD) + ++crew_pods; + else if (which_module == STORAGE_BAY) + ++bays; + } + + worth = fuel_required / FUEL_TANK_SCALE; + total = 0; + num_searches = 0; + beg_mod = end_mod = (BYTE)~0; + while (total < worth && ShipWorth () && ++num_searches) + { + DWORD rand_val; + + rand_val = Random (); + switch (which_module = LOBYTE (LOWORD (rand_val)) % (CREW_POD + 1)) + { + case PLANET_LANDER: + if (SIS_copy.NumLanders == 0) + continue; + --SIS_copy.NumLanders; + break; + case FUSION_THRUSTER: + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + if (SIS_copy.DriveSlots[i] < EMPTY_SLOT) + break; + } + if (i == NUM_DRIVE_SLOTS) + continue; + SIS_copy.DriveSlots[i] = EMPTY_SLOT + 0; + break; + case TURNING_JETS: + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + if (SIS_copy.JetSlots[i] < EMPTY_SLOT) + break; + } + if (i == NUM_JET_SLOTS) + continue; + SIS_copy.JetSlots[i] = EMPTY_SLOT + 1; + break; + case CREW_POD: + i = HIBYTE (LOWORD (rand_val)) % NUM_MODULE_SLOTS; + if ((which_module = SIS_copy.ModuleSlots[i]) >= EMPTY_SLOT + || which_module == FUEL_TANK + || which_module == HIGHEFF_FUELSYS + || (which_module == STORAGE_BAY + && module_count[STORAGE_BAY] >= bays) + || (which_module == CREW_POD + && module_count[CREW_POD] >= crew_pods)) + continue; + SIS_copy.ModuleSlots[i] = EMPTY_SLOT + 2; + break; + } + + if (beg_mod == (BYTE)~0) + beg_mod = end_mod = which_module; + else if (which_module > end_mod) + end_mod = which_module; + ++module_count[which_module]; + total += GLOBAL (ModuleCost[which_module]); + } + + if (total == 0) + { + NPCPhrase (CHARITY); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, fuel_required, 0); + ClearSemaphore (&GraphicsSem); + return (FALSE); + } + else + { + NPCPhrase (RESCUE_OFFER); + if ((rescue_fuel = fuel_required) == capacity) + NPCPhrase (RESCUE_TANKS); + else + NPCPhrase (RESCUE_HOME); + for (i = PLANET_LANDER; i < BOMB_MODULE_0; ++i) + { + if (module_count[i]) + { + RESPONSE_REF pStr; + + switch (i) + { + case PLANET_LANDER: + pStr = LANDERS; + break; + case FUSION_THRUSTER: + pStr = THRUSTERS; + break; + case TURNING_JETS: + pStr = JETS; + break; + case CREW_POD: + pStr = PODS; + break; + case STORAGE_BAY: + pStr = BAYS; + break; + case DYNAMO_UNIT: + pStr = DYNAMOS; + break; + case SHIVA_FURNACE: + pStr = FURNACES; + break; + case GUN_WEAPON: + pStr = GUNS; + break; + case BLASTER_WEAPON: + pStr = BLASTERS; + break; + case CANNON_WEAPON: + pStr = CANNONS; + break; + case TRACKING_SYSTEM: + pStr = TRACKERS; + break; + case ANTIMISSILE_DEFENSE: + pStr = DEFENSES; + break; + } + + if (i == end_mod && i != beg_mod) + NPCPhrase (END_LIST_WITH_AND); + NPCPhrase (ENUMERATE_ONE + (module_count[i] - 1)); + NPCPhrase (pStr); + } + } + } + } + + return (TRUE); +} + +static void +ExitConversation (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, no_trade_now)) + NPCPhrase (OK_NO_TRADE_NOW_BYE); + else if (PLAYER_SAID (R, youre_on)) + { + NPCPhrase (YOU_GIVE_US_NO_CHOICE); + + SET_GAME_STATE (MELNORME_ANGER, 1); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, so_we_can_attack)) + { + NPCPhrase (DECEITFUL_HUMAN); + + SET_GAME_STATE (MELNORME_ANGER, 2); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, bye_melnorme_slightly_angry)) + NPCPhrase (MELNORME_SLIGHTLY_ANGRY_GOODBYE); + else if (PLAYER_SAID (R, ok_strip_me)) + { + if (ShipWorth () < 4000 / MODULE_COST_SCALE) + /* is ship worth stripping */ + NPCPhrase (NOT_WORTH_STRIPPING); + else + { + SET_GAME_STATE (MELNORME_ANGER, 0); + + StripShip ((COUNT)~0); + NPCPhrase (FAIR_JUSTICE); + } + } + else if (PLAYER_SAID (R, fight_some_more)) + { + NPCPhrase (OK_FIGHT_SOME_MORE); + + SET_GAME_STATE (MELNORME_ANGER, 3); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, bye_melnorme_pissed_off)) + NPCPhrase (MELNORME_PISSED_OFF_GOODBYE); + else if (PLAYER_SAID (R, well_if_thats_the_way_you_feel)) + { + NPCPhrase (WE_FIGHT_AGAIN); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, you_hate_us_so_we_go_away)) + NPCPhrase (HATE_YOU_GOODBYE); + else if (PLAYER_SAID (R, take_it)) + { + StripShip (0); + NPCPhrase (HAPPY_TO_HAVE_RESCUED); + } + else if (PLAYER_SAID (R, leave_it)) + { + SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 1); + NPCPhrase (MAYBE_SEE_YOU_LATER); + } + else if (PLAYER_SAID (R, no_help)) + { + SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 1); + NPCPhrase (GOODBYE_AND_GOODLUCK); + } + else if (PLAYER_SAID (R, no_changed_mind)) + { + NPCPhrase (GOODBYE_AND_GOODLUCK_AGAIN); + } + else if (PLAYER_SAID (R, be_leaving_now) + || PLAYER_SAID (R, goodbye)) + { + NPCPhrase (FRIENDLY_GOODBYE); + } +} + +static void +DoRescue (RESPONSE_REF R) +{ + SIZE dx, dy; + COUNT fuel_required; + + dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) + - SOL_X; + dy = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)) + - SOL_Y; + fuel_required = square_root ( + (DWORD)((long)dx * dx + (long)dy * dy) + ) + (2 * FUEL_TANK_SCALE); + + if (StripShip (fuel_required)) + { + Response (take_it, ExitConversation); + Response (leave_it, ExitConversation); + } +} + +static COUNT +DeltaCredit (SIZE delta_credit) +{ + COUNT Credit; + + Credit = MAKE_WORD ( + GET_GAME_STATE (MELNORME_CREDIT0), + GET_GAME_STATE (MELNORME_CREDIT1) + ); + if ((int)delta_credit >= 0 || ((int)(-delta_credit) <= (int)(Credit))) + { + Credit += delta_credit; + SET_GAME_STATE (MELNORME_CREDIT0, LOBYTE (Credit)); + SET_GAME_STATE (MELNORME_CREDIT1, HIBYTE (Credit)); + SetSemaphore (&GraphicsSem); + DrawStatusMessage ((UNICODE *)~0); + ClearSemaphore (&GraphicsSem); + } + else + { + NPCPhrase (NEED_MORE_CREDIT0); + NPCPhrase (delta_credit); + NPCPhrase (NEED_MORE_CREDIT1); + } + + return (Credit); +} + +static void +CurrentEvents (void) +{ + BYTE stack; + + stack = GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK); + switch (stack++) + { + case 0: + NPCPhrase (OK_BUY_EVENT_1); + break; + case 1: + NPCPhrase (OK_BUY_EVENT_2); + break; + case 2: + NPCPhrase (OK_BUY_EVENT_3); + break; + case 3: + NPCPhrase (OK_BUY_EVENT_4); + break; + case 4: + NPCPhrase (OK_BUY_EVENT_5); + break; + case 5: + NPCPhrase (OK_BUY_EVENT_6); + break; + case 6: + NPCPhrase (OK_BUY_EVENT_7); + break; + case 7: + NPCPhrase (OK_BUY_EVENT_8); + break; + } + SET_GAME_STATE (MELNORME_EVENTS_INFO_STACK, stack); +} + +static void +AlienRaces (void) +{ + BYTE stack; + + stack = GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK); + switch (stack++) + { + case 0: + NPCPhrase (OK_BUY_ALIEN_RACE_1); + break; + case 1: + NPCPhrase (OK_BUY_ALIEN_RACE_2); + break; + case 2: + NPCPhrase (OK_BUY_ALIEN_RACE_3); + break; + case 3: + NPCPhrase (OK_BUY_ALIEN_RACE_4); + break; + case 4: + NPCPhrase (OK_BUY_ALIEN_RACE_5); + break; + case 5: + NPCPhrase (OK_BUY_ALIEN_RACE_6); + break; + case 6: + NPCPhrase (OK_BUY_ALIEN_RACE_7); + break; + case 7: + NPCPhrase (OK_BUY_ALIEN_RACE_8); + break; + case 8: + NPCPhrase (OK_BUY_ALIEN_RACE_9); + break; + case 9: + NPCPhrase (OK_BUY_ALIEN_RACE_10); + break; + case 10: + NPCPhrase (OK_BUY_ALIEN_RACE_11); + break; + case 11: + NPCPhrase (OK_BUY_ALIEN_RACE_12); + break; + case 12: + NPCPhrase (OK_BUY_ALIEN_RACE_13); + break; + case 13: + NPCPhrase (OK_BUY_ALIEN_RACE_14); + if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) + { + SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 1); + SET_GAME_STATE (SPATHI_HOME_VISITS, 7); + } + break; + case 14: + NPCPhrase (OK_BUY_ALIEN_RACE_15); + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) + { + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); + } + SET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1); + break; + case 15: + NPCPhrase (OK_BUY_ALIEN_RACE_16); + break; + } + SET_GAME_STATE (MELNORME_ALIEN_INFO_STACK, stack); +} + +static void +History (void) +{ + BYTE stack; + + stack = GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK); + switch (stack++) + { + case 0: + NPCPhrase (OK_BUY_HISTORY_1); + break; + case 1: + NPCPhrase (OK_BUY_HISTORY_2); + break; + case 2: + NPCPhrase (OK_BUY_HISTORY_3); + break; + case 3: + NPCPhrase (OK_BUY_HISTORY_4); + break; + case 4: + NPCPhrase (OK_BUY_HISTORY_5); + break; + case 5: + NPCPhrase (OK_BUY_HISTORY_6); + break; + case 6: + NPCPhrase (OK_BUY_HISTORY_7); + break; + case 7: + NPCPhrase (OK_BUY_HISTORY_8); + break; + case 8: + NPCPhrase (OK_BUY_HISTORY_9); + break; + } + SET_GAME_STATE (MELNORME_HISTORY_INFO_STACK, stack); +} + +static void NatureOfConversation (RESPONSE_REF R); + +static BYTE AskedToBuy; + +static void +DoBuy (RESPONSE_REF R) +{ + COUNT credit; + SIZE needed_credit; + BYTE slot; + DWORD capacity; + + credit = MAKE_WORD ( + GET_GAME_STATE (MELNORME_CREDIT0), + GET_GAME_STATE (MELNORME_CREDIT1) + ); + + capacity = FUEL_RESERVE; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) + { + COUNT volume; + + volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; + capacity += volume; + } + } while (slot--); + + if (credit == 0) + { + AskedToBuy = TRUE; + NPCPhrase (NEED_CREDIT); + + NatureOfConversation (R); + } + else if (PLAYER_SAID (R, buy_fuel) + || PLAYER_SAID (R, buy_1_fuel) + || PLAYER_SAID (R, buy_5_fuel) + || PLAYER_SAID (R, buy_10_fuel) + || PLAYER_SAID (R, buy_25_fuel) + || PLAYER_SAID (R, fill_me_up)) + { + needed_credit = 0; + if (PLAYER_SAID (R, buy_1_fuel)) + needed_credit = 1; + else if (PLAYER_SAID (R, buy_5_fuel)) + needed_credit = 5; + else if (PLAYER_SAID (R, buy_10_fuel)) + needed_credit = 10; + else if (PLAYER_SAID (R, buy_25_fuel)) + needed_credit = 25; + else if (PLAYER_SAID (R, fill_me_up)) + needed_credit = (COUNT)~0; + + if (needed_credit == 0) + { + if (!GET_GAME_STATE (MELNORME_FUEL_PROCEDURE)) + { + NPCPhrase (BUY_FUEL_INTRO); + SET_GAME_STATE (MELNORME_FUEL_PROCEDURE, 1); + } + } + else + { + if (needed_credit == (COUNT)~0 + && (needed_credit = (capacity / FUEL_TANK_SCALE) + - (GLOBAL_SIS (FuelOnBoard) + / FUEL_TANK_SCALE)) == 0) + needed_credit = 1; + + if (GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE + + needed_credit > capacity / FUEL_TANK_SCALE) + { + NPCPhrase (NO_ROOM_FOR_FUEL); + goto TryFuelAgain; + } + + if ((int)(needed_credit * (BIO_CREDIT_VALUE / 2)) <= (int)credit) + { + DWORD f; + + NPCPhrase (GOT_FUEL); + + f = (DWORD)needed_credit * FUEL_TANK_SCALE; + SetSemaphore (&GraphicsSem); + while (f > 0x3FFFL) + { + DeltaSISGauges (0, 0x3FFF, 0); + f -= 0x3FFF; + } + DeltaSISGauges (0, (SIZE)f, 0); + ClearSemaphore (&GraphicsSem); + } + needed_credit *= (BIO_CREDIT_VALUE / 2); + } + if (needed_credit) + { + DeltaCredit (-needed_credit); + if (GLOBAL_SIS (FuelOnBoard) >= capacity) + goto BuyBuyBuy; + } +TryFuelAgain: + NPCPhrase (HOW_MUCH_FUEL); + + Response (buy_1_fuel, DoBuy); + Response (buy_5_fuel, DoBuy); + Response (buy_10_fuel, DoBuy); + Response (buy_25_fuel, DoBuy); + Response (fill_me_up, DoBuy); + Response (done_buying_fuel, DoBuy); + } + else if (PLAYER_SAID (R, buy_technology) + || PLAYER_SAID (R, buy_new_tech)) + { + BYTE stack; + + needed_credit = 0; + if (PLAYER_SAID (R, buy_technology)) + { + if (!GET_GAME_STATE (MELNORME_TECH_PROCEDURE)) + { + NPCPhrase (BUY_NEW_TECH_INTRO); + SET_GAME_STATE (MELNORME_TECH_PROCEDURE, 1); + } + stack = 0; + } + else + { + RESPONSE_REF pStr; + + stack = GET_GAME_STATE (MELNORME_TECH_STACK); + switch (stack) + { + case 0: + pStr = OK_BUY_NEW_TECH_1; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 1: + pStr = OK_BUY_NEW_TECH_2; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 2: + pStr = OK_BUY_NEW_TECH_3; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 3: + pStr = OK_BUY_NEW_TECH_4; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 4: + pStr = OK_BUY_NEW_TECH_5; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 5: + pStr = OK_BUY_NEW_TECH_6; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 6: + pStr = OK_BUY_NEW_TECH_7; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 7: + pStr = OK_BUY_NEW_TECH_8; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 8: + pStr = OK_BUY_NEW_TECH_9; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 9: + pStr = OK_BUY_NEW_TECH_10; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 10: + pStr = OK_BUY_NEW_TECH_11; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 11: + pStr = OK_BUY_NEW_TECH_12; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + case 12: + pStr = OK_BUY_NEW_TECH_13; + needed_credit = 75 * BIO_CREDIT_VALUE; + break; + } + if ((int)needed_credit > (int)credit) + { + DeltaCredit (-needed_credit); + goto BuyBuyBuy; + } + else + { + ++stack; + NPCPhrase (pStr); + DeltaCredit (-needed_credit); + } + } + + switch (stack) + { + case 0: + if (GLOBAL (ModuleCost[BLASTER_WEAPON]) == 0) + { + NPCPhrase (NEW_TECH_1); + break; + } + ++stack; + case 1: + GLOBAL (ModuleCost[BLASTER_WEAPON]) = + 4000 / MODULE_COST_SCALE; + if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) + { + NPCPhrase (NEW_TECH_2); + break; + } + ++stack; + case 2: + SET_GAME_STATE (IMPROVED_LANDER_SPEED, 1); + if (GLOBAL (ModuleCost[ANTIMISSILE_DEFENSE]) == 0) + { + NPCPhrase (NEW_TECH_3); + break; + } + ++stack; + case 3: + GLOBAL (ModuleCost[ANTIMISSILE_DEFENSE]) = + 4000 / MODULE_COST_SCALE; + if (!(GET_GAME_STATE (LANDER_SHIELDS) + & (1 << BIOLOGICAL_DISASTER))) + { + NPCPhrase (NEW_TECH_4); + break; + } + ++stack; + case 4: + credit = GET_GAME_STATE (LANDER_SHIELDS) + | (1 << BIOLOGICAL_DISASTER); + SET_GAME_STATE (LANDER_SHIELDS, credit); + if (!GET_GAME_STATE (IMPROVED_LANDER_CARGO)) + { + NPCPhrase (NEW_TECH_5); + break; + } + ++stack; + case 5: + SET_GAME_STATE (IMPROVED_LANDER_CARGO, 1); + if (GLOBAL (ModuleCost[HIGHEFF_FUELSYS]) == 0) + { + NPCPhrase (NEW_TECH_6); + break; + } + ++stack; + case 6: + GLOBAL (ModuleCost[HIGHEFF_FUELSYS]) = + 1000 / MODULE_COST_SCALE; + if (!GET_GAME_STATE (IMPROVED_LANDER_SHOT)) + { + NPCPhrase (NEW_TECH_7); + break; + } + ++stack; + case 7: + SET_GAME_STATE (IMPROVED_LANDER_SHOT, 1); + if (!(GET_GAME_STATE (LANDER_SHIELDS) + & (1 << EARTHQUAKE_DISASTER))) + { + NPCPhrase (NEW_TECH_8); + break; + } + ++stack; + case 8: + credit = GET_GAME_STATE (LANDER_SHIELDS) + | (1 << EARTHQUAKE_DISASTER); + SET_GAME_STATE (LANDER_SHIELDS, credit); + if (GLOBAL (ModuleCost[TRACKING_SYSTEM]) == 0) + { + NPCPhrase (NEW_TECH_9); + break; + } + ++stack; + case 9: + GLOBAL (ModuleCost[TRACKING_SYSTEM]) = + 5000 / MODULE_COST_SCALE; + if (!(GET_GAME_STATE (LANDER_SHIELDS) + & (1 << LIGHTNING_DISASTER))) + { + NPCPhrase (NEW_TECH_10); + break; + } + ++stack; + case 10: + credit = GET_GAME_STATE (LANDER_SHIELDS) + | (1 << LIGHTNING_DISASTER); + SET_GAME_STATE (LANDER_SHIELDS, credit); + if (!(GET_GAME_STATE (LANDER_SHIELDS) + & (1 << LAVASPOT_DISASTER))) + { + NPCPhrase (NEW_TECH_11); + break; + } + ++stack; + case 11: + credit = GET_GAME_STATE (LANDER_SHIELDS) + | (1 << LAVASPOT_DISASTER); + SET_GAME_STATE (LANDER_SHIELDS, credit); + if (GLOBAL (ModuleCost[CANNON_WEAPON]) == 0) + { + NPCPhrase (NEW_TECH_12); + break; + } + ++stack; + case 12: + GLOBAL (ModuleCost[CANNON_WEAPON]) = + 6000 / MODULE_COST_SCALE; + if (GLOBAL (ModuleCost[SHIVA_FURNACE]) == 0) + { + NPCPhrase (NEW_TECH_13); + break; + } + ++stack; + case 13: + GLOBAL (ModuleCost[SHIVA_FURNACE]) = + 4000 / MODULE_COST_SCALE; + NPCPhrase (NEW_TECH_ALL_GONE); + SET_GAME_STATE (MELNORME_TECH_STACK, stack); + goto BuyBuyBuy; + } + SET_GAME_STATE (MELNORME_TECH_STACK, stack); + + Response (buy_new_tech, DoBuy); + Response (no_buy_new_tech, DoBuy); + } + else if (PLAYER_SAID (R, buy_info) + || PLAYER_SAID (R, buy_current_events) + || PLAYER_SAID (R, buy_alien_races) + || PLAYER_SAID (R, buy_history)) + { + needed_credit = 0; + if (PLAYER_SAID (R, buy_info)) + { + if (GET_GAME_STATE (MELNORME_INFO_PROCEDURE)) + NPCPhrase (OK_BUY_INFO); + else + { + NPCPhrase (BUY_INFO_INTRO); + SET_GAME_STATE (MELNORME_INFO_PROCEDURE, 1); + } + } + else + { +#define INFO_COST 75 + needed_credit = INFO_COST; + if ((int)credit >= (int)needed_credit) + { + if (PLAYER_SAID (R, buy_current_events)) + CurrentEvents (); + else if (PLAYER_SAID (R, buy_alien_races)) + AlienRaces (); + else /* if (R == buy_history) */ + History (); + } + + DeltaCredit (-needed_credit); + if (GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS + || GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS + || GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS) + { + } + else + { + NPCPhrase (INFO_ALL_GONE); + goto BuyBuyBuy; + } + } + + if (GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS) + Response (buy_current_events, DoBuy); + if (GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS) + Response (buy_alien_races, DoBuy); + if (GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS) + Response (buy_history, DoBuy); + Response (done_buying_info, DoBuy); + } + else + { + if (PLAYER_SAID (R, done_buying_fuel)) + NPCPhrase (OK_DONE_BUYING_FUEL); + else if (PLAYER_SAID (R, no_buy_new_tech)) + NPCPhrase (OK_NO_BUY_NEW_TECH); + else if (PLAYER_SAID (R, done_buying_info)) + NPCPhrase (OK_DONE_BUYING_INFO); + else + NPCPhrase (WHAT_TO_BUY); + +BuyBuyBuy: + if (GLOBAL_SIS (FuelOnBoard) < capacity) + Response (buy_fuel, DoBuy); + if (GET_GAME_STATE (MELNORME_TECH_STACK) < NUM_TECH_ITEMS) + Response (buy_technology, DoBuy); + if (GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS + || GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS + || GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS) + Response (buy_info, DoBuy); + Response (done_buying, NatureOfConversation); + Response (be_leaving_now, ExitConversation); + } +} + +static void +DoSell (RESPONSE_REF R) +{ + BYTE num_new_rainbows; + UWORD rainbow_mask; + SIZE added_credit; + + rainbow_mask = MAKE_WORD ( + GET_GAME_STATE (RAINBOW_WORLD0), + GET_GAME_STATE (RAINBOW_WORLD1) + ); + num_new_rainbows = (BYTE)(-GET_GAME_STATE (MELNORME_RAINBOW_COUNT)); + while (rainbow_mask) + { + if (rainbow_mask & 1) + ++num_new_rainbows; + + rainbow_mask >>= 1; + } + + if (!PLAYER_SAID (R, sell)) + { + if (PLAYER_SAID (R, sell_life_data)) + { + DWORD TimeIn; + + added_credit = GLOBAL_SIS (TotalBioMass) * BIO_CREDIT_VALUE; + + NPCPhrase (SOLD_LIFE_DATA1); + NPCPhrase (-(int)GLOBAL_SIS (TotalBioMass)); + NPCPhrase (SOLD_LIFE_DATA2); + NPCPhrase (-(int)added_credit); + NPCPhrase (SOLD_LIFE_DATA3); + AlienTalkSegue ((COUNT)~0); + + DrawCargoStrings ((BYTE)~0, (BYTE)~0); + TimeIn = SleepTask (GetTimeCounter () + (ONE_SECOND / 2)); + DrawCargoStrings ( + (BYTE)NUM_ELEMENT_CATEGORIES, + (BYTE)NUM_ELEMENT_CATEGORIES + ); + do + { + TimeIn = TaskSwitch (); + if (AnyButtonPress (TRUE)) + { + DeltaCredit (GLOBAL_SIS (TotalBioMass) * BIO_CREDIT_VALUE); + GLOBAL_SIS (TotalBioMass) = 0; + } + else + { + --GLOBAL_SIS (TotalBioMass); + DeltaCredit (BIO_CREDIT_VALUE); + } + DrawCargoStrings ( + (BYTE)NUM_ELEMENT_CATEGORIES, + (BYTE)NUM_ELEMENT_CATEGORIES + ); + } while (GLOBAL_SIS (TotalBioMass)); + SleepTask (GetTimeCounter () + (ONE_SECOND / 2)); + + SetSemaphore (&GraphicsSem); + ClearSISRect (DRAW_SIS_DISPLAY); + ClearSemaphore (&GraphicsSem); + } + else /* if (R == sell_rainbow_locations) */ + { + added_credit = num_new_rainbows * (250 * BIO_CREDIT_VALUE); + + NPCPhrase (SOLD_RAINBOW_LOCATIONS1); + NPCPhrase (-(int)num_new_rainbows); + NPCPhrase (SOLD_RAINBOW_LOCATIONS2); + NPCPhrase (-(int)added_credit); + NPCPhrase (SOLD_RAINBOW_LOCATIONS3); + + num_new_rainbows += GET_GAME_STATE (MELNORME_RAINBOW_COUNT); + SET_GAME_STATE (MELNORME_RAINBOW_COUNT, num_new_rainbows); + num_new_rainbows = 0; + + DeltaCredit (added_credit); + } + + AskedToBuy = FALSE; + } + + if (GLOBAL_SIS (TotalBioMass) || num_new_rainbows) + { + NPCPhrase (WHAT_TO_SELL); + + if (GLOBAL_SIS (TotalBioMass)) + Response (sell_life_data, DoSell); + if (num_new_rainbows) + Response (sell_rainbow_locations, DoSell); + Response (done_selling, NatureOfConversation); + } + else + { + if (PLAYER_SAID (R, sell)) + NPCPhrase (NOTHING_TO_SELL); + DISABLE_PHRASE (sell); + + NatureOfConversation (R); + } +} + +static void +NatureOfConversation (RESPONSE_REF R) +{ + BYTE num_new_rainbows; + UWORD rainbow_mask; + COUNT Credit; + + if (PLAYER_SAID (R, get_on_with_business)) + { + SET_GAME_STATE (MELNORME_YACK_STACK2, 5); + R = 0; + } + + Credit = DeltaCredit (0); + if (R == 0) + { + BYTE stack; + + stack = (BYTE)(GET_GAME_STATE (MELNORME_YACK_STACK2) - 5); + switch (stack++) + { + case 0: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_1); + break; + case 1: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_2); + break; + case 2: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_3); + break; + case 3: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_4); + break; + case 4: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_5); + break; + case 5: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_6); + break; + case 6: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_7); + break; + case 7: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_8); + break; + case 8: + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_9); + break; + default: + --stack; + NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_10); + break; + } + SET_GAME_STATE (MELNORME_YACK_STACK2, stack + 5); + } + + rainbow_mask = MAKE_WORD ( + GET_GAME_STATE (RAINBOW_WORLD0), + GET_GAME_STATE (RAINBOW_WORLD1) + ); + num_new_rainbows = (BYTE)(-GET_GAME_STATE (MELNORME_RAINBOW_COUNT)); + while (rainbow_mask) + { + if (rainbow_mask & 1) + ++num_new_rainbows; + + rainbow_mask >>= 1; + } + + if (GLOBAL_SIS (FuelOnBoard) > 0 + || GLOBAL_SIS (TotalBioMass) + || Credit + || num_new_rainbows) + { + if (!GET_GAME_STATE (TRADED_WITH_MELNORME)) + { + SET_GAME_STATE (TRADED_WITH_MELNORME, 1); + + NPCPhrase (TRADING_INFO); + } + + if (R == 0) + { + /* Melnorme reports any news and turns purple */ + NPCPhrase (BUY_OR_SELL); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND / 2); + } + else if (PLAYER_SAID (R, why_turned_purple)) + { + SET_GAME_STATE (WHY_MELNORME_PURPLE, 1) + + NPCPhrase (TURNED_PURPLE_BECAUSE); + } + else if (PLAYER_SAID (R, done_selling)) + { + NPCPhrase (OK_DONE_SELLING); + } + else if (PLAYER_SAID (R, done_buying)) + { + NPCPhrase (OK_DONE_BUYING); + } + + if (!GET_GAME_STATE (WHY_MELNORME_PURPLE)) + { + Response (why_turned_purple, NatureOfConversation); + } + if (!AskedToBuy) + Response (buy, DoBuy); + if (PHRASE_ENABLED (sell)) + Response (sell, DoSell); + Response (goodbye, ExitConversation); + } + else /* needs to be rescued */ + { + if (GET_GAME_STATE (MELNORME_RESCUE_REFUSED)) + { + NPCPhrase (CHANGED_MIND); + + Response (yes_changed_mind, DoRescue); + Response (no_changed_mind, ExitConversation); + } + else + { + BYTE num_rescues; + + num_rescues = GET_GAME_STATE (MELNORME_RESCUE_COUNT); + switch (num_rescues) + { + case 0: + NPCPhrase (RESCUE_EXPLANATION); + break; + case 1: + NPCPhrase (RESCUE_AGAIN_1); + break; + case 2: + NPCPhrase (RESCUE_AGAIN_2); + break; + case 3: + NPCPhrase (RESCUE_AGAIN_3); + break; + case 4: + NPCPhrase (RESCUE_AGAIN_4); + break; + case 5: + NPCPhrase (RESCUE_AGAIN_5); + break; + } + + if (num_rescues < 5) + { + ++num_rescues; + SET_GAME_STATE (MELNORME_RESCUE_COUNT, num_rescues); + } + + NPCPhrase (SHOULD_WE_HELP_YOU); + + Response (yes_help, DoRescue); + Response (no_help, ExitConversation); + } + } +} + +static void +DoBluster (RESPONSE_REF R) +{ + static BYTE local_stack0 = 0, local_stack1 = 0; + + if (PLAYER_SAID (R, trade_is_for_the_weak)) + { + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 2) + ), ONE_SECOND / 2); + + SET_GAME_STATE (MELNORME_YACK_STACK2, 4); + NPCPhrase (WERE_NOT_AFRAID); + } + else if (PLAYER_SAID (R, why_blue_light)) + { + SET_GAME_STATE (WHY_MELNORME_BLUE, 1); + + NPCPhrase (BLUE_IS_MAD); + } + else if (PLAYER_SAID (R, we_strong_1)) + { + local_stack0 = 1; + NPCPhrase (YOU_NOT_STRONG_1); + } + else if (PLAYER_SAID (R, we_strong_2)) + { + local_stack0 = 2; + NPCPhrase (YOU_NOT_STRONG_2); + } + else if (PLAYER_SAID (R, we_strong_3)) + { + local_stack0 = 3; + NPCPhrase (YOU_NOT_STRONG_3); + } + else if (PLAYER_SAID (R, just_testing)) + { + local_stack1 = 1; + NPCPhrase (REALLY_TESTING); + } + + if (!GET_GAME_STATE (WHY_MELNORME_BLUE)) + Response (why_blue_light, DoBluster); + switch (local_stack0) + { + case 0: + Response (we_strong_1, DoBluster); + break; + case 1: + Response (we_strong_2, DoBluster); + break; + case 2: + Response (we_strong_3, DoBluster); + break; + } + switch (local_stack1) + { + case 0: + Response (just_testing, DoBluster); + break; + case 1: + { + Response (yes_really_testing, DoFirstMeeting); + break; + } + } + Response (youre_on, ExitConversation); +} + +static void +yack0_respond (void) +{ + + switch (GET_GAME_STATE (MELNORME_YACK_STACK0)) + { + case 0: + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + we_are_from_alliance0, + (vararg_dcl)buf, + (RESPONSE_REF)-1 + ); + DoResponsePhrase (we_are_from_alliance0, DoFirstMeeting, shared_phrase_buf); + break; + } + case 1: + Response (how_know, DoFirstMeeting); + break; + } +} + +static void +yack1_respond (void) +{ + switch (GET_GAME_STATE (MELNORME_YACK_STACK1)) + { + case 0: + Response (what_about_yourselves, DoFirstMeeting); + break; + case 1: + Response (what_factors, DoFirstMeeting); + case 2: + Response (get_on_with_business, NatureOfConversation); + break; + } +} + +static void +yack2_respond (void) +{ + switch (GET_GAME_STATE (MELNORME_YACK_STACK2)) + { + case 0: + Response (what_about_universe, DoFirstMeeting); + break; + case 1: + Response (giving_is_good_1, DoFirstMeeting); + break; + case 2: + Response (giving_is_good_2, DoFirstMeeting); + break; + case 3: + Response (trade_is_for_the_weak, DoBluster); + break; + } +} + +static void +DoFirstMeeting (RESPONSE_REF R) +{ + BYTE last_stack = 0; + PVOIDFUNC temp_func, stack_func[] = + { + yack0_respond, + yack1_respond, + yack2_respond, + }; + + if (R == 0) + { + BYTE business_count; + + business_count = GET_GAME_STATE (MELNORME_BUSINESS_COUNT); + switch (business_count++) + { + case 0: + NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_1); + break; + case 1: + NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_2); + break; + case 2: + NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_3); + --business_count; + break; + } + SET_GAME_STATE (MELNORME_BUSINESS_COUNT, business_count); + } + else if (PLAYER_SAID (R, we_are_from_alliance0)) + { + SET_GAME_STATE (MELNORME_YACK_STACK0, 1); + NPCPhrase (KNOW_OF_YOU); + } + else if (PLAYER_SAID (R, how_know)) + { + SET_GAME_STATE (MELNORME_YACK_STACK0, 2); + NPCPhrase (KNOW_BECAUSE); + } + else if (PLAYER_SAID (R, what_about_yourselves)) + { + last_stack = 1; + SET_GAME_STATE (MELNORME_YACK_STACK1, 1); + NPCPhrase (NO_TALK_ABOUT_OURSELVES); + } + else if (PLAYER_SAID (R, what_factors)) + { + last_stack = 1; + SET_GAME_STATE (MELNORME_YACK_STACK1, 2); + NPCPhrase (FACTORS_ARE); + } + else if (PLAYER_SAID (R, what_about_universe)) + { + last_stack = 2; + SET_GAME_STATE (MELNORME_YACK_STACK2, 1); + NPCPhrase (NO_FREE_LUNCH); + } + else if (PLAYER_SAID (R, giving_is_good_1)) + { + last_stack = 2; + SET_GAME_STATE (MELNORME_YACK_STACK2, 2); + NPCPhrase (GIVING_IS_BAD_1); + } + else if (PLAYER_SAID (R, giving_is_good_2)) + { + last_stack = 2; + SET_GAME_STATE (MELNORME_YACK_STACK2, 3); + NPCPhrase (GIVING_IS_BAD_2); + } + else if (PLAYER_SAID (R, yes_really_testing)) + { + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), ONE_SECOND / 2); + + NPCPhrase (TEST_RESULTS); + } + else if (PLAYER_SAID (R, we_apologize)) + { + SET_GAME_STATE (MELNORME_ANGER, 0); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), ONE_SECOND / 2); + + NPCPhrase (APOLOGY_ACCEPTED); + } + + temp_func = stack_func[0]; + stack_func[0] = stack_func[last_stack]; + stack_func[last_stack] = temp_func; + (*stack_func[0]) (); + (*stack_func[1]) (); + (*stack_func[2]) (); + Response (no_trade_now, ExitConversation); +} + +static void +DoMelnormeMiffed (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE miffed_count; + + miffed_count = GET_GAME_STATE (MELNORME_MIFFED_COUNT); + switch (miffed_count++) + { + case 0: + NPCPhrase (HELLO_SLIGHTLY_ANGRY_1); + break; + case 1: + NPCPhrase (HELLO_SLIGHTLY_ANGRY_2); + break; + default: + --miffed_count; + NPCPhrase (HELLO_SLIGHTLY_ANGRY_3); + break; + } + SET_GAME_STATE (MELNORME_MIFFED_COUNT, miffed_count); + + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 2) + ), ONE_SECOND / 2); + } + else if (PLAYER_SAID (R, explore_relationship)) + { + SET_GAME_STATE (MELNORME_YACK_STACK3, 1); + + NPCPhrase (EXAMPLE_OF_RELATIONSHIP); + } + else if (PLAYER_SAID (R, excuse_1)) + { + SET_GAME_STATE (MELNORME_YACK_STACK3, 2); + + NPCPhrase (NO_EXCUSE_1); + } + else if (PLAYER_SAID (R, excuse_2)) + { + SET_GAME_STATE (MELNORME_YACK_STACK3, 3); + + NPCPhrase (NO_EXCUSE_2); + } + else if (PLAYER_SAID (R, excuse_3)) + { + SET_GAME_STATE (MELNORME_YACK_STACK3, 4); + + NPCPhrase (NO_EXCUSE_3); + } + + switch (GET_GAME_STATE (MELNORME_YACK_STACK3)) + { + case 0: + Response (explore_relationship, DoMelnormeMiffed); + break; + case 1: + Response (excuse_1, DoMelnormeMiffed); + break; + case 2: + Response (excuse_2, DoMelnormeMiffed); + break; + case 3: + Response (excuse_3, DoMelnormeMiffed); + break; + } + Response (we_apologize, DoFirstMeeting); + Response (so_we_can_attack, ExitConversation); + Response (bye_melnorme_slightly_angry, ExitConversation); +} + +static void +DoMelnormePissed (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE pissed_count; + + pissed_count = GET_GAME_STATE (MELNORME_PISSED_COUNT); + switch (pissed_count++) + { + case 0: + NPCPhrase (HELLO_PISSED_OFF_1); + break; + case 1: + NPCPhrase (HELLO_PISSED_OFF_2); + break; + default: + --pissed_count; + NPCPhrase (HELLO_PISSED_OFF_3); + break; + } + SET_GAME_STATE (MELNORME_PISSED_COUNT, pissed_count); + + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 2) + ), ONE_SECOND / 2); + } + else if (PLAYER_SAID (R, beg_forgiveness)) + { + SET_GAME_STATE (MELNORME_YACK_STACK4, 1); + + NPCPhrase (LOTS_TO_MAKE_UP_FOR); + } + else if (PLAYER_SAID (R, you_are_so_right)) + { + SET_GAME_STATE (MELNORME_YACK_STACK4, 2); + + NPCPhrase (ONE_LAST_CHANCE); + } + + switch (GET_GAME_STATE (MELNORME_YACK_STACK4)) + { + case 0: + Response (beg_forgiveness, DoMelnormePissed); + break; + case 1: + Response (you_are_so_right, DoMelnormePissed); + break; + case 2: + Response (ok_strip_me, ExitConversation); + break; + } + Response (fight_some_more, ExitConversation); + Response (bye_melnorme_pissed_off, ExitConversation); +} + +static void +DoMelnormeHate (RESPONSE_REF R) +{ + BYTE hate_count; + + hate_count = GET_GAME_STATE (MELNORME_HATE_COUNT); + switch (hate_count++) + { + case 0: + NPCPhrase (HELLO_HATE_YOU_1); + break; + case 1: + NPCPhrase (HELLO_HATE_YOU_2); + break; + default: + --hate_count; + NPCPhrase (HELLO_HATE_YOU_3); + break; + } + SET_GAME_STATE (MELNORME_HATE_COUNT, hate_count); + + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 2) + ), ONE_SECOND / 2); + + Response (well_if_thats_the_way_you_feel, ExitConversation); + Response (you_hate_us_so_we_go_away, ExitConversation); +} + +static void +Intro (void) +{ + if (GET_GAME_STATE (MET_MELNORME) == 0) + { + SET_GAME_STATE (MET_MELNORME, 1); + DoFirstMeeting (0); + } + else + { + switch (GET_GAME_STATE (MELNORME_ANGER)) + { + case 0: + if (GET_GAME_STATE (MELNORME_YACK_STACK2) <= 5) + DoFirstMeeting (0); + else + NatureOfConversation (0); + break; + case 1: + DoMelnormeMiffed (0); + break; + case 2: + DoMelnormePissed (0); + break; + default: + DoMelnormeHate (0); + break; + } + } +} + +static COUNT +uninit_melnorme (void) +{ + SetSemaphore (&GraphicsSem); + DrawStatusMessage (0); + ClearSemaphore (&GraphicsSem); + + return (0); +} + +LOCDATAPTR +init_melnorme_comm (void) +{ + LOCDATAPTR retval; + + melnorme_desc.init_encounter_func = Intro; + melnorme_desc.uninit_encounter_func = uninit_melnorme; + + melnorme_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + melnorme_desc.AlienTextTemplate.baseline.y = 0; + melnorme_desc.AlienTextTemplate.align = ALIGN_CENTER; + melnorme_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + AskedToBuy = FALSE; + retval = &melnorme_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/melnorm/melnorm.res b/sc2/src/sc2code/comm/melnorm/melnorm.res new file mode 100644 index 000000000..4286f3a60 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/melnorm.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/melnorm + +PACKAGE MELNORME_PACKAGE melnorm.con + GFXRES MELNORME_PMAP_ANIM melnorm.ani + FONTRES MELNORME_FONT melnorm.fon + MUSICRES MELNORME_MUSIC melnorm.mod + STRTAB MELNORME_CONVERSATION_PHRASES melnorm.txt + STRTAB MELNORME_COLOR_MAP melnorm.ct diff --git a/sc2/src/sc2code/comm/melnorm/resinst.h b/sc2/src/sc2code/comm/melnorm/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/melnorm/respkg.h b/sc2/src/sc2code/comm/melnorm/respkg.h new file mode 100644 index 000000000..94c3a3ecc --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/respkg.h @@ -0,0 +1,5 @@ +enum +{ + MELNORME_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/melnorm/restypes.h b/sc2/src/sc2code/comm/melnorm/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/melnorm/strings.h b/sc2/src/sc2code/comm/melnorm/strings.h new file mode 100644 index 000000000..911212e6e --- /dev/null +++ b/sc2/src/sc2code/comm/melnorm/strings.h @@ -0,0 +1,280 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HELLO_NOW_DOWN_TO_BUSINESS_1, + HELLO_NOW_DOWN_TO_BUSINESS_2, + HELLO_NOW_DOWN_TO_BUSINESS_3, + KNOW_OF_YOU, + how_know, + KNOW_BECAUSE, + what_about_yourselves, + NO_TALK_ABOUT_OURSELVES, + what_factors, + FACTORS_ARE, + what_about_universe, + NO_FREE_LUNCH, + giving_is_good_1, + GIVING_IS_BAD_1, + giving_is_good_2, + GIVING_IS_BAD_2, + get_on_with_business, + trade_is_for_the_weak, + WERE_NOT_AFRAID, + no_trade_now, + OK_NO_TRADE_NOW_BYE, + HELLO_AND_DOWN_TO_BUSINESS_1, + HELLO_AND_DOWN_TO_BUSINESS_2, + HELLO_AND_DOWN_TO_BUSINESS_3, + HELLO_AND_DOWN_TO_BUSINESS_4, + HELLO_AND_DOWN_TO_BUSINESS_5, + HELLO_AND_DOWN_TO_BUSINESS_6, + HELLO_AND_DOWN_TO_BUSINESS_7, + HELLO_AND_DOWN_TO_BUSINESS_8, + HELLO_AND_DOWN_TO_BUSINESS_9, + HELLO_AND_DOWN_TO_BUSINESS_10, + whats_my_credit, + HELLO_SLIGHTLY_ANGRY_1, + HELLO_SLIGHTLY_ANGRY_2, + HELLO_SLIGHTLY_ANGRY_3, + explore_relationship, + EXAMPLE_OF_RELATIONSHIP, + excuse_1, + NO_EXCUSE_1, + excuse_2, + NO_EXCUSE_2, + excuse_3, + NO_EXCUSE_3, + we_apologize, + APOLOGY_ACCEPTED, + so_we_can_attack, + DECEITFUL_HUMAN, + bye_melnorme_slightly_angry, + MELNORME_SLIGHTLY_ANGRY_GOODBYE, + HELLO_HATE_YOU_1, + HELLO_HATE_YOU_2, + HELLO_HATE_YOU_3, + well_if_thats_the_way_you_feel, + you_hate_us_so_we_go_away, + HATE_YOU_GOODBYE, + WE_FIGHT_AGAIN, + RESCUE_EXPLANATION, + RESCUE_AGAIN_1, + RESCUE_AGAIN_2, + RESCUE_AGAIN_3, + RESCUE_AGAIN_4, + RESCUE_AGAIN_5, + CHANGED_MIND, + no_changed_mind, + yes_changed_mind, + SHOULD_WE_HELP_YOU, + yes_help, + no_help, + RESCUE_OFFER, + RESCUE_TANKS, + RESCUE_HOME, + take_it, + leave_it, + HAPPY_TO_HAVE_RESCUED, + MAYBE_SEE_YOU_LATER, + GOODBYE_AND_GOODLUCK, + GOODBYE_AND_GOODLUCK_AGAIN, + HELLO_PISSED_OFF_1, + HELLO_PISSED_OFF_2, + HELLO_PISSED_OFF_3, + beg_forgiveness, + LOTS_TO_MAKE_UP_FOR, + you_are_so_right, + ONE_LAST_CHANCE, + ok_strip_me, + no_strip_now, + NOT_WORTH_STRIPPING, + FAIR_JUSTICE, + bye_melnorme_pissed_off, + MELNORME_PISSED_OFF_GOODBYE, + fight_some_more, + OK_FIGHT_SOME_MORE, + why_blue_light, + BLUE_IS_MAD, + we_strong_1, + YOU_NOT_STRONG_1, + we_strong_2, + YOU_NOT_STRONG_2, + we_strong_3, + YOU_NOT_STRONG_3, + just_testing, + REALLY_TESTING, + yes_really_testing, + TEST_RESULTS, + youre_on, + YOU_GIVE_US_NO_CHOICE, + TRADING_INFO, + BUY_OR_SELL, + goodbye, + why_turned_purple, + buy, + sell, + TURNED_PURPLE_BECAUSE, + NOTHING_TO_SELL, + WHAT_TO_SELL, + OK_DONE_SELLING, + sell_life_data, + SOLD_LIFE_DATA1, + SOLD_LIFE_DATA2, + SOLD_LIFE_DATA3, + sell_rainbow_locations, + SOLD_RAINBOW_LOCATIONS1, + SOLD_RAINBOW_LOCATIONS2, + SOLD_RAINBOW_LOCATIONS3, + sell_precursor_find, + SOLD_PRECURSOR_FIND, + changed_mind_no_sell, + done_selling, + NEED_CREDIT, + WHAT_TO_BUY, + WHAT_MORE_TO_BUY, + OK_DONE_BUYING, + buy_fuel, + done_buying, + be_leaving_now, + HOW_MUCH_FUEL, + buy_1_fuel, + GOT_FUEL, + buy_5_fuel, + buy_10_fuel, + buy_25_fuel, + done_buying_fuel, + FRIENDLY_GOODBYE, + CREDIT_IS0, + CREDIT_IS1, + NEED_MORE_CREDIT0, + NEED_MORE_CREDIT1, + BUY_FUEL_INTRO, + NO_ROOM_FOR_FUEL, + buy_info, + buy_technology, + buy_current_events, + buy_alien_races, + buy_history, + done_buying_info, + no_buy_info, + BUY_INFO_INTRO, + OK_BUY_INFO, + OK_NO_BUY_INFO, + OK_DONE_BUYING_INFO, + OK_BUY_EVENT_1, + OK_BUY_EVENT_2, + OK_BUY_EVENT_3, + OK_BUY_EVENT_4, + OK_BUY_EVENT_5, + OK_BUY_EVENT_6, + OK_BUY_EVENT_7, + OK_BUY_EVENT_8, + OK_BUY_ALIEN_RACE_1, + OK_BUY_ALIEN_RACE_2, + OK_BUY_ALIEN_RACE_3, + OK_BUY_ALIEN_RACE_4, + OK_BUY_ALIEN_RACE_5, + OK_BUY_ALIEN_RACE_6, + OK_BUY_ALIEN_RACE_7, + OK_BUY_ALIEN_RACE_8, + OK_BUY_ALIEN_RACE_9, + OK_BUY_ALIEN_RACE_10, + OK_BUY_ALIEN_RACE_11, + OK_BUY_ALIEN_RACE_12, + OK_BUY_ALIEN_RACE_13, + OK_BUY_ALIEN_RACE_14, + OK_BUY_ALIEN_RACE_15, + OK_BUY_ALIEN_RACE_16, + OK_BUY_HISTORY_1, + OK_BUY_HISTORY_2, + OK_BUY_HISTORY_3, + OK_BUY_HISTORY_4, + OK_BUY_HISTORY_5, + OK_BUY_HISTORY_6, + OK_BUY_HISTORY_7, + OK_BUY_HISTORY_8, + OK_BUY_HISTORY_9, + INFO_ALL_GONE, + buy_new_tech, + no_buy_new_tech, + done_buying_new_tech, + fill_me_up, + OK_FILL_YOU_UP, + BUY_NEW_TECH_INTRO, + OK_BUY_NEW_TECH, + OK_NO_BUY_NEW_TECH, + OK_DONE_BUYING_NEW_TECH, + OK_DONE_BUYING_FUEL, + NEW_TECH_1, + NEW_TECH_2, + NEW_TECH_3, + NEW_TECH_4, + NEW_TECH_5, + NEW_TECH_6, + NEW_TECH_7, + NEW_TECH_8, + NEW_TECH_9, + NEW_TECH_10, + NEW_TECH_11, + NEW_TECH_12, + NEW_TECH_13, + OK_BUY_NEW_TECH_1, + OK_BUY_NEW_TECH_2, + OK_BUY_NEW_TECH_3, + OK_BUY_NEW_TECH_4, + OK_BUY_NEW_TECH_5, + OK_BUY_NEW_TECH_6, + OK_BUY_NEW_TECH_7, + OK_BUY_NEW_TECH_8, + OK_BUY_NEW_TECH_9, + OK_BUY_NEW_TECH_10, + OK_BUY_NEW_TECH_11, + OK_BUY_NEW_TECH_12, + OK_BUY_NEW_TECH_13, + CHARITY, + NEW_TECH_ALL_GONE, + we_are_from_alliance0, + STRIP_HEAD, + LANDERS, + THRUSTERS, + JETS, + PODS, + BAYS, + DYNAMOS, + FURNACES, + GUNS, + BLASTERS, + CANNONS, + TRACKERS, + DEFENSES, + name_1, + name_2, + name_3, + name_40, + name_41, + ENUMERATE_ONE, + END_LIST_WITH_AND = ENUMERATE_ONE + 16 +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/mycon/ifontres.h b/sc2/src/sc2code/comm/mycon/ifontres.h new file mode 100644 index 000000000..a31d4ca75 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/ifontres.h @@ -0,0 +1,3 @@ +#define MYCON_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/mycon/igfxres.h b/sc2/src/sc2code/comm/mycon/igfxres.h new file mode 100644 index 000000000..6a4ce3b6b --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/igfxres.h @@ -0,0 +1,3 @@ +#define MYCON_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/mycon/imusicre.h b/sc2/src/sc2code/comm/mycon/imusicre.h new file mode 100644 index 000000000..4e7f0456c --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/imusicre.h @@ -0,0 +1,3 @@ +#define MYCON_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/mycon/istrtab.h b/sc2/src/sc2code/comm/mycon/istrtab.h new file mode 100644 index 000000000..b4bdbc777 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/istrtab.h @@ -0,0 +1,3 @@ +#define MYCON_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/mycon/mycon.res b/sc2/src/sc2code/comm/mycon/mycon.res new file mode 100644 index 000000000..6509ed212 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/mycon.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/mycon + +PACKAGE MYCON_PACKAGE mycon.con + GFXRES MYCON_PMAP_ANIM mycon.ani + FONTRES MYCON_FONT mycon.fon + MUSICRES MYCON_MUSIC mycon.mod + STRTAB MYCON_CONVERSATION_PHRASES mycon.txt + diff --git a/sc2/src/sc2code/comm/mycon/myconc.c b/sc2/src/sc2code/comm/mycon/myconc.c new file mode 100644 index 000000000..c974dd2eb --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/myconc.c @@ -0,0 +1,618 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/mycon/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/mycon/strings.h" + +static LOCDATA mycon_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)MYCON_PMAP_ANIM, /* AlienFrame */ + (FONT)MYCON_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + MYCON_MUSIC, /* AlienSong */ + MYCON_CONVERSATION_PHRASES, /* PlayerPhrases */ + 5, /* NumAnimations */ + { + { + 12, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + (1 << 1), /* BlockMask */ + }, + { + 18, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + (1 << 0), /* BlockMask */ + }, + { + 22, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + { + 28, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + { + 33, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 9, 0, /* FrameRate */ + 9, 0, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 11, /* NumFrames */ + 0, /* AnimFlags */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static BYTE MadeChoice = 0; + +static void +DoRamble (RESPONSE_REF R) +{ + BYTE Counter; + + Counter = GET_GAME_STATE (MYCON_RAMBLE); + switch (Counter++) + { + case 0: + NPCPhrase (RAMBLE_1); + break; + case 1: + NPCPhrase (RAMBLE_2); + break; + case 2: + NPCPhrase (RAMBLE_3); + break; + case 3: + NPCPhrase (RAMBLE_4); + break; + case 4: + NPCPhrase (RAMBLE_5); + break; + case 5: + NPCPhrase (RAMBLE_6); + break; + case 6: + NPCPhrase (RAMBLE_7); + break; + case 7: + NPCPhrase (RAMBLE_8); + break; + case 8: + NPCPhrase (RAMBLE_9); + break; + case 9: + NPCPhrase (RAMBLE_10); + break; + case 10: + NPCPhrase (RAMBLE_11); + break; + case 11: + NPCPhrase (RAMBLE_12); + break; + case 12: + NPCPhrase (RAMBLE_13); + break; + case 13: + NPCPhrase (RAMBLE_14); + break; + case 14: + NPCPhrase (RAMBLE_15); + break; + case 15: + NPCPhrase (RAMBLE_16); + break; + case 16: + NPCPhrase (RAMBLE_17); + break; + case 17: + NPCPhrase (RAMBLE_18); + break; + case 18: + NPCPhrase (RAMBLE_19); + break; + case 19: + NPCPhrase (RAMBLE_20); + break; + case 20: + NPCPhrase (RAMBLE_21); + break; + case 21: + NPCPhrase (RAMBLE_22); + break; + case 22: + NPCPhrase (RAMBLE_23); + break; + case 23: + NPCPhrase (RAMBLE_24); + break; + case 24: + NPCPhrase (RAMBLE_25); + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) + { + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); + } + break; + case 25: + NPCPhrase (RAMBLE_26); + break; + case 26: + NPCPhrase (RAMBLE_27); + break; + case 27: + NPCPhrase (RAMBLE_28); + break; + case 28: + NPCPhrase (RAMBLE_29); + break; + case 29: + NPCPhrase (RAMBLE_30); + break; + case 30: + NPCPhrase (RAMBLE_31); + break; + case 31: + NPCPhrase (RAMBLE_32); + Counter = 0; + break; + } + SET_GAME_STATE (MYCON_RAMBLE, Counter); + + if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + { + if (!PLAYER_SAID (R, come_in_peace) + && !PLAYER_SAID (R, gonna_die)) + { + Counter = (GET_GAME_STATE (MYCON_INSULTS) + 1) & 7; + SET_GAME_STATE (MYCON_INSULTS, Counter); + MadeChoice = 1; + } + } + else if (!PLAYER_SAID (R, lets_be_friends) + && !PLAYER_SAID (R, came_to_homeworld) + && !PLAYER_SAID (R, submit_to_us)) + { + Counter = (GET_GAME_STATE (MYCON_INFO) + 1) & 15; + SET_GAME_STATE (MYCON_INFO, Counter); + MadeChoice = 1; + } +} + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye_space)) + NPCPhrase (BYE_AND_DIE_SPACE); + else if (PLAYER_SAID (R, bye_homeworld)) + NPCPhrase (BYE_AND_DIE_HOMEWORLD); + else if (PLAYER_SAID (R, like_to_land)) + NPCPhrase (NEVER_LET_LAND); + else if (PLAYER_SAID (R, bye_sun_device)) + { + NPCPhrase (GOODBYE_SUN_DEVICE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + DoRamble (R); + if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + NPCPhrase (BYE_AND_DIE_SPACE); + else + NPCPhrase (BYE_AND_DIE_HOMEWORLD); + } +} + +static void +SunDevice (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_up_sun_device)) + { + NPCPhrase (GENERAL_INFO_SUN_DEVICE); + + DISABLE_PHRASE (whats_up_sun_device); + } + else if (PLAYER_SAID (R, how_goes_implanting)) + { + NPCPhrase (UNFORSEEN_DELAYS); + + DISABLE_PHRASE (how_goes_implanting); + } + else if (PLAYER_SAID (R, i_have_a_cunning_plan)) + { + NPCPhrase (DIE_LIAR /* WONT_FALL_FOR_TRICK */); + + SET_GAME_STATE (NO_TRICK_AT_SUN, 1); + } + + if (PHRASE_ENABLED (whats_up_sun_device)) + Response (whats_up_sun_device, SunDevice); + if (GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) + { + if (PHRASE_ENABLED (how_goes_implanting) && GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) + Response (how_goes_implanting, SunDevice); + Response (like_to_land, CombatIsInevitable); + } + else if (GET_GAME_STATE (MYCON_AMBUSH) + && !GET_GAME_STATE (NO_TRICK_AT_SUN)) + Response (i_have_a_cunning_plan, SunDevice); + Response (bye_sun_device, CombatIsInevitable); +} + +static void +TrickMycon (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, i_have_a_cunning_plan)) + { + NPCPhrase (TELL_US_ABOUT_WORLD); + + DISABLE_PHRASE (i_have_a_cunning_plan); + } + else if (PLAYER_SAID (R, clue_1)) + { + NPCPhrase (RESPONSE_1); + + DISABLE_PHRASE (clue_1); + } + else if (PLAYER_SAID (R, clue_2)) + { + NPCPhrase (RESPONSE_2); + + DISABLE_PHRASE (clue_2); + } + else if (PLAYER_SAID (R, clue_3)) + { + NPCPhrase (RESPONSE_3); + + DISABLE_PHRASE (clue_3); + } + + if (PHRASE_ENABLED (clue_1) == 0 + && PHRASE_ENABLED (clue_2) == 0 + && PHRASE_ENABLED (clue_3) == 0) + { + NPCPhrase (WE_GO_TO_IMPLANT); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (MYCON_FELL_FOR_AMBUSH, 1); + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_MYCON_MISSION); + } + else + NPCPhrase (AMBUSH_TAIL); + + if (PHRASE_ENABLED (clue_1)) + Response (clue_1, TrickMycon); + if (PHRASE_ENABLED (clue_2)) + Response (clue_2, TrickMycon); + if (PHRASE_ENABLED (clue_3)) + Response (clue_3, TrickMycon); +} + +static void +NormalMycon (RESPONSE_REF R) +{ + RESPONSE_FUNC RespFunc; + + if (PLAYER_SAID (R, what_about_shattered)) + { + NPCPhrase (ABOUT_SHATTERED); + + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); + } + else if (R) + { + DoRamble (R); + NPCPhrase (RAMBLE_TAIL); + + DISABLE_PHRASE (RESPONSE_TO_REF (R)); + } + + if ((BYTE)Random () < 256 * 30 / 100) + RespFunc = (RESPONSE_FUNC)CombatIsInevitable; + else + RespFunc = (RESPONSE_FUNC)NormalMycon; + if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + { + if (PHRASE_ENABLED (come_in_peace)) + Response (come_in_peace, RespFunc); + if (PHRASE_ENABLED (gonna_die)) + Response (gonna_die, RespFunc); + if (!MadeChoice) switch (GET_GAME_STATE (MYCON_INSULTS)) + { + case 0: + Response (insult_1, RespFunc); + break; + case 1: + Response (insult_2, RespFunc); + break; + case 2: + Response (insult_3, RespFunc); + break; + case 3: + Response (insult_4, RespFunc); + break; + case 4: + Response (insult_5, RespFunc); + break; + case 5: + Response (insult_6, RespFunc); + break; + case 6: + Response (insult_7, RespFunc); + break; + case 7: + Response (insult_8, RespFunc); + break; + } + Response (bye_space, CombatIsInevitable); + } + else + { + if (!MadeChoice) switch (GET_GAME_STATE (MYCON_INFO)) + { + case 0: + Response (question_1, RespFunc); + break; + case 1: + Response (question_2, RespFunc); + break; + case 2: + Response (question_3, RespFunc); + break; + case 3: + Response (question_4, RespFunc); + break; + case 4: + Response (question_5, RespFunc); + break; + case 5: + Response (question_6, RespFunc); + break; + case 6: + Response (question_7, RespFunc); + break; + case 7: + Response (question_8, RespFunc); + break; + case 8: + Response (question_9, RespFunc); + break; + case 9: + Response (question_10, RespFunc); + break; + case 10: + Response (question_11, RespFunc); + break; + case 11: + Response (question_12, RespFunc); + break; + case 12: + Response (question_13, RespFunc); + break; + case 13: + Response (question_14, RespFunc); + break; + case 14: + Response (question_15, RespFunc); + break; + case 15: + Response (question_16, RespFunc); + break; + } + if (PHRASE_ENABLED (lets_be_friends)) + Response (lets_be_friends, RespFunc); + if (PHRASE_ENABLED (came_to_homeworld)) + Response (came_to_homeworld, RespFunc); + if (PHRASE_ENABLED (submit_to_us)) + Response (submit_to_us, RespFunc); + if (!GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) + { + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 1) + Response (what_about_shattered, NormalMycon); + if (GET_GAME_STATE (MYCON_AMBUSH)) + { + Response (i_have_a_cunning_plan, TrickMycon); + } + } + Response (bye_homeworld, CombatIsInevitable); + } +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (GET_GAME_STATE (SUN_DEVICE)) + { + NumVisits = GET_GAME_STATE (MYCON_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (DIE_THIEF); + break; + case 1: + NPCPhrase (DIE_THIEF_AGAIN); + --NumVisits; + break; + } + SET_GAME_STATE (MYCON_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (MYCON_KNOW_AMBUSH)) + { + NPCPhrase (DIE_LIAR); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (MYCON_SUN_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_SUN_DEVICE_WORLD_1); + break; + case 1: + NPCPhrase (HELLO_SUN_DEVICE_WORLD_2); + --NumVisits; + break; + } + SET_GAME_STATE (MYCON_SUN_VISITS, NumVisits); + + SunDevice ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (MYCON_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_HOMEWORLD_1); + break; + case 1: + NPCPhrase (HELLO_HOMEWORLD_2); + break; + case 2: + NPCPhrase (HELLO_HOMEWORLD_3); + break; + case 3: + NPCPhrase (HELLO_HOMEWORLD_4); + break; + case 4: + NPCPhrase (HELLO_HOMEWORLD_5); + break; + case 5: + NPCPhrase (HELLO_HOMEWORLD_6); + break; + case 6: + NPCPhrase (HELLO_HOMEWORLD_7); + break; + case 7: + NPCPhrase (HELLO_HOMEWORLD_8); + --NumVisits; + break; + } + SET_GAME_STATE (MYCON_HOME_VISITS, NumVisits); + + NormalMycon ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (MYCON_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_SPACE_2); + break; + case 2: + NPCPhrase (HELLO_SPACE_3); + break; + case 3: + NPCPhrase (HELLO_SPACE_4); + break; + case 4: + NPCPhrase (HELLO_SPACE_5); + break; + case 5: + NPCPhrase (HELLO_SPACE_6); + break; + case 6: + NPCPhrase (HELLO_SPACE_7); + break; + case 7: + NPCPhrase (HELLO_SPACE_8); + --NumVisits; + break; + } + SET_GAME_STATE (MYCON_VISITS, NumVisits); + + NormalMycon ((RESPONSE_REF)0); + } +} + +static COUNT +uninit_mycon (void) +{ + return (0); +} + +LOCDATAPTR +init_mycon_comm (void) +{ + LOCDATAPTR retval; + + mycon_desc.init_encounter_func = Intro; + mycon_desc.uninit_encounter_func = uninit_mycon; + + mycon_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + mycon_desc.AlienTextTemplate.baseline.y = 0; + mycon_desc.AlienTextTemplate.align = ALIGN_CENTER; + mycon_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + retval = &mycon_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/mycon/resinst.h b/sc2/src/sc2code/comm/mycon/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/mycon/respkg.h b/sc2/src/sc2code/comm/mycon/respkg.h new file mode 100644 index 000000000..963fdabc2 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/respkg.h @@ -0,0 +1,5 @@ +enum +{ + MYCON_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/mycon/restypes.h b/sc2/src/sc2code/comm/mycon/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/mycon/strings.h b/sc2/src/sc2code/comm/mycon/strings.h new file mode 100644 index 000000000..dff78ac2f --- /dev/null +++ b/sc2/src/sc2code/comm/mycon/strings.h @@ -0,0 +1,135 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + TELL_US_ABOUT_WORLD, + BYE_AND_DIE_HOMEWORLD, + RAMBLE_1, + RAMBLE_2, + RAMBLE_3, + RAMBLE_4, + RAMBLE_5, + RAMBLE_6, + RAMBLE_7, + RAMBLE_8, + RAMBLE_9, + RAMBLE_10, + RAMBLE_11, + RAMBLE_12, + RAMBLE_13, + RAMBLE_14, + RAMBLE_15, + RAMBLE_16, + RAMBLE_17, + RAMBLE_18, + RAMBLE_19, + RAMBLE_20, + RAMBLE_21, + RAMBLE_22, + RAMBLE_23, + RAMBLE_24, + RAMBLE_25, + RAMBLE_26, + RAMBLE_27, + RAMBLE_28, + RAMBLE_29, + RAMBLE_30, + RAMBLE_31, + RAMBLE_32, + question_1, + question_2, + question_3, + question_4, + question_5, + question_6, + question_7, + question_8, + question_9, + question_10, + question_11, + question_12, + question_13, + question_14, + question_15, + question_16, + bye_space, + BYE_AND_DIE_SPACE, + gonna_die, + insult_1, + insult_2, + insult_3, + insult_4, + insult_5, + insult_6, + insult_7, + insult_8, + come_in_peace, + HELLO_HOMEWORLD_1, + HELLO_HOMEWORLD_2, + HELLO_HOMEWORLD_3, + HELLO_HOMEWORLD_4, + HELLO_HOMEWORLD_5, + HELLO_HOMEWORLD_6, + HELLO_HOMEWORLD_7, + HELLO_HOMEWORLD_8, + HELLO_SPACE_1, + HELLO_SPACE_2, + HELLO_SPACE_3, + HELLO_SPACE_4, + HELLO_SPACE_5, + HELLO_SPACE_6, + HELLO_SPACE_7, + HELLO_SPACE_8, + lets_be_friends, + came_to_homeworld, + submit_to_us, + bye_sun_device, + GOODBYE_SUN_DEVICE, + RESPONSE_1, + RESPONSE_2, + RESPONSE_3, + clue_1, + clue_2, + clue_3, + what_about_shattered, + ABOUT_SHATTERED, + HELLO_SUN_DEVICE_WORLD_1, + HELLO_SUN_DEVICE_WORLD_2, + whats_up_sun_device, + GENERAL_INFO_SUN_DEVICE, + like_to_land, + NEVER_LET_LAND, + bye_homeworld, + i_have_a_cunning_plan, + DIE_LIAR, + how_goes_implanting, + UNFORSEEN_DELAYS, + DIE_THIEF, + DIE_THIEF_AGAIN, + GOODBYE_AND_DIE, + AMBUSH_TAIL, + RAMBLE_TAIL, + WE_GO_TO_IMPLANT, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/orz/ifontres.h b/sc2/src/sc2code/comm/orz/ifontres.h new file mode 100644 index 000000000..6fb559e52 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/ifontres.h @@ -0,0 +1,3 @@ +#define ORZ_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/orz/igfxres.h b/sc2/src/sc2code/comm/orz/igfxres.h new file mode 100644 index 000000000..ed6ff5c30 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/igfxres.h @@ -0,0 +1,3 @@ +#define ORZ_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/orz/imusicre.h b/sc2/src/sc2code/comm/orz/imusicre.h new file mode 100644 index 000000000..8b9ed4f0d --- /dev/null +++ b/sc2/src/sc2code/comm/orz/imusicre.h @@ -0,0 +1,3 @@ +#define ORZ_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/orz/istrtab.h b/sc2/src/sc2code/comm/orz/istrtab.h new file mode 100644 index 000000000..61dd25977 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/istrtab.h @@ -0,0 +1,4 @@ +#define ORZ_CONVERSATION_PHRASES 0x00200004L +#define ORZ_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/orz/orz.res b/sc2/src/sc2code/comm/orz/orz.res new file mode 100644 index 000000000..e73838a5f --- /dev/null +++ b/sc2/src/sc2code/comm/orz/orz.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/orz + +PACKAGE ORZ_PACKAGE orz.con + GFXRES ORZ_PMAP_ANIM orz.ani + FONTRES ORZ_FONT orz.fon + MUSICRES ORZ_MUSIC orz.mod + STRTAB ORZ_CONVERSATION_PHRASES orz.txt + STRTAB ORZ_COLOR_MAP orz.ct diff --git a/sc2/src/sc2code/comm/orz/orzc.c b/sc2/src/sc2code/comm/orz/orzc.c new file mode 100644 index 000000000..0b71881a3 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/orzc.c @@ -0,0 +1,882 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/orz/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/orz/strings.h" + +static LOCDATA orz_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)ORZ_PMAP_ANIM, /* AlienFrame */ + (FONT)ORZ_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + (COLORMAP)ORZ_COLOR_MAP, /* AlienColorMap */ + ORZ_MUSIC, /* AlienSong */ + ORZ_CONVERSATION_PHRASES, /* PlayerPhrases */ + 12 /* 13 */, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 10, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 15, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 17, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 20, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, ONE_SECOND * 3, /* RestartRate */ + (1 << 7), /* BlockMask */ + }, + { + 22, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), /* BlockMask */ + }, + { + 30, /* StartIndex */ + 3, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), /* BlockMask */ + }, + { + 33, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, ONE_SECOND * 3, /* RestartRate */ + (1 << 4), /* BlockMask */ + }, + { + 36, /* StartIndex */ + 25, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 2, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 61, /* StartIndex */ + 15, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 2, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 76, /* StartIndex */ + 17, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 2, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12), /* BlockMask */ + }, + { + 93, /* StartIndex */ + 25, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 2, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 118, /* StartIndex */ + 11, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 2, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 10), /* BlockMask */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 8, 8, /* FrameRate */ + 10, ONE_SECOND * 3 / 8, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye_ally)) + NPCPhrase (GOODBYE_ALLY); + else if (PLAYER_SAID (R, bye_neutral)) + NPCPhrase (GOODBYE_NEUTRAL); + else if (PLAYER_SAID (R, bye_angry)) + NPCPhrase (GOODBYE_ANGRY); + else if (PLAYER_SAID (R, bye_taalo)) + { + if (GET_GAME_STATE (ORZ_MANNER) == 1) + NPCPhrase (ANGRY_TAALO_GOODBYE); + else + NPCPhrase (FRIENDLY_TAALO_GOODBYE); + } + else if (PLAYER_SAID (R, hostile_2)) + { + NPCPhrase (HOSTILITY_IS_BAD_2); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, may_we_land)) + { + NPCPhrase (SURE_LAND); + + SET_GAME_STATE (TAALO_UNPROTECTED, 1); + } + else if (PLAYER_SAID (R, yes_alliance) + || PLAYER_SAID (R, were_sorry)) + { + if (PLAYER_SAID (R, yes_alliance)) + NPCPhrase (GREAT); + else + NPCPhrase (APOLOGY_ACCEPTED); + + SET_GAME_STATE (ORZ_ANDRO_STATE, 0); + SET_GAME_STATE (ORZ_GENERAL_INFO, 0); + SET_GAME_STATE (ORZ_PERSONAL_INFO, 0); + SET_GAME_STATE (ORZ_MANNER, 3); + ActivateStarShip (ORZ_SHIP, 0); + } + else if (PLAYER_SAID (R, demand_to_land)) + { + NPCPhrase (NO_DEMAND); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, about_andro_3) + || PLAYER_SAID (R, must_know_about_androsyn)) + { + if (PLAYER_SAID (R, about_andro_3)) + NPCPhrase (BLEW_IT); + else + NPCPhrase (KNOW_TOO_MUCH); + + SET_GAME_STATE (ORZ_VISITS, 0); + SET_GAME_STATE (ORZ_MANNER, 2); + SET_GAME_STATE (BATTLE_SEGUE, 1); + if (PLAYER_SAID (R, about_andro_3)) + ActivateStarShip (ORZ_SHIP, -1); + + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND / 2); + } + else /* insults */ + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (ORZ_PERSONAL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (INSULTED_1); + break; + case 1: + NPCPhrase (INSULTED_2); + break; + case 2: + NPCPhrase (INSULTED_3); + SET_GAME_STATE (BATTLE_SEGUE, 1); + break; + case 7: + --NumVisits; + default: + NPCPhrase (INSULTED_4); + SET_GAME_STATE (BATTLE_SEGUE, 1); + break; + } + SET_GAME_STATE (ORZ_PERSONAL_INFO, NumVisits); + } +} + +static void +TaaloWorld (RESPONSE_REF R) +{ + BYTE Manner; + + Manner = GET_GAME_STATE (ORZ_MANNER); + if (PLAYER_SAID (R, demand_to_land)) + { + NPCPhrase (ASK_NICELY); + + DISABLE_PHRASE (demand_to_land); + } + else if (PLAYER_SAID (R, why_you_here)) + { + if (Manner != 1) + NPCPhrase (FRIENDLY_EXPLANATION); + else + NPCPhrase (ANGRY_EXPLANATION); + + DISABLE_PHRASE (why_you_here); + } + else if (PLAYER_SAID (R, what_is_this_place)) + { + if (Manner != 1) + NPCPhrase (FRIENDLY_PLACE); + else + NPCPhrase (ANGRY_PLACE); + + DISABLE_PHRASE (what_is_this_place); + } + else if (PLAYER_SAID (R, may_we_land)) + { + NPCPhrase (ALLIES_CAN_VISIT); + + DISABLE_PHRASE (may_we_land); + } + else if (PLAYER_SAID (R, make_alliance)) + { + NPCPhrase (CANT_ALLY_HERE); + + DISABLE_PHRASE (make_alliance); + } + else if (PLAYER_SAID (R, why_busy)) + { + NPCPhrase (BUSY_BECAUSE); + + DISABLE_PHRASE (why_busy); + } + + if (PHRASE_ENABLED (may_we_land)) + { + if (Manner == 3 && (ActivateStarShip ( + ORZ_SHIP, CHECK_ALLIANCE + ) & GOOD_GUY)) + Response (may_we_land, ExitConversation); + else + Response (may_we_land, TaaloWorld); + } + else if (PHRASE_ENABLED (make_alliance)) + Response (make_alliance, TaaloWorld); + else if (PHRASE_ENABLED (why_busy)) + Response (why_busy, TaaloWorld); + if (PHRASE_ENABLED (demand_to_land)) + { + if (Manner == 1) + Response (demand_to_land, ExitConversation); + else + Response (demand_to_land, TaaloWorld); + } + if (PHRASE_ENABLED (why_you_here)) + Response (why_you_here, TaaloWorld); + if (PHRASE_ENABLED (what_is_this_place)) + Response (what_is_this_place, TaaloWorld); + Response (bye_taalo, ExitConversation); +} + +static void +OrzAllied (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_ally)) + { + NumVisits = GET_GAME_STATE (ORZ_GENERAL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_ALLY_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_ALLY_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_ALLY_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_ALLY_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_GENERAL_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_ally); + } + else if (PLAYER_SAID (R, more_about_you)) + { + NumVisits = GET_GAME_STATE (ORZ_PERSONAL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (ABOUT_US_1); + break; + case 1: + NPCPhrase (ABOUT_US_2); + break; + case 2: + NPCPhrase (ABOUT_US_3); + break; + case 3: + NPCPhrase (ABOUT_US_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_PERSONAL_INFO, NumVisits); + + DISABLE_PHRASE (more_about_you); + } + else if (PLAYER_SAID (R, about_andro_1)) + { + NPCPhrase (FORGET_ANDRO_1); + + SET_GAME_STATE (ORZ_ANDRO_STATE, 1); + } + else if (PLAYER_SAID (R, about_andro_2)) + { + NPCPhrase (FORGET_ANDRO_2); + + SET_GAME_STATE (ORZ_ANDRO_STATE, 2); + } + + if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 0) + Response (about_andro_1, OrzAllied); + else if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 1) + Response (about_andro_2, OrzAllied); + else + { + Response (about_andro_3, ExitConversation); + } + if (PHRASE_ENABLED (whats_up_ally)) + Response (whats_up_ally, OrzAllied); + if (PHRASE_ENABLED (more_about_you)) + Response (more_about_you, OrzAllied); + Response (bye_ally, ExitConversation); +} + +static void OrzNeutral (RESPONSE_REF R); + +static void +WhereAndrosyn (RESPONSE_REF R) +{ + NPCPhrase (DISEMBLE_ABOUT_ANDROSYN); + DISABLE_PHRASE (where_androsyn); + + Response (must_know_about_androsyn, ExitConversation); + Response (dont_really_care, OrzNeutral); +} + +static void +OfferAlliance (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, seem_like_nice_guys)) + NPCPhrase (ARE_NICE_WANT_ALLY); + else if (PLAYER_SAID (R, talk_about_alliance)) + NPCPhrase (OK_TALK_ALLIANCE); + else if (PLAYER_SAID (R, why_so_trusting)) + { + NPCPhrase (TRUSTING_BECAUSE); + + SET_GAME_STATE (ORZ_STACK1, 1); + } + + Response (no_alliance, OrzNeutral); + Response (decide_later, OrzNeutral); + if (GET_GAME_STATE (ORZ_STACK1) == 0) + { + Response (why_so_trusting, OfferAlliance); + } + Response (yes_alliance, ExitConversation); +} + +static void +OrzNeutral (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, hostile_1)) + { + NPCPhrase (HOSTILITY_IS_BAD_1); + + DISABLE_PHRASE (hostile_1); + LastStack = 2; + } + else if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (NICE_TO_MEET_YOU); + + SET_GAME_STATE (ORZ_STACK0, 1); + LastStack = 1; + } + else if (PLAYER_SAID (R, who_you)) + { + NPCPhrase (WE_ARE_ORZ); + + SET_GAME_STATE (ORZ_ANDRO_STATE, 1); + } + else if (PLAYER_SAID (R, why_here)) + { + NPCPhrase (HERE_BECAUSE); + + SET_GAME_STATE (ORZ_ANDRO_STATE, 2); + } + else if (PLAYER_SAID (R, no_alliance)) + { + NPCPhrase (MAYBE_LATER); + + DISABLE_PHRASE (talk_about_alliance); + SET_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1); + } + else if (PLAYER_SAID (R, decide_later)) + { + NPCPhrase (OK_LATER); + + DISABLE_PHRASE (talk_about_alliance); + SET_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1); + } + else if (PLAYER_SAID (R, dont_really_care)) + NPCPhrase (YOU_ARE_OUR_FRIENDS); + else if (PLAYER_SAID (R, where_androsyn)) + { + WhereAndrosyn (R); + + goto ExitNeutral; + } + else if (PLAYER_SAID (R, talk_about_alliance) + || PLAYER_SAID (R, seem_like_nice_guys)) + { + OfferAlliance (R); + + goto ExitNeutral; + } + else if (PLAYER_SAID (R, hostile_2)) + { + ExitConversation (R); + + goto ExitNeutral; + } + + if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 0) + pStr[0] = who_you; + else if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 1) + pStr[0] = why_here; + else if (PHRASE_ENABLED (where_androsyn) && GET_GAME_STATE (ORZ_ANDRO_STATE) == 2) + pStr[0] = where_androsyn; + if (GET_GAME_STATE (REFUSED_ORZ_ALLIANCE)) + { + if (PHRASE_ENABLED (talk_about_alliance)) + pStr[1] = talk_about_alliance; + } + else if (GET_GAME_STATE (ORZ_STACK0) == 0) + { + construct_response (shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0); + pStr[1] = we_are_vindicator0; + } + else + pStr[1] = seem_like_nice_guys; + if (PHRASE_ENABLED (hostile_1)) + pStr[2] = hostile_1; + else + pStr[2] = hostile_2; + + if (pStr[LastStack]) + { + if (pStr[LastStack] != we_are_vindicator0) + Response (pStr[LastStack], OrzNeutral); + else + DoResponsePhrase (pStr[LastStack], OrzNeutral, shared_phrase_buf); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != we_are_vindicator0) + Response (pStr[i], OrzNeutral); + else + DoResponsePhrase (pStr[i], OrzNeutral, shared_phrase_buf); + } + } + Response (bye_neutral, ExitConversation); +ExitNeutral: + ; +} + +static void +OrzAngry (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_up_angry)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (ORZ_GENERAL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_ANGRY_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_ANGRY_2); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_GENERAL_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_angry); + } + + if (PHRASE_ENABLED (whats_up_angry)) + { + Response (whats_up_angry, OrzAngry); + } + Response (were_sorry, ExitConversation); + switch (GET_GAME_STATE (ORZ_PERSONAL_INFO)) + { + case 0: + Response (insult_1, ExitConversation); + break; + case 1: + Response (insult_2, ExitConversation); + break; + case 2: + Response (insult_3, ExitConversation); + break; + case 3: + Response (insult_4, ExitConversation); + break; + case 4: + Response (insult_5, ExitConversation); + break; + case 5: + Response (insult_6, ExitConversation); + break; + case 6: + Response (insult_7, ExitConversation); + break; + case 7: + Response (insult_8, ExitConversation); + break; + } + Response (bye_angry, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits, Manner; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (!GET_GAME_STATE (MET_ORZ_BEFORE)) + NPCPhrase (INIT_HELLO); + + Manner = GET_GAME_STATE (ORZ_MANNER); + if (Manner == 2) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + + NumVisits = GET_GAME_STATE (ORZ_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (TAALO_VISITS); + if (Manner == 0) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (FRIENDLY_ALLIED_TAALO_HELLO_1); + break; + case 1: + NPCPhrase (FRIENDLY_ALLIED_TAALO_HELLO_2); + --NumVisits; + break; + } + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (ANGRY_TAALO_HELLO_1); + break; + case 1: + NPCPhrase (ANGRY_TAALO_HELLO_2); + --NumVisits; + break; + } + } + SET_GAME_STATE (TAALO_VISITS, NumVisits); + + TaaloWorld ((RESPONSE_REF)0); + } + else if (Manner == 3 && (ActivateStarShip ( + ORZ_SHIP, CHECK_ALLIANCE + ) & GOOD_GUY)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (ORZ_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ALLIED_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (ALLIED_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (ALLIED_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (ALLIED_SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_VISITS, NumVisits); + } + + OrzAllied ((RESPONSE_REF)0); + } + else if (Manner != 1) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (ORZ_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (NEUTRAL_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (NEUTRAL_SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_VISITS, NumVisits); + } + + OrzNeutral ((RESPONSE_REF)0); + } + else + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ANGRY_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (ANGRY_HOMEWORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (ORZ_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ANGRY_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (ANGRY_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (ORZ_VISITS, NumVisits); + } + + OrzAngry ((RESPONSE_REF)0); + } + + if (!GET_GAME_STATE (MET_ORZ_BEFORE)) + { + COUNT N; + + SET_GAME_STATE (MET_ORZ_BEFORE, 1); + + N = CommData.AlienTalkDesc.NumFrames; + CommData.AlienTalkDesc.NumFrames = 0; + AlienTalkSegue (1); + CommData.AlienTalkDesc.NumFrames = N; + } + +ExitIntro: + ; +} + +static COUNT +uninit_orz (void) +{ + BYTE Manner; + + if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && (Manner = GET_GAME_STATE (ORZ_MANNER)) != 2) + { + SET_GAME_STATE (ORZ_MANNER, 1); + if (Manner != 1) + { + SET_GAME_STATE (ORZ_VISITS, 0); + SET_GAME_STATE (ORZ_HOME_VISITS, 0); + SET_GAME_STATE (TAALO_VISITS, 0); + } + } + + return (0); +} + +LOCDATAPTR +init_orz_comm (void) +{ + LOCDATAPTR retval; + + orz_desc.init_encounter_func = Intro; + orz_desc.uninit_encounter_func = uninit_orz; + + orz_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + orz_desc.AlienTextTemplate.baseline.y = 0; + orz_desc.AlienTextTemplate.align = ALIGN_CENTER; + orz_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (ORZ_MANNER) == 3 + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &orz_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/orz/resinst.h b/sc2/src/sc2code/comm/orz/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/orz/respkg.h b/sc2/src/sc2code/comm/orz/respkg.h new file mode 100644 index 000000000..8c73dcb8d --- /dev/null +++ b/sc2/src/sc2code/comm/orz/respkg.h @@ -0,0 +1,5 @@ +enum +{ + ORZ_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/orz/restypes.h b/sc2/src/sc2code/comm/orz/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/orz/strings.h b/sc2/src/sc2code/comm/orz/strings.h new file mode 100644 index 000000000..d6267e679 --- /dev/null +++ b/sc2/src/sc2code/comm/orz/strings.h @@ -0,0 +1,142 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + INIT_HELLO, + who_you, + WE_ARE_ORZ, + why_here, + HERE_BECAUSE, + ALLIED_HOMEWORLD_HELLO_1, + ALLIED_HOMEWORLD_HELLO_2, + ALLIED_HOMEWORLD_HELLO_3, + ALLIED_HOMEWORLD_HELLO_4, + ALLIED_SPACE_HELLO_1, + ALLIED_SPACE_HELLO_2, + ALLIED_SPACE_HELLO_3, + ALLIED_SPACE_HELLO_4, + whats_up_ally, + GENERAL_INFO_ALLY_1, + GENERAL_INFO_ALLY_2, + GENERAL_INFO_ALLY_3, + GENERAL_INFO_ALLY_4, + more_about_you, + ABOUT_US_1, + ABOUT_US_2, + ABOUT_US_3, + ABOUT_US_4, + where_androsyn, + DISEMBLE_ABOUT_ANDROSYN, + must_know_about_androsyn, + KNOW_TOO_MUCH, + dont_really_care, + YOU_ARE_OUR_FRIENDS, + about_andro_1, + FORGET_ANDRO_1, + about_andro_2, + FORGET_ANDRO_2, + about_andro_3, + BLEW_IT, + NEUTRAL_HOMEWORLD_HELLO_1, + NEUTRAL_HOMEWORLD_HELLO_2, + NEUTRAL_HOMEWORLD_HELLO_3, + NEUTRAL_HOMEWORLD_HELLO_4, + NEUTRAL_SPACE_HELLO_1, + NEUTRAL_SPACE_HELLO_2, + NEUTRAL_SPACE_HELLO_3, + NEUTRAL_SPACE_HELLO_4, + hostile_1, + HOSTILITY_IS_BAD_1, + hostile_2, + HOSTILITY_IS_BAD_2, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + NICE_TO_MEET_YOU, + seem_like_nice_guys, + ARE_NICE_WANT_ALLY, + talk_about_alliance, + OK_TALK_ALLIANCE, + yes_alliance, + GREAT, + no_alliance, + MAYBE_LATER, + decide_later, + OK_LATER, + why_so_trusting, + TRUSTING_BECAUSE, + bye_neutral, + GOODBYE_NEUTRAL, + ANGRY_SPACE_HELLO_1, + ANGRY_SPACE_HELLO_2, + ANGRY_HOMEWORLD_HELLO_1, + ANGRY_HOMEWORLD_HELLO_2, + whats_up_angry, + GENERAL_INFO_ANGRY_1, + GENERAL_INFO_ANGRY_2, + were_sorry, + APOLOGY_ACCEPTED, + insult_1, + insult_2, + insult_3, + insult_4, + insult_5, + insult_6, + insult_7, + insult_8, + INSULTED_1, + INSULTED_2, + INSULTED_3, + INSULTED_4, + bye_angry, + GOODBYE_ANGRY, + ANGRY_TAALO_HELLO_1, + ANGRY_TAALO_HELLO_2, + FRIENDLY_ALLIED_TAALO_HELLO_1, + FRIENDLY_ALLIED_TAALO_HELLO_2, + demand_to_land, + NO_DEMAND, + ASK_NICELY, + why_you_here, + ANGRY_EXPLANATION, + FRIENDLY_EXPLANATION, + what_is_this_place, + FRIENDLY_PLACE, + ANGRY_PLACE, + may_we_land, + SURE_LAND, + ALLIES_CAN_VISIT, + make_alliance, + CANT_ALLY_HERE, + why_busy, + BUSY_BECAUSE, + bye_taalo, + bye_ally, + GOODBYE_ALLY, + FRIENDLY_TAALO_GOODBYE, + ANGRY_TAALO_GOODBYE, + HOSTILE_HELLO_1, + HOSTILE_HELLO_2, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/pkunk/ifontres.h b/sc2/src/sc2code/comm/pkunk/ifontres.h new file mode 100644 index 000000000..3fa09cf16 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/ifontres.h @@ -0,0 +1,3 @@ +#define PKUNK_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/pkunk/igfxres.h b/sc2/src/sc2code/comm/pkunk/igfxres.h new file mode 100644 index 000000000..9909cb0f3 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/igfxres.h @@ -0,0 +1,3 @@ +#define PKUNK_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/pkunk/imusicre.h b/sc2/src/sc2code/comm/pkunk/imusicre.h new file mode 100644 index 000000000..b185a4df4 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/imusicre.h @@ -0,0 +1,3 @@ +#define PKUNK_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/pkunk/istrtab.h b/sc2/src/sc2code/comm/pkunk/istrtab.h new file mode 100644 index 000000000..950e65f9c --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/istrtab.h @@ -0,0 +1,3 @@ +#define PKUNK_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/pkunk/pkunk.res b/sc2/src/sc2code/comm/pkunk/pkunk.res new file mode 100644 index 000000000..082411b7b --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/pkunk.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/pkunk + +PACKAGE PKUNK_PACKAGE pkunk.con + GFXRES PKUNK_PMAP_ANIM pkunk.ani + FONTRES PKUNK_FONT pkunk.fon + MUSICRES PKUNK_MUSIC pkunk.mod + STRTAB PKUNK_CONVERSATION_PHRASES pkunk.txt + diff --git a/sc2/src/sc2code/comm/pkunk/pkunkc.c b/sc2/src/sc2code/comm/pkunk/pkunkc.c new file mode 100644 index 000000000..ea650223d --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/pkunkc.c @@ -0,0 +1,1121 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/pkunk/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/pkunk/strings.h" + +static LOCDATA pkunk_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)PKUNK_PMAP_ANIM, /* AlienFrame */ + (FONT)PKUNK_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + PKUNK_MUSIC, /* AlienSong */ + PKUNK_CONVERSATION_PHRASES, /* PlayerPhrases */ + 3, /* NumAnimations */ + { + { + 3, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM + | WAIT_TALKING, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 7, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 2), /* BlockMask */ + }, + { + 11, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 1), /* BlockMask */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 2, /* NumFrames */ + 0, /* AnimFlags */ + 8, 20, /* FrameRate */ + 10, ONE_SECOND / 2, /* RestartRate */ + }, +}; + +static BOOLEAN +ShipsReady (void) +{ + SIZE i; + + return (GET_GAME_STATE (PKUNK_MANNER) == 3 + && !((i = (GLOBAL (GameClock.year_index) - START_YEAR) + - GET_GAME_STATE (PKUNK_SHIP_YEAR)) < 0 + || (i == 0 + && (i = GLOBAL (GameClock.month_index) - + GET_GAME_STATE (PKUNK_SHIP_MONTH)) < 0 + || (i == 0 + && GLOBAL (GameClock.day_index) < + GET_GAME_STATE (PKUNK_SHIP_DAY))))); +} + +static void +PrepareShip (void) +{ +#define MAX_PKUNK_SHIPS 4 + if (ActivateStarShip (PKUNK_SHIP, MAX_PKUNK_SHIPS)) + { + BYTE mi, di, yi; + + mi = GLOBAL (GameClock.month_index); + SET_GAME_STATE (PKUNK_SHIP_MONTH, mi); + if ((di = GLOBAL (GameClock.day_index)) > 28) + di = 28; + SET_GAME_STATE (PKUNK_SHIP_DAY, di); + yi = (BYTE)(GLOBAL (GameClock.year_index) - START_YEAR) + 1; + SET_GAME_STATE (PKUNK_SHIP_YEAR, yi); + } +} + +#define GOOD_REASON_1 (1 << 0) +#define GOOD_REASON_2 (1 << 1) +#define BAD_REASON_1 (1 << 2) +#define BAD_REASON_2 (1 << 3) + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, friendly_bye_space)) + NPCPhrase (FRIENDLY_GOODBYE_SPACE); + else if (PLAYER_SAID (R, neutral_bye_space)) + NPCPhrase (NEUTRAL_GOODBYE_SPACE); + else if (PLAYER_SAID (R, bye_angry)) + NPCPhrase (GOODBYE_ANGRY); + else if (PLAYER_SAID (R, bye_friendly)) + NPCPhrase (GOODBYE_FRIENDLY); + else if (PLAYER_SAID (R, we_here_to_help) + || PLAYER_SAID (R, we_need_help)) + { + if (PLAYER_SAID (R, we_here_to_help)) + NPCPhrase (NEED_HELP); + else + NPCPhrase (GIVE_HELP); + NPCPhrase (ALMOST_ALLIANCE); + + SET_GAME_STATE (PKUNK_MANNER, 3); + SET_GAME_STATE (PKUNK_VISITS, 0); + SET_GAME_STATE (PKUNK_HOME_VISITS, 0); + SET_GAME_STATE (PKUNK_INFO, 0); + + AddEvent (RELATIVE_EVENT, 6, 0, 0, ADVANCE_PKUNK_MISSION); + if (ActivateStarShip (PKUNK_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (INIT_NO_ROOM); + else + { + NPCPhrase (INIT_SHIP_GIFT); + AlienTalkSegue ((COUNT)~0); + PrepareShip (); + } + } + else if (PLAYER_SAID (R, try_to_be_nicer)) + { + NPCPhrase (CANT_ASK_FOR_MORE); + NPCPhrase (VISIT_OUR_HOMEWORLD); + + SET_GAME_STATE (PKUNK_MANNER, 3); + SET_GAME_STATE (PKUNK_VISITS, 0); + SET_GAME_STATE (PKUNK_HOME_VISITS, 0); + SET_GAME_STATE (PKUNK_INFO, 0); + } + else if (PLAYER_SAID (R, must_conquer) + || PLAYER_SAID (R, obey)) + { + if (PLAYER_SAID (R, obey)) + NPCPhrase (NO_OBEY); + else + { + NPCPhrase (BAD_IDEA); + + SET_GAME_STATE (PKUNK_MANNER, 2); + } + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, die_idiot_fools)) + { + NPCPhrase (VERY_WELL); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, suit_yourself)) + NPCPhrase (GOODBYE_MIGRATION); + else + { + BYTE ReasonMask; + + ReasonMask = GET_GAME_STATE (PKUNK_REASONS); + if (PLAYER_SAID (R, good_reason_1)) + { + NPCPhrase (WE_GO_HOME_1); + ReasonMask |= GOOD_REASON_1; + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_PKUNK_MISSION); + } + else if (PLAYER_SAID (R, good_reason_2)) + { + NPCPhrase (WE_GO_HOME_2); + ReasonMask |= GOOD_REASON_2; + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_PKUNK_MISSION); + } + else if (PLAYER_SAID (R, bad_reason_1)) + { + NPCPhrase (NO_GO_HOME_1); + ReasonMask |= BAD_REASON_1; + } + else if (PLAYER_SAID (R, bad_reason_2)) + { + NPCPhrase (NO_GO_HOME_2); + ReasonMask |= BAD_REASON_2; + } + SET_GAME_STATE (PKUNK_REASONS, ReasonMask); + } +} + +static void PkunkHome (RESPONSE_REF R); + +static void +PkunkAngry (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, why_insults)) + { + NPCPhrase (RELEASE_TENSION); + + DISABLE_PHRASE (why_insults); + } + else if (PLAYER_SAID (R, what_about_you)) + { + NPCPhrase (ABOUT_US); + + DISABLE_PHRASE (what_about_you); + } + else if (PLAYER_SAID (R, should_be_friends)) + { + NPCPhrase (YES_FRIENDS); + + DISABLE_PHRASE (should_be_friends); + } + + if (PHRASE_ENABLED (should_be_friends)) + { + Response (should_be_friends, PkunkAngry); + } + else + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + Response (try_to_be_nicer, PkunkHome); + else + Response (try_to_be_nicer, ExitConversation); + } + Response (die_idiot_fools, ExitConversation); + if (PHRASE_ENABLED (why_insults)) + Response (why_insults, PkunkAngry); + if (PHRASE_ENABLED (what_about_you)) + Response (what_about_you, PkunkAngry); + Response (bye_angry, ExitConversation); +} + +static void +DiscussConquer (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_conquer)) + { + NPCPhrase (WHY_CONQUER); + + DISABLE_PHRASE (we_conquer); + } + else if (PLAYER_SAID (R, conquer_because_1)) + { + NPCPhrase (NOT_CONQUER_10); + NPCPhrase (GLOBAL_ALLIANCE_NAME + name_1); + NPCPhrase (NOT_CONQUER_11); + NPCPhrase (GLOBAL_ALLIANCE_NAME + name_1); + NPCPhrase (NOT_CONQUER_12); + + DISABLE_PHRASE (conquer_because_1); + } + else if (PLAYER_SAID (R, conquer_because_2)) + { + NPCPhrase (NOT_CONQUER_2); + + DISABLE_PHRASE (conquer_because_2); + } + + if (PHRASE_ENABLED (conquer_because_1)) + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + conquer_because_1, + (vararg_dcl)buf, + (RESPONSE_REF)-1 + ); + DoResponsePhrase (conquer_because_1, DiscussConquer, shared_phrase_buf); + } + if (PHRASE_ENABLED (conquer_because_2)) + Response (conquer_because_2, DiscussConquer); + Response (must_conquer, ExitConversation); + Response (no_conquest, PkunkHome); +} + +static void +OfferAlliance (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_are_vindicator0)) + NPCPhrase (WHY_YOU_HERE); + else if (PLAYER_SAID (R, exploring_universe)) + { + NPCPhrase (SENSE_DEEPER_CONFLICT); + + DISABLE_PHRASE (exploring_universe); + } + else if (PLAYER_SAID (R, fun_cruise)) + { + NPCPhrase (REPRESS); + + DISABLE_PHRASE (fun_cruise); + } + + Response (we_here_to_help, ExitConversation); + Response (we_need_help, ExitConversation); + if (PHRASE_ENABLED (exploring_universe)) + Response (exploring_universe, OfferAlliance); + if (PHRASE_ENABLED (fun_cruise)) + Response (fun_cruise, OfferAlliance); +} + +static void +AboutPkunk (RESPONSE_REF R) +{ + BYTE InfoLeft; + + InfoLeft = FALSE; + if (PLAYER_SAID (R, what_about_you)) + NPCPhrase (ABOUT_US); + else if (PLAYER_SAID (R, what_about_history)) + { + NPCPhrase (ABOUT_HISTORY); + + DISABLE_PHRASE (what_about_history); + } + else if (PLAYER_SAID (R, what_about_yehat)) + { + NPCPhrase (ABOUT_YEHAT); + + DISABLE_PHRASE (what_about_yehat); + } + else if (PLAYER_SAID (R, what_about_culture)) + { + NPCPhrase (ABOUT_CULTURE); + + DISABLE_PHRASE (what_about_culture); + } + else if (PLAYER_SAID (R, elaborate_culture)) + { + NPCPhrase (OK_ELABORATE_CULTURE); + + DISABLE_PHRASE (elaborate_culture); + } + else if (PLAYER_SAID (R, what_about_future)) + { + NPCPhrase (ABOUT_FUTURE); + + DISABLE_PHRASE (what_about_future); + } + + if (PHRASE_ENABLED (what_about_history)) + { + Response (what_about_history, AboutPkunk); + InfoLeft = TRUE; + } + else if (PHRASE_ENABLED (what_about_yehat)) + { + Response (what_about_yehat, AboutPkunk); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_culture)) + { + Response (what_about_culture, AboutPkunk); + InfoLeft = TRUE; + } + else if (PHRASE_ENABLED (elaborate_culture)) + { + Response (elaborate_culture, AboutPkunk); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_future)) + { + Response (what_about_future, AboutPkunk); + InfoLeft = TRUE; + } + Response (enough_about_you, PkunkHome); + + if (!InfoLeft) + { + DISABLE_PHRASE (what_about_you); + } +} + +static void +AboutIlwrath (RESPONSE_REF R) +{ + BYTE InfoLeft; + + InfoLeft = FALSE; + if (PLAYER_SAID (R, what_about_ilwrath)) + NPCPhrase (ABOUT_ILWRATH); + else if (PLAYER_SAID (R, why_ilwrath_fight)) + { + NPCPhrase (ILWRATH_FIGHT_BECAUSE); + + DISABLE_PHRASE (why_ilwrath_fight); + } + else if (PLAYER_SAID (R, when_fight_start)) + { + NPCPhrase (FIGHT_START_WHEN); + + DISABLE_PHRASE (when_fight_start); + } + else if (PLAYER_SAID (R, how_goes_fight)) + { + NPCPhrase (FIGHT_GOES); + + DISABLE_PHRASE (how_goes_fight); + } + else if (PLAYER_SAID (R, how_stop_fight)) + { + NPCPhrase (STOP_FIGHT_LIKE_SO); + + DISABLE_PHRASE (how_stop_fight); + } + + if (PHRASE_ENABLED (why_ilwrath_fight)) + { + Response (why_ilwrath_fight, AboutIlwrath); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (when_fight_start)) + { + Response (when_fight_start, AboutIlwrath); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (how_goes_fight)) + { + Response (how_goes_fight, AboutIlwrath); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (how_stop_fight)) + { + Response (how_stop_fight, AboutIlwrath); + InfoLeft = TRUE; + } + Response (enough_ilwrath, PkunkHome); + + if (!InfoLeft) + { + DISABLE_PHRASE (what_about_ilwrath); + } +} + +static void +PkunkHome (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, no_conquest)) + NPCPhrase (GOOD_IDEA); + else if (PLAYER_SAID (R, enough_ilwrath)) + NPCPhrase (OK_ENOUGH_ILWRATH); + else if (PLAYER_SAID (R, enough_about_you)) + NPCPhrase (OK_ENOUGH_ABOUT_US); + else if (PLAYER_SAID (R, where_fleet_1) + || PLAYER_SAID (R, where_fleet_2) + || PLAYER_SAID (R, where_fleet_3)) + { + SET_GAME_STATE (PKUNK_SWITCH, 1); + if (!(GET_GAME_STATE (PKUNK_MISSION) & 1)) + { + NumVisits = GET_GAME_STATE (PKUNK_RETURN); + switch (NumVisits++) + { + case 0: + NPCPhrase (RETURNING_FROM_YEHAT_1); + break; + case 1: + NPCPhrase (RETURNING_FROM_YEHAT_2); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_RETURN, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (PKUNK_MIGRATE); + switch (NumVisits++) + { + case 0: + NPCPhrase (MIGRATING_HOMEWORLD_1); + break; + case 1: + NPCPhrase (MIGRATING_HOMEWORLD_2); + break; + case 2: + NPCPhrase (MIGRATING_HOMEWORLD_3); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_MIGRATE, NumVisits); + } + + NumVisits = GET_GAME_STATE (PKUNK_FLEET) + 1; + SET_GAME_STATE (PKUNK_FLEET, NumVisits); + + DISABLE_PHRASE (where_fleet_1); + } + else if (PLAYER_SAID (R, am_worried_1) + || PLAYER_SAID (R, am_worried_2) + || PLAYER_SAID (R, am_worried_3)) + { + NumVisits = GET_GAME_STATE (PKUNK_WORRY); + switch (NumVisits++) + { + case 0: + NPCPhrase (DONT_WORRY_1); + break; + case 1: + NPCPhrase (DONT_WORRY_2); + break; + case 2: + NPCPhrase (DONT_WORRY_3); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_WORRY, NumVisits); + + DISABLE_PHRASE (am_worried_1); + } + else if (PLAYER_SAID (R, try_to_be_nicer)) + { + NPCPhrase (CANT_ASK_FOR_MORE); + if (!GET_GAME_STATE (CLEAR_SPINDLE)) + { + NPCPhrase (GIVE_SPINDLE); + + SET_GAME_STATE (CLEAR_SPINDLE, 1); + SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); + } + NPCPhrase (CAN_BE_FRIENDS); + + SET_GAME_STATE (PKUNK_MANNER, 3); + SET_GAME_STATE (PKUNK_VISITS, 0); + SET_GAME_STATE (PKUNK_HOME_VISITS, 0); + } + else if (PLAYER_SAID (R, what_about_ilwrath)) + { + NPCPhrase (ABOUT_ILWRATH /* ILWRATH_GONE */); + + DISABLE_PHRASE (what_about_ilwrath); + } + + if (PHRASE_ENABLED (we_conquer) && GET_GAME_STATE (PKUNK_MANNER) == 0) + { + Response (we_conquer, DiscussConquer); + } + if (GET_GAME_STATE (PKUNK_ON_THE_MOVE)) + { + if (PHRASE_ENABLED (where_fleet_1) && !GET_GAME_STATE (PKUNK_SWITCH)) + { + switch (GET_GAME_STATE (PKUNK_FLEET)) + { + case 0: + Response (where_fleet_1, PkunkHome); + break; + case 1: + Response (where_fleet_2, PkunkHome); + break; + case 2: + Response (where_fleet_3, PkunkHome); + break; + } + } + else if (!PHRASE_ENABLED (where_fleet_1) + && PHRASE_ENABLED (am_worried_1) + && (GET_GAME_STATE (PKUNK_MISSION) & 1)) + { + switch (GET_GAME_STATE (PKUNK_WORRY)) + { + case 0: + Response (am_worried_1, PkunkHome); + break; + case 1: + Response (am_worried_2, PkunkHome); + break; + case 2: + Response (am_worried_3, PkunkHome); + break; + } + } + } + if (!GET_GAME_STATE (PKUNK_SHIP_MONTH)) + { + construct_response (shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0); + DoResponsePhrase (we_are_vindicator0, OfferAlliance, shared_phrase_buf); + } + if (PHRASE_ENABLED (what_about_you)) + { + Response (what_about_you, AboutPkunk); + } + if (PHRASE_ENABLED (what_about_ilwrath)) + { + if (!GET_GAME_STATE (ILWRATH_DECEIVED)) + { + Response (what_about_ilwrath, AboutIlwrath); + } + else + { + Response (what_about_ilwrath, PkunkHome); + } + } + Response (bye_friendly, ExitConversation); +} + +static void +PkunkFriendlySpace (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_space)) + { + if (ShipsReady ()) + NPCPhrase (SHIPS_AT_HOME); + else + { + NumVisits = GET_GAME_STATE (PKUNK_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_SPACE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_SPACE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_SPACE_4); + break; + case 4: + NPCPhrase (GENERAL_INFO_SPACE_5); + break; + case 5: + NPCPhrase (GENERAL_INFO_SPACE_6); + break; + case 6: + NPCPhrase (GENERAL_INFO_SPACE_7); + break; + case 7: + NPCPhrase (GENERAL_INFO_SPACE_8); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_INFO, NumVisits); + } + + DISABLE_PHRASE (whats_up_space); + } + else if (PLAYER_SAID (R, how_goes_war)) + { + NumVisits = GET_GAME_STATE (PKUNK_WAR); + switch (NumVisits++) + { + case 0: + NPCPhrase (WAR_GOES_1); + SET_GAME_STATE (KNOW_URQUAN_STORY, 1); + SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1) + break; + case 1: + NPCPhrase (WAR_GOES_2); + break; + case 2: + NPCPhrase (WAR_GOES_3); + break; + case 3: + NPCPhrase (WAR_GOES_4); + SET_GAME_STATE (PKUNK_DONE_WAR, 1); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_WAR, NumVisits); + + DISABLE_PHRASE (how_goes_war); + } + else if (PLAYER_SAID (R, tell_my_fortune)) + { + NumVisits = GET_GAME_STATE (PKUNK_FORTUNE); + switch (NumVisits++) + { + case 0: + NPCPhrase (FORTUNE_IS_1); + break; + case 1: + NPCPhrase (FORTUNE_IS_2); + break; + case 2: + NPCPhrase (FORTUNE_IS_3); + break; + case 3: + NPCPhrase (FORTUNE_IS_4); + break; + case 4: + NPCPhrase (FORTUNE_IS_5); + break; + case 5: + NPCPhrase (FORTUNE_IS_6); + break; + case 6: + NPCPhrase (FORTUNE_IS_7); + break; + case 7: + NPCPhrase (FORTUNE_IS_8); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_FORTUNE, NumVisits); + + DISABLE_PHRASE (tell_my_fortune); + } + + if (PHRASE_ENABLED (whats_up_space)) + Response (whats_up_space, PkunkFriendlySpace); + if (!GET_GAME_STATE (PKUNK_DONE_WAR) && PHRASE_ENABLED (how_goes_war)) + Response (how_goes_war, PkunkFriendlySpace); + if (PHRASE_ENABLED (tell_my_fortune)) + Response (tell_my_fortune, PkunkFriendlySpace); + Response (friendly_bye_space, ExitConversation); +} + +static void +PkunkNeutralSpace (RESPONSE_REF R) +{ + BYTE NumVisits; + //PTR_DESC PtrDesc; + + if (PLAYER_SAID (R, form_alliance)) + { + NPCPhrase (GO_TO_HOMEWORLD); + + DISABLE_PHRASE (form_alliance); + } + else if (PLAYER_SAID (R, can_you_help)) + { + NPCPhrase (GO_TO_HOMEWORLD_AGAIN); + + DISABLE_PHRASE (can_you_help); + } + else if (PLAYER_SAID (R, hostile_greeting)) + { + NPCPhrase (DONT_BE_HOSTILE); + + DISABLE_PHRASE (hostile_greeting); + } + else if (PLAYER_SAID (R, whats_up_neutral)) + { + NumVisits = GET_GAME_STATE (PKUNK_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_SPACE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_SPACE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_SPACE_4); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_neutral); + } + + if (PHRASE_ENABLED (form_alliance)) + Response (form_alliance, PkunkNeutralSpace); + else if (PHRASE_ENABLED (can_you_help)) + Response (can_you_help, PkunkNeutralSpace); + if (PHRASE_ENABLED (hostile_greeting)) + Response (hostile_greeting, PkunkNeutralSpace); + else + { + Response (obey, ExitConversation); + } + if (PHRASE_ENABLED (whats_up_neutral)) + Response (whats_up_neutral, PkunkNeutralSpace); + Response (neutral_bye_space, ExitConversation); +} + +static void +PkunkMigrate (RESPONSE_REF R) +{ + BYTE ReasonMask; + + ReasonMask = GET_GAME_STATE (PKUNK_REASONS); + if (!(ReasonMask & GOOD_REASON_1)) + Response (good_reason_1, ExitConversation); + if (!(ReasonMask & BAD_REASON_1)) + Response (bad_reason_1, ExitConversation); + if (!(ReasonMask & GOOD_REASON_2)) + Response (good_reason_2, ExitConversation); + if (!(ReasonMask & BAD_REASON_2)) + Response (bad_reason_2, ExitConversation); + Response (suit_yourself, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits, Manner; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + Manner = GET_GAME_STATE (PKUNK_MANNER); + if (Manner == 2) + { + NumVisits = GET_GAME_STATE (PKUNK_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HATE_YOU_FOREVER_1); + break; + case 1: + NPCPhrase (HATE_YOU_FOREVER_2); + break; + case 2: + NPCPhrase (HATE_YOU_FOREVER_3); + break; + case 3: + NPCPhrase (HATE_YOU_FOREVER_4); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (Manner == 1) + { + NumVisits = GET_GAME_STATE (PKUNK_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (SPIRITUAL_PROBLEMS_1); + break; + case 1: + NPCPhrase (SPIRITUAL_PROBLEMS_2); + break; + case 2: + NPCPhrase (SPIRITUAL_PROBLEMS_3); + break; + case 3: + NPCPhrase (SPIRITUAL_PROBLEMS_4); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_VISITS, NumVisits); + + PkunkAngry ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + if (!GET_GAME_STATE (CLEAR_SPINDLE)) + { + NPCPhrase (GIVE_SPINDLE); + + SET_GAME_STATE (CLEAR_SPINDLE, 1); + SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); + } + else if (!GET_GAME_STATE (PKUNK_SENSE_VICTOR) + && GLOBAL (GameClock.year_index) > START_YEAR + && !GET_GAME_STATE (KOHR_AH_FRENZY)) + { + NPCPhrase (SENSE_KOHRAH_VICTORY); + + SET_GAME_STATE (PKUNK_SENSE_VICTOR, 1); + } + + NumVisits = GET_GAME_STATE (PKUNK_HOME_VISITS); + if (Manner == 0) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + } + else + { + if (NumVisits && ShipsReady ()) + { + if (ActivateStarShip (PKUNK_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (NO_ROOM); + else + { + NPCPhrase (SHIP_GIFT); + PrepareShip (); + } + } + else switch (NumVisits++) + { + case 0: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_4); + break; + case 4: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_5); + break; + case 5: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_6); + break; + case 6: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_7); + break; + case 7: + NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_8); + --NumVisits; + break; + } + } + SET_GAME_STATE (PKUNK_HOME_VISITS, NumVisits); + + PkunkHome ((RESPONSE_REF)0); + } + else if ((NumVisits = GET_GAME_STATE (PKUNK_MISSION)) == 0 + || !(NumVisits & 1)) + { + NumVisits = GET_GAME_STATE (PKUNK_VISITS); + if (Manner == 3) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (FRIENDLY_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (FRIENDLY_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (FRIENDLY_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (FRIENDLY_SPACE_HELLO_4); + break; + case 4: + NPCPhrase (FRIENDLY_SPACE_HELLO_5); + break; + case 5: + NPCPhrase (FRIENDLY_SPACE_HELLO_6); + break; + case 6: + NPCPhrase (FRIENDLY_SPACE_HELLO_7); + break; + case 7: + NPCPhrase (FRIENDLY_SPACE_HELLO_8); + --NumVisits; + break; + } + + PkunkFriendlySpace ((RESPONSE_REF)0); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (NEUTRAL_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (NEUTRAL_SPACE_HELLO_4); + --NumVisits; + break; + } + + PkunkNeutralSpace ((RESPONSE_REF)0); + } + SET_GAME_STATE (PKUNK_VISITS, NumVisits); + + } + else + { + NumVisits = GET_GAME_STATE (PKUNK_MIGRATE_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (MIGRATING_SPACE_1); + break; + case 1: + NPCPhrase (MIGRATING_SPACE_2); + break; + case 2: + NPCPhrase (MIGRATING_SPACE_3); + break; + case 3: + NPCPhrase (MIGRATING_SPACE_4); + break; + case 4: + NPCPhrase (MIGRATING_SPACE_5); + break; + case 5: + NPCPhrase (MIGRATING_SPACE_6); + break; + case 6: + NPCPhrase (MIGRATING_SPACE_7); + break; + case 7: + NPCPhrase (MIGRATING_SPACE_8); + --NumVisits; + break; + } + SET_GAME_STATE (PKUNK_MIGRATE_VISITS, NumVisits); + + PkunkMigrate ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_pkunk (void) +{ + BYTE Manner; + + if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && (Manner = GET_GAME_STATE (PKUNK_MANNER)) != 2) + { + SET_GAME_STATE (PKUNK_MANNER, 1); + if (Manner != 1) + { + SET_GAME_STATE (PKUNK_VISITS, 0); + SET_GAME_STATE (PKUNK_HOME_VISITS, 0); + } + } + + return (0); +} + +LOCDATAPTR +init_pkunk_comm (void) +{ + LOCDATAPTR retval; + + //PTR_DESC PtrDesc; + + pkunk_desc.init_encounter_func = Intro; + pkunk_desc.uninit_encounter_func = uninit_pkunk; + + pkunk_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + pkunk_desc.AlienTextTemplate.baseline.y = 0; + pkunk_desc.AlienTextTemplate.align = ALIGN_CENTER; + pkunk_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (PKUNK_MANNER) == 3 + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &pkunk_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/pkunk/resinst.h b/sc2/src/sc2code/comm/pkunk/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/pkunk/respkg.h b/sc2/src/sc2code/comm/pkunk/respkg.h new file mode 100644 index 000000000..c804d87cf --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/respkg.h @@ -0,0 +1,5 @@ +enum +{ + PKUNK_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/pkunk/restypes.h b/sc2/src/sc2code/comm/pkunk/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/pkunk/strings.h b/sc2/src/sc2code/comm/pkunk/strings.h new file mode 100644 index 000000000..af6d67166 --- /dev/null +++ b/sc2/src/sc2code/comm/pkunk/strings.h @@ -0,0 +1,210 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + GIVE_SPINDLE, + name_1, + name_2, + name_3, + name_40, + name_41, + NEUTRAL_SPACE_HELLO_1, + NEUTRAL_SPACE_HELLO_3, + NEUTRAL_SPACE_HELLO_2, + NEUTRAL_SPACE_HELLO_4, + FRIENDLY_SPACE_HELLO_1, + FRIENDLY_SPACE_HELLO_2, + FRIENDLY_SPACE_HELLO_3, + FRIENDLY_SPACE_HELLO_4, + FRIENDLY_SPACE_HELLO_5, + FRIENDLY_SPACE_HELLO_6, + FRIENDLY_SPACE_HELLO_7, + FRIENDLY_SPACE_HELLO_8, + NEUTRAL_HOMEWORLD_HELLO_1, + NEUTRAL_HOMEWORLD_HELLO_2, + NEUTRAL_HOMEWORLD_HELLO_3, + NEUTRAL_HOMEWORLD_HELLO_4, + FRIENDLY_HOMEWORLD_HELLO_1, + FRIENDLY_HOMEWORLD_HELLO_2, + FRIENDLY_HOMEWORLD_HELLO_3, + FRIENDLY_HOMEWORLD_HELLO_4, + FRIENDLY_HOMEWORLD_HELLO_5, + FRIENDLY_HOMEWORLD_HELLO_6, + FRIENDLY_HOMEWORLD_HELLO_7, + FRIENDLY_HOMEWORLD_HELLO_8, + whats_up_neutral, + GENERAL_INFO_NEUTRAL_1, + GENERAL_INFO_NEUTRAL_2, + GENERAL_INFO_NEUTRAL_3, + GENERAL_INFO_NEUTRAL_4, + good_reason_1, + WE_GO_HOME_1, + good_reason_2, + WE_GO_HOME_2, + bad_reason_1, + NO_GO_HOME_1, + bad_reason_2, + NO_GO_HOME_2, + SENSE_KOHRAH_VICTORY, + SPIRITUAL_PROBLEMS_1, + SPIRITUAL_PROBLEMS_2, + SPIRITUAL_PROBLEMS_3, + SPIRITUAL_PROBLEMS_4, + HATE_YOU_FOREVER_1, + HATE_YOU_FOREVER_2, + HATE_YOU_FOREVER_3, + HATE_YOU_FOREVER_4, + MIGRATING_SPACE_1, + MIGRATING_SPACE_2, + MIGRATING_SPACE_3, + MIGRATING_SPACE_4, + MIGRATING_SPACE_5, + MIGRATING_SPACE_6, + MIGRATING_SPACE_7, + MIGRATING_SPACE_8, + die_idiot_fools, + VERY_WELL, + why_insults, + RELEASE_TENSION, + what_about_you_angry, + ABOUT_US_ANGRY, + what_about_you, + should_be_friends, + YES_FRIENDS, + try_to_be_nicer, + CANT_ASK_FOR_MORE, + VISIT_OUR_HOMEWORLD, + CAN_BE_FRIENDS, + bye_angry, + GOODBYE_ANGRY, + we_conquer, + WHY_CONQUER, + conquer_because_1, + NOT_CONQUER_10, + NOT_CONQUER_11, + NOT_CONQUER_12, + conquer_because_2, + NOT_CONQUER_2, + must_conquer, + BAD_IDEA, + no_conquest, + GOOD_IDEA, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + WHY_YOU_HERE, + we_here_to_help, + NEED_HELP, + we_need_help, + GIVE_HELP, + exploring_universe, + SENSE_DEEPER_CONFLICT, + fun_cruise, + REPRESS, + why_ilwrath_fight, + ILWRATH_FIGHT_BECAUSE, + when_fight_start, + FIGHT_START_WHEN, + how_goes_fight, + FIGHT_GOES, + how_goes_war, + WAR_GOES_1, + WAR_GOES_2, + WAR_GOES_3, + WAR_GOES_4, + how_stop_fight, + STOP_FIGHT_LIKE_SO, + enough_ilwrath, + OK_ENOUGH_ILWRATH, + what_about_history, + ABOUT_HISTORY, + what_about_yehat, + ABOUT_YEHAT, + what_about_culture, + ABOUT_CULTURE, + elaborate_culture, + OK_ELABORATE_CULTURE, + what_about_future, + ABOUT_FUTURE, + enough_about_you, + OK_ENOUGH_ABOUT_US, + ABOUT_US, + where_fleet_1, + where_fleet_2, + where_fleet_3, + MIGRATING_HOMEWORLD_1, + MIGRATING_HOMEWORLD_2, + MIGRATING_HOMEWORLD_3, + RETURNING_FROM_YEHAT_1, + RETURNING_FROM_YEHAT_2, + am_worried_1, + am_worried_2, + am_worried_3, + DONT_WORRY_1, + DONT_WORRY_2, + DONT_WORRY_3, + form_alliance, + GO_TO_HOMEWORLD, + can_you_help, + GO_TO_HOMEWORLD_AGAIN, + hostile_greeting, + DONT_BE_HOSTILE, + obey, + NO_OBEY, + neutral_bye_space, + NEUTRAL_GOODBYE_SPACE, + SHIP_GIFT, + NO_ROOM, + friendly_bye_space, + FRIENDLY_GOODBYE_SPACE, + bye_friendly, + GOODBYE_FRIENDLY, + ALMOST_ALLIANCE, + INIT_NO_ROOM, + INIT_SHIP_GIFT, + suit_yourself, + GOODBYE_MIGRATION, + what_about_ilwrath, + ABOUT_ILWRATH, + whats_up_space, + SHIPS_AT_HOME, + GENERAL_INFO_SPACE_1, + GENERAL_INFO_SPACE_2, + GENERAL_INFO_SPACE_3, + GENERAL_INFO_SPACE_4, + GENERAL_INFO_SPACE_5, + GENERAL_INFO_SPACE_6, + GENERAL_INFO_SPACE_7, + GENERAL_INFO_SPACE_8, + tell_my_fortune, + FORTUNE_IS_1, + FORTUNE_IS_2, + FORTUNE_IS_3, + FORTUNE_IS_4, + FORTUNE_IS_5, + FORTUNE_IS_6, + FORTUNE_IS_7, + FORTUNE_IS_8, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/rebel/rebel.c b/sc2/src/sc2code/comm/rebel/rebel.c new file mode 100644 index 000000000..5dd2138ba --- /dev/null +++ b/sc2/src/sc2code/comm/rebel/rebel.c @@ -0,0 +1,426 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/yehat/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/rebel/strings.h" + +static LOCDATA yehat_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)YEHAT_PMAP_ANIM, /* AlienFrame */ + (FONT)YEHAT_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* (SIS_TEXT_WIDTH - 16) * 2 / 3, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + YEHAT_MUSIC, /* AlienSong */ + REBEL_CONVERSATION_PHRASES, /* PlayerPhrases */ + 15, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), + }, + { + 7, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), + }, + { + 10, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4) | (1 << 14), + }, + { + 13, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), + }, + { + 16, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ + (1 << 2) | (1 << 14), + }, + { + 21, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ + (1 << 3), + }, + { + 26, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ + (1 << 0) | (1 << 1), + }, + { + 28, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ + (1 << 0) | (1 << 1), + }, + { + 30, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 33, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 36, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 39, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 42, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 45, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 48, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 2) | (1 << 4), + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +PrepareShip (void) +{ + BYTE mi, di, yi; + + mi = (GLOBAL (GameClock.month_index) % 12) + 1; + SET_GAME_STATE (YEHAT_SHIP_MONTH, mi); + if ((di = GLOBAL (GameClock.day_index)) > 28) + di = 28; + SET_GAME_STATE (YEHAT_SHIP_DAY, di); + yi = (BYTE)(GLOBAL (GameClock.year_index) - START_YEAR); + if (mi == 1) + ++yi; + SET_GAME_STATE (YEHAT_SHIP_YEAR, yi); +} + +static void +ExitConversation (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, bye_rebel)) + NPCPhrase (GOODBYE_REBEL); +} + +static void Rebels (RESPONSE_REF R); + +static void +RebelInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + //PTR_DESC PtrDesc; + + InfoLeft = FALSE; + if (PLAYER_SAID (R, give_info_rebels)) + NPCPhrase (WHAT_INFO); + else if (PLAYER_SAID (R, what_about_urquan)) + { + NPCPhrase (ABOUT_URQUAN); + + DISABLE_PHRASE (what_about_urquan); + } + else if (PLAYER_SAID (R, what_about_royalty)) + { + NPCPhrase (ABOUT_ROYALTY); + + DISABLE_PHRASE (what_about_royalty); + } + else if (PLAYER_SAID (R, what_about_war)) + { + NPCPhrase (ABOUT_WAR); + + DISABLE_PHRASE (what_about_war); + } + else if (PLAYER_SAID (R, what_about_vux)) + { + NPCPhrase (ABOUT_VUX); + + DISABLE_PHRASE (what_about_vux); + } + else if (PLAYER_SAID (R, what_about_clue)) + { + NPCPhrase (ABOUT_CLUE); + + DISABLE_PHRASE (what_about_clue); + } + + if (PHRASE_ENABLED (what_about_urquan)) + { + Response (what_about_urquan, RebelInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_royalty)) + { + Response (what_about_royalty, RebelInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_war)) + { + Response (what_about_war, RebelInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_vux)) + { + Response (what_about_vux, RebelInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_clue)) + { + Response (what_about_clue, RebelInfo); + InfoLeft = TRUE; + } + Response (enough_info, Rebels); + + if (!InfoLeft) + { + DISABLE_PHRASE (give_info_rebels); + } +} + +static void +Rebels (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, how_goes_revolution)) + { + NumVisits = GET_GAME_STATE (YEHAT_REBEL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (REBEL_REVOLUTION_1); + break; + case 1: + NPCPhrase (REBEL_REVOLUTION_2); + break; + case 2: + NPCPhrase (REBEL_REVOLUTION_3); + break; + case 3: + NPCPhrase (REBEL_REVOLUTION_4); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_REBEL_INFO, NumVisits); + + DISABLE_PHRASE (how_goes_revolution); + } + else if (PLAYER_SAID (R, any_ships)) + { + if (GET_GAME_STATE (YEHAT_SHIP_MONTH) + && ((NumVisits = (GLOBAL (GameClock.year_index) - START_YEAR) + - GET_GAME_STATE (YEHAT_SHIP_YEAR)) < 0 + || (NumVisits == 0 + && (NumVisits = GLOBAL (GameClock.month_index) - + GET_GAME_STATE (YEHAT_SHIP_MONTH)) < 0 + || (NumVisits == 0 + && GLOBAL (GameClock.day_index) < + GET_GAME_STATE (YEHAT_SHIP_DAY))))) + NPCPhrase (NO_SHIPS_YET); + else if ((NumVisits = ActivateStarShip (YEHAT_SHIP, FEASIBILITY_STUDY)) == 0) + NPCPhrase (NO_ROOM); + else + { +#define NUM_YEHAT_SHIPS 4 + if (NumVisits < NUM_YEHAT_SHIPS) + NPCPhrase (HAVE_FEW_SHIPS); + else + { + NumVisits = NUM_YEHAT_SHIPS; + NPCPhrase (HAVE_ALL_SHIPS); + } + + AlienTalkSegue ((COUNT)~0); + ActivateStarShip (YEHAT_SHIP, NumVisits); + PrepareShip (); + } + + DISABLE_PHRASE (any_ships); + } + else if (PLAYER_SAID (R, what_about_pkunk_rebel)) + { + if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) + NPCPhrase (PKUNK_ABSORBED_REBEL); + else + NPCPhrase (HATE_PKUNK_REBEL); + + SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1); + } + else if (PLAYER_SAID (R, enough_info)) + NPCPhrase (OK_ENOUGH_INFO); + + if (PHRASE_ENABLED (how_goes_revolution)) + Response (how_goes_revolution, Rebels); + if (!GET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK) + && GET_GAME_STATE (PKUNK_VISITS) + && GET_GAME_STATE (PKUNK_HOME_VISITS)) + Response (what_about_pkunk_rebel, Rebels); + if (PHRASE_ENABLED (any_ships)) + Response (any_ships, Rebels); + if (PHRASE_ENABLED (give_info_rebels)) + { + Response (give_info_rebels, RebelInfo); + } + Response (bye_rebel, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + NPCPhrase (YEHAT_CAVALRY); + AlienTalkSegue ((COUNT)~0); + + if ((NumVisits = (BYTE)ActivateStarShip ( + YEHAT_REBEL_SHIP, FEASIBILITY_STUDY + )) > 8) + NumVisits = 8; + ActivateStarShip (YEHAT_REBEL_SHIP, NumVisits - (NumVisits >> 1)); + ActivateStarShip (PKUNK_SHIP, NumVisits >> 1); + } + else + { + NumVisits = GET_GAME_STATE (YEHAT_REBEL_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (REBEL_HELLO_1); + break; + case 1: + NPCPhrase (REBEL_HELLO_2); + break; + case 2: + NPCPhrase (REBEL_HELLO_3); + break; + case 3: + NPCPhrase (REBEL_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_REBEL_VISITS, NumVisits); + + Rebels ((RESPONSE_REF)0); + } +} + +static COUNT +uninit_yehat (void) +{ + return (0); +} + +LOCDATAPTR +init_rebel_yehat_comm (void) +{ + LOCDATAPTR retval; + + yehat_desc.init_encounter_func = Intro; + yehat_desc.uninit_encounter_func = uninit_yehat; + + yehat_desc.AlienTextTemplate.baseline.x = SIS_SCREEN_WIDTH * 2 / 3; + yehat_desc.AlienTextTemplate.baseline.y = 107 * 2 / 3; + yehat_desc.AlienTextTemplate.align = ALIGN_CENTER; + yehat_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) * 2 / 3; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &yehat_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/rebel/strings.h b/sc2/src/sc2code/comm/rebel/strings.h new file mode 100644 index 000000000..370e684ff --- /dev/null +++ b/sc2/src/sc2code/comm/rebel/strings.h @@ -0,0 +1,61 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + REBEL_HELLO_1, + REBEL_HELLO_2, + REBEL_HELLO_3, + REBEL_HELLO_4, + how_goes_revolution, + REBEL_REVOLUTION_1, + REBEL_REVOLUTION_2, + REBEL_REVOLUTION_3, + REBEL_REVOLUTION_4, + any_ships, + NO_ROOM, + HAVE_ALL_SHIPS, + HAVE_FEW_SHIPS, + NO_SHIPS_YET, + give_info_rebels, + WHAT_INFO, + what_about_royalty, + ABOUT_ROYALTY, + what_about_war, + ABOUT_WAR, + what_about_urquan, + ABOUT_URQUAN, + what_about_vux, + ABOUT_VUX, + what_about_clue, + ABOUT_CLUE, + enough_info, + OK_ENOUGH_INFO, + bye_rebel, + GOODBYE_REBEL, + YEHAT_CAVALRY, + what_about_pkunk_rebel, + PKUNK_ABSORBED_REBEL, + HATE_PKUNK_REBEL, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/shofixt/ifontres.h b/sc2/src/sc2code/comm/shofixt/ifontres.h new file mode 100644 index 000000000..d1242647f --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/ifontres.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/shofixt/igfxres.h b/sc2/src/sc2code/comm/shofixt/igfxres.h new file mode 100644 index 000000000..7a92854d7 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/igfxres.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/shofixt/imusicre.h b/sc2/src/sc2code/comm/shofixt/imusicre.h new file mode 100644 index 000000000..4e5e08d0c --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/imusicre.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/shofixt/istrtab.h b/sc2/src/sc2code/comm/shofixt/istrtab.h new file mode 100644 index 000000000..d9b93c667 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/istrtab.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/shofixt/resinst.h b/sc2/src/sc2code/comm/shofixt/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/shofixt/respkg.h b/sc2/src/sc2code/comm/shofixt/respkg.h new file mode 100644 index 000000000..0f7349626 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/respkg.h @@ -0,0 +1,5 @@ +enum +{ + SHOFIXTI_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/shofixt/restypes.h b/sc2/src/sc2code/comm/shofixt/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/shofixt/shofixt.c b/sc2/src/sc2code/comm/shofixt/shofixt.c new file mode 100644 index 000000000..db55d76f5 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/shofixt.c @@ -0,0 +1,637 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/shofixt/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/shofixt/strings.h" + +static LOCDATA shofixti_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SHOFIXTI_PMAP_ANIM, /* AlienFrame */ + (FONT)SHOFIXTI_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + SHOFIXTI_MUSIC, /* AlienSong */ + SHOFIXTI_CONVERSATION_PHRASES, /* PlayerPhrases */ + 11, /* NumAnimations */ + { + { + 5, /* StartIndex */ + 15, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + 4, 0, /* RestartRate */ + }, + { + 20, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + (ONE_SECOND >> 1), (ONE_SECOND >> 1) * 3, /* RestartRate */ + }, + { + 23, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + (ONE_SECOND >> 1), (ONE_SECOND >> 1) * 3, /* RestartRate */ + }, + { + 26, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 29, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + + { + 33, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + }, + { + 39, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + (1 << 7), /* BlockMask */ + }, + { + 46, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + (1 << 6), /* BlockMask */ + }, + { + 52, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + }, + { + 56, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + (1 << 10), /* BlockMask */ + }, + { + 63, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 4, /* FrameRate */ + 6, 4, /* RestartRate */ + (1 << 9), /* BlockMask */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 4, /* NumFrames */ + 0, /* AnimFlags */ + 6, 0, /* FrameRate */ + 8, 0, /* RestartRate */ + }, +}; + +static RESPONSE_REF shofixti_name; + +static void +GetShofixtiName (void) +{ + if (GET_GAME_STATE (SHOFIXTI_KIA)) + shofixti_name = katana; + else + shofixti_name = tanaka; +} + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye0)) + { + NPCPhrase (GOODBYE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, go_ahead)) + { + NPCPhrase (ON_SECOND_THOUGHT); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, need_you_for_duty)) + { + NPCPhrase (OK_WILL_BE_SENTRY); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, females) + || PLAYER_SAID (R, nubiles) + || PLAYER_SAID (R, rat_babes)) + { + NPCPhrase (LEAPING_HAPPINESS); + + SET_GAME_STATE (SHOFIXTI_RECRUITED, 1); + SET_GAME_STATE (MAIDENS_ON_SHIP, 0); + SET_GAME_STATE (BATTLE_SEGUE, 0); + + AddEvent (RELATIVE_EVENT, 2, 0, 0, SHOFIXTI_RETURN_EVENT); + } + else if (PLAYER_SAID (R, dont_attack)) + { + NPCPhrase (TYPICAL_PLOY); + + SET_GAME_STATE (SHOFIXTI_STACK1, 1); + } + else if (PLAYER_SAID (R, hey_stop)) + { + NPCPhrase (ONLY_STOP); + + SET_GAME_STATE (SHOFIXTI_STACK1, 2); + } + else if (PLAYER_SAID (R, look_you_are)) + { + NPCPhrase (TOO_BAD); + + SET_GAME_STATE (SHOFIXTI_STACK1, 3); + } + else if (PLAYER_SAID (R, no_one_insults)) + { + NPCPhrase (YOU_LIMP); + + SET_GAME_STATE (SHOFIXTI_STACK2, 1); + } + else if (PLAYER_SAID (R, mighty_words)) + { + NPCPhrase (HANG_YOUR); + + SET_GAME_STATE (SHOFIXTI_STACK2, 2); + } + else if (PLAYER_SAID (R, dont_know)) + { + NPCPhrase (NEVER); + + SET_GAME_STATE (SHOFIXTI_STACK3, 1); + } + else if (PLAYER_SAID (R, look0)) + { + NPCPhrase (FOR_YOU); + + SET_GAME_STATE (SHOFIXTI_STACK3, 2); + } + else if (PLAYER_SAID (R, no_bloodshed)) + { + NPCPhrase (YES_BLOODSHED); + + SET_GAME_STATE (SHOFIXTI_STACK3, 3); + } + else if (PLAYER_SAID (R, dont_want_to_fight)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SHOFIXTI_STACK4); + switch (NumVisits++) + { + case 0: + NPCPhrase (MUST_FIGHT_YOU_URQUAN_1); + break; + case 1: + NPCPhrase (MUST_FIGHT_YOU_URQUAN_2); + break; + case 2: + NPCPhrase (MUST_FIGHT_YOU_URQUAN_3); + break; + case 3: + NPCPhrase (MUST_FIGHT_YOU_URQUAN_4); + --NumVisits; + break; + } + SET_GAME_STATE (SHOFIXTI_STACK4, NumVisits); + } +} + +static void +GiveMaidens (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, important_duty)) + { + NPCPhrase (WHAT_DUTY); + + Response (procreating_wildly, GiveMaidens); + Response (replenishing_your_species, GiveMaidens); + Response (hope_you_have, GiveMaidens); + } + else + { + NPCPhrase (SOUNDS_GREAT_BUT_HOW); + + Response (females, ExitConversation); + Response (nubiles, ExitConversation); + Response (rat_babes, ExitConversation); + } +} + +static void +ConsoleShofixti (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, dont_do_it)) + { + NPCPhrase (YES_I_DO_IT); + DISABLE_PHRASE (dont_do_it); + } + else + NPCPhrase (VERY_SAD_KILL_SELF); + + if (GET_GAME_STATE (MAIDENS_ON_SHIP)) + { + Response (important_duty, GiveMaidens); + } + if (PHRASE_ENABLED (dont_do_it)) + { + Response (dont_do_it, ConsoleShofixti); + } + Response (need_you_for_duty, ExitConversation); + Response (go_ahead, ExitConversation); +} + +static void +ExplainDefeat (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, i_am_nice)) + NPCPhrase (MUST_UNDERSTAND); + else if (PLAYER_SAID (R, i_am_guy)) + NPCPhrase (NICE_BUT_WHAT_IS_DONKEY); + else /* if (PLAYER_SAID (R, i_am_captain0)) */ + NPCPhrase (SO_SORRY); + NPCPhrase (IS_DEFEAT_TRUE); + + Response (yes_and_no, ConsoleShofixti); + Response (clobbered, ConsoleShofixti); + Response (butt_blasted, ConsoleShofixti); +} + +static void +RealizeMistake (RESPONSE_REF R) +{ + NPCPhrase (DGRUNTI); + SET_GAME_STATE (SHOFIXTI_STACK1, 0); + SET_GAME_STATE (SHOFIXTI_STACK3, 0); + SET_GAME_STATE (SHOFIXTI_STACK2, 3); + + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + i_am_captain0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + i_am_captain1, + buf, + i_am_captain2, + GLOBAL_SIS (ShipName), + i_am_captain3, + 0 + ); + } + DoResponsePhrase (i_am_captain0, ExplainDefeat, shared_phrase_buf); + Response (i_am_nice, ExplainDefeat); + Response (i_am_guy, ExplainDefeat); +} + +static void +Hostile (RESPONSE_REF R) +{ + switch (GET_GAME_STATE (SHOFIXTI_STACK1)) + { + case 0: + Response (dont_attack, ExitConversation); + break; + case 1: + Response (hey_stop, ExitConversation); + break; + case 2: + Response (look_you_are, ExitConversation); + break; + } + switch (GET_GAME_STATE (SHOFIXTI_STACK2)) + { + case 0: + Response (no_one_insults, ExitConversation); + break; + case 1: + Response (mighty_words, ExitConversation); + break; + case 2: + Response (donkey_breath, RealizeMistake); + break; + } + switch (GET_GAME_STATE (SHOFIXTI_STACK3)) + { + case 0: + Response (dont_know, ExitConversation); + break; + case 1: + { + construct_response ( + shared_phrase_buf, + look0, + "", + shofixti_name, + "", + look1, + 0 + ); + DoResponsePhrase (look0, ExitConversation, shared_phrase_buf); + break; + } + case 2: + Response (look_you_are, ExitConversation); + break; + } + Response (dont_want_to_fight, ExitConversation); +} + +static void +Friendly (RESPONSE_REF R) +{ + BYTE i, LastStack; + struct + { + RESPONSE_REF pStr; + UNICODE *c_buf; + } Resp[3]; + static UNICODE buf0[80], buf1[80]; + + LastStack = 0; + memset (Resp, 0, sizeof (Resp)); + if (PLAYER_SAID (R, report0)) + { + NPCPhrase (NOTHING_NEW0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (NOTHING_NEW1); + + DISABLE_PHRASE (report0); + } + else if (PLAYER_SAID (R, why_here0)) + { + NPCPhrase (I_GUARD); + + LastStack = 1; + SET_GAME_STATE (SHOFIXTI_STACK1, 1); + } + else if (PLAYER_SAID (R, what_happened)) + { + NPCPhrase (MET_VUX); + + LastStack = 1; + SET_GAME_STATE (SHOFIXTI_STACK1, 2); + } + else if (PLAYER_SAID (R, glory_device)) + { + NPCPhrase (SWITCH_BROKE); + + SET_GAME_STATE (SHOFIXTI_STACK1, 3); + } + else if (PLAYER_SAID (R, where_world)) + { + NPCPhrase (BLEW_IT_UP); + + LastStack = 2; + SET_GAME_STATE (SHOFIXTI_STACK3, 1); + } + else if (PLAYER_SAID (R, how_survive)) + { + NPCPhrase (NOT_HERE); + + SET_GAME_STATE (SHOFIXTI_STACK3, 2); + } + + if (PHRASE_ENABLED (report0)) + { + construct_response ( + buf0, + report0, + "", + shofixti_name, + "", + report1, + 0 + ); + Resp[0].pStr = report0; + Resp[0].c_buf = buf0; + } + + switch (GET_GAME_STATE (SHOFIXTI_STACK1)) + { + case 0: + construct_response ( + buf1, + why_here0, + "", + shofixti_name, + "", + why_here1, + 0 + ); + Resp[1].pStr = why_here0; + Resp[1].c_buf = buf1; + break; + case 1: + Resp[1].pStr = what_happened; + break; + case 2: + Resp[1].pStr = glory_device; + break; + } + + switch (GET_GAME_STATE (SHOFIXTI_STACK3)) + { + case 0: + Resp[2].pStr = where_world; + break; + case 1: + Resp[2].pStr = how_survive; + break; + } + + if (Resp[LastStack].pStr) + DoResponsePhrase (Resp[LastStack].pStr, Friendly, Resp[LastStack].c_buf); + for (i = 0; i < 3; ++i) + { + if (i != LastStack && Resp[i].pStr) + DoResponsePhrase (Resp[i].pStr, Friendly, Resp[i].c_buf); + } + if (GET_GAME_STATE (MAIDENS_ON_SHIP)) + { + Response (important_duty, GiveMaidens); + } + + construct_response ( + shared_phrase_buf, + bye0, + "", + shofixti_name, + "", + bye1, + 0 + ); + DoResponsePhrase (bye0, ExitConversation, shared_phrase_buf); +} + +static void +Intro (void) +{ + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + GetShofixtiName (); + + if (GET_GAME_STATE (SHOFIXTI_STACK2) > 2) + { + NPCPhrase (FRIENDLY_HELLO0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (FRIENDLY_HELLO1); + NPCPhrase (GLOBAL_SHIP_NAME); + NPCPhrase (FRIENDLY_HELLO2); + + Friendly ((RESPONSE_REF)0); + } + else + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SHOFIXTI_VISITS); + if (GET_GAME_STATE (SHOFIXTI_KIA)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_KATANA_1); + break; + case 1: + NPCPhrase (HOSTILE_KATANA_2); + break; + case 2: + NPCPhrase (HOSTILE_KATANA_3); + break; + case 3: + NPCPhrase (HOSTILE_KATANA_4); + --NumVisits; + break; + } + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_TANAKA_1); + break; + case 1: + NPCPhrase (HOSTILE_TANAKA_2); + break; + case 2: + NPCPhrase (HOSTILE_TANAKA_3); + break; + case 3: + NPCPhrase (HOSTILE_TANAKA_4); + break; + case 4: + NPCPhrase (HOSTILE_TANAKA_5); + break; + case 5: + NPCPhrase (HOSTILE_TANAKA_6); + break; + case 6: + NPCPhrase (HOSTILE_TANAKA_7); + break; + case 7: + NPCPhrase (HOSTILE_TANAKA_8); + --NumVisits; + break; + } + } + SET_GAME_STATE (SHOFIXTI_VISITS, NumVisits); + + Hostile ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_shofixti (void) +{ + return(0); +} + +LOCDATAPTR +init_shofixti_comm (void) +{ + LOCDATAPTR retval; + + shofixti_desc.init_encounter_func = Intro; + shofixti_desc.uninit_encounter_func = uninit_shofixti; + + shofixti_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + shofixti_desc.AlienTextTemplate.baseline.y = 0; + shofixti_desc.AlienTextTemplate.align = ALIGN_CENTER; + shofixti_desc.AlienTextWidth = SIS_TEXT_WIDTH; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + + retval = &shofixti_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/shofixt/shofixt.res b/sc2/src/sc2code/comm/shofixt/shofixt.res new file mode 100644 index 000000000..4bb1f0d48 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/shofixt.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/shofixt + +PACKAGE SHOFIXTI_PACKAGE shofixt.con + GFXRES SHOFIXTI_PMAP_ANIM shofixt.ani + FONTRES SHOFIXTI_FONT shofixt.fon + MUSICRES SHOFIXTI_MUSIC shofixt.mod + STRTAB SHOFIXTI_CONVERSATION_PHRASES shofixt.txt + diff --git a/sc2/src/sc2code/comm/shofixt/strings.h b/sc2/src/sc2code/comm/shofixt/strings.h new file mode 100644 index 000000000..2fbf6a438 --- /dev/null +++ b/sc2/src/sc2code/comm/shofixt/strings.h @@ -0,0 +1,124 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + name_1, + name_2, + name_3, + name_40, + name_41, + tanaka, + katana, + HOSTILE_KATANA_1, + HOSTILE_KATANA_2, + HOSTILE_KATANA_3, + HOSTILE_KATANA_4, + HOSTILE_TANAKA_1, + HOSTILE_TANAKA_2, + HOSTILE_TANAKA_3, + HOSTILE_TANAKA_4, + HOSTILE_TANAKA_5, + HOSTILE_TANAKA_6, + HOSTILE_TANAKA_7, + HOSTILE_TANAKA_8, + dont_attack, + TYPICAL_PLOY, + hey_stop, + ONLY_STOP, + look_you_are, + TOO_BAD, + dont_know, + NEVER, + look0, + look1, + FOR_YOU, + no_bloodshed, + YES_BLOODSHED, + dont_want_to_fight, + MUST_FIGHT_YOU_URQUAN_1, + MUST_FIGHT_YOU_URQUAN_2, + MUST_FIGHT_YOU_URQUAN_3, + MUST_FIGHT_YOU_URQUAN_4, + no_one_insults, + YOU_LIMP, + mighty_words, + HANG_YOUR, + donkey_breath, + DGRUNTI, + i_am_captain0, + i_am_captain1, + i_am_captain2, + i_am_captain3, + i_am_nice, + i_am_guy, + SO_SORRY, + MUST_UNDERSTAND, + NICE_BUT_WHAT_IS_DONKEY, + IS_DEFEAT_TRUE, + yes_and_no, + butt_blasted, + clobbered, + VERY_SAD_KILL_SELF, + important_duty, + WHAT_DUTY, + need_you_for_duty, + OK_WILL_BE_SENTRY, + dont_do_it, + YES_I_DO_IT, + go_ahead, + ON_SECOND_THOUGHT, + procreating_wildly, + replenishing_your_species, + hope_you_have, + SOUNDS_GREAT_BUT_HOW, + females, + nubiles, + rat_babes, + LEAPING_HAPPINESS, + bye0, + bye1, + GOODBYE0, + GOODBYE1, + why_here0, + why_here1, + I_GUARD, + where_world, + BLEW_IT_UP, + how_survive, + NOT_HERE, + what_happened, + MET_VUX, + glory_device, + SWITCH_BROKE, + bye, + GOODBYE, + FRIENDLY_HELLO0, + FRIENDLY_HELLO1, + FRIENDLY_HELLO2, + report0, + report1, + NOTHING_NEW0, + NOTHING_NEW1, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/slyhome/ifontres.h b/sc2/src/sc2code/comm/slyhome/ifontres.h new file mode 100644 index 000000000..bc7938024 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/ifontres.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/slyhome/igfxres.h b/sc2/src/sc2code/comm/slyhome/igfxres.h new file mode 100644 index 000000000..519690b41 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/igfxres.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/slyhome/imusicre.h b/sc2/src/sc2code/comm/slyhome/imusicre.h new file mode 100644 index 000000000..60cd7834b --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/imusicre.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/slyhome/istrtab.h b/sc2/src/sc2code/comm/slyhome/istrtab.h new file mode 100644 index 000000000..e6b44008e --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/istrtab.h @@ -0,0 +1,4 @@ +#define SLYLANDRO_CONVERSATION_PHRASES 0x00200004L +#define SLYLANDRO_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/slyhome/resinst.h b/sc2/src/sc2code/comm/slyhome/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/slyhome/respkg.h b/sc2/src/sc2code/comm/slyhome/respkg.h new file mode 100644 index 000000000..e103d5190 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/respkg.h @@ -0,0 +1,5 @@ +enum +{ + SLYLANDRO_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/slyhome/restypes.h b/sc2/src/sc2code/comm/slyhome/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/slyhome/slyhome.c b/sc2/src/sc2code/comm/slyhome/slyhome.c new file mode 100644 index 000000000..4197ac6a6 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/slyhome.c @@ -0,0 +1,884 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/slyhome/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/slyhome/strings.h" + +static LOCDATA slylandro_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SLYLANDRO_PMAP_ANIM, /* AlienFrame */ + (FONT)SLYLANDRO_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ + (COLORMAP)SLYLANDRO_COLOR_MAP, /* AlienColorMap */ + SLYLANDRO_MUSIC, /* AlienSong */ + SLYLANDRO_CONVERSATION_PHRASES, /* PlayerPhrases */ + 13, /* NumAnimations */ + { + { + 0, /* StartIndex */ + 5, /* NumFrames */ + RANDOM_ANIM | COLORXFORM_ANIM, /* AnimFlags */ + 15, 75, /* FrameRate */ + 15, 75, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 6, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 11, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 16, /* StartIndex */ + 6, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + 8, 0, /* RestartRate */ + }, + { + 30, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 8) | (1 << 9), /* BlockMask */ + }, + { + 39, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 43, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), /* BlockMask */ + }, + { + 48, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), /* BlockMask */ + }, + { + 54, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12), /* BlockMask */ + }, + { + 60, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12), /* BlockMask */ + }, + { + 67, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 10) | (1 << 11), /* BlockMask */ + }, + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + switch (GET_GAME_STATE (SLYLANDRO_HOME_VISITS)) + { + case 1: + NPCPhrase (GOODBYE_1); + break; + default: + NPCPhrase (GOODBYE_2); + break; + } +} + +static void HomeWorld (RESPONSE_REF R); + +static void +HumanInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + + if (PLAYER_SAID (R, happy_to_tell_more)) + { + NPCPhrase (TELL_MORE); + + SET_GAME_STATE (SLYLANDRO_STACK4, 1); + } + else if (PLAYER_SAID (R, would_you_like_to_know_more)) + { + NPCPhrase (YES_TELL_MORE); + } + else if (PLAYER_SAID (R, we_come_from_earth)) + { + NPCPhrase (OK_EARTH); + + SET_GAME_STATE (SLYLANDRO_KNOW_EARTH, 1); + } + else if (PLAYER_SAID (R, we_explore)) + { + NPCPhrase (OK_EXPLORE); + + SET_GAME_STATE (SLYLANDRO_KNOW_EXPLORE, 1); + } + else if (PLAYER_SAID (R, we_fight_urquan)) + { + NPCPhrase (URQUAN_NICE_GUYS); + + SET_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 1); + } + else if (PLAYER_SAID (R, not_same_urquan)) + { + NPCPhrase (PERSONALITY_CHANGE); + + SET_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 2); + } + else if (PLAYER_SAID (R, we_gather)) + { + NPCPhrase (MAYBE_INTERESTED); + + SET_GAME_STATE (SLYLANDRO_KNOW_GATHER, 1); + } + + InfoLeft = FALSE; + if (GET_GAME_STATE (SLYLANDRO_KNOW_URQUAN) == 1) + { + InfoLeft = TRUE; + Response (not_same_urquan, HumanInfo); + } + if (!GET_GAME_STATE (SLYLANDRO_KNOW_EARTH)) + { + InfoLeft = TRUE; + Response (we_come_from_earth, HumanInfo); + } + if (!GET_GAME_STATE (SLYLANDRO_KNOW_EXPLORE)) + { + InfoLeft = TRUE; + Response (we_explore, HumanInfo); + } + if (!GET_GAME_STATE (SLYLANDRO_KNOW_URQUAN)) + { + InfoLeft = TRUE; + Response (we_fight_urquan, HumanInfo); + } + if (!GET_GAME_STATE (SLYLANDRO_KNOW_GATHER)) + { + InfoLeft = TRUE; + Response (we_gather, HumanInfo); + } + + Response (enough_about_me, HomeWorld); + if (!InfoLeft) + { + SET_GAME_STATE (SLYLANDRO_STACK4, 2); + } +} + +static void +SlylandroInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + + if (PLAYER_SAID (R, like_more_about_you)) + { + NPCPhrase (SURE_KNOW_WHAT); + } + else if (PLAYER_SAID (R, what_about_home)) + { + NPCPhrase (ABOUT_HOME); + + DISABLE_PHRASE (what_about_home); + } + else if (PLAYER_SAID (R, what_about_culture)) + { + NPCPhrase (ABOUT_CULTURE); + + DISABLE_PHRASE (what_about_culture); + } + else if (PLAYER_SAID (R, what_about_history)) + { + NPCPhrase (ABOUT_HISTORY); + + DISABLE_PHRASE (what_about_history); + } + else if (PLAYER_SAID (R, what_about_biology)) + { + NPCPhrase (ABOUT_BIOLOGY); + + DISABLE_PHRASE (what_about_biology); + } + + InfoLeft = FALSE; + if (PHRASE_ENABLED (what_about_home)) + { + InfoLeft = TRUE; + Response (what_about_home, SlylandroInfo); + } + if (PHRASE_ENABLED (what_about_culture)) + { + InfoLeft = TRUE; + Response (what_about_culture, SlylandroInfo); + } + if (PHRASE_ENABLED (what_about_history)) + { + InfoLeft = TRUE; + Response (what_about_history, SlylandroInfo); + } + if (PHRASE_ENABLED (what_about_biology)) + { + InfoLeft = TRUE; + Response (what_about_biology, SlylandroInfo); + } + + Response (enough_info, HomeWorld); + if (!InfoLeft) + { + DISABLE_PHRASE (like_more_about_you); + } +} + +static void +FixBug (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, think_about_rep_priorities)) + NPCPhrase (UH_OH); + else if (PLAYER_SAID (R, hunt_them_down)) + { + NPCPhrase (GROW_TOO_FAST); + + DISABLE_PHRASE (hunt_them_down); + } + else if (PLAYER_SAID (R, sue_melnorme)) + { + NPCPhrase (SIGNED_WAIVER); + + DISABLE_PHRASE (sue_melnorme); + } + else if (PLAYER_SAID (R, recall_signal)) + { + NPCPhrase (NOT_THIS_MODEL); + + DISABLE_PHRASE (recall_signal); + } + + if (PHRASE_ENABLED (hunt_them_down)) + Response (hunt_them_down, FixBug); + if (PHRASE_ENABLED (sue_melnorme)) + Response (sue_melnorme, FixBug); + if (PHRASE_ENABLED (recall_signal)) + Response (recall_signal, FixBug); + Response (mega_self_destruct, HomeWorld); +} + +static void +ProbeBug (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, probe_has_bug)) + NPCPhrase (NO_IT_DOESNT); + else if (PLAYER_SAID (R, tell_me_about_rep_2)) + { + NPCPhrase (REP_NO_PROBLEM); + + DISABLE_PHRASE (tell_me_about_rep_2); + } + else if (PLAYER_SAID (R, what_about_rep_priorities)) + { + NPCPhrase (MAXIMUM_SO_WHAT); + + DISABLE_PHRASE (what_about_rep_priorities); + } + else if (PLAYER_SAID (R, tell_me_about_attack)) + { + NPCPhrase (ATTACK_NO_PROBLEM); + + DISABLE_PHRASE (tell_me_about_attack); + } + + if (PHRASE_ENABLED (tell_me_about_rep_2)) + Response (tell_me_about_rep_2, ProbeBug); + else if (PHRASE_ENABLED (what_about_rep_priorities)) + Response (what_about_rep_priorities, ProbeBug); + else + { + Response (think_about_rep_priorities, FixBug); + } + if (PHRASE_ENABLED (tell_me_about_attack)) + Response (tell_me_about_attack, ProbeBug); +} + +static void ProbeInfo (RESPONSE_REF R); + +static void +ProbeFunction (RESPONSE_REF R) +{ + BYTE LastStack; + RESPONSE_REF pStr[2]; + + LastStack = 0; + pStr[0] = pStr[1] = 0; + if (PLAYER_SAID (R, talk_more_probe_attack)) + { + NPCPhrase (NO_PROBLEM_BUT_SURE); + } + else if (PLAYER_SAID (R, tell_me_about_basics)) + { + NPCPhrase (BASIC_COMMANDS); + + SET_GAME_STATE (PLAYER_KNOWS_PROGRAM, 1); + DISABLE_PHRASE (tell_basics_again); + } + else if (PLAYER_SAID (R, tell_basics_again)) + { + NPCPhrase (OK_BASICS_AGAIN); + + DISABLE_PHRASE (tell_basics_again); + } + else if (PLAYER_SAID (R, what_effect)) + { + NPCPhrase (AFFECTS_BEHAVIOR); + + SET_GAME_STATE (PLAYER_KNOWS_EFFECTS, 1); + DISABLE_PHRASE (what_effect); + } + else if (PLAYER_SAID (R, tell_me_about_rep_1)) + { + NPCPhrase (ABOUT_REP); + + LastStack = 2; + SET_GAME_STATE (SLYLANDRO_STACK8, 3); + } + else if (PLAYER_SAID (R, what_set_priority)) + { + NPCPhrase (MAXIMUM); + + SET_GAME_STATE (PLAYER_KNOWS_PRIORITY, 1); + DISABLE_PHRASE (what_set_priority); + } + else if (PLAYER_SAID (R, how_does_probe_defend)) + { + NPCPhrase (ONLY_SELF_DEFENSE); + + LastStack = 1; + SET_GAME_STATE (SLYLANDRO_STACK9, 1); + } + else if (PLAYER_SAID (R, combat_behavior)) + { + NPCPhrase (MISSILE_BATTERIES); + + LastStack = 1; + SET_GAME_STATE (SLYLANDRO_STACK9, 2); + } + else if (PLAYER_SAID (R, what_missile_batteries)) + { + NPCPhrase (LIGHTNING_ONLY_FOR_HARVESTING); + + SET_GAME_STATE (SLYLANDRO_STACK9, 3); + } + + switch (GET_GAME_STATE (SLYLANDRO_STACK9)) + { + case 0: + pStr[0] = how_does_probe_defend; + break; + case 1: + pStr[0] = combat_behavior; + break; + case 2: + pStr[0] = what_missile_batteries; + break; + } + switch (GET_GAME_STATE (SLYLANDRO_STACK8)) + { + case 2: + pStr[1] = tell_me_about_rep_1; + break; + case 3: + if (PHRASE_ENABLED (what_set_priority)) + pStr[1] = what_set_priority; + break; + } + + if (LastStack && pStr[LastStack - 1]) + Response (pStr[LastStack - 1], ProbeFunction); + if (!GET_GAME_STATE (PLAYER_KNOWS_PROGRAM)) + Response (tell_me_about_basics, ProbeFunction); + else + { + if (GET_GAME_STATE (PLAYER_KNOWS_PRIORITY)) + { + if (GET_GAME_STATE (PLAYER_KNOWS_EFFECTS)) + { + Response (probe_has_bug, ProbeBug); + } + if (PHRASE_ENABLED (what_effect)) + Response (what_effect, ProbeFunction); + } + if (PHRASE_ENABLED (tell_basics_again)) + Response (tell_basics_again, ProbeFunction); + } + if (LastStack == 0) + { + do + { + if (pStr[LastStack]) + Response (pStr[LastStack], ProbeFunction); + } while (++LastStack < 2); + } + else + { + LastStack = (LastStack - 1) ^ 1; + if (pStr[LastStack]) + Response (pStr[LastStack], ProbeFunction); + } + + Response (enough_problem, ProbeInfo); +} + +static void +ProbeInfo (RESPONSE_REF R) +{ + BYTE i, LastStack, InfoLeft; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, what_are_probes)) + { + NPCPhrase (PROBES_ARE); + + SET_GAME_STATE (SLYLANDRO_STACK5, 1); + } + else if (PLAYER_SAID (R, know_more_probe)) + NPCPhrase (OK_WHAT_MORE_PROBE); + else if (PLAYER_SAID (R, why_probe_always_attack)) + { + NPCPhrase (ONLY_DEFEND); + + SET_GAME_STATE (SLYLANDRO_STACK6, 1); + } + else if (PLAYER_SAID (R, talk_more_probe_attack)) + { + ProbeFunction (R); + goto ExitProbeInfo; + } + else if (PLAYER_SAID (R, where_probes_from)) + { + NPCPhrase (PROBES_FROM_MELNORME); + + LastStack = 1; + SET_GAME_STATE (SLYLANDRO_STACK7, 1); + } + else if (PLAYER_SAID (R, why_sell)) + { + NPCPhrase (SELL_FOR_INFO); + + LastStack = 1; + SET_GAME_STATE (SLYLANDRO_STACK7, 2); + } + else if (PLAYER_SAID (R, how_long_ago)) + { + NPCPhrase (FIFTY_THOUSAND_ROTATIONS); + + SET_GAME_STATE (SLYLANDRO_STACK7, 3); + } + else if (PLAYER_SAID (R, whats_probes_mission)) + { + NPCPhrase (SEEK_OUT_NEW_LIFE); + + LastStack = 2; + SET_GAME_STATE (SLYLANDRO_STACK8, 1); + } + else if (PLAYER_SAID (R, if_only_one)) + { + NPCPhrase (THEY_REPLICATE); + + SET_GAME_STATE (SLYLANDRO_STACK8, 2); + } + else if (PLAYER_SAID (R, enough_problem)) + NPCPhrase (OK_ENOUGH_PROBLEM); + + if (!GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN) + && GET_GAME_STATE (PROBE_EXHIBITED_BUG)) + { + switch (GET_GAME_STATE (SLYLANDRO_STACK6)) + { + case 0: + pStr[0] = why_probe_always_attack; + break; + case 1: + pStr[0] = talk_more_probe_attack; + break; + } + } + switch (GET_GAME_STATE (SLYLANDRO_STACK7)) + { + case 0: + pStr[1] = where_probes_from; + break; + case 1: + pStr[1] = why_sell; + break; + case 2: + pStr[1] = how_long_ago; + break; + } + switch (GET_GAME_STATE (SLYLANDRO_STACK8)) + { + case 0: + pStr[2] = whats_probes_mission; + break; + case 1: + pStr[2] = if_only_one; + break; + } + + InfoLeft = FALSE; + if (pStr[LastStack]) + { + InfoLeft = TRUE; + Response (pStr[LastStack], ProbeInfo); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + InfoLeft = TRUE; + Response (pStr[i], ProbeInfo); + } + } + + Response (enough_probe, HomeWorld); + if (!InfoLeft) + { + DISABLE_PHRASE (know_more_probe); + } +ExitProbeInfo: + ; +} + +static void +HomeWorld (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, we_are_us0)) + { + NPCPhrase (TERRIBLY_EXCITING); + + SET_GAME_STATE (SLYLANDRO_STACK1, 1); + DISABLE_PHRASE (we_are_us0); + } + else if (PLAYER_SAID (R, what_other_visitors)) + { + NPCPhrase (VISITORS); + + SET_GAME_STATE (PLAYER_KNOWS_PROBE, 1); + SET_GAME_STATE (SLYLANDRO_STACK1, 2); + } + else if (PLAYER_SAID (R, any_other_visitors)) + { + NPCPhrase (LONG_AGO); + + SET_GAME_STATE (SLYLANDRO_STACK1, 3); + } + else if (PLAYER_SAID (R, what_about_sentient_milieu)) + { + NPCPhrase (MET_TAALO_THEY_ARE_FROM); + + SET_GAME_STATE (SLYLANDRO_STACK1, 4); + } + else if (PLAYER_SAID (R, who_else)) + { + NPCPhrase (PRECURSORS); + + SET_GAME_STATE (SLYLANDRO_STACK1, 5); + } + else if (PLAYER_SAID (R, precursors_yow)) + { + NPCPhrase (ABOUT_PRECURSORS); + + SET_GAME_STATE (SLYLANDRO_STACK1, 6); + } + else if (PLAYER_SAID (R, must_know_more)) + { + NPCPhrase (ALL_WE_KNOW); + + SET_GAME_STATE (SLYLANDRO_STACK1, 7); + } + else if (PLAYER_SAID (R, who_are_you)) + { + NPCPhrase (WE_ARE_SLY); + + LastStack = 1; + SET_GAME_STATE (SLYLANDRO_STACK2, 1); + } + else if (PLAYER_SAID (R, where_are_you)) + { + NPCPhrase (DOWN_HERE); + + LastStack = 2; + SET_GAME_STATE (SLYLANDRO_STACK3, 1); + } + else if (PLAYER_SAID (R, thats_impossible_1)) + { + NPCPhrase (NO_ITS_NOT_1); + + LastStack = 2; + SET_GAME_STATE (SLYLANDRO_STACK3, 2); + } + else if (PLAYER_SAID (R, thats_impossible_2)) + { + NPCPhrase (NO_ITS_NOT_2); + + LastStack = 2; + SET_GAME_STATE (SLYLANDRO_STACK3, 3); + } + else if (PLAYER_SAID (R, like_more_about_you)) + { + SlylandroInfo (R); + goto ExitHomeWorld; + } + else if (PLAYER_SAID (R, enough_about_me)) + NPCPhrase (OK_ENOUGH_YOU); + else if (PLAYER_SAID (R, enough_info)) + NPCPhrase (OK_ENOUGH_INFO); + else if (PLAYER_SAID (R, enough_probe)) + NPCPhrase (OK_ENOUGH_PROBE); + else if (PLAYER_SAID (R, mega_self_destruct)) + { + NPCPhrase (WHY_YES_THERE_IS); + + SET_GAME_STATE (SLYLANDRO_KNOW_BROKEN, 1); + SET_GAME_STATE (DESTRUCT_CODE_ON_SHIP, 1); + i = GET_GAME_STATE (SLYLANDRO_MULTIPLIER) + 1; + SET_GAME_STATE (SLYLANDRO_MULTIPLIER, i); + AddEvent (RELATIVE_EVENT, 0, 0, 0, SLYLANDRO_RAMP_DOWN); + } + + switch (GET_GAME_STATE (SLYLANDRO_STACK1)) + { + case 0: + construct_response (shared_phrase_buf, + we_are_us0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_us1, + GLOBAL_SIS (ShipName), + we_are_us2, + 0); + pStr[0] = we_are_us0; + break; + case 1: + pStr[0] = what_other_visitors; + break; + case 2: + pStr[0] = any_other_visitors; + break; + case 3: + pStr[0] = what_about_sentient_milieu; + break; + case 4: + pStr[0] = who_else; + break; + case 5: + pStr[0] = precursors_yow; + break; + case 6: + pStr[0] = must_know_more; + break; + } + switch (GET_GAME_STATE (SLYLANDRO_STACK2)) + { + case 0: + pStr[1] = who_are_you; + break; + case 1: + if (PHRASE_ENABLED (like_more_about_you)) + pStr[1] = like_more_about_you; + break; + } + switch (GET_GAME_STATE (SLYLANDRO_STACK3)) + { + case 0: + pStr[2] = where_are_you; + break; + case 1: + pStr[2] = thats_impossible_1; + break; + case 2: + pStr[2] = thats_impossible_2; + break; + } + + if (pStr[LastStack]) + { + if (pStr[LastStack] != we_are_us0) + Response (pStr[LastStack], HomeWorld); + else + DoResponsePhrase (pStr[LastStack], HomeWorld, shared_phrase_buf); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != we_are_us0) + Response (pStr[i], HomeWorld); + else + DoResponsePhrase (pStr[i], HomeWorld, shared_phrase_buf); + } + } + if (GET_GAME_STATE (SLYLANDRO_STACK1)) + { + switch (GET_GAME_STATE (SLYLANDRO_STACK4)) + { + case 0: + Response (happy_to_tell_more, HumanInfo); + break; + case 1: + Response (would_you_like_to_know_more, HumanInfo); + break; + } + } + if (GET_GAME_STATE (PLAYER_KNOWS_PROBE) + && !GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN)) + { + switch (GET_GAME_STATE (SLYLANDRO_STACK5)) + { + case 0: + Response (what_are_probes, ProbeInfo); + break; + case 1: + if (PHRASE_ENABLED (know_more_probe)) + Response (know_more_probe, ProbeInfo); + break; + } + } + Response (bye, ExitConversation); +ExitHomeWorld: + ; +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN) + && (NumVisits = GET_GAME_STATE (RECALL_VISITS)) == 0) + { + NPCPhrase (RECALL_PROGRAM_1); + ++NumVisits; + SET_GAME_STATE (RECALL_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (SLYLANDRO_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_1); + break; + case 1: + NPCPhrase (HELLO_2); + break; + case 2: + NPCPhrase (HELLO_3); + break; + case 3: + NPCPhrase (HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_HOME_VISITS, NumVisits); + } + + HomeWorld ((RESPONSE_REF)0); +} + +static COUNT +uninit_slylandro (void) +{ + return (0); +} + +LOCDATAPTR +init_slylandro_comm (void) +{ + LOCDATAPTR retval; + + slylandro_desc.init_encounter_func = Intro; + slylandro_desc.uninit_encounter_func = uninit_slylandro; + + slylandro_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + slylandro_desc.AlienTextTemplate.baseline.y = 0; + slylandro_desc.AlienTextTemplate.align = ALIGN_CENTER; + slylandro_desc.AlienTextWidth = SIS_TEXT_WIDTH; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &slylandro_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/slyhome/slyhome.res b/sc2/src/sc2code/comm/slyhome/slyhome.res new file mode 100644 index 000000000..dc73c0080 --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/slyhome.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/slyhome + +PACKAGE SLYLANDRO_PACKAGE slyhome.con + GFXRES SLYLANDRO_PMAP_ANIM slyhome.ani + FONTRES SLYLANDRO_FONT slyhome.fon + MUSICRES SLYLANDRO_MUSIC slyhome.mod + STRTAB SLYLANDRO_CONVERSATION_PHRASES slyhome.txt + STRTAB SLYLANDRO_COLOR_MAP slyhome.ct diff --git a/sc2/src/sc2code/comm/slyhome/strings.h b/sc2/src/sc2code/comm/slyhome/strings.h new file mode 100644 index 000000000..c453ba31d --- /dev/null +++ b/sc2/src/sc2code/comm/slyhome/strings.h @@ -0,0 +1,143 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HELLO_1, + HELLO_2, + HELLO_3, + HELLO_4, + RECALL_PROGRAM_1, + we_are_us0, + we_are_us1, + we_are_us2, + TERRIBLY_EXCITING, + happy_to_tell_more, + TELL_MORE, + would_you_like_to_know_more, + YES_TELL_MORE, + we_come_from_earth, + OK_EARTH, + we_explore, + OK_EXPLORE, + we_fight_urquan, + URQUAN_NICE_GUYS, + not_same_urquan, + PERSONALITY_CHANGE, + we_gather, + MAYBE_INTERESTED, + enough_about_me, + OK_ENOUGH_YOU, + what_other_visitors, + VISITORS, + any_other_visitors, + LONG_AGO, + what_about_sentient_milieu, + MET_TAALO_THEY_ARE_FROM, + who_else, + PRECURSORS, + precursors_yow, + ABOUT_PRECURSORS, + must_know_more, + ALL_WE_KNOW, + who_are_you, + WE_ARE_SLY, + like_more_about_you, + SURE_KNOW_WHAT, + what_about_home, + ABOUT_HOME, + what_about_culture, + ABOUT_CULTURE, + what_about_history, + ABOUT_HISTORY, + what_about_biology, + ABOUT_BIOLOGY, + enough_info, + OK_ENOUGH_INFO, + where_are_you, + DOWN_HERE, + thats_impossible_1, + NO_ITS_NOT_1, + thats_impossible_2, + NO_ITS_NOT_2, + bye, + GOODBYE_1, + GOODBYE_2, + what_are_probes, + PROBES_ARE, + know_more_probe, + OK_WHAT_MORE_PROBE, + where_probes_from, + PROBES_FROM_MELNORME, + why_sell, + SELL_FOR_INFO, + how_long_ago, + FIFTY_THOUSAND_ROTATIONS, + whats_probes_mission, + SEEK_OUT_NEW_LIFE, + if_only_one, + THEY_REPLICATE, + enough_probe, + OK_ENOUGH_PROBE, + why_probe_always_attack, + ONLY_DEFEND, + talk_more_probe_attack, + NO_PROBLEM_BUT_SURE, + tell_me_about_basics, + BASIC_COMMANDS, + tell_basics_again, + OK_BASICS_AGAIN, + what_effect, + AFFECTS_BEHAVIOR, + how_does_probe_defend, + ONLY_SELF_DEFENSE, + combat_behavior, + MISSILE_BATTERIES, + what_missile_batteries, + LIGHTNING_ONLY_FOR_HARVESTING, + tell_me_about_rep_1, + ABOUT_REP, + what_set_priority, + MAXIMUM, + enough_problem, + OK_ENOUGH_PROBLEM, + probe_has_bug, + NO_IT_DOESNT, + tell_me_about_attack, + ATTACK_NO_PROBLEM, + tell_me_about_rep_2, + REP_NO_PROBLEM, + what_about_rep_priorities, + MAXIMUM_SO_WHAT, + think_about_rep_priorities, + UH_OH, + hunt_them_down, + GROW_TOO_FAST, + sue_melnorme, + SIGNED_WAIVER, + recall_signal, + NOT_THIS_MODEL, + mega_self_destruct, + WHY_YES_THERE_IS, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/slyland/ifontres.h b/sc2/src/sc2code/comm/slyland/ifontres.h new file mode 100644 index 000000000..ec3590ee4 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/ifontres.h @@ -0,0 +1,3 @@ +#define SLYLAND_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/slyland/igfxres.h b/sc2/src/sc2code/comm/slyland/igfxres.h new file mode 100644 index 000000000..0b9187fd9 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/igfxres.h @@ -0,0 +1,3 @@ +#define SLYLAND_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/slyland/imusicre.h b/sc2/src/sc2code/comm/slyland/imusicre.h new file mode 100644 index 000000000..c58bc7dc7 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/imusicre.h @@ -0,0 +1,3 @@ +#define SLYLAND_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/slyland/istrtab.h b/sc2/src/sc2code/comm/slyland/istrtab.h new file mode 100644 index 000000000..3c6c3d12e --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/istrtab.h @@ -0,0 +1,3 @@ +#define SLYLAND_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/slyland/resinst.h b/sc2/src/sc2code/comm/slyland/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/slyland/respkg.h b/sc2/src/sc2code/comm/slyland/respkg.h new file mode 100644 index 000000000..fc3e6b101 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/respkg.h @@ -0,0 +1,5 @@ +enum +{ + SLYLAND_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/slyland/restypes.h b/sc2/src/sc2code/comm/slyland/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/slyland/slyland.c b/sc2/src/sc2code/comm/slyland/slyland.c new file mode 100644 index 000000000..e11c124b4 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/slyland.c @@ -0,0 +1,384 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/slyland/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/slyland/strings.h" + +static LOCDATA slylandro_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SLYLAND_PMAP_ANIM, /* AlienFrame */ + (FONT)SLYLAND_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + SLYLAND_MUSIC, /* AlienSong */ + SLYLAND_CONVERSATION_PHRASES, /* PlayerPhrases */ + 6, /* NumAnimations */ + { + { + 1, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 3) /* BlockMask */ + }, + { + 10, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 4) /* BlockMask */ + }, + { + 18, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 5) /* BlockMask */ + }, + { + 26, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 0) /* BlockMask */ + }, + { + 34, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 1) /* BlockMask */ + }, + { + 42, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 3, /* RestartRate */ + (1 << 2) /* BlockMask */ + }, + }, +}; + +static RESPONSE_REF threat = 0, + something_wrong = 0, + we_are_us = 0, + why_attack = 0, + bye = 0; + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + if (R == 0) + { + if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) + Response (destruct_code, CombatIsInevitable); + switch (GET_GAME_STATE (SLYLANDRO_PROBE_THREAT)) + { + case 0: + threat = threat_1; + break; + case 1: + threat = threat_2; + break; + case 2: + threat = threat_3; + break; + default: + threat = threat_4; + break; + } + Response (threat, CombatIsInevitable); + switch (GET_GAME_STATE (SLYLANDRO_PROBE_WRONG)) + { + case 0: + something_wrong = something_wrong_1; + break; + case 1: + something_wrong = something_wrong_2; + break; + case 2: + something_wrong = something_wrong_3; + break; + default: + something_wrong = something_wrong_4; + break; + } + Response (something_wrong, CombatIsInevitable); + switch (GET_GAME_STATE (SLYLANDRO_PROBE_ID)) + { + case 0: + we_are_us = we_are_us_1; + break; + case 1: + we_are_us = we_are_us_2; + break; + case 2: + we_are_us = we_are_us_3; + break; + default: + we_are_us = we_are_us_4; + break; + } + Response (we_are_us, CombatIsInevitable); + switch (GET_GAME_STATE (SLYLANDRO_PROBE_INFO)) + { + case 0: + why_attack = why_attack_1; + break; + case 1: + why_attack = why_attack_2; + break; + case 2: + why_attack = why_attack_3; + break; + default: + why_attack = why_attack_4; + break; + } + Response (why_attack, CombatIsInevitable); + switch (GET_GAME_STATE (SLYLANDRO_PROBE_EXIT)) + { + case 0: + bye = bye_1; + break; + case 1: + bye = bye_2; + break; + case 2: + bye = bye_3; + break; + default: + bye = bye_4; + break; + } + Response (bye, CombatIsInevitable); + } + else if (PLAYER_SAID (R, destruct_code)) + { + COUNT race_bounty[] = + { + RACE_SHIP_COST + }; + + NPCPhrase (DESTRUCT_SEQUENCE); + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 0, race_bounty[SLYLANDRO_SHIP] >> 3); + ClearSemaphore (&GraphicsSem); + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + BYTE NumVisits; + + if (PLAYER_SAID (R, threat)) + { + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_THREAT); + switch (NumVisits++) + { + case 0: + NPCPhrase (PROGRAMMED_TO_DEFEND_1); + break; + case 1: + NPCPhrase (PROGRAMMED_TO_DEFEND_2); + break; + case 2: + NPCPhrase (PROGRAMMED_TO_DEFEND_3); + break; + case 3: + NPCPhrase (PROGRAMMED_TO_DEFEND_4); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_PROBE_THREAT, NumVisits); + } + else if (PLAYER_SAID (R, something_wrong)) + { + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_WRONG); + switch (NumVisits++) + { + case 0: + NPCPhrase (NOMINAL_FUNCTION_1); + break; + case 1: + NPCPhrase (NOMINAL_FUNCTION_2); + break; + case 2: + NPCPhrase (NOMINAL_FUNCTION_3); + break; + case 3: + NPCPhrase (NOMINAL_FUNCTION_4); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_PROBE_WRONG, NumVisits); + } + else if (PLAYER_SAID (R, we_are_us)) + { + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_ID); + switch (NumVisits++) + { + case 0: + NPCPhrase (THIS_IS_PROBE_1); + break; + case 1: + NPCPhrase (THIS_IS_PROBE_2); + break; + case 2: + NPCPhrase (THIS_IS_PROBE_3); + break; + case 3: + { + NPCPhrase (THIS_IS_PROBE_40); + NPCPhrase (GLOBAL_PLAYER_LOCATION); + NPCPhrase (THIS_IS_PROBE_41); + + --NumVisits; + break; + } + } + SET_GAME_STATE (SLYLANDRO_PROBE_ID, NumVisits); + } + else if (PLAYER_SAID (R, why_attack)) + { + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (PEACEFUL_MISSION_1); + break; + case 1: + NPCPhrase (PEACEFUL_MISSION_2); + break; + case 2: + NPCPhrase (PEACEFUL_MISSION_3); + break; + case 3: + NPCPhrase (PEACEFUL_MISSION_4); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_PROBE_INFO, NumVisits); + } + else if (PLAYER_SAID (R, bye)) + { + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_EXIT); + switch (NumVisits++) + { + case 0: + NPCPhrase (GOODBYE_1); + break; + case 1: + NPCPhrase (GOODBYE_2); + break; + case 2: + NPCPhrase (GOODBYE_3); + break; + case 3: + NPCPhrase (GOODBYE_4); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_PROBE_EXIT, NumVisits); + } + + NPCPhrase (HOSTILE); + + SET_GAME_STATE (PROBE_EXHIBITED_BUG, 1); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } +} + +static void +Intro (void) +{ + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (WE_COME_IN_PEACE_1); + break; + case 1: + NPCPhrase (WE_COME_IN_PEACE_2); + break; + case 2: + NPCPhrase (WE_COME_IN_PEACE_3); + break; + case 3: + NPCPhrase (WE_COME_IN_PEACE_4); + break; + case 4: + NPCPhrase (WE_COME_IN_PEACE_5); + break; + case 5: + NPCPhrase (WE_COME_IN_PEACE_6); + break; + case 6: + NPCPhrase (WE_COME_IN_PEACE_7); + break; + case 7: + NPCPhrase (WE_COME_IN_PEACE_8); + --NumVisits; + break; + } + SET_GAME_STATE (SLYLANDRO_PROBE_VISITS, NumVisits); + + CombatIsInevitable ((RESPONSE_REF)0); +} + +static COUNT +uninit_slyland (void) +{ + return (0); +} + +LOCDATAPTR +init_slyland_comm (void) +{ + LOCDATAPTR retval; + + slylandro_desc.init_encounter_func = Intro; + slylandro_desc.uninit_encounter_func = uninit_slyland; + + slylandro_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + slylandro_desc.AlienTextTemplate.baseline.y = 0; + slylandro_desc.AlienTextTemplate.align = ALIGN_CENTER; + slylandro_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + SET_GAME_STATE (BATTLE_SEGUE, 1); + retval = &slylandro_desc; + + return (retval); +} + diff --git a/sc2/src/sc2code/comm/slyland/slyland.res b/sc2/src/sc2code/comm/slyland/slyland.res new file mode 100644 index 000000000..d689a2fd3 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/slyland.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/slyland + +PACKAGE SLYLAND_PACKAGE slyland.con + GFXRES SLYLAND_PMAP_ANIM slyland.ani + FONTRES SLYLAND_FONT slyland.fon + MUSICRES SLYLAND_MUSIC slyland.mod + STRTAB SLYLAND_CONVERSATION_PHRASES slyland.txt + diff --git a/sc2/src/sc2code/comm/slyland/strings.h b/sc2/src/sc2code/comm/slyland/strings.h new file mode 100644 index 000000000..468c5ca02 --- /dev/null +++ b/sc2/src/sc2code/comm/slyland/strings.h @@ -0,0 +1,79 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + WE_COME_IN_PEACE_1, + WE_COME_IN_PEACE_2, + WE_COME_IN_PEACE_3, + WE_COME_IN_PEACE_4, + WE_COME_IN_PEACE_5, + WE_COME_IN_PEACE_6, + WE_COME_IN_PEACE_7, + WE_COME_IN_PEACE_8, + threat_1, + threat_2, + threat_3, + threat_4, + PROGRAMMED_TO_DEFEND_1, + PROGRAMMED_TO_DEFEND_2, + PROGRAMMED_TO_DEFEND_3, + PROGRAMMED_TO_DEFEND_4, + something_wrong_1, + something_wrong_2, + something_wrong_3, + something_wrong_4, + NOMINAL_FUNCTION_1, + NOMINAL_FUNCTION_2, + NOMINAL_FUNCTION_3, + NOMINAL_FUNCTION_4, + we_are_us_1, + we_are_us_2, + we_are_us_3, + we_are_us_4, + THIS_IS_PROBE_1, + THIS_IS_PROBE_2, + THIS_IS_PROBE_3, + THIS_IS_PROBE_40, + THIS_IS_PROBE_41, + why_attack_1, + why_attack_2, + why_attack_3, + why_attack_4, + PEACEFUL_MISSION_1, + PEACEFUL_MISSION_2, + PEACEFUL_MISSION_3, + PEACEFUL_MISSION_4, + bye_1, + bye_2, + bye_3, + bye_4, + GOODBYE_1, + GOODBYE_2, + GOODBYE_3, + GOODBYE_4, + HOSTILE, + DESTRUCT_SEQUENCE, + destruct_code, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/spahome/spahome.c b/sc2/src/sc2code/comm/spahome/spahome.c new file mode 100644 index 000000000..68224febb --- /dev/null +++ b/sc2/src/sc2code/comm/spahome/spahome.c @@ -0,0 +1,983 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/spathi/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/spahome/strings.h" + +static LOCDATA spahome_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SPATHI_HOME_PMAP_ANIM, /* AlienFrame */ + (FONT)SPATHI_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + (COLORMAP)SPATHI_HOME_COLOR_MAP, /* AlienColorMap */ + SPATHI_MUSIC, /* AlienSong */ + SPATHI_HOME_CONVERSATION_PHRASES, /* PlayerPhrases */ + 14, /* NumAnimations */ + { + { + 1, /* StartIndex */ + 3, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 4, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 9, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 10) | (1 << 11), /* BlockMask */ + }, + { + 13, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 6, 0, /* RestartRate */ + (1 << 4) | (1 << 5) /* BlockMask */ + }, + { + 19, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 3) | (1 << 5), /* BlockMask */ + }, + { + 22, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + 12, 4, /* RestartRate */ + (1 << 3) | (1 << 4) + | (1 << 10), /* BlockMask */ + }, + { + 26, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + (1 << 10), /* BlockMask */ + }, + { + 29, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 32, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 6, 0, /* RestartRate */ + (1 << 9) | (1 << 10), /* BlockMask */ + }, + { + 39, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 8) | (1 << 10), /* BlockMask */ + }, + { + 42, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + 4, 0, /* RestartRate */ + (1 << 8) | (1 << 9) + | (1 << 6) | (1 << 2) + | (1 << 11) | (1 << 5), /* BlockMask */ + }, + { + 46, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + 12, 4, /* RestartRate */ + (1 << 2) | (1 << 10), /* BlockMask */ + }, + { + 50, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 6, 0, /* RestartRate */ + (1 << 13), /* BlockMask */ + }, + { + 56, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12), /* BlockMask */ + }, + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + if (PLAYER_SAID (R, we_attack_again)) + { + NPCPhrase (WE_FIGHT_AGAIN); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, surrender_or_die)) + { + NPCPhrase (DEFEND_OURSELVES); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (NO_PASSWORD); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, gort_merenga) + || PLAYER_SAID (R, guph_florp) + || PLAYER_SAID (R, wagngl_fthagn) + || PLAYER_SAID (R, pleeese)) + { + NPCPhrase (WRONG_PASSWORD); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, screw_password)) + { + NPCPhrase (NO_PASSWORD); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, bye_no_ally_offer)) + NPCPhrase (GOODBYE_NO_ALLY_OFFER); + else if (PLAYER_SAID (R, bye_angry_spathi)) + NPCPhrase (GOODBYE_ANGRY_SPATHI); + else if (PLAYER_SAID (R, bye_ally)) + NPCPhrase (GOODBYE_ALLY); + else if (PLAYER_SAID (R, already_got_them)) + { + NPCPhrase (EARLY_BIRD_CHECK); + + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + SET_GAME_STATE (SPATHI_VISITS, 0); + SET_GAME_STATE (SPATHI_PARTY, 1); + SET_GAME_STATE (SPATHI_MANNER, 3); + } + else if (PLAYER_SAID (R, too_dangerous)) + NPCPhrase (WE_AGREE); + else if (PLAYER_SAID (R, think_more)) + NPCPhrase (COWARD); + else if (PLAYER_SAID (R, i_accept)) + { + NPCPhrase (AWAIT_RETURN); + + SET_GAME_STATE (SPATHI_QUEST, 1); + SET_GAME_STATE (SPATHI_MANNER, 3); + SET_GAME_STATE (SPATHI_VISITS, 0); + } + else if (PLAYER_SAID (R, do_as_we_say)) + { + NPCPhrase (DEPART_FOR_EARTH); + + ActivateStarShip (SPATHI_SHIP, 0); + AddEvent (RELATIVE_EVENT, 6, 0, 0, SPATHI_SHIELD_EVENT); + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + SET_GAME_STATE (SPATHI_VISITS, 0); + } + else if (PLAYER_SAID (R, killed_them_all_1)) + { + NPCPhrase (WILL_CHECK_1); + + if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) + { + SET_GAME_STATE (LIED_ABOUT_CREATURES, 1); + } + else + { + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + SET_GAME_STATE (SPATHI_VISITS, 0); + SET_GAME_STATE (SPATHI_PARTY, 1); + SET_GAME_STATE (SPATHI_MANNER, 3); + } + } + else if (PLAYER_SAID (R, killed_them_all_2)) + { + NPCPhrase (WILL_CHECK_2); + + if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) + { + SET_GAME_STATE (LIED_ABOUT_CREATURES, 2); + } + else + { + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + SET_GAME_STATE (SPATHI_VISITS, 0); + SET_GAME_STATE (SPATHI_PARTY, 1); + SET_GAME_STATE (SPATHI_MANNER, 3); + } + } + else if (PLAYER_SAID (R, bye_before_party)) + { + NPCPhrase (GOODBYE_BEFORE_PARTY); + } + else if (PLAYER_SAID (R, bye_from_party_1) + || PLAYER_SAID (R, bye_from_party_2) + || PLAYER_SAID (R, bye_from_party_3)) + { + NPCPhrase (GOODBYE_FROM_PARTY); + } +} + +static void SpathiAllies (RESPONSE_REF R); + +static void +SpathiInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + + InfoLeft = FALSE; + if (PLAYER_SAID (R, like_some_info)) + NPCPhrase (WHAT_ABOUT); + else if (PLAYER_SAID (R, what_about_hierarchy)) + { + NPCPhrase (ABOUT_HIERARCHY); + + DISABLE_PHRASE (what_about_hierarchy); + } + else if (PLAYER_SAID (R, what_about_history)) + { + NPCPhrase (ABOUT_HISTORY); + + DISABLE_PHRASE (what_about_history); + } + else if (PLAYER_SAID (R, what_about_alliance)) + { + NPCPhrase (ABOUT_ALLIANCE); + + DISABLE_PHRASE (what_about_alliance); + } + else if (PLAYER_SAID (R, what_about_other)) + { + NPCPhrase (ABOUT_OTHER); + + DISABLE_PHRASE (what_about_other); + } + else if (PLAYER_SAID (R, what_about_precursors)) + { + NPCPhrase (ABOUT_PRECURSORS); + + DISABLE_PHRASE (what_about_precursors); + } + + if (PHRASE_ENABLED (what_about_hierarchy)) + { + InfoLeft = TRUE; + Response (what_about_hierarchy, SpathiInfo); + } + if (PHRASE_ENABLED (what_about_history)) + { + InfoLeft = TRUE; + Response (what_about_history, SpathiInfo); + } + if (PHRASE_ENABLED (what_about_alliance)) + { + InfoLeft = TRUE; + Response (what_about_alliance, SpathiInfo); + } + if (PHRASE_ENABLED (what_about_other)) + { + InfoLeft = TRUE; + Response (what_about_other, SpathiInfo); + } + if (PHRASE_ENABLED (what_about_precursors)) + { + InfoLeft = TRUE; + Response (what_about_precursors, SpathiInfo); + } + Response (enough_info, SpathiAllies); + + if (!InfoLeft) + { + DISABLE_PHRASE (like_some_info); + } +} + +static void +SpathiAllies (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (R == 0) + { + NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_ALLIES_1); + break; + case 1: + NPCPhrase (HELLO_ALLIES_2); + break; + case 2: + NPCPhrase (HELLO_ALLIES_3); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, whats_up)) + { + NumVisits = GET_GAME_STATE (SPATHI_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_3); + SET_GAME_STATE (KNOW_URQUAN_STORY, 1); + SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1) + break; + case 3: + NPCPhrase (GENERAL_INFO_4); + break; + case 4: + NPCPhrase (GENERAL_INFO_5); + --NumVisits; + break; + case 5: + NPCPhrase (GENERAL_INFO_5); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_INFO, NumVisits); + + DISABLE_PHRASE (whats_up); + } + else if (PLAYER_SAID (R, resources_please)) + { + NPCPhrase (SORRY_NO_RESOURCES); + + DISABLE_PHRASE (resources_please); + } + else if (PLAYER_SAID (R, something_fishy)) + { + NPCPhrase (NOTHING_FISHY); + + SET_GAME_STATE (SPATHI_INFO, 5); + } + else if (PLAYER_SAID (R, enough_info)) + NPCPhrase (OK_ENOUGH_INFO); + + if (GET_GAME_STATE (SPATHI_INFO) == 4) + Response (something_fishy, SpathiAllies); + if (PHRASE_ENABLED (whats_up)) + Response (whats_up, SpathiAllies); + if (PHRASE_ENABLED (resources_please)) + Response (resources_please, SpathiAllies); + if (PHRASE_ENABLED (like_some_info)) + Response (like_some_info, SpathiInfo); + Response (bye_ally, ExitConversation); +} + +static void +SpathiQuest (RESPONSE_REF R) +{ + if (R == 0) + { + if (!GET_GAME_STATE (LIED_ABOUT_CREATURES)) + NPCPhrase (HOW_GO_EFFORTS); + else + NPCPhrase (YOU_LIED_1); + } + else if (PLAYER_SAID (R, little_mistake)) + { + NPCPhrase (BIG_MISTAKE); + + DISABLE_PHRASE (little_mistake); + } + else if (PLAYER_SAID (R, talk_test)) + { + NPCPhrase (TEST_AGAIN); + + DISABLE_PHRASE (talk_test); + } + else if (PLAYER_SAID (R, zapped_a_few)) + { + NPCPhrase (YOU_FORTUNATE); + + DISABLE_PHRASE (zapped_a_few); + } + + if (!GET_GAME_STATE (LIED_ABOUT_CREATURES)) + Response (killed_them_all_1, ExitConversation); + else + { + if (PHRASE_ENABLED (little_mistake)) + { + Response (little_mistake, SpathiQuest); + } + Response (killed_them_all_2, ExitConversation); + } + if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) + { + if (PHRASE_ENABLED (talk_test)) + { + Response (talk_test, SpathiQuest); + } + if (PHRASE_ENABLED (zapped_a_few) + && GET_GAME_STATE (SPATHI_CREATURES_EXAMINED)) + { + Response (zapped_a_few, SpathiQuest); + } + Response (bye_before_party, ExitConversation); + } +} + +static void +LearnQuest (RESPONSE_REF R) +{ + if (R == 0) + { + NPCPhrase (QUEST_AGAIN); + + DISABLE_PHRASE (what_test); + if (GET_GAME_STATE (KNOW_SPATHI_EVIL)) + { + DISABLE_PHRASE (tell_evil); + } + } + else if (PLAYER_SAID (R, how_prove)) + NPCPhrase (BETTER_IDEA); + else if (PLAYER_SAID (R, what_test)) + { + NPCPhrase (WIPE_EVIL); + + SET_GAME_STATE (KNOW_SPATHI_QUEST, 1); + DISABLE_PHRASE (what_test); + } + else if (PLAYER_SAID (R, tell_evil)) + { + NPCPhrase (BEFORE_ACCEPT); + + SET_GAME_STATE (KNOW_SPATHI_EVIL, 1); + DISABLE_PHRASE (tell_evil); + DISABLE_PHRASE (prove_strength); + } + else if (PLAYER_SAID (R, prove_strength)) + { + NPCPhrase (YOUR_BEHAVIOR); + + DISABLE_PHRASE (prove_strength); + } + else if (PLAYER_SAID (R, why_dont_you_do_it)) + { + NPCPhrase (WE_WONT_BECAUSE); + + DISABLE_PHRASE (why_dont_you_do_it); + } + + if (PHRASE_ENABLED (what_test)) + Response (what_test, LearnQuest); + else if (GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) + { + Response (already_got_them, ExitConversation); + } + else if (PHRASE_ENABLED (tell_evil)) + { + Response (too_dangerous, ExitConversation); + Response (tell_evil, LearnQuest); + } + else + { + Response (too_dangerous, ExitConversation); + Response (think_more, ExitConversation); + Response (i_accept, ExitConversation); + } + if (PHRASE_ENABLED (prove_strength) && !GET_GAME_STATE (KNOW_SPATHI_QUEST)) + Response (prove_strength, LearnQuest); + if (PHRASE_ENABLED (why_dont_you_do_it)) + Response (why_dont_you_do_it, LearnQuest); +} + +static void +AllianceOffer (RESPONSE_REF R) +{ + //PTR_DESC PtrDesc; + + if (PLAYER_SAID (R, misunderstanding)) + { + NPCPhrase (JUST_MISUNDERSTANDING); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND / 4); + + SET_GAME_STATE (SPATHI_MANNER, 3); + SET_GAME_STATE (SPATHI_VISITS, 0); + } + else if (PLAYER_SAID (R, we_come_in_peace)) + NPCPhrase (OF_COURSE); + else if (PLAYER_SAID (R, hand_in_friendship)) + { + NPCPhrase (TOO_AFRAID); + + DISABLE_PHRASE (hand_in_friendship); + } + else if (PLAYER_SAID (R, stronger)) + { + NPCPhrase (YOURE_NOT); + + DISABLE_PHRASE (stronger); + } + else if (PLAYER_SAID (R, yes_we_are)) + { + NPCPhrase (NO_YOURE_NOT); + + DISABLE_PHRASE (yes_we_are); + } + else if (PLAYER_SAID (R, share_info)) + { + NPCPhrase (NO_INFO); + + DISABLE_PHRASE (share_info); + } + else if (PLAYER_SAID (R, give_us_resources)) + { + NPCPhrase (NO_RESOURCES); + + DISABLE_PHRASE (give_us_resources); + } + + if (PHRASE_ENABLED (hand_in_friendship)) + Response (hand_in_friendship, AllianceOffer); + else if (PHRASE_ENABLED (stronger)) + Response (stronger, AllianceOffer); + else if (PHRASE_ENABLED (yes_we_are)) + Response (yes_we_are, AllianceOffer); + else + { + Response (how_prove, LearnQuest); + } + if (PHRASE_ENABLED (share_info)) + Response (share_info, AllianceOffer); + if (PHRASE_ENABLED (give_us_resources)) + Response (give_us_resources, AllianceOffer); +} + +static void +SpathiAngry (RESPONSE_REF R) +{ + if (R == 0) + { + NPCPhrase (MEAN_GUYS_RETURN); + + Response (we_apologize, SpathiAngry); + } + else /* if (R == we_apologize) */ + { + NPCPhrase (DONT_BELIEVE); + + Response (misunderstanding, AllianceOffer); + } + + Response (we_attack_again, ExitConversation); + Response (bye_angry_spathi, ExitConversation); +} + +static void +SpathiParty (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (MUST_PARTY_1); + break; + case 1: + NPCPhrase (MUST_PARTY_2); + break; + case 2: + NPCPhrase (MUST_PARTY_3); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, deals_a_deal)) + { + NPCPhrase (WAIT_A_WHILE); + + DISABLE_PHRASE (deals_a_deal); + } + else if (PLAYER_SAID (R, how_long)) + { + NPCPhrase (TEN_YEARS); + + DISABLE_PHRASE (how_long); + } + else if (PLAYER_SAID (R, reneging)) + { + NPCPhrase (ADULT_VIEW); + + DISABLE_PHRASE (reneging); + } + else if (PLAYER_SAID (R, return_beasts)) + { + NPCPhrase (WHAT_RELATIONSHIP); + + DISABLE_PHRASE (return_beasts); + } + else if (PLAYER_SAID (R, minds_and_might)) + { + NPCPhrase (HUH); + + DISABLE_PHRASE (minds_and_might); + } + else if (PLAYER_SAID (R, fellowship)) + { + NPCPhrase (WHAT); + + DISABLE_PHRASE (fellowship); + } + + if (PHRASE_ENABLED (deals_a_deal)) + Response (deals_a_deal, SpathiParty); + else if (PHRASE_ENABLED (how_long)) + Response (how_long, SpathiParty); + else if (PHRASE_ENABLED (reneging)) + Response (reneging, SpathiParty); + else if (PHRASE_ENABLED (return_beasts)) + Response (return_beasts, SpathiParty); + else + { + if (PHRASE_ENABLED (minds_and_might)) + Response (minds_and_might, SpathiParty); + if (PHRASE_ENABLED (fellowship)) + Response (fellowship, SpathiParty); + Response (do_as_we_say, ExitConversation); + + goto ExitParty; + } + switch (GET_GAME_STATE (SPATHI_HOME_VISITS) - 1) + { + case 0: + Response (bye_from_party_1, ExitConversation); + break; + case 1: + Response (bye_from_party_2, ExitConversation); + break; + default: + Response (bye_from_party_3, ExitConversation); + break; + } +ExitParty: + ; +} + +static void +SpathiCouncil (RESPONSE_REF R) +{ + if (R == 0) + NPCPhrase (HELLO_AGAIN); + else if (PLAYER_SAID (R, good_password)) + { + NPCPhrase (YES_GOOD_PASSWORD); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND / 4); + + SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 1); + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + } + else if (PLAYER_SAID (R, we_come_in_peace)) + { + NPCPhrase (KILLED_SPATHI); + + DISABLE_PHRASE (we_come_in_peace); + } + else if (PLAYER_SAID (R, spathi_on_pluto)) + { + NPCPhrase (WHERE_SPATHI); + + DISABLE_PHRASE (spathi_on_pluto); + } + else if (PLAYER_SAID (R, hostage)) + { + NPCPhrase (GUN_TO_HEAD); + + SET_GAME_STATE (FOUND_PLUTO_SPATHI, 3); + DISABLE_PHRASE (hostage); + } + else if (PLAYER_SAID (R, killed_fwiffo)) + { + NPCPhrase (POOR_FWIFFO); + + SET_GAME_STATE (FOUND_PLUTO_SPATHI, 3); + DISABLE_PHRASE (killed_fwiffo); + } + else if (PLAYER_SAID (R, fwiffo_fine)) + { + NPCPhrase (NOT_LIKELY); + + R = killed_fwiffo; + DISABLE_PHRASE (fwiffo_fine); + } + else if (PLAYER_SAID (R, surrender)) + { + NPCPhrase (NO_SURRENDER); + + DISABLE_PHRASE (surrender); + } + + if (GET_GAME_STATE (SPATHI_MANNER) == 0) + { + Response (we_come_in_peace, AllianceOffer); + } + else if (PHRASE_ENABLED (we_come_in_peace)) + { + Response (we_come_in_peace, SpathiCouncil); + } + else + { + Response (misunderstanding, AllianceOffer); + } + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) + && GET_GAME_STATE (FOUND_PLUTO_SPATHI) < 3) + { + if (PHRASE_ENABLED (spathi_on_pluto)) + Response (spathi_on_pluto, SpathiCouncil); + else if (ActivateStarShip (SPATHI_SHIP, ESCORTING_FLAGSHIP)) + { + if (PHRASE_ENABLED (hostage)) + Response (hostage, SpathiCouncil); + } + else if (PHRASE_ENABLED (killed_fwiffo)) + { + Response (killed_fwiffo, SpathiCouncil); + if (PHRASE_ENABLED (fwiffo_fine)) + Response (fwiffo_fine, SpathiCouncil); + } + } + if (PHRASE_ENABLED (surrender)) + Response (surrender, SpathiCouncil); + else + { + Response (surrender_or_die, ExitConversation); + } + Response (bye_no_ally_offer, ExitConversation); +} + +static void +SpathiPassword (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); + switch (NumVisits++) + { + default: + NPCPhrase (WHAT_IS_PASSWORD); + NumVisits = 1; + break; + case 1: + NPCPhrase (WHAT_IS_PASSWORD_AGAIN); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, what_do_i_get)) + { + NPCPhrase (YOU_GET_TO_LIVE); + + DISABLE_PHRASE (what_do_i_get); + } + + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) + || GET_GAME_STATE (KNOW_SPATHI_PASSWORD)) + { + Response (good_password, SpathiCouncil); + if (PHRASE_ENABLED (what_do_i_get)) + { + Response (what_do_i_get, SpathiPassword); + } + } + else + { + construct_response (shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0); + DoResponsePhrase (we_are_vindicator0, ExitConversation, shared_phrase_buf); + Response (gort_merenga, ExitConversation); + Response (guph_florp, ExitConversation); + Response (wagngl_fthagn, ExitConversation); + Response (pleeese, ExitConversation); + Response (screw_password, ExitConversation); + } +} + +static void +Intro (void) +{ + BYTE Manner; + + Manner = GET_GAME_STATE (SPATHI_MANNER); + if (Manner == 2) + { + NPCPhrase (HATE_YOU_FOREVER); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (Manner == 1 + && GET_GAME_STATE (KNOW_SPATHI_PASSWORD) + && (GET_GAME_STATE (FOUND_PLUTO_SPATHI) + || GET_GAME_STATE (SPATHI_HOME_VISITS) != 7)) + { + SpathiAngry ((RESPONSE_REF)0); + } + else if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + SpathiAllies ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (SPATHI_PARTY)) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + SpathiParty ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (SPATHI_QUEST)) + { + if (GET_GAME_STATE (LIED_ABOUT_CREATURES) < 2) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + SpathiQuest ((RESPONSE_REF)0); + } + else + { + NPCPhrase (YOU_LIED_2); + + SET_GAME_STATE (SPATHI_MANNER, 2); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + } + else if (GET_GAME_STATE (KNOW_SPATHI_QUEST)) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + LearnQuest ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (KNOW_SPATHI_PASSWORD) + && (GET_GAME_STATE (FOUND_PLUTO_SPATHI) + || GET_GAME_STATE (SPATHI_HOME_VISITS) != 7)) + { + CommData.AlienColorMap = + SetAbsColorMapIndex (CommData.AlienColorMap, 1); + SpathiCouncil ((RESPONSE_REF)0); + } + else + { + SpathiPassword ((RESPONSE_REF)0); + } +} + +static COUNT +uninit_spahome (void) +{ + BYTE Manner; + + if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && (Manner = GET_GAME_STATE (SPATHI_MANNER)) != 2) + { + SET_GAME_STATE (SPATHI_MANNER, 1); + if (Manner != 1) + { + SET_GAME_STATE (SPATHI_VISITS, 0); + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + } + } + + return (0); +} + +LOCDATAPTR +init_spahome_comm () +{ + LOCDATAPTR retval; + + spahome_desc.init_encounter_func = Intro; + spahome_desc.uninit_encounter_func = uninit_spahome; + + spahome_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + spahome_desc.AlienTextTemplate.baseline.y = 0; + spahome_desc.AlienTextTemplate.align = ALIGN_CENTER; + spahome_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (SPATHI_MANNER) == 3) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + + retval = &spahome_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/spahome/strings.h b/sc2/src/sc2code/comm/spahome/strings.h new file mode 100644 index 000000000..c2a289560 --- /dev/null +++ b/sc2/src/sc2code/comm/spahome/strings.h @@ -0,0 +1,177 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + null_phrase, + killed_fwiffo, + fwiffo_fine, + we_attack_again, + bye_no_ally_offer, + bye_angry_spathi, + why_dont_you_do_it, + we_apologize, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + gort_merenga, + guph_florp, + pleeese, + wagngl_fthagn, + screw_password, + good_password, + what_do_i_get, + spathi_on_pluto, + hostage, + we_come_in_peace, + misunderstanding, + give_us_resources, + resources_please, + bye_ally, + what_about_hierarchy, + what_about_history, + what_about_alliance, + what_about_other, + what_about_precursors, + enough_info, + little_mistake, + bye_before_party, + something_fishy, + surrender, + surrender_or_die, + hand_in_friendship, + stronger, + yes_we_are, + how_prove, + share_info, + prove_strength, + what_test, + think_more, + tell_evil, + i_accept, + talk_test, + already_got_them, + too_dangerous, + killed_them_all_1, + killed_them_all_2, + zapped_a_few, + no_landing, + saw_creatures, + bye_from_party_1, + bye_from_party_2, + bye_from_party_3, + deals_a_deal, + how_long, + reneging, + return_beasts, + minds_and_might, + fellowship, + do_as_we_say, + whats_up, + like_some_info +}; + +enum +{ + NULL_PHRASE, + POOR_FWIFFO, + NOT_LIKELY, + WE_FIGHT_AGAIN, + GOODBYE_NO_ALLY_OFFER, + GOODBYE_ANGRY_SPATHI, + WE_WONT_BECAUSE, + MEAN_GUYS_RETURN, + DONT_BELIEVE, + HELLO_AGAIN, + HATE_YOU_FOREVER, + WHAT_IS_PASSWORD, + WHAT_IS_PASSWORD_AGAIN, + WRONG_PASSWORD, + NO_PASSWORD, + YOU_GET_TO_LIVE, + YES_GOOD_PASSWORD, + WHERE_SPATHI, + GUN_TO_HEAD, + OF_COURSE, + KILLED_SPATHI, + JUST_MISUNDERSTANDING, + NO_RESOURCES, + SORRY_NO_RESOURCES, + GOODBYE_ALLY, + OK_ENOUGH_INFO, + ABOUT_HIERARCHY, + ABOUT_HISTORY, + ABOUT_ALLIANCE, + ABOUT_OTHER, + ABOUT_PRECURSORS, + BIG_MISTAKE, + QUEST_AGAIN, + GOODBYE_BEFORE_PARTY, + GOOD_START, + NOTHING_FISHY, + NO_SURRENDER, + DEFEND_OURSELVES, + TOO_AFRAID, + YOURE_NOT, + NO_YOURE_NOT, + BETTER_IDEA, + NO_INFO, + WE_UNDERSTAND, + YOUR_BEHAVIOR, + BEFORE_ACCEPT, + WIPE_EVIL, + COWARD, + AWAIT_RETURN, + EARLY_BIRD_CHECK, + NOT_SURPRISED, + TEST_AGAIN, + WE_AGREE, + HOW_GO_EFFORTS, + WILL_CHECK_1, + WILL_CHECK_2, + RETURN_COMPLETE, + MUST_DESTROY_ALL, + YOU_FORTUNATE, + YOU_LIED_1, + YOU_LIED_2, + GOODBYE_FROM_PARTY, + MUST_PARTY_1, + MUST_PARTY_2, + MUST_PARTY_3, + WAIT_A_WHILE, + TEN_YEARS, + ADULT_VIEW, + WHAT_RELATIONSHIP, + HUH, + WHAT, + DEPART_FOR_EARTH, + HELLO_ALLIES_1, + HELLO_ALLIES_2, + HELLO_ALLIES_3, + GENERAL_INFO_1, + GENERAL_INFO_2, + GENERAL_INFO_3, + GENERAL_INFO_4, + GENERAL_INFO_5, + WHAT_ABOUT +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/spathi/ifontres.h b/sc2/src/sc2code/comm/spathi/ifontres.h new file mode 100644 index 000000000..02a0eeb55 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/ifontres.h @@ -0,0 +1,3 @@ +#define SPATHI_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/spathi/igfxres.h b/sc2/src/sc2code/comm/spathi/igfxres.h new file mode 100644 index 000000000..fc7907b47 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/igfxres.h @@ -0,0 +1,4 @@ +#define SPATHI_PMAP_ANIM 0x00200002L +#define SPATHI_HOME_PMAP_ANIM 0x00400102L + + diff --git a/sc2/src/sc2code/comm/spathi/imusicre.h b/sc2/src/sc2code/comm/spathi/imusicre.h new file mode 100644 index 000000000..bf2a5d8c9 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/imusicre.h @@ -0,0 +1,3 @@ +#define SPATHI_MUSIC 0x00600006L + + diff --git a/sc2/src/sc2code/comm/spathi/istrtab.h b/sc2/src/sc2code/comm/spathi/istrtab.h new file mode 100644 index 000000000..94230b841 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/istrtab.h @@ -0,0 +1,5 @@ +#define SPATHI_CONVERSATION_PHRASES 0x00200004L +#define SPATHI_HOME_COLOR_MAP 0x00400104L +#define SPATHI_HOME_CONVERSATION_PHRASES 0x00400204L + + diff --git a/sc2/src/sc2code/comm/spathi/resinst.h b/sc2/src/sc2code/comm/spathi/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/spathi/respkg.h b/sc2/src/sc2code/comm/spathi/respkg.h new file mode 100644 index 000000000..938cf7d3b --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/respkg.h @@ -0,0 +1,7 @@ +enum +{ + SPATHI_ART_PACKAGE = 1, + SPATHI_HOME_ART_PACKAGE, + SPATHI_COMMON_PACKAGE +}; + diff --git a/sc2/src/sc2code/comm/spathi/restypes.h b/sc2/src/sc2code/comm/spathi/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/spathi/spathi.res b/sc2/src/sc2code/comm/spathi/spathi.res new file mode 100644 index 000000000..ab1e21e05 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/spathi.res @@ -0,0 +1,17 @@ +INCLUDE ../../star3do.typ + +PATH comm/spathi +PACKAGE SPATHI_ART_PACKAGE spathi.con + GFXRES SPATHI_PMAP_ANIM spathi.ani + FONTRES SPATHI_FONT spathi.fon + STRTAB SPATHI_CONVERSATION_PHRASES spathi.txt + +PATH comm/spahome +PACKAGE SPATHI_HOME_ART_PACKAGE spathi.con + GFXRES SPATHI_HOME_PMAP_ANIM spahome.ani + STRTAB SPATHI_HOME_COLOR_MAP spahome.ct + STRTAB SPATHI_HOME_CONVERSATION_PHRASES spahome.txt + +PATH comm/spathi +PACKAGE SPATHI_COMMON_PACKAGE spathi.con + MUSICRES SPATHI_MUSIC spathi.mod diff --git a/sc2/src/sc2code/comm/spathi/spathic.c b/sc2/src/sc2code/comm/spathi/spathic.c new file mode 100644 index 000000000..1fec45b9d --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/spathic.c @@ -0,0 +1,792 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/spathi/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/spathi/strings.h" + +static LOCDATA spathi_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SPATHI_PMAP_ANIM, /* AlienFrame */ + (FONT)SPATHI_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + SPATHI_MUSIC, /* AlienSong */ + SPATHI_CONVERSATION_PHRASES, /* PlayerPhrases */ + 8, /* NumAnimations */ + { + { + 1, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 0, ONE_SECOND, /* RestartRate */ + (1 << 1), /* BlockMask */ + }, + { + 7, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 6, 0, /* RestartRate */ + (1 << 0), /* BlockMask */ + }, + { + 16, /* StartIndex */ + 4, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 8, /* FrameRate */ + 12, 8, /* RestartRate */ + (1 << 4), /* BlockMask */ + }, + { + 20, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* FrameRate */ + (1 << 5) + }, + { + 24, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 2), /* BlockMask */ + }, + + + { + 34, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 3), /* BlockMask */ + }, + { + 38, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 41, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, +#ifdef NEVER + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 29, /* StartIndex */ + 5, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +#endif /* NEVER */ +}; + +static void +ExitConversation (Response) +RESPONSE_REF Response; +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (Response, bye_ally_space)) + NPCPhrase (GOODBYE_ALLY_SPACE); + else if (PLAYER_SAID (Response, bye_friendly_space)) + NPCPhrase (GOODBYE_FRIENDLY_SPACE); + else if (PLAYER_SAID (Response, part_in_peace)) + NPCPhrase (KEEP_IT_SECRET); + else if (PLAYER_SAID (Response, we_sorry_space)) + NPCPhrase (APOLOGIZE_AT_HOMEWORLD); + else if (PLAYER_SAID (Response, give_info_space)) + NPCPhrase (HERES_SOME_INFO); + else if (PLAYER_SAID (Response, bye_angry_space)) + NPCPhrase (GOODBYE_ANGRY_SPACE); + else if (PLAYER_SAID (Response, attack_you_now)) + { + NPCPhrase (YIPES); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (Response, we_fight_again_space)) + { + NPCPhrase (OK_FIGHT_AGAIN_SPACE); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (Response, die_slugboy) + || PLAYER_SAID (Response, we_fight_1) + || PLAYER_SAID (Response, we_fight_2) + || PLAYER_SAID (Response, pay_for_crimes) + || PLAYER_SAID (Response, tell_me_coordinates) + || PLAYER_SAID (Response, changed_mind)) + { + if (PLAYER_SAID (Response, tell_me_coordinates)) + NPCPhrase (FAKE_COORDINATES); + NPCPhrase (OK_WE_FIGHT_AT_PLUTO); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (Response, join_us)) + { + if (ActivateStarShip (SPATHI_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (TOO_SCARY); + else + { + NPCPhrase (WILL_JOIN); + + AlienTalkSegue ((COUNT)~0); + ActivateStarShip (SPATHI_SHIP, 1); + } + } +} + +static void +SpathiOnPluto (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, hi_there)) + NPCPhrase (ARE_YOU_SURE); + else if (PLAYER_SAID (R, dont_kill)) + NPCPhrase (OK_WONT); + else if (PLAYER_SAID (R, youre_forgiven)) + NPCPhrase (THANKS_FOR_FORGIVENESS); + else if (PLAYER_SAID (R, you_wont_die_yet)) + NPCPhrase (ETERNAL_GRATITUDE); + else if (PLAYER_SAID (R, you_may_live)) + NPCPhrase (GEE_THANKS); + else if (PLAYER_SAID (R, youve_got_me_all_wrong)) + NPCPhrase (SORRY_NO_COORDS); + else if (PLAYER_SAID (R, what_doing_on_pluto_1)) + { + NPCPhrase (ABOUT_20_YEARS_AGO); + + DISABLE_PHRASE (what_doing_on_pluto_1); + } + else if (PLAYER_SAID (R, what_doing_on_pluto_2)) + { + NPCPhrase (WHEN_URQUAN_ARRIVED); + + DISABLE_PHRASE (what_doing_on_pluto_2); + } + else if (PLAYER_SAID (R, what_doing_on_pluto_3)) + { + NPCPhrase (STATIONED_ON_EARTH_MOON); + + DISABLE_PHRASE (what_doing_on_pluto_3); + } + else if (PLAYER_SAID (R, what_about_ilwrath)) + { + NPCPhrase (ABOUT_ILWRATH); + + DISABLE_PHRASE (what_about_ilwrath); + } + else if (PLAYER_SAID (R, when_ilwrath)) + { + NPCPhrase (THEN_ILWRATH); + + DISABLE_PHRASE (when_ilwrath); + } + else if (PLAYER_SAID (R, what_about_moonbase)) + { + NPCPhrase (SET_UP_BASE); + + DISABLE_PHRASE (what_about_moonbase); + } + else if (PLAYER_SAID (R, what_about_other_spathi)) + { + NPCPhrase (SPATHI_ARE); + + DISABLE_PHRASE (what_about_other_spathi); + } + else if (PLAYER_SAID (R, what_about_other_spathi)) + { + NPCPhrase (THEN_ILWRATH); + + DISABLE_PHRASE (what_about_other_spathi); + } + else if (PLAYER_SAID (R, how_many_crew)) + { + NPCPhrase (THOUSANDS); + + DISABLE_PHRASE (how_many_crew); + } + else if (PLAYER_SAID (R, really_thousands)) + { + NPCPhrase (JUST_ME); + + DISABLE_PHRASE (really_thousands); + } + else if (PLAYER_SAID (R, full_of_monsters)) + { + NPCPhrase (HOW_TRUE); + + DISABLE_PHRASE (full_of_monsters); + } + else if (PLAYER_SAID (R, what_enemy)) + { + NPCPhrase (ENEMY_IS); + + DISABLE_PHRASE (what_enemy); + } + else if (PLAYER_SAID (R, why_you_here)) + { + NPCPhrase (DREW_SHORT_STRAW); + + DISABLE_PHRASE (why_you_here); + } + else if (PLAYER_SAID (R, where_are_urquan)) + { + NPCPhrase (URQUAN_LEFT); + + DISABLE_PHRASE (where_are_urquan); + } + else if (PLAYER_SAID (R, what_about_other_races)) + { + NPCPhrase (ABOUT_OTHER_RACES); + + DISABLE_PHRASE (what_about_other_races); + } + else if (PLAYER_SAID (R, what_blaze_of_glory)) + { + NPCPhrase (BLAZE_IS); + + DISABLE_PHRASE (what_blaze_of_glory); + } + else if (PLAYER_SAID (R, what_about_yourself)) + { + NPCPhrase (ABOUT_MYSELF); + + DISABLE_PHRASE (what_about_yourself); + } + else if (PLAYER_SAID (R, join_us)) + { + static BYTE join_us_refusals; + + if (join_us_refusals == 0) + { + NPCPhrase (WONT_JOIN_1); + ++join_us_refusals; + } + else if (join_us_refusals == 1) + { + NPCPhrase (WONT_JOIN_2); + ++join_us_refusals; + } + else + NPCPhrase (WONT_JOIN_3); + } + + if (PHRASE_ENABLED (what_doing_on_pluto_1)) + Response (what_doing_on_pluto_1, SpathiOnPluto); + else if (PHRASE_ENABLED (what_doing_on_pluto_2)) + Response (what_doing_on_pluto_2, SpathiOnPluto); + else if (PHRASE_ENABLED (what_doing_on_pluto_3)) + Response (what_doing_on_pluto_3, SpathiOnPluto); + else + { + if (PHRASE_ENABLED (what_about_ilwrath)) + Response (what_about_ilwrath, SpathiOnPluto); + else if (PHRASE_ENABLED (when_ilwrath)) + Response (when_ilwrath, SpathiOnPluto); + + if (PHRASE_ENABLED (what_about_moonbase)) + Response (what_about_moonbase, SpathiOnPluto); + else if (PHRASE_ENABLED (what_about_other_spathi)) + Response (what_about_other_spathi, SpathiOnPluto); + else + { + if (PHRASE_ENABLED (how_many_crew)) + Response (how_many_crew, SpathiOnPluto); + else if (PHRASE_ENABLED (really_thousands)) + Response (really_thousands, SpathiOnPluto); + else if (PHRASE_ENABLED (full_of_monsters)) + Response (full_of_monsters, SpathiOnPluto); + + if (PHRASE_ENABLED (what_enemy)) + Response (what_enemy, SpathiOnPluto); + else if (PHRASE_ENABLED (why_you_here)) + Response (why_you_here, SpathiOnPluto); + } + } + if (PHRASE_ENABLED (where_are_urquan)) + Response (where_are_urquan, SpathiOnPluto); + else if (PHRASE_ENABLED (what_about_other_races)) + Response (what_about_other_races, SpathiOnPluto); + else if (PHRASE_ENABLED (what_blaze_of_glory)) + Response (what_blaze_of_glory, SpathiOnPluto); + else if (PHRASE_ENABLED (what_about_yourself)) + Response (what_about_yourself, SpathiOnPluto); + + if (!PHRASE_ENABLED (full_of_monsters)) + Response (join_us, ExitConversation); + else + Response (join_us, SpathiOnPluto); + Response (changed_mind, ExitConversation); +} + +static void +SpathiMustGrovel (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, identify)) + { + NPCPhrase (I_FWIFFO); + + Response (do_cultural, SpathiMustGrovel); + Response (youre_forgiven, SpathiOnPluto); + Response (die_slugboy, ExitConversation); + } + else if (PLAYER_SAID (R, do_cultural)) + { + NPCPhrase (WEZZY_WEZZAH); + + Response (begin_ritual, SpathiMustGrovel); + Response (you_wont_die_yet, SpathiOnPluto); + Response (we_fight_2, ExitConversation); + } + else if (PLAYER_SAID (R, begin_ritual)) + { + NPCPhrase (MUST_DO_RITUAL_AT_HOME); + + Response (you_may_live, SpathiOnPluto); + Response (pay_for_crimes, ExitConversation); + Response (what_are_coordinates, SpathiMustGrovel); + } + else /* if (R == what_are_coordinates) */ + { + NPCPhrase (COORDINATES_ARE); + + Response (youve_got_me_all_wrong, SpathiOnPluto); + Response (tell_me_coordinates, ExitConversation); + } +} + +static void +SpathiAllies (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_ALLIED_HELLO_SPACE); + break; + case 1: + NPCPhrase (SUBSEQUENT_ALLIED_HELLO_SPACE); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, whats_up_space_2)) + { + NPCPhrase (GENERAL_INFO_SPACE_2); + + DISABLE_PHRASE (whats_up_space_2); + } + else if (PLAYER_SAID (R, give_us_info_from_space)) + { + NPCPhrase (GET_INFO_FROM_SPATHIWA); + + DISABLE_PHRASE (give_us_info_from_space); + } + else if (PLAYER_SAID (R, give_us_resources_space)) + { + NPCPhrase (GET_RESOURCES_FROM_SPATHIWA); + + DISABLE_PHRASE (give_us_resources_space); + } + else if (PLAYER_SAID (R, what_do_for_fun)) + { + NPCPhrase (DO_THIS_FOR_FUN); + + DISABLE_PHRASE (what_do_for_fun); + } + + if (PHRASE_ENABLED (whats_up_space_2)) + Response (whats_up_space_2, SpathiAllies); + if (PHRASE_ENABLED (give_us_info_from_space)) + Response (give_us_info_from_space, SpathiAllies); + if (PHRASE_ENABLED (give_us_resources_space)) + Response (give_us_resources_space, SpathiAllies); + if (PHRASE_ENABLED (what_do_for_fun)) + Response (what_do_for_fun, SpathiAllies); + Response (bye_ally_space, ExitConversation); +} + +static void +SpathiFriendly (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_FRIENDLY_HELLO_SPACE); + break; + case 1: + NPCPhrase (SUBSEQUENT_FRIENDLY_HELLO_SPACE); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, since_friendly_give_stuff)) + { + NPCPhrase (GIVE_ADVICE); + + DISABLE_PHRASE (since_friendly_give_stuff); + } + else if (PLAYER_SAID (R, whats_up_space_1)) + { + NPCPhrase (GENERAL_INFO_SPACE_1); + + DISABLE_PHRASE (whats_up_space_1); + } + + if (PHRASE_ENABLED (whats_up_space_1)) + Response (whats_up_space_1, SpathiFriendly); + if (PHRASE_ENABLED (since_friendly_give_stuff)) + Response (since_friendly_give_stuff, SpathiFriendly); + Response (bye_friendly_space, ExitConversation); +} + +static void SpathiNeutral (RESPONSE_REF R); + +static void +SpathiBefriend (RESPONSE_REF R) +{ + BYTE InfoLeft, LastStack; + RESPONSE_REF pStr[2]; + + InfoLeft = FALSE; + LastStack = 0; + pStr[0] = pStr[1] = 0; + if (PLAYER_SAID (R, come_in_peace)) + NPCPhrase (AGAINST_NATURE); + else if (PLAYER_SAID (R, looking_for_a_few_good_squids)) + { + NPCPhrase (URQUAN_SLAVES); + + DISABLE_PHRASE (looking_for_a_few_good_squids); + } + else if (PLAYER_SAID (R, why_slaves)) + { + NPCPhrase (UMGAH_TRICK); + + DISABLE_PHRASE (why_slaves); + } + else if (PLAYER_SAID (R, tell_us_about_you)) + { + NPCPhrase (ABOUT_US); + + DISABLE_PHRASE (tell_us_about_you); + LastStack = 1; + } + else if (PLAYER_SAID (R, what_you_really_want)) + { + NPCPhrase (WANT_THIS); + + DISABLE_PHRASE (what_you_really_want); + } + else if (PLAYER_SAID (R, how_about_alliance)) + { + NPCPhrase (SURE); + + DISABLE_PHRASE (how_about_alliance); + } + + if (PHRASE_ENABLED (looking_for_a_few_good_squids)) + pStr[0] = looking_for_a_few_good_squids; + else if (PHRASE_ENABLED (why_slaves)) + pStr[0] = why_slaves; + if (PHRASE_ENABLED (tell_us_about_you)) + pStr[1] = tell_us_about_you; + else if (PHRASE_ENABLED (what_you_really_want)) + pStr[1] = what_you_really_want; + if (pStr[LastStack]) + { + InfoLeft = TRUE; + Response (pStr[LastStack], SpathiBefriend); + } + LastStack ^= 1; + if (pStr[LastStack]) + { + InfoLeft = TRUE; + Response (pStr[LastStack], SpathiBefriend); + } + if (PHRASE_ENABLED (how_about_alliance)) + { + InfoLeft = TRUE; + Response (how_about_alliance, SpathiBefriend); + } + + if (!InfoLeft) + { + SET_GAME_STATE (SPATHI_STACK1, 1); + SpathiNeutral (R); + } +} + +static void +SpathiAntagonize (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, prepare_to_die)) + { + NPCPhrase (ALWAYS_PREPARED); + + SET_GAME_STATE (SPATHI_STACK2, 1); + } + else if (PLAYER_SAID (R, heard_youre_cowards)) + { + NPCPhrase (DARN_TOOTIN); + + DISABLE_PHRASE (heard_youre_cowards); + } + else if (PLAYER_SAID (R, wanna_fight)) + { + NPCPhrase (YES_WE_DO); + + DISABLE_PHRASE (wanna_fight); + } + else if (PLAYER_SAID (R, so_lets_fight)) + { + NPCPhrase (OK_LETS_FIGHT); + + DISABLE_PHRASE (so_lets_fight); + } + else if (PLAYER_SAID (R, so_lets_fight_already)) + { + NPCPhrase (DONT_REALLY_WANT_TO_FIGHT); + + DISABLE_PHRASE (so_lets_fight_already); + } + + if (PHRASE_ENABLED (wanna_fight)) + Response (wanna_fight, SpathiAntagonize); + else if (PHRASE_ENABLED (so_lets_fight)) + Response (so_lets_fight, SpathiAntagonize); + else if (PHRASE_ENABLED (so_lets_fight_already)) + Response (so_lets_fight_already, SpathiAntagonize); + if (PHRASE_ENABLED (heard_youre_cowards)) + Response (heard_youre_cowards, SpathiAntagonize); + Response (attack_you_now, ExitConversation); +} + +static void +SpathiNeutral (RESPONSE_REF R) +{ + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_NEUTRAL_HELLO_SPACE); + break; + case 1: + NPCPhrase (SUBSEQUENT_NEUTRAL_HELLO_SPACE); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, look_weird)) + { + NPCPhrase (YOU_LOOK_WEIRD); + + SET_GAME_STATE (SPATHI_STACK0, 1); + } + else if (PLAYER_SAID (R, no_look_really_weird)) + { + NPCPhrase (NO_YOU_LOOK_REALLY_WEIRD); + + SET_GAME_STATE (SPATHI_STACK0, 2); + } + + switch (GET_GAME_STATE (SPATHI_STACK0)) + { + case 0: + Response (look_weird, SpathiNeutral); + break; + case 1: + Response (no_look_really_weird, SpathiNeutral); + break; + } + if (GET_GAME_STATE (SPATHI_STACK1) == 0) + { + Response (come_in_peace, SpathiBefriend); + } + if (GET_GAME_STATE (SPATHI_STACK2) == 0) + { + Response (prepare_to_die, SpathiAntagonize); + } + else + { + Response (attack_you_now, ExitConversation); + } + Response (part_in_peace, ExitConversation); +} + +static void +Intro (void) +{ + BYTE Manner; + + Manner = GET_GAME_STATE (SPATHI_MANNER); + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) + { + NPCPhrase (SORRY_ABOUT_THAT); + + /* if already know password from Melnorme, + * but haven't visited Spathiwa yet . . . + */ + if (GET_GAME_STATE (SPATHI_HOME_VISITS) == 7) + { + SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 0); + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + } + + Response (identify, SpathiMustGrovel); + Response (hi_there, SpathiOnPluto); + Response (dont_kill, SpathiOnPluto); + Response (we_fight_1, ExitConversation); + } + else if (Manner == 2) + { + NPCPhrase (HATE_YOU_FOREVER_SPACE); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (Manner == 1) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SPATHI_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_ANGRY_HELLO_SPACE); + break; + case 1: + NPCPhrase (SUBSEQUENT_ANGRY_HELLO_SPACE); + --NumVisits; + break; + } + SET_GAME_STATE (SPATHI_VISITS, NumVisits); + + Response (give_info_space, ExitConversation); + Response (we_sorry_space,ExitConversation); + Response (we_fight_again_space, ExitConversation); + Response (bye_angry_space, ExitConversation); + } + else if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) + { + SpathiAllies ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (SPATHI_QUEST)) + { + SpathiFriendly ((RESPONSE_REF)0); + } + else + { + SpathiNeutral ((RESPONSE_REF)0); + } +} + +static COUNT +uninit_spathi (void) +{ + BYTE Manner; + + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) + { + SET_GAME_STATE (FOUND_PLUTO_SPATHI, 2); + } + else if (GET_GAME_STATE (BATTLE_SEGUE) == 1 + && (Manner = GET_GAME_STATE (SPATHI_MANNER)) != 2) + { + SET_GAME_STATE (SPATHI_MANNER, 1); + if (Manner != 1) + { + SET_GAME_STATE (SPATHI_VISITS, 0); + /* if don't know about Spathi via Melnorme . . . */ + if (GET_GAME_STATE (SPATHI_HOME_VISITS) != 7) + { + SET_GAME_STATE (SPATHI_HOME_VISITS, 0); + } + } + } + + return (0); +} + +LOCDATAPTR +init_spathi_comm (void) +{ + LOCDATAPTR retval; + + spathi_desc.init_encounter_func = Intro; + spathi_desc.uninit_encounter_func = uninit_spathi; + + spathi_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + spathi_desc.AlienTextTemplate.baseline.y = 0; + spathi_desc.AlienTextTemplate.align = ALIGN_CENTER; + spathi_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1 + || GET_GAME_STATE (SPATHI_MANNER) == 3 + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &spathi_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/spathi/strings.h b/sc2/src/sc2code/comm/spathi/strings.h new file mode 100644 index 000000000..cbab78d65 --- /dev/null +++ b/sc2/src/sc2code/comm/spathi/strings.h @@ -0,0 +1,160 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + SORRY_ABOUT_THAT, + identify, + I_FWIFFO, + hi_there, + ARE_YOU_SURE, + dont_kill, + we_fight_1, + we_fight_2, + OK_WONT, + do_cultural, + WEZZY_WEZZAH, + die_slugboy, + begin_ritual, + MUST_DO_RITUAL_AT_HOME, + you_wont_die_yet, + ETERNAL_GRATITUDE, + we_fight, + pay_for_crimes, + CLUTCH_MAVEN, + you_may_live, + HONEST_AND_FRIENDLY, + what_are_coordinates, + COORDINATES_ARE, + tell_me_coordinates, + FAKE_COORDINATES, + TOO_SCARY, + youve_got_me_all_wrong, + SORRY_NO_COORDS, + what_doing_on_pluto_1, + ABOUT_20_YEARS_AGO, + what_doing_on_pluto_2, + WHEN_URQUAN_ARRIVED, + where_are_urquan, + URQUAN_LEFT, + what_about_other_races, + ABOUT_OTHER_RACES, + what_doing_on_pluto_3, + what_about_yourself, + ABOUT_MYSELF, + STATIONED_ON_EARTH_MOON, + what_blaze_of_glory, + BLAZE_IS, + what_about_moonbase, + SET_UP_BASE, + what_about_ilwrath, + ABOUT_ILWRATH, + what_about_other_spathi, + really_thousands, + SPATHI_ARE, + what_enemy, + ENEMY_IS, + when_ilwrath, + THEN_ILWRATH, + why_you_here, + DREW_SHORT_STRAW, + how_many_crew, + JUST_ME, + THOUSANDS, + full_of_monsters, + HOW_TRUE, + join_us, + WILL_JOIN, + WONT_JOIN_1, + give_ship_or_die, + WONT_JOIN_2, + WONT_JOIN_3, + GEE_THANKS, + changed_mind, + youre_forgiven, + THANKS_FOR_FORGIVENESS, + HATE_YOU_FOREVER_SPACE, + INIT_ANGRY_HELLO_SPACE, + SUBSEQUENT_ANGRY_HELLO_SPACE, + INIT_NEUTRAL_HELLO_SPACE, + SUBSEQUENT_NEUTRAL_HELLO_SPACE, + INIT_FRIENDLY_HELLO_SPACE, + SUBSEQUENT_FRIENDLY_HELLO_SPACE, + INIT_ALLIED_HELLO_SPACE, + SUBSEQUENT_ALLIED_HELLO_SPACE, + give_info_space, + HERES_SOME_INFO, + we_sorry_space, + APOLOGIZE_AT_HOMEWORLD, + we_fight_again_space, + OK_FIGHT_AGAIN_SPACE, + bye_angry_space, + GOODBYE_ANGRY_SPACE, + look_weird, + YOU_LOOK_WEIRD, + no_look_really_weird, + NO_YOU_LOOK_REALLY_WEIRD, + come_in_peace, + AGAINST_NATURE, + prepare_to_die, + ALWAYS_PREPARED, + since_friendly_give_stuff, + GIVE_ADVICE, + whats_up_space_1, + GENERAL_INFO_SPACE_1, + bye_friendly_space, + GOODBYE_FRIENDLY_SPACE, + looking_for_a_few_good_squids, + URQUAN_SLAVES, + why_slaves, + UMGAH_TRICK, + tell_us_about_you, + ABOUT_US, + what_you_really_want, + WANT_THIS, + how_about_alliance, + SURE, + part_in_peace, + KEEP_IT_SECRET, + heard_youre_cowards, + DARN_TOOTIN, + wanna_fight, + YES_WE_DO, + so_lets_fight, + OK_LETS_FIGHT, + so_lets_fight_already, + DONT_REALLY_WANT_TO_FIGHT, + attack_you_now, + YIPES, + whats_up_space_2, + GENERAL_INFO_SPACE_2, + give_us_info_from_space, + GET_INFO_FROM_SPATHIWA, + give_us_resources_space, + GET_RESOURCES_FROM_SPATHIWA, + what_do_for_fun, + DO_THIS_FOR_FUN, + bye_ally_space, + GOODBYE_ALLY_SPACE, + OK_WE_FIGHT_AT_PLUTO, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/starbas/starbas.c b/sc2/src/sc2code/comm/starbas/starbas.c new file mode 100644 index 000000000..1c91e6ba9 --- /dev/null +++ b/sc2/src/sc2code/comm/starbas/starbas.c @@ -0,0 +1,1933 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/comandr/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/starbas/strings.h" + +//Added by Chris + +void ShowRemainingCapacity (void); + +void DrawCargoStrings (BYTE OldElement, BYTE NewElement); + +//End Added by Chris + +static LOCDATA commander_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)COMMANDER_PMAP_ANIM, /* AlienFrame */ + (FONT)COMMANDER_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ + (COLORMAP)COMMANDER_COLOR_MAP, /* AlienColorMap */ + COMMANDER_MUSIC, /* AlienSong */ + STARBASE_CONVERSATION_PHRASES, /* PlayerPhrases */ + 10, /* NumAnimations */ + { + { /* Blink */ + 1, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Running light */ + 10, /* StartIndex */ + 30, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + ONE_SECOND * 2, 0, /* RestartRate */ + }, + { /* Arc welder 0 */ + 40, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 1 */ + 47, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 2 */ + 55, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 3 */ + 61, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 4 */ + 67, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 5 */ + 74, /* StartIndex */ + 11, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Arc welder 6 */ + 85, /* StartIndex */ + 10, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 3, 0, /* FrameRate */ + 0, ONE_SECOND * 8, /* RestartRate */ + }, + { /* Flagship picture */ + 95, /* StartIndex */ + 1, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 4, /* StartIndex */ + 6, /* NumFrames */ + 0, /* AnimFlags */ + 12, 8, /* FrameRate */ + 14, 10, /* RestartRate */ + }, +}; + +static DWORD CurBulletinMask; + +static void +ByeBye (R) +RESPONSE_REF R; +{ + BYTE b0, b1, b2, b3; + + b0 = GET_GAME_STATE (STARBASE_BULLETS0); + b1 = GET_GAME_STATE (STARBASE_BULLETS1); + b2 = GET_GAME_STATE (STARBASE_BULLETS2); + b3 = GET_GAME_STATE (STARBASE_BULLETS3); + CurBulletinMask |= MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + b0 = LOBYTE (LOWORD (CurBulletinMask)); + b1 = HIBYTE (LOWORD (CurBulletinMask)); + b2 = LOBYTE (HIWORD (CurBulletinMask)); + b3 = HIBYTE (HIWORD (CurBulletinMask)); + SET_GAME_STATE (STARBASE_BULLETS0, b0); + SET_GAME_STATE (STARBASE_BULLETS1, b1); + SET_GAME_STATE (STARBASE_BULLETS2, b2); + SET_GAME_STATE (STARBASE_BULLETS3, b3); + + /* if (R == goodbye_starbase_commander) */ + if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) + NPCPhrase (GOOD_LUCK_AGAIN); + else + { + RESPONSE_REF pStr0, pStr1; + + switch ((BYTE)Random () & 7) + { + case 0: + pStr0 = NORMAL_GOODBYE_A0; + pStr1 = NORMAL_GOODBYE_A1; + break; + case 1: + pStr0 = NORMAL_GOODBYE_B0; + pStr1 = NORMAL_GOODBYE_B1; + break; + case 2: + pStr0 = NORMAL_GOODBYE_C0; + pStr1 = NORMAL_GOODBYE_C1; + break; + case 3: + pStr0 = NORMAL_GOODBYE_D0; + pStr1 = NORMAL_GOODBYE_D1; + break; + case 4: + pStr0 = NORMAL_GOODBYE_E0; + pStr1 = NORMAL_GOODBYE_E1; + break; + case 5: + pStr0 = NORMAL_GOODBYE_F0; + pStr1 = NORMAL_GOODBYE_F1; + break; + case 6: + pStr0 = NORMAL_GOODBYE_G0; + pStr1 = NORMAL_GOODBYE_G1; + break; + case 7: + pStr0 = NORMAL_GOODBYE_H0; + pStr1 = NORMAL_GOODBYE_H1; + break; + } + + NPCPhrase (pStr0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (pStr1); + } +} + +static void NeedInfo (RESPONSE_REF R); +static void TellHistory (RESPONSE_REF R); +static void AlienRaces (RESPONSE_REF R); + +static BYTE stack0 = 0, + stack1 = 0, + stack2 = 0, + stack3 = 0; + +static void +AllianceInfo (RESPONSE_REF R) +{ +#define ALLIANCE_SHOFIXTI (1 << 0) +#define ALLIANCE_YEHAT (1 << 1) +#define ALLIANCE_ARILOU (1 << 2) +#define ALLIANCE_CHENJESU (1 << 3) +#define ALLIANCE_MMRNMHRM (1 << 4) +#define ALLIANCE_SYREEN (1 << 5) + static BYTE AllianceMask = 0; + + if (PLAYER_SAID (R, what_about_alliance)) + { + NPCPhrase (WHICH_ALLIANCE); + AllianceMask = 0; + } + else if (PLAYER_SAID (R, shofixti)) + { + NPCPhrase (ABOUT_SHOFIXTI); + AllianceMask |= ALLIANCE_SHOFIXTI; + } + else if (PLAYER_SAID (R, yehat)) + { + NPCPhrase (ABOUT_YEHAT); + AllianceMask |= ALLIANCE_YEHAT; + } + else if (PLAYER_SAID (R, arilou)) + { + NPCPhrase (ABOUT_ARILOU); + AllianceMask |= ALLIANCE_ARILOU; + } + else if (PLAYER_SAID (R, chenjesu)) + { + NPCPhrase (ABOUT_CHENJESU); + AllianceMask |= ALLIANCE_CHENJESU; + } + else if (PLAYER_SAID (R, mmrnmhrm)) + { + NPCPhrase (ABOUT_MMRNMHRM); + AllianceMask |= ALLIANCE_MMRNMHRM; + } + else if (PLAYER_SAID (R, syreen)) + { + NPCPhrase (ABOUT_SYREEN); + AllianceMask |= ALLIANCE_SYREEN; + } + + if (!(AllianceMask & ALLIANCE_SHOFIXTI)) + Response (shofixti, AllianceInfo); + if (!(AllianceMask & ALLIANCE_YEHAT)) + Response (yehat, AllianceInfo); + if (!(AllianceMask & ALLIANCE_ARILOU)) + Response (arilou, AllianceInfo); + if (!(AllianceMask & ALLIANCE_CHENJESU)) + Response (chenjesu, AllianceInfo); + if (!(AllianceMask & ALLIANCE_MMRNMHRM)) + Response (mmrnmhrm, AllianceInfo); + if (!(AllianceMask & ALLIANCE_SYREEN)) + Response (syreen, AllianceInfo); + Response (enough_alliance, AlienRaces); +} + +static void +HierarchyInfo (RESPONSE_REF R) +{ +#define HIERARCHY_MYCON (1 << 0) +#define HIERARCHY_SPATHI (1 << 1) +#define HIERARCHY_UMGAH (1 << 2) +#define HIERARCHY_ANDROSYNTH (1 << 3) +#define HIERARCHY_ILWRATH (1 << 4) +#define HIERARCHY_VUX (1 << 5) + static BYTE HierarchyMask = 0; + + if (PLAYER_SAID (R, what_about_hierarchy)) + { + NPCPhrase (WHICH_HIERARCHY); + HierarchyMask = 0; + } + else if (PLAYER_SAID (R, mycon)) + { + NPCPhrase (ABOUT_MYCON); + HierarchyMask |= HIERARCHY_MYCON; + } + else if (PLAYER_SAID (R, spathi)) + { + NPCPhrase (ABOUT_SPATHI); + HierarchyMask |= HIERARCHY_SPATHI; + } + else if (PLAYER_SAID (R, umgah)) + { + NPCPhrase (ABOUT_UMGAH); + HierarchyMask |= HIERARCHY_UMGAH; + } + else if (PLAYER_SAID (R, androsynth)) + { + NPCPhrase (ABOUT_ANDROSYNTH); + HierarchyMask |= HIERARCHY_ANDROSYNTH; + } + else if (PLAYER_SAID (R, ilwrath)) + { + NPCPhrase (ABOUT_ILWRATH); + HierarchyMask |= HIERARCHY_ILWRATH; + } + else if (PLAYER_SAID (R, vux)) + { + NPCPhrase (ABOUT_VUX); + HierarchyMask |= HIERARCHY_VUX; + } + + if (!(HierarchyMask & HIERARCHY_MYCON)) + Response (mycon, HierarchyInfo); + if (!(HierarchyMask & HIERARCHY_SPATHI)) + Response (spathi, HierarchyInfo); + if (!(HierarchyMask & HIERARCHY_UMGAH)) + Response (umgah, HierarchyInfo); + if (!(HierarchyMask & HIERARCHY_ANDROSYNTH)) + Response (androsynth, HierarchyInfo); + if (!(HierarchyMask & HIERARCHY_ILWRATH)) + Response (ilwrath, HierarchyInfo); + if (!(HierarchyMask & HIERARCHY_VUX)) + Response (vux, HierarchyInfo); + Response (enough_hierarchy, AlienRaces); +} + +static void +AlienRaces (RESPONSE_REF R) +{ +#define RACES_ALLIANCE (1 << 0) +#define RACES_HIERARCHY (1 << 1) +#define RACES_OTHER (1 << 2) + static BYTE RacesMask = 0; + + if (PLAYER_SAID (R, alien_races)) + { + NPCPhrase (WHICH_ALIEN); + RacesMask = 0; + } + else if (PLAYER_SAID (R, enough_alliance)) + { + NPCPhrase (OK_ENOUGH_ALLIANCE); + RacesMask |= RACES_ALLIANCE; + } + else if (PLAYER_SAID (R, enough_hierarchy)) + { + NPCPhrase (OK_ENOUGH_HIERARCHY); + RacesMask |= RACES_HIERARCHY; + } + else if (PLAYER_SAID (R, what_about_other)) + { + NPCPhrase (ABOUT_OTHER); + RacesMask |= RACES_OTHER; + } + + if (!(RacesMask & RACES_ALLIANCE)) + { + Response (what_about_alliance, AllianceInfo); + } + if (!(RacesMask & RACES_HIERARCHY)) + { + Response (what_about_hierarchy, HierarchyInfo); + } + if (!(RacesMask & RACES_OTHER)) + { + Response (what_about_other, AlienRaces); + } + Response (enough_aliens, TellHistory); +} + +static void +WarInfo (RESPONSE_REF R) +{ +#define WAR_STARTED (1 << 0) +#define WAR_WAS_LIKE (1 << 1) +#define WAR_LOST (1 << 2) +#define WAR_AFTERMATH (1 << 3) + static BYTE WarMask = 0; + + if (PLAYER_SAID (R, the_war)) + { + NPCPhrase (WHICH_WAR); + WarMask = 0; + } + else if (PLAYER_SAID (R, what_started_war)) + { + NPCPhrase (URQUAN_STARTED_WAR); + WarMask |= WAR_STARTED; + } + else if (PLAYER_SAID (R, what_was_war_like)) + { + NPCPhrase (WAR_WAS_LIKE_SO); + WarMask |= WAR_WAS_LIKE; + } + else if (PLAYER_SAID (R, why_lose_war)) + { + NPCPhrase (LOST_WAR_BECAUSE); + WarMask |= WAR_LOST; + } + else if (PLAYER_SAID (R, what_after_war)) + { + NPCPhrase (AFTER_WAR); + WarMask |= WAR_AFTERMATH; + } + + if (!(WarMask & WAR_STARTED)) + Response (what_started_war, WarInfo); + if (!(WarMask & WAR_WAS_LIKE)) + Response (what_was_war_like, WarInfo); + if (!(WarMask & WAR_LOST)) + Response (why_lose_war, WarInfo); + if (!(WarMask & WAR_AFTERMATH)) + Response (what_after_war, WarInfo); + Response (enough_war, TellHistory); +} + +static void +AncientHistory (RESPONSE_REF R) +{ +#define ANCIENT_PRECURSORS (1 << 0) +#define ANCIENT_RACES (1 << 1) +#define ANCIENT_EARTH (1 << 2) + static BYTE AncientMask = 0; + + if (PLAYER_SAID (R, ancient_history)) + { + NPCPhrase (WHICH_ANCIENT); + AncientMask = 0; + } + else if (PLAYER_SAID (R, precursors)) + { + NPCPhrase (ABOUT_PRECURSORS); + AncientMask |= ANCIENT_PRECURSORS; + } + else if (PLAYER_SAID (R, old_races)) + { + NPCPhrase (ABOUT_OLD_RACES); + AncientMask |= ANCIENT_RACES; + } + else if (PLAYER_SAID (R, aliens_on_earth)) + { + NPCPhrase (ABOUT_ALIENS_ON_EARTH); + AncientMask |= ANCIENT_EARTH; + } + + if (!(AncientMask & ANCIENT_PRECURSORS)) + Response (precursors, AncientHistory); + if (!(AncientMask & ANCIENT_RACES)) + Response (old_races, AncientHistory); + if (!(AncientMask & ANCIENT_EARTH)) + Response (aliens_on_earth, AncientHistory); + Response (enough_ancient, TellHistory); +} + +static void +TellHistory (RESPONSE_REF R) +{ + RESPONSE_REF pstack[3]; + + if (PLAYER_SAID (R, history)) + { + NPCPhrase (WHICH_HISTORY); + stack0 = stack1 = stack2 = 0; + } + else if (PLAYER_SAID (R, enough_aliens)) + { + NPCPhrase (OK_ENOUGH_ALIENS); + + stack0 = 1; + } + else if (PLAYER_SAID (R, enough_war)) + { + NPCPhrase (OK_ENOUGH_WAR); + + stack1 = 1; + } + else if (PLAYER_SAID (R, enough_ancient)) + { + NPCPhrase (OK_ENOUGH_ANCIENT); + + stack2 = 1; + } + + switch (stack0) + { + case 0: + pstack[0] = alien_races; + break; + case 1: + pstack[0] = 0; + break; + } + switch (stack1) + { + case 0: + pstack[1] = the_war; + break; + case 1: + pstack[1] = 0; + break; + } + switch (stack2) + { + case 0: + pstack[2] = ancient_history; + break; + case 1: + pstack[2] = 0; + break; + } + + if (pstack[0]) + { + Response (pstack[0], AlienRaces); + } + if (pstack[1]) + { + Response (pstack[1], WarInfo); + } + if (pstack[2]) + { + Response (pstack[2], AncientHistory); + } + Response (enough_history, NeedInfo); +} + +static void +DefeatUrquan (RESPONSE_REF R) +{ +#define HOW_FIND_URQUAN (1 << 0) +#define HOW_FIGHT_URQUAN (1 << 1) +#define HOW_ALLY_AGAINST_URQUAN (1 << 2) +#define HOW_STRONG_AGAINST_URQUAN (1 << 3) + static BYTE DefeatMask = 0; + static void TellMission (RESPONSE_REF R); + + if (PLAYER_SAID (R, how_defeat)) + { + NPCPhrase (DEFEAT_LIKE_SO); + DefeatMask = 0; + } + else if (PLAYER_SAID (R, how_find_urquan)) + { + NPCPhrase (FIND_URQUAN); + DefeatMask |= HOW_FIND_URQUAN; + } + else if (PLAYER_SAID (R, how_fight_urquan)) + { + NPCPhrase (FIGHT_URQUAN); + DefeatMask |= HOW_FIGHT_URQUAN; + } + else if (PLAYER_SAID (R, how_ally)) + { + NPCPhrase (ALLY_LIKE_SO); + DefeatMask |= HOW_ALLY_AGAINST_URQUAN; + } + else if (PLAYER_SAID (R, how_get_strong)) + { + NPCPhrase (STRONG_LIKE_SO); + DefeatMask |= HOW_STRONG_AGAINST_URQUAN; + } + + if (!(DefeatMask & HOW_FIND_URQUAN)) + Response (how_find_urquan, DefeatUrquan); + if (!(DefeatMask & HOW_FIGHT_URQUAN)) + Response (how_fight_urquan, DefeatUrquan); + if (!(DefeatMask & HOW_ALLY_AGAINST_URQUAN)) + Response (how_ally, DefeatUrquan); + if (!(DefeatMask & HOW_STRONG_AGAINST_URQUAN)) + Response (how_get_strong, DefeatUrquan); + Response (enough_defeat, TellMission); +} + +static void +AnalyzeCondition (void) +{ + BYTE i; + BYTE num_thrusters = 0, + num_jets = 0, + num_guns = 0, + num_bays = 0, + num_batts = 0, + num_track = 0, + num_defense = 0; + BOOLEAN HasMinimum; + + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + if (GLOBAL_SIS (DriveSlots[i]) < EMPTY_SLOT) + ++num_thrusters; + } + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + if (GLOBAL_SIS (JetSlots[i]) < EMPTY_SLOT) + ++num_jets; + } + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + BYTE which_piece; + + switch (which_piece = GLOBAL_SIS (ModuleSlots[i])) + { + case STORAGE_BAY: + ++num_bays; + break; + case DYNAMO_UNIT: + case SHIVA_FURNACE: + num_batts += 1 + (which_piece - DYNAMO_UNIT); + break; + case GUN_WEAPON: + case BLASTER_WEAPON: + case CANNON_WEAPON: + num_guns += 1 + (which_piece - GUN_WEAPON); + break; + case TRACKING_SYSTEM: + ++num_track; + break; + case ANTIMISSILE_DEFENSE: + ++num_defense; + break; + } + } + if (num_track && num_guns) + num_guns += 2; + + HasMinimum = (num_thrusters >= 7 && num_jets >= 5 + && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY + && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY + && num_bays >= 1 && GLOBAL_SIS (NumLanders) + && num_batts >= 1 && num_guns >= 2); + NPCPhrase (LETS_SEE); + if (!HasMinimum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) + { + NPCPhrase (IMPROVE_1); + if (num_thrusters < 7) + NPCPhrase (NEED_THRUSTERS_1); + if (num_jets < 5) + NPCPhrase (NEED_TURN_1); + if (num_guns < 2) + NPCPhrase (NEED_GUNS_1); + if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY) + NPCPhrase (NEED_CREW_1); + if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY) + NPCPhrase (NEED_FUEL_1); + if (num_bays < 1) + NPCPhrase (NEED_STORAGE_1); + if (GLOBAL_SIS (NumLanders) == 0) + NPCPhrase (NEED_LANDERS_1); + if (num_batts < 1) + NPCPhrase (NEED_DYNAMOS_1); + + if (GLOBAL_SIS (ResUnits) >= 3000) + NPCPhrase (IMPROVE_FLAGSHIP_WITH_RU); + else + NPCPhrase (GO_GET_MINERALS); + } + else + { + BYTE num_aliens = 0; + COUNT FleetStrength; + BOOLEAN HasMaximum; + + FleetStrength = ActivateStarShip (0, ESCORT_WORTH); + for (i = 0; i < NUM_AVAILABLE_RACES; ++i) + { + if (i != HUMAN_SHIP + && (ActivateStarShip (i, CHECK_ALLIANCE) & GOOD_GUY)) + ++num_aliens; + } + + HasMaximum = (num_thrusters == NUM_DRIVE_SLOTS + && num_jets == NUM_JET_SLOTS + && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY * 3 + && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY * 3 + && GLOBAL_SIS (NumLanders) >= 3 + && num_batts >= 4 && num_guns >= 7 && num_defense >= 2); + if (!HasMaximum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) + NPCPhrase (GOT_OK_FLAGSHIP); + else + NPCPhrase (GOT_AWESOME_FLAGSHIP); + + if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) + { + NPCPhrase (CHMMR_IMPROVED_BOMB); + if (FleetStrength < 20000) + NPCPhrase (MUST_ACQUIRE_AWESOME_FLEET); + else + { + NPCPhrase (GOT_AWESOME_FLEET); + if (!GET_GAME_STATE (TALKING_PET_ON_SHIP)) + NPCPhrase (MUST_ELIMINATE_URQUAN_GUARDS); + else + NPCPhrase (GO_DESTROY_SAMATRA); + } + } + else if (num_aliens < 2) + NPCPhrase (GO_ALLY_WITH_ALIENS); + else + { + NPCPhrase (MADE_SOME_ALLIES); + if (FleetStrength < 6000) + { + if (GLOBAL_SIS (ResUnits) >= 3000) + NPCPhrase (BUY_COMBAT_SHIPS); + else + NPCPhrase (GET_SHIPS_BY_MINING_OR_ALLIANCE); + } + else + { + NPCPhrase (GOT_OK_FLEET); + if (!HasMaximum) + { + NPCPhrase (IMPROVE_2); + if (num_thrusters < NUM_DRIVE_SLOTS) + NPCPhrase (NEED_THRUSTERS_2); + if (num_jets < NUM_JET_SLOTS) + NPCPhrase (NEED_TURN_2); + if (num_guns < 7) + NPCPhrase (NEED_GUNS_2); + if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY * 3) + NPCPhrase (NEED_CREW_2); + if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY * 3) + NPCPhrase (NEED_FUEL_2); + if (GLOBAL_SIS (NumLanders) < 3) + NPCPhrase (NEED_LANDERS_2); + if (num_batts < 4) + NPCPhrase (NEED_DYNAMOS_2); + if (num_defense < 2) + NPCPhrase (NEED_POINT); + } + else if (!GET_GAME_STATE (AWARE_OF_SAMATRA)) + NPCPhrase (GO_LEARN_ABOUT_URQUAN); + else + { + NPCPhrase (KNOW_ABOUT_SAMATRA); + if (!GET_GAME_STATE (UTWIG_BOMB)) + NPCPhrase (FIND_WAY_TO_DESTROY_SAMATRA); + else if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + NPCPhrase (MUST_INCREASE_BOMB_STRENGTH); + } + } + } + } +} + +static void +TellMission (RESPONSE_REF R) +{ + RESPONSE_REF pstack[4]; + + if (PLAYER_SAID (R, our_mission)) + { + NPCPhrase (WHICH_MISSION); + stack0 = stack1 = stack2 = stack3 = 0; + } + else if (PLAYER_SAID (R, where_get_minerals)) + { + NPCPhrase (GET_MINERALS); + + stack0 = 1; + } + else if (PLAYER_SAID (R, what_about_aliens)) + { + NPCPhrase (ABOUT_ALIENS); + + stack1 = 1; + } + else if (PLAYER_SAID (R, what_do_now)) + { + AnalyzeCondition (); + + stack2 = 1; + } + else if (PLAYER_SAID (R, what_about_urquan)) + { + NPCPhrase (MUST_DEFEAT); + + stack3 = 1; + } + else if (PLAYER_SAID (R, enough_defeat)) + { + NPCPhrase (OK_ENOUGH_DEFEAT); + + stack3 = 2; + } + + switch (stack0) + { + case 0: + pstack[0] = where_get_minerals; + break; + default: + pstack[0] = 0; + break; + } + switch (stack1) + { + case 0: + pstack[1] = what_about_aliens; + break; + default: + pstack[1] = 0; + break; + } + switch (stack2) + { + case 0: + pstack[2] = what_do_now; + break; + default: + pstack[2] = 0; + break; + } + switch (stack3) + { + case 0: + pstack[3] = what_about_urquan; + break; + case 1: + pstack[3] = how_defeat; + break; + default: + pstack[3] = 0; + break; + } + + if (pstack[0]) + Response (pstack[0], TellMission); + if (pstack[1]) + Response (pstack[1], TellMission); + if (pstack[2]) + Response (pstack[2], TellMission); + if (pstack[3]) + { + if (stack3 == 1) + Response (pstack[3], DefeatUrquan); + else + Response (pstack[3], TellMission); + } + + Response (enough_mission, NeedInfo); +} + +static void +TellStarBase (RESPONSE_REF R) +{ + RESPONSE_REF pstack[4]; + static UNICODE buf0[80]; + + if (PLAYER_SAID (R, starbase_functions)) + { + NPCPhrase (WHICH_FUNCTION); + stack0 = stack1 = stack2 = stack3 = 0; + } + else if (PLAYER_SAID (R, tell_me_about_fuel0)) + { + NPCPhrase (ABOUT_FUEL); + + stack1 = 1; + } + else if (PLAYER_SAID (R, tell_me_about_crew)) + { + NPCPhrase (ABOUT_CREW0); + NPCPhrase (GLOBAL_SHIP_NAME); + NPCPhrase (ABOUT_CREW1); + + stack2 = 2; + } + else if (PLAYER_SAID (R, tell_me_about_modules0)) + { + NPCPhrase (ABOUT_MODULES); + + stack0 = 1; + } + else if (PLAYER_SAID (R, tell_me_about_ships)) + { + NPCPhrase (ABOUT_SHIPS); + + stack2 = 1; + } + else if (PLAYER_SAID (R, tell_me_about_ru)) + { + NPCPhrase (ABOUT_RU); + + stack3 = 1; + } + else if (PLAYER_SAID (R, tell_me_about_minerals)) + { + NPCPhrase (ABOUT_MINERALS); + + stack3 = 2; + } + else if (PLAYER_SAID (R, tell_me_about_life)) + { + NPCPhrase (ABOUT_LIFE); + + stack3 = 3; + } + + switch (stack0) + { + case 0: + construct_response ( + buf0, + tell_me_about_modules0, + (vararg_dcl)GLOBAL_SIS (ShipName), + tell_me_about_modules1, + 0 + ); + pstack[0] = tell_me_about_modules0; + break; + default: + pstack[0] = 0; + break; + } + switch (stack1) + { + case 0: + construct_response ( + shared_phrase_buf, + tell_me_about_fuel0, + (vararg_dcl)GLOBAL_SIS (ShipName), + tell_me_about_fuel1, + 0 + ); + pstack[1] = tell_me_about_fuel0; + break; + default: + pstack[1] = 0; + break; + } + switch (stack2) + { + case 0: + pstack[2] = tell_me_about_ships; + break; + case 1: + pstack[2] = tell_me_about_crew; + break; + default: + pstack[2] = 0; + break; + } + switch (stack3) + { + case 0: + pstack[3] = tell_me_about_ru; + break; + case 1: + pstack[3] = tell_me_about_minerals; + break; + case 2: + pstack[3] = tell_me_about_life; + break; + default: + pstack[3] = 0; + break; + } + + if (pstack[0]) + DoResponsePhrase (pstack[0], TellStarBase, buf0); + if (pstack[1]) + DoResponsePhrase (pstack[1], TellStarBase, shared_phrase_buf); + if (pstack[2]) + Response (pstack[2], TellStarBase); + if (pstack[3]) + Response (pstack[3], TellStarBase); + + Response (enough_starbase, NeedInfo); +} + +static void NormalStarbase (RESPONSE_REF R); + +static void +NeedInfo (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, need_info)) + NPCPhrase (WHAT_KIND_OF_INFO); + else if (PLAYER_SAID (R, enough_starbase)) + NPCPhrase (OK_ENOUGH_STARBASE); + else if (PLAYER_SAID (R, enough_history)) + NPCPhrase (OK_ENOUGH_HISTORY); + else if (PLAYER_SAID (R, enough_mission)) + NPCPhrase (OK_ENOUGH_MISSION); + + Response (starbase_functions, TellStarBase); + Response (history, TellHistory); + Response (our_mission, TellMission); + Response (no_need_info, NormalStarbase); +} + +static BOOLEAN +DiscussDevices (BOOLEAN TalkAbout) +{ + COUNT i, VuxBeastIndex, PhraseIndex; + BOOLEAN Undiscussed; + + if (TalkAbout) + NPCPhrase (DEVICE_HEAD); + PhraseIndex = 2; + + VuxBeastIndex = 0; + Undiscussed = FALSE; + for (i = 0; i < NUM_DEVICES; ++i) + { + RESPONSE_REF pStr; + + pStr = 0; + switch (i) + { + case ROSY_SPHERE_DEVICE: + if (GET_GAME_STATE (ROSY_SPHERE_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_ROSY_SPHERE)) + { + pStr = ABOUT_SPHERE; + SET_GAME_STATE (DISCUSSED_ROSY_SPHERE, TalkAbout); + } + break; + case ARTIFACT_2_DEVICE: + if (GET_GAME_STATE (ARTIFACT_2_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_ARTIFACT_2)) + { + pStr = ABOUT_ARTIFACT_2; + SET_GAME_STATE (DISCUSSED_ARTIFACT_2, TalkAbout); + } + break; + case ARTIFACT_3_DEVICE: + if (GET_GAME_STATE (ARTIFACT_3_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_ARTIFACT_3)) + { + pStr = ABOUT_ARTIFACT_3; + SET_GAME_STATE (DISCUSSED_ARTIFACT_3, TalkAbout); + } + break; + case SUN_EFFICIENCY_DEVICE: + if (GET_GAME_STATE (SUN_DEVICE_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY)) + { + pStr = ABOUT_SUN; + SET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY, TalkAbout); + } + break; + case UTWIG_BOMB_DEVICE: + if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_UTWIG_BOMB)) + { + pStr = ABOUT_BOMB; + SET_GAME_STATE (DISCUSSED_UTWIG_BOMB, TalkAbout); + } + break; + case ULTRON_0_DEVICE: + if (GET_GAME_STATE (ULTRON_CONDITION) == 1 + && !GET_GAME_STATE (DISCUSSED_ULTRON)) + { + pStr = ABOUT_ULTRON_0; + SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); + } + break; + case ULTRON_1_DEVICE: + if (GET_GAME_STATE (ULTRON_CONDITION) == 2 + && !GET_GAME_STATE (DISCUSSED_ULTRON)) + { + pStr = ABOUT_ULTRON_1; + SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); + } + break; + case ULTRON_2_DEVICE: + if (GET_GAME_STATE (ULTRON_CONDITION) == 3 + && !GET_GAME_STATE (DISCUSSED_ULTRON)) + { + pStr = ABOUT_ULTRON_2; + SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); + } + break; + case ULTRON_3_DEVICE: + if (GET_GAME_STATE (ULTRON_CONDITION) == 4 + && !GET_GAME_STATE (DISCUSSED_ULTRON)) + { + pStr = ABOUT_ULTRON_3; + SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); + } + break; + case MAIDENS_DEVICE: + if (GET_GAME_STATE (MAIDENS_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_MAIDENS)) + { + pStr = ABOUT_MAIDENS; + SET_GAME_STATE (DISCUSSED_MAIDENS, TalkAbout); + } + break; + case TALKING_PET_DEVICE: + if (GET_GAME_STATE (TALKING_PET_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_TALKING_PET)) + { + pStr = ABOUT_TALKPET; + SET_GAME_STATE (DISCUSSED_TALKING_PET, TalkAbout); + } + break; + case AQUA_HELIX_DEVICE: + if (GET_GAME_STATE (AQUA_HELIX_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_AQUA_HELIX)) + { + pStr = ABOUT_HELIX; + SET_GAME_STATE (DISCUSSED_AQUA_HELIX, TalkAbout); + } + break; + case CLEAR_SPINDLE_DEVICE: + if (GET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE)) + { + pStr = ABOUT_SPINDLE; + SET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE, TalkAbout); + } + break; + case UMGAH_HYPERWAVE_DEVICE: + if (GET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE)) + { + pStr = ABOUT_UCASTER; + SET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE, TalkAbout); + } + break; +#ifdef NEVER + case DATA_PLATE_1_DEVICE: + if (GET_GAME_STATE (DATA_PLATE_1_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_1)) + { + pStr = (PSTR)ABOUT_DATAPLATE_1; + SET_GAME_STATE (DISCUSSED_DATA_PLATE_1, TalkAbout); + } + break; + case DATA_PLATE_2_DEVICE: + if (GET_GAME_STATE (DATA_PLATE_2_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_2)) + { + pStr = (PSTR)ABOUT_DATAPLATE_2; + SET_GAME_STATE (DISCUSSED_DATA_PLATE_2, TalkAbout); + } + break; + case DATA_PLATE_3_DEVICE: + if (GET_GAME_STATE (DATA_PLATE_3_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_3)) + { + pStr = (PSTR)ABOUT_DATAPLATE_3; + SET_GAME_STATE (DISCUSSED_DATA_PLATE_3, TalkAbout); + } + break; +#endif /* NEVER */ + case TAALO_PROTECTOR_DEVICE: + if (GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR)) + { + pStr = ABOUT_SHIELD; + SET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR, TalkAbout); + } + break; + case EGG_CASING0_DEVICE: + if (GET_GAME_STATE (EGG_CASE0_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_EGG_CASING0)) + { + pStr = ABOUT_EGGCASE_0; + SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); + } + break; + case EGG_CASING1_DEVICE: + if (GET_GAME_STATE (EGG_CASE1_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_EGG_CASING1)) + { + pStr = ABOUT_EGGCASE_0; + SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); + } + break; + case EGG_CASING2_DEVICE: + if (GET_GAME_STATE (EGG_CASE2_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_EGG_CASING2)) + { + pStr = ABOUT_EGGCASE_0; + SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); + SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); + } + break; + case SYREEN_SHUTTLE_DEVICE: + if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE)) + { + pStr = ABOUT_SHUTTLE; + SET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE, TalkAbout); + } + break; + case VUX_BEAST_DEVICE: + if (GET_GAME_STATE (VUX_BEAST_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_VUX_BEAST)) + { + pStr = ABOUT_VUXBEAST0; + SET_GAME_STATE (DISCUSSED_VUX_BEAST, TalkAbout); + } + break; + case DESTRUCT_CODE_DEVICE: + if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_DESTRUCT_CODE)) + { + pStr = ABOUT_DESTRUCT; + SET_GAME_STATE (DISCUSSED_DESTRUCT_CODE, TalkAbout); + } + break; + case PORTAL_SPAWNER_DEVICE: + if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER)) + { + pStr = ABOUT_PORTAL; + SET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER, TalkAbout); + } + break; + case URQUAN_WARP_DEVICE: + if (GET_GAME_STATE (PORTAL_KEY_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_URQUAN_WARP)) + { + pStr = ABOUT_WARPPOD; + SET_GAME_STATE (DISCUSSED_URQUAN_WARP, TalkAbout); + } + break; + case BURVIX_HYPERWAVE_DEVICE: + if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP) + && !GET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE)) + { + pStr = ABOUT_BCASTER; + SET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE, TalkAbout); + } + break; + } + + if (pStr) + { + if (TalkAbout) + { + if (PhraseIndex > 2) + NPCPhrase (BETWEEN_DEVICES); + NPCPhrase (pStr); + if (pStr == ABOUT_VUXBEAST0) + { + VuxBeastIndex = ++PhraseIndex; + NPCPhrase (ABOUT_VUXBEAST1); + } + } + PhraseIndex += 2; + } + } + + if (TalkAbout) + { + NPCPhrase (DEVICE_TAIL); + + if (VuxBeastIndex) + { + for (i = 1; i < VuxBeastIndex; ++i) + AlienTalkSegue (i); + i = CommData.AlienTalkDesc.NumFrames; + CommData.AlienTalkDesc.NumFrames = 0; + AlienTalkSegue (VuxBeastIndex); + CommData.AlienTalkDesc.NumFrames = i; + AlienTalkSegue ((COUNT)~0); + } + } + + return (PhraseIndex > 2); +} + +static BOOLEAN +CheckTiming (COUNT month_index, COUNT day_index) +{ + COUNT mi, year_index; + BYTE days_in_month[12] = + { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + }; + + mi = GET_GAME_STATE (STARBASE_MONTH); + year_index = START_YEAR; + + day_index += GET_GAME_STATE (STARBASE_DAY); + while (day_index > days_in_month[mi - 1]) + { + day_index -= days_in_month[mi - 1]; + if (++mi > 12) + { + mi = 1; + ++year_index; + } + } + + month_index += mi; + year_index += (month_index - 1) / 12; + month_index = ((month_index - 1) % 12) + 1; + + return (year_index < GLOBAL (GameClock.year_index) + || (year_index == GLOBAL (GameClock.year_index) + && (month_index < GLOBAL (GameClock.month_index) + || (month_index == GLOBAL (GameClock.month_index) + && day_index < GLOBAL (GameClock.day_index))))); +} + +static void +CheckBulletins (BOOLEAN Repeat) +{ + RESPONSE_REF pIntro; + BYTE b0, b1, b2, b3; + DWORD BulletinMask; + + if (Repeat) + BulletinMask = CurBulletinMask ^ 0xFFFFFFFFL; + else + { + b0 = GET_GAME_STATE (STARBASE_BULLETS0); + b1 = GET_GAME_STATE (STARBASE_BULLETS1); + b2 = GET_GAME_STATE (STARBASE_BULLETS2); + b3 = GET_GAME_STATE (STARBASE_BULLETS3); + BulletinMask = MAKE_DWORD (MAKE_WORD (b0, b1), MAKE_WORD (b2, b3)); + } + + pIntro = 0; + for (b0 = 0; b0 < 32; ++b0) + { + if (!(BulletinMask & (1L << b0))) + { + RESPONSE_REF pStr; + + pStr = 0; + switch (b0) + { + case 0: + if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_1; + } + break; + case 1: + if (ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_2; + } + break; + case 2: + if (ActivateStarShip (SUPOX_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_3; + } + break; + case 3: + if (ActivateStarShip (UTWIG_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_4; + } + break; + case 4: + if (ActivateStarShip (ORZ_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_5; + } + break; + case 5: + if (GET_GAME_STATE (ARILOU_MANNER) == 2) + BulletinMask |= 1L << b0; + else if (GET_GAME_STATE (PORTAL_SPAWNER) + && (Repeat || ActivateStarShip ( + ARILOU_SHIP, FEASIBILITY_STUDY + ))) + { +#define NUM_GIFT_ARILOUS 3 + pStr = STARBASE_BULLETIN_6; + if (!Repeat) + ActivateStarShip (ARILOU_SHIP, NUM_GIFT_ARILOUS); + } + break; + case 6: + if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 1) + { + pStr = STARBASE_BULLETIN_7; + } + break; + case 7: + if (GET_GAME_STATE (MET_MELNORME)) + BulletinMask |= 1L << b0; + else if (CheckTiming (3, 0)) + { + pStr = STARBASE_BULLETIN_8; + } + break; + case 8: + if (GET_GAME_STATE (MET_MELNORME)) + BulletinMask |= 1L << b0; + else if (CheckTiming (6, 0)) + { + pStr = STARBASE_BULLETIN_9; + } + break; + case 9: + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI)) + BulletinMask |= 1L << b0; + else if (CheckTiming (0, 7)) + { + pStr = STARBASE_BULLETIN_10; + } + break; + case 10: + if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) + { + pStr = STARBASE_BULLETIN_11; + } + break; + case 11: + if (GET_GAME_STATE (ZOQFOT_HOME_VISITS) + || GET_GAME_STATE (ZOQFOT_GRPOFFS0) + || GET_GAME_STATE (ZOQFOT_GRPOFFS1) + || GET_GAME_STATE (ZOQFOT_GRPOFFS2) + || GET_GAME_STATE (ZOQFOT_GRPOFFS3)) + BulletinMask |= 1L << b0; + else if (CheckTiming (0, 42)) + { + pStr = STARBASE_BULLETIN_12; + } + break; + case 12: + if (ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_13; + } + break; + case 13: + if (ActivateStarShip (SHOFIXTI_SHIP, CHECK_ALLIANCE) + & GOOD_GUY) + { + pStr = STARBASE_BULLETIN_14; + } + break; + case 14: + if (GET_GAME_STATE (PKUNK_MISSION)) + { + pStr = STARBASE_BULLETIN_15; + } + break; + case 15: + if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) + BulletinMask |= 1L << b0; + else if (CheckTiming (7, 0)) + { + pStr = STARBASE_BULLETIN_16; + } + break; + case 16: + break; + case 17: + if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) + { + pStr = STARBASE_BULLETIN_18; + } + break; + case 18: + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + pStr = STARBASE_BULLETIN_19; + } + break; + case 19: + break; + case 20: + break; + case 21: + if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 2) + { + pStr = STARBASE_BULLETIN_22; + } + break; + case 22: + break; + case 23: + break; + case 24: + break; + case 25: + break; + case 26: + { + COUNT crew_sold; + + crew_sold = MAKE_WORD ( + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) + ); + if (crew_sold > 100) + BulletinMask |= 1L << b0; + else if (crew_sold) + { + pStr = STARBASE_BULLETIN_27; + } + break; + } + case 27: + { + COUNT crew_sold; + + crew_sold = MAKE_WORD ( + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) + ); + if (crew_sold > 250) + BulletinMask |= 1L << b0; + else if (crew_sold > 100) + { + pStr = STARBASE_BULLETIN_28; + } + break; + } + case 28: + { + COUNT crew_bought; + + crew_bought = MAKE_WORD ( + GET_GAME_STATE (CREW_PURCHASED0), + GET_GAME_STATE (CREW_PURCHASED1) + ); + if (crew_bought >= CREW_EXPENSE_THRESHOLD) + { + pStr = STARBASE_BULLETIN_29; + } + break; + } + case 29: + if (MAKE_WORD ( + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), + GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) + ) > 250) + { + pStr = STARBASE_BULLETIN_30; + } + break; + case 30: + break; + case 31: + break; + } + + if (pStr) + { + if (pIntro) + NPCPhrase (BETWEEN_BULLETINS); + else if (Repeat) + pIntro = BEFORE_WE_GO_ON_1; + else + { + switch ((BYTE)Random () % 7) + { + case 0: + pIntro = BEFORE_WE_GO_ON_1; + break; + case 1: + pIntro = BEFORE_WE_GO_ON_2; + break; + case 2: + pIntro = BEFORE_WE_GO_ON_3; + break; + case 3: + pIntro = BEFORE_WE_GO_ON_4; + break; + case 4: + pIntro = BEFORE_WE_GO_ON_5; + break; + case 5: + pIntro = BEFORE_WE_GO_ON_6; + break; + default: + pIntro = BEFORE_WE_GO_ON_7; + break; + } + + NPCPhrase (pIntro); + } + + NPCPhrase (pStr); + CurBulletinMask |= 1L << b0; + } + } + } + + if (pIntro == 0 && GET_GAME_STATE (STARBASE_VISITED)) + NPCPhrase (RETURN_HELLO); + else if (!Repeat) + { + b0 = LOBYTE (LOWORD (BulletinMask)); + b1 = HIBYTE (LOWORD (BulletinMask)); + b2 = LOBYTE (HIWORD (BulletinMask)); + b3 = HIBYTE (HIWORD (BulletinMask)); + SET_GAME_STATE (STARBASE_BULLETS0, b0); + SET_GAME_STATE (STARBASE_BULLETS1, b1); + SET_GAME_STATE (STARBASE_BULLETS2, b2); + SET_GAME_STATE (STARBASE_BULLETS3, b3); + } +} + +static void +NormalStarbase (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, no_need_info)) + NPCPhrase (OK_NO_NEED_INFO); + else if (PLAYER_SAID (R, new_devices)) + DiscussDevices (TRUE); + else if (PLAYER_SAID (R, repeat_bulletins)) + CheckBulletins (TRUE); + else if (R == 0) + { + if (GET_GAME_STATE (MOONBASE_ON_SHIP)) + { + NPCPhrase (STARBASE_IS_READY_A); + NPCPhrase (GLOBAL_SHIP_NAME); + NPCPhrase (STARBASE_IS_READY_B); + NPCPhrase (GLOBAL_SHIP_NAME); + NPCPhrase (STARBASE_IS_READY_C); + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 0, 2500); + ClearSemaphore (&GraphicsSem); + SET_GAME_STATE (STARBASE_MONTH, + GLOBAL (GameClock.month_index)); + SET_GAME_STATE (STARBASE_DAY, + GLOBAL (GameClock.day_index)); + } + else if (GET_GAME_STATE (STARBASE_VISITED)) + { + CheckBulletins (FALSE); + } + else + { + RESPONSE_REF pStr0, pStr1; + + switch ((BYTE)Random () & 7) + { + case 0: + pStr0 = NORMAL_HELLO_A0; + pStr1 = NORMAL_HELLO_A1; + break; + case 1: + pStr0 = NORMAL_HELLO_B0; + pStr1 = NORMAL_HELLO_B1; + break; + case 2: + pStr0 = NORMAL_HELLO_C0; + pStr1 = NORMAL_HELLO_C1; + break; + case 3: + pStr0 = NORMAL_HELLO_D0; + pStr1 = NORMAL_HELLO_D1; + break; + case 4: + pStr0 = NORMAL_HELLO_E0; + pStr1 = NORMAL_HELLO_E1; + break; + case 5: + pStr0 = NORMAL_HELLO_F0; + pStr1 = NORMAL_HELLO_F1; + break; + case 6: + pStr0 = NORMAL_HELLO_G0; + pStr1 = NORMAL_HELLO_G1; + break; + case 7: + pStr0 = NORMAL_HELLO_H0; + pStr1 = NORMAL_HELLO_H1; + break; + } + NPCPhrase (pStr0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (pStr1); + CheckBulletins (FALSE); + } + + SET_GAME_STATE (STARBASE_VISITED, 1); + } + + if (GLOBAL_SIS (TotalElementMass)) + { + static void SellMinerals (RESPONSE_REF R); + + Response (have_minerals, SellMinerals); + } + if (DiscussDevices (FALSE)) + Response (new_devices, NormalStarbase); + if (CurBulletinMask) + Response (repeat_bulletins, NormalStarbase); + Response (need_info, NeedInfo); + Response (goodbye_commander, ByeBye); +} + +static void +SellMinerals (RESPONSE_REF R) +{ + COUNT i, total; + BOOLEAN Sleepy; + RESPONSE_REF pStr1, pStr2; + + total = 0; + Sleepy = TRUE; + for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) + { + COUNT amount; + DWORD TimeIn; + + if (i == 0) + { + DrawCargoStrings ((BYTE)~0, (BYTE)~0); + TimeIn = SleepTask (GetTimeCounter () + (ONE_SECOND / 2)); + DrawCargoStrings ((BYTE)0, (BYTE)0); + } + else if (Sleepy) + { + DrawCargoStrings ((BYTE)(i - 1), (BYTE)i); + TimeIn = GetTimeCounter (); + } + + if (amount = GLOBAL_SIS (ElementAmounts[i])) + { + total += amount * GLOBAL (ElementWorth[i]); + do + { + if (!Sleepy || AnyButtonPress (TRUE)) + { + Sleepy = FALSE; + GLOBAL_SIS (ElementAmounts[i]) = 0; + GLOBAL_SIS (TotalElementMass) -= amount; + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, 0, amount * GLOBAL (ElementWorth[i])); + ClearSemaphore (&GraphicsSem); + break; + } + + --GLOBAL_SIS (ElementAmounts[i]); + --GLOBAL_SIS (TotalElementMass); + TimeIn = TaskSwitch (); + DrawCargoStrings ((BYTE)i, (BYTE)i); + SetSemaphore (&GraphicsSem); + ShowRemainingCapacity (); + DeltaSISGauges (0, 0, GLOBAL (ElementWorth[i])); + ClearSemaphore (&GraphicsSem); + } while (--amount); + } + if (Sleepy) + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 4)); + } + SleepTask (GetTimeCounter () + (ONE_SECOND / 2)); + + SetSemaphore (&GraphicsSem); + ClearSISRect (DRAW_SIS_DISPLAY); + ClearSemaphore (&GraphicsSem); +// DrawStorageBays (FALSE); + + if (total < 1000) + { + total = GET_GAME_STATE (LIGHT_MINERAL_LOAD); + switch (total++) + { + case 0: + pStr1 = LIGHT_LOAD_A0; + pStr2 = LIGHT_LOAD_A1; + break; + case 1: + pStr1 = LIGHT_LOAD_B0; + pStr2 = LIGHT_LOAD_B1; + break; + case 2: + pStr1 = LIGHT_LOAD_C0; + pStr2 = LIGHT_LOAD_C1; + break; + case 3: + pStr1 = LIGHT_LOAD_D0; + pStr2 = LIGHT_LOAD_D1; + break; + case 4: + pStr1 = LIGHT_LOAD_E0; + pStr2 = LIGHT_LOAD_E1; + break; + case 5: + pStr1 = LIGHT_LOAD_F0; + pStr2 = LIGHT_LOAD_F1; + break; + case 6: + --total; + pStr1 = LIGHT_LOAD_G0; + pStr2 = LIGHT_LOAD_G1; + break; + } + SET_GAME_STATE (LIGHT_MINERAL_LOAD, total); + } + else if (total < 2500) + { + total = GET_GAME_STATE (MEDIUM_MINERAL_LOAD); + switch (total++) + { + case 0: + pStr1 = MEDIUM_LOAD_A0; + pStr2 = MEDIUM_LOAD_A1; + break; + case 1: + pStr1 = MEDIUM_LOAD_B0; + pStr2 = MEDIUM_LOAD_B1; + break; + case 2: + pStr1 = MEDIUM_LOAD_C0; + pStr2 = MEDIUM_LOAD_C1; + break; + case 3: + pStr1 = MEDIUM_LOAD_D0; + pStr2 = MEDIUM_LOAD_D1; + break; + case 4: + pStr1 = MEDIUM_LOAD_E0; + pStr2 = MEDIUM_LOAD_E1; + break; + case 5: + pStr1 = MEDIUM_LOAD_F0; + pStr2 = MEDIUM_LOAD_F1; + break; + case 6: + --total; + pStr1 = MEDIUM_LOAD_G0; + pStr2 = MEDIUM_LOAD_G1; + break; + } + SET_GAME_STATE (MEDIUM_MINERAL_LOAD, total); + } + else + { + total = GET_GAME_STATE (HEAVY_MINERAL_LOAD); + switch (total++) + { + case 0: + pStr1 = HEAVY_LOAD_A0; + pStr2 = HEAVY_LOAD_A1; + break; + case 1: + pStr1 = HEAVY_LOAD_B0; + pStr2 = HEAVY_LOAD_B1; + break; + case 2: + pStr1 = HEAVY_LOAD_C0; + pStr2 = HEAVY_LOAD_C1; + break; + case 3: + pStr1 = HEAVY_LOAD_D0; + pStr2 = HEAVY_LOAD_D1; + break; + case 4: + pStr1 = HEAVY_LOAD_E0; + pStr2 = HEAVY_LOAD_E1; + break; + case 5: + pStr1 = HEAVY_LOAD_F0; + pStr2 = HEAVY_LOAD_F1; + break; + case 6: + --total; + pStr1 = HEAVY_LOAD_G0; + pStr2 = HEAVY_LOAD_G1; + break; + } + SET_GAME_STATE (HEAVY_MINERAL_LOAD, total); + } + + NPCPhrase (pStr1); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (pStr2); + + NormalStarbase (R); +} + +static void +Intro (void) +{ + NormalStarbase (NULL_PTR); +} + +static COUNT +uninit_starbase (void) +{ + SET_GAME_STATE (MOONBASE_ON_SHIP, 0); + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + SET_GAME_STATE (CHMMR_BOMB_STATE, 3); + } + + return (0); +} + +LOCDATAPTR +init_starbase_comm () +{ + LOCDATAPTR retval; + + commander_desc.init_encounter_func = Intro; + commander_desc.uninit_encounter_func = uninit_starbase; + + commander_desc.AlienTextWidth = 143; + commander_desc.AlienTextTemplate.baseline.x = 164; + commander_desc.AlienTextTemplate.baseline.y = 20; + commander_desc.AlienTextTemplate.align = ALIGN_CENTER; + + CurBulletinMask = 0; + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &commander_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/starbas/strings.h b/sc2/src/sc2code/comm/starbas/strings.h new file mode 100644 index 000000000..0e0f67102 --- /dev/null +++ b/sc2/src/sc2code/comm/starbas/strings.h @@ -0,0 +1,322 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + BEFORE_WE_GO_ON_1, + BEFORE_WE_GO_ON_2, + BEFORE_WE_GO_ON_3, + BEFORE_WE_GO_ON_4, + BEFORE_WE_GO_ON_5, + BEFORE_WE_GO_ON_6, + BEFORE_WE_GO_ON_7, + NORMAL_HELLO_A0, + NORMAL_HELLO_A1, + NORMAL_HELLO_B0, + NORMAL_HELLO_B1, + NORMAL_HELLO_C0, + NORMAL_HELLO_C1, + NORMAL_HELLO_D0, + NORMAL_HELLO_D1, + NORMAL_HELLO_E0, + NORMAL_HELLO_E1, + NORMAL_HELLO_F0, + NORMAL_HELLO_F1, + NORMAL_HELLO_G0, + NORMAL_HELLO_G1, + NORMAL_HELLO_H0, + NORMAL_HELLO_H1, + RETURN_HELLO, + NORMAL_HELLO_TAIL, + NORMAL_GOODBYE_A0, + NORMAL_GOODBYE_A1, + NORMAL_GOODBYE_B0, + NORMAL_GOODBYE_B1, + NORMAL_GOODBYE_C0, + NORMAL_GOODBYE_C1, + NORMAL_GOODBYE_D0, + NORMAL_GOODBYE_D1, + NORMAL_GOODBYE_E0, + NORMAL_GOODBYE_E1, + NORMAL_GOODBYE_F0, + NORMAL_GOODBYE_F1, + NORMAL_GOODBYE_G0, + NORMAL_GOODBYE_G1, + NORMAL_GOODBYE_H0, + NORMAL_GOODBYE_H1, + LIGHT_LOAD_A0, + LIGHT_LOAD_A1, + LIGHT_LOAD_B0, + LIGHT_LOAD_B1, + LIGHT_LOAD_C0, + LIGHT_LOAD_C1, + LIGHT_LOAD_D0, + LIGHT_LOAD_D1, + LIGHT_LOAD_E0, + LIGHT_LOAD_E1, + LIGHT_LOAD_F0, + LIGHT_LOAD_F1, + LIGHT_LOAD_G0, + LIGHT_LOAD_G1, + MEDIUM_LOAD_A0, + MEDIUM_LOAD_A1, + MEDIUM_LOAD_B0, + MEDIUM_LOAD_B1, + MEDIUM_LOAD_C0, + MEDIUM_LOAD_C1, + MEDIUM_LOAD_D0, + MEDIUM_LOAD_D1, + MEDIUM_LOAD_E0, + MEDIUM_LOAD_E1, + MEDIUM_LOAD_F0, + MEDIUM_LOAD_F1, + MEDIUM_LOAD_G0, + MEDIUM_LOAD_G1, + HEAVY_LOAD_A0, + HEAVY_LOAD_A1, + HEAVY_LOAD_B0, + HEAVY_LOAD_B1, + HEAVY_LOAD_C0, + HEAVY_LOAD_C1, + HEAVY_LOAD_D0, + HEAVY_LOAD_D1, + HEAVY_LOAD_E0, + HEAVY_LOAD_E1, + HEAVY_LOAD_F0, + HEAVY_LOAD_F1, + HEAVY_LOAD_G0 , + HEAVY_LOAD_G1, + STARBASE_IS_READY_A, + STARBASE_IS_READY_B, + STARBASE_IS_READY_C, + WHAT_KIND_OF_INFO, + WHICH_FUNCTION, + WHICH_HISTORY, + WHICH_MISSION, + OK_NO_NEED_INFO, + ABOUT_FUEL, + ABOUT_MODULES, + ABOUT_CREW0, + ABOUT_CREW1, + ABOUT_SHIPS, + ABOUT_RU, + ABOUT_MINERALS, + ABOUT_LIFE, + OK_ENOUGH_STARBASE, + OK_ENOUGH_MISSION, + GET_MINERALS, + ABOUT_ALIENS, + MUST_DEFEAT, + DEFEAT_LIKE_SO, + FIND_URQUAN, + FIGHT_URQUAN, + ALLY_LIKE_SO, + STRONG_LIKE_SO, + OK_ENOUGH_DEFEAT, + WHICH_ALIEN, + WHICH_WAR, + WHICH_ANCIENT, + OK_ENOUGH_HISTORY, + WHICH_ALLIANCE, + WHICH_HIERARCHY, + ABOUT_OTHER, + OK_ENOUGH_ALIENS, + ABOUT_SHOFIXTI, + ABOUT_YEHAT, + ABOUT_ARILOU, + ABOUT_CHENJESU, + ABOUT_MMRNMHRM, + ABOUT_SYREEN, + OK_ENOUGH_ALLIANCE, + ABOUT_URQUAN, + ABOUT_MYCON, + ABOUT_SPATHI, + ABOUT_UMGAH, + ABOUT_ANDROSYNTH, + ABOUT_VUX, + ABOUT_ILWRATH, + OK_ENOUGH_HIERARCHY, + ABOUT_PRECURSORS, + ABOUT_OLD_RACES, + ABOUT_ALIENS_ON_EARTH, + OK_ENOUGH_ANCIENT, + URQUAN_STARTED_WAR, + WAR_WAS_LIKE_SO, + LOST_WAR_BECAUSE, + AFTER_WAR, + OK_ENOUGH_WAR, + STARBASE_BULLETIN_TAIL, + BETWEEN_BULLETINS, + STARBASE_BULLETIN_1, + STARBASE_BULLETIN_2, + STARBASE_BULLETIN_3, + STARBASE_BULLETIN_4, + STARBASE_BULLETIN_5, + STARBASE_BULLETIN_6, + STARBASE_BULLETIN_7, + STARBASE_BULLETIN_8, + STARBASE_BULLETIN_9, + STARBASE_BULLETIN_10, + STARBASE_BULLETIN_11, + STARBASE_BULLETIN_12, + STARBASE_BULLETIN_13, + STARBASE_BULLETIN_14, + STARBASE_BULLETIN_15, + STARBASE_BULLETIN_16, + STARBASE_BULLETIN_18, + STARBASE_BULLETIN_19, + STARBASE_BULLETIN_22, + STARBASE_BULLETIN_27, + STARBASE_BULLETIN_28, + STARBASE_BULLETIN_29, + STARBASE_BULLETIN_30, + DEVICE_HEAD, + BETWEEN_DEVICES, + DEVICE_TAIL, + ABOUT_PORTAL, + ABOUT_TALKPET, + ABOUT_BOMB, + ABOUT_SUN, + ABOUT_MAIDENS, + ABOUT_SPHERE, + ABOUT_HELIX, + ABOUT_SPINDLE, + ABOUT_ULTRON_0, + ABOUT_ULTRON_1, + ABOUT_ULTRON_2, + ABOUT_ULTRON_3, + ABOUT_UCASTER, + ABOUT_BCASTER, + ABOUT_SHIELD, + ABOUT_EGGCASE_0, + ABOUT_SHUTTLE, + ABOUT_VUXBEAST0, + ABOUT_VUXBEAST1, + ABOUT_DESTRUCT, + ABOUT_WARPPOD, + ABOUT_ARTIFACT_2, + ABOUT_ARTIFACT_3, + LETS_SEE, + GO_GET_MINERALS, + IMPROVE_FLAGSHIP_WITH_RU, + GOT_OK_FLAGSHIP, + GO_ALLY_WITH_ALIENS, + MADE_SOME_ALLIES, + GET_SHIPS_BY_MINING_OR_ALLIANCE, + GOT_OK_FLEET, + BUY_COMBAT_SHIPS, + GO_LEARN_ABOUT_URQUAN, + MAKE_FLAGSHIP_AWESOME, + KNOW_ABOUT_SAMATRA, + GOT_AWESOME_FLAGSHIP, + GOT_BOMB, + FIND_WAY_TO_DESTROY_SAMATRA, + MUST_INCREASE_BOMB_STRENGTH, + MUST_ACQUIRE_AWESOME_FLEET, + MUST_ELIMINATE_URQUAN_GUARDS, + CHMMR_IMPROVED_BOMB, + GOT_AWESOME_FLEET, + GO_DESTROY_SAMATRA, + GOOD_LUCK_AGAIN, + IMPROVE_1, + IMPROVE_2, + NEED_THRUSTERS_1, + NEED_THRUSTERS_2, + NEED_TURN_1, + NEED_TURN_2, + NEED_GUNS_1, + NEED_GUNS_2, + NEED_CREW_1, + NEED_CREW_2, + NEED_FUEL_1, + NEED_FUEL_2, + NEED_STORAGE_1, + NEED_LANDERS_2, + NEED_LANDERS_1, + NEED_DYNAMOS_1, + NEED_DYNAMOS_2, + NEED_POINT, + + have_minerals, + goodbye_commander, + repeat_bulletins, + need_info, + starbase_functions, + history, + our_mission, + no_need_info, + enough_starbase, + enough_mission, + tell_me_about_fuel0, + tell_me_about_fuel1, + tell_me_about_modules0, + tell_me_about_modules1, + tell_me_about_crew, + tell_me_about_ships, + tell_me_about_ru, + tell_me_about_minerals, + tell_me_about_life, + where_get_minerals, + what_about_aliens, + what_about_urquan, + how_defeat, + how_find_urquan, + how_fight_urquan, + how_ally, + enough_defeat, + alien_races, + the_war, + ancient_history, + enough_history, + what_about_alliance, + what_about_hierarchy, + what_about_other, + enough_aliens, + shofixti, + yehat, + arilou, + chenjesu, + mmrnmhrm, + syreen, + enough_alliance, + urquan, + mycon, + spathi, + umgah, + androsynth, + vux, + ilwrath, + enough_hierarchy, + precursors, + old_races, + aliens_on_earth, + enough_ancient, + what_started_war, + what_was_war_like, + why_lose_war, + what_after_war, + enough_war, + new_devices, + how_get_strong, + what_do_now, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/supox/ifontres.h b/sc2/src/sc2code/comm/supox/ifontres.h new file mode 100644 index 000000000..f9e7a49d9 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/ifontres.h @@ -0,0 +1,3 @@ +#define SUPOX_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/supox/igfxres.h b/sc2/src/sc2code/comm/supox/igfxres.h new file mode 100644 index 000000000..4cf0d309c --- /dev/null +++ b/sc2/src/sc2code/comm/supox/igfxres.h @@ -0,0 +1,3 @@ +#define SUPOX_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/supox/imusicre.h b/sc2/src/sc2code/comm/supox/imusicre.h new file mode 100644 index 000000000..5e4e1d40f --- /dev/null +++ b/sc2/src/sc2code/comm/supox/imusicre.h @@ -0,0 +1,3 @@ +#define SUPOX_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/supox/istrtab.h b/sc2/src/sc2code/comm/supox/istrtab.h new file mode 100644 index 000000000..0ba741d42 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/istrtab.h @@ -0,0 +1,3 @@ +#define SUPOX_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/supox/resinst.h b/sc2/src/sc2code/comm/supox/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/supox/respkg.h b/sc2/src/sc2code/comm/supox/respkg.h new file mode 100644 index 000000000..994623220 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/respkg.h @@ -0,0 +1,5 @@ +enum +{ + SUPOX_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/supox/restypes.h b/sc2/src/sc2code/comm/supox/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/supox/strings.h b/sc2/src/sc2code/comm/supox/strings.h new file mode 100644 index 000000000..403526883 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/strings.h @@ -0,0 +1,123 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + NEUTRAL_SPACE_HELLO_1, + NEUTRAL_SPACE_HELLO_2, + NEUTRAL_HOMEWORLD_HELLO_1, + NEUTRAL_HOMEWORLD_HELLO_2, + HOSTILE_SPACE_HELLO_1, + HOSTILE_SPACE_HELLO_2, + ALLIED_HOMEWORLD_HELLO_1, + ALLIED_HOMEWORLD_HELLO_2, + ALLIED_HOMEWORLD_HELLO_3, + ALLIED_HOMEWORLD_HELLO_4, + i_am0, + i_am1, + WE_ARE_SUPOX, + my_ship0, + my_ship1, + OUR_SHIP, + from_alliance0, + from_alliance1, + FROM_SUPOX, + are_you_copying, + YEAH_SORRY, + why_copy, + SYMBIOTS, + tell_us_of_your_species, + OUR_SPECIES, + plants_arent_intelligent, + PROVES_WERE_SPECIAL, + anyone_around_here, + UTWIG_NEARBY, + what_relation_to_utwig, + UTWIG_ALLIES, + whats_wrong_with_utwig, + BROKE_ULTRON, + whats_ultron, + TAKE_ULTRON, + what_do_i_do_now, + FIX_IT, + thanks_now_we_eat_you, + HIDEOUS_MONSTERS, + got_fixed_ultron, + GOOD_GIVE_TO_UTWIG, + look_i_repaired_lots, + ALMOST_THERE, + look_i_slightly_repaired, + GREAT_DO_MORE, + where_get_repairs, + ANCIENT_RHYME, + bye_neutral, + GOODBYE_NEUTRAL, + ABOUT_BATTLE, + HELLO_BEFORE_KOHRAH_SPACE_1, + HELLO_BEFORE_KOHRAH_SPACE_2, + HELLO_DURING_KOHRAH_SPACE_1, + HELLO_DURING_KOHRAH_SPACE_2, + HELLO_AFTER_KOHRAH_SPACE_1, + HELLO_AFTER_KOHRAH_SPACE_2, + whats_up_after_space, + GENERAL_INFO_AFTER_SPACE_1, + GENERAL_INFO_AFTER_SPACE_2, + what_now_after_space, + DO_THIS_AFTER_SPACE, + bye_after_space, + GOODBYE_AFTER_SPACE, + whats_up_before_space, + GENERAL_INFO_BEFORE_SPACE_1, + GENERAL_INFO_BEFORE_SPACE_2, + what_now_before_space, + DO_THIS_BEFORE_SPACE, + bye_before_space, + GOODBYE_BEFORE_SPACE, + how_went_war, + how_goes_war, + BATTLE_HAPPENS_1, + BATTLE_HAPPENS_2, + FLEET_ON_WAY, + learn_new_info, + NO_NEW_INFO, + SAMATRA, + what_now_homeworld, + HOPE_KILL_EACH_OTHER, + UP_TO_YOU, + can_you_help, + HOW_HELP, + DONT_NEED, + HAVE_4_SHIPS, + give_info, + GOOD_HINTS, + how_is_ultron, + ULTRON_IS_GREAT, + bye_allied_homeworld, + GOODBYE_ALLIED_HOMEWORLD, + name_1, + name_2, + name_3, + name_40, + name_41, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/supox/supox.res b/sc2/src/sc2code/comm/supox/supox.res new file mode 100644 index 000000000..bb74f611a --- /dev/null +++ b/sc2/src/sc2code/comm/supox/supox.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/supox + +PACKAGE SUPOX_PACKAGE supox.con + GFXRES SUPOX_PMAP_ANIM supox.ani + FONTRES SUPOX_FONT supox.fon + MUSICRES SUPOX_MUSIC supox.mod + STRTAB SUPOX_CONVERSATION_PHRASES supox.txt + diff --git a/sc2/src/sc2code/comm/supox/supoxc.c b/sc2/src/sc2code/comm/supox/supoxc.c new file mode 100644 index 000000000..cf27e0903 --- /dev/null +++ b/sc2/src/sc2code/comm/supox/supoxc.c @@ -0,0 +1,688 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/supox/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/supox/strings.h" + +static LOCDATA supox_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SUPOX_PMAP_ANIM, /* AlienFrame */ + (FONT)SUPOX_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + SUPOX_MUSIC, /* AlienSong */ + SUPOX_CONVERSATION_PHRASES, /* PlayerPhrases */ + 4, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 9, /* StartIndex */ + 10, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 19, /* StartIndex */ + 10, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 29, /* StartIndex */ + 13, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye_neutral)) + NPCPhrase (GOODBYE_NEUTRAL); + else if (PLAYER_SAID (R, what_do_i_do_now)) + NPCPhrase (FIX_IT); + else if (PLAYER_SAID (R, thanks_now_we_eat_you)) + { + NPCPhrase (HIDEOUS_MONSTERS); + + SET_GAME_STATE (SUPOX_HOSTILE, 1); + SET_GAME_STATE (SUPOX_HOME_VISITS, 0); + SET_GAME_STATE (SUPOX_VISITS, 0); + } + else if (PLAYER_SAID (R, bye_after_space)) + NPCPhrase (GOODBYE_AFTER_SPACE); + else if (PLAYER_SAID (R, bye_before_space)) + NPCPhrase (GOODBYE_BEFORE_SPACE); + else if (PLAYER_SAID (R, bye_allied_homeworld)) + NPCPhrase (GOODBYE_ALLIED_HOMEWORLD); + else if (PLAYER_SAID (R, can_you_help)) + { + NPCPhrase (HOW_HELP); + if (ActivateStarShip (SUPOX_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (DONT_NEED); + else + { + NPCPhrase (HAVE_4_SHIPS); + + AlienTalkSegue ((COUNT)~0); + ActivateStarShip (SUPOX_SHIP, 4); + } + } +} + +static void AlliedHome (RESPONSE_REF R); + +static void +AlliedHome (RESPONSE_REF R) +{ + BYTE NumVisits, News; + + News = GET_GAME_STATE (SUPOX_WAR_NEWS); + NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (PLAYER_SAID (R, how_went_war)) + { + NPCPhrase (ABOUT_BATTLE); + + News |= (1 << 0); + } + else if (PLAYER_SAID (R, how_goes_war)) + { + if (NumVisits == 1) + { + NPCPhrase (FLEET_ON_WAY); + + SET_GAME_STATE (SUPOX_WAR_NEWS, 1); + } + else switch (GET_GAME_STATE (SUPOX_WAR_NEWS)) + { + case 0: + NPCPhrase (BATTLE_HAPPENS_1); + News = 1; + break; + case 1: + NPCPhrase (BATTLE_HAPPENS_2); + News = 2; + break; + } + + DISABLE_PHRASE (how_goes_war); + } + else if (PLAYER_SAID (R, learn_new_info)) + { + if (NumVisits < 5) + NPCPhrase (NO_NEW_INFO); + else + { + NPCPhrase (SAMATRA); + + News |= (1 << 1); + } + + DISABLE_PHRASE (learn_new_info); + } + else if (PLAYER_SAID (R, what_now_homeworld)) + { + if (NumVisits < 5) + NPCPhrase (UP_TO_YOU); + else + NPCPhrase (HOPE_KILL_EACH_OTHER); + + DISABLE_PHRASE (what_now_homeworld); + } + else if (PLAYER_SAID (R, how_is_ultron)) + { + NPCPhrase (ULTRON_IS_GREAT); + + DISABLE_PHRASE (how_is_ultron); + } + SET_GAME_STATE (SUPOX_WAR_NEWS, News); + + if (NumVisits >= 5) + { + if (!(News & (1 << 0))) + Response (how_went_war, AlliedHome); + } + else if (PHRASE_ENABLED (how_goes_war) + && ((NumVisits == 1 && News == 0) + || (NumVisits && News < 2))) + Response (how_goes_war, AlliedHome); + if (PHRASE_ENABLED (learn_new_info)) + Response (learn_new_info, AlliedHome); + if (PHRASE_ENABLED (what_now_homeworld)) + Response (what_now_homeworld, AlliedHome); + if (PHRASE_ENABLED (how_is_ultron)) + Response (how_is_ultron, AlliedHome); + if (NumVisits == 0) + Response (can_you_help, ExitConversation); + Response (bye_allied_homeworld, ExitConversation); +} + +static void +BeforeKohrAh (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_before_space)) + { + NumVisits = GET_GAME_STATE (SUPOX_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_BEFORE_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_BEFORE_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_before_space); + } + else if (PLAYER_SAID (R, what_now_before_space)) + { + NPCPhrase (DO_THIS_BEFORE_SPACE); + + DISABLE_PHRASE (what_now_before_space); + } + + if (PHRASE_ENABLED (whats_up_before_space)) + Response (whats_up_before_space, BeforeKohrAh); + if (PHRASE_ENABLED (what_now_before_space)) + Response (what_now_before_space, BeforeKohrAh); + Response (bye_before_space, ExitConversation); +} + +static void +AfterKohrAh (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_after_space)) + { + NumVisits = GET_GAME_STATE (SUPOX_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_AFTER_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_AFTER_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_after_space); + } + else if (PLAYER_SAID (R, what_now_after_space)) + { + NPCPhrase (DO_THIS_AFTER_SPACE); + + DISABLE_PHRASE (what_now_after_space); + } + + if (PHRASE_ENABLED (whats_up_after_space)) + Response (whats_up_after_space, AfterKohrAh); + if (PHRASE_ENABLED (what_now_after_space)) + Response (what_now_after_space, AfterKohrAh); + Response (bye_after_space, ExitConversation); +} + +static void +NeutralSupox (RESPONSE_REF R) +{ + BYTE i, LastStack, NumVisits; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, i_am0)) + { + NPCPhrase (WE_ARE_SUPOX); + + SET_GAME_STATE (SUPOX_STACK1, 1); + DISABLE_PHRASE (i_am0); + } + else if (PLAYER_SAID (R, my_ship0)) + { + NPCPhrase (OUR_SHIP); + + SET_GAME_STATE (SUPOX_STACK1, 2); + DISABLE_PHRASE (my_ship0); + } + else if (PLAYER_SAID (R, from_alliance0)) + { + NPCPhrase (FROM_SUPOX); + + SET_GAME_STATE (SUPOX_STACK1, 3); + DISABLE_PHRASE (from_alliance0); + } + else if (PLAYER_SAID (R, are_you_copying)) + { + NPCPhrase (YEAH_SORRY); + + SET_GAME_STATE (SUPOX_STACK1, 4); + } + else if (PLAYER_SAID (R, why_copy)) + { + NPCPhrase (SYMBIOTS); + + SET_GAME_STATE (SUPOX_STACK1, 5); + } + else if (PLAYER_SAID (R, tell_us_of_your_species)) + { + NPCPhrase (OUR_SPECIES); + + LastStack = 1; + SET_GAME_STATE (SUPOX_STACK2, 1); + } + else if (PLAYER_SAID (R, plants_arent_intelligent)) + { + NPCPhrase (PROVES_WERE_SPECIAL); + + SET_GAME_STATE (SUPOX_STACK2, 2); + } + else if (PLAYER_SAID (R, anyone_around_here)) + { + NPCPhrase (UTWIG_NEARBY); + + LastStack = 2; + SET_GAME_STATE (SUPOX_WAR_NEWS, 1); + ActivateStarShip (UTWIG_SHIP, SPHERE_TRACKING); + } + else if (PLAYER_SAID (R, what_relation_to_utwig)) + { + NPCPhrase (UTWIG_ALLIES); + + LastStack = 2; + SET_GAME_STATE (SUPOX_WAR_NEWS, 1); + } + else if (PLAYER_SAID (R, whats_wrong_with_utwig)) + { + NPCPhrase (BROKE_ULTRON); + + LastStack = 2; + SET_GAME_STATE (SUPOX_WAR_NEWS, 2); + } + else if (PLAYER_SAID (R, whats_ultron)) + { + NPCPhrase (TAKE_ULTRON); + + SET_GAME_STATE (SUPOX_WAR_NEWS, 0); + SET_GAME_STATE (ULTRON_CONDITION, 1); + + Response (what_do_i_do_now, ExitConversation); + Response (thanks_now_we_eat_you, ExitConversation); + + goto ExitSupox; + } + else if (PLAYER_SAID (R, got_fixed_ultron)) + { + NPCPhrase (GOOD_GIVE_TO_UTWIG); + + SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); + } + else if (PLAYER_SAID (R, look_i_repaired_lots)) + { + NPCPhrase (ALMOST_THERE); + + SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); + } + else if (PLAYER_SAID (R, look_i_slightly_repaired)) + { + NPCPhrase (GREAT_DO_MORE); + + SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); + } + else if (PLAYER_SAID (R, where_get_repairs)) + { + NPCPhrase (ANCIENT_RHYME); + + SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); + } + + switch (GET_GAME_STATE (SUPOX_STACK2)) + { + case 0: + pStr[1] = tell_us_of_your_species; + break; + case 1: + pStr[1] = plants_arent_intelligent; + break; + } + switch (GET_GAME_STATE (SUPOX_STACK1)) + { + case 0: + construct_response (shared_phrase_buf, + i_am0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + i_am1, + 0); + pStr[0] = i_am0; + pStr[1] = 0; + break; + case 1: + construct_response (shared_phrase_buf, + my_ship0, + (vararg_dcl)GLOBAL_SIS (ShipName), + my_ship1, + 0); + pStr[0] = my_ship0; + pStr[1] = 0; + break; + case 2: + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + from_alliance0, + (vararg_dcl)buf, + from_alliance1, + 0 + ); + } + pStr[0] = from_alliance0; + pStr[1] = 0; + break; + case 3: + pStr[0] = are_you_copying; + break; + case 4: + pStr[0] = why_copy; + break; + } + NumVisits = GET_GAME_STATE (ULTRON_CONDITION); + if (NumVisits == 0) + { + switch (GET_GAME_STATE (SUPOX_WAR_NEWS)) + { + case 0: + if (GET_GAME_STATE (UTWIG_VISITS) + || GET_GAME_STATE (UTWIG_HOME_VISITS) + || GET_GAME_STATE (BOMB_VISITS)) + pStr[2] = what_relation_to_utwig; + else + pStr[2] = anyone_around_here; + break; + case 1: + pStr[2] = whats_wrong_with_utwig; + break; + case 2: + pStr[2] = whats_ultron; + break; + } + } + if (pStr[LastStack]) + { + if (LastStack != 0 || GET_GAME_STATE (SUPOX_STACK1) > 2) + Response (pStr[LastStack], NeutralSupox); + else + DoResponsePhrase (pStr[LastStack], NeutralSupox, shared_phrase_buf); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + if (i != 0 || GET_GAME_STATE (SUPOX_STACK1) > 2) + Response (pStr[i], NeutralSupox); + else + DoResponsePhrase (pStr[i], NeutralSupox, shared_phrase_buf); + } + } + if (!GET_GAME_STATE (SUPOX_ULTRON_HELP)) + { + switch (NumVisits) + { + case 1: + Response (where_get_repairs, NeutralSupox); + break; + case 2: + Response (look_i_slightly_repaired, NeutralSupox); + break; + case 3: + Response (look_i_repaired_lots, NeutralSupox); + break; + case 4: + Response (got_fixed_ultron, NeutralSupox); + break; + } + } + Response (bye_neutral, ExitConversation); +ExitSupox: + ; +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (SUPOX_HOSTILE)) + { + NumVisits = GET_GAME_STATE (SUPOX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (ActivateStarShip (SUPOX_SHIP, CHECK_ALLIANCE) & GOOD_GUY) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (SUPOX_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_HOME_VISITS, NumVisits); + + AlliedHome ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (NumVisits == 1) + { + NumVisits = GET_GAME_STATE (SUPOX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_VISITS, NumVisits); + + BeforeKohrAh ((RESPONSE_REF)0); + } + else if (NumVisits < 5) + { + NumVisits = GET_GAME_STATE (SUPOX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_DURING_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_DURING_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (SUPOX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_VISITS, NumVisits); + + AfterKohrAh ((RESPONSE_REF)0); + } + } + } + else + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (SUPOX_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (SUPOX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (SUPOX_VISITS, NumVisits); + } + + NeutralSupox ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_supox (void) +{ + return (0); +} + +LOCDATAPTR +init_supox_comm (void) +{ + LOCDATAPTR retval; + + supox_desc.init_encounter_func = Intro; + supox_desc.uninit_encounter_func = uninit_supox; + + supox_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + supox_desc.AlienTextTemplate.baseline.y = 0; + supox_desc.AlienTextTemplate.align = ALIGN_CENTER; + supox_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (!GET_GAME_STATE (SUPOX_HOSTILE) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &supox_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/syreen/ifontres.h b/sc2/src/sc2code/comm/syreen/ifontres.h new file mode 100644 index 000000000..a73d9d1bc --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/ifontres.h @@ -0,0 +1,3 @@ +#define SYREEN_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/syreen/igfxres.h b/sc2/src/sc2code/comm/syreen/igfxres.h new file mode 100644 index 000000000..b981d6aff --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/igfxres.h @@ -0,0 +1,3 @@ +#define SYREEN_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/syreen/imusicre.h b/sc2/src/sc2code/comm/syreen/imusicre.h new file mode 100644 index 000000000..47b3d7ac3 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/imusicre.h @@ -0,0 +1,3 @@ +#define SYREEN_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/syreen/istrtab.h b/sc2/src/sc2code/comm/syreen/istrtab.h new file mode 100644 index 000000000..d255f9f31 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/istrtab.h @@ -0,0 +1,4 @@ +#define SYREEN_CONVERSATION_PHRASES 0x00200004L +#define SYREEN_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/syreen/resinst.h b/sc2/src/sc2code/comm/syreen/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/syreen/respkg.h b/sc2/src/sc2code/comm/syreen/respkg.h new file mode 100644 index 000000000..80bba0320 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/respkg.h @@ -0,0 +1,5 @@ +enum +{ + SYREEN_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/syreen/restypes.h b/sc2/src/sc2code/comm/syreen/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/syreen/strings.h b/sc2/src/sc2code/comm/syreen/strings.h new file mode 100644 index 000000000..fa7ed440f --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/strings.h @@ -0,0 +1,171 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HELLO_BEFORE_AMBUSH_1, + HELLO_BEFORE_AMBUSH_2, + HELLO_BEFORE_AMBUSH_3, + HELLO_BEFORE_AMBUSH_4, + we_are_vice_squad, + OK_VICE, + we_are_the_one_for_you_baby, + MAYBE_CAPTAIN, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + WELCOME_VINDICATOR0, + WELCOME_VINDICATOR1, + WELCOME_VINDICATOR2, + we_are_impressed, + SO_AM_I_CAPTAIN, + HOW_CAN_YOU_BE_HERE, + we_here_to_help, + NO_NEED_HELP, + we_need_help, + CANT_GIVE_HELP, + i_need_you, + OK_NEED, + i_need_touch_o_vision, + TOUCH_O_VISION, + know_about_deep_children, + WHAT_ABOUT_DEEP_CHILDREN, + mycons_involved, + WHAT_PROOF, + have_no_proof, + NEED_PROOF, + have_proof, + SEE_PROOF, + look_at_egg_sacks, + HORRIBLE_TRUTH, + what_doing_here, + OUR_NEW_WORLD, + what_about_war, + ABOUT_WAR, + help_us, + WONT_HELP, + what_about_history, + BEFORE_WAR, + what_about_homeworld, + ABOUT_HOMEWORLD, + what_happened, + DONT_KNOW_HOW, + what_about_outfit, + HOPE_YOU_LIKE_IT, + where_mates, + MATES_KILLED, + get_lonely, + MAKE_OUT_ALL_RIGHT, + bye, + GOODBYE, + MUST_ACT, + whats_next_step, + OPEN_VAULT, + where_is_it, + DONT_KNOW_WHERE, + been_there, + GREAT, + GIVE_SHUTTLE, + im_on_my_way, + doing_this_for_you, + if_i_die, + GOOD_LUCK, + OK_FOUND_VAULT, + what_now, + HERES_THE_PLAN, + whats_my_reward, + HERES_REWARD, + bye_after_vault, + GOODBYE_AFTER_VAULT, + HELLO_AFTER_AMBUSH_1, + HELLO_AFTER_AMBUSH_2, + HELLO_AFTER_AMBUSH_3, + HELLO_AFTER_AMBUSH_4, + what_now_after_ambush, + DO_THIS_AFTER_AMBUSH, + what_about_you, + ABOUT_ME, + whats_up_after_ambush, + GENERAL_INFO_AFTER_AMBUSH_1, + GENERAL_INFO_AFTER_AMBUSH_2, + GENERAL_INFO_AFTER_AMBUSH_3, + GENERAL_INFO_AFTER_AMBUSH_4, + bye_after_ambush, + GOODBYE_AFTER_AMBUSH, + FOUND_VAULT_YET_1, + FOUND_VAULT_YET_2, + vault_hint, + OK_HINT, + found_vault, + bye_before_vault, + GOODBYE_BEFORE_VAULT, + what_do_i_get_for_this, + GRATITUDE, + not_sure, + PLEASE, + READY_FOR_AMBUSH, + repeat_plan, + OK_REPEAT_PLAN, + bye_before_ambush, + GOODBYE_BEFORE_AMBUSH, + what_about_us, + ABOUT_US, + MORE_COMFORTABLE0, + MORE_COMFORTABLE1, + in_the_spirit, + OK_SPIRIT0, + OK_SPIRIT1, + OK_SPIRIT2, + OK_SPIRIT3, + what_in_mind, + SOMETHING_LIKE_THIS0, + SOMETHING_LIKE_THIS1, + SOMETHING_LIKE_THIS2, + SOMETHING_LIKE_THIS3, + hands_off, + OK_WONT_USE_HANDS0, + OK_WONT_USE_HANDS1, + OK_WONT_USE_HANDS2, + OK_WONT_USE_HANDS3, + why_lights_off, + LIGHTS_OFF_BECAUSE0, + LIGHTS_OFF_BECAUSE1, + LIGHTS_OFF_BECAUSE2, + LIGHTS_OFF_BECAUSE3, + evil_monster, + NOT_EVIL_MONSTER, + disease, + JUST_RELAX, + what_happens_if_i_touch_this, + THIS_HAPPENS0, + THIS_HAPPENS1, + are_you_sure_this_is_ok, + YES_SURE, + boy_they_never_taught, + THEN_LET_ME_TEACH, + not_much_more_to_say, + THEN_STOP_TALKING, + LATER, + SEX_GOODBYE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/syreen/syreen.res b/sc2/src/sc2code/comm/syreen/syreen.res new file mode 100644 index 000000000..0ffca2608 --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/syreen.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/syreen + +PACKAGE SYREEN_PACKAGE syreen.con + GFXRES SYREEN_PMAP_ANIM syreen.ani + FONTRES SYREEN_FONT syreen.fon + MUSICRES SYREEN_MUSIC syreen.mod + STRTAB SYREEN_CONVERSATION_PHRASES syreen.txt + STRTAB SYREEN_COLOR_MAP syreen.ct diff --git a/sc2/src/sc2code/comm/syreen/syreenc.c b/sc2/src/sc2code/comm/syreen/syreenc.c new file mode 100644 index 000000000..dac84402f --- /dev/null +++ b/sc2/src/sc2code/comm/syreen/syreenc.c @@ -0,0 +1,946 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/syreen/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/syreen/strings.h" + +static LOCDATA syreen_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)SYREEN_PMAP_ANIM, /* AlienFrame */ + (FONT)SYREEN_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + (COLORMAP)SYREEN_COLOR_MAP, /* AlienColorMap */ + SYREEN_MUSIC, /* AlienSong */ + SYREEN_CONVERSATION_PHRASES, /* PlayerPhrases */ + 15, /* NumAnimations */ + { + { + 5, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 7, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 9, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 11, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 13, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 15, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12), /* BlockMask */ + }, + { + 17, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 19, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 13), + }, + { + 21, /* StartIndex */ + 6, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 27, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + (1 << 14), /* BlockMask */ + }, + { + 31, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 37, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* RestartRate */ + }, + { + 41, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), /* BlockMask */ + }, + { + 44, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 20, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND, /* RestartRate */ + (1 << 7) | (1 << 14), /* BlockMask */ + }, + { + 48, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 16, 8, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND,/* RestartRate */ + (1 << 9) | (1 << 13), /* BlockMask */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 4, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +FriendlyExit (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye)) + NPCPhrase (GOODBYE); + else if (PLAYER_SAID (R, im_on_my_way) + || PLAYER_SAID (R, doing_this_for_you) + || PLAYER_SAID (R, if_i_die)) + NPCPhrase (GOOD_LUCK); + else if (PLAYER_SAID (R, bye_before_vault)) + NPCPhrase (GOODBYE_BEFORE_VAULT); + else if (PLAYER_SAID (R, bye_after_vault)) + NPCPhrase (GOODBYE_AFTER_VAULT); + else if (PLAYER_SAID (R, bye_before_ambush)) + NPCPhrase (GOODBYE_BEFORE_AMBUSH); + else if (PLAYER_SAID (R, bye_after_ambush)) + NPCPhrase (GOODBYE_AFTER_AMBUSH); + else + { + if (PLAYER_SAID (R, hands_off)) + { + NPCPhrase (OK_WONT_USE_HANDS0); + NPCPhrase (OK_WONT_USE_HANDS1); + NPCPhrase (OK_WONT_USE_HANDS2); + NPCPhrase (OK_WONT_USE_HANDS3); + + syreen_desc.AlienTextTemplate.align = ALIGN_RIGHT; + syreen_desc.AlienTextTemplate.baseline.x = SIS_SCREEN_WIDTH - TEXT_X_OFFS; + AlienTalkSegue (1); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 3 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 3 / 4; + AlienTalkSegue (2); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 2 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 2 / 4; + AlienTalkSegue (3); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 1 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 1 / 4; + AlienTalkSegue ((COUNT)~0); + + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 0; + syreen_desc.AlienTextTemplate.align = ALIGN_CENTER; + syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + } + else if (PLAYER_SAID (R, not_much_more_to_say)) + NPCPhrase (THEN_STOP_TALKING); + NPCPhrase (LATER); + NPCPhrase (SEX_GOODBYE); + + AlienTalkSegue (1); + AlienTalkSegue (2); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), ONE_SECOND / 2); + AlienTalkSegue ((COUNT)~0); + + SET_GAME_STATE (PLAYER_HAD_SEX, 1); + SET_GAME_STATE (PLAYER_HAVING_SEX, 0); + } +} + +static void +Sex (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, in_the_spirit)) + { + NPCPhrase (OK_SPIRIT0); + NPCPhrase (OK_SPIRIT1); + NPCPhrase (OK_SPIRIT2); + NPCPhrase (OK_SPIRIT3); + + syreen_desc.AlienTextTemplate.align = ALIGN_LEFT; + syreen_desc.AlienTextTemplate.baseline.x = TEXT_X_OFFS; + AlienTalkSegue (1); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 1 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 1 / 4; + AlienTalkSegue (2); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 2 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 2 / 4; + AlienTalkSegue (3); + + syreen_desc.AlienTextTemplate.baseline.x = SIS_TEXT_WIDTH * 3 / 4; + syreen_desc.AlienTextTemplate.baseline.y = 120 * 3 / 4; + AlienTalkSegue ((COUNT)~0); + + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 0; + syreen_desc.AlienTextTemplate.align = ALIGN_CENTER; + syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + } + else if (PLAYER_SAID (R, what_in_mind)) + { + NPCPhrase (SOMETHING_LIKE_THIS0); + NPCPhrase (SOMETHING_LIKE_THIS1); + NPCPhrase (SOMETHING_LIKE_THIS2); + NPCPhrase (SOMETHING_LIKE_THIS3); + + syreen_desc.AlienTextTemplate.align = ALIGN_LEFT; + syreen_desc.AlienTextTemplate.baseline.x = TEXT_X_OFFS; + AlienTalkSegue (1); + + syreen_desc.AlienTextTemplate.baseline.y = 120 * 3 / 4; + AlienTalkSegue (2); + + syreen_desc.AlienTextTemplate.align = ALIGN_RIGHT; + syreen_desc.AlienTextTemplate.baseline.x = SIS_SCREEN_WIDTH - TEXT_X_OFFS; + AlienTalkSegue (3); + + syreen_desc.AlienTextTemplate.baseline.y = 0; + AlienTalkSegue ((COUNT)~0); + + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 0; + syreen_desc.AlienTextTemplate.align = ALIGN_CENTER; + syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + } + else if (PLAYER_SAID (R, disease)) + NPCPhrase (JUST_RELAX); + else if (PLAYER_SAID (R, what_happens_if_i_touch_this)) + { + NPCPhrase (THIS_HAPPENS0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (THIS_HAPPENS1); + + DISABLE_PHRASE (what_happens_if_i_touch_this); + } + else if (PLAYER_SAID (R, are_you_sure_this_is_ok)) + { + NPCPhrase (YES_SURE); + + DISABLE_PHRASE (are_you_sure_this_is_ok); + } + else if (PLAYER_SAID (R, boy_they_never_taught)) + { + NPCPhrase (THEN_LET_ME_TEACH); + + DISABLE_PHRASE (boy_they_never_taught); + } + + if (!PHRASE_ENABLED (what_happens_if_i_touch_this) + && !PHRASE_ENABLED (are_you_sure_this_is_ok) + && !PHRASE_ENABLED (boy_they_never_taught)) + Response (not_much_more_to_say, FriendlyExit); + else + { + if (PHRASE_ENABLED (what_happens_if_i_touch_this)) + Response (what_happens_if_i_touch_this, Sex); + if (PHRASE_ENABLED (are_you_sure_this_is_ok)) + Response (are_you_sure_this_is_ok, Sex); + if (PHRASE_ENABLED (boy_they_never_taught)) + Response (boy_they_never_taught, Sex); + } +} + +static void +Foreplay (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_my_reward) + || PLAYER_SAID (R, what_about_us)) + { + if (PLAYER_SAID (R, whats_my_reward)) + NPCPhrase (HERES_REWARD); + else + NPCPhrase (ABOUT_US); + NPCPhrase (MORE_COMFORTABLE0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (MORE_COMFORTABLE1); + AlienTalkSegue (1); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND); + AlienTalkSegue ((COUNT)~0); + + SET_GAME_STATE (PLAYER_HAVING_SEX, 1); + } + else if (PLAYER_SAID (R, why_lights_off)) + { + NPCPhrase (LIGHTS_OFF_BECAUSE0); + NPCPhrase (LIGHTS_OFF_BECAUSE1); + NPCPhrase (LIGHTS_OFF_BECAUSE2); + NPCPhrase (LIGHTS_OFF_BECAUSE3); + + AlienTalkSegue (1); + syreen_desc.AlienTextWidth >>= 1; + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 2); + syreen_desc.AlienTextTemplate.baseline.y = 50; + AlienTalkSegue (2); + syreen_desc.AlienTextTemplate.baseline.x = + (TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1)) + + (SIS_TEXT_WIDTH >> 2); + AlienTalkSegue (3); + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 90; + syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + AlienTalkSegue ((COUNT)~0); + + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 0; + + DISABLE_PHRASE (why_lights_off); + } + else if (PLAYER_SAID (R, evil_monster)) + { + NPCPhrase (NOT_EVIL_MONSTER); + + DISABLE_PHRASE (evil_monster); + } + + if (PHRASE_ENABLED (why_lights_off)) + Response (why_lights_off, Foreplay); + else if (PHRASE_ENABLED (evil_monster)) + Response (evil_monster, Foreplay); + else + Response (disease, Sex); + Response (in_the_spirit, Sex); + Response (what_in_mind, Sex); + Response (hands_off, FriendlyExit); +} + +static void +AfterAmbush (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, what_now_after_ambush)) + { + NPCPhrase (DO_THIS_AFTER_AMBUSH); + + ActivateStarShip (SYREEN_SHIP, 0); + } + else if (PLAYER_SAID (R, what_about_you)) + { + NPCPhrase (ABOUT_ME); + + DISABLE_PHRASE (what_about_you); + } + else if (PLAYER_SAID (R, whats_up_after_ambush)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (SYREEN_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_4); + --NumVisits; + break; + } + SET_GAME_STATE (SYREEN_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_after_ambush); + } + + if (PHRASE_ENABLED (what_about_you)) + Response (what_about_you, AfterAmbush); + else if (!GET_GAME_STATE (PLAYER_HAD_SEX)) + { + Response (what_about_us, Foreplay); + } + if (!(ActivateStarShip (SYREEN_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) + Response (what_now_after_ambush, AfterAmbush); + if (PHRASE_ENABLED (whats_up_after_ambush)) + Response (whats_up_after_ambush, AfterAmbush); + Response (bye_after_ambush, FriendlyExit); +} + +static void +AmbushReady (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, repeat_plan)) + { + NPCPhrase (OK_REPEAT_PLAN); + + DISABLE_PHRASE (repeat_plan); + } + + if (PHRASE_ENABLED (repeat_plan)) + Response (repeat_plan, AmbushReady); + Response (bye_before_ambush, FriendlyExit); +} + +static void +SyreenShuttle (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_next_step)) + { + NPCPhrase (OPEN_VAULT); + + DISABLE_PHRASE (whats_next_step); + } + else if (PLAYER_SAID (R, what_do_i_get_for_this)) + { + NPCPhrase (GRATITUDE); + + DISABLE_PHRASE (what_do_i_get_for_this); + } + else if (PLAYER_SAID (R, not_sure)) + { + NPCPhrase (PLEASE); + + DISABLE_PHRASE (not_sure); + } + else if (PLAYER_SAID (R, where_is_it)) + { + NPCPhrase (DONT_KNOW_WHERE); + NPCPhrase (GIVE_SHUTTLE); + + SET_GAME_STATE (SYREEN_SHUTTLE, 1); + SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1); + + DISABLE_PHRASE (where_is_it); + } + else if (PLAYER_SAID (R, been_there)) + { + NPCPhrase (GREAT); + NPCPhrase (GIVE_SHUTTLE); + + SET_GAME_STATE (SYREEN_SHUTTLE, 1); + SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1); + + DISABLE_PHRASE (been_there); + } + + if (PHRASE_ENABLED (whats_next_step)) + Response (whats_next_step, SyreenShuttle); + else + { + if (!GET_GAME_STATE (KNOW_SYREEN_VAULT)) + { + if (PHRASE_ENABLED (where_is_it)) + Response (where_is_it, SyreenShuttle); + } + else + { + if (PHRASE_ENABLED (been_there)) + Response (been_there, SyreenShuttle); + } + if (!PHRASE_ENABLED (where_is_it) + || !PHRASE_ENABLED (been_there)) + { + Response (im_on_my_way, FriendlyExit); + Response (doing_this_for_you, FriendlyExit); + Response (if_i_die, FriendlyExit); + } + } + if (PHRASE_ENABLED (what_do_i_get_for_this)) + Response (what_do_i_get_for_this, SyreenShuttle); + if (PHRASE_ENABLED (not_sure)) + Response (not_sure, SyreenShuttle); +} + +static void +NormalSyreen (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[4]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; + if (PLAYER_SAID (R, we_here_to_help)) + NPCPhrase (NO_NEED_HELP); + else if (PLAYER_SAID (R, we_need_help)) + NPCPhrase (CANT_GIVE_HELP); + else if (PLAYER_SAID (R, know_about_deep_children)) + { + NPCPhrase (WHAT_ABOUT_DEEP_CHILDREN); + + DISABLE_PHRASE (know_about_deep_children); + } + else if (PLAYER_SAID (R, mycons_involved)) + { + NPCPhrase (WHAT_PROOF); + + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 3); + } + else if (PLAYER_SAID (R, have_no_proof)) + { + NPCPhrase (NEED_PROOF); + + SET_GAME_STATE (SYREEN_WANT_PROOF, 1); + } + else if (PLAYER_SAID (R, have_proof)) + { + NPCPhrase (SEE_PROOF); + + DISABLE_PHRASE (have_proof); + } + else if (PLAYER_SAID (R, what_doing_here)) + { + NPCPhrase (OUR_NEW_WORLD); + + SET_GAME_STATE (SYREEN_STACK0, 1); + LastStack = 1; + } + else if (PLAYER_SAID (R, what_about_war)) + { + NPCPhrase (ABOUT_WAR); + + SET_GAME_STATE (SYREEN_STACK0, 2); + LastStack = 1; + } + else if (PLAYER_SAID (R, help_us)) + { + NPCPhrase (WONT_HELP); + + SET_GAME_STATE (SYREEN_STACK0, 3); + } + else if (PLAYER_SAID (R, what_about_history)) + { + NPCPhrase (BEFORE_WAR); + + SET_GAME_STATE (SYREEN_STACK1, 1); + LastStack = 2; + } + else if (PLAYER_SAID (R, what_about_homeworld)) + { + NPCPhrase (ABOUT_HOMEWORLD); + + SET_GAME_STATE (SYREEN_STACK1, 2); + LastStack = 2; + } + else if (PLAYER_SAID (R, what_happened)) + { + NPCPhrase (DONT_KNOW_HOW); + + SET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1); + SET_GAME_STATE (SYREEN_STACK1, 3); + } + else if (PLAYER_SAID (R, what_about_outfit)) + { + NPCPhrase (HOPE_YOU_LIKE_IT); + + SET_GAME_STATE (SYREEN_STACK2, 1); + LastStack = 3; + } + else if (PLAYER_SAID (R, where_mates)) + { + NPCPhrase (MATES_KILLED); + + SET_GAME_STATE (SYREEN_STACK2, 2); + LastStack = 3; + } + else if (PLAYER_SAID (R, get_lonely)) + { + NPCPhrase (MAKE_OUT_ALL_RIGHT); + + SET_GAME_STATE (SYREEN_STACK2, 3); + } + else if (PLAYER_SAID (R, look_at_egg_sacks)) + { + NPCPhrase (HORRIBLE_TRUTH); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (SYREEN_HOME_VISITS, 0); + SET_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON, 1); + + SyreenShuttle ((RESPONSE_REF)0); + goto ExitSyreen; + } + + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 3) + { + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 2 + && GET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED)) + { + if (PHRASE_ENABLED (know_about_deep_children)) + pStr[0] = know_about_deep_children; + else + pStr[0] = mycons_involved; + } + } + else + { + if (GET_GAME_STATE (EGG_CASE0_ON_SHIP) + || GET_GAME_STATE (EGG_CASE1_ON_SHIP) + || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) + { + if (PHRASE_ENABLED (have_proof)) + pStr[0] = have_proof; + else + pStr[0] = look_at_egg_sacks; + } + else if (!GET_GAME_STATE (SYREEN_WANT_PROOF)) + { + pStr[0] = have_no_proof; + } + } + switch (GET_GAME_STATE (SYREEN_STACK0)) + { + case 0: + pStr[1] = what_doing_here; + break; + case 1: + pStr[1] = what_about_war; + break; + case 2: + pStr[1] = help_us; + break; + } + switch (GET_GAME_STATE (SYREEN_STACK1)) + { + case 0: + pStr[2] = what_about_history; + break; + case 1: + pStr[2] = what_about_homeworld; + break; + case 2: + pStr[2] = what_happened; + break; + } + switch (GET_GAME_STATE (SYREEN_STACK2)) + { + case 0: + pStr[3] = what_about_outfit; + break; + case 1: + pStr[3] = where_mates; + break; + case 2: + pStr[3] = get_lonely; + break; + } + if (pStr[LastStack]) + Response (pStr[LastStack], NormalSyreen); + for (i = 0; i < 4; ++i) + { + if (i != LastStack && pStr[i]) + Response (pStr[i], NormalSyreen); + } + Response (bye, FriendlyExit); +ExitSyreen: + ; +} + +static void +InitialSyreen (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_are_vice_squad)) + { + NPCPhrase (OK_VICE); + NPCPhrase (HOW_CAN_YOU_BE_HERE); + } + else if (PLAYER_SAID (R, we_are_the_one_for_you_baby)) + { + NPCPhrase (MAYBE_CAPTAIN); + NPCPhrase (HOW_CAN_YOU_BE_HERE); + } + else if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (WELCOME_VINDICATOR0); + NPCPhrase (GLOBAL_PLAYER_NAME); + NPCPhrase (WELCOME_VINDICATOR1); + NPCPhrase (GLOBAL_SHIP_NAME); + NPCPhrase (WELCOME_VINDICATOR2); + NPCPhrase (HOW_CAN_YOU_BE_HERE); + } + else if (PLAYER_SAID (R, we_are_impressed)) + { + NPCPhrase (SO_AM_I_CAPTAIN); + NPCPhrase (HOW_CAN_YOU_BE_HERE); + } + else if (PLAYER_SAID (R, i_need_you)) + { + NPCPhrase (OK_NEED); + + DISABLE_PHRASE (i_need_you); + } + else if (PLAYER_SAID (R, i_need_touch_o_vision)) + { + NPCPhrase (TOUCH_O_VISION); + + DISABLE_PHRASE (i_need_touch_o_vision); + } + + Response (we_here_to_help, NormalSyreen); + Response (we_need_help, NormalSyreen); + if (PHRASE_ENABLED (i_need_you)) + Response (i_need_you, InitialSyreen); + if (PHRASE_ENABLED (i_need_touch_o_vision)) + Response (i_need_touch_o_vision, InitialSyreen); +} + +static void +PlanAmbush (RESPONSE_REF R) +{ + NPCPhrase (OK_FOUND_VAULT); + + SET_GAME_STATE (MYCON_AMBUSH, 1); + SET_GAME_STATE (SYREEN_HOME_VISITS, 0); + + Response (whats_my_reward, Foreplay); + Response (bye_after_vault, FriendlyExit); +} + +static void +SyreenVault (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, vault_hint)) + { + NPCPhrase (OK_HINT); + + DISABLE_PHRASE (vault_hint); + } + + if (PHRASE_ENABLED (vault_hint)) + { + Response (vault_hint, SyreenVault); + } + Response (bye_before_vault, FriendlyExit); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + NumVisits = GET_GAME_STATE (SYREEN_HOME_VISITS); + if (GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AFTER_AMBUSH_1); + break; + case 1: + NPCPhrase (HELLO_AFTER_AMBUSH_2); + break; + case 2: + NPCPhrase (HELLO_AFTER_AMBUSH_3); + break; + case 3: + NPCPhrase (HELLO_AFTER_AMBUSH_3); + --NumVisits; + break; + } + + AfterAmbush ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (MYCON_AMBUSH)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (READY_FOR_AMBUSH); + --NumVisits; + break; + } + + AmbushReady ((RESPONSE_REF)0); + } + else if (!GET_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_BEFORE_AMBUSH_1); + break; + case 1: + NPCPhrase (HELLO_BEFORE_AMBUSH_2); + break; + case 2: + NPCPhrase (HELLO_BEFORE_AMBUSH_3); + break; + case 3: + NPCPhrase (HELLO_BEFORE_AMBUSH_4); + --NumVisits; + break; + } + + if (NumVisits > 1) + NormalSyreen ((RESPONSE_REF)0); + else + { + construct_response (shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0); + Response (we_are_vice_squad, InitialSyreen); + Response (we_are_the_one_for_you_baby, InitialSyreen); + DoResponsePhrase (we_are_vindicator0, InitialSyreen, shared_phrase_buf); + Response (we_are_impressed, InitialSyreen); + } + } +#ifdef NEVER + else if (!GET_GAME_STATE (SYREEN_SHUTTLE)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (MUST_ACT); + --NumVisits; + break; + } + + SyreenShuttle ((RESPONSE_REF)0); + } +#endif /* NEVER */ + else if (GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) + { + PlanAmbush ((RESPONSE_REF)0); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (FOUND_VAULT_YET_1); + break; + case 1: + NPCPhrase (FOUND_VAULT_YET_2); + --NumVisits; + break; + } + + SyreenVault ((RESPONSE_REF)0); + } + SET_GAME_STATE (SYREEN_HOME_VISITS, NumVisits); +ExitIntro: + ; +} + +static COUNT +uninit_syreen (void) +{ + return (0); +} + +LOCDATAPTR +init_syreen_comm (void) +{ + LOCDATAPTR retval; + + syreen_desc.init_encounter_func = Intro; + syreen_desc.uninit_encounter_func = uninit_syreen; + + syreen_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + syreen_desc.AlienTextTemplate.baseline.y = 0; + syreen_desc.AlienTextTemplate.align = ALIGN_CENTER; + syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + retval = &syreen_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/talkpet/ifontres.h b/sc2/src/sc2code/comm/talkpet/ifontres.h new file mode 100644 index 000000000..d3a07cbf9 --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/ifontres.h @@ -0,0 +1,3 @@ +#define TALKING_PET_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/talkpet/igfxres.h b/sc2/src/sc2code/comm/talkpet/igfxres.h new file mode 100644 index 000000000..72bd8d274 --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/igfxres.h @@ -0,0 +1,3 @@ +#define TALKING_PET_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/talkpet/imusicre.h b/sc2/src/sc2code/comm/talkpet/imusicre.h new file mode 100644 index 000000000..3c66ee923 --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/imusicre.h @@ -0,0 +1,3 @@ +#define TALKING_PET_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/talkpet/istrtab.h b/sc2/src/sc2code/comm/talkpet/istrtab.h new file mode 100644 index 000000000..f958a9fae --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/istrtab.h @@ -0,0 +1,4 @@ +#define TALKING_PET_CONVERSATION_PHRASES 0x00200004L +#define TALKING_PET_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/talkpet/resinst.h b/sc2/src/sc2code/comm/talkpet/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/talkpet/respkg.h b/sc2/src/sc2code/comm/talkpet/respkg.h new file mode 100644 index 000000000..58de0172d --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/respkg.h @@ -0,0 +1,5 @@ +enum +{ + TALKING_PET_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/talkpet/restypes.h b/sc2/src/sc2code/comm/talkpet/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/talkpet/strings.h b/sc2/src/sc2code/comm/talkpet/strings.h new file mode 100644 index 000000000..930175aad --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/strings.h @@ -0,0 +1,138 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HELLO_AT_UMGAH, + what_are_you, + JUST_TALKING_PET, + talking_pets_dumb, + OH_NO_YOU_DONT, + what_do_to_umgah, + DID_NOTHING, + umgah_zombies, + WORKS_LIKE_THIS, + we_are_vindicator0, + we_are_vindicator1, + GOOD_FOR_YOU, + must_explain_presence, + EXPLAIN_NOTHING_MONKEY_BOY, + bye_at_umgah, + GOODBYE_AT_UMGAH, + HYPNOTIZE_AGAIN_1, + HYPNOTIZE_AGAIN_2, + HYPNOTIZE_AGAIN_3, + HYPNOTIZE_AGAIN_4, + HYPNO_TAIL, + CANT_COMPEL, + LETS_MAKE_A_DEAL, + what_kind_of_deal, + HELP_DEFEAT_URQUAN, + ok_lets_do_it, + COMING_ABOARD, + how_trust, + TRUST, + boneless_dweeb, + YOUR_BONELESS_DWEEB, + what_are_you_really, + POOR_DNYARRI, + hard_to_believe, + ITS_TRUE, + bullshit, + WORTH_A_TRY, + kill_you, + PLEASE_DONT, + must_kill, + DONT_KILL, + want_kill_1, + want_kill_2, + want_kill_3, + GLAD_YOU_WONT_KILL, + whats_up_onboard, + GENERAL_INFO_ONBOARD_1, + GENERAL_INFO_ONBOARD_2, + GENERAL_INFO_ONBOARD_3, + GENERAL_INFO_ONBOARD_4, + GENERAL_INFO_ONBOARD_5, + GENERAL_INFO_ONBOARD_6, + GENERAL_INFO_ONBOARD_7, + GENERAL_INFO_ONBOARD_8, + HELLO_AS_DEVICE_1, + HELLO_AS_DEVICE_2, + HELLO_AS_DEVICE_3, + HELLO_AS_DEVICE_4, + HELLO_AS_DEVICE_5, + HELLO_AS_DEVICE_6, + HELLO_AS_DEVICE_7, + HELLO_AS_DEVICE_8, + CYBORG_PEP_TALK, + HUMAN_PEP_TALK, + I_SENSE_MY_SLAVES, + HAVENT_GOT_EVERYTHING, + NEED_BOMB, + SOUP_UP_BOMB, + SOUP_UP_FLEET, + SOUP_UP_FLAGSHIP, + COMEBACK_WHEN_READY, + what_now, + DO_THIS, + compel_urquan, + HERE_WE_GO, + im_scared, + STUPID_FOP, + compel_that_ship, + SAVING_MY_POWER, + any_suggestions, + SUGGESTION_1, + SUGGESTION_2, + SUGGESTION_3, + SUGGESTION_4, + SUGGESTION_5, + SUGGESTION_6, + SUGGESTION_7, + SUGGESTION_8, + about_your_race, + WHAT_ABOUT_RACE, + you_lied, + SO_WHAT, + bye_onboard, + GOODBYE_ONBOARD, + what_about_physiology, + NO_TALK_ABOUT_SELF, + what_about_powers, + NOT_POWERS_BUT_FLOWERS, + yes_flowers, + GOOD_HUMAN, + wish_to_go_now, + EXCELLENT_IDEA, + what_about_your_history, + ABOUT_HISTORY, + sentient_milieu, + ABOUT_SENTIENT_MILIEU, + what_about_war, + ABOUT_WAR, + enough_info, + OK_ENOUGH_INFO, + UMGAH_ALL_GONE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/talkpet/talkpet.c b/sc2/src/sc2code/comm/talkpet/talkpet.c new file mode 100644 index 000000000..b4304d52d --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/talkpet.c @@ -0,0 +1,803 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/talkpet/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/talkpet/strings.h" + +static LOCDATA talkpet_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)TALKING_PET_PMAP_ANIM, /* AlienFrame */ + (FONT)TALKING_PET_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + (COLORMAP)TALKING_PET_COLOR_MAP, /* AlienColorMap */ + TALKING_PET_MUSIC, /* AlienSong */ + TALKING_PET_CONVERSATION_PHRASES, /* PlayerPhrases */ + 16, /* NumAnimations */ + { + { + 7, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 10, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 13, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 16, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 18, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 13) /* BlockMask */ + }, + { + 21, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 12) | (1 << 14), /* BlockMask */ + }, + { + 24, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 26, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 28, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 32, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 35, /* StartIndex */ + 5, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 40, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 42, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), /* BlockMask */ + }, + { + 48, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4), /* BlockMask */ + }, + { + 50, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), /* BlockMask */ + }, + { + 52, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 6, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +#define NUM_STROBES 10 + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (SHIP_TO_COMPEL, 0); + + if (PLAYER_SAID (R, compel_urquan)) + { + NPCPhrase (HERE_WE_GO); + + SET_GAME_STATE (URQUAN_MESSED_UP, 1); + } + else if (PLAYER_SAID (R, wish_to_go_now)) + NPCPhrase (EXCELLENT_IDEA); + else if (PLAYER_SAID (R, bye_onboard)) + NPCPhrase (GOODBYE_ONBOARD); + else if (PLAYER_SAID (R, compel_that_ship)) + NPCPhrase (SAVING_MY_POWER); + else if (PLAYER_SAID (R, ok_lets_do_it) + || PLAYER_SAID (R, want_kill_1) + || PLAYER_SAID (R, want_kill_2) + || PLAYER_SAID (R, want_kill_3)) + { + if (PLAYER_SAID (R, ok_lets_do_it)) + NPCPhrase (COMING_ABOARD); + else + NPCPhrase (GLAD_YOU_WONT_KILL); + + SET_GAME_STATE (TALKING_PET, 1); + SET_GAME_STATE (TALKING_PET_ON_SHIP, 1); + SET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 0); + SET_GAME_STATE (UMGAH_VISITS, 0); + SET_GAME_STATE (UMGAH_HOME_VISITS, 0); + SET_GAME_STATE (ARILOU_STACK_2, 0) + } +} + +static void +MindFuckUrquan (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, what_now)) + { + NPCPhrase (DO_THIS); + + DISABLE_PHRASE (what_now); + } + else if (PLAYER_SAID (R, im_scared)) + { + NPCPhrase (STUPID_FOP); + + DISABLE_PHRASE (im_scared); + } + + if (PHRASE_ENABLED (what_now)) + Response (what_now, MindFuckUrquan); + if (PHRASE_ENABLED (im_scared)) + Response (im_scared, MindFuckUrquan); + Response (compel_urquan, ExitConversation); +} + +static void PetDevice (RESPONSE_REF R); + +static void +MindControl (RESPONSE_REF R) +{ + BYTE i; +RESPONSE_FUNC RespFunc; + + if (PLAYER_SAID (R, what_about_powers)) + { + NPCPhrase (NOT_POWERS_BUT_FLOWERS); + + RespFunc = (RESPONSE_FUNC)MindControl; + R = yes_flowers; + } + else /* if (R == yes_flowers) */ + { + NPCPhrase (GOOD_HUMAN); + + RespFunc = (RESPONSE_FUNC)ExitConversation; + R = wish_to_go_now; + } + + AlienTalkSegue ((COUNT)~0); + + for (i = 0; i < NUM_STROBES; ++i) + { + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), 0); + SleepTask (GetTimeCounter () + 1); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), 0); + SleepTask (GetTimeCounter () + 1); + } + + Response (R, RespFunc); +} + +static void +PetInfo (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, about_your_race)) + NPCPhrase (WHAT_ABOUT_RACE); + else if (PLAYER_SAID (R, what_about_physiology)) + { + NPCPhrase (NO_TALK_ABOUT_SELF); + + DISABLE_PHRASE (what_about_physiology); + } + else if (PLAYER_SAID (R, what_about_your_history)) + { + NPCPhrase (ABOUT_HISTORY); + + DISABLE_PHRASE (what_about_your_history); + } + else if (PLAYER_SAID (R, sentient_milieu)) + { + NPCPhrase (ABOUT_SENTIENT_MILIEU); + + DISABLE_PHRASE (sentient_milieu); + } + else if (PLAYER_SAID (R, what_about_war)) + { + NPCPhrase (ABOUT_WAR); + + DISABLE_PHRASE (what_about_war); + } + + if (PHRASE_ENABLED (what_about_physiology)) + { + Response (what_about_physiology, PetInfo); + } + else + { + Response (what_about_powers, MindControl); + } + if (PHRASE_ENABLED (what_about_your_history)) + Response (what_about_your_history, PetInfo); + else if (PHRASE_ENABLED (sentient_milieu)) + Response (sentient_milieu, PetInfo); + else if (PHRASE_ENABLED (what_about_war)) + Response (what_about_war, PetInfo); + Response (enough_info, PetDevice); +} + +static void +PetDevice (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_onboard)) + { + NumVisits = GET_GAME_STATE (TALKING_PET_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_ONBOARD_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_ONBOARD_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_ONBOARD_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_ONBOARD_4); + break; + case 4: + NPCPhrase (GENERAL_INFO_ONBOARD_5); + break; + case 5: + NPCPhrase (GENERAL_INFO_ONBOARD_6); + break; + case 6: + NPCPhrase (GENERAL_INFO_ONBOARD_7); + break; + case 7: + NPCPhrase (GENERAL_INFO_ONBOARD_8); + --NumVisits; + break; + } + SET_GAME_STATE (TALKING_PET_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_onboard); + } + else if (PLAYER_SAID (R, any_suggestions)) + { + NumVisits = GET_GAME_STATE (TALKING_PET_SUGGESTIONS); + switch (NumVisits++) + { + case 0: + NPCPhrase (SUGGESTION_1); + break; + case 1: + NPCPhrase (SUGGESTION_2); + break; + case 2: + NPCPhrase (SUGGESTION_3); + break; + case 3: + NPCPhrase (SUGGESTION_4); + break; + case 4: + NPCPhrase (SUGGESTION_5); + break; + case 5: + NPCPhrase (SUGGESTION_6); + break; + case 6: + NPCPhrase (SUGGESTION_7); + break; + case 7: + NPCPhrase (SUGGESTION_8); + --NumVisits; + break; + } + SET_GAME_STATE (TALKING_PET_SUGGESTIONS, NumVisits); + + DISABLE_PHRASE (any_suggestions); + } + else if (PLAYER_SAID (R, enough_info)) + NPCPhrase (OK_ENOUGH_INFO); + else if (PLAYER_SAID (R, you_lied)) + { + NPCPhrase (SO_WHAT); + + SET_GAME_STATE (DNYARRI_LIED, 0); + } + + if (GET_GAME_STATE (SHIP_TO_COMPEL)) + { + Response (compel_that_ship, ExitConversation); + } + if (PHRASE_ENABLED (whats_up_onboard)) + Response (whats_up_onboard, PetDevice); + if (PHRASE_ENABLED (any_suggestions)) + Response (any_suggestions, PetDevice); + Response (about_your_race, PetInfo); + if (GET_GAME_STATE (DNYARRI_LIED) && GET_GAME_STATE (LEARNED_TALKING_PET)) + Response (you_lied, PetDevice); + Response (bye_onboard, ExitConversation); +} + +static void +CompelPlayer (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, what_are_you)) + { + NPCPhrase (JUST_TALKING_PET); + + DISABLE_PHRASE (what_are_you); + } + else if (PLAYER_SAID (R, what_do_to_umgah)) + { + NPCPhrase (DID_NOTHING); + + DISABLE_PHRASE (what_do_to_umgah); + LastStack = 1; + } + else if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (GOOD_FOR_YOU); + + DISABLE_PHRASE (we_are_vindicator0); + LastStack = 2; + } + else if (R != 0) + { + if (PLAYER_SAID (R, bye_at_umgah)) + NPCPhrase (GOODBYE_AT_UMGAH); + else if (PLAYER_SAID (R, must_explain_presence)) + NPCPhrase (EXPLAIN_NOTHING_MONKEY_BOY); + else if (PLAYER_SAID (R, umgah_zombies)) + NPCPhrase (WORKS_LIKE_THIS); + else if (PLAYER_SAID (R, talking_pets_dumb)) + NPCPhrase (OH_NO_YOU_DONT); + + SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); + if (!GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP)) + { + SET_GAME_STATE (PLAYER_HYPNOTIZED, 1); + } + else + { + NPCPhrase (CANT_COMPEL); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + + goto ExitCompel; + } + + if (PHRASE_ENABLED (what_are_you)) + pStr[0] = what_are_you; + else + pStr[0] = talking_pets_dumb; + if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) + { + if (PHRASE_ENABLED (what_do_to_umgah)) + pStr[1] = what_do_to_umgah; + else + pStr[1] = umgah_zombies; + } + if (PHRASE_ENABLED (we_are_vindicator0)) + { + construct_response ( + shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (ShipName), + we_are_vindicator1, + 0 + ); + pStr[2] = we_are_vindicator0; + } + else + pStr[2] = must_explain_presence; + + if (pStr[LastStack]) + { + if (pStr[LastStack] != we_are_vindicator0) + Response (pStr[LastStack], CompelPlayer); + else + DoResponsePhrase (pStr[LastStack], CompelPlayer, shared_phrase_buf); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != we_are_vindicator0) + Response (pStr[i], CompelPlayer); + else + DoResponsePhrase (pStr[i], CompelPlayer, shared_phrase_buf); + } + } + Response (bye_at_umgah, CompelPlayer); +ExitCompel: + ; +} + +static void PetDeal (RESPONSE_REF R); + +static void +KillPet (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, must_kill)) + { + BYTE i; + + NPCPhrase (DONT_KILL); + AlienTalkSegue ((COUNT)~0); + + for (i = 0; i < NUM_STROBES; ++i) + { + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), 0); + SleepTask (GetTimeCounter () + 1); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 0) + ), 0); + SleepTask (GetTimeCounter () + 1); + } + } + + Response (want_kill_1, ExitConversation); + Response (want_kill_2, ExitConversation); + Response (want_kill_3, ExitConversation); +} + +static void +PetDeal (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, what_kind_of_deal)) + { + NPCPhrase (HELP_DEFEAT_URQUAN); + + DISABLE_PHRASE (what_kind_of_deal); + } + else if (PLAYER_SAID (R, how_trust)) + { + NPCPhrase (TRUST); + + DISABLE_PHRASE (how_trust); + } + else if (PLAYER_SAID (R, boneless_dweeb)) + { + NPCPhrase (YOUR_BONELESS_DWEEB); + + DISABLE_PHRASE (boneless_dweeb); + } + else if (PLAYER_SAID (R, what_are_you_really)) + { + NPCPhrase (POOR_DNYARRI); + + DISABLE_PHRASE (what_are_you_really); + } + else if (PLAYER_SAID (R, hard_to_believe)) + { + NPCPhrase (ITS_TRUE); + + SET_GAME_STATE (DNYARRI_LIED, 1); + DISABLE_PHRASE (hard_to_believe); + } + else if (PLAYER_SAID (R, bullshit)) + { + NPCPhrase (WORTH_A_TRY); + + DISABLE_PHRASE (bullshit); + } + else if (PLAYER_SAID (R, kill_you)) + { + NPCPhrase (PLEASE_DONT); + + DISABLE_PHRASE (kill_you); + } + + if (PHRASE_ENABLED (what_kind_of_deal)) + Response (what_kind_of_deal, PetDeal); + else + { + if (PHRASE_ENABLED (how_trust)) + Response (how_trust, PetDeal); + else if (PHRASE_ENABLED (boneless_dweeb)) + Response (boneless_dweeb, PetDeal); + Response (ok_lets_do_it, ExitConversation); + } + if (PHRASE_ENABLED (what_are_you_really)) + Response (what_are_you_really, PetDeal); + else + { + if (PHRASE_ENABLED (hard_to_believe) && !GET_GAME_STATE (LEARNED_TALKING_PET)) + Response (hard_to_believe, PetDeal); + else if (PHRASE_ENABLED (bullshit) && GET_GAME_STATE (LEARNED_TALKING_PET)) + Response (bullshit, PetDeal); + } + if (PHRASE_ENABLED (kill_you)) + Response (kill_you, PetDeal); + else if (PHRASE_ENABLED (must_kill)) + { + Response (must_kill, KillPet); + } +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + SET_GAME_STATE (SHIP_TO_COMPEL, 0); + SET_GAME_STATE (BATTLE_SEGUE, 1); + if (!(GLOBAL (glob_flags) & CYBORG_ENABLED)) + { + NPCPhrase (HUMAN_PEP_TALK); + } + else + { + NPCPhrase (CYBORG_PEP_TALK); + } + } + else if (GET_GAME_STATE (READY_TO_CONFUSE_URQUAN)) + { + SET_GAME_STATE (SHIP_TO_COMPEL, 0); + SET_GAME_STATE (READY_TO_CONFUSE_URQUAN, 0); + if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) + { + NPCPhrase (HAVENT_GOT_EVERYTHING); + if (!GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) + NPCPhrase (NEED_BOMB); + else + NPCPhrase (SOUP_UP_BOMB); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (GET_GAME_STATE (URQUAN_MESSED_UP)) + { + NPCPhrase (NULL_PHRASE /* HELLO_AFTER_COMPEL_URQUAN */); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + NPCPhrase (I_SENSE_MY_SLAVES); + + MindFuckUrquan ((RESPONSE_REF)0); + } + } + else if (GET_GAME_STATE (TALKING_PET_ON_SHIP)) + { + NumVisits = GET_GAME_STATE (TALKING_PET_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AS_DEVICE_1); + break; + case 1: + NPCPhrase (HELLO_AS_DEVICE_2); + break; + case 2: + NPCPhrase (HELLO_AS_DEVICE_3); + break; + case 3: + NPCPhrase (HELLO_AS_DEVICE_4); + break; + case 4: + NPCPhrase (HELLO_AS_DEVICE_5); + break; + case 5: + NPCPhrase (HELLO_AS_DEVICE_6); + break; + case 6: + NPCPhrase (HELLO_AS_DEVICE_7); + break; + case 7: + NPCPhrase (HELLO_AS_DEVICE_8); + --NumVisits; + break; + } + SET_GAME_STATE (TALKING_PET_VISITS, NumVisits); + + PetDevice ((RESPONSE_REF)0); + } + else if (GetHeadLink (&GLOBAL (npc_built_ship_q))) + { + NumVisits = GET_GAME_STATE (TALKING_PET_HOME_VISITS); + switch (NumVisits++) + { + case 0: + SET_GAME_STATE (UMGAH_VISITS, 0); + NPCPhrase (HELLO_AT_UMGAH); + break; + case 1: + NPCPhrase (HYPNOTIZE_AGAIN_1); + break; + case 2: + NPCPhrase (HYPNOTIZE_AGAIN_2); + break; + case 3: + NPCPhrase (HYPNOTIZE_AGAIN_3); + break; + case 4: + NPCPhrase (HYPNOTIZE_AGAIN_4); + --NumVisits; + break; + } + SET_GAME_STATE (TALKING_PET_HOME_VISITS, NumVisits); + + if (NumVisits == 1) + { + CompelPlayer ((RESPONSE_REF)0); + } + else if (!GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP)) + { + SET_GAME_STATE (PLAYER_HYPNOTIZED, 1); + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + NPCPhrase (CANT_COMPEL); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + } + else + { + if (ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING)) + NPCPhrase (LETS_MAKE_A_DEAL); + else + NPCPhrase (UMGAH_ALL_GONE); + + PetDeal ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_talkpet (void) +{ + return (0); +} + +LOCDATAPTR +init_talkpet_comm (void) +{ + LOCDATAPTR retval; + + talkpet_desc.init_encounter_func = Intro; + talkpet_desc.uninit_encounter_func = uninit_talkpet; + + talkpet_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + talkpet_desc.AlienTextTemplate.baseline.y = 0; + talkpet_desc.AlienTextTemplate.align = ALIGN_CENTER; + talkpet_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + + retval = &talkpet_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/talkpet/talkpet.res b/sc2/src/sc2code/comm/talkpet/talkpet.res new file mode 100644 index 000000000..6d17e602c --- /dev/null +++ b/sc2/src/sc2code/comm/talkpet/talkpet.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/talkpet + +PACKAGE TALKING_PET_PACKAGE talkpet.con + GFXRES TALKING_PET_PMAP_ANIM talkpet.ani + FONTRES TALKING_PET_FONT talkpet.fon + MUSICRES TALKING_PET_MUSIC talkpet.mod + STRTAB TALKING_PET_CONVERSATION_PHRASES talkpet.txt + STRTAB TALKING_PET_COLOR_MAP talkpet.ct diff --git a/sc2/src/sc2code/comm/thradd/ifontres.h b/sc2/src/sc2code/comm/thradd/ifontres.h new file mode 100644 index 000000000..1a7b4aac9 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/ifontres.h @@ -0,0 +1,3 @@ +#define THRADD_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/thradd/igfxres.h b/sc2/src/sc2code/comm/thradd/igfxres.h new file mode 100644 index 000000000..d3c7c33c3 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/igfxres.h @@ -0,0 +1,3 @@ +#define THRADD_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/thradd/imusicre.h b/sc2/src/sc2code/comm/thradd/imusicre.h new file mode 100644 index 000000000..989c26580 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/imusicre.h @@ -0,0 +1,3 @@ +#define THRADD_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/thradd/istrtab.h b/sc2/src/sc2code/comm/thradd/istrtab.h new file mode 100644 index 000000000..5d89e576b --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/istrtab.h @@ -0,0 +1,3 @@ +#define THRADD_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/thradd/resinst.h b/sc2/src/sc2code/comm/thradd/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/thradd/respkg.h b/sc2/src/sc2code/comm/thradd/respkg.h new file mode 100644 index 000000000..039e8e2c3 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/respkg.h @@ -0,0 +1,5 @@ +enum +{ + THRADD_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/thradd/restypes.h b/sc2/src/sc2code/comm/thradd/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/thradd/strings.h b/sc2/src/sc2code/comm/thradd/strings.h new file mode 100644 index 000000000..1f1a4b99f --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/strings.h @@ -0,0 +1,179 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HOSTILE_SPACE_HELLO_1, + HOSTILE_SPACE_HELLO_2, + HOSTILE_SPACE_HELLO_3, + HOSTILE_SPACE_HELLO_4, + HOSTILE_HOMEWORLD_HELLO_1, + HOSTILE_HOMEWORLD_HELLO_2, + HOSTILE_HOMEWORLD_HELLO_3, + HOSTILE_HOMEWORLD_HELLO_4, + whats_up_hostile_1, + whats_up_hostile_2, + GENERAL_INFO_HOSTILE_1, + GENERAL_INFO_HOSTILE_2, + GENERAL_INFO_HOSTILE_3, + GENERAL_INFO_HOSTILE_4, + what_about_you_1, + ABOUT_US_1, + what_about_you_2, + ABOUT_US_2, + what_about_urquan_1, + ABOUT_URQUAN_1, + what_about_urquan_2, + ABOUT_URQUAN_2, + got_idea, + GOOD_IDEA, + WE_GO_TO_IMPRESS_URQUAN_1, + WE_GO_TO_IMPRESS_URQUAN_2, + WE_IMPRESSING_URQUAN_1, + WE_IMPRESSING_URQUAN_2, + WE_IMPRESSED_URQUAN_1, + WE_IMPRESSED_URQUAN_2, + HOSTILE_HELIX_HELLO_1, + HOSTILE_HELIX_HELLO_2, + submit_1, + NO_SUBMIT_1, + submit_2, + NO_SUBMIT_2, + be_friends_1, + NO_FRIENDS_1, + be_friends_2, + NO_FRIENDS_2, + how_impressed_urquan_1, + IMPRESSED_LIKE_SO_1, + how_impressed_urquan_2, + IMPRESSED_LIKE_SO_2, + bye_hostile_1, + GOODBYE_HOSTILE_1, + bye_hostile_2, + GOODBYE_HOSTILE_2, + why_you_here_hostile, + NONE_OF_YOUR_CONCERN, + demand_to_land, + NO_DEMAND, + what_about_this_world, + BLUE_HELIX, + whats_helix_hostile, + HELIX_IS_HOSTILE, + i_need_to_land_lie, + CAUGHT_LIE, + bye_hostile_helix, + GOODBYE_HOSTILE_HELIX, + DIE_THIEF_1, + DIE_THIEF_2, + AMAZING_PERFORMANCE, + IMPRESSIVE_PERFORMANCE, + ADEQUATE_PERFORMANCE, + HELLO_POLITE_1, + HELLO_POLITE_2, + HELLO_POLITE_3, + HELLO_POLITE_4, + HELLO_RHYME_1, + HELLO_RHYME_2, + HELLO_RHYME_3, + HELLO_RHYME_4, + HELLO_PIG_LATIN_1, + HELLO_PIG_LATIN_2, + HELLO_PIG_LATIN_3, + HELLO_PIG_LATIN_4, + HELLO_LIKE_YOU_1, + HELLO_LIKE_YOU_2, + HELLO_LIKE_YOU_3, + HELLO_LIKE_YOU_4, + WELCOME_SPACE0, + WELCOME_SPACE1, + WELCOME_HOMEWORLD0, + WELCOME_HOMEWORLD1, + WELCOME_HELIX0, + WELCOME_HELIX1, + why_you_here_ally, + GUARDING_HELIX_ALLY, + whats_helix_ally, + HELIX_IS_ALLY, + may_i_land, + SURE_LAND, + whats_up_ally, + GENERAL_INFO_ALLY_1, + GENERAL_INFO_ALLY_2, + GENERAL_INFO_ALLY_3, + GENERAL_INFO_ALLY_4, + HOW_SHOULD_WE_ACT, + friendly, + OK_FRIENDLY, + wacky, + OK_WACKY, + just_like_us, + OK_JUST_LIKE_YOU, + WORK_TO_DO, + contemplative, + OK_CONTEMPLATIVE, + how_goes_culture, + CONTEMP_GOES_1, + CONTEMP_GOES_2, + FRIENDLY_GOES_1, + FRIENDLY_GOES_2, + WACKY_GOES_1, + WACKY_GOES_2, + LIKE_YOU_GOES_1, + LIKE_YOU_GOES_2, + bye_ally, + GOODBYE_ALLY_1, + GOODBYE_ALLY_2, + GOODBYE_ALLY_3, + GOODBYE_ALLY_4, + be_polite, + OK_POLITE, + speak_pig_latin, + OK_PIG_LATIN, + use_rhymes, + OK_RHYMES, + just_the_way_we_do, + OK_WAY_YOU_DO, + WHAT_NAME_FOR_CULTURE, + alliance_name, + OK_ALLIANCE_NAME, + NAME_TAIL, + you_decide, + OK_CULTURE_20, + fat, + OK_FAT, + the_slave_empire, + OK_SLAVE, + FAT_JERKS, + CULTURE, + SLAVE_EMPIRE, + name_1, + name_2, + name_3, + name_40, + name_41, + HAVING_FUN_WITH_ILWRATH_1, + HAVING_FUN_WITH_ILWRATH_2, + GO_AWAY_FIGHTING_ILWRATH_1, + GO_AWAY_FIGHTING_ILWRATH_2, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/thradd/thradd.res b/sc2/src/sc2code/comm/thradd/thradd.res new file mode 100644 index 000000000..83a9ab802 --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/thradd.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/thradd + +PACKAGE THRADD_PACKAGE thradd.con + GFXRES THRADD_PMAP_ANIM thradd.ani + FONTRES THRADD_FONT thradd.fon + MUSICRES THRADD_MUSIC thradd.mod + STRTAB THRADD_CONVERSATION_PHRASES thradd.txt + diff --git a/sc2/src/sc2code/comm/thradd/thraddc.c b/sc2/src/sc2code/comm/thradd/thraddc.c new file mode 100644 index 000000000..5f3b6f39f --- /dev/null +++ b/sc2/src/sc2code/comm/thradd/thraddc.c @@ -0,0 +1,923 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/thradd/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/thradd/strings.h" + +static LOCDATA thradd_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)THRADD_PMAP_ANIM, /* AlienFrame */ + (FONT)THRADD_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + THRADD_MUSIC, /* AlienSong */ + THRADD_CONVERSATION_PHRASES, /* PlayerPhrases */ + 8, /* NumAnimations */ + { + { + 8, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* RestartRate */ + (1 << 4), /* BlockMask */ + }, + { + 12, /* StartIndex */ + 9, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 21, /* StartIndex */ + 6, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 27, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4), /* BlockMask */ + }, + { + 30, /* StartIndex */ + 12, /* NumFrames */ + CIRCULAR_ANIM + | WAIT_TALKING, /* AnimFlags */ + 10, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND, /* RestartRate */ + (1 << 0) | (1 << 3) | (1 << 5), + }, + { + 42, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4) | (1 << 6), /* BlockMask */ + }, + { + 47, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 4, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), /* BlockMask */ + }, + { + 52, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + 6, 0, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 7, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static int +GetCultureName (void) +{ + int culture; + + switch (GET_GAME_STATE (THRADD_CULTURE)) + { + case 1: + culture = CULTURE; + break; + case 2: + culture = FAT_JERKS; + break; + case 3: + culture = SLAVE_EMPIRE; + break; + } + + return (culture); +} + +static void +PolitePhrase (BYTE which_phrase) +{ + switch (which_phrase) + { + case 0: + NPCPhrase (HELLO_POLITE_1); + break; + case 1: + NPCPhrase (HELLO_POLITE_2); + break; + case 2: + NPCPhrase (HELLO_POLITE_3); + break; + case 3: + NPCPhrase (HELLO_POLITE_4); + break; + } +} + +static void +RhymePhrase (BYTE which_phrase) +{ + switch (which_phrase) + { + case 0: + NPCPhrase (HELLO_RHYME_1); + break; + case 1: + NPCPhrase (HELLO_RHYME_2); + break; + case 2: + NPCPhrase (HELLO_RHYME_3); + break; + case 3: + NPCPhrase (HELLO_RHYME_4); + break; + } +} + +static void +PigLatinPhrase (BYTE which_phrase) +{ + switch (which_phrase) + { + case 0: + NPCPhrase (HELLO_PIG_LATIN_1); + break; + case 1: + NPCPhrase (HELLO_PIG_LATIN_2); + break; + case 2: + NPCPhrase (HELLO_PIG_LATIN_3); + break; + case 3: + NPCPhrase (HELLO_PIG_LATIN_4); + break; + } +} + +static void +LikeYouPhrase (BYTE which_phrase) +{ + switch (which_phrase) + { + case 0: + NPCPhrase (HELLO_LIKE_YOU_1); + break; + case 1: + NPCPhrase (HELLO_LIKE_YOU_2); + break; + case 2: + NPCPhrase (HELLO_LIKE_YOU_3); + break; + case 3: + NPCPhrase (HELLO_LIKE_YOU_4); + break; + } +} + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye_hostile_2)) + NPCPhrase (GOODBYE_HOSTILE_2); + else if (PLAYER_SAID (R, bye_hostile_1)) + { + NPCPhrase (GOODBYE_HOSTILE_1); + + SET_GAME_STATE (THRADD_HOSTILE_STACK_5, 1); + } + else if (PLAYER_SAID (R, submit_1)) + { + NPCPhrase (NO_SUBMIT_1); + + SET_GAME_STATE (THRADD_HOSTILE_STACK_2, 1); + } + else if (PLAYER_SAID (R, submit_2)) + NPCPhrase (NO_SUBMIT_2); + else if (PLAYER_SAID (R, got_idea)) + { + NPCPhrase (GOOD_IDEA); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_THRADD_MISSION); + SET_GAME_STATE (THRADD_STACK_1, 5); + } + else if (PLAYER_SAID (R, bye_hostile_helix)) + NPCPhrase (GOODBYE_HOSTILE_HELIX); + else if (PLAYER_SAID (R, bye_ally)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (THRADD_STACK_1); + switch (NumVisits++) + { + case 0: + NPCPhrase (GOODBYE_ALLY_1); + break; + case 1: + NPCPhrase (GOODBYE_ALLY_2); + break; + case 2: + NPCPhrase (GOODBYE_ALLY_3); + break; + case 3: + NPCPhrase (GOODBYE_ALLY_4); + --NumVisits; + break; + } + SET_GAME_STATE (THRADD_STACK_1, NumVisits); + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, may_i_land)) + { + NPCPhrase (SURE_LAND); + + SET_GAME_STATE (HELIX_UNPROTECTED, 1); + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, demand_to_land)) + NPCPhrase (NO_DEMAND); + else if (PLAYER_SAID (R, i_need_to_land_lie)) + NPCPhrase (CAUGHT_LIE); + else + { + if (PLAYER_SAID (R, contemplative)) + { + NPCPhrase (OK_CONTEMPLATIVE); + + SET_GAME_STATE (THRADD_DEMEANOR, 0); + } + else if (PLAYER_SAID (R, friendly)) + { + NPCPhrase (OK_FRIENDLY); + + SET_GAME_STATE (THRADD_DEMEANOR, 1); + } + else if (PLAYER_SAID (R, wacky)) + { + NPCPhrase (OK_WACKY); + + SET_GAME_STATE (THRADD_DEMEANOR, 2); + } + else if (PLAYER_SAID (R, just_like_us)) + { + NPCPhrase (OK_JUST_LIKE_YOU); + + SET_GAME_STATE (THRADD_DEMEANOR, 3); + } + NPCPhrase (WORK_TO_DO); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } +} + +static void +ThraddAllies (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, why_you_here_ally)) + { + NPCPhrase (GUARDING_HELIX_ALLY); + + DISABLE_PHRASE (why_you_here_ally); + } + else if (PLAYER_SAID (R, whats_helix_ally)) + { + NPCPhrase (HELIX_IS_ALLY); + + DISABLE_PHRASE (whats_helix_ally); + } + else if (PLAYER_SAID (R, whats_up_ally)) + { + NumVisits = GET_GAME_STATE (THRADD_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_ALLY_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_ALLY_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_ALLY_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_ALLY_4); + --NumVisits; + break; + } + SET_GAME_STATE (THRADD_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_ally); + } + else if (PLAYER_SAID (R, how_goes_culture)) + { + NumVisits = GET_GAME_STATE (THRADD_DEMEANOR); + switch (NumVisits & ((1 << 2) - 1)) + { + case 0: + if (!(NumVisits & ~((1 << 2) - 1))) + NPCPhrase (CONTEMP_GOES_1); + else + NPCPhrase (CONTEMP_GOES_2); + break; + case 1: + if (!(NumVisits & ~((1 << 2) - 1))) + NPCPhrase (FRIENDLY_GOES_1); + else + NPCPhrase (FRIENDLY_GOES_2); + break; + case 2: + if (!(NumVisits & ~((1 << 2) - 1))) + NPCPhrase (WACKY_GOES_1); + else + NPCPhrase (WACKY_GOES_2); + break; + case 3: + if (!(NumVisits & ~((1 << 2) - 1))) + NPCPhrase (LIKE_YOU_GOES_1); + else + NPCPhrase (LIKE_YOU_GOES_2); + break; + } + NumVisits |= 1 << 2; + SET_GAME_STATE (THRADD_DEMEANOR, NumVisits); + + DISABLE_PHRASE (how_goes_culture); + } + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + if (PHRASE_ENABLED (why_you_here_ally)) + Response (why_you_here_ally, ThraddAllies); + else + { + if (PHRASE_ENABLED (whats_helix_ally)) + Response (whats_helix_ally, ThraddAllies); + Response (may_i_land, ExitConversation); + } + } + if (PHRASE_ENABLED (whats_up_ally)) + Response (whats_up_ally, ThraddAllies); + if (PHRASE_ENABLED (how_goes_culture)) + Response (how_goes_culture, ThraddAllies); + Response (bye_ally, ExitConversation); +} + +static void +ThraddDemeanor (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, you_decide)) + { + NPCPhrase (OK_CULTURE_20); + + SET_GAME_STATE (THRADD_CULTURE, 1); + } + else if (PLAYER_SAID (R, fat)) + { + NPCPhrase (OK_FAT); + + SET_GAME_STATE (THRADD_CULTURE, 2); + } + else if (PLAYER_SAID (R, the_slave_empire)) + { + SET_GAME_STATE (THRADD_CULTURE, 3); + + NPCPhrase (OK_SLAVE); + } + + NPCPhrase (HOW_SHOULD_WE_ACT); + Response (contemplative, ExitConversation); + Response (friendly, ExitConversation); + Response (wacky, ExitConversation); + Response (just_like_us, ExitConversation); +} + +static void +ThraddCulture (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, be_polite)) + { + NPCPhrase (OK_POLITE); + + SET_GAME_STATE (THRADD_INTRO, 0); + } + else if (PLAYER_SAID (R, use_rhymes)) + { + NPCPhrase (OK_RHYMES); + + SET_GAME_STATE (THRADD_INTRO, 1); + } + else if (PLAYER_SAID (R, speak_pig_latin)) + { + NPCPhrase (OK_PIG_LATIN); + + SET_GAME_STATE (THRADD_INTRO, 2); + } + else if (PLAYER_SAID (R, just_the_way_we_do)) + { + NPCPhrase (OK_WAY_YOU_DO); + + SET_GAME_STATE (THRADD_INTRO, 3); + } + NPCPhrase (WHAT_NAME_FOR_CULTURE); + + Response (you_decide, ThraddDemeanor); + Response (fat, ThraddDemeanor); + Response (the_slave_empire, ThraddDemeanor); +} + +static void +ThraddWorship (RESPONSE_REF R) +{ + SET_GAME_STATE (THRADD_VISITS, 0); + SET_GAME_STATE (THRADD_MANNER, 1); + SET_GAME_STATE (THRADD_STACK_1, 0); + ActivateStarShip (THRADDASH_SHIP, 0); + + Response (be_polite, ThraddCulture); + Response (speak_pig_latin, ThraddCulture); + Response (use_rhymes, ThraddCulture); + Response (just_the_way_we_do, ThraddCulture); +} + +static void +HelixWorld (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, why_you_here_hostile)) + { + NPCPhrase (NONE_OF_YOUR_CONCERN); + + SET_GAME_STATE (THRADD_CULTURE, 1); + } + else if (PLAYER_SAID (R, what_about_this_world)) + { + NPCPhrase (BLUE_HELIX); + + SET_GAME_STATE (THRADD_INTRO, 1); + } + else if (PLAYER_SAID (R, whats_helix_hostile)) + { + NPCPhrase (HELIX_IS_HOSTILE); + + SET_GAME_STATE (THRADD_INTRO, 2); + } + else if (PLAYER_SAID (R, i_need_to_land_lie)) + { + NPCPhrase (CAUGHT_LIE); + + SET_GAME_STATE (THRADD_DEMEANOR, 1); + } + + if (!GET_GAME_STATE (THRADD_CULTURE)) + Response (why_you_here_hostile, HelixWorld); + else + { + Response (demand_to_land, ExitConversation); + } + switch (GET_GAME_STATE (THRADD_INTRO)) + { + case 0: + Response (what_about_this_world, HelixWorld); + break; + case 1: + Response (whats_helix_hostile, HelixWorld); + break; + } + if (!GET_GAME_STATE (THRADD_DEMEANOR)) + { + Response (i_need_to_land_lie, ExitConversation); + } + Response (bye_hostile_helix, ExitConversation); +} + +static void +ThraddHostile (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_up_hostile_1)) + { + NPCPhrase (GENERAL_INFO_HOSTILE_1); + + SET_GAME_STATE (THRADD_INFO, 1); + DISABLE_PHRASE (whats_up_hostile_2); + } + else if (PLAYER_SAID (R, whats_up_hostile_2)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (THRADD_INFO); + switch (NumVisits++) + { + case 1: + NPCPhrase (GENERAL_INFO_HOSTILE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_HOSTILE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_HOSTILE_4); + --NumVisits; + break; + } + SET_GAME_STATE (THRADD_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_hostile_2); + } + else if (PLAYER_SAID (R, what_about_you_1)) + { + NPCPhrase (ABOUT_US_1); + + SET_GAME_STATE (THRADD_STACK_1, 1); + } + else if (PLAYER_SAID (R, what_about_you_2)) + { + NPCPhrase (ABOUT_US_2); + + SET_GAME_STATE (THRADD_STACK_1, 2); + } + else if (PLAYER_SAID (R, what_about_urquan_1)) + { + NPCPhrase (ABOUT_URQUAN_1); + + SET_GAME_STATE (THRADD_STACK_1, 3); + } + else if (PLAYER_SAID (R, what_about_urquan_2)) + { + NPCPhrase (ABOUT_URQUAN_2); + + SET_GAME_STATE (THRADD_STACK_1, 4); + } + else if (PLAYER_SAID (R, be_friends_1)) + { + NPCPhrase (NO_FRIENDS_1); + + SET_GAME_STATE (THRADD_HOSTILE_STACK_3, 1); + } + else if (PLAYER_SAID (R, be_friends_2)) + { + NPCPhrase (NO_FRIENDS_2); + DISABLE_PHRASE (be_friends_2); + } + else if (PLAYER_SAID (R, how_impressed_urquan_1)) + { + NPCPhrase (IMPRESSED_LIKE_SO_1); + + SET_GAME_STATE (THRADD_HOSTILE_STACK_4, 1); + } + else if (PLAYER_SAID (R, how_impressed_urquan_2)) + { + NPCPhrase (IMPRESSED_LIKE_SO_2); + + SET_GAME_STATE (THRADD_MISSION, 5); + } + + if (GET_GAME_STATE (THRADD_INFO) == 0) + Response (whats_up_hostile_1, ThraddHostile); + else if (PHRASE_ENABLED (whats_up_hostile_2)) + Response (whats_up_hostile_2, ThraddHostile); + switch (GET_GAME_STATE (THRADD_STACK_1)) + { + case 0: + Response (what_about_you_1, ThraddHostile); + break; + case 1: + Response (what_about_you_2, ThraddHostile); + break; + case 2: + Response (what_about_urquan_1, ThraddHostile); + break; + case 3: + Response (what_about_urquan_2, ThraddHostile); + break; + case 4: + if (!GET_GAME_STATE (KOHR_AH_FRENZY)) + Response (got_idea, ExitConversation); + else + { + SET_GAME_STATE (THRADD_STACK_1, 5); + } + break; + } + if (GET_GAME_STATE (THRADD_HOSTILE_STACK_2) == 0) + Response (submit_1, ExitConversation); + else + Response (submit_2, ExitConversation); + if (GET_GAME_STATE (THRADD_HOSTILE_STACK_3) == 0) + Response (be_friends_1, ThraddHostile); + else if (PHRASE_ENABLED (be_friends_2)) + Response (be_friends_2, ThraddHostile); + if (GET_GAME_STATE (THRADD_MISSION) == 4) + { + if (GET_GAME_STATE (THRADD_HOSTILE_STACK_4) == 0) + Response (how_impressed_urquan_1, ThraddHostile); + else + Response (how_impressed_urquan_2, ThraddHostile); + } + if (GET_GAME_STATE (THRADD_HOSTILE_STACK_5) == 0) + Response (bye_hostile_1, ExitConversation); + else + Response (bye_hostile_2, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (AQUA_HELIX)) + { + NumVisits = GET_GAME_STATE (HELIX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (DIE_THIEF_1); + break; + case 1: + NPCPhrase (DIE_THIEF_2); + --NumVisits; + break; + } + SET_GAME_STATE (HELIX_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) + { + NumVisits = GET_GAME_STATE (THRADD_VISITS); + if (GET_GAME_STATE (THRADD_MANNER)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (HAVING_FUN_WITH_ILWRATH_1); + break; + case 1: + NPCPhrase (HAVING_FUN_WITH_ILWRATH_2); + --NumVisits; + break; + } + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (GO_AWAY_FIGHTING_ILWRATH_1); + break; + case 1: + NPCPhrase (GO_AWAY_FIGHTING_ILWRATH_2); + --NumVisits; + break; + } + } + SET_GAME_STATE (THRADD_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (GET_GAME_STATE (THRADD_MANNER)) + { + RESPONSE_REF pStr0, pStr1; + + NumVisits = GET_GAME_STATE (THRADD_VISITS); + switch (GET_GAME_STATE (THRADD_INTRO)) + { + case 0: + PolitePhrase (NumVisits); + break; + case 1: + RhymePhrase (NumVisits); + break; + case 2: + PigLatinPhrase (NumVisits); + break; + case 3: + LikeYouPhrase (NumVisits); + break; + } + if (++NumVisits < 4) + { + SET_GAME_STATE (THRADD_VISITS, NumVisits); + } + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + pStr0 = WELCOME_HELIX0; + pStr1 = WELCOME_HELIX1; + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + pStr0 = WELCOME_HOMEWORLD0; + pStr1 = WELCOME_HOMEWORLD1; + } + else + { + pStr0 = WELCOME_SPACE0; + pStr1 = WELCOME_SPACE1; + } + NPCPhrase (pStr0); + NPCPhrase (GetCultureName ()); + NPCPhrase (pStr1); + + ThraddAllies ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (HELIX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HELIX_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_HELIX_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (HELIX_VISITS, NumVisits); + + HelixWorld ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (THRADDASH_BODY_COUNT) >= THRADDASH_BODY_THRESHOLD) + { + NPCPhrase (AMAZING_PERFORMANCE); + + ThraddWorship ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (THRADDASH_BODY_COUNT); + if (NumVisits >= 16 + && GET_GAME_STATE (THRADD_BODY_LEVEL) == 1) + { + SET_GAME_STATE (THRADD_BODY_LEVEL, 2); + NPCPhrase (IMPRESSIVE_PERFORMANCE); + } + else if (NumVisits >= 8 + && GET_GAME_STATE (THRADD_BODY_LEVEL) == 0) + { + SET_GAME_STATE (THRADD_BODY_LEVEL, 1); + NPCPhrase (ADEQUATE_PERFORMANCE); + } + + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (THRADD_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (THRADD_HOME_VISITS, NumVisits); + } + else if ((NumVisits = GET_GAME_STATE (THRADD_MISSION)) == 0 + || NumVisits > 3) + { + NumVisits = GET_GAME_STATE (THRADD_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_SPACE_HELLO_2); + break; + case 2: + NPCPhrase (HOSTILE_SPACE_HELLO_3); + break; + case 3: + NPCPhrase (HOSTILE_SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (THRADD_VISITS, NumVisits); + } + else + { + switch (NumVisits) + { + case 1: + if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) + NPCPhrase (WE_GO_TO_IMPRESS_URQUAN_1); + else + NPCPhrase (WE_GO_TO_IMPRESS_URQUAN_2); + break; + case 2: + if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) + NPCPhrase (WE_IMPRESSING_URQUAN_1); + else + NPCPhrase (WE_IMPRESSING_URQUAN_2); + break; + case 3: + if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) + NPCPhrase (WE_IMPRESSED_URQUAN_1); + else + NPCPhrase (WE_IMPRESSED_URQUAN_2); + break; + } + SET_GAME_STATE (THRADD_MISSION_VISITS, 1); + } + + ThraddHostile ((RESPONSE_REF)0); + } + } +ExitIntro: + ; +} + +static COUNT +uninit_thradd (void) +{ + return (0); +} + +LOCDATAPTR +init_thradd_comm (void) +{ + LOCDATAPTR retval; + + thradd_desc.init_encounter_func = Intro; + thradd_desc.uninit_encounter_func = uninit_thradd; + + thradd_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + thradd_desc.AlienTextTemplate.baseline.y = 0; + thradd_desc.AlienTextTemplate.align = ALIGN_CENTER; + thradd_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (THRADD_MANNER) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &thradd_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/umgah/ifontres.h b/sc2/src/sc2code/comm/umgah/ifontres.h new file mode 100644 index 000000000..e8d0f0fa0 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/ifontres.h @@ -0,0 +1,3 @@ +#define UMGAH_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/umgah/igfxres.h b/sc2/src/sc2code/comm/umgah/igfxres.h new file mode 100644 index 000000000..ef784dbdc --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/igfxres.h @@ -0,0 +1,3 @@ +#define UMGAH_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/umgah/imusicre.h b/sc2/src/sc2code/comm/umgah/imusicre.h new file mode 100644 index 000000000..ccc24ceb6 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/imusicre.h @@ -0,0 +1,3 @@ +#define UMGAH_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/umgah/istrtab.h b/sc2/src/sc2code/comm/umgah/istrtab.h new file mode 100644 index 000000000..e8db92e9c --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/istrtab.h @@ -0,0 +1,3 @@ +#define UMGAH_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/umgah/resinst.h b/sc2/src/sc2code/comm/umgah/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/umgah/respkg.h b/sc2/src/sc2code/comm/umgah/respkg.h new file mode 100644 index 000000000..69b1a810d --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/respkg.h @@ -0,0 +1,5 @@ +enum +{ + UMGAH_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/umgah/restypes.h b/sc2/src/sc2code/comm/umgah/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/umgah/strings.h b/sc2/src/sc2code/comm/umgah/strings.h new file mode 100644 index 000000000..a56ca82e7 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/strings.h @@ -0,0 +1,114 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HWLD_PRE_ZOMBIE_HELLO_1, + HWLD_PRE_ZOMBIE_HELLO_2, + HWLD_PRE_ZOMBIE_HELLO_3, + HWLD_PRE_ZOMBIE_HELLO_4, + SPACE_PRE_ZOMBIE_HELLO_1, + SPACE_PRE_ZOMBIE_HELLO_2, + SPACE_PRE_ZOMBIE_HELLO_3, + SPACE_PRE_ZOMBIE_HELLO_4, + UNKNOWN_ZOMBIE_HELLO_1, + UNKNOWN_ZOMBIE_HELLO_2, + UNKNOWN_ZOMBIE_HELLO_3, + UNKNOWN_ZOMBIE_HELLO_4, + DESTROY_INTERFERER_1, + DESTROY_INTERFERER_2, + DESTROY_INTERFERER_3, + DESTROY_INTERFERER_4, + REVEALED_ZOMBIE_HELLO_1, + REVEALED_ZOMBIE_HELLO_2, + REVEALED_ZOMBIE_HELLO_3, + REVEALED_ZOMBIE_HELLO_4, + HOSTILE_HELLO_1, + HOSTILE_HELLO_2, + HOSTILE_HELLO_3, + HOSTILE_HELLO_4, + REWARD_AT_HOMEWORLD_1, + REWARD_AT_HOMEWORLD_2, + POST_ZOMBIE_HWLD_HELLO, + owe_me_big_time, + our_largesse, + GIVE_LIFEDATA, + THANKS, + what_do_with_tpet, + TRICK_URQUAN, + any_jokes, + SURE, + what_before_tpet, + TRKD_SPATHI_AND_ILWRATH, + where_caster, + SPATHI_TOOK_THEM, + so_what_for_now, + DO_THIS_NOW, + bye_post_zombie, + FUNNY_IDEA, + whats_up_pre_zombie, + GENERAL_INFO_PRE_ZOMBIE, + evil_blobbies_give_up, + NOT_EVIL_BLOBBIES, + evil_blobbies_must_die, + OH_NO_WE_WONT, + can_we_be_friends, + SURE_FRIENDS, + want_to_defeat_urquan, + FINE_BY_US, + bye_pre_zombie, + GOODBYE_PRE_ZOMBIE, + threat, + NO_THREAT, + whats_up_zombies, + GENERAL_INFO_ZOMBIE, + how_goes_tpet, + WHAT_TPET, + you_told_us, + SADLY_IT_DIED, + dont_believe, + THEN_DIE, + bye_unknown, + GOODBYE_UNKNOWN, + evil_blobbies, + YES_VERY_EVIL, + give_up_or_die, + NOT_GIVE_UP, + we_vindicator0, + we_vindicator1, + we_vindicator2, + GOOD_FOR_YOU_1, + come_in_peace, + GOOD_FOR_YOU_2, + know_any_jokes, + JOKE_1, + better_joke, + JOKE_2, + not_very_funny, + YES_WE_ARE, + what_about_tpet, + arilou_told_us, + bye_zombie, + GOODBYE_ZOMBIE, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/umgah/umgah.res b/sc2/src/sc2code/comm/umgah/umgah.res new file mode 100644 index 000000000..d5c4a5a67 --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/umgah.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/umgah + +PACKAGE UMGAH_PACKAGE umgah.con + GFXRES UMGAH_PMAP_ANIM umgah.ani + FONTRES UMGAH_FONT umgah.fon + MUSICRES UMGAH_MUSIC umgah.mod + STRTAB UMGAH_CONVERSATION_PHRASES umgah.txt + diff --git a/sc2/src/sc2code/comm/umgah/umgahc.c b/sc2/src/sc2code/comm/umgah/umgahc.c new file mode 100644 index 000000000..f938163fd --- /dev/null +++ b/sc2/src/sc2code/comm/umgah/umgahc.c @@ -0,0 +1,710 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/umgah/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/umgah/strings.h" + +static LOCDATA umgah_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)UMGAH_PMAP_ANIM, /* AlienFrame */ + (FONT)UMGAH_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + UMGAH_MUSIC, /* AlienSong */ + UMGAH_CONVERSATION_PHRASES, /* PlayerPhrases */ + 16, /* NumAnimations */ + { + { + 5, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), + }, + { + 8, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 6), + }, + { + 11, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 7), + }, + { + 13, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 8), + }, + { + 15, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 9), + }, + { + 17, /* StartIndex */ + 3, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 14, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ + (1 << 0), + }, + { + 20, /* StartIndex */ + 3, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 14, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ + (1 << 1), + }, + { + 23, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 14, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ + (1 << 2), + }, + { + 25, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 14, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ + (1 << 3), + }, + { + 27, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 14, 0, /* FrameRate */ + ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ + (1 << 4), + }, + { + 29, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 32, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 35, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 40, /* StartIndex */ + 6, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, 0, /* RestartRate */ + }, + { + 46, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 24, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 15), /* BlockMask */ + }, + { + 48, /* StartIndex */ + 2, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 24, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 14), /* BlockMask */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 4, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye_zombie)) + { + NPCPhrase (GOODBYE_ZOMBIE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, bye_pre_zombie)) + NPCPhrase (GOODBYE_PRE_ZOMBIE); + else if (PLAYER_SAID (R, can_we_be_friends)) + { + NPCPhrase (SURE_FRIENDS); + + SET_GAME_STATE (UMGAH_MENTIONED_TRICKS, 1); + } + else if (PLAYER_SAID (R, evil_blobbies_give_up)) + { + NPCPhrase (NOT_EVIL_BLOBBIES); + + SET_GAME_STATE (UMGAH_EVIL_BLOBBIES, 1); + } + else if (PLAYER_SAID (R, evil_blobbies_must_die)) + NPCPhrase (OH_NO_WE_WONT); + else if (PLAYER_SAID (R, threat)) + NPCPhrase (NO_THREAT); + else if (PLAYER_SAID (R, dont_believe)) + { + NPCPhrase (THEN_DIE); + + SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); + SET_GAME_STATE (UMGAH_VISITS, 0); + } + else if (PLAYER_SAID (R, bye_unknown)) + { + NPCPhrase (GOODBYE_UNKNOWN); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, bye_post_zombie)) + { + NPCPhrase (FUNNY_IDEA); + + AlienTalkSegue ((COUNT)~0); + ActivateStarShip (UMGAH_SHIP, 4); + SET_GAME_STATE (UMGAH_HOSTILE, 1); + } +} + +static void +Zombies (RESPONSE_REF R) +{ + if (GET_GAME_STATE (MET_NORMAL_UMGAH)) + { + if (PLAYER_SAID (R, whats_up_zombies)) + { + NPCPhrase (GENERAL_INFO_ZOMBIE); + + DISABLE_PHRASE (whats_up_zombies); + } + else if (PLAYER_SAID (R, how_goes_tpet)) + { + NPCPhrase (WHAT_TPET); + + DISABLE_PHRASE (how_goes_tpet); + } + else if (PLAYER_SAID (R, you_told_us)) + { + NPCPhrase (SADLY_IT_DIED); + + DISABLE_PHRASE (you_told_us); + } + + if (PHRASE_ENABLED (whats_up_zombies) && PHRASE_ENABLED (how_goes_tpet)) + Response (whats_up_zombies, Zombies); + if (PHRASE_ENABLED (how_goes_tpet)) + Response (how_goes_tpet, Zombies); + else if (PHRASE_ENABLED (you_told_us)) + Response (you_told_us, Zombies); + else + { + Response (dont_believe, CombatIsInevitable); + } + if (PHRASE_ENABLED (whats_up_zombies) && !PHRASE_ENABLED (how_goes_tpet)) + Response (whats_up_zombies, Zombies); + Response (threat, CombatIsInevitable); + Response (bye_unknown, CombatIsInevitable); + } + else + { + BYTE i, LastStack; + RESPONSE_REF pStr[4]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; + if (PLAYER_SAID (R, evil_blobbies)) + { + NPCPhrase (YES_VERY_EVIL); + + DISABLE_PHRASE (evil_blobbies); + LastStack = 0; + } + else if (PLAYER_SAID (R, we_vindicator0)) + { + NPCPhrase (GOOD_FOR_YOU_1); + + DISABLE_PHRASE (we_vindicator0); + LastStack = 1; + } + else if (PLAYER_SAID (R, come_in_peace)) + { + NPCPhrase (GOOD_FOR_YOU_2); + + DISABLE_PHRASE (come_in_peace); + LastStack = 1; + } + else if (PLAYER_SAID (R, know_any_jokes)) + { + NPCPhrase (JOKE_1); + + DISABLE_PHRASE (know_any_jokes); + LastStack = 2; + } + else if (PLAYER_SAID (R, better_joke)) + { + NPCPhrase (JOKE_2); + + DISABLE_PHRASE (better_joke); + LastStack = 2; + } + else if (PLAYER_SAID (R, not_very_funny)) + { + NPCPhrase (YES_WE_ARE); + + DISABLE_PHRASE (not_very_funny); + LastStack = 2; + } + else if (PLAYER_SAID (R, what_about_tpet)) + { + NPCPhrase (WHAT_TPET); + + DISABLE_PHRASE (what_about_tpet); + LastStack = 3; + } + else if (PLAYER_SAID (R, give_up_or_die)) + { + NPCPhrase (NOT_GIVE_UP); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + goto ExitZombies; + } + else if (PLAYER_SAID (R, arilou_told_us)) + { + NPCPhrase (THEN_DIE); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); + SET_GAME_STATE (UMGAH_VISITS, 0); + goto ExitZombies; + } + + if (PHRASE_ENABLED (evil_blobbies)) + pStr[0] = evil_blobbies; + else + pStr[0] = give_up_or_die; + + if (PHRASE_ENABLED (we_vindicator0)) + { + construct_response (shared_phrase_buf, + we_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_vindicator1, + GLOBAL_SIS (ShipName), + we_vindicator2, + 0); + pStr[1] = we_vindicator0; + } + else if (PHRASE_ENABLED (come_in_peace)) + pStr[1] = come_in_peace; + + if (PHRASE_ENABLED (know_any_jokes)) + pStr[2] = know_any_jokes; + else if (PHRASE_ENABLED (better_joke)) + pStr[2] = better_joke; + else if (PHRASE_ENABLED (not_very_funny)) + pStr[2] = not_very_funny; + + if (PHRASE_ENABLED (what_about_tpet)) + pStr[3] = what_about_tpet; + else + pStr[3] = arilou_told_us; + + if (pStr[LastStack]) + { + if (pStr[LastStack] != we_vindicator0) + Response (pStr[LastStack], Zombies); + else + DoResponsePhrase (pStr[LastStack], Zombies, shared_phrase_buf); + } + for (i = 0; i < 4; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != we_vindicator0) + Response (pStr[i], Zombies); + else + DoResponsePhrase (pStr[i], Zombies, shared_phrase_buf); + } + } + Response (bye_zombie, CombatIsInevitable); +ExitZombies: + ; + } +} + +static void +NormalUmgah (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, whats_up_pre_zombie)) + { + NPCPhrase (GENERAL_INFO_PRE_ZOMBIE); + + DISABLE_PHRASE (whats_up_pre_zombie); + } + else if (PLAYER_SAID (R, want_to_defeat_urquan)) + { + NPCPhrase (FINE_BY_US); + + DISABLE_PHRASE (want_to_defeat_urquan); + } + + if (!GET_GAME_STATE (UMGAH_EVIL_BLOBBIES)) + Response (evil_blobbies_give_up, CombatIsInevitable); + else + Response (evil_blobbies_must_die, CombatIsInevitable); + if (PHRASE_ENABLED (whats_up_pre_zombie)) + Response (whats_up_pre_zombie, NormalUmgah); + if (PHRASE_ENABLED (want_to_defeat_urquan)) + Response (want_to_defeat_urquan, NormalUmgah); + switch (GET_GAME_STATE (UMGAH_MENTIONED_TRICKS)) + { + case 0: + Response (can_we_be_friends, CombatIsInevitable); + break; + } + Response (bye_pre_zombie, CombatIsInevitable); +} + +static void +UmgahReward (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, what_before_tpet)) + { + NPCPhrase (TRKD_SPATHI_AND_ILWRATH); + + DISABLE_PHRASE (what_before_tpet); + } + else if (PLAYER_SAID (R, where_caster)) + { + NPCPhrase (SPATHI_TOOK_THEM); + + DISABLE_PHRASE (where_caster); + } + else if (PLAYER_SAID (R, owe_me_big_time)) + { + NPCPhrase (GIVE_LIFEDATA); + + GLOBAL_SIS (TotalBioMass) += 1000 / BIO_CREDIT_VALUE; + DISABLE_PHRASE (owe_me_big_time); + DISABLE_PHRASE (our_largesse); + } + else if (PLAYER_SAID (R, our_largesse)) + { + NPCPhrase (THANKS); + + GLOBAL_SIS (TotalBioMass) += 1000 / BIO_CREDIT_VALUE; + DISABLE_PHRASE (our_largesse); + DISABLE_PHRASE (owe_me_big_time); + } + else if (PLAYER_SAID (R, what_do_with_tpet)) + { + NPCPhrase (TRICK_URQUAN); + + DISABLE_PHRASE (what_do_with_tpet); + } + else if (PLAYER_SAID (R, any_jokes)) + { + NPCPhrase (SURE); + + DISABLE_PHRASE (any_jokes); + } + else if (PLAYER_SAID (R, so_what_for_now)) + { + NPCPhrase (DO_THIS_NOW); + + DISABLE_PHRASE (so_what_for_now); + } + + if (!GET_GAME_STATE (MET_NORMAL_UMGAH)) + { + if (PHRASE_ENABLED (what_before_tpet)) + Response (what_before_tpet, UmgahReward); + else if (PHRASE_ENABLED (where_caster)) + Response (where_caster, UmgahReward); + } + if (PHRASE_ENABLED (owe_me_big_time)) + { + Response (owe_me_big_time, UmgahReward); + Response (our_largesse, UmgahReward); + } + if (PHRASE_ENABLED (what_do_with_tpet)) + Response (what_do_with_tpet, UmgahReward); + else if (PHRASE_ENABLED (any_jokes) && GET_GAME_STATE (UMGAH_MENTIONED_TRICKS) < 2) + Response (any_jokes, UmgahReward); + if (PHRASE_ENABLED (so_what_for_now)) + Response (so_what_for_now, UmgahReward); + Response (bye_post_zombie, CombatIsInevitable); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (GET_GAME_STATE (UMGAH_HOSTILE)) + { + NumVisits = GET_GAME_STATE (UMGAH_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_HELLO_2); + break; + case 2: + NPCPhrase (HOSTILE_HELLO_3); + break; + case 3: + NPCPhrase (HOSTILE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (UMGAH_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) + { + NumVisits = GET_GAME_STATE (UMGAH_VISITS); + if (GET_GAME_STATE (TALKING_PET_VISITS)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (DESTROY_INTERFERER_1); + break; + case 1: + NPCPhrase (DESTROY_INTERFERER_2); + break; + case 2: + NPCPhrase (DESTROY_INTERFERER_3); + break; + case 3: + NPCPhrase (DESTROY_INTERFERER_4); + --NumVisits; + break; + } + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (REVEALED_ZOMBIE_HELLO_1); + break; + case 1: + NPCPhrase (REVEALED_ZOMBIE_HELLO_2); + break; + case 2: + NPCPhrase (REVEALED_ZOMBIE_HELLO_3); + break; + case 3: + NPCPhrase (REVEALED_ZOMBIE_HELLO_4); + --NumVisits; + break; + } + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (UNKNOWN_ZOMBIE_HELLO_1); + break; + case 1: + NPCPhrase (UNKNOWN_ZOMBIE_HELLO_2); + break; + case 2: + NPCPhrase (UNKNOWN_ZOMBIE_HELLO_3); + break; + case 3: + NPCPhrase (UNKNOWN_ZOMBIE_HELLO_4); + --NumVisits; + break; + } + + Zombies ((RESPONSE_REF)0); + } + SET_GAME_STATE (UMGAH_VISITS, NumVisits); + } + else if (!GET_GAME_STATE (TALKING_PET)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (UMGAH_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_1); + break; + case 1: + NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_2); + break; + case 2: + NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_3); + break; + case 3: + NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (UMGAH_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (UMGAH_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_1); + break; + case 1: + NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_2); + break; + case 2: + NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_3); + break; + case 3: + NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (UMGAH_VISITS, NumVisits); + } + + NormalUmgah ((RESPONSE_REF)0); + } + else + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NPCPhrase (POST_ZOMBIE_HWLD_HELLO); + + UmgahReward ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (UMGAH_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (REWARD_AT_HOMEWORLD_1); + break; + case 1: + NPCPhrase (REWARD_AT_HOMEWORLD_2); + --NumVisits; + break; + } + SET_GAME_STATE (UMGAH_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + } +} + +static COUNT +uninit_umgah (void) +{ + if (!GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) + { + SET_GAME_STATE (MET_NORMAL_UMGAH, 1); + } + + return (0); +} + +LOCDATAPTR +init_umgah_comm (void) +{ + LOCDATAPTR retval; + + umgah_desc.init_encounter_func = Intro; + umgah_desc.uninit_encounter_func = uninit_umgah; + + umgah_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + umgah_desc.AlienTextTemplate.baseline.y = 0; + umgah_desc.AlienTextTemplate.align = ALIGN_CENTER; + umgah_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if ((GET_GAME_STATE (TALKING_PET) && !GET_GAME_STATE (UMGAH_HOSTILE)) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &umgah_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/urquan/icode.h b/sc2/src/sc2code/comm/urquan/icode.h new file mode 100644 index 000000000..6451bef6d --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/icode.h @@ -0,0 +1,4 @@ +#define URQUAN_CODE 0x00200006L + +typedef RESOURCE CODE_INSTANCE; + diff --git a/sc2/src/sc2code/comm/urquan/ifontres.h b/sc2/src/sc2code/comm/urquan/ifontres.h new file mode 100644 index 000000000..20cfd6779 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/ifontres.h @@ -0,0 +1,3 @@ +#define URQUAN_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/urquan/igfxres.h b/sc2/src/sc2code/comm/urquan/igfxres.h new file mode 100644 index 000000000..d0be042ed --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/igfxres.h @@ -0,0 +1,3 @@ +#define URQUAN_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/urquan/imusicre.h b/sc2/src/sc2code/comm/urquan/imusicre.h new file mode 100644 index 000000000..3ea6b103c --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/imusicre.h @@ -0,0 +1,3 @@ +#define URQUAN_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/urquan/istrtab.h b/sc2/src/sc2code/comm/urquan/istrtab.h new file mode 100644 index 000000000..eb74ec457 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/istrtab.h @@ -0,0 +1,3 @@ +#define URQUAN_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/urquan/resinst.h b/sc2/src/sc2code/comm/urquan/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/urquan/respkg.h b/sc2/src/sc2code/comm/urquan/respkg.h new file mode 100644 index 000000000..58fbb6fb6 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/respkg.h @@ -0,0 +1,5 @@ +enum +{ + URQUAN_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/urquan/restypes.h b/sc2/src/sc2code/comm/urquan/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/urquan/strings.h b/sc2/src/sc2code/comm/urquan/strings.h new file mode 100644 index 000000000..6a21fd2dc --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/strings.h @@ -0,0 +1,100 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HELLO_SAMATRA, + SENSE_EVIL, + INIT_URQUAN_WAKE_UP, + where_am_i, + YOU_ARE_HERE, + why_does_my_head_hurt, + HURTS_BECAUSE, + what_about_2_weeks, + ABOUT_2_WEEKS, + compulsion, + WHAT_COMPULSION, + wascally_little_guy, + WHAT_IT_LOOK_LIKE, + terran_amphibian, + talking_pet_on_steroids, + BAD_NEWS, + turd_and_toad, + WHAT_IS_TURD_AND_TOAD, + alien_mind_control, + WHAT_FELT_LIKE, + possessed_by_devil, + STUPID_DEVIL, + falling_asleep, + someone_else_controlled, + SOUNDS_FAMILIAR, + before_coffee, + EXPLAIN, + why_explain, + MUST_EXPLAIN, + bye_init_hypno, + GOODBYE_AND_DIE_INIT_HYPNO, + SUBSEQUENT_URQUAN_WAKE_UP, + uh_oh, + NO_UH_OH, + stop_meeting, + NO_STOP_MEETING, + bye_sub_hypno, + GOODBYE_AND_DIE_SUB_HYPNO, + CAUGHT_YA, + INIT_FLEE_HUMAN, + SUBSEQUENT_FLEE_HUMAN, + why_flee, + FLEE_BECAUSE, + what_happens_now, + HAPPENS_NOW, + what_about_you, + ABOUT_US, + bye_wars_over, + GOODBYE_WARS_OVER, + SEND_MESSAGE, + INIT_HELLO, + SUBSEQUENT_HELLO_1, + SUBSEQUENT_HELLO_2, + SUBSEQUENT_HELLO_3, + SUBSEQUENT_HELLO_4, + you_must_surrender, + NOPE, + i_surrender, + DISOBEDIENCE_PUNISHED, + i_wont_surrender, + BAD_CHOICE, + i_will_surrender, + GOOD_CHOICE, + key_phrase, + URQUAN_STORY, + like_to_leave, + INDEPENDENCE_IS_BAD, + whats_up_1, + GENERAL_INFO_1, + whats_up_2, + GENERAL_INFO_2, + whats_up_3, + GENERAL_INFO_3, + whats_up_4, + GENERAL_INFO_4, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/urquan/urquan.res b/sc2/src/sc2code/comm/urquan/urquan.res new file mode 100644 index 000000000..0ef33fab4 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/urquan.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/urquan + +PACKAGE URQUAN_PACKAGE urquan.con + GFXRES URQUAN_PMAP_ANIM urquan.ani + FONTRES URQUAN_FONT urquan.fon + MUSICRES URQUAN_MUSIC urquan.mod + STRTAB URQUAN_CONVERSATION_PHRASES urquan.txt + diff --git a/sc2/src/sc2code/comm/urquan/urquanc.c b/sc2/src/sc2code/comm/urquan/urquanc.c new file mode 100644 index 000000000..06bcaf592 --- /dev/null +++ b/sc2/src/sc2code/comm/urquan/urquanc.c @@ -0,0 +1,556 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/urquan/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/urquan/strings.h" + +static LOCDATA urquan_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)URQUAN_PMAP_ANIM, /* AlienFrame */ + (FONT)URQUAN_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + URQUAN_MUSIC, /* AlienSong */ + URQUAN_CONVERSATION_PHRASES, /* PlayerPhrases */ + 7, /* NumAnimations */ + { + { + 7, /* StartIndex */ + 6, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 12, 0, /* FrameRate */ + 12, 0, /* RestartRate */ + }, + { + 13, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 16, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 19, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 29, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 36, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 1, /* StartIndex */ + 2, /* NumFrames */ + 0, /* AnimFlags */ + 20, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 2, /* StartIndex */ + 5, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, you_must_surrender)) + NPCPhrase (NOPE); + else if (PLAYER_SAID (R, whats_up_1) + || PLAYER_SAID (R, whats_up_2) + || PLAYER_SAID (R, whats_up_3) + || PLAYER_SAID (R, whats_up_4)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (URQUAN_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_4); + --NumVisits; + break; + } + SET_GAME_STATE (URQUAN_INFO, NumVisits); + } + else if (PLAYER_SAID (R, i_wont_surrender)) + NPCPhrase (BAD_CHOICE); + else if (PLAYER_SAID (R, i_will_surrender)) + { + NPCPhrase (GOOD_CHOICE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; + GLOBAL (CurrentActivity) |= CHECK_RESTART; + } + else if (PLAYER_SAID (R, like_to_leave)) + NPCPhrase (INDEPENDENCE_IS_BAD); + else if (PLAYER_SAID (R, bye_wars_over)) + { + NPCPhrase (GOODBYE_WARS_OVER); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, bye_sub_hypno)) + NPCPhrase (GOODBYE_AND_DIE_SUB_HYPNO); + else if (PLAYER_SAID (R, bye_init_hypno)) + { + NPCPhrase (GOODBYE_AND_DIE_INIT_HYPNO); + + SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); + } + else if (PLAYER_SAID (R, terran_amphibian) + || PLAYER_SAID (R, talking_pet_on_steroids)) + { + NPCPhrase (BAD_NEWS); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); + } + else if (PLAYER_SAID (R, falling_asleep) + || PLAYER_SAID (R, someone_else_controlled)) + { + NPCPhrase (SOUNDS_FAMILIAR); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); + } +} + +static void +DescribePet (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, wascally_little_guy)) + NPCPhrase (WHAT_IT_LOOK_LIKE); + else if (PLAYER_SAID (R, turd_and_toad)) + { + NPCPhrase (WHAT_IS_TURD_AND_TOAD); + + DISABLE_PHRASE (turd_and_toad); + } + + Response (terran_amphibian, CombatIsInevitable); + Response (talking_pet_on_steroids, CombatIsInevitable); + if (PHRASE_ENABLED (turd_and_toad)) + { + Response (turd_and_toad, DescribePet); + } +} + +static void +DescribeCompulsion (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, alien_mind_control)) + NPCPhrase (WHAT_FELT_LIKE); + else if (PLAYER_SAID (R, before_coffee)) + { + NPCPhrase (EXPLAIN); + + DISABLE_PHRASE (before_coffee); + } + + Response (falling_asleep, CombatIsInevitable); + Response (someone_else_controlled, CombatIsInevitable); + if (PHRASE_ENABLED (before_coffee)) + { + Response (before_coffee, DescribeCompulsion); + } +} + +static void +MentionCompulsion (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, compulsion)) + { + NPCPhrase (WHAT_COMPULSION); + + SET_GAME_STATE (MENTIONED_PET_COMPULSION, 1); + } + else if (PLAYER_SAID (R, possessed_by_devil)) + { + NPCPhrase (STUPID_DEVIL); + + DISABLE_PHRASE (possessed_by_devil); + } + else if (PLAYER_SAID (R, why_explain)) + { + NPCPhrase (MUST_EXPLAIN); + + DISABLE_PHRASE (why_explain); + } + + Response (wascally_little_guy, DescribePet); + Response (alien_mind_control, DescribeCompulsion); + if (PHRASE_ENABLED (possessed_by_devil)) + Response (possessed_by_devil, MentionCompulsion); + if (PHRASE_ENABLED (why_explain)) + Response (why_explain, MentionCompulsion); +} + +static void +UrquanHypno (RESPONSE_REF R) +{ + if (GET_GAME_STATE (URQUAN_HYPNO_VISITS) == 0) + { + if (R == 0) + NPCPhrase (INIT_URQUAN_WAKE_UP); + else if (PLAYER_SAID (R, where_am_i)) + { + NPCPhrase (YOU_ARE_HERE); + + DISABLE_PHRASE (where_am_i); + } + else if (PLAYER_SAID (R, why_does_my_head_hurt)) + { + NPCPhrase (HURTS_BECAUSE); + + DISABLE_PHRASE (why_does_my_head_hurt); + } + else if (PLAYER_SAID (R, what_about_2_weeks)) + { + NPCPhrase (ABOUT_2_WEEKS); + + DISABLE_PHRASE (what_about_2_weeks); + } + + if (PHRASE_ENABLED (where_am_i)) + Response (where_am_i, UrquanHypno); + if (PHRASE_ENABLED (why_does_my_head_hurt)) + Response (why_does_my_head_hurt, UrquanHypno); + if (PHRASE_ENABLED (what_about_2_weeks)) + Response (what_about_2_weeks, UrquanHypno); + Response (compulsion, MentionCompulsion); + Response (bye_init_hypno, CombatIsInevitable); + } + else + { + if (R == 0) + NPCPhrase (SUBSEQUENT_URQUAN_WAKE_UP); + else if (PLAYER_SAID (R, uh_oh)) + { + NPCPhrase (NO_UH_OH); + + DISABLE_PHRASE (uh_oh); + } + else if (PLAYER_SAID (R, stop_meeting)) + { + NPCPhrase (NO_STOP_MEETING); + + DISABLE_PHRASE (stop_meeting); + } + + if (PHRASE_ENABLED (uh_oh)) + Response (uh_oh, UrquanHypno); + if (PHRASE_ENABLED (stop_meeting)) + Response (stop_meeting, UrquanHypno); + if (!GET_GAME_STATE (MENTIONED_PET_COMPULSION)) + { + Response (compulsion, MentionCompulsion); + } + Response (bye_sub_hypno, CombatIsInevitable); + } +} + +static void +NormalUrquan (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, i_surrender)) + { + NPCPhrase (DISOBEDIENCE_PUNISHED); + + Response (i_wont_surrender, CombatIsInevitable); + Response (i_will_surrender, CombatIsInevitable); + } + else + { + if (PLAYER_SAID (R, key_phrase)) + { + NPCPhrase (URQUAN_STORY); + + SET_GAME_STATE (KNOW_URQUAN_STORY, 2); + } + + Response (you_must_surrender, CombatIsInevitable); + if (GET_GAME_STATE (KNOW_URQUAN_STORY) == 1) + { + Response (key_phrase, NormalUrquan); + } + switch (GET_GAME_STATE (URQUAN_INFO)) + { + case 0: + Response (whats_up_1, CombatIsInevitable); + break; + case 1: + Response (whats_up_2, CombatIsInevitable); + break; + case 2: + Response (whats_up_3, CombatIsInevitable); + break; + case 3: + Response (whats_up_4, CombatIsInevitable); + break; + } + Response (i_surrender, NormalUrquan); + Response (like_to_leave, CombatIsInevitable); + } +} + +static void +LoserUrquan (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, why_flee)) + { + NPCPhrase (FLEE_BECAUSE); + + DISABLE_PHRASE (why_flee); + } + else if (PLAYER_SAID (R, what_happens_now)) + { + NPCPhrase (HAPPENS_NOW); + + DISABLE_PHRASE (what_happens_now); + } + else if (PLAYER_SAID (R, what_about_you)) + { + NPCPhrase (ABOUT_US); + + DISABLE_PHRASE (what_about_you); + } + + if (PHRASE_ENABLED (why_flee)) + Response (why_flee, LoserUrquan); + if (PHRASE_ENABLED (what_happens_now)) + Response (what_happens_now, LoserUrquan); + if (PHRASE_ENABLED (what_about_you)) + Response (what_about_you, LoserUrquan); + Response (bye_wars_over, CombatIsInevitable); +} + +static void +Intro (void) +{ + BYTE b0, b1, b2, b3; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + b0 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS0); + b1 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS1); + b2 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS2); + b3 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS3); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && GLOBAL (BattleGroupRef) + && GLOBAL (BattleGroupRef) == MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + )) + { + NPCPhrase (SEND_MESSAGE); + SET_GAME_STATE (PROBE_MESSAGE_DELIVERED, 1); + } + else if (GET_GAME_STATE (PLAYER_HYPNOTIZED)) + { + UrquanHypno ((RESPONSE_REF)0); + } + else + { + BYTE NumVisits; + + if (!GET_GAME_STATE (URQUAN_SENSES_EVIL) + && GET_GAME_STATE (TALKING_PET_ON_SHIP)) + { + NPCPhrase (SENSE_EVIL); + SET_GAME_STATE (URQUAN_SENSES_EVIL, 1); + } + + b0 = GET_GAME_STATE (COLONY_GRPOFFS0); + b1 = GET_GAME_STATE (COLONY_GRPOFFS1); + b2 = GET_GAME_STATE (COLONY_GRPOFFS2); + b3 = GET_GAME_STATE (COLONY_GRPOFFS3); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && GLOBAL (BattleGroupRef) + && GLOBAL (BattleGroupRef) == MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + )) + { + NPCPhrase (CAUGHT_YA); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + goto ExitIntro; + } + + b0 = GET_GAME_STATE (SAMATRA_GRPOFFS0); + b1 = GET_GAME_STATE (SAMATRA_GRPOFFS1); + b2 = GET_GAME_STATE (SAMATRA_GRPOFFS2); + b3 = GET_GAME_STATE (SAMATRA_GRPOFFS3); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && GLOBAL (BattleGroupRef) + && GLOBAL (BattleGroupRef) == MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + )) + { + NPCPhrase (HELLO_SAMATRA); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + NumVisits = GET_GAME_STATE (URQUAN_VISITS); + if (!GET_GAME_STATE (KOHR_AH_FRENZY)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_HELLO); + break; + case 1: + NPCPhrase (SUBSEQUENT_HELLO_1); + break; + case 2: + NPCPhrase (SUBSEQUENT_HELLO_2); + break; + case 3: + NPCPhrase (SUBSEQUENT_HELLO_3); + break; + case 4: + NPCPhrase (SUBSEQUENT_HELLO_4); + --NumVisits; + break; + } + + NormalUrquan ((RESPONSE_REF)0); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (INIT_FLEE_HUMAN); + LoserUrquan ((RESPONSE_REF)0); + break; + case 1: + NPCPhrase (SUBSEQUENT_FLEE_HUMAN); + SET_GAME_STATE (BATTLE_SEGUE, 0); + --NumVisits; + break; + } + } + SET_GAME_STATE (URQUAN_VISITS, NumVisits); + } + } +ExitIntro: + ; +} + +static COUNT +uninit_urquan (void) +{ + SET_GAME_STATE (PLAYER_HYPNOTIZED, 0); + + return (0); +} + +LOCDATAPTR +init_urquan_comm (void) +{ + LOCDATAPTR retval; + + BYTE b0, b1, b2, b3; + + urquan_desc.init_encounter_func = Intro; + urquan_desc.uninit_encounter_func = uninit_urquan; + + urquan_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + urquan_desc.AlienTextTemplate.baseline.y = 0; + urquan_desc.AlienTextTemplate.align = ALIGN_CENTER; + urquan_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + b0 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS0); + b1 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS1); + b2 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS2); + b3 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS3); + if (GET_GAME_STATE (PLAYER_HYPNOTIZED) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE + || (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && GLOBAL (BattleGroupRef) + && GLOBAL (BattleGroupRef) == MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ))) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &urquan_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/utwig/ifontres.h b/sc2/src/sc2code/comm/utwig/ifontres.h new file mode 100644 index 000000000..ff953a06d --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/ifontres.h @@ -0,0 +1,3 @@ +#define UTWIG_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/utwig/igfxres.h b/sc2/src/sc2code/comm/utwig/igfxres.h new file mode 100644 index 000000000..f37512565 --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/igfxres.h @@ -0,0 +1,3 @@ +#define UTWIG_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/utwig/imusicre.h b/sc2/src/sc2code/comm/utwig/imusicre.h new file mode 100644 index 000000000..0565a4d8d --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/imusicre.h @@ -0,0 +1,3 @@ +#define UTWIG_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/utwig/istrtab.h b/sc2/src/sc2code/comm/utwig/istrtab.h new file mode 100644 index 000000000..dcda816bf --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/istrtab.h @@ -0,0 +1,3 @@ +#define UTWIG_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/utwig/resinst.h b/sc2/src/sc2code/comm/utwig/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/utwig/respkg.h b/sc2/src/sc2code/comm/utwig/respkg.h new file mode 100644 index 000000000..b555f33c6 --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/respkg.h @@ -0,0 +1,5 @@ +enum +{ + UTWIG_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/utwig/restypes.h b/sc2/src/sc2code/comm/utwig/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/utwig/strings.h b/sc2/src/sc2code/comm/utwig/strings.h new file mode 100644 index 000000000..70543759e --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/strings.h @@ -0,0 +1,142 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + NEUTRAL_SPACE_HELLO_1, + NEUTRAL_SPACE_HELLO_2, + HOSTILE_SPACE_HELLO_1, + HOSTILE_SPACE_HELLO_2, + BOMB_WORLD_HELLO_1, + BOMB_WORLD_HELLO_2, + HOSTILE_BOMB_HELLO_1, + HOSTILE_BOMB_HELLO_2, + NEUTRAL_HOMEWORLD_HELLO_1, + NEUTRAL_HOMEWORLD_HELLO_2, + NEUTRAL_HOMEWORLD_HELLO_3, + NEUTRAL_HOMEWORLD_HELLO_4, + HOSTILE_HOMEWORLD_HELLO_1, + HOSTILE_HOMEWORLD_HELLO_2, + why_you_here, + WE_GUARD_BOMB, + what_about_bomb, + ABOUT_BOMB, + give_us_bomb_or_die, + GUARDS_WARN, + demand_bomb, + GUARDS_FIGHT, + may_we_have_bomb, + NO_BOMB, + please, + SORRY_NO_BOMB, + whats_up_bomb, + GENERAL_INFO_BOMB_1, + GENERAL_INFO_BOMB_2, + bye_bomb, + GOODBYE_BOMB, + hey_wait_got_ultron, + TAUNT_US_BUT_WE_LOOK, + TRICKED_US_1, + TRICKED_US_2, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + WOULD_BE_HAPPY_BUT, + why_sad, + ULTRON_BROKE, + what_ultron, + GLORIOUS_ULTRON, + dont_be_babies, + MOCK_OUR_PAIN, + real_sorry_about_ultron, + APPRECIATE_SYMPATHY, + what_about_you_1, + ABOUT_US_1, + what_about_you_2, + ABOUT_US_2, + what_about_you_3, + ABOUT_US_3, + what_about_urquan_1, + ABOUT_URQUAN_1, + what_about_urquan_2, + ABOUT_URQUAN_2, + got_ultron, + DONT_WANT_TO_LOOK, + SICK_TRICK_1, + SICK_TRICK_2, + bye_neutral, + GOODBYE_NEUTRAL, + TOO_LATE, + name_1, + name_2, + name_3, + name_40, + name_41, + HAPPY_DAYS, + OK_ATTACK_KOHRAH, + whats_up_after_space, + GENERAL_INFO_AFTER_SPACE_1, + GENERAL_INFO_AFTER_SPACE_2, + what_now_after_space, + DO_THIS_AFTER_SPACE, + bye_after_space, + GOODBYE_AFTER_SPACE, + whats_up_before_space, + GENERAL_INFO_BEFORE_SPACE_1, + GENERAL_INFO_BEFORE_SPACE_2, + what_now_before_space, + DO_THIS_BEFORE_SPACE, + bye_before_space, + GOODBYE_BEFORE_SPACE, + how_went_war, + ABOUT_BATTLE, + how_goes_war, + BATTLE_HAPPENS_1, + BATTLE_HAPPENS_2, + FLEET_ON_WAY, + learn_new_info, + NO_NEW_INFO, + SAMATRA, + what_now_homeworld, + HOPE_KILL_EACH_OTHER, + how_is_ultron, + ULTRON_IS_GREAT, + bye_allied_homeworld, + GOODBYE_ALLIED_HOMEWORLD, + ALLIED_HOMEWORLD_HELLO_1, + ALLIED_HOMEWORLD_HELLO_2, + ALLIED_HOMEWORLD_HELLO_3, + ALLIED_HOMEWORLD_HELLO_4, + HELLO_BEFORE_KOHRAH_SPACE_1, + HELLO_BEFORE_KOHRAH_SPACE_2, + HELLO_DURING_KOHRAH_SPACE_1, + HELLO_DURING_KOHRAH_SPACE_2, + HELLO_AFTER_KOHRAH_SPACE_1, + HELLO_AFTER_KOHRAH_SPACE_2, + UP_TO_YOU, + can_you_help, + HOW_HELP, + DONT_NEED, + HAVE_4_SHIPS, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/utwig/utwig.res b/sc2/src/sc2code/comm/utwig/utwig.res new file mode 100644 index 000000000..8a4a9f70c --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/utwig.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/utwig + +PACKAGE UTWIG_PACKAGE utwig.con + GFXRES UTWIG_PMAP_ANIM utwig.ani + FONTRES UTWIG_FONT utwig.fon + MUSICRES UTWIG_MUSIC utwig.mod + STRTAB UTWIG_CONVERSATION_PHRASES utwig.txt + diff --git a/sc2/src/sc2code/comm/utwig/utwigc.c b/sc2/src/sc2code/comm/utwig/utwigc.c new file mode 100644 index 000000000..e87a321b4 --- /dev/null +++ b/sc2/src/sc2code/comm/utwig/utwigc.c @@ -0,0 +1,948 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/utwig/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/utwig/strings.h" + +static LOCDATA utwig_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)UTWIG_PMAP_ANIM, /* AlienFrame */ + (FONT)UTWIG_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + UTWIG_MUSIC, /* AlienSong */ + UTWIG_CONVERSATION_PHRASES, /* PlayerPhrases */ + 16, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 4, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 7, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + (1 << 2), /* BlockMask */ + }, + { + 11, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + (1 << 1), /* BlockMask */ + }, + { + 13, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 10, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, + { + 18, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 20, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 22, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 25, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 27, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 30, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 32, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 34, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 36, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 38, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 40, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + { + 42, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 16, 4, /* FrameRate */ + ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 6, 6, /* FrameRate */ + 14, ONE_SECOND / 2, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye_neutral)) + NPCPhrase (GOODBYE_NEUTRAL); + else if (PLAYER_SAID (R, bye_after_space)) + NPCPhrase (GOODBYE_AFTER_SPACE); + else if (PLAYER_SAID (R, bye_before_space)) + NPCPhrase (GOODBYE_BEFORE_SPACE); + else if (PLAYER_SAID (R, bye_allied_homeworld)) + NPCPhrase (GOODBYE_ALLIED_HOMEWORLD); + else if (PLAYER_SAID (R, bye_bomb)) + NPCPhrase (GOODBYE_BOMB); + else if (PLAYER_SAID (R, demand_bomb)) + { + NPCPhrase (GUARDS_FIGHT); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, got_ultron) + || PLAYER_SAID (R, hey_wait_got_ultron)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NPCPhrase (NULL_PHRASE /* NO_ULTRON_AT_BOMB */); + + SET_GAME_STATE (REFUSED_ULTRON_AT_BOMB, 1); + } + else + { + if (PLAYER_SAID (R, got_ultron)) + NPCPhrase (DONT_WANT_TO_LOOK); + else + NPCPhrase (TAUNT_US_BUT_WE_LOOK); + if (GET_GAME_STATE (ULTRON_CONDITION) < 4) + { + switch (GET_GAME_STATE (UTWIG_INFO)) + { + case 0: + if (PLAYER_SAID (R, got_ultron)) + NPCPhrase (SICK_TRICK_1); + else + { + NPCPhrase (TRICKED_US_1); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + break; + case 1: + if (PLAYER_SAID (R, got_ultron)) + NPCPhrase (SICK_TRICK_2); + else + { + NPCPhrase (TRICKED_US_2); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + break; + } + SET_GAME_STATE (UTWIG_INFO, 1); + } + else + { + NPCPhrase (HAPPY_DAYS); + if (GET_GAME_STATE (KOHR_AH_FRENZY)) + NPCPhrase (TOO_LATE); + else + { + NPCPhrase (OK_ATTACK_KOHRAH); + + AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_UTWIG_SUPOX_MISSION); + } + + SET_GAME_STATE (UTWIG_HAVE_ULTRON, 1); + SET_GAME_STATE (ULTRON_CONDITION, 5); + + SET_GAME_STATE (UTWIG_VISITS, 0); + SET_GAME_STATE (SUPOX_VISITS, 0); + SET_GAME_STATE (UTWIG_HOME_VISITS, 0); + SET_GAME_STATE (SUPOX_HOME_VISITS, 0); + SET_GAME_STATE (BOMB_VISITS, 0); + + SET_GAME_STATE (SUPOX_INFO, 0); + SET_GAME_STATE (UTWIG_INFO, 0); + SET_GAME_STATE (SUPOX_WAR_NEWS, 0); + SET_GAME_STATE (UTWIG_WAR_NEWS, 0); + SET_GAME_STATE (SUPOX_HOSTILE, 0); + SET_GAME_STATE (UTWIG_HOSTILE, 0); + + ActivateStarShip (UTWIG_SHIP, 0); + ActivateStarShip (SUPOX_SHIP, 0); + } + } + } + else if (PLAYER_SAID (R, can_you_help)) + { + NPCPhrase (HOW_HELP); + if (ActivateStarShip (UTWIG_SHIP, FEASIBILITY_STUDY) == 0) + NPCPhrase (DONT_NEED); + else + { + NPCPhrase (HAVE_4_SHIPS); + + AlienTalkSegue ((COUNT)~0); + ActivateStarShip (UTWIG_SHIP, 4); + } + } +} + +static void AlliedHome (RESPONSE_REF R); + +static void +AlliedHome (RESPONSE_REF R) +{ + BYTE NumVisits, News; + + News = GET_GAME_STATE (UTWIG_WAR_NEWS); + NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (PLAYER_SAID (R, how_went_war)) + { + NPCPhrase (ABOUT_BATTLE); + + News |= (1 << 0); + } + else if (PLAYER_SAID (R, how_goes_war)) + { + if (NumVisits == 1) + { + NPCPhrase (FLEET_ON_WAY); + + SET_GAME_STATE (UTWIG_WAR_NEWS, 1); + } + else switch (GET_GAME_STATE (UTWIG_WAR_NEWS)) + { + case 0: + NPCPhrase (BATTLE_HAPPENS_1); + News = 1; + break; + case 1: + NPCPhrase (BATTLE_HAPPENS_2); + News = 2; + break; + } + + DISABLE_PHRASE (how_goes_war); + } + else if (PLAYER_SAID (R, learn_new_info)) + { + if (NumVisits < 5) + NPCPhrase (NO_NEW_INFO); + else + { + NPCPhrase (SAMATRA); + + News |= (1 << 1); + } + + DISABLE_PHRASE (learn_new_info); + } + else if (PLAYER_SAID (R, what_now_homeworld)) + { + if (NumVisits < 5) + NPCPhrase (UP_TO_YOU); + else + NPCPhrase (HOPE_KILL_EACH_OTHER); + + DISABLE_PHRASE (what_now_homeworld); + } + else if (PLAYER_SAID (R, how_is_ultron)) + { + NPCPhrase (ULTRON_IS_GREAT); + + DISABLE_PHRASE (how_is_ultron); + } + SET_GAME_STATE (UTWIG_WAR_NEWS, News); + + if (NumVisits >= 5) + { + if (!(News & (1 << 0))) + Response (how_went_war, AlliedHome); + } + else if (PHRASE_ENABLED (how_goes_war) + && ((NumVisits == 1 && News == 0) + || (NumVisits && News < 2))) + Response (how_goes_war, AlliedHome); + if (PHRASE_ENABLED (learn_new_info)) + Response (learn_new_info, AlliedHome); + if (PHRASE_ENABLED (what_now_homeworld)) + Response (what_now_homeworld, AlliedHome); + if (PHRASE_ENABLED (how_is_ultron)) + Response (how_is_ultron, AlliedHome); + if (NumVisits == 0) + Response (can_you_help, ExitConversation); + Response (bye_allied_homeworld, ExitConversation); +} + +static void +BeforeKohrAh (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_before_space)) + { + NumVisits = GET_GAME_STATE (UTWIG_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_BEFORE_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_BEFORE_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_before_space); + } + else if (PLAYER_SAID (R, what_now_before_space)) + { + NPCPhrase (DO_THIS_BEFORE_SPACE); + + DISABLE_PHRASE (what_now_before_space); + } + + if (PHRASE_ENABLED (whats_up_before_space)) + Response (whats_up_before_space, BeforeKohrAh); + if (PHRASE_ENABLED (what_now_before_space)) + Response (what_now_before_space, BeforeKohrAh); + Response (bye_before_space, ExitConversation); +} + +static void +AfterKohrAh (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_after_space)) + { + NumVisits = GET_GAME_STATE (UTWIG_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_AFTER_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_AFTER_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_after_space); + } + else if (PLAYER_SAID (R, what_now_after_space)) + { + NPCPhrase (DO_THIS_AFTER_SPACE); + + DISABLE_PHRASE (what_now_after_space); + } + + if (PHRASE_ENABLED (whats_up_after_space)) + Response (whats_up_after_space, AfterKohrAh); + if (PHRASE_ENABLED (what_now_after_space)) + Response (what_now_after_space, AfterKohrAh); + Response (bye_after_space, ExitConversation); +} + +static void +NeutralUtwig (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[4]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; + if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (WOULD_BE_HAPPY_BUT); + + SET_GAME_STATE (UTWIG_STACK1, 1); + } + else if (PLAYER_SAID (R, why_sad)) + { + NPCPhrase (ULTRON_BROKE); + + SET_GAME_STATE (UTWIG_STACK1, 2); + } + else if (PLAYER_SAID (R, what_ultron)) + { + NPCPhrase (GLORIOUS_ULTRON); + + SET_GAME_STATE (UTWIG_STACK1, 3); + } + else if (PLAYER_SAID (R, dont_be_babies)) + { + NPCPhrase (MOCK_OUR_PAIN); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + SET_GAME_STATE (UTWIG_STACK1, 4); + SET_GAME_STATE (UTWIG_HOSTILE, 1); + SET_GAME_STATE (UTWIG_INFO, 0); + SET_GAME_STATE (UTWIG_HOME_VISITS, 0); + SET_GAME_STATE (UTWIG_VISITS, 0); + SET_GAME_STATE (BOMB_VISITS, 0); + goto ExitUtwig; + } + else if (PLAYER_SAID (R, real_sorry_about_ultron)) + { + NPCPhrase (APPRECIATE_SYMPATHY); + + SET_GAME_STATE (UTWIG_STACK1, 4); + goto ExitUtwig; + } + else if (PLAYER_SAID (R, what_about_you_1)) + { + NPCPhrase (ABOUT_US_1); + + LastStack = 2; + SET_GAME_STATE (UTWIG_WAR_NEWS, 1); + } + else if (PLAYER_SAID (R, what_about_you_2)) + { + NPCPhrase (ABOUT_US_2); + + LastStack = 2; + SET_GAME_STATE (UTWIG_WAR_NEWS, 2); + } + else if (PLAYER_SAID (R, what_about_you_3)) + { + NPCPhrase (ABOUT_US_3); + + SET_GAME_STATE (UTWIG_WAR_NEWS, 3); + } + else if (PLAYER_SAID (R, what_about_urquan_1)) + { + NPCPhrase (ABOUT_URQUAN_1); + + LastStack = 3; + SET_GAME_STATE (UTWIG_STACK2, 1); + } + else if (PLAYER_SAID (R, what_about_urquan_2)) + { + NPCPhrase (ABOUT_URQUAN_2); + + SET_GAME_STATE (UTWIG_STACK2, 2); + } + + switch (GET_GAME_STATE (UTWIG_STACK1)) + { + case 0: + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + we_are_vindicator1, + buf, + we_are_vindicator2, + 0 + ); + } + pStr[0] = we_are_vindicator0; + break; + case 1: + pStr[0] = why_sad; + break; + case 2: + pStr[0] = what_ultron; + break; + case 3: + pStr[0] = dont_be_babies; + pStr[1] = real_sorry_about_ultron; + break; + } + switch (GET_GAME_STATE (UTWIG_WAR_NEWS)) + { + case 0: + pStr[2] = what_about_you_1; + break; + case 1: + pStr[2] = what_about_you_2; + break; + case 2: + pStr[2] = what_about_you_3; + break; + } + switch (GET_GAME_STATE (UTWIG_STACK2)) + { + case 0: + pStr[2] = what_about_urquan_1; + break; + case 1: + pStr[2] = what_about_urquan_2; + break; + } + + if (pStr[LastStack]) + { + if (pStr[LastStack] != we_are_vindicator0) + Response (pStr[LastStack], NeutralUtwig); + else + DoResponsePhrase (pStr[LastStack], NeutralUtwig, shared_phrase_buf); + } + for (i = 0; i < 4; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != we_are_vindicator0) + Response (pStr[i], NeutralUtwig); + else + DoResponsePhrase (pStr[i], NeutralUtwig, shared_phrase_buf); + } + } + if (GET_GAME_STATE (ULTRON_CONDITION)) + Response (got_ultron, ExitConversation); + Response (bye_neutral, ExitConversation); +ExitUtwig: + ; +} + +static void +BombWorld (RESPONSE_REF R) +{ + BYTE LastStack; + RESPONSE_REF pStr[2]; + + LastStack = 0; + pStr[0] = pStr[1] = 0; + if (PLAYER_SAID (R, why_you_here)) + { + NPCPhrase (WE_GUARD_BOMB); + + SET_GAME_STATE (BOMB_STACK1, 1); + } + else if (PLAYER_SAID (R, what_about_bomb)) + { + NPCPhrase (ABOUT_BOMB); + + SET_GAME_STATE (BOMB_STACK1, 2); + } + else if (PLAYER_SAID (R, give_us_bomb_or_die)) + { + NPCPhrase (GUARDS_WARN); + + SET_GAME_STATE (BOMB_STACK1, 3); + } + else if (PLAYER_SAID (R, demand_bomb)) + { + NPCPhrase (GUARDS_FIGHT); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + SET_GAME_STATE (UTWIG_HOSTILE, 1); + SET_GAME_STATE (UTWIG_INFO, 0); + SET_GAME_STATE (UTWIG_HOME_VISITS, 0); + SET_GAME_STATE (UTWIG_VISITS, 0); + SET_GAME_STATE (BOMB_VISITS, 0); + goto ExitBomb; + } + else if (PLAYER_SAID (R, may_we_have_bomb)) + { + NPCPhrase (NO_BOMB); + + LastStack = 1; + SET_GAME_STATE (BOMB_STACK2, 1); + } + else if (PLAYER_SAID (R, please)) + { + NPCPhrase (SORRY_NO_BOMB); + + SET_GAME_STATE (BOMB_STACK2, 2); + } + else if (PLAYER_SAID (R, whats_up_bomb)) + { + if (GET_GAME_STATE (BOMB_INFO)) + NPCPhrase (GENERAL_INFO_BOMB_2); + else + { + NPCPhrase (GENERAL_INFO_BOMB_1); + + SET_GAME_STATE (BOMB_INFO, 1); + } + + DISABLE_PHRASE (whats_up_bomb); + } + + switch (GET_GAME_STATE (BOMB_STACK2)) + { + case 0: + pStr[1] = may_we_have_bomb; + break; + case 1: + pStr[1] = please; + break; + } + switch (GET_GAME_STATE (BOMB_STACK1)) + { + case 0: + pStr[0] = why_you_here; + pStr[1] = 0; + break; + case 1: + pStr[0] = what_about_bomb; + pStr[1] = 0; + break; + case 2: + pStr[0] = give_us_bomb_or_die; + break; + case 3: + pStr[0] = demand_bomb; + break; + } + + if (pStr[LastStack]) + Response (pStr[LastStack], BombWorld); + LastStack ^= 1; + if (pStr[LastStack]) + Response (pStr[LastStack], BombWorld); + if (PHRASE_ENABLED (whats_up_bomb)) + Response (whats_up_bomb, BombWorld); + if (GET_GAME_STATE (ULTRON_CONDITION) + && !GET_GAME_STATE (REFUSED_ULTRON_AT_BOMB)) + Response (got_ultron, ExitConversation); + Response (bye_bomb, ExitConversation); +ExitBomb: + ; +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (UTWIG_HOSTILE)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (BOMB_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_BOMB_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_BOMB_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (BOMB_VISITS, NumVisits); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_HOMEWORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (UTWIG_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (HOSTILE_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_VISITS, NumVisits); + } + + if (!GET_GAME_STATE (ULTRON_CONDITION) + || (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6))) + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + Response (hey_wait_got_ultron, ExitConversation); + } + } + else if (ActivateStarShip (UTWIG_SHIP, CHECK_ALLIANCE) & GOOD_GUY) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); + + AlliedHome ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (NumVisits == 1) + { + NumVisits = GET_GAME_STATE (UTWIG_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_VISITS, NumVisits); + + BeforeKohrAh ((RESPONSE_REF)0); + } + else if (NumVisits < 5) + { + NumVisits = GET_GAME_STATE (UTWIG_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_DURING_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_DURING_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (UTWIG_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_1); + break; + case 1: + NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_VISITS, NumVisits); + + AfterKohrAh ((RESPONSE_REF)0); + } + } + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + NumVisits = GET_GAME_STATE (BOMB_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (BOMB_WORLD_HELLO_1); + break; + case 1: + NPCPhrase (BOMB_WORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (BOMB_VISITS, NumVisits); + + BombWorld ((RESPONSE_REF)0); + } + else + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (UTWIG_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (NEUTRAL_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (UTWIG_VISITS, NumVisits); + } + + NeutralUtwig ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_utwig (void) +{ + return (0); +} + +LOCDATAPTR +init_utwig_comm (void) +{ + LOCDATAPTR retval; + + utwig_desc.init_encounter_func = Intro; + utwig_desc.uninit_encounter_func = uninit_utwig; + + utwig_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); + utwig_desc.AlienTextTemplate.baseline.y = 64; + utwig_desc.AlienTextTemplate.align = ALIGN_CENTER; + utwig_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; + + if (GET_GAME_STATE (UTWIG_HAVE_ULTRON) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &utwig_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/vux/ifontres.h b/sc2/src/sc2code/comm/vux/ifontres.h new file mode 100644 index 000000000..2d738e595 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/ifontres.h @@ -0,0 +1,3 @@ +#define VUX_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/vux/igfxres.h b/sc2/src/sc2code/comm/vux/igfxres.h new file mode 100644 index 000000000..a62ac6783 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/igfxres.h @@ -0,0 +1,3 @@ +#define VUX_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/vux/imusicre.h b/sc2/src/sc2code/comm/vux/imusicre.h new file mode 100644 index 000000000..2dc4ca187 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/imusicre.h @@ -0,0 +1,3 @@ +#define VUX_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/vux/istrtab.h b/sc2/src/sc2code/comm/vux/istrtab.h new file mode 100644 index 000000000..99c07aa1d --- /dev/null +++ b/sc2/src/sc2code/comm/vux/istrtab.h @@ -0,0 +1,4 @@ +#define VUX_CONVERSATION_PHRASES 0x00200004L +#define VUX_COLOR_MAP 0x00200104L + + diff --git a/sc2/src/sc2code/comm/vux/resinst.h b/sc2/src/sc2code/comm/vux/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/vux/respkg.h b/sc2/src/sc2code/comm/vux/respkg.h new file mode 100644 index 000000000..5e8f93151 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/respkg.h @@ -0,0 +1,5 @@ +enum +{ + VUX_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/vux/restypes.h b/sc2/src/sc2code/comm/vux/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/vux/strings.h b/sc2/src/sc2code/comm/vux/strings.h new file mode 100644 index 000000000..5dc74603a --- /dev/null +++ b/sc2/src/sc2code/comm/vux/strings.h @@ -0,0 +1,128 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + ZEX_HELLO_1, + ZEX_HELLO_2, + ZEX_HELLO_3, + ZEX_HELLO_4, + FIGHT_OR_TRADE_1, + FIGHT_OR_TRADE_2, + what_you_do_here, + MY_MENAGERIE, + what_about_menagerie, + NEED_NEW_CREATURE, + what_about_creature, + ABOUT_CREATURE, + about_creature_again, + CREATURE_AGAIN, + i_have_beast, + GIVE_BEAST, + ok_take_beast, + FOOL_AIEE0, + FOOL_AIEE1, + why_trust_1, + TRUST_1, + why_trust_2, + TRUST_2, + why_trust_3, + TRUST_3, + why_dont_you_attack, + LIKE_YOU, + why_like_me, + LIKE_BECAUSE, + are_you_a_pervert, + CALL_ME_WHAT_YOU_WISH, + take_by_force, + PRECURSOR_DEVICE, + regardless, + THEN_FIGHT, + you_lied, + YUP_LIED, + kill_you, + FIGHT_AGAIN, + bye_zex, + GOODBYE_ZEX, + HOMEWORLD_HELLO_1, + HOMEWORLD_HELLO_2, + HOMEWORLD_HELLO_3, + HOMEWORLD_HELLO_4, + SPACE_HELLO_1, + SPACE_HELLO_2, + SPACE_HELLO_3, + SPACE_HELLO_4, + kill_you_squids_1, + kill_you_squids_2, + kill_you_squids_3, + kill_you_squids_4, + WE_FIGHT, + why_so_mean, + URQUAN_SLAVES, + deeper_reason, + OLD_INSULT, + if_we_apologize, + PROBABLY_NOT, + try_any_way, + NOPE, + APOLOGIZE_IN_SPACE, + apology_1, + NOT_ACCEPTED_1, + apology_2, + NOT_ACCEPTED_2, + apology_3, + NOT_ACCEPTED_3, + apology_4, + NOT_ACCEPTED_4, + apology_5, + NOT_ACCEPTED_5, + apology_6, + NOT_ACCEPTED_6, + apology_7, + NOT_ACCEPTED_7, + apology_8, + NOT_ACCEPTED_8, + apology_9, + NOT_ACCEPTED_9, + apology_10, + TRUTH, + whats_up_hostile, + GENERAL_INFO_HOSTILE_1, + GENERAL_INFO_HOSTILE_2, + GENERAL_INFO_HOSTILE_3, + GENERAL_INFO_HOSTILE_4, + cant_we_be_friends_1, + NEVER_UGLY_HUMANS_1, + cant_we_be_friends_2, + NEVER_UGLY_HUMANS_2, + cant_we_be_friends_3, + NEVER_UGLY_HUMANS_3, + cant_we_be_friends_4, + NEVER_UGLY_HUMANS_4, + bye_hostile_space, + GOODBYE_AND_DIE_HOSTILE_SPACE_1, + GOODBYE_AND_DIE_HOSTILE_SPACE_2, + GOODBYE_AND_DIE_HOSTILE_SPACE_3, + GOODBYE_AND_DIE_HOSTILE_SPACE_4, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/vux/vux.res b/sc2/src/sc2code/comm/vux/vux.res new file mode 100644 index 000000000..bb48cfc1e --- /dev/null +++ b/sc2/src/sc2code/comm/vux/vux.res @@ -0,0 +1,11 @@ +INCLUDE ../../star3do.typ + +PATH comm/vux + +PACKAGE VUX_PACKAGE vux.con + GFXRES VUX_PMAP_ANIM vux.ani + FONTRES VUX_FONT vux.fon + MUSICRES VUX_MUSIC vux.mod + STRTAB VUX_CONVERSATION_PHRASES vux.txt + STRTAB VUX_COLOR_MAP vux.ct + diff --git a/sc2/src/sc2code/comm/vux/vuxc.c b/sc2/src/sc2code/comm/vux/vuxc.c new file mode 100644 index 000000000..01dfedfb4 --- /dev/null +++ b/sc2/src/sc2code/comm/vux/vuxc.c @@ -0,0 +1,770 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/vux/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/vux/strings.h" + +static LOCDATA vux_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)VUX_PMAP_ANIM, /* AlienFrame */ + (FONT)VUX_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* (SIS_TEXT_WIDTH - 16) >> 1, */ /* AlienTextWidth */ + VUX_COLOR_MAP, /* AlienColorMap */ + VUX_MUSIC, /* AlienSong */ + VUX_CONVERSATION_PHRASES, /* PlayerPhrases */ + 17, /* NumAnimations */ + { + { + 12, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 15, /* StartIndex */ + 5, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 20, /* StartIndex */ + 14, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 0, /* FrameRate */ + 4, 0, /* RestartRate */ + }, + { + 34, /* StartIndex */ + 7, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 41, /* StartIndex */ + 6, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 47, /* StartIndex */ + 11, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 58, /* StartIndex */ + 3, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 61, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 65, /* StartIndex */ + 4, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 69, /* StartIndex */ + 2, /* NumFrames */ + RANDOM_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 71, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + }, + { + 74, /* StartIndex */ + 6, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* FrameRate */ + }, + { + 80, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* FrameRate */ + (1 << 14), /* BlockMask */ + }, + { + 85, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* FrameRate */ + }, + { + 90, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + 8, 8, /* FrameRate */ + (1 << 12), /* BlockMask */ + }, + { + 95, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 5, ONE_SECOND * 5,/* RestartRate */ + }, + { + 99, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 5, ONE_SECOND * 5,/* RestartRate */ + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 11, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +CombatIsInevitable (RESPONSE_REF R) +{ + BYTE NumVisits; + + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, ok_take_beast)) + { + NPCPhrase (FOOL_AIEE0); + NPCPhrase (FOOL_AIEE1); + + AlienTalkSegue (1); + XFormPLUT (GetColorMapAddress ( + SetAbsColorMapIndex (CommData.AlienColorMap, 1) + ), ONE_SECOND / 4); + AlienTalkSegue ((COUNT)~0); + + SET_GAME_STATE (VUX_BEAST_ON_SHIP, 0); + SET_GAME_STATE (ZEX_IS_DEAD, 1); + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else if (PLAYER_SAID (R, try_any_way)) + { + NPCPhrase (NOPE); + + SET_GAME_STATE (VUX_STACK_1, 4); + } + else if (PLAYER_SAID (R, kill_you_squids_1) + || PLAYER_SAID (R, kill_you_squids_2) + || PLAYER_SAID (R, kill_you_squids_3) + || PLAYER_SAID (R, kill_you_squids_4)) + { + NPCPhrase (WE_FIGHT); + + NumVisits = GET_GAME_STATE (VUX_STACK_2) + 1; + if (NumVisits <= 3) + { + SET_GAME_STATE (VUX_STACK_2, NumVisits); + } + } + else if (PLAYER_SAID (R, cant_we_be_friends_1) + || PLAYER_SAID (R, cant_we_be_friends_2) + || PLAYER_SAID (R, cant_we_be_friends_3) + || PLAYER_SAID (R, cant_we_be_friends_4)) + { + NumVisits = GET_GAME_STATE (VUX_STACK_3); + switch (NumVisits++) + { + case 0: + NPCPhrase (NEVER_UGLY_HUMANS_1); + break; + case 1: + NPCPhrase (NEVER_UGLY_HUMANS_2); + break; + case 2: + NPCPhrase (NEVER_UGLY_HUMANS_3); + break; + case 3: + NPCPhrase (NEVER_UGLY_HUMANS_4); + --NumVisits; + break; + } + SET_GAME_STATE (VUX_STACK_3, NumVisits); + } + else if (PLAYER_SAID (R, bye_hostile_space)) + { + NumVisits = GET_GAME_STATE (VUX_STACK_4); + switch (NumVisits++) + { + case 0: + NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_1); + break; + case 1: + NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_2); + break; + case 2: + NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_3); + break; + case 3: + NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_4); + --NumVisits; + break; + } + SET_GAME_STATE (VUX_STACK_4, NumVisits); + } + else if (PLAYER_SAID (R, bye_zex)) + { + NPCPhrase (GOODBYE_ZEX); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + NumVisits = GET_GAME_STATE (VUX_STACK_1); + switch (NumVisits++) + { + case 4: + NPCPhrase (NOT_ACCEPTED_1); + break; + case 5: + NPCPhrase (NOT_ACCEPTED_2); + break; + case 6: + NPCPhrase (NOT_ACCEPTED_3); + break; + case 7: + NPCPhrase (NOT_ACCEPTED_4); + break; + case 8: + NPCPhrase (NOT_ACCEPTED_5); + break; + case 9: + NPCPhrase (NOT_ACCEPTED_6); + break; + case 10: + NPCPhrase (NOT_ACCEPTED_7); + break; + case 11: + NPCPhrase (NOT_ACCEPTED_8); + break; + case 12: + NPCPhrase (NOT_ACCEPTED_9); + break; + case 13: + NPCPhrase (TRUTH); + break; + } + SET_GAME_STATE (VUX_STACK_1, NumVisits); + } +} + +static void +Menagerie (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[3]; + //PTR_DESC PtrDesc; + + if (PLAYER_SAID (R, i_have_beast) + || PLAYER_SAID (R, why_trust_1) + || PLAYER_SAID (R, why_trust_2) + || PLAYER_SAID (R, why_trust_3)) + { + if (PLAYER_SAID (R, i_have_beast)) + NPCPhrase (GIVE_BEAST); + else if (PLAYER_SAID (R, why_trust_1)) + { + NPCPhrase (TRUST_1); + + DISABLE_PHRASE (why_trust_1); + } + else if (PLAYER_SAID (R, why_trust_2)) + { + NPCPhrase (TRUST_2); + + DISABLE_PHRASE (why_trust_2); + } + else if (PLAYER_SAID (R, why_trust_3)) + { + NPCPhrase (TRUST_3); + + DISABLE_PHRASE (why_trust_3); + } + + if (PHRASE_ENABLED (why_trust_1)) + Response (why_trust_1, Menagerie); + else if (PHRASE_ENABLED (why_trust_2)) + Response (why_trust_2, Menagerie); + else if (PHRASE_ENABLED (why_trust_3)) + Response (why_trust_3, Menagerie); + Response (ok_take_beast, CombatIsInevitable); + } + else if (PLAYER_SAID (R, kill_you)) + { + NPCPhrase (FIGHT_AGAIN); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, regardless)) + { + NPCPhrase (THEN_FIGHT); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + SET_GAME_STATE (ZEX_STACK_3, 2); + SET_GAME_STATE (ZEX_VISITS, 0); + } + else + { + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (R == 0) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (ZEX_VISITS); + if (GET_GAME_STATE (ZEX_STACK_3) >= 2) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (FIGHT_OR_TRADE_1); + break; + case 1: + NPCPhrase (FIGHT_OR_TRADE_2); + --NumVisits; + break; + } + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (ZEX_HELLO_1); + break; + case 1: + NPCPhrase (ZEX_HELLO_2); + break; + case 2: + NPCPhrase (ZEX_HELLO_3); + break; + case 3: + NPCPhrase (ZEX_HELLO_4); + --NumVisits; + break; + } + } + SET_GAME_STATE (ZEX_VISITS, NumVisits); + } + else if (PLAYER_SAID (R, what_you_do_here)) + { + NPCPhrase (MY_MENAGERIE); + + SET_GAME_STATE (ZEX_STACK_1, 1); + } + else if (PLAYER_SAID (R, what_about_menagerie)) + { + NPCPhrase (NEED_NEW_CREATURE); + + SET_GAME_STATE (ZEX_STACK_1, 2); + } + else if (PLAYER_SAID (R, what_about_creature)) + { + NPCPhrase (ABOUT_CREATURE); + + SET_GAME_STATE (KNOW_ZEX_WANTS_MONSTER, 1); + SET_GAME_STATE (ZEX_STACK_1, 3); + + R = about_creature_again; + DISABLE_PHRASE (what_about_creature); + } + else if (PLAYER_SAID (R, about_creature_again)) + { + NPCPhrase (CREATURE_AGAIN); + + DISABLE_PHRASE (about_creature_again); + } + else if (PLAYER_SAID (R, why_dont_you_attack)) + { + NPCPhrase (LIKE_YOU); + + LastStack = 1; + SET_GAME_STATE (ZEX_STACK_2, 1); + } + else if (PLAYER_SAID (R, why_like_me)) + { + NPCPhrase (LIKE_BECAUSE); + + LastStack = 1; + SET_GAME_STATE (ZEX_STACK_2, 2); + } + else if (PLAYER_SAID (R, are_you_a_pervert)) + { + NPCPhrase (CALL_ME_WHAT_YOU_WISH); + + SET_GAME_STATE (ZEX_STACK_2, 3); + } + else if (PLAYER_SAID (R, take_by_force)) + { + NPCPhrase (PRECURSOR_DEVICE); + + LastStack = 2; + SET_GAME_STATE (ZEX_STACK_3, 1); + } + else if (PLAYER_SAID (R, you_lied)) + { + NPCPhrase (YUP_LIED); + + LastStack = 2; + SET_GAME_STATE (ZEX_STACK_3, 3); + } + + if (GET_GAME_STATE (KNOW_ZEX_WANTS_MONSTER) + && GET_GAME_STATE (VUX_BEAST_ON_SHIP)) + pStr[0] = i_have_beast; + else + { + switch (GET_GAME_STATE (ZEX_STACK_1)) + { + case 0: + pStr[0] = what_you_do_here; + break; + case 1: + pStr[0] = what_about_menagerie; + break; + case 2: + pStr[0] = what_about_creature; + break; + case 3: + if (PHRASE_ENABLED (about_creature_again)) + pStr[0] = about_creature_again; + break; + } + } + switch (GET_GAME_STATE (ZEX_STACK_2)) + { + case 0: + pStr[1] = why_dont_you_attack; + break; + case 1: + pStr[1] = why_like_me; + break; + case 2: + pStr[1] = are_you_a_pervert; + break; + } + switch (GET_GAME_STATE (ZEX_STACK_3)) + { + case 0: + pStr[2] = take_by_force; + break; + case 1: + pStr[2] = regardless; + break; + case 2: + pStr[2] = you_lied; + break; + case 3: + pStr[2] = kill_you; + break; + } + + if (pStr[LastStack]) + Response (pStr[LastStack], Menagerie); + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + Response (pStr[i], Menagerie); + } + Response (bye_zex, CombatIsInevitable); + } +} + +static void +NormalVux (RESPONSE_REF R) +{ + //PTR_DESC PtrDesc; + + if (PLAYER_SAID (R, why_so_mean)) + { + NPCPhrase (URQUAN_SLAVES); + + SET_GAME_STATE (VUX_STACK_1, 1); + } + else if (PLAYER_SAID (R, deeper_reason)) + { + NPCPhrase (OLD_INSULT); + + SET_GAME_STATE (VUX_STACK_1, 2); + } + else if (PLAYER_SAID (R, if_we_apologize)) + { + NPCPhrase (PROBABLY_NOT); + + SET_GAME_STATE (VUX_STACK_1, 3); + } + else if (PLAYER_SAID (R, whats_up_hostile)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (VUX_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_HOSTILE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_HOSTILE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_HOSTILE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_HOSTILE_4); + --NumVisits; + break; + } + SET_GAME_STATE (VUX_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_hostile); + } + + switch (GET_GAME_STATE (VUX_STACK_1)) + { + case 0: + Response (why_so_mean, NormalVux); + break; + case 1: + Response (deeper_reason, NormalVux); + break; + case 2: + Response (if_we_apologize, NormalVux); + break; + case 3: + Response (try_any_way, CombatIsInevitable); + break; + case 4: + Response (apology_1, CombatIsInevitable); + break; + case 5: + Response (apology_2, CombatIsInevitable); + break; + case 6: + Response (apology_3, CombatIsInevitable); + break; + case 7: + Response (apology_4, CombatIsInevitable); + break; + case 8: + Response (apology_5, CombatIsInevitable); + break; + case 9: + Response (apology_6, CombatIsInevitable); + break; + case 10: + Response (apology_7, CombatIsInevitable); + break; + case 11: + Response (apology_8, CombatIsInevitable); + break; + case 12: + Response (apology_9, CombatIsInevitable); + break; + case 13: + Response (apology_10, CombatIsInevitable); + break; + } + + switch (GET_GAME_STATE (VUX_STACK_2)) + { + case 0: + Response (kill_you_squids_1, CombatIsInevitable); + break; + case 1: + Response (kill_you_squids_2, CombatIsInevitable); + break; + case 2: + Response (kill_you_squids_3, CombatIsInevitable); + break; + case 3: + Response (kill_you_squids_4, CombatIsInevitable); + break; + } + + if (PHRASE_ENABLED (whats_up_hostile)) + { + Response (whats_up_hostile, NormalVux); + } + + if (GET_GAME_STATE (VUX_STACK_1) > 13) + { + switch (GET_GAME_STATE (VUX_STACK_3)) + { + case 0: + Response (cant_we_be_friends_1, CombatIsInevitable); + break; + case 1: + Response (cant_we_be_friends_2, CombatIsInevitable); + break; + case 2: + Response (cant_we_be_friends_3, CombatIsInevitable); + break; + case 3: + Response (cant_we_be_friends_4, CombatIsInevitable); + break; + } + } + + Response (bye_hostile_space, CombatIsInevitable); +} + +static void +Intro (void) +{ + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + { + Menagerie ((RESPONSE_REF)0); + } + else + { + BYTE NumVisits; + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (VUX_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (HOMEWORLD_HELLO_2); + break; + case 2: + NPCPhrase (HOMEWORLD_HELLO_3); + break; + case 3: + NPCPhrase (HOMEWORLD_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (VUX_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (VUX_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (SPACE_HELLO_1); + break; + case 1: + NPCPhrase (SPACE_HELLO_2); + break; + case 2: + NPCPhrase (SPACE_HELLO_3); + break; + case 3: + NPCPhrase (SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (VUX_VISITS, NumVisits); + } + + NormalVux ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_vux (void) +{ + return (0); +} + +LOCDATAPTR +init_vux_comm (void) +{ + LOCDATAPTR retval; + + vux_desc.init_encounter_func = Intro; + vux_desc.uninit_encounter_func = uninit_vux; + + vux_desc.AlienTextTemplate.baseline.x = + TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1) + + (SIS_TEXT_WIDTH >> 2); + vux_desc.AlienTextTemplate.baseline.y = 0; + vux_desc.AlienTextTemplate.align = ALIGN_CENTER; + vux_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) >> 1; + + if ((GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + retval = &vux_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/yehat/ifontres.h b/sc2/src/sc2code/comm/yehat/ifontres.h new file mode 100644 index 000000000..38d96cb3c --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/ifontres.h @@ -0,0 +1,3 @@ +#define YEHAT_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/yehat/igfxres.h b/sc2/src/sc2code/comm/yehat/igfxres.h new file mode 100644 index 000000000..68ebbc19c --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/igfxres.h @@ -0,0 +1,3 @@ +#define YEHAT_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/yehat/imusicre.h b/sc2/src/sc2code/comm/yehat/imusicre.h new file mode 100644 index 000000000..d36abc0a6 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/imusicre.h @@ -0,0 +1,3 @@ +#define YEHAT_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/yehat/istrtab.h b/sc2/src/sc2code/comm/yehat/istrtab.h new file mode 100644 index 000000000..039de3dba --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/istrtab.h @@ -0,0 +1,4 @@ +#define YEHAT_CONVERSATION_PHRASES 0x00400004L +#define REBEL_CONVERSATION_PHRASES 0x00600104L + + diff --git a/sc2/src/sc2code/comm/yehat/resinst.h b/sc2/src/sc2code/comm/yehat/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/yehat/respkg.h b/sc2/src/sc2code/comm/yehat/respkg.h new file mode 100644 index 000000000..ffcd8ddaf --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/respkg.h @@ -0,0 +1,7 @@ +enum +{ + YEHAT_PACKAGE = 1, + YEHAT_PHRASE_PACKAGE, + REBEL_PHRASE_PACKAGE +}; + diff --git a/sc2/src/sc2code/comm/yehat/restypes.h b/sc2/src/sc2code/comm/yehat/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/yehat/strings.h b/sc2/src/sc2code/comm/yehat/strings.h new file mode 100644 index 000000000..1bcd8fe19 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/strings.h @@ -0,0 +1,101 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + HOMEWORLD_HELLO_1, + HOMEWORLD_HELLO_2, + whats_up_homeworld, + GENERAL_INFO_HOMEWORLD_1, + GENERAL_INFO_HOMEWORLD_2, + i_demand_you_ally_homeworld0, + i_demand_you_ally_homeworld1, + i_demand_you_ally_homeworld2, + i_demand_you_ally_homeworld3, + ENEMY_MUST_DIE, + at_least_help_us_homeworld, + NO_HELP_ENEMY, + give_info, + NO_INFO_FOR_ENEMY, + what_about_pkunk_royalist, + PKUNK_ABSORBED_ROYALIST, + HATE_PKUNK_ROYALIST, + bye_homeworld, + GOODBYE_AND_DIE_HOMEWORLD, + SPACE_HELLO_1, + SPACE_HELLO_2, + SPACE_HELLO_3, + SPACE_HELLO_4, + whats_up_space_1, + GENERAL_INFO_SPACE_1, + whats_up_space_2, + GENERAL_INFO_SPACE_2, + whats_up_space_3, + GENERAL_INFO_SPACE_3, + whats_up_space_4, + GENERAL_INFO_SPACE_4, + i_demand_you_ally_space0, + i_demand_you_ally_space1, + i_demand_you_ally_space2, + i_demand_you_ally_space3, + WE_CANNOT_1, + obligation, + WE_CANNOT_2, + at_least_help_us_space, + SORRY_CANNOT, + dishonor, + HERES_A_HINT, + what_about_pkunk_space, + PKUNK_ABSORBED_SPACE, + HATE_PKUNK_SPACE, + bye_space, + GO_IN_PEACE, + GOODBYE_AND_DIE_SPACE, + shofixti_alive_1, + shofixti_alive_2, + SEND_HIM_OVER_1, + SEND_HIM_OVER_2, + not_here, + not_send, + JUST_A_TRICK_1, + JUST_A_TRICK_2, + ok_send, + WE_REVOLT, + ROYALIST_SPACE_HELLO_1, + ROYALIST_SPACE_HELLO_2, + ROYALIST_HOMEWORLD_HELLO_1, + ROYALIST_HOMEWORLD_HELLO_2, + how_is_rebellion, + ROYALIST_REBELLION_1, + ROYALIST_REBELLION_2, + sorry_about_revolution, + ALL_YOUR_FAULT, + bye_royalist, + GOODBYE_AND_DIE_ROYALIST, + name_1, + name_2, + name_3, + name_40, + name_41, +}; + +#endif /* _STRINGS_H */ diff --git a/sc2/src/sc2code/comm/yehat/yehat.res b/sc2/src/sc2code/comm/yehat/yehat.res new file mode 100644 index 000000000..070fa6ee0 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/yehat.res @@ -0,0 +1,15 @@ +INCLUDE ../../star3do.typ + +PATH comm/yehat +PACKAGE YEHAT_PACKAGE yehat.con + GFXRES YEHAT_PMAP_ANIM yehat.ani + FONTRES YEHAT_FONT yehat.ani + MUSICRES YEHAT_MUSIC yehat.mod + +PACKAGE YEHAT_PHRASE_PACKAGE yehat.con + STRTAB YEHAT_CONVERSATION_PHRASES yehat.txt + +PATH comm/rebel +PACKAGE REBEL_PHRASE_PACKAGE yehat.con + STRTAB REBEL_CONVERSATION_PHRASES rebel.txt + diff --git a/sc2/src/sc2code/comm/yehat/yehatc.c b/sc2/src/sc2code/comm/yehat/yehatc.c new file mode 100644 index 000000000..eb0b5fee6 --- /dev/null +++ b/sc2/src/sc2code/comm/yehat/yehatc.c @@ -0,0 +1,665 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/yehat/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/yehat/strings.h" + +static LOCDATA yehat_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)YEHAT_PMAP_ANIM, /* AlienFrame */ + (FONT)YEHAT_FONT, /* AlienFont */ + WHITE_COLOR, /* AlienTextFColor */ + BLACK_COLOR, /* AlienTextBColor */ + 0, /* (SIS_TEXT_WIDTH - 16) * 2 / 3, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + YEHAT_MUSIC, /* AlienSong */ + YEHAT_CONVERSATION_PHRASES, /* PlayerPhrases */ + 15, /* NumAnimations */ + { + { + 4, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND / 4, ONE_SECOND / 2,/* RestartRate */ + (1 << 6) | (1 << 7), + }, + { + 7, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 12, 12, /* FrameRate */ + ONE_SECOND / 4, ONE_SECOND / 2,/* RestartRate */ + (1 << 6) | (1 << 7), + }, + { + 10, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 4) | (1 << 14), + }, + { + 13, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 6, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 5), + }, + { + 16, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ + (1 << 2) | (1 << 14), + }, + { + 21, /* StartIndex */ + 5, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ + (1 << 3), + }, + { + 26, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ + (1 << 0) | (1 << 1), + }, + { + 28, /* StartIndex */ + 2, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 8, 8, /* FrameRate */ + ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ + (1 << 0) | (1 << 1), + }, + { + 30, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 33, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 36, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 39, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 42, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 45, /* StartIndex */ + 3, /* NumFrames */ + YOYO_ANIM, /* AnimFlags */ + 4, 4, /* FrameRate */ + 4, 4, /* RestartRate */ + }, + { + 48, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM + | WAIT_TALKING, /* AnimFlags */ + 4, 0, /* FrameRate */ + ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ + (1 << 2) | (1 << 4), + }, + }, + { + 0, /* StartIndex */ + 0, /* NumFrames */ + 0, /* AnimFlags */ + 0, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + 1, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 1); + + if (PLAYER_SAID (R, bye_homeworld)) + NPCPhrase (GOODBYE_AND_DIE_HOMEWORLD); + else if (PLAYER_SAID (R, bye_royalist)) + NPCPhrase (GOODBYE_AND_DIE_ROYALIST); + else if (PLAYER_SAID (R, i_demand_you_ally_homeworld0)) + { + NPCPhrase (ENEMY_MUST_DIE); + + SET_GAME_STATE (NO_YEHAT_ALLY_HOME, 1); + } + else if (PLAYER_SAID (R, bye_space)) + { + if ((BYTE)Random () & 1) + NPCPhrase (GOODBYE_AND_DIE_SPACE); + else + { + NPCPhrase (GO_IN_PEACE); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + } + else if (PLAYER_SAID (R, not_here) + || PLAYER_SAID (R, not_send)) + { + switch (GET_GAME_STATE (YEHAT_REBEL_VISITS)) + { + case 0: + NPCPhrase (JUST_A_TRICK_1); + break; + case 1: + NPCPhrase (JUST_A_TRICK_2); + break; + } + SET_GAME_STATE (YEHAT_REBEL_VISITS, 1); + } + else if (PLAYER_SAID (R, ok_send)) + { + NPCPhrase (WE_REVOLT); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (YEHAT_CIVIL_WAR, 1); + SET_GAME_STATE (YEHAT_VISITS, 0); + SET_GAME_STATE (YEHAT_HOME_VISITS, 0); + SET_GAME_STATE (YEHAT_REBEL_VISITS, 0); + SET_GAME_STATE (YEHAT_REBEL_INFO, 0); + SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 0); + SET_GAME_STATE (NO_YEHAT_INFO, 0); + + AddEvent (RELATIVE_EVENT, 0, 0, 0, YEHAT_REBEL_EVENT); + } +} + +static void +Royalists (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, how_is_rebellion)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (YEHAT_ROYALIST_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (ROYALIST_REBELLION_1); + break; + case 1: + NPCPhrase (ROYALIST_REBELLION_2); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_ROYALIST_INFO, NumVisits); + + DISABLE_PHRASE (how_is_rebellion); + } + else if (PLAYER_SAID (R, what_about_pkunk_royalist)) + { + if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) + NPCPhrase (PKUNK_ABSORBED_ROYALIST); + else + NPCPhrase (HATE_PKUNK_ROYALIST); + + SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); + } + else if (PLAYER_SAID (R, sorry_about_revolution)) + { + NPCPhrase (ALL_YOUR_FAULT); + + SET_GAME_STATE (NO_YEHAT_INFO, 1); + } + + if (PHRASE_ENABLED (how_is_rebellion)) + Response (how_is_rebellion, Royalists); + if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) + && GET_GAME_STATE (PKUNK_VISITS) + && GET_GAME_STATE (PKUNK_HOME_VISITS)) + Response (what_about_pkunk_royalist, Royalists); + if (!GET_GAME_STATE (NO_YEHAT_INFO)) + Response (sorry_about_revolution, Royalists); + Response (bye_royalist, ExitConversation); +} + +static void +StartRevolt (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, shofixti_alive_1)) + { + NPCPhrase (SEND_HIM_OVER_1); + + SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1); + } + else if (PLAYER_SAID (R, shofixti_alive_2)) + NPCPhrase (SEND_HIM_OVER_2); + + if (ActivateStarShip (SHOFIXTI_SHIP, ESCORTING_FLAGSHIP)) + Response (ok_send, ExitConversation); + else + Response (not_here, ExitConversation); + Response (not_send, ExitConversation); +} + +static void +YehatHome (RESPONSE_REF R) +{ + + if (PLAYER_SAID (R, whats_up_homeworld)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (YEHAT_ROYALIST_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_HOMEWORLD_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_HOMEWORLD_2); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_ROYALIST_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_homeworld); + } + else if (PLAYER_SAID (R, at_least_help_us_homeworld)) + { + NPCPhrase (NO_HELP_ENEMY); + + SET_GAME_STATE (NO_YEHAT_HELP_HOME, 1); + } + else if (PLAYER_SAID (R, give_info)) + { + NPCPhrase (NO_INFO_FOR_ENEMY); + + SET_GAME_STATE (NO_YEHAT_INFO, 1); + } + else if (PLAYER_SAID (R, what_about_pkunk_royalist)) + { + if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) + NPCPhrase (PKUNK_ABSORBED_ROYALIST); + else + NPCPhrase (HATE_PKUNK_ROYALIST); + + SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); + } + + if (PHRASE_ENABLED (whats_up_homeworld)) + Response (whats_up_homeworld, YehatHome); + if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) + && GET_GAME_STATE (PKUNK_VISITS) + && GET_GAME_STATE (PKUNK_HOME_VISITS)) + Response (what_about_pkunk_royalist, YehatHome); + if (!GET_GAME_STATE (NO_YEHAT_HELP_HOME)) + Response (at_least_help_us_homeworld, YehatHome); + if (!GET_GAME_STATE (NO_YEHAT_INFO)) + Response (give_info, YehatHome); + if (!GET_GAME_STATE (NO_YEHAT_ALLY_HOME)) + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + i_demand_you_ally_homeworld0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + i_demand_you_ally_homeworld1, + buf, + i_demand_you_ally_homeworld2, + GLOBAL_SIS (ShipName), + i_demand_you_ally_homeworld3, + 0 + ); + DoResponsePhrase (i_demand_you_ally_homeworld0, + ExitConversation, shared_phrase_buf); + } + Response (bye_homeworld, ExitConversation); +} + +static void +YehatSpace (RESPONSE_REF R) +{ + BYTE i, LastStack; + RESPONSE_REF pStr[3]; + + LastStack = 0; + pStr[0] = pStr[1] = pStr[2] = 0; + if (PLAYER_SAID (R, whats_up_space_1) + || PLAYER_SAID (R, whats_up_space_2) + || PLAYER_SAID (R, whats_up_space_3) + || PLAYER_SAID (R, whats_up_space_4)) + { + BYTE NumVisits; + + NumVisits = GET_GAME_STATE (YEHAT_REBEL_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_SPACE_1); + break; + case 1: + NPCPhrase (GENERAL_INFO_SPACE_2); + break; + case 2: + NPCPhrase (GENERAL_INFO_SPACE_3); + break; + case 3: + NPCPhrase (GENERAL_INFO_SPACE_4); + break; + } + SET_GAME_STATE (YEHAT_REBEL_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_space_1); + } + else if (PLAYER_SAID (R, i_demand_you_ally_space0)) + { + NPCPhrase (WE_CANNOT_1); + + LastStack = 2; + SET_GAME_STATE (NO_YEHAT_ALLY_SPACE, 1); + } + else if (PLAYER_SAID (R, obligation)) + { + NPCPhrase (WE_CANNOT_2); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (NO_YEHAT_ALLY_SPACE, 2); + + goto ExitYehat; + } + else if (PLAYER_SAID (R, at_least_help_us_space)) + { + NPCPhrase (SORRY_CANNOT); + + LastStack = 1; + SET_GAME_STATE (NO_YEHAT_HELP_SPACE, 1); + } + else if (PLAYER_SAID (R, dishonor)) + { + NPCPhrase (HERES_A_HINT); + + SET_GAME_STATE (NO_YEHAT_HELP_SPACE, 2); + } + else if (PLAYER_SAID (R, what_about_pkunk_royalist)) + { + if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) + NPCPhrase (PKUNK_ABSORBED_ROYALIST); + else + NPCPhrase (HATE_PKUNK_ROYALIST); + + SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); + } + +// SET_FUNCPTR (&PtrDesc, YehatSpace); + if (PHRASE_ENABLED (whats_up_space_1)) + { + switch (GET_GAME_STATE (YEHAT_REBEL_INFO)) + { + case 0: + pStr[0] = whats_up_space_1; + break; + case 1: + pStr[0] = whats_up_space_2; + break; + case 2: + pStr[0] = whats_up_space_3; + break; + case 3: + pStr[0] = whats_up_space_4; + break; + } + } + switch (GET_GAME_STATE (NO_YEHAT_HELP_SPACE)) + { + case 0: + pStr[1] = at_least_help_us_space; + break; + case 1: + pStr[1] = dishonor; + break; + } + switch (GET_GAME_STATE (NO_YEHAT_ALLY_SPACE)) + { + case 0: + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + i_demand_you_ally_space0, + (vararg_dcl)GLOBAL_SIS (CommanderName), + i_demand_you_ally_space1, + GLOBAL_SIS (ShipName), + i_demand_you_ally_space2, + buf, + i_demand_you_ally_space3, + 0 + ); + pStr[2] = i_demand_you_ally_space0; + break; + } + case 1: + pStr[2] = obligation; + break; + } + + if (pStr[LastStack]) + { + if (pStr[LastStack] != i_demand_you_ally_space0) + Response (pStr[LastStack], YehatSpace); + else + DoResponsePhrase (pStr[LastStack], YehatSpace, shared_phrase_buf); + } + for (i = 0; i < 3; ++i) + { + if (i != LastStack && pStr[i]) + { + if (pStr[i] != i_demand_you_ally_space0) + Response (pStr[i], YehatSpace); + else + DoResponsePhrase (pStr[i], YehatSpace, shared_phrase_buf); + } + } + if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) + && GET_GAME_STATE (PKUNK_VISITS) + && GET_GAME_STATE (PKUNK_HOME_VISITS)) + Response (what_about_pkunk_royalist, YehatSpace); + if (GET_GAME_STATE (SHOFIXTI_VISITS)) + { + switch (GET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK)) + { + case 0: + Response (shofixti_alive_1, StartRevolt); + break; + case 1: + Response (shofixti_alive_2, StartRevolt); + break; + } + } + Response (bye_space, ExitConversation); +ExitYehat: + ; +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +// NPCPhrase (OUT_TAKES); + + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (YEHAT_CIVIL_WAR)) + { + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (YEHAT_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ROYALIST_HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (ROYALIST_HOMEWORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_HOME_VISITS, NumVisits); + } + else + { + NumVisits = GET_GAME_STATE (YEHAT_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (ROYALIST_SPACE_HELLO_1); + break; + case 1: + NPCPhrase (ROYALIST_SPACE_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_VISITS, NumVisits); + } + + Royalists ((RESPONSE_REF)0); + } + else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NumVisits = GET_GAME_STATE (YEHAT_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOMEWORLD_HELLO_1); + break; + case 1: + NPCPhrase (HOMEWORLD_HELLO_2); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_HOME_VISITS, NumVisits); + + YehatHome ((RESPONSE_REF)0); + } + else + { + NumVisits = GET_GAME_STATE (YEHAT_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (SPACE_HELLO_1); + break; + case 1: + NPCPhrase (SPACE_HELLO_2); + break; + case 2: + NPCPhrase (SPACE_HELLO_3); + break; + case 3: + NPCPhrase (SPACE_HELLO_4); + --NumVisits; + break; + } + SET_GAME_STATE (YEHAT_VISITS, NumVisits); + + YehatSpace ((RESPONSE_REF)0); + } +ExitIntro: + ; +} + +static COUNT +uninit_yehat (void) +{ + return (0); +} + +LOCDATAPTR +init_yehat_comm (void) +{ + LOCDATAPTR retval; + + yehat_desc.init_encounter_func = Intro; + yehat_desc.uninit_encounter_func = uninit_yehat; + + yehat_desc.AlienTextTemplate.baseline.x = SIS_SCREEN_WIDTH * 2 / 3; + yehat_desc.AlienTextTemplate.baseline.y = 107 * 2 / 3; + yehat_desc.AlienTextTemplate.align = ALIGN_CENTER; + yehat_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) * 2 / 3; + + if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + retval = &yehat_desc; + + return (retval); +} diff --git a/sc2/src/sc2code/comm/zoqfot/ifontres.h b/sc2/src/sc2code/comm/zoqfot/ifontres.h new file mode 100644 index 000000000..8cf28f796 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/ifontres.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_FONT 0x00200003L + + diff --git a/sc2/src/sc2code/comm/zoqfot/igfxres.h b/sc2/src/sc2code/comm/zoqfot/igfxres.h new file mode 100644 index 000000000..5688586c8 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/igfxres.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/comm/zoqfot/imusicre.h b/sc2/src/sc2code/comm/zoqfot/imusicre.h new file mode 100644 index 000000000..7247ee77a --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/imusicre.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_MUSIC 0x00200006L + + diff --git a/sc2/src/sc2code/comm/zoqfot/istrtab.h b/sc2/src/sc2code/comm/zoqfot/istrtab.h new file mode 100644 index 000000000..31865094a --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/istrtab.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_CONVERSATION_PHRASES 0x00200004L + + diff --git a/sc2/src/sc2code/comm/zoqfot/resinst.h b/sc2/src/sc2code/comm/zoqfot/resinst.h new file mode 100644 index 000000000..ebced6772 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "imusicre.h" diff --git a/sc2/src/sc2code/comm/zoqfot/respkg.h b/sc2/src/sc2code/comm/zoqfot/respkg.h new file mode 100644 index 000000000..4eb7faabc --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/respkg.h @@ -0,0 +1,5 @@ +enum +{ + ZOQFOTPIK_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/comm/zoqfot/restypes.h b/sc2/src/sc2code/comm/zoqfot/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/comm/zoqfot/strings.h b/sc2/src/sc2code/comm/zoqfot/strings.h new file mode 100644 index 000000000..f1ec9ab45 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/strings.h @@ -0,0 +1,351 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGS_H +#define _STRINGS_H + +enum +{ + NULL_PHRASE, + WE_ARE0, + WE_ARE1, + WE_ARE2, + WE_ARE3, + WE_ARE4, + WE_ARE5, + WE_ARE6, + WE_ARE7, + SCOUT_HELLO0, + SCOUT_HELLO1, + SCOUT_HELLO2, + SCOUT_HELLO3, + INIT_HOME_HELLO0, + INIT_HOME_HELLO1, + INIT_HOME_HELLO2, + INIT_HOME_HELLO3, + which_fot, + HE_IS0, + HE_IS1, + HE_IS2, + HE_IS3, + HE_IS4, + HE_IS5, + HE_IS6, + HE_IS7, + we_are_vindicator0, + we_are_vindicator1, + we_are_vindicator2, + WE_GLAD0, + WE_GLAD1, + WE_GLAD2, + WE_GLAD3, + WE_GLAD4, + WE_GLAD5, + quiet_toadies, + TOLD_YOU0, + TOLD_YOU1, + TOLD_YOU2, + TOLD_YOU3, + TOLD_YOU4, + TOLD_YOU5, + TOLD_YOU6, + TOLD_YOU7, + your_race, + YEARS_AGO0, + YEARS_AGO1, + YEARS_AGO2, + YEARS_AGO3, + YEARS_AGO4, + YEARS_AGO5, + YEARS_AGO6, + YEARS_AGO7, + YEARS_AGO8, + YEARS_AGO9, + YEARS_AGO10, + YEARS_AGO11, + YEARS_AGO12, + YEARS_AGO13, + where_from, + TRAVELED_FAR0, + TRAVELED_FAR1, + TRAVELED_FAR2, + TRAVELED_FAR3, + TRAVELED_FAR4, + TRAVELED_FAR5, + what_emergency, + UNDER_ATTACK0, + UNDER_ATTACK1, + UNDER_ATTACK2, + UNDER_ATTACK3, + UNDER_ATTACK4, + UNDER_ATTACK5, + UNDER_ATTACK6, + UNDER_ATTACK7, + UNDER_ATTACK8, + UNDER_ATTACK9, + UNDER_ATTACK10, + UNDER_ATTACK11, + tough_luck, + NOT_HELPFUL0, + NOT_HELPFUL1, + NOT_HELPFUL2, + NOT_HELPFUL3, + NOT_HELPFUL4, + NOT_HELPFUL5, + what_look_like, + LOOK_LIKE0, + LOOK_LIKE1, + LOOK_LIKE2, + LOOK_LIKE3, + valuable_info, + GOODBYE0, + GOODBYE1, + GOODBYE2, + GOODBYE3, + all_very_interesting, + SEE_TOLD_YOU0, + SEE_TOLD_YOU1, + SEE_TOLD_YOU2, + SEE_TOLD_YOU3, + how_can_i_help, + ALLY_WITH_US0, + ALLY_WITH_US1, + ALLY_WITH_US2, + ALLY_WITH_US3, + ALLY_WITH_US4, + ALLY_WITH_US5, + decide_later, + PLEASE_HURRY0, + PLEASE_HURRY1, + EMMISSARIES0, + EMMISSARIES1, + EMMISSARIES2, + EMMISSARIES3, + EMMISSARIES4, + EMMISSARIES5, + EMMISSARIES6, + EMMISSARIES7, + sure, + WE_ALLY0, + WE_ALLY1, + WE_ALLY2, + WE_ALLY3, + WE_ALLY4, + WE_ALLY5, + never, + WE_ENEMIES0, + WE_ENEMIES1, + HOSTILE_HELLO_10, + HOSTILE_HELLO_11, + HOSTILE_HELLO_20, + HOSTILE_HELLO_21, + HOSTILE_HELLO_22, + HOSTILE_HELLO_23, + HOSTILE_HELLO_24, + HOSTILE_HELLO_25, + HOSTILE_HELLO_30, + HOSTILE_HELLO_31, + HOSTILE_HELLO_40, + HOSTILE_HELLO_41, + NEUTRAL_HOME_HELLO_10, + NEUTRAL_HOME_HELLO_11, + NEUTRAL_HOME_HELLO_12, + NEUTRAL_HOME_HELLO_13, + NEUTRAL_HOME_HELLO_20, + NEUTRAL_HOME_HELLO_21, + NEUTRAL_HOME_HELLO_22, + NEUTRAL_HOME_HELLO_23, + ALLIED_HOME_HELLO_10, + ALLIED_HOME_HELLO_11, + ALLIED_HOME_HELLO_12, + ALLIED_HOME_HELLO_13, + ALLIED_HOME_HELLO_20, + ALLIED_HOME_HELLO_21, + ALLIED_HOME_HELLO_22, + ALLIED_HOME_HELLO_23, + ALLIED_HOME_HELLO_24, + ALLIED_HOME_HELLO_25, + ALLIED_HOME_HELLO_26, + ALLIED_HOME_HELLO_27, + ALLIED_HOME_HELLO_30, + ALLIED_HOME_HELLO_31, + ALLIED_HOME_HELLO_40, + ALLIED_HOME_HELLO_41, + THANKS_FOR_RESCUE0, + THANKS_FOR_RESCUE1, + THANKS_FOR_RESCUE2, + THANKS_FOR_RESCUE3, + THANKS_FOR_RESCUE4, + THANKS_FOR_RESCUE5, + THANKS_FOR_RESCUE6, + THANKS_FOR_RESCUE7, + THANKS_FOR_RESCUE8, + THANKS_FOR_RESCUE9, + THANKS_FOR_RESCUE10, + THANKS_FOR_RESCUE11, + bye_homeworld, + GOODBYE_HOME0, + GOODBYE_HOME1, + whats_up_homeworld, + GENERAL_INFO_10, + GENERAL_INFO_11, + GENERAL_INFO_12, + GENERAL_INFO_13, + GENERAL_INFO_20, + GENERAL_INFO_21, + GENERAL_INFO_22, + GENERAL_INFO_23, + GENERAL_INFO_24, + GENERAL_INFO_25, + GENERAL_INFO_26, + GENERAL_INFO_27, + GENERAL_INFO_30, + GENERAL_INFO_31, + GENERAL_INFO_32, + GENERAL_INFO_33, + GENERAL_INFO_34, + GENERAL_INFO_35, + GENERAL_INFO_40, + GENERAL_INFO_41, + GENERAL_INFO_42, + GENERAL_INFO_43, + GENERAL_INFO_44, + GENERAL_INFO_45, + GENERAL_INFO_46, + GENERAL_INFO_47, + GENERAL_INFO_48, + GENERAL_INFO_49, + GENERAL_INFO_410, + GENERAL_INFO_411, + any_war_news, + UTWIG_DELAY0, + UTWIG_DELAY1, + UTWIG_DELAY2, + UTWIG_DELAY3, + UTWIG_DELAY4, + UTWIG_DELAY5, + UTWIG_DELAY6, + UTWIG_DELAY7, + UTWIG_DELAY8, + UTWIG_DELAY9, + UTWIG_DELAY10, + UTWIG_DELAY11, + UTWIG_DELAY12, + UTWIG_DELAY13, + KOHRAH_WINNING0, + KOHRAH_WINNING1, + KOHRAH_WINNING2, + KOHRAH_WINNING3, + KOHRAH_WINNING4, + KOHRAH_WINNING5, + KOHRAH_WINNING6, + KOHRAH_WINNING7, + KOHRAH_WINNING8, + KOHRAH_WINNING9, + URQUAN_NEARLY_GONE0, + URQUAN_NEARLY_GONE1, + URQUAN_NEARLY_GONE2, + URQUAN_NEARLY_GONE3, + URQUAN_NEARLY_GONE4, + URQUAN_NEARLY_GONE5, + KOHRAH_FRENZY0, + KOHRAH_FRENZY1, + KOHRAH_FRENZY2, + KOHRAH_FRENZY3, + KOHRAH_FRENZY4, + KOHRAH_FRENZY5, + KOHRAH_FRENZY6, + KOHRAH_FRENZY7, + KOHRAH_FRENZY8, + KOHRAH_FRENZY9, + KOHRAH_FRENZY10, + KOHRAH_FRENZY11, + NO_WAR_NEWS0, + NO_WAR_NEWS1, + i_want_alliance, + GOOD0, + GOOD1, + GOOD2, + GOOD3, + GOOD4, + GOOD5, + GOOD6, + GOOD7, + GOOD8, + GOOD9, + want_specific_info, + WHAT_SPECIFIC_INFO0, + WHAT_SPECIFIC_INFO1, + enough_info, + OK_ENOUGH_INFO, + what_about_others, + ABOUT_OTHERS0, + ABOUT_OTHERS1, + ABOUT_OTHERS2, + ABOUT_OTHERS3, + ABOUT_OTHERS4, + ABOUT_OTHERS5, + ABOUT_OTHERS6, + ABOUT_OTHERS7, + ABOUT_OTHERS8, + ABOUT_OTHERS9, + ABOUT_OTHERS10, + ABOUT_OTHERS11, + ABOUT_OTHERS12, + ABOUT_OTHERS13, + what_about_zebranky, + ABOUT_ZEBRANKY0, + ABOUT_ZEBRANKY1, + ABOUT_ZEBRANKY2, + ABOUT_ZEBRANKY3, + ABOUT_ZEBRANKY4, + ABOUT_ZEBRANKY5, + ABOUT_ZEBRANKY6, + ABOUT_ZEBRANKY7, + what_about_past, + ABOUT_PAST0, + ABOUT_PAST1, + ABOUT_PAST2, + ABOUT_PAST3, + ABOUT_PAST4, + ABOUT_PAST5, + ABOUT_PAST6, + ABOUT_PAST7, + ABOUT_PAST8, + ABOUT_PAST9, + ABOUT_PAST10, + ABOUT_PAST11, + what_about_stinger, + ABOUT_STINGER0, + ABOUT_STINGER1, + ABOUT_STINGER2, + ABOUT_STINGER3, + ABOUT_STINGER4, + ABOUT_STINGER5, + what_about_guy_in_back, + ABOUT_GUY0, + ABOUT_GUY1, + name_1, + name_2, + name_3, + name_40, + name_41, +}; + +#endif /* _STRINGS_H */ + diff --git a/sc2/src/sc2code/comm/zoqfot/zoqfot.res b/sc2/src/sc2code/comm/zoqfot/zoqfot.res new file mode 100644 index 000000000..a7bdfc467 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/zoqfot.res @@ -0,0 +1,10 @@ +INCLUDE ../../star3do.typ + +PATH comm/zoqfot + +PACKAGE ZOQFOTPIK_PACKAGE zoqfot.con + GFXRES ZOQFOTPIK_PMAP_ANIM zoqfot.ani + FONTRES ZOQFOTPIK_FONT zoqfot.fon + MUSICRES ZOQFOTPIK_MUSIC zoqfot.mod + STRTAB ZOQFOTPIK_CONVERSATION_PHRASES zoqfot.txt + diff --git a/sc2/src/sc2code/comm/zoqfot/zoqfotc.c b/sc2/src/sc2code/comm/zoqfot/zoqfotc.c new file mode 100644 index 000000000..d8da37a06 --- /dev/null +++ b/sc2/src/sc2code/comm/zoqfot/zoqfotc.c @@ -0,0 +1,1210 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "comm/zoqfot/resinst.h" +#include "starcon.h" +#include "commglue.h" +#include "comm/zoqfot/strings.h" + +#define ZOQ_FG_COLOR WHITE_COLOR +#define ZOQ_BG_COLOR BLACK_COLOR +#define ZOQ_BASE_X (TEXT_X_OFFS + ((SIS_TEXT_WIDTH >> 1) >> 1)) +#define ZOQ_BASE_Y 24 +#define ZOQ_TALK_INDEX 18 +#define ZOQ_TALK_FRAMES 5 +#define FOT_TO_ZOQ 23 + +#define PIK_FG_COLOR WHITE_COLOR +#define PIK_BG_COLOR BLACK_COLOR +#define PIK_BASE_X (SIS_SCREEN_WIDTH - (TEXT_X_OFFS + ((SIS_TEXT_WIDTH >> 1) >> 1))) +#define PIK_BASE_Y 24 +#define PIK_TALK_INDEX 29 +#define PIK_TALK_FRAMES 2 +#define FOT_TO_PIK 26 + +static LOCDATA zoqfot_desc = +{ + NULL_PTR, /* init_encounter_func */ + NULL_PTR, /* uninit_encounter_func */ + (FRAME)ZOQFOTPIK_PMAP_ANIM, /* AlienFrame */ + (FONT)ZOQFOTPIK_FONT, /* AlienFont */ + 0, /* AlienTextFColor */ + 0, /* AlienTextBColor */ + 0, /* SIS_SCREEN_WIDTH, */ /* AlienTextWidth */ + 0, /* AlienColorMap */ + ZOQFOTPIK_MUSIC, /* AlienSong */ + ZOQFOTPIK_CONVERSATION_PHRASES, /* PlayerPhrases */ + 3, /* NumAnimations */ + { + { /* Eye blink */ + 1, /* StartIndex */ + 4, /* NumFrames */ + YOYO_ANIM /* AnimFlags */ + | WAIT_TALKING, + 5, 0, /* FrameRate */ + 0, ONE_SECOND * 10, /* RestartRate */ + }, + { /* Blow smoke */ + 5, /* StartIndex */ + 5, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 7, 0, /* FrameRate */ + ONE_SECOND * 2, 0, /* RestartRate */ + }, + { /* Gulp */ + 10, /* StartIndex */ + 8, /* NumFrames */ + CIRCULAR_ANIM, /* AnimFlags */ + 8, 0, /* FrameRate */ + 0, ONE_SECOND * 10, /* RestartRate */ + }, + }, + { /* Move Eye */ + FOT_TO_ZOQ, /* StartIndex */ + 3, /* NumFrames */ + 0, /* AnimFlags */ + 4, 0, /* FrameRate */ + 0, 0, /* RestartRate */ + }, + { + ZOQ_TALK_INDEX, /* StartIndex */ + ZOQ_TALK_FRAMES, /* NumFrames */ + 0, /* AnimFlags */ + 8, 0, /* FrameRate */ + 10, 0, /* RestartRate */ + }, +}; + +enum +{ + ZOQ_ALIEN, + FOT_ALIEN, + PIK_ALIEN +}; + +static void +SelectAlien (COUNT index, BYTE which_alien) +{ + switch (which_alien) + { + case ZOQ_ALIEN: + CommData.AlienTransitionDesc.StartIndex = FOT_TO_ZOQ; + CommData.AlienTalkDesc.StartIndex = ZOQ_TALK_INDEX; + CommData.AlienTalkDesc.NumFrames = ZOQ_TALK_FRAMES; + CommData.AlienAmbientArray[1].AnimFlags &= ~WAIT_TALKING; + + CommData.AlienTextTemplate.baseline.x = ZOQ_BASE_X; + CommData.AlienTextTemplate.baseline.y = ZOQ_BASE_Y; + CommData.AlienTextFColor = ZOQ_FG_COLOR; + CommData.AlienTextBColor = ZOQ_BG_COLOR; + break; + case FOT_ALIEN: + break; + case PIK_ALIEN: + CommData.AlienTransitionDesc.StartIndex = FOT_TO_PIK; + CommData.AlienTalkDesc.StartIndex = PIK_TALK_INDEX; + CommData.AlienTalkDesc.NumFrames = PIK_TALK_FRAMES; + CommData.AlienAmbientArray[1].AnimFlags |= WAIT_TALKING; + + CommData.AlienTextTemplate.baseline.x = PIK_BASE_X; + CommData.AlienTextTemplate.baseline.y = PIK_BASE_Y; + CommData.AlienTextFColor = PIK_FG_COLOR; + CommData.AlienTextBColor = PIK_BG_COLOR; + break; + } + + AlienTalkSegue (index); +} + +static void +ExitConversation (RESPONSE_REF R) +{ + SET_GAME_STATE (BATTLE_SEGUE, 0); + + if (PLAYER_SAID (R, bye_homeworld)) + { + NPCPhrase (GOODBYE_HOME0); + NPCPhrase (GOODBYE_HOME1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else if (PLAYER_SAID (R, decide_later)) + { + NPCPhrase (PLEASE_HURRY0); + NPCPhrase (PLEASE_HURRY1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else if (PLAYER_SAID (R, valuable_info)) + { + NPCPhrase (GOODBYE0); + NPCPhrase (GOODBYE1); + NPCPhrase (GOODBYE2); + NPCPhrase (GOODBYE3); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else if (PLAYER_SAID (R, how_can_i_help)) + { + NPCPhrase (EMMISSARIES0); + NPCPhrase (EMMISSARIES1); + NPCPhrase (EMMISSARIES2); + NPCPhrase (EMMISSARIES3); + NPCPhrase (EMMISSARIES4); + NPCPhrase (EMMISSARIES5); + NPCPhrase (EMMISSARIES6); + NPCPhrase (EMMISSARIES7); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else if (PLAYER_SAID (R, sure)) + { + NPCPhrase (WE_ALLY0); + NPCPhrase (WE_ALLY1); + NPCPhrase (WE_ALLY2); + NPCPhrase (WE_ALLY3); + NPCPhrase (WE_ALLY4); + NPCPhrase (WE_ALLY5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + ActivateStarShip (ZOQFOTPIK_SHIP, 0); + AddEvent (RELATIVE_EVENT, 3, 0, 0, ZOQFOT_DISTRESS_EVENT); + SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); + } + else if (PLAYER_SAID (R, all_very_interesting)) + { + NPCPhrase (SEE_TOLD_YOU0); + NPCPhrase (SEE_TOLD_YOU1); + NPCPhrase (SEE_TOLD_YOU2); + NPCPhrase (SEE_TOLD_YOU3); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + SET_GAME_STATE (ZOQFOT_HOSTILE, 1); + SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (PLAYER_SAID (R, never)) + { + NPCPhrase (WE_ENEMIES0); + NPCPhrase (WE_ENEMIES1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); + SET_GAME_STATE (ZOQFOT_HOSTILE, 1); + SET_GAME_STATE (BATTLE_SEGUE, 1); + } +} + +static void +FormAlliance (RESPONSE_REF R) +{ + NPCPhrase (ALLY_WITH_US0); + NPCPhrase (ALLY_WITH_US1); + NPCPhrase (ALLY_WITH_US2); + NPCPhrase (ALLY_WITH_US3); + NPCPhrase (ALLY_WITH_US4); + NPCPhrase (ALLY_WITH_US5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + Response (sure, ExitConversation); + Response (never, ExitConversation); + Response (decide_later, ExitConversation); +} + +static void +ZoqFotIntro (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, we_are_vindicator0)) + { + NPCPhrase (WE_GLAD0); + NPCPhrase (WE_GLAD1); + NPCPhrase (WE_GLAD2); + NPCPhrase (WE_GLAD3); + NPCPhrase (WE_GLAD4); + NPCPhrase (WE_GLAD5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (we_are_vindicator0); + } + else if (PLAYER_SAID (R, your_race)) + { + NPCPhrase (YEARS_AGO0); + NPCPhrase (YEARS_AGO1); + NPCPhrase (YEARS_AGO2); + NPCPhrase (YEARS_AGO3); + NPCPhrase (YEARS_AGO4); + NPCPhrase (YEARS_AGO5); + NPCPhrase (YEARS_AGO6); + NPCPhrase (YEARS_AGO7); + NPCPhrase (YEARS_AGO8); + NPCPhrase (YEARS_AGO9); + NPCPhrase (YEARS_AGO10); + NPCPhrase (YEARS_AGO11); + NPCPhrase (YEARS_AGO12); + NPCPhrase (YEARS_AGO13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien (12, PIK_ALIEN); + SelectAlien (13, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (your_race); + } + else if (PLAYER_SAID (R, where_from)) + { + NPCPhrase (TRAVELED_FAR0); + NPCPhrase (TRAVELED_FAR1); + NPCPhrase (TRAVELED_FAR2); + NPCPhrase (TRAVELED_FAR3); + NPCPhrase (TRAVELED_FAR4); + NPCPhrase (TRAVELED_FAR5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (where_from); + } + else if (PLAYER_SAID (R, what_emergency)) + { + NPCPhrase (UNDER_ATTACK0); + NPCPhrase (UNDER_ATTACK1); + NPCPhrase (UNDER_ATTACK2); + NPCPhrase (UNDER_ATTACK3); + NPCPhrase (UNDER_ATTACK4); + NPCPhrase (UNDER_ATTACK5); + NPCPhrase (UNDER_ATTACK6); + NPCPhrase (UNDER_ATTACK7); + NPCPhrase (UNDER_ATTACK8); + NPCPhrase (UNDER_ATTACK9); + NPCPhrase (UNDER_ATTACK10); + NPCPhrase (UNDER_ATTACK11); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_emergency); + } + else if (PLAYER_SAID (R, tough_luck)) + { + NPCPhrase (NOT_HELPFUL0); + NPCPhrase (NOT_HELPFUL1); + NPCPhrase (NOT_HELPFUL2); + NPCPhrase (NOT_HELPFUL3); + NPCPhrase (NOT_HELPFUL4); + NPCPhrase (NOT_HELPFUL5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (tough_luck); + } + else if (PLAYER_SAID (R, what_look_like)) + { + NPCPhrase (LOOK_LIKE0); + NPCPhrase (LOOK_LIKE1); + NPCPhrase (LOOK_LIKE2); + NPCPhrase (LOOK_LIKE3); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_look_like); + } + +// printf ("yr = 0x%x wf = 0x%x\n", alien_text[your_race][0], alien_text[where_from][0]); +// printf ("we = 0x%x tl = 0x%x\n", alien_text[what_emergency][0], alien_text[tough_luck][0]); +// printf ("wll = 0x%x\n", what_look_like); + if (PHRASE_ENABLED (your_race) + || PHRASE_ENABLED (where_from) + || PHRASE_ENABLED (what_emergency)) + { + if (PHRASE_ENABLED (your_race)) + Response (your_race, ZoqFotIntro); + if (PHRASE_ENABLED (where_from)) + Response (where_from, ZoqFotIntro); + if (PHRASE_ENABLED (what_emergency)) + Response (what_emergency, ZoqFotIntro); + } + else + { + if (PHRASE_ENABLED (tough_luck)) + Response (tough_luck, ZoqFotIntro); + if (PHRASE_ENABLED (what_look_like)) + Response (what_look_like, ZoqFotIntro); + Response (all_very_interesting, ExitConversation); + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + Response (how_can_i_help, FormAlliance); + } + else + { + Response (how_can_i_help, ExitConversation); + } + Response (valuable_info, ExitConversation); + } +} + +static void +AquaintZoqFot (RESPONSE_REF R) +{ + if (PLAYER_SAID (R, which_fot)) + { + NPCPhrase (HE_IS0); + NPCPhrase (HE_IS1); + NPCPhrase (HE_IS2); + NPCPhrase (HE_IS3); + NPCPhrase (HE_IS4); + NPCPhrase (HE_IS5); + NPCPhrase (HE_IS6); + NPCPhrase (HE_IS7); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (which_fot); + } + else if (PLAYER_SAID (R, quiet_toadies)) + { + NPCPhrase (TOLD_YOU0); + NPCPhrase (TOLD_YOU1); + NPCPhrase (TOLD_YOU2); + NPCPhrase (TOLD_YOU3); + NPCPhrase (TOLD_YOU4); + NPCPhrase (TOLD_YOU5); + NPCPhrase (TOLD_YOU6); + NPCPhrase (TOLD_YOU7); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (quiet_toadies); + } + + if (PHRASE_ENABLED (we_are_vindicator0)) + { + UNICODE buf[80]; + + GetAllianceName (buf, name_1); + construct_response ( + shared_phrase_buf, + we_are_vindicator0, + (vararg_dcl)buf, + we_are_vindicator1, + GLOBAL_SIS (ShipName), + we_are_vindicator2, + 0 + ); + } + + if (PHRASE_ENABLED (which_fot)) + Response (which_fot, AquaintZoqFot); + if (PHRASE_ENABLED (we_are_vindicator0)) + DoResponsePhrase (we_are_vindicator0, ZoqFotIntro, shared_phrase_buf); + if (PHRASE_ENABLED (quiet_toadies)) + Response (quiet_toadies, AquaintZoqFot); + Response (all_very_interesting, ExitConversation); + Response (valuable_info, ExitConversation); +} + +static void ZoqFotHome (RESPONSE_REF R); + +static void +ZoqFotInfo (RESPONSE_REF R) +{ + BYTE InfoLeft; + + if (PLAYER_SAID (R, want_specific_info)) + { + NPCPhrase (WHAT_SPECIFIC_INFO0); + NPCPhrase (WHAT_SPECIFIC_INFO1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else if (PLAYER_SAID (R, what_about_others)) + { + NPCPhrase (ABOUT_OTHERS0); + NPCPhrase (ABOUT_OTHERS1); + NPCPhrase (ABOUT_OTHERS2); + NPCPhrase (ABOUT_OTHERS3); + NPCPhrase (ABOUT_OTHERS4); + NPCPhrase (ABOUT_OTHERS5); + NPCPhrase (ABOUT_OTHERS6); + NPCPhrase (ABOUT_OTHERS7); + NPCPhrase (ABOUT_OTHERS8); + NPCPhrase (ABOUT_OTHERS9); + NPCPhrase (ABOUT_OTHERS10); + NPCPhrase (ABOUT_OTHERS11); + NPCPhrase (ABOUT_OTHERS12); + NPCPhrase (ABOUT_OTHERS13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien (12, PIK_ALIEN); + SelectAlien (13, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_about_others); + } + else if (PLAYER_SAID (R, what_about_zebranky)) + { + NPCPhrase (ABOUT_ZEBRANKY0); + NPCPhrase (ABOUT_ZEBRANKY1); + NPCPhrase (ABOUT_ZEBRANKY2); + NPCPhrase (ABOUT_ZEBRANKY3); + NPCPhrase (ABOUT_ZEBRANKY4); + NPCPhrase (ABOUT_ZEBRANKY5); + NPCPhrase (ABOUT_ZEBRANKY6); + NPCPhrase (ABOUT_ZEBRANKY7); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_about_zebranky); + } + else if (PLAYER_SAID (R, what_about_stinger)) + { + NPCPhrase (ABOUT_STINGER0); + NPCPhrase (ABOUT_STINGER1); + NPCPhrase (ABOUT_STINGER2); + NPCPhrase (ABOUT_STINGER3); + NPCPhrase (ABOUT_STINGER4); + NPCPhrase (ABOUT_STINGER5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_about_stinger); + } + else if (PLAYER_SAID (R, what_about_guy_in_back)) + { + NPCPhrase (ABOUT_GUY0); + NPCPhrase (ABOUT_GUY1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_about_guy_in_back); + } + else if (PLAYER_SAID (R, what_about_past)) + { + NPCPhrase (ABOUT_PAST0); + NPCPhrase (ABOUT_PAST1); + NPCPhrase (ABOUT_PAST2); + NPCPhrase (ABOUT_PAST3); + NPCPhrase (ABOUT_PAST4); + NPCPhrase (ABOUT_PAST5); + NPCPhrase (ABOUT_PAST6); + NPCPhrase (ABOUT_PAST7); + NPCPhrase (ABOUT_PAST8); + NPCPhrase (ABOUT_PAST9); + NPCPhrase (ABOUT_PAST10); + NPCPhrase (ABOUT_PAST11); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + DISABLE_PHRASE (what_about_past); + } + + InfoLeft = FALSE; + if (PHRASE_ENABLED (what_about_others)) + { + Response (what_about_others, ZoqFotInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_zebranky)) + { + Response (what_about_zebranky, ZoqFotInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_stinger)) + { + Response (what_about_stinger, ZoqFotInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_guy_in_back)) + { + Response (what_about_guy_in_back, ZoqFotInfo); + InfoLeft = TRUE; + } + if (PHRASE_ENABLED (what_about_past)) + { + Response (what_about_past, ZoqFotInfo); + InfoLeft = TRUE; + } + Response (enough_info, ZoqFotHome); + + if (!InfoLeft) + { + DISABLE_PHRASE (want_specific_info); + } +} + +static void +ZoqFotHome (RESPONSE_REF R) +{ + BYTE NumVisits; + + if (PLAYER_SAID (R, whats_up_homeworld)) + { + NumVisits = GET_GAME_STATE (ZOQFOT_INFO); + switch (NumVisits++) + { + case 0: + NPCPhrase (GENERAL_INFO_10); + NPCPhrase (GENERAL_INFO_11); + NPCPhrase (GENERAL_INFO_12); + NPCPhrase (GENERAL_INFO_13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 1: + NPCPhrase (GENERAL_INFO_20); + NPCPhrase (GENERAL_INFO_21); + NPCPhrase (GENERAL_INFO_22); + NPCPhrase (GENERAL_INFO_23); + NPCPhrase (GENERAL_INFO_24); + NPCPhrase (GENERAL_INFO_25); + NPCPhrase (GENERAL_INFO_26); + NPCPhrase (GENERAL_INFO_27); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 2: + NPCPhrase (GENERAL_INFO_30); + NPCPhrase (GENERAL_INFO_31); + NPCPhrase (GENERAL_INFO_32); + NPCPhrase (GENERAL_INFO_33); + NPCPhrase (GENERAL_INFO_34); + NPCPhrase (GENERAL_INFO_35); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 3: + NPCPhrase (GENERAL_INFO_40); + NPCPhrase (GENERAL_INFO_41); + NPCPhrase (GENERAL_INFO_42); + NPCPhrase (GENERAL_INFO_43); + NPCPhrase (GENERAL_INFO_44); + NPCPhrase (GENERAL_INFO_45); + NPCPhrase (GENERAL_INFO_46); + NPCPhrase (GENERAL_INFO_47); + NPCPhrase (GENERAL_INFO_48); + NPCPhrase (GENERAL_INFO_49); + NPCPhrase (GENERAL_INFO_410); + NPCPhrase (GENERAL_INFO_411); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + --NumVisits; + break; + } + SET_GAME_STATE (ZOQFOT_INFO, NumVisits); + + DISABLE_PHRASE (whats_up_homeworld); + } + else if (PLAYER_SAID (R, any_war_news)) + { +#define UTWIG_BUY_TIME (1 << 0) +#define KOHR_AH_WIN (1 << 1) +#define URQUAN_LOSE (1 << 2) +#define KOHR_AH_KILL (1 << 3) +#define KNOW_ALL (UTWIG_BUY_TIME | KOHR_AH_WIN | URQUAN_LOSE | KOHR_AH_KILL) + BYTE KnowMask; + + NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + KnowMask = GET_GAME_STATE (ZOQFOT_KNOW_MASK); + if (!(KnowMask & KOHR_AH_KILL) && GET_GAME_STATE (KOHR_AH_FRENZY)) + { + NPCPhrase (KOHRAH_FRENZY0); + NPCPhrase (KOHRAH_FRENZY1); + NPCPhrase (KOHRAH_FRENZY2); + NPCPhrase (KOHRAH_FRENZY3); + NPCPhrase (KOHRAH_FRENZY4); + NPCPhrase (KOHRAH_FRENZY5); + NPCPhrase (KOHRAH_FRENZY6); + NPCPhrase (KOHRAH_FRENZY7); + NPCPhrase (KOHRAH_FRENZY8); + NPCPhrase (KOHRAH_FRENZY9); + NPCPhrase (KOHRAH_FRENZY10); + NPCPhrase (KOHRAH_FRENZY11); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + KnowMask = KNOW_ALL; + } + else if (!(KnowMask & UTWIG_BUY_TIME) + && NumVisits > 0 && NumVisits < 5) + { + NPCPhrase (UTWIG_DELAY0); + NPCPhrase (UTWIG_DELAY1); + NPCPhrase (UTWIG_DELAY2); + NPCPhrase (UTWIG_DELAY3); + NPCPhrase (UTWIG_DELAY4); + NPCPhrase (UTWIG_DELAY5); + NPCPhrase (UTWIG_DELAY6); + NPCPhrase (UTWIG_DELAY7); + NPCPhrase (UTWIG_DELAY8); + NPCPhrase (UTWIG_DELAY9); + NPCPhrase (UTWIG_DELAY10); + NPCPhrase (UTWIG_DELAY11); + NPCPhrase (UTWIG_DELAY12); + NPCPhrase (UTWIG_DELAY13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien (12, PIK_ALIEN); + SelectAlien (13, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + KnowMask |= UTWIG_BUY_TIME; + } + else + { + SIZE i; + + i = START_YEAR + YEARS_TO_KOHRAH_VICTORY; + if (NumVisits) + ++i; + if ((i -= GLOBAL (GameClock.year_index)) == 1 + && GLOBAL (GameClock.month_index) > 2) + i = 0; + if (!(KnowMask & URQUAN_LOSE) && i <= 0) + { + NPCPhrase (URQUAN_NEARLY_GONE0); + NPCPhrase (URQUAN_NEARLY_GONE1); + NPCPhrase (URQUAN_NEARLY_GONE2); + NPCPhrase (URQUAN_NEARLY_GONE3); + NPCPhrase (URQUAN_NEARLY_GONE4); + NPCPhrase (URQUAN_NEARLY_GONE5); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + KnowMask |= KOHR_AH_WIN | URQUAN_LOSE; + } + else if (!(KnowMask & KOHR_AH_WIN) && i == 1) + { + NPCPhrase (KOHRAH_WINNING0); + NPCPhrase (KOHRAH_WINNING1); + NPCPhrase (KOHRAH_WINNING2); + NPCPhrase (KOHRAH_WINNING3); + NPCPhrase (KOHRAH_WINNING4); + NPCPhrase (KOHRAH_WINNING5); + NPCPhrase (KOHRAH_WINNING6); + NPCPhrase (KOHRAH_WINNING7); + NPCPhrase (KOHRAH_WINNING8); + NPCPhrase (KOHRAH_WINNING9); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + KnowMask |= KOHR_AH_WIN; + } + else + { + NPCPhrase (NO_WAR_NEWS0); + NPCPhrase (NO_WAR_NEWS1); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + } + SET_GAME_STATE (ZOQFOT_KNOW_MASK, KnowMask); + + DISABLE_PHRASE (any_war_news); + } + else if (PLAYER_SAID (R, i_want_alliance)) + { + NPCPhrase (GOOD0); + NPCPhrase (GOOD1); + NPCPhrase (GOOD2); + NPCPhrase (GOOD3); + NPCPhrase (GOOD4); + NPCPhrase (GOOD5); + NPCPhrase (GOOD6); + NPCPhrase (GOOD7); + NPCPhrase (GOOD8); + NPCPhrase (GOOD9); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + ActivateStarShip (ZOQFOTPIK_SHIP, 0); + AddEvent (RELATIVE_EVENT, 3, 0, 0, ZOQFOT_DISTRESS_EVENT); + } + else if (PLAYER_SAID (R, enough_info)) + { + NPCPhrase (OK_ENOUGH_INFO); + SelectAlien ((COUNT)~0, ZOQ_ALIEN); + } + + if (PHRASE_ENABLED (whats_up_homeworld)) + Response (whats_up_homeworld, ZoqFotHome); + if (PHRASE_ENABLED (any_war_news)) + Response (any_war_news, ZoqFotHome); + if (!(ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) + Response (i_want_alliance, ZoqFotHome); + else if (PHRASE_ENABLED (want_specific_info)) + { + Response (want_specific_info, ZoqFotInfo); + } + Response (bye_homeworld, ExitConversation); +} + +static void +Intro (void) +{ + BYTE NumVisits; + + if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { +#ifdef NOT_YET + NPCPhrase (OUT_TAKES0); + NPCPhrase (OUT_TAKES1); + NPCPhrase (OUT_TAKES2); + NPCPhrase (OUT_TAKES3); + NPCPhrase (OUT_TAKES4); + NPCPhrase (OUT_TAKES5); + NPCPhrase (OUT_TAKES6); + NPCPhrase (OUT_TAKES7); + NPCPhrase (OUT_TAKES8); + NPCPhrase (OUT_TAKES9); + NPCPhrase (OUT_TAKES10); + NPCPhrase (OUT_TAKES11); + NPCPhrase (OUT_TAKES12); + NPCPhrase (OUT_TAKES13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien (12, PIK_ALIEN); + SelectAlien (13, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); +#else /* YET */ + NPCPhrase (WE_ARE0); + NPCPhrase (WE_ARE1); + NPCPhrase (WE_ARE2); + NPCPhrase (WE_ARE3); + NPCPhrase (WE_ARE4); + NPCPhrase (WE_ARE5); + NPCPhrase (WE_ARE6); + NPCPhrase (WE_ARE7); + NPCPhrase (SCOUT_HELLO0); + NPCPhrase (SCOUT_HELLO1); + NPCPhrase (SCOUT_HELLO2); + NPCPhrase (SCOUT_HELLO3); + + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); +#endif /* NOT_YET */ + SET_GAME_STATE (BATTLE_SEGUE, 0); + goto ExitIntro; + } + + if (GET_GAME_STATE (ZOQFOT_HOSTILE)) + { + NumVisits = GET_GAME_STATE (ZOQFOT_HOME_VISITS); + switch (NumVisits++) + { + case 0: + NPCPhrase (HOSTILE_HELLO_10); + NPCPhrase (HOSTILE_HELLO_11); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 1: + NPCPhrase (HOSTILE_HELLO_20); + NPCPhrase (HOSTILE_HELLO_21); + NPCPhrase (HOSTILE_HELLO_22); + NPCPhrase (HOSTILE_HELLO_23); + NPCPhrase (HOSTILE_HELLO_24); + NPCPhrase (HOSTILE_HELLO_25); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 2: + NPCPhrase (HOSTILE_HELLO_30); + NPCPhrase (HOSTILE_HELLO_31); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 3: + NPCPhrase (HOSTILE_HELLO_40); + NPCPhrase (HOSTILE_HELLO_41); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + --NumVisits; + break; + } + SET_GAME_STATE (ZOQFOT_HOME_VISITS, NumVisits); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + else if (!GET_GAME_STATE (MET_ZOQFOT)) + { + SET_GAME_STATE (MET_ZOQFOT, 1); + + NPCPhrase (WE_ARE0); + NPCPhrase (WE_ARE1); + NPCPhrase (WE_ARE2); + NPCPhrase (WE_ARE3); + NPCPhrase (WE_ARE4); + NPCPhrase (WE_ARE5); + NPCPhrase (WE_ARE6); + NPCPhrase (WE_ARE7); + + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) + { + NPCPhrase (INIT_HOME_HELLO0); + NPCPhrase (INIT_HOME_HELLO1); + NPCPhrase (INIT_HOME_HELLO2); + NPCPhrase (INIT_HOME_HELLO3); + } + else + { + NPCPhrase (SCOUT_HELLO0); + NPCPhrase (SCOUT_HELLO1); + NPCPhrase (SCOUT_HELLO2); + NPCPhrase (SCOUT_HELLO3); + } + + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + AquaintZoqFot (0); + } + else + { + if (GET_GAME_STATE (ZOQFOT_DISTRESS)) + { +#define MAX_ZFP_SHIPS 4 + NPCPhrase (THANKS_FOR_RESCUE0); + NPCPhrase (THANKS_FOR_RESCUE1); + NPCPhrase (THANKS_FOR_RESCUE2); + NPCPhrase (THANKS_FOR_RESCUE3); + NPCPhrase (THANKS_FOR_RESCUE4); + NPCPhrase (THANKS_FOR_RESCUE5); + NPCPhrase (THANKS_FOR_RESCUE6); + NPCPhrase (THANKS_FOR_RESCUE7); + NPCPhrase (THANKS_FOR_RESCUE8); + NPCPhrase (THANKS_FOR_RESCUE9); + NPCPhrase (THANKS_FOR_RESCUE10); + NPCPhrase (THANKS_FOR_RESCUE11); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien (8, PIK_ALIEN); + SelectAlien (9, ZOQ_ALIEN); + SelectAlien (10, PIK_ALIEN); + SelectAlien (11, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + + SET_GAME_STATE (ZOQFOT_DISTRESS, 0); + ActivateStarShip (ZOQFOTPIK_SHIP, MAX_ZFP_SHIPS); + } + else + { + NumVisits = GET_GAME_STATE (ZOQFOT_HOME_VISITS); + if (!(ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) + { + switch (NumVisits++) + { + case 0: + NPCPhrase (NEUTRAL_HOME_HELLO_10); + NPCPhrase (NEUTRAL_HOME_HELLO_11); + NPCPhrase (NEUTRAL_HOME_HELLO_12); + NPCPhrase (NEUTRAL_HOME_HELLO_13); + break; + case 1: + NPCPhrase (NEUTRAL_HOME_HELLO_20); + NPCPhrase (NEUTRAL_HOME_HELLO_21); + NPCPhrase (NEUTRAL_HOME_HELLO_22); + NPCPhrase (NEUTRAL_HOME_HELLO_23); + --NumVisits; + break; + } + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + } + else + { + switch (NumVisits++) + { + case 0: + NPCPhrase (ALLIED_HOME_HELLO_10); + NPCPhrase (ALLIED_HOME_HELLO_11); + NPCPhrase (ALLIED_HOME_HELLO_12); + NPCPhrase (ALLIED_HOME_HELLO_13); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 1: + NPCPhrase (ALLIED_HOME_HELLO_20); + NPCPhrase (ALLIED_HOME_HELLO_21); + NPCPhrase (ALLIED_HOME_HELLO_22); + NPCPhrase (ALLIED_HOME_HELLO_23); + NPCPhrase (ALLIED_HOME_HELLO_24); + NPCPhrase (ALLIED_HOME_HELLO_25); + NPCPhrase (ALLIED_HOME_HELLO_26); + NPCPhrase (ALLIED_HOME_HELLO_27); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien (2, PIK_ALIEN); + SelectAlien (3, ZOQ_ALIEN); + SelectAlien (4, PIK_ALIEN); + SelectAlien (5, ZOQ_ALIEN); + SelectAlien (6, PIK_ALIEN); + SelectAlien (7, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 2: + NPCPhrase (ALLIED_HOME_HELLO_30); + NPCPhrase (ALLIED_HOME_HELLO_31); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + break; + case 3: + NPCPhrase (ALLIED_HOME_HELLO_40); + NPCPhrase (ALLIED_HOME_HELLO_41); + SelectAlien (1, ZOQ_ALIEN); + SelectAlien ((COUNT)~0, PIK_ALIEN); + --NumVisits; + break; + } + } + SET_GAME_STATE (ZOQFOT_HOME_VISITS, NumVisits); + } + + ZoqFotHome (0); + } +ExitIntro: + ; +} + +static COUNT +uninit_zoqfot (void) +{ + return (0); +} + +LOCDATAPTR +init_zoqfot_comm (void) +{ + LOCDATAPTR retval; + + zoqfot_desc.init_encounter_func = Intro; + zoqfot_desc.uninit_encounter_func = uninit_zoqfot; + + zoqfot_desc.AlienTextTemplate.align = ALIGN_CENTER; + zoqfot_desc.AlienTextWidth = (SIS_TEXT_WIDTH >> 1) - TEXT_X_OFFS; + + if ((ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY) + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + } + else + { + SET_GAME_STATE (BATTLE_SEGUE, 1); + } + + retval = &zoqfot_desc; + + return (retval); +} + diff --git a/sc2/src/sc2code/commglue.c b/sc2/src/sc2code/commglue.c new file mode 100644 index 000000000..1498a86cf --- /dev/null +++ b/sc2/src/sc2code/commglue.c @@ -0,0 +1,205 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "commglue.h" +#include "SDL_wrapper.h" + +void +NPCPhrase (int index) +{ + UNICODE *pStr, numbuf[100]; + void *pClip; + + switch (index) + { + case GLOBAL_PLAYER_NAME: + pStr = GLOBAL_SIS (CommanderName); + pClip = 0; + break; + case GLOBAL_SHIP_NAME: + pStr = GLOBAL_SIS (ShipName); + pClip = 0; + break; + case GLOBAL_PLAYER_LOCATION: + { + SIZE dx, dy; + COUNT adx, ady; + + dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) - 333; + adx = dx >= 0 ? dx : -dx; + dy = 9812 - LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + ady = dy >= 0 ? dy : -dy; + wsprintf (numbuf, + "%+04d.%01u,%+04d.%01u", + (SIZE)(dy / 10), (COUNT)(ady % 10), + (SIZE)(dx / 10), (COUNT)(adx % 10)); + pStr = numbuf; + pClip = 0; + break; + } + default: + if (index < 0) + { + if (index > UNREASONABLE_NUMBER) + sprintf (numbuf, "%d", -index); + else + { + COUNT i; + STRING S; + + index -= GLOBAL_ALLIANCE_NAME; + + i = GET_GAME_STATE (NEW_ALLIANCE_NAME); + S = SetAbsStringTableIndex (CommData.ConversationPhrases, (index - 1) + i); + wstrcpy (numbuf, (UNICODE *)GetStringAddress (S)); + if (i == 3) + wstrcat (numbuf, GLOBAL_SIS (CommanderName)); + } + pStr = numbuf; + pClip = 0; + } + else + { + pStr = (UNICODE *)GetStringAddress ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) + ); + pClip = GetStringSoundClip ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) + ); + } + break; + } + + SpliceTrack (pClip, pStr); +} + +void +GetAllianceName (UNICODE *buf, RESPONSE_REF name_1) +{ + COUNT i; + STRING S; + + i = GET_GAME_STATE (NEW_ALLIANCE_NAME); + S = SetAbsStringTableIndex (CommData.ConversationPhrases, (name_1 - 1) + i); + wstrcpy (buf, (UNICODE *)GetStringAddress (S)); + if (i == 3) + { + wstrcat (buf, GLOBAL_SIS (CommanderName)); + wstrcat (buf, (UNICODE *)GetStringAddress (SetRelStringTableIndex (S, 1))); + } +} + +void +construct_response (UNICODE *buf, RESPONSE_REF R, vararg_dcl c_args, + ...) +{ + UNICODE *name; + vararg_list vlist; + + vararg_start (vlist, c_args); + do + { + COUNT len; + STRING S; + + S = SetAbsStringTableIndex (CommData.ConversationPhrases, R - 1); + wstrcpy (buf, (UNICODE *)GetStringAddress (S)); + len = wstrlen (buf); + buf += len; + name = vararg_val (vlist, UNICODE *); + if (name) + { + len = wstrlen (name); + wstrncpy (buf, name, len); + buf += len; + + if ((R = vararg_val (vlist, RESPONSE_REF)) == (RESPONSE_REF)-1) + name = 0; + } + } while (name); + vararg_end (vlist); + + *buf = '\0'; +} + +LOCDATAPTR +init_race (RESOURCE comm_id) +{ + switch (comm_id) + { + case ARILOU_CONVERSATION: + return ((LOCDATAPTR)init_arilou_comm ()); + case BLACKURQ_CONVERSATION: + return ((LOCDATAPTR)init_blackurq_comm ()); + case CHMMR_CONVERSATION: + return ((LOCDATAPTR)init_chmmr_comm ()); + case COMMANDER_CONVERSATION: + if (!GET_GAME_STATE (STARBASE_AVAILABLE)) + return ((LOCDATAPTR)init_commander_comm ()); + else + return ((LOCDATAPTR)init_starbase_comm ()); + case DRUUGE_CONVERSATION: + return ((LOCDATAPTR)init_druuge_comm ()); + case ILWRATH_CONVERSATION: + return ((LOCDATAPTR)init_ilwrath_comm ()); + case MELNORME_CONVERSATION: + return ((LOCDATAPTR)init_melnorme_comm ()); + case MYCON_CONVERSATION: + return ((LOCDATAPTR)init_mycon_comm ()); + case ORZ_CONVERSATION: + return ((LOCDATAPTR)init_orz_comm ()); + case PKUNK_CONVERSATION: + return ((LOCDATAPTR)init_pkunk_comm ()); + case SHOFIXTI_CONVERSATION: + return ((LOCDATAPTR)init_shofixti_comm ()); + case SLYLANDRO_CONVERSATION: + return ((LOCDATAPTR)init_slyland_comm ()); + case SLYLANDRO_HOME_CONVERSATION: + return ((LOCDATAPTR)init_slylandro_comm ()); + case SPATHI_CONVERSATION: + if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + return ((LOCDATAPTR)init_spathi_comm ()); + else + return ((LOCDATAPTR)init_spahome_comm ()); + case SUPOX_CONVERSATION: + return ((LOCDATAPTR)init_supox_comm ()); + case SYREEN_CONVERSATION: + return ((LOCDATAPTR)init_syreen_comm ()); + case TALKING_PET_CONVERSATION: + return ((LOCDATAPTR)init_talkpet_comm ()); + case THRADD_CONVERSATION: + return ((LOCDATAPTR)init_thradd_comm ()); + case UMGAH_CONVERSATION: + return ((LOCDATAPTR)init_umgah_comm ()); + case URQUAN_CONVERSATION: + return ((LOCDATAPTR)init_urquan_comm ()); + case UTWIG_CONVERSATION: + return ((LOCDATAPTR)init_utwig_comm ()); + case VUX_CONVERSATION: + return ((LOCDATAPTR)init_vux_comm ()); + case YEHAT_REBEL_CONVERSATION: + return ((LOCDATAPTR)init_rebel_yehat_comm ()); + case YEHAT_CONVERSATION: + return ((LOCDATAPTR)init_yehat_comm ()); + case ZOQFOTPIK_CONVERSATION: + return ((LOCDATAPTR)init_zoqfot_comm ()); + default: + return ((LOCDATAPTR)init_chmmr_comm ()); + } +} diff --git a/sc2/src/sc2code/commglue.h b/sc2/src/sc2code/commglue.h new file mode 100644 index 000000000..758de0e49 --- /dev/null +++ b/sc2/src/sc2code/commglue.h @@ -0,0 +1,126 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _COMMGLUE_H +#define _COMMGLUE_H + +extern LOCDATA CommData; +extern int cur_comm; +extern UNICODE shared_phrase_buf[256]; + +#define PLAYER_SAID(r,i) ((r)==(i)) +#define PHRASE_ENABLED(p) \ + (*(UNICODE *)GetStringAddress ( \ + SetAbsStringTableIndex (CommData.ConversationPhrases, (p)-1) \ + ) != '\0') +#define DISABLE_PHRASE(p) \ + (*(UNICODE *)GetStringAddress ( \ + SetAbsStringTableIndex (CommData.ConversationPhrases, (p)-1) \ + ) = '\0') +#define RESPONSE_TO_REF(R) (R) + +#define Response(i,a) \ + DoResponsePhrase(i,(RESPONSE_FUNC)a,0) + +enum +{ + GLOBAL_PLAYER_NAME = -1000000, + GLOBAL_SHIP_NAME, + GLOBAL_PLAYER_LOCATION, + + GLOBAL_ALLIANCE_NAME, + UNREASONABLE_NUMBER = GLOBAL_ALLIANCE_NAME + 1000, +}; + +typedef COUNT RESPONSE_REF; + +typedef void (*RESPONSE_FUNC) (RESPONSE_REF R); + +extern void DoResponsePhrase (RESPONSE_REF R, RESPONSE_FUNC + response_func, UNICODE *ContstructStr); +extern void DoNPCPhrase (UNICODE *pStr); + +extern void NPCPhrase (int index); + +extern void GetAllianceName (UNICODE *buf, RESPONSE_REF name_1); + +extern void construct_response (UNICODE *buf, RESPONSE_REF R, vararg_dcl + c_args, ...); + +extern LOCDATAPTR init_race (RESOURCE comm_id); + +extern LOCDATAPTR init_arilou_comm (void); + +extern LOCDATAPTR init_blackurq_comm (void); + +extern LOCDATAPTR init_chmmr_comm (void); + +extern LOCDATAPTR init_commander_comm (void); + +extern LOCDATAPTR init_druuge_comm (void); + +extern LOCDATAPTR init_ilwrath_comm (void); + +extern LOCDATAPTR init_melnorme_comm (void); + +extern LOCDATAPTR init_mycon_comm (void); + +extern LOCDATAPTR init_orz_comm (void); + +extern LOCDATAPTR init_pkunk_comm (void); + +extern LOCDATAPTR init_rebel_yehat_comm (void); + +extern LOCDATAPTR init_shofixti_comm (void); + +extern LOCDATAPTR init_slyland_comm (void); + +extern LOCDATAPTR init_slylandro_comm (void); + +extern LOCDATAPTR init_spahome_comm (void); + +extern LOCDATAPTR init_spathi_comm (void); + +extern LOCDATAPTR init_starbase_comm (void); + +extern LOCDATAPTR init_supox_comm (void); + +extern LOCDATAPTR init_syreen_comm (void); + +extern LOCDATAPTR init_talkpet_comm (void); + +extern LOCDATAPTR init_thradd_comm (void); + +extern LOCDATAPTR init_umgah_comm (void); + +extern LOCDATAPTR init_urquan_comm (void); + +extern LOCDATAPTR init_utwig_comm (void); + +extern LOCDATAPTR init_vux_comm (void); + +extern LOCDATAPTR init_yehat_comm (void); + +extern LOCDATAPTR init_zoqfot_comm (void); + +extern LOCDATAPTR init_umgah_comm (void); + +extern DWORD XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval); + +#endif /* _COMMGLUE_H */ + diff --git a/sc2/src/sc2code/confirm.c b/sc2/src/sc2code/confirm.c new file mode 100644 index 000000000..d83689544 --- /dev/null +++ b/sc2/src/sc2code/confirm.c @@ -0,0 +1,111 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "commglue.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void WaitForNoInput (SIZE Duration); + +//End Added by Chris + +INPUT_STATE +ConfirmExit (void) +{ + INPUT_STATE InputState; + BOOLEAN ClockActive; + + ClockActive = (BOOLEAN)(LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE + && GameClockRunning ()); + if (ClockActive) + SuspendGameClock (); + else if (CommData.ConversationPhrases && PlayingTrack ()) + PauseTrack (); + + SetSemaphore (&GraphicsSem); + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + InputState = DEVICE_EXIT; + else + { + RECT r; + STAMP s; + FRAME F; + CONTEXT oldContext; + DRAW_STATE oldDrawState; + + oldContext = SetContext (ScreenContext); + oldDrawState = SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + s.frame = SetAbsFrameIndex (ActivityFrame, 1); + GetFrameRect (s.frame, &r); + r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; + r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; + s.origin = r.corner; + F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); + DrawStamp (&s); + + FlushGraphics (); + + { + INPUT_STATE PressState; + + GLOBAL (CurrentActivity) |= CHECK_ABORT; + + PressState = GetInputState (NormalInput); + do + { + TaskSwitch (); + InputState = GetInputState (NormalInput); + if (PressState) + { + PressState = InputState; + InputState = 0; + } + } while (!InputState); + } + + s.frame = F; + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + + if (InputState & DEVICE_BUTTON2) + InputState = DEVICE_EXIT; + else + { + InputState = 0; + GLOBAL (CurrentActivity) &= ~CHECK_ABORT; + WaitForNoInput (ONE_SECOND / 4); + FlushInput (); + } + + SetContextDrawState (oldDrawState); + SetContext (oldContext); + } + ClearSemaphore (&GraphicsSem); + + if (ClockActive) + ResumeGameClock (); + else if (CommData.ConversationPhrases && PlayingTrack ()) + ResumeTrack (); + + return (InputState); +} + + diff --git a/sc2/src/sc2code/credits.c b/sc2/src/sc2code/credits.c new file mode 100644 index 000000000..751eb1670 --- /dev/null +++ b/sc2/src/sc2code/credits.c @@ -0,0 +1,116 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void FreeSC2Data (void); + +void FreeLanderData (void); + +void FreeIPData (void); + +void FreeMasterShipList (void); + +void UninitSpace (void); + +void FreeHyperData (void); + +//End Added by Chris + +void +Credits (void) +{ +#define NUM_CREDITS 20 + COUNT i; + RES_TYPE rt; + RES_INSTANCE ri; + RES_PACKAGE rp; + RECT r; + FRAME f[NUM_CREDITS]; + STAMP s; + DWORD TimeIn; + MUSIC_REF hMusic; + BYTE fade_buf[1]; + +FreeSC2Data (); +FreeLanderData (); +FreeIPData (); +FreeHyperData (); + rt = GET_TYPE (CREDIT00_ANIM); + ri = GET_INSTANCE (CREDIT00_ANIM); + rp = GET_PACKAGE (CREDIT00_ANIM); + for (i = 0; i < NUM_CREDITS; ++i, ++rp, ++ri) + { + f[i] = CaptureDrawable (LoadGraphic ( + MAKE_RESOURCE (rp, rt, ri) + )); + } + + hMusic = LoadMusicInstance (CREDITS_MUSIC); + if (hMusic) + PlayMusic (hMusic, TRUE, 1); + + SetSemaphore (&GraphicsSem); + SetContext (ScreenContext); + GetContextClipRect (&r); + s.origin.x = s.origin.y = 0; + + BatchGraphics (); + s.frame = f[0]; + DrawStamp (&s); + UnbatchGraphics (); + + fade_buf[0] = FadeAllToColor; + SleepTask (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); + + TimeIn = GetTimeCounter (); + for (i = 1; i < NUM_CREDITS; ++i) + { + BatchGraphics (); + s.frame = f[0]; + DrawStamp (&s); + s.frame = f[i]; + DrawStamp (&s); + ScreenTransition (3, &r); + UnbatchGraphics (); + DestroyDrawable (ReleaseDrawable (f[i])); + + TimeIn = SleepTask (TimeIn + ONE_SECOND * 5); + } + + DestroyDrawable (ReleaseDrawable (f[0])); + ClearSemaphore (&GraphicsSem); + + while (!AnyButtonPress (FALSE)); + while (AnyButtonPress (FALSE)); + + fade_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); + FlushColorXForms (); + + if (hMusic) + { + StopMusic (); + DestroyMusic (hMusic); + } +} + + diff --git a/sc2/src/sc2code/cyborg.c b/sc2/src/sc2code/cyborg.c new file mode 100644 index 000000000..5693186ef --- /dev/null +++ b/sc2/src/sc2code/cyborg.c @@ -0,0 +1,1349 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +COUNT +PlotIntercept (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1, COUNT + max_turns, COUNT margin_of_error) +{ + register SIZE dy; + register SIZE time_y_0, time_y_1; + POINT dst[2]; + RECT r0, r1; + SIZE dx_0, dy_0, dx_1, dy_1; + + if ((ElementPtr0->state_flags | ElementPtr1->state_flags) & FINITE_LIFE) + { + if (!(ElementPtr0->state_flags & FINITE_LIFE)) + { + if (ElementPtr1->life_span < max_turns) + max_turns = ElementPtr1->life_span; + } + else if (!(ElementPtr1->state_flags & FINITE_LIFE)) + { + if (ElementPtr0->life_span < max_turns) + max_turns = ElementPtr0->life_span; + } + else + { + if (ElementPtr0->life_span < max_turns) + max_turns = ElementPtr0->life_span; + if (ElementPtr1->life_span < max_turns) + max_turns = ElementPtr1->life_span; + } + } + + dst[0] = ElementPtr0->current.location; + GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx_0, &dy_0); + dx_0 = (SIZE)VELOCITY_TO_WORLD ((long)dx_0 * (long)max_turns); + dy_0 = (SIZE)VELOCITY_TO_WORLD ((long)dy_0 * (long)max_turns); + + dst[1] = ElementPtr1->current.location; + GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx_1, &dy_1); + dx_1 = (SIZE)VELOCITY_TO_WORLD ((long)dx_1 * (long)max_turns); + dy_1 = (SIZE)VELOCITY_TO_WORLD ((long)dy_1 * (long)max_turns); + + if (margin_of_error) + { + dst[1].y -= margin_of_error; + time_y_0 = 1; + time_y_1 = margin_of_error << 1; + } + else + { + GetFrameRect ( + ElementPtr0->IntersectControl.IntersectStamp.frame, + &r0); + GetFrameRect ( + ElementPtr1->IntersectControl.IntersectStamp.frame, + &r1); + + dst[0].y += DISPLAY_TO_WORLD (r0.corner.y); + dst[1].y += DISPLAY_TO_WORLD (r1.corner.y); + time_y_0 = DISPLAY_TO_WORLD (r0.extent.height); + time_y_1 = DISPLAY_TO_WORLD (r1.extent.height); + } + + dy = dst[1].y - dst[0].y; + time_y_0 = dy - time_y_0 + 1; + time_y_1 = dy + time_y_1 - 1; + dy = dy_0 - dy_1; + + if ((time_y_0 <= 0 && time_y_1 >= 0) + || (time_y_0 > 0 && dy >= time_y_0) + || (time_y_1 < 0 && dy <= time_y_1)) + { + register SIZE dx; + register SIZE time_x_0, time_x_1; + + if (margin_of_error) + { + dst[1].x -= margin_of_error; + time_x_0 = 1; + time_x_1 = margin_of_error << 1; + } + else + { + dst[0].x += DISPLAY_TO_WORLD (r0.corner.x); + dst[1].x += DISPLAY_TO_WORLD (r1.corner.x); + time_x_0 = DISPLAY_TO_WORLD (r0.extent.width); + time_x_1 = DISPLAY_TO_WORLD (r1.extent.width); + } + + dx = dst[1].x - dst[0].x; + time_x_0 = dx - time_x_0 + 1; + time_x_1 = dx + time_x_1 - 1; + dx = dx_0 - dx_1; + + if ((time_x_0 <= 0 && time_x_1 >= 0) + || (time_x_0 > 0 && dx >= time_x_0) + || (time_x_1 < 0 && dx <= time_x_1)) + { + if (dx == 0 && dy == 0) + time_y_0 = time_y_1 = 0; + else + { + SIZE t; + long time_beg, time_end, fract; + + if (time_y_1 < 0) + { + t = time_y_0; + time_y_0 = -time_y_1; + time_y_1 = -t; + } + else if (time_y_0 <= 0) + { + if (dy < 0) + time_y_1 = -time_y_0; + time_y_0 = 0; + } + if (dy < 0) + dy = -dy; + if (dy < time_y_1) + time_y_1 = dy; + + if (time_x_1 < 0) + { + t = time_x_0; + time_x_0 = -time_x_1; + time_x_1 = -t; + } + else if (time_x_0 <= 0) + { + if (dx < 0) + time_x_1 = -time_x_0; + time_x_0 = 0; + } + if (dx < 0) + dx = -dx; + if (dx < time_x_1) + time_x_1 = dx; + + if (dx == 0) + { + time_beg = time_y_0; + time_end = time_y_1; + fract = dy; + } + else if (dy == 0) + { + time_beg = time_x_0; + time_end = time_x_1; + fract = dx; + } + else + { + long time_x, time_y; + + time_x = (long)time_x_0 * (long)dy; + time_y = (long)time_y_0 * (long)dx; + time_beg = time_x < time_y ? time_y : time_x; + + time_x = (long)time_x_1 * (long)dy; + time_y = (long)time_y_1 * (long)dx; + time_end = time_x > time_y ? time_y : time_x; + + fract = (long)dx * (long)dy; + } + + if ((time_beg *= max_turns) < fract) + time_y_0 = 0; + else + time_y_0 = (SIZE)(time_beg / fract); + + if (time_end >= fract) /* just in case of overflow */ + time_y_1 = max_turns - 1; + else + time_y_1 = (SIZE)((time_end * max_turns) / fract); + } + + if (time_y_0 <= time_y_1) + { + if (margin_of_error != 0) + return ((COUNT)time_y_0 + 1); + else + { + POINT Pt0, Pt1; + VELOCITY_DESC Velocity0, Velocity1; + INTERSECT_CONTROL Control0, Control1; + + Pt0 = ElementPtr0->current.location; + Velocity0 = ElementPtr0->velocity; + Control0 = ElementPtr0->IntersectControl; + + Pt1 = ElementPtr1->current.location; + Velocity1 = ElementPtr1->velocity; + Control1 = ElementPtr1->IntersectControl; + + if (time_y_0) + { + GetNextVelocityComponents (&Velocity0, &dx_0, &dy_0, time_y_0); + Pt0.x += dx_0; + Pt0.y += dy_0; + Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); + Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); + + GetNextVelocityComponents (&Velocity1, &dx_1, &dy_1, time_y_0); + Pt1.x += dx_1; + Pt1.y += dy_1; + Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); + Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); + } + + do + { + TIME_VALUE when; + + ++time_y_0; + + GetNextVelocityComponents (&Velocity0, &dx_0, &dy_0, 1); + Pt0.x += dx_0; + Pt0.y += dy_0; + + GetNextVelocityComponents (&Velocity1, &dx_1, &dy_1, 1); + Pt1.x += dx_1; + Pt1.y += dy_1; + + Control0.IntersectStamp.origin = Control0.EndPoint; + Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); + Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); + + Control1.IntersectStamp.origin = Control1.EndPoint; + Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); + Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); + when = DrawablesIntersect (&Control0, + &Control1, MAX_TIME_VALUE); + if (when) + { + if (when == 1 + && time_y_0 == 1 + && ((ElementPtr0->state_flags + | ElementPtr1->state_flags) & APPEARING)) + { + when = 0; + Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); + Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); + + Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); + Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); + } + + if (when) + return ((COUNT)time_y_0); + } + } while (time_y_0 < time_y_1); + } + } + } + } + + return (0); +} + +STARSHIPPTR CyborgDescPtr; + +#ifdef DEBUG +static COUNT turn_counter[NUM_PLAYERS]; +#endif /* DEBUG */ + +static void +InitCyborg (STARSHIPPTR StarShipPtr) +{ + COUNT Index, Divisor; + +#ifdef DEBUG +//turn_counter[which_ship] = 0; +#endif /* DEBUG */ + + Index = StarShipPtr->RaceDescPtr->characteristics.max_thrust + * StarShipPtr->RaceDescPtr->characteristics.thrust_increment; + if ((Divisor = StarShipPtr->RaceDescPtr->characteristics.turn_wait + + StarShipPtr->RaceDescPtr->characteristics.thrust_wait) > 0) + Index /= Divisor; + else + Index >>= 1; +#ifdef PRINT_MI +{ +char buf[40]; + +GetStringContents (StarShipPtr->RaceDescPtr->ship_data.race_strings, buf, FALSE); +printf ("MI(%s) -- <%u:%u> = %u\n", +buf, +StarShipPtr->RaceDescPtr->characteristics.max_thrust * +StarShipPtr->RaceDescPtr->characteristics.thrust_increment, +Divisor, +Index); +} +#endif /* PRINT_MI */ + StarShipPtr->RaceDescPtr->cyborg_control.ManeuverabilityIndex = Index; +#ifdef DEBUG +//turn_counter[which_ship] = 0; +#endif /* DEBUG */ +} + +static void +ship_movement (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) +{ + if (EvalDescPtr->which_turn == 0) + EvalDescPtr->which_turn = 1; + + switch (EvalDescPtr->MoveState) + { + case PURSUE: + Pursue (ShipPtr, EvalDescPtr); + break; + case AVOID: +#ifdef NOTYET + Avoid (ShipPtr, EvalDescPtr); + break; +#endif /* NOTYET */ + case ENTICE: + Entice (ShipPtr, EvalDescPtr); + break; + case NO_MOVEMENT: + break; + } +} + +BOOLEAN +ship_weapons (ELEMENTPTR ShipPtr, ELEMENTPTR OtherPtr, COUNT + margin_of_error) +{ + SIZE delta_x, delta_y; + COUNT n, num_weapons; + ELEMENT Ship; + HELEMENT Weapon[6]; + STARSHIPPTR StarShipPtr; + + if (OBJECT_CLOAKED (OtherPtr)) + margin_of_error += DISPLAY_TO_WORLD (40); + + Ship = *ShipPtr; + GetNextVelocityComponents (&Ship.velocity, + &delta_x, &delta_y, 1); + Ship.next.location.x = + Ship.current.location.x + delta_x; + Ship.next.location.y = + Ship.current.location.y + delta_y; + Ship.current.location = Ship.next.location; + + GetElementStarShip (&Ship, &StarShipPtr); + num_weapons = + (*StarShipPtr->RaceDescPtr->init_weapon_func) (&Ship, Weapon); + + if ((n = num_weapons)) + { + HELEMENT *WeaponPtr, w; + //STARSHIPPTR StarShipPtr; + ELEMENTPTR EPtr; + + WeaponPtr = &Weapon[0]; + do + { + w = *WeaponPtr; + if (w) + { + EPtr = LockElement (w, &EPtr); + if (EPtr->state_flags & APPEARING) + { + EPtr->next = EPtr->current; + InitIntersectStartPoint (EPtr); + InitIntersectEndPoint (EPtr); + InitIntersectFrame (EPtr); + } + + if (PlotIntercept (EPtr, OtherPtr, + EPtr->life_span, margin_of_error)) + { + UnlockElement (w); + break; + } + + UnlockElement (w); + FreeElement (w); + } + ++WeaponPtr; + } while (--n); + + if ((num_weapons = n)) + { + do + { + w = *WeaponPtr++; + if (w) + FreeElement (w); + } while (--n); + } + } + + return (num_weapons > 0); +} + +void +ship_intelligence (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR ObjectsOfConcern, + COUNT ConcernCounter) +{ + BOOLEAN ShipMoved, ShipFired; + COUNT margin_of_error; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + ShipMoved = TRUE; + if (ShipPtr->turn_wait == 0) + ShipMoved = FALSE; + if (ShipPtr->thrust_wait == 0) + ShipMoved = FALSE; + + ShipFired = TRUE; + if (StarShipPtr->weapon_counter == 0) + { + StarShipPtr->ship_input_state &= ~WEAPON; + if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON)) + ShipFired = FALSE; + } + + if (PlayerControl[cur_player] & AWESOME_RATING) + margin_of_error = 0; + else if (PlayerControl[cur_player] & GOOD_RATING) + margin_of_error = DISPLAY_TO_WORLD (20); + else /* if (PlayerControl[cur_player] & STANDARD_RATING) */ + margin_of_error = DISPLAY_TO_WORLD (40); + + ObjectsOfConcern += ConcernCounter; + while (ConcernCounter--) + { + --ObjectsOfConcern; + if (ObjectsOfConcern->ObjectPtr) + { + if (!ShipMoved + && (ConcernCounter != ENEMY_WEAPON_INDEX + || ObjectsOfConcern->MoveState == PURSUE +|| (ObjectsOfConcern->ObjectPtr->state_flags & CREW_OBJECT) + || MANEUVERABILITY ( + &StarShipPtr->RaceDescPtr->cyborg_control + ) >= MEDIUM_SHIP)) + { + ship_movement (ShipPtr, ObjectsOfConcern); + ShipMoved = TRUE; + } + if (!ShipFired + && (ConcernCounter == ENEMY_SHIP_INDEX + || (ConcernCounter == ENEMY_WEAPON_INDEX + && ObjectsOfConcern->MoveState != AVOID +#ifdef NEVER + && !(PlayerControl[cur_player] & STANDARD_RATING) +#endif /* NEVER */ + ))) + { + ShipFired = ship_weapons (ShipPtr, + ObjectsOfConcern->ObjectPtr, margin_of_error); + if (ShipFired) + StarShipPtr->ship_input_state |= WEAPON; + } + } + } +} + +BOOLEAN +TurnShip (ELEMENTPTR ShipPtr, COUNT angle) +{ + COUNT f, ship_delta_facing; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + f = StarShipPtr->ShipFacing; + ship_delta_facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle) - f); + if (ship_delta_facing) + { + if (ship_delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) + ship_delta_facing = + NORMALIZE_FACING (ship_delta_facing + + (Random () & 1 ? + ANGLE_TO_FACING (OCTANT >> 1) : + -ANGLE_TO_FACING (OCTANT >> 1))); + + if (ship_delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + { + StarShipPtr->ship_input_state |= RIGHT; + ++f; + ShipPtr->next.image.frame = + IncFrameIndex (ShipPtr->current.image.frame); + } + else + { + StarShipPtr->ship_input_state |= LEFT; + --f; + ShipPtr->next.image.frame = + DecFrameIndex (ShipPtr->current.image.frame); + } + +#ifdef NOTYET + if (((StarShipPtr->ship_input_state & (LEFT | RIGHT)) + ^ (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) == (LEFT | RIGHT)) + StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); + else +#endif /* NOTYET */ + { + StarShipPtr->ShipFacing = NORMALIZE_FACING (f); + + return (TRUE); + } + } + + return (FALSE); +} + +BOOLEAN +ThrustShip (ELEMENTPTR ShipPtr, COUNT angle) +{ + BOOLEAN ShouldThrust; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->ship_input_state & THRUST) + ShouldThrust = TRUE; + else if (NORMALIZE_FACING (ANGLE_TO_FACING (angle) + - ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity))) == 0 + && (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + && !(StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL)) + ShouldThrust = FALSE; + else + { + SIZE ship_delta_facing; + + ship_delta_facing = + NORMALIZE_FACING (ANGLE_TO_FACING (angle) + - StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)); + if (ship_delta_facing == ANGLE_TO_FACING (QUADRANT) + || ((StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) + && ship_delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE))) + ShouldThrust = TRUE; + else + ShouldThrust = FALSE; + } + + if (ShouldThrust) + { + inertial_thrust (ShipPtr); + + StarShipPtr->ship_input_state |= THRUST; + } + + return (ShouldThrust); +} + +void +Pursue (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) +{ + INPUT_STATE maneuver_state; + COUNT desired_thrust_angle, desired_turn_angle; + SIZE delta_x, delta_y; + SIZE ship_delta_x, ship_delta_y; + SIZE other_delta_x, other_delta_y; + ELEMENTPTR OtherObjPtr; + VELOCITY_DESC ShipVelocity, OtherVelocity; + + ShipVelocity = ShipPtr->velocity; + GetNextVelocityComponents (&ShipVelocity, + &ship_delta_x, &ship_delta_y, EvalDescPtr->which_turn); + ShipPtr->next.location.x = + ShipPtr->current.location.x + ship_delta_x; + ShipPtr->next.location.y = + ShipPtr->current.location.y + ship_delta_y; + + OtherObjPtr = EvalDescPtr->ObjectPtr; + OtherVelocity = OtherObjPtr->velocity; + GetNextVelocityComponents (&OtherVelocity, + &other_delta_x, &other_delta_y, EvalDescPtr->which_turn); + + delta_x = (OtherObjPtr->current.location.x + other_delta_x) + - ShipPtr->next.location.x; + delta_y = (OtherObjPtr->current.location.y + other_delta_y) + - ShipPtr->next.location.y; + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + desired_thrust_angle = ARCTAN (delta_x, delta_y); + + maneuver_state = 0; + if (ShipPtr->turn_wait == 0) + maneuver_state |= LEFT | RIGHT; + if (ShipPtr->thrust_wait == 0 + && ((OtherObjPtr->state_flags & PLAYER_SHIP) + || ((OtherObjPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) + || OtherObjPtr->preprocess_func == crew_preprocess)) + maneuver_state |= THRUST; + + desired_turn_angle = NORMALIZE_ANGLE (desired_thrust_angle + HALF_CIRCLE); + /* other player's ship */ + if ((OtherObjPtr->state_flags & PLAYER_SHIP) + && OtherObjPtr->mass_points <= MAX_SHIP_MASS) + { + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + GetElementStarShip (OtherObjPtr, &EnemyStarShipPtr); + if ((MANEUVERABILITY ( + &StarShipPtr->RaceDescPtr->cyborg_control + ) >= FAST_SHIP + && WEAPON_RANGE (&StarShipPtr->RaceDescPtr->cyborg_control) + > CLOSE_RANGE_WEAPON) + || (EvalDescPtr->which_turn >= 24 + && (StarShipPtr->RaceDescPtr->characteristics.max_thrust * 2 / 3 < + EnemyStarShipPtr->RaceDescPtr->characteristics.max_thrust + || (EnemyStarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)))) + { + UWORD ship_flags; + + ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; + /* you're maneuverable */ + if (MANEUVERABILITY ( + &StarShipPtr->RaceDescPtr->cyborg_control + ) >= MEDIUM_SHIP) + { + UWORD fire_flags; + COUNT facing; + + for (fire_flags = FIRES_FORE, facing = EvalDescPtr->facing; + fire_flags <= FIRES_LEFT; + fire_flags <<= 1, facing += QUADRANT) + { + if + ( + /* he's dangerous in this direction */ + (ship_flags & fire_flags) + /* he's facing direction you want to go */ + && NORMALIZE_ANGLE ( + desired_turn_angle - facing + OCTANT + ) <= QUADRANT + && ( + /* he's moving */ + (other_delta_x != 0 || other_delta_y != 0) + && + /* he's coasting backwards */ + NORMALIZE_ANGLE ( + (GetVelocityTravelAngle (&OtherVelocity) + HALF_CIRCLE) + - facing + (OCTANT + (OCTANT >> 1))) + <= ((OCTANT + (OCTANT >> 1)) << 1)) + ) + { + /* catch him on the back side */ + desired_thrust_angle = desired_turn_angle; + break; + } + } + } + + if (desired_thrust_angle != desired_turn_angle + && (other_delta_x || other_delta_y) + && EvalDescPtr->which_turn >= 24 + && NORMALIZE_ANGLE (desired_thrust_angle + - GetVelocityTravelAngle (&OtherVelocity) + + OCTANT) <= QUADRANT + && ((NORMALIZE_ANGLE ( + GetVelocityTravelAngle (&OtherVelocity) + - GetVelocityTravelAngle (&ShipVelocity) + + OCTANT) <= QUADRANT + && (((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) + && !(StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)) + || (ship_flags & DONT_CHASE))) + || NORMALIZE_ANGLE ( + desired_turn_angle + - FACING_TO_ANGLE (StarShipPtr->ShipFacing) + + OCTANT) <= QUADRANT)) + desired_thrust_angle = desired_turn_angle; + } + } + + if (maneuver_state & (LEFT | RIGHT)) + TurnShip (ShipPtr, desired_thrust_angle); + + if (maneuver_state & THRUST) + ThrustShip (ShipPtr, desired_thrust_angle); +} + +void +Entice (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) +{ + INPUT_STATE maneuver_state; + COUNT desired_thrust_angle, desired_turn_angle; + COUNT cone_of_fire, travel_angle; + SIZE delta_x, delta_y; + SIZE ship_delta_x, ship_delta_y; + SIZE other_delta_x, other_delta_y; + ELEMENTPTR OtherObjPtr; + VELOCITY_DESC ShipVelocity, OtherVelocity; + STARSHIPPTR StarShipPtr; + RACE_DESCPTR RDPtr; + + ShipVelocity = ShipPtr->velocity; + GetNextVelocityComponents (&ShipVelocity, + &ship_delta_x, &ship_delta_y, EvalDescPtr->which_turn); + ShipPtr->next.location.x = + ShipPtr->current.location.x + ship_delta_x; + ShipPtr->next.location.y = + ShipPtr->current.location.y + ship_delta_y; + + OtherObjPtr = (ELEMENTPTR)EvalDescPtr->ObjectPtr; + OtherVelocity = OtherObjPtr->velocity; + GetNextVelocityComponents (&OtherVelocity, + &other_delta_x, &other_delta_y, EvalDescPtr->which_turn); + + delta_x = (OtherObjPtr->current.location.x + other_delta_x) + - ShipPtr->next.location.x; + delta_y = (OtherObjPtr->current.location.y + other_delta_y) + - ShipPtr->next.location.y; + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + desired_thrust_angle = ARCTAN (delta_x, delta_y); + + maneuver_state = 0; + if (ShipPtr->turn_wait == 0) + maneuver_state |= LEFT | RIGHT; + if (ShipPtr->thrust_wait == 0) + maneuver_state |= THRUST; + + delta_x = ship_delta_x - other_delta_x; + delta_y = ship_delta_y - other_delta_y; + travel_angle = ARCTAN (delta_x, delta_y); + desired_turn_angle = NORMALIZE_ANGLE (desired_thrust_angle + HALF_CIRCLE); + + GetElementStarShip (ShipPtr, &StarShipPtr); + RDPtr = StarShipPtr->RaceDescPtr; + if (EvalDescPtr->MoveState == AVOID) + { + desired_turn_angle = + NORMALIZE_ANGLE (desired_turn_angle - EvalDescPtr->facing); + + if (NORMALIZE_FACING (ANGLE_TO_FACING (desired_turn_angle))) + { + if (desired_turn_angle <= HALF_CIRCLE) + desired_thrust_angle = RIGHT; + else /* if (desired_turn_angle > HALF_CIRCLE) */ + desired_thrust_angle = LEFT; + } + else + { + desired_turn_angle = NORMALIZE_ANGLE ( + FACING_TO_ANGLE (StarShipPtr->ShipFacing) + - EvalDescPtr->facing + ); + if ((desired_turn_angle & (HALF_CIRCLE - 1)) == 0) + desired_thrust_angle = Random () & 1 ? RIGHT : LEFT; + else + desired_thrust_angle = desired_turn_angle < HALF_CIRCLE ? RIGHT : LEFT; + } + + if (desired_thrust_angle == LEFT) + { +#define FLANK_LEFT -QUADRANT +#define SHIP_LEFT -OCTANT + desired_thrust_angle = EvalDescPtr->facing + + FLANK_LEFT - (SHIP_LEFT >> 1); + } + else + { +#define FLANK_RIGHT QUADRANT +#define SHIP_RIGHT OCTANT + desired_thrust_angle = EvalDescPtr->facing + + FLANK_RIGHT - (SHIP_RIGHT >> 1); + } + + desired_thrust_angle = NORMALIZE_ANGLE (desired_thrust_angle); + } + else if (GRAVITY_MASS (OtherObjPtr->mass_points)) + { + COUNT planet_facing; + + planet_facing = NORMALIZE_FACING (ANGLE_TO_FACING (desired_thrust_angle)); + cone_of_fire = NORMALIZE_FACING ( + planet_facing + - StarShipPtr->ShipFacing + + ANGLE_TO_FACING (QUADRANT)); + + if (RDPtr->characteristics.thrust_increment != + RDPtr->characteristics.max_thrust) + maneuver_state &= ~THRUST; + + /* if not pointing towards planet */ + if (cone_of_fire > ANGLE_TO_FACING (QUADRANT << 1)) + desired_turn_angle = desired_thrust_angle; + /* if pointing directly at planet */ + else if (cone_of_fire == ANGLE_TO_FACING (QUADRANT) + && NORMALIZE_FACING (ANGLE_TO_FACING (travel_angle)) != planet_facing) + desired_turn_angle = travel_angle; + else if (cone_of_fire == 0 + || cone_of_fire == ANGLE_TO_FACING (QUADRANT << 1) + || (!(maneuver_state & THRUST) + && (cone_of_fire < ANGLE_TO_FACING (OCTANT) + || cone_of_fire > ANGLE_TO_FACING ((QUADRANT << 1) - OCTANT)))) + { + desired_turn_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + if (NORMALIZE_ANGLE (desired_turn_angle + - travel_angle + QUADRANT) > HALF_CIRCLE) + desired_turn_angle = travel_angle; + if (ShipPtr->thrust_wait == 0) + maneuver_state |= THRUST; + } + + desired_thrust_angle = desired_turn_angle; + } + else + { + COUNT WRange; + + WRange = WEAPON_RANGE ( + &RDPtr->cyborg_control + ); + + cone_of_fire = NORMALIZE_ANGLE (desired_turn_angle + - EvalDescPtr->facing + OCTANT); + if (OtherObjPtr->state_flags & PLAYER_SHIP) + { + UWORD fire_flags, ship_flags; + COUNT facing; + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (OtherObjPtr, &EnemyStarShipPtr); + ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; + for (fire_flags = FIRES_FORE, facing = EvalDescPtr->facing; + fire_flags <= FIRES_LEFT; + fire_flags <<= 1, facing += QUADRANT) + { + if + ( + /* he's dangerous in this direction */ + (ship_flags & fire_flags) + /* he's facing direction you want to go */ + && (cone_of_fire = NORMALIZE_ANGLE ( + desired_turn_angle - facing + OCTANT + )) <= QUADRANT + /* he's moving */ + && ((other_delta_x != 0 || other_delta_y != 0) + /* he's coasting backwards */ + && NORMALIZE_ANGLE ( + (GetVelocityTravelAngle (&OtherVelocity) + HALF_CIRCLE) + - facing + OCTANT) <= QUADRANT) + ) + { + /* need to be close for a kill */ + if (WRange < LONG_RANGE_WEAPON + && EvalDescPtr->which_turn <= 32) + { + /* catch him on the back side */ + desired_thrust_angle = desired_turn_angle; + goto DoManeuver; + } + + break; + } + } + + if (EvalDescPtr->which_turn <= 8 + && RDPtr->characteristics.max_thrust <= + EnemyStarShipPtr->RaceDescPtr->characteristics.max_thrust) + goto DoManeuver; + } + + if + ( +#ifdef NOTYET + WRange < LONG_RANGE_WEAPON + && +#endif /* NOTYET */ + /* not at full speed */ + !(StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + && (PlotIntercept ( + ShipPtr, OtherObjPtr, 40, CLOSE_RANGE_WEAPON << 1 + ) +#ifdef NOTYET + || + ( + /* object's facing direction you want to go */ + cone_of_fire <= QUADRANT + /* and you're basically going in that direction */ + && (travel_angle == FULL_CIRCLE + || NORMALIZE_ANGLE (travel_angle + - desired_thrust_angle + QUADRANT) <= HALF_CIRCLE) + /* and object's in range */ + && PlotIntercept (ShipPtr, OtherObjPtr, 1, WRange) + ) +#endif /* NOTYET */ + ) + ) + { + if + ( + /* pointed straight at him */ + NORMALIZE_ANGLE (desired_thrust_angle + - FACING_TO_ANGLE (StarShipPtr->ShipFacing) + OCTANT) <= QUADRANT + /* or not exposed to business end */ + || cone_of_fire > QUADRANT + ) + { + desired_thrust_angle = desired_turn_angle; + } + else + { +#ifdef NOTYET + if + ( + travel_angle != FULL_CIRCLE + && NORMALIZE_ANGLE (travel_angle + - desired_turn_angle + OCTANT) <= QUADRANT + ) + { + desired_turn_angle = + NORMALIZE_ANGLE ((EvalDescPtr->facing + HALF_CIRCLE) + + (travel_angle - desired_turn_angle)); + if (!(maneuver_state & (LEFT | RIGHT))) + maneuver_state &= ~THRUST; + } + + if (maneuver_state & (LEFT | RIGHT)) + { + TurnShip (ShipPtr, desired_turn_angle); + maneuver_state &= ~(LEFT | RIGHT); + } +#endif /* NOTYET */ + + desired_thrust_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); +desired_turn_angle = desired_thrust_angle; + } + } + else if ((cone_of_fire = PlotIntercept ( + ShipPtr, OtherObjPtr, 10, WRange +#ifdef OLD + - (WRange >> 3) +#else /* !OLD */ + - (WRange >> 2) +#endif /* OLD */ + ))) + { + if (RDPtr->characteristics.thrust_increment != + RDPtr->characteristics.max_thrust + /* and already at full speed */ + && (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + /* and facing away from enemy */ + && (NORMALIZE_ANGLE (desired_turn_angle + - ARCTAN (ship_delta_x, ship_delta_y) + + (OCTANT + 2)) <= ((OCTANT + 2) << 1) + /* or not on collision course */ + || !PlotIntercept ( + ShipPtr, OtherObjPtr, 30, CLOSE_RANGE_WEAPON << 1 + ))) + maneuver_state &= ~THRUST; + /* veer off */ + else if (cone_of_fire == 1 + || RDPtr->characteristics.thrust_increment != + RDPtr->characteristics.max_thrust) + { + if (maneuver_state & (LEFT | RIGHT)) + { + TurnShip (ShipPtr, desired_turn_angle); + maneuver_state &= ~(LEFT | RIGHT); + } + + if (NORMALIZE_ANGLE (desired_thrust_angle + - ARCTAN (ship_delta_x, ship_delta_y) + + (OCTANT + 2)) <= ((OCTANT + 2) << 1)) + desired_thrust_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + else + desired_thrust_angle = desired_turn_angle; + } + } + } + +DoManeuver: + if (maneuver_state & (LEFT | RIGHT)) + TurnShip (ShipPtr, desired_thrust_angle); + + if (maneuver_state & THRUST) + ThrustShip (ShipPtr, desired_thrust_angle); +} + +void +Avoid (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) +{ + (void) ShipPtr; /* Satisfying compiler (unused parameter) */ + (void) EvalDescPtr; /* Satisfying compiler (unused parameter) */ +} + +INPUT_STATE +tactical_intelligence (void) +{ + ELEMENTPTR ShipPtr; + ELEMENT Ship; + COUNT ShipFacing; + HELEMENT hElement, hNextElement; + COUNT ConcernCounter; + EVALUATE_DESC ObjectsOfConcern[10]; + BOOLEAN ShipMoved, UltraManeuverable; + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + RACE_DESCPTR RDPtr, EnemyRDPtr; + +#ifdef DEBUG +++turn_counter[cur_player]; +#endif /* DEBUG */ + + StarShipPtr = CyborgDescPtr; + RDPtr = StarShipPtr->RaceDescPtr; + + if (RDPtr->cyborg_control.ManeuverabilityIndex == 0) + InitCyborg (StarShipPtr); + + LockElement (StarShipPtr->hShip, &ShipPtr); + if (RDPtr->ship_info.crew_level == 0 + || GetPrimType (&DisplayArray[ShipPtr->PrimIndex]) == NO_PRIM) + { + UnlockElement (StarShipPtr->hShip); + return (0); + } + + ShipMoved = TRUE; + if (PlayerControl[cur_player] & STANDARD_RATING) + ++StarShipPtr->special_counter; + +#ifdef DEBUG_CYBORG +if (!(ShipPtr->state_flags & FINITE_LIFE) + && ShipPtr->life_span == NORMAL_LIFE) + ShipPtr->life_span += 2; /* make ship invulnerable */ +#endif /* DEBUG_CYBORG */ + Ship = *ShipPtr; + UnlockElement (StarShipPtr->hShip); + ShipFacing = StarShipPtr->ShipFacing; + + for (ConcernCounter = 0; + ConcernCounter <= FIRST_EMPTY_INDEX; ++ConcernCounter) + { + ObjectsOfConcern[ConcernCounter].ObjectPtr = 0; + ObjectsOfConcern[ConcernCounter].MoveState = NO_MOVEMENT; + ObjectsOfConcern[ConcernCounter].which_turn = (COUNT)~0; + } + --ConcernCounter; + + UltraManeuverable = (BOOLEAN)( + RDPtr->characteristics.thrust_increment == + RDPtr->characteristics.max_thrust + && MANEUVERABILITY (&RDPtr->cyborg_control) >= MEDIUM_SHIP + ); + + if (Ship.turn_wait == 0) + { + ShipMoved = FALSE; + StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); + } + if (Ship.thrust_wait == 0) + { + ShipMoved = FALSE; + StarShipPtr->ship_input_state &= ~THRUST; + } + + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + EVALUATE_DESC ed; + + LockElement (hElement, &ed.ObjectPtr); + hNextElement = GetSuccElement (ed.ObjectPtr); + if (CollisionPossible (ed.ObjectPtr, &Ship)) + { + SIZE dx, dy; + + dx = ed.ObjectPtr->next.location.x + - Ship.next.location.x; + dy = ed.ObjectPtr->next.location.y + - Ship.next.location.y; + dx = WRAP_DELTA_X (dx); + dy = WRAP_DELTA_Y (dy); + if (GRAVITY_MASS (ed.ObjectPtr->mass_points)) + { + COUNT maneuver_turn, ship_bounds; + RECT ship_footprint; + + if (UltraManeuverable) + maneuver_turn = 16; + else if (MANEUVERABILITY (&RDPtr->cyborg_control) <= MEDIUM_SHIP) + maneuver_turn = 48; + else + maneuver_turn = 32; + + GetFrameRect (SetAbsFrameIndex ( + Ship.IntersectControl.IntersectStamp.frame, 0 + ), &ship_footprint); + ship_bounds = (COUNT)(ship_footprint.extent.width + + ship_footprint.extent.height); + + if (!ShipMoved && (ed.which_turn = + PlotIntercept (ed.ObjectPtr, &Ship, maneuver_turn, + DISPLAY_TO_WORLD (30 + (ship_bounds * 3 /* << 2 */))))) + { + if (ed.which_turn > 1 + || PlotIntercept (ed.ObjectPtr, &Ship, 1, + DISPLAY_TO_WORLD (35 + ship_bounds)) + || PlotIntercept (ed.ObjectPtr, &Ship, + maneuver_turn << 1, + DISPLAY_TO_WORLD (40 + ship_bounds)) > 1) + { + ed.facing = ARCTAN (-dx, -dy); + if (UltraManeuverable) + ed.MoveState = AVOID; + else + ed.MoveState = ENTICE; + + ObjectsOfConcern[GRAVITY_MASS_INDEX] = ed; + } + else if (!UltraManeuverable) + { + ++Ship.thrust_wait; + if (Ship.turn_wait) + ShipMoved = TRUE; + } + } + } + else if (ed.ObjectPtr->state_flags & PLAYER_SHIP) + { + GetElementStarShip (ed.ObjectPtr, &EnemyStarShipPtr); + EnemyRDPtr = EnemyStarShipPtr->RaceDescPtr; + if (EnemyRDPtr->cyborg_control.ManeuverabilityIndex == 0) + InitCyborg (EnemyStarShipPtr); + + ed.which_turn = WORLD_TO_TURN ( + square_root ((long)dx * dx + (long)dy * dy) + ); + if (ed.which_turn > ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn) + { + UnlockElement (hElement); + continue; + } + else if (ed.which_turn == 0) + ed.which_turn = 1; + + ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr = ed.ObjectPtr; + ObjectsOfConcern[ENEMY_SHIP_INDEX].facing = +#ifdef MAYBE + OBJECT_CLOAKED (ed.ObjectPtr) ? + GetVelocityTravelAngle (&ed.ObjectPtr->velocity) : +#endif /* MAYBE */ + FACING_TO_ANGLE (EnemyStarShipPtr->ShipFacing); + ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn = ed.which_turn; + + if (ShipMoved + || ed.ObjectPtr->mass_points > MAX_SHIP_MASS + || (WEAPON_RANGE (&RDPtr->cyborg_control) < LONG_RANGE_WEAPON + && (WEAPON_RANGE (&RDPtr->cyborg_control) <= CLOSE_RANGE_WEAPON + || (WEAPON_RANGE (&EnemyRDPtr->cyborg_control) >= LONG_RANGE_WEAPON + && (EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON)) + || ( +#ifdef OLD + MANEUVERABILITY (&RDPtr->cyborg_control) < + MANEUVERABILITY (&EnemyRDPtr->cyborg_control) +#else /* !OLD */ + RDPtr->characteristics.max_thrust < + EnemyRDPtr->characteristics.max_thrust +#endif /* !OLD */ + && WEAPON_RANGE (&RDPtr->cyborg_control) < + WEAPON_RANGE (&EnemyRDPtr->cyborg_control))))) + ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = PURSUE; + else + ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; + + if ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON) + && ship_weapons (ed.ObjectPtr, &Ship, 0)) + { + ed.which_turn = 1; + ed.MoveState = AVOID; + ed.facing = ObjectsOfConcern[ENEMY_SHIP_INDEX].facing; + + ObjectsOfConcern[ENEMY_WEAPON_INDEX] = ed; + } + } + else if (ed.ObjectPtr->pParent == 0) + { + if (!(ed.ObjectPtr->state_flags & FINITE_LIFE)) + { + ed.which_turn = WORLD_TO_TURN ( + square_root ((long)dx * dx + (long)dy * dy) + ); + + if (ed.which_turn < + ObjectsOfConcern[FIRST_EMPTY_INDEX].which_turn) + { + ed.MoveState = PURSUE; + ed.facing = GetVelocityTravelAngle ( + &ed.ObjectPtr->velocity + ); + + ObjectsOfConcern[FIRST_EMPTY_INDEX] = ed; + } + } + } + else if ((ed.ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) != + (Ship.state_flags & (GOOD_GUY | BAD_GUY)) + && ed.ObjectPtr->preprocess_func != crew_preprocess + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn > 1 + && ed.ObjectPtr->life_span > 0) + { + GetElementStarShip (ed.ObjectPtr, &EnemyStarShipPtr); + EnemyRDPtr = EnemyStarShipPtr->RaceDescPtr; + if (((EnemyRDPtr->ship_info.ship_flags & SEEKING_WEAPON) + && ed.ObjectPtr->next.image.farray != + EnemyRDPtr->ship_data.special) + || ((EnemyRDPtr->ship_info.ship_flags & SEEKING_SPECIAL) + && ed.ObjectPtr->next.image.farray == + EnemyRDPtr->ship_data.special)) + { + if ((!(ed.ObjectPtr->state_flags & (FINITE_LIFE | CREW_OBJECT)) + && RDPtr->characteristics.max_thrust > DISPLAY_TO_WORLD (8)) + || NORMALIZE_ANGLE (GetVelocityTravelAngle ( + &ed.ObjectPtr->velocity + ) - ARCTAN (-dx, -dy) + + QUADRANT) > HALF_CIRCLE) + ed.which_turn = 0; + else + { + ed.which_turn = WORLD_TO_TURN ( + square_root ((long)dx * dx + (long)dy * dy) + ); + + ed.MoveState = ENTICE; + if (UltraManeuverable) + { + if (ed.which_turn == 0) + ed.which_turn = 1; + else if (ed.which_turn > 16) + ed.which_turn = 0; + } + else if (ed.which_turn == 0) + ed.which_turn = 1; + else if (ed.which_turn > 16 + || (MANEUVERABILITY ( + &RDPtr->cyborg_control + ) > MEDIUM_SHIP + && ed.which_turn > 8)) + ed.which_turn = 0; + } + } + else if (!(PlayerControl[cur_player] & AWESOME_RATING)) + ed.which_turn = 0; + else + { + ed.which_turn = + PlotIntercept (ed.ObjectPtr, + &Ship, ed.ObjectPtr->life_span, + DISPLAY_TO_WORLD (40)); + ed.MoveState = AVOID; + } + + if (ed.which_turn > 0 + && (ed.which_turn < + ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn + || (ed.which_turn == + ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn + && ed.MoveState == AVOID))) + { + ed.facing = GetVelocityTravelAngle ( + &ed.ObjectPtr->velocity + ); + + ObjectsOfConcern[ENEMY_WEAPON_INDEX] = ed; + } + } + else if ((ed.ObjectPtr->state_flags & CREW_OBJECT) + && ((!(ed.ObjectPtr->state_flags & IGNORE_SIMILAR) + && (ed.ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (Ship.state_flags & (GOOD_GUY | BAD_GUY))) + || ed.ObjectPtr->preprocess_func == crew_preprocess) + && ObjectsOfConcern[CREW_OBJECT_INDEX].which_turn > 1) + { + ed.which_turn = WORLD_TO_TURN ( + square_root ((long)dx * dx + (long)dy * dy) + ); + + if (ed.which_turn == 0) + ed.which_turn = 1; + + if (ObjectsOfConcern[CREW_OBJECT_INDEX].which_turn > + ed.which_turn + && (ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 32 + || (ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 8 + && StarShipPtr->hShip == ed.ObjectPtr->hTarget))) + { + ed.MoveState = PURSUE; + ed.facing = 0; + ObjectsOfConcern[CREW_OBJECT_INDEX] = ed; + } + } + } + UnlockElement (hElement); + } + + (*RDPtr->cyborg_control.intelligence_func) + (&Ship, ObjectsOfConcern, ConcernCounter); +#ifdef DEBUG_CYBORG +StarShipPtr->ship_input_state &= ~SPECIAL; +#endif /* DEBUG_CYBORG */ + + StarShipPtr->ShipFacing = ShipFacing; + { + INPUT_STATE InputState; + + InputState = 0; + if (StarShipPtr->ship_input_state & LEFT) + SetInputXComponent (&InputState, -1); + else if (StarShipPtr->ship_input_state & RIGHT) + SetInputXComponent (&InputState, 1); + if (StarShipPtr->ship_input_state & THRUST) + SetInputYComponent (&InputState, -1); + if (StarShipPtr->ship_input_state & WEAPON) + InputState |= DEVICE_BUTTON2; + if (StarShipPtr->ship_input_state & SPECIAL) + InputState |= DEVICE_BUTTON3; + if (InputState) + SetInputDevType (&InputState, JOYSTICK_DEVICE); + + return (InputState); + } +} + diff --git a/sc2/src/sc2code/demo.c b/sc2/src/sc2code/demo.c new file mode 100644 index 000000000..0cefb9301 --- /dev/null +++ b/sc2/src/sc2code/demo.c @@ -0,0 +1,140 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "declib.h" + +#if DEMO_MODE || CREATE_JOURNAL +static DECODE_REF journal_fh; +static char journal_buf[1024 +#if CREATE_JOURNAL + * 8 +#else /* DEMO_MODE */ + * 2 +#endif + ]; +INPUT_REF DemoInput; +#endif + +#if DEMO_MODE + +static INPUT_REF OldArrowInput; + +INPUT_STATE +demo_input (INPUT_REF InputRef, INPUT_STATE InputState) +{ + if (InputState || AnyButtonPress () || cread ( + (PBYTE)&InputState, sizeof (InputState), 1, journal_fh + ) == 0) + { + cclose (journal_fh); + journal_fh = 0; + + StopMusic (); + StopSound (); + + FreeKernel (); + exit (1); + } + + return (InputState); +} + +#endif /* DEMO_MODE */ + +#if CREATE_JOURNAL + +void +JournalInput (INPUT_STATE InputState) +{ + if (ArrowInput != DemoInput && journal_fh) + cwrite ((PBYTE)&InputState, sizeof (InputState), 1, journal_fh); +} + +#endif /* CREATE_JOURNAL */ + +#if DEMO_MODE || CREATE_JOURNAL + +void +OpenJournal (void) +{ + DWORD start_seed; + +#if CREATE_JOURNAL + if (battle_counter) + { + if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_WRITE)) + { + start_seed = SeedRandomNumbers (); + cwrite ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); + } + } + else +#endif /* CREATE_JOURNAL */ + { + FILE *fp; + + if (fp = OpenResFile ("starcon.jnl", "rb")) + { + ReadResFile (journal_buf, 1, sizeof (journal_buf), fp); + CloseResFile (fp); + + if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_READ)) + { + OldArrowInput = ArrowInput; + ArrowInput = DemoInput; + PlayerInput[0] = PlayerInput[1] = DemoInput; + + FlushInput (); + + cread ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); + SeedRandom (start_seed); + } + } + } +} + +BOOLEAN +CloseJournal (void) +{ + if (journal_fh) + { + FILE *fp; + + cclose (journal_fh); + journal_fh = 0; + + if (ArrowInput == DemoInput) + { + ArrowInput = OldArrowInput; + return (FALSE); + } +#if CREATE_JOURNAL + else if (fp = OpenResFile ("starcon.jnl", "wb")) + { + WriteResFile (journal_buf, 1, sizeof (journal_buf), fp); + CloseResFile (fp); + } +#endif /* CREATE_JOURNAL */ + } + + return (TRUE); +} + +#endif + diff --git a/sc2/src/sc2code/demo.h b/sc2/src/sc2code/demo.h new file mode 100644 index 000000000..9835a7540 --- /dev/null +++ b/sc2/src/sc2code/demo.h @@ -0,0 +1,53 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DEMO_H +#define _DEMO_H + +#ifndef DEMO_MODE +#define DEMO_MODE 0 +#endif /* DEMO_MODE */ +#ifndef CREATE_JOURNAL +#define CREATE_JOURNAL 0 +#endif /* CREATE_JOURNAL */ + +extern INPUT_STATE demo_input (INPUT_REF InputRef, INPUT_STATE + InputState); + +extern INPUT_REF DemoInput; + +#if !(DEMO_MODE || CREATE_JOURNAL) + +#define OpenJournal SeedRandomNumbers +#define CloseJournal() TRUE +#define JournalInput(is) + +#else + +extern void OpenJournal (void); +extern BOOLEAN CloseJournal (void); +#if !CREATE_JOURNAL +#define JournalInput(is) +#else /* CREATE_JOURNAL */ +extern void JournalInput (INPUT_STATE InputState); +#endif /* CREATE_JOURNAL */ + +#endif + +#endif /* _DEMO_H */ + diff --git a/sc2/src/sc2code/displist.c b/sc2/src/sc2code/displist.c new file mode 100644 index 000000000..5c4ac4224 --- /dev/null +++ b/sc2/src/sc2code/displist.c @@ -0,0 +1,243 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "displist.h" + +BOOLEAN +InitQueue (PQUEUE pq, COUNT num_elements, OBJ_SIZE size) +{ + SetHeadLink (pq, NULL_HANDLE); + SetTailLink (pq, NULL_HANDLE); + SetLinkSize (pq, size); +#ifndef QUEUE_TABLE + return (TRUE); +#else /* QUEUE_TABLE */ + SetFreeList (pq, NULL_HANDLE); +// printf ("num_elements = %d (%d)\n", num_elements, (BYTE)num_elements); + if (AllocQueueTab (pq, num_elements) && LockQueueTab (pq)) + { + do + FreeLink (pq, GetLinkAddr (pq, num_elements)); + while (--num_elements); + + return (TRUE); + } + + return (FALSE); +#endif /* QUEUE_TABLE */ +} + +BOOLEAN +UninitQueue (PQUEUE pq) +{ +#ifdef QUEUE_TABLE + SetHeadLink (pq, NULL_HANDLE); + SetTailLink (pq, NULL_HANDLE); + SetFreeList (pq, NULL_HANDLE); + UnlockQueueTab (pq); + FreeQueueTab (pq); + + return (TRUE); +#else /* !QUEUE_TABLE */ + HLINK hLink; + + while ((hLink = GetHeadLink (pq)) != NULL_HANDLE) + { + RemoveQueue (pq, hLink); + if (!FreeLink (pq, hLink)) + return (FALSE); + } + + return (TRUE); +#endif /* QUEUE_TABLE */ +} + +void +ReinitQueue (PQUEUE pq) +{ + SetHeadLink (pq, NULL_HANDLE); + SetTailLink (pq, NULL_HANDLE); +#ifdef QUEUE_TABLE + { + COUNT num_elements; + + SetFreeList (pq, NULL_HANDLE); + + num_elements = SizeQueueTab (pq); + if (num_elements) + { + do + FreeLink (pq, GetLinkAddr (pq, num_elements)); + while (--num_elements); + } + } +#endif /* QUEUE_TABLE */ +} + +#ifdef QUEUE_TABLE +HLINK +AllocLink (PQUEUE pq) +{ + HLINK hLink; + + hLink = GetFreeList (pq); + if (hLink) + { + LINKPTR LinkPtr; + + LinkPtr = LockLink (pq, hLink); + SetFreeList (pq, _GetSuccLink (LinkPtr)); + UnlockLink (pq, hLink); + } +/* +else +printf ("No more elements\n"); +*/ + return (hLink); +} + +void +FreeLink (PQUEUE pq, HLINK hLink) +{ + LINKPTR LinkPtr; + + LinkPtr = LockLink (pq, hLink); + _SetSuccLink (LinkPtr, GetFreeList (pq)); + UnlockLink (pq, hLink); + + SetFreeList (pq, hLink); +} +#endif /* QUEUE_TABLE */ + +void +PutQueue (PQUEUE pq, HLINK hLink) +{ + LINKPTR LinkPtr; + + if (GetHeadLink (pq) == 0) + SetHeadLink (pq, hLink); + else + { + HLINK hTail; + LINKPTR lpTail; + + hTail = GetTailLink (pq); + lpTail = LockLink (pq, hTail); + _SetSuccLink (lpTail, hLink); + UnlockLink (pq, hTail); + } + + LinkPtr = LockLink (pq, hLink); + _SetPredLink (LinkPtr, GetTailLink (pq)); + _SetSuccLink (LinkPtr, NULL_HANDLE); + UnlockLink (pq, hLink); + + SetTailLink (pq, hLink); +} + +void +InsertQueue (PQUEUE pq, HLINK hLink, HLINK hRefLink) +{ + if (hRefLink == 0) + PutQueue (pq, hLink); + else + { + LINKPTR LinkPtr, RefLinkPtr; + + LinkPtr = LockLink (pq, hLink); + RefLinkPtr = LockLink (pq, hRefLink); + _SetPredLink (LinkPtr, _GetPredLink (RefLinkPtr)); + _SetPredLink (RefLinkPtr, hLink); + _SetSuccLink (LinkPtr, hRefLink); + + if (GetHeadLink (pq) == hRefLink) + SetHeadLink (pq, hLink); + else + { + HLINK hPredLink; + LINKPTR PredLinkPtr; + + hPredLink = _GetPredLink (LinkPtr); + PredLinkPtr = LockLink (pq, hPredLink); + _SetSuccLink (PredLinkPtr, hLink); + UnlockLink (pq, hPredLink); + } + UnlockLink (pq, hRefLink); + UnlockLink (pq, hLink); + } +} + +void +RemoveQueue (PQUEUE pq, HLINK hLink) +{ + LINKPTR LinkPtr; + + LinkPtr = LockLink (pq, hLink); + if (GetHeadLink (pq) == hLink) + { + SetHeadLink (pq, _GetSuccLink (LinkPtr)); + } + else + { + HLINK hPredLink; + LINKPTR PredLinkPtr; + + hPredLink = _GetPredLink (LinkPtr); + PredLinkPtr = LockLink (pq, hPredLink); + _SetSuccLink (PredLinkPtr, _GetSuccLink (LinkPtr)); + UnlockLink (pq, hPredLink); + } + if (GetTailLink (pq) == hLink) + { + SetTailLink (pq, _GetPredLink (LinkPtr)); + } + else + { + HLINK hSuccLink, hPredLink; + LINKPTR SuccLinkPtr; + + hSuccLink = _GetSuccLink (LinkPtr); + SuccLinkPtr = LockLink (pq, hSuccLink); + hPredLink = _GetPredLink (LinkPtr); + _SetPredLink (SuccLinkPtr, hPredLink); + UnlockLink (pq, hSuccLink); + } + UnlockLink (pq, hLink); +} + +COUNT +CountLinks (PQUEUE pq) +{ + COUNT LinkCount; + HLINK hLink, hNextLink; + + LinkCount = 0; + for (hLink = GetHeadLink (pq); hLink; hLink = hNextLink) + { + LINKPTR LinkPtr; + + ++LinkCount; + + LinkPtr = LockLink (pq, hLink); + hNextLink = _GetSuccLink (LinkPtr); + UnlockLink (pq, hLink); + } + + return (LinkCount); +} + diff --git a/sc2/src/sc2code/displist.h b/sc2/src/sc2code/displist.h new file mode 100644 index 000000000..2e758ec64 --- /dev/null +++ b/sc2/src/sc2code/displist.h @@ -0,0 +1,111 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DISPLIST_H +#define _DISPLIST_H + +#include "memlib.h" + +#define QUEUE_TABLE + +#ifdef QUEUE_TABLE +typedef PVOID QUEUE_HANDLE; +#else /* !QUEUE_TABLE */ +typedef MEM_HANDLE QUEUE_HANDLE; +#endif /* QUEUE_TABLE */ + +typedef UWORD OBJ_SIZE; +typedef QUEUE_HANDLE HLINK; + +typedef struct link +{ + HLINK pred, succ; +} LINK; +typedef LINK *PLINK; + +#ifndef _INPINTRN_H +/* This ifndef is temporary to avoid a collision with inpintrn.h + This shouldn't be necessary, but SDL_wrappper.h isn't set up correctly + at the moment. */ +typedef PBYTE BYTEPTR; +#endif +typedef PUWORD WORDPTR; +typedef PVOID VOIDPTR; +typedef PLINK LINKPTR; + +#ifdef QUEUE_TABLE +#define LockLink(pq, h) (LINKPTR)(h) +#define UnlockLink(pq, h) +#define GetFreeList(pq) (pq)->free_list +#define SetFreeList(pq, h) (pq)->free_list = (h) +#define AllocQueueTab(pq,n) \ + ((pq)->hq_tab = mem_allocate ((MEM_SIZE)((COUNT)(pq)->object_size * \ + (COUNT)((pq)->num_objects = (BYTE)(n))), \ + MEM_PRIMARY, DEFAULT_MEM_PRIORITY, MEM_SIMPLE)) +#define LockQueueTab(pq) ((pq)->pq_tab = (BYTEPTR)mem_lock ((pq)->hq_tab)) +#define UnlockQueueTab(pq) mem_unlock ((pq)->hq_tab) +#define FreeQueueTab(pq) mem_release ((pq)->hq_tab); (pq)->hq_tab = 0 +#define SizeQueueTab(pq) (COUNT)((pq)->num_objects) +#define GetLinkAddr(pq,i) (HLINK)((pq)->pq_tab + ((pq)->object_size * ((i) - 1))) +#else /* !QUEUE_TABLE */ +#define AllocLink(pq) (HLINK)mem_request ((pq)->object_size) +#define LockLink(pq, h) (LINKPTR)mem_lock (h) +#define UnlockLink(pq, h) mem_unlock (h) +#define FreeLink(pq,h) mem_release (h) +#endif /* QUEUE_TABLE */ + +typedef struct queue +{ + HLINK head, tail; +// BYTE object_size; + COUNT object_size; +#ifdef QUEUE_TABLE + BYTE num_objects; + HLINK free_list; + MEM_HANDLE hq_tab; + BYTEPTR pq_tab; +#endif /* QUEUE_TABLE */ +} QUEUE; +typedef QUEUE *PQUEUE; + +// #define SetLinkSize(pq,s) ((pq)->object_size = (BYTE)(s)) +#define SetLinkSize(pq,s) ((pq)->object_size = (COUNT)(s)) +#define GetLinkSize(pq) (COUNT)((pq)->object_size) +#define GetHeadLink(pq) ((pq)->head) +#define SetHeadLink(pq,h) ((pq)->head = (h)) +#define GetTailLink(pq) ((pq)->tail) +#define SetTailLink(pq,h) ((pq)->tail = (h)) +#define _GetPredLink(lpE) ((lpE)->pred) +#define _SetPredLink(lpE,h) ((lpE)->pred = (h)) +#define _GetSuccLink(lpE) ((lpE)->succ) +#define _SetSuccLink(lpE,h) ((lpE)->succ = (h)) + +extern BOOLEAN InitQueue (PQUEUE pq, COUNT num_elements, OBJ_SIZE size); +extern BOOLEAN UninitQueue (PQUEUE pq); +extern void ReinitQueue (PQUEUE pq); +extern void PutQueue (PQUEUE pq, HLINK hLink); +extern void InsertQueue (PQUEUE pq, HLINK hLink, HLINK hRefLink); +extern void RemoveQueue (PQUEUE pq, HLINK hLink); +extern COUNT CountLinks (PQUEUE pq); +#ifdef QUEUE_TABLE +extern HLINK AllocLink (PQUEUE pq); +extern void FreeLink (PQUEUE pq, HLINK hLink); +#endif /* QUEUE_TABLE */ + +#endif /* _DISPLIST_H */ + diff --git a/sc2/src/sc2code/dummy.c b/sc2/src/sc2code/dummy.c new file mode 100644 index 000000000..7ae1752d1 --- /dev/null +++ b/sc2/src/sc2code/dummy.c @@ -0,0 +1,575 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "starcon.h" +#include "coderes.h" + +MEM_HANDLE +LoadVidInstance (DWORD res) +{ + (void) res; /* Satisfying compiler (unused parameter) */ + return (0); +} + +/* +void +unlink (PVOID filename) +{ +} +*/ + +MEM_HANDLE +LoadCodeResFile (PSTR pStr) +{ + (void) pStr; /* Satisfying compiler (unused parameter) */ + return (0); +} + +static MEM_HANDLE +GetCodeResData (FILE *fp, DWORD length) +{ +enum +{ + ANDROSYN_CODE_RES, + ARILOU_CODE_RES, + BLACKURQ_CODE_RES, + CHENJESU_CODE_RES, + CHMMR_CODE_RES, + DRUUGE_CODE_RES, + HUMAN_CODE_RES, + ILWRATH_CODE_RES, + MELNORME_CODE_RES, + MMRNMHRM_CODE_RES, + MYCON_CODE_RES, + ORZ_CODE_RES, + PKUNK_CODE_RES, + SHOFIXTI_CODE_RES, + SLYLANDR_CODE_RES, + SPATHI_CODE_RES, + SUPOX_CODE_RES, + SYREEN_CODE_RES, + THRADD_CODE_RES, + UMGAH_CODE_RES, + URQUAN_CODE_RES, + UTWIG_CODE_RES, + VUX_CODE_RES, + YEHAT_CODE_RES, + ZOQFOT_CODE_RES, + + SAMATRA_CODE_RES, + SIS_CODE_RES, + PROBE_CODE_RES +}; + + BYTE which_res; + MEM_HANDLE hData; + + which_res = GetResFileChar (fp); + hData = mem_request (sizeof (MEM_HANDLE) + sizeof (RACE_DESC)); + if (hData) + { + RACE_DESCPTR RDPtr; + + RDPtr = 0; + switch (which_res) + { + case ANDROSYN_CODE_RES: + { + extern RACE_DESCPTR init_androsynth (void); + + RDPtr = init_androsynth (); + break; + } + case ARILOU_CODE_RES: + { + extern RACE_DESCPTR init_arilou (void); + + RDPtr = init_arilou (); + break; + } + case BLACKURQ_CODE_RES: + { + extern RACE_DESCPTR + init_black_urquan + (void); + + RDPtr = init_black_urquan (); + break; + } + case CHENJESU_CODE_RES: + { + extern + RACE_DESCPTR + init_chenjesu + (void); + + RDPtr = init_chenjesu (); + break; + } + case CHMMR_CODE_RES: + { + + extern + RACE_DESCPTR + init_chmmr + (void); + + RDPtr = init_chmmr (); + break; + } + case DRUUGE_CODE_RES: + { + + extern + RACE_DESCPTR + init_druuge + (void); + + RDPtr = init_druuge (); + break; + } + case HUMAN_CODE_RES: + { + + extern + RACE_DESCPTR + init_human + (void); + + RDPtr = init_human (); + break; + } + case ILWRATH_CODE_RES: + { + + extern + RACE_DESCPTR + init_ilwrath + (void); + + RDPtr = init_ilwrath (); + break; + } + case MELNORME_CODE_RES: + { + + extern + RACE_DESCPTR + init_melnorme + (void); + + RDPtr = init_melnorme (); + break; + } + case MMRNMHRM_CODE_RES: + { + + extern + RACE_DESCPTR + init_mmrnmhrm + (void); + + RDPtr = init_mmrnmhrm (); + break; + } + case MYCON_CODE_RES: + { + + extern + RACE_DESCPTR + init_mycon + (void); + + RDPtr = init_mycon (); + break; + } + case ORZ_CODE_RES: + { + + extern + RACE_DESCPTR + init_orz + (void); + + RDPtr = init_orz (); + break; + } + case PKUNK_CODE_RES: + { + + extern + RACE_DESCPTR + init_pkunk + (void); + + RDPtr = init_pkunk (); + break; + } + case SHOFIXTI_CODE_RES: + { + + extern + RACE_DESCPTR + init_shofixti + (void); + + RDPtr = init_shofixti (); + break; + } + case SLYLANDR_CODE_RES: + { + + extern + RACE_DESCPTR + init_slylandro + (void); + + RDPtr = init_slylandro (); + break; + } + case SPATHI_CODE_RES: + { + + extern + RACE_DESCPTR + init_spathi + (void); + + RDPtr = init_spathi (); + break; + } + case SUPOX_CODE_RES: + { + + extern + RACE_DESCPTR + init_supox + (void); + + RDPtr = init_supox (); + break; + } + case SYREEN_CODE_RES: + { + + extern + RACE_DESCPTR + init_syreen + (void); + + RDPtr = init_syreen (); + break; + } + case THRADD_CODE_RES: + { + + extern + RACE_DESCPTR + init_thraddash + (void); + + RDPtr = init_thraddash (); + break; + } + case UMGAH_CODE_RES: + { + + extern + RACE_DESCPTR + init_umgah + (void); + + RDPtr = init_umgah (); + break; + } + case URQUAN_CODE_RES: + { + + extern + RACE_DESCPTR + init_urquan + (void); + + RDPtr = init_urquan (); + break; + } + case UTWIG_CODE_RES: + { + + extern + RACE_DESCPTR + init_utwig + (void); + + RDPtr = init_utwig (); + break; + } + case VUX_CODE_RES: + { + + extern + RACE_DESCPTR + init_vux + (void); + + RDPtr = init_vux (); + break; + } + case YEHAT_CODE_RES: + { + + extern + RACE_DESCPTR + init_yehat + (void); + + RDPtr = init_yehat (); + break; + } + case ZOQFOT_CODE_RES: + { + + extern + RACE_DESCPTR + init_zoqfotpik + (void); + + RDPtr = init_zoqfotpik (); + break; + } + case SAMATRA_CODE_RES: + { + + extern + RACE_DESCPTR + init_samatra + (void); + + RDPtr = init_samatra (); + break; + } + case SIS_CODE_RES: + { + + extern + RACE_DESCPTR + init_sis + (void); + + RDPtr = init_sis (); + break; + } + case PROBE_CODE_RES: + { + + extern + RACE_DESCPTR + init_probe + (void); + + RDPtr = init_probe (); + break; + } + } + + if (RDPtr == 0) + { + mem_release (hData); + hData = 0; + } + else + { + MEM_HANDLE *lp; + + lp = (MEM_HANDLE *)mem_lock (hData); + *((RACE_DESCPTR)&lp[1]) = *RDPtr; + mem_unlock (hData); + } + } + (void) length; /* Satisfying compiler (unused parameter) */ + return (hData); +} + + + BOOLEAN + + InstallCodeResType + (COUNT + code_type) +{ + return (InstallResTypeVectors (code_type, + GetCodeResData, mem_release)); +} + + + MEM_HANDLE + + LoadCodeResInstance + (DWORD + res) +{ + MEM_HANDLE hData; + + hData = GetResource (res); + if (hData) + DetachResource (res); + + return (hData); +} + + + BOOLEAN + + DestroyCodeRes + (MEM_HANDLE + hCode) +{ + return (mem_release (hCode)); +} + + + PVOID + + CaptureCodeRes + (MEM_HANDLE + hCode, + PVOID + pData, + PVOID + *ppLocData, + GLUEFUNC + glue_func) +{ + MEM_HANDLE *p; + + if(hCode==0) + { + printf("Ack! dummy.c::CaptureCodeRes() hCode==0! FATAL!\n"); + return(0); + } + + p = (MEM_HANDLE *)mem_lock (hCode); + *p = hCode; + *ppLocData = &p[1]; + + (void) pData; /* Satisfying compiler (unused parameter) */ + (void) glue_func; /* Satisfying compiler (unused parameter) */ + return (p); +} + + + MEM_HANDLE + + ReleaseCodeRes + (PVOID + CodeRef) +{ + if (CodeRef) + { + MEM_HANDLE hCode; + + mem_unlock (hCode = *(MEM_HANDLE *)CodeRef); + return (hCode); + } + + return (0); +} + + + DWORD + + race_glue + (COUNT + selector, + vararg_dcl + args, + ...) +{ + (void) selector; /* Satisfying compiler (unused parameter) */ + (void) args; /* Satisfying compiler (unused parameter) */ + return (0); +} + + + DRAWABLE + + CreatePixmapRegion + (FRAME + Frame, + PPOINT + lpOrg, + SIZE + width, + SIZE + height) +{ + (void) lpOrg; /* Satisfying compiler (unused parameter) */ + (void) width; /* Satisfying compiler (unused parameter) */ + (void) height; /* Satisfying compiler (unused parameter) */ + return (GetFrameHandle (Frame)); +} + + + void + + SetPrimNextLink + (PPRIMITIVE + pPrim, + COUNT + Link) +{ + SetPrimLinks (pPrim, END_OF_LIST, Link); +} + + + COUNT + + GetPrimNextLink + (PPRIMITIVE + pPrim) +{ + return (GetSuccLink (GetPrimLinks (pPrim))); +} + +/* + + char + + *fgets + (char + *s, + int + n, + FILE + *fp) +{ + return (0); +} +*/ + + + int + + abs + (int + n) +{ + if (n < 0) n = -n; + return (n); +} diff --git a/sc2/src/sc2code/element.h b/sc2/src/sc2code/element.h new file mode 100644 index 000000000..9ea3b6794 --- /dev/null +++ b/sc2/src/sc2code/element.h @@ -0,0 +1,209 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ELEMENT_H +#define _ELEMENT_H + +#define BATTLE_FRAME_RATE 5 + +#define SHIP_INFO_HEIGHT 65 +#define CAPTAIN_XOFFS 4 +#define CAPTAIN_YOFFS (SHIP_INFO_HEIGHT + 4) +#define SHIP_STATUS_HEIGHT (STATUS_HEIGHT >> 1) +#define BAD_GUY_YOFFS 0 +#define GOOD_GUY_YOFFS SHIP_STATUS_HEIGHT +#define STARCON_TEXT_HEIGHT 7 +#define TINY_TEXT_HEIGHT 9 + +#define NORMAL_LIFE 1 + +typedef QUEUE_HANDLE HELEMENT; + +#define GOOD_GUY (1 << 0) +#define BAD_GUY (1 << 1) +#define PLAYER_SHIP (1 << 2) + +#define APPEARING (1 << 3) +#define DISAPPEARING (1 << 4) +#define CHANGING (1 << 5) + +#define NONSOLID (1 << 6) +#define COLLISION (1 << 7) +#define IGNORE_SIMILAR (1 << 8) +#define DEFY_PHYSICS (1 << 9) + +#define FINITE_LIFE (1 << 10) + +#define PRE_PROCESS (1 << 11) +#define POST_PROCESS (1 << 12) + +#define IGNORE_VELOCITY (1 << 13) +#define CREW_OBJECT (1 << 14) +#define BACKGROUND_OBJECT (1 << 15) + +#define HYPERJUMP_LIFE 15 + +#define NUM_EXPLOSION_FRAMES 12 + +#define GAME_SOUND_PRIORITY 2 + +typedef enum +{ + VIEW_STABLE, + VIEW_SCROLL, + VIEW_CHANGE +} VIEW_STATE; + +typedef UWORD ELEMENT_FLAGS; + +#define NO_PRIM NUM_PRIMS + +typedef struct state +{ + POINT location; + struct + { + FRAME frame; + PFRAME farray; + } image; +} STATE; +typedef STATE *PSTATE; + +typedef struct element +{ + HELEMENT pred, succ; + + void (*preprocess_func) (struct element *ElementPtr); + void (*postprocess_func) (struct element *ElementPtr); + void (*collision_func) (struct element *ElementPtr0, PPOINT + pPt0, struct element *ElementPtr1, PPOINT pPt1); + void (*death_func) (struct element *ElementPtr); + + ELEMENT_FLAGS state_flags; + COUNT life_span; + BYTE crew_level, mass_points; + BYTE turn_wait, thrust_wait; + VELOCITY_DESC velocity; + INTERSECT_CONTROL IntersectControl; + COUNT PrimIndex; + STATE current, next; + + PVOID pParent; + HELEMENT hTarget; +} ELEMENT; +typedef ELEMENT *PELEMENT; + +#define MAX_DISPLAY_PRIMS 280 +extern COUNT DisplayFreeList; +extern PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS]; + +#define AllocDisplayPrim() DisplayFreeList; \ + DisplayFreeList = GetSuccLink (GetPrimLinks (&DisplayArray[DisplayFreeList])) +#define FreeDisplayPrim(p) SetPrimLinks (&DisplayArray[p], END_OF_LIST, DisplayFreeList); \ + DisplayFreeList = (p) + +#define STATEPTR PSTATE +#define ELEMENTPTR PELEMENT + +#define GetElementStarShip(e,psd) *(psd) = (PVOID)(e)->pParent +#define SetElementStarShip(e,psd) ((e)->pParent = (PVOID)(psd)) + +#define blast_offset thrust_wait +#define hit_points crew_level +#define next_turn thrust_wait +#define MAX_CREW_SIZE 42 +#define MAX_ENERGY_SIZE 42 +#define MAX_SHIP_MASS 10 +#define GRAVITY_MASS(m) ((m) > MAX_SHIP_MASS * 10) +#define GRAVITY_THRESHOLD (COUNT)255 + +#define WHICH_SIDE(f) (((f) & BAD_GUY) >> 1) +#define OBJECT_CLOAKED(eptr) \ + (GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) >= NUM_PRIMS \ + || (GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) == STAMPFILL_PRIM \ + && GetPrimColor (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) == BLACK_COLOR)) +#define UNDEFINED_LEVEL 0 + +extern HELEMENT AllocElement (void); +extern void FreeElement (HELEMENT hElement); +#define PutElement(h) PutQueue (&disp_q, h) +#define InsertElement(h,i) InsertQueue (&disp_q, h, i) +#define GetHeadElement() GetHeadLink (&disp_q) +#define GetTailElement() GetTailLink (&disp_q) +#define LockElement(h,eptr) *(eptr) = (ELEMENTPTR)LockLink (&disp_q, h) +#define UnlockElement(h) UnlockLink (&disp_q, h) +#define RemoveElement(h) RemoveQueue (&disp_q, h) +#define GetPredElement(l) _GetPredLink (l) +#define GetSuccElement(l) _GetSuccLink (l) + +extern void RedrawQueue (BOOLEAN clear); +extern BOOLEAN DeltaEnergy (ELEMENTPTR ElementPtr, SIZE + energy_delta); +extern BOOLEAN DeltaCrew (ELEMENTPTR ElementPtr, SIZE + crew_delta); + +extern void PlaySound (SOUND S, BYTE Priority); + +extern void ProcessSound (SOUND Sound); + +extern void PreProcessStatus (PELEMENT ShipPtr); +extern void PostProcessStatus (PELEMENT ShipPtr); + +extern void load_gravity_well (BYTE selector); +extern void free_gravity_well (void); +extern void spawn_planet (void); +extern void spawn_asteroid (PELEMENT ElementPtr); +extern void animation_preprocess (PELEMENT ElementPtr); +extern void do_damage (ELEMENTPTR ElementPtr, SIZE + damage); +extern void collision (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1); +extern void crew_preprocess (PELEMENT ElementPtr); +extern void crew_collision (PELEMENT ElementPtr0, PPOINT + pPt0, PELEMENT ElementPtr1, PPOINT pPt1); +extern void AbandonShip (ELEMENTPTR ShipPtr, ELEMENTPTR + TargetPtr, COUNT crew_loss); +extern BOOLEAN TimeSpaceMatterConflict (ELEMENTPTR + ElementPtr); +extern COUNT PlotIntercept (ELEMENTPTR ElementPtr0, + ELEMENTPTR ElementPtr1, COUNT max_turns, COUNT + margin_of_error); +extern BOOLEAN LoadKernel (int argc, char *argv[]); +extern void FreeKernel (void); + +extern void InitDisplayList (void); + +extern void InitGalaxy (void); +extern void MoveGalaxy (VIEW_STATE view_state, register + SIZE dx, register SIZE dy); +extern void ship_preprocess (PELEMENT ElementPtr); +extern void ship_postprocess (register PELEMENT + ElementPtr); +extern void ship_death (PELEMENT ShipPtr); +extern BOOLEAN hyper_transition (PELEMENT ElementPtr); + +extern BOOLEAN CalculateGravity (PELEMENT ElementPtr); +extern UWORD inertial_thrust (ELEMENTPTR ElementPtr); +extern void SetUpElement (register ELEMENTPTR + ElementPtr); + +extern void BattleSong (BOOLEAN DoPlay); +extern void FreeBattleSong (void); + +#endif /* _ELEMENT_H */ + diff --git a/sc2/src/sc2code/encount.c b/sc2/src/sc2code/encount.c new file mode 100644 index 000000000..b9e42438b --- /dev/null +++ b/sc2/src/sc2code/encount.c @@ -0,0 +1,794 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static BOOLEAN +DoSelectAction (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->CurState = ATTACK + 1; + return (FALSE); + } + + if (!pMS->Initialized) + { + pMS->Initialized = TRUE; + pMS->InputFunc = DoSelectAction; + } + else if (InputState & DEVICE_BUTTON1) + { + switch (pMS->CurState) + { + case HAIL: + case ATTACK: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + pMS->CurState = HAIL; + return (FALSE); + case ATTACK + 1: + pMS->Initialized = GameOptions (); + if (pMS->Initialized) + { + DrawMenuStateStrings (PM_CONVERSE, pMS->CurState); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + return ((BOOLEAN)pMS->Initialized); + } + } + else + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == HAIL) + NewState = ATTACK + 1; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == ATTACK + 1) + NewState = HAIL; + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_CONVERSE, NewState); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +void +BuildBattle (COUNT which_player) +{ + PQUEUE pQueue; + HSTARSHIP hStarShip, hNextShip; + HSTARSHIP hBuiltShip; + STARSHIPPTR BuiltShipPtr; + + battle_counter = 0; + if (GetHeadLink (&GLOBAL (npc_built_ship_q)) == 0) + { + SET_GAME_STATE (BATTLE_SEGUE, 0); + return; + } + + if (which_player == 0) + pQueue = &GLOBAL (built_ship_q); + else + { + switch (LOBYTE (GLOBAL (CurrentActivity))) + { + case IN_LAST_BATTLE: + load_gravity_well (NUMBER_OF_PLANET_TYPES); + break; + case IN_HYPERSPACE: + load_gravity_well ((BYTE)((COUNT)Random () + % NUMBER_OF_PLANET_TYPES)); + break; + default: + SET_GAME_STATE (ESCAPE_COUNTER, 110); + load_gravity_well (GET_GAME_STATE (BATTLE_PLANET)); + break; + } + pQueue = &GLOBAL (npc_built_ship_q); + } + + ReinitQueue (&race_q[which_player]); + for (hStarShip = GetHeadLink (pQueue); + hStarShip != 0; hStarShip = hNextShip) + { + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); + hNextShip = _GetSuccLink (FragPtr); + + hBuiltShip = Build (&race_q[which_player], + GET_RACE_ID (FragPtr) == SAMATRA_SHIP ? + SAMATRA_RES_INDEX : FragPtr->RaceResIndex, + 1 << which_player, + StarShipCaptain (FragPtr)); + if (hBuiltShip) + { + BuiltShipPtr = LockStarShip ( + &race_q[which_player], + hBuiltShip + ); + BuiltShipPtr->captains_name_index = + StarShipCaptain (BuiltShipPtr); + BuiltShipPtr->cur_status_flags = + StarShipPlayer (BuiltShipPtr); + if (FragPtr->ShipInfo.crew_level != (BYTE)~0) + BuiltShipPtr->special_counter = FragPtr->ShipInfo.crew_level; + else /* if infinite ships */ + BuiltShipPtr->special_counter = FragPtr->ShipInfo.max_crew; + BuiltShipPtr->RaceDescPtr = + (RACE_DESCPTR)&FragPtr->ShipInfo; + + UnlockStarShip ( + &race_q[which_player], + hBuiltShip + ); + } + + UnlockStarShip (pQueue, hStarShip); + } + + if (which_player == 0 + && (hBuiltShip = Build (&race_q[0], + SIS_RES_INDEX, GOOD_GUY, 0))) + { + BuiltShipPtr = LockStarShip ( + &race_q[0], + hBuiltShip + ); + BuiltShipPtr->captains_name_index = + StarShipCaptain (BuiltShipPtr); + BuiltShipPtr->cur_status_flags = + StarShipPlayer (BuiltShipPtr); + if (GLOBAL_SIS (CrewEnlisted) >= MAX_CREW_SIZE - 1) + BuiltShipPtr->special_counter = MAX_CREW_SIZE; + else + BuiltShipPtr->special_counter = (BYTE)( + GLOBAL_SIS (CrewEnlisted) + 1 + ); + BuiltShipPtr->energy_counter = MAX_ENERGY_SIZE; + UnlockStarShip ( + &race_q[0], + hBuiltShip + ); + } +} + +COUNT +InitEncounter (void) +{ + COUNT i; + MEM_HANDLE hOldIndex; + FRAME SegueFrame; + STAMP s; + TEXT t; + extern FRAME planet[]; +MUSIC_REF MR; + + SetSemaphore (&GraphicsSem); + + hOldIndex = SetResourceIndex (hResIndex); + + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContextFont (TinyFont); + +MR = LoadMusicInstance (REDALERT_MUSIC); +PlayMusic (MR, FALSE, 1); + SegueFrame = CaptureDrawable (LoadGraphic (SEGUE_PMAP_ANIM)); +ClearSemaphore (&GraphicsSem); +while (PLRPlaying (MR)) + TaskSwitch (); +StopMusic (); +DestroyMusic (MR); +SetSemaphore (&GraphicsSem); + s.origin.x = s.origin.y = 0; + + BatchGraphics (); + + SetContextBackGroundColor (BLACK_COLOR); + ClearDrawable (); + s.frame = SegueFrame; + DrawStamp (&s); + +// t.baseline.x = SIS_SCREEN_WIDTH >> 1; + t.baseline.x = (SIS_SCREEN_WIDTH >> 1) + 1; + t.baseline.y = 10; + t.align = ALIGN_CENTER; + + SetContextFont (MicroFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 0); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 12; + t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 1); + t.CharCount = (COUNT)~0; + DrawText (&t); + } + else + { + UNICODE buf[40]; + + t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 2); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 12; + GetClusterName (CurStarDescPtr, buf); + t.pStr = buf; + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 12; + t.pStr = GLOBAL_SIS (PlanetName); + t.CharCount = (COUNT)~0; + DrawText (&t); + } + + s.origin.x = SIS_SCREEN_WIDTH >> 1; + s.origin.y = SIS_SCREEN_HEIGHT >> 1; + s.frame = planet[0]; + DrawStamp (&s); + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_LAST_BATTLE) + { +#define NUM_DISPLAY_PTS (sizeof (display_pt) / sizeof (display_pt[0])) + HSTARSHIP hStarShip, hNextShip; + POINT display_pt[] = + { + {10, 51}, + {-10, 51}, + {33, 40}, + {-33, 40}, + {49, 18}, + {-49, 18}, + {52, -6}, + {-52, -6}, + {44, -27}, + {-44, -27}, + }; + + for (hStarShip = GetHeadLink (&race_q[1]), i = 0; + hStarShip && i < 60; hStarShip = hNextShip, ++i) + { + RECT r; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&race_q[1], hStarShip); + if (StarShipPtr->RaceDescPtr->ship_info.crew_level != (BYTE)~0) + hNextShip = _GetSuccLink (StarShipPtr); + else /* if infinite ships */ + hNextShip = hStarShip; + + s.origin = display_pt[i % NUM_DISPLAY_PTS]; + if (i >= NUM_DISPLAY_PTS) + { + COUNT angle, radius; + + radius = square_root ((long)s.origin.x * s.origin.x + + (long)s.origin.y * s.origin.y) + + ((i / NUM_DISPLAY_PTS) * 18); + + angle = ARCTAN (s.origin.x, s.origin.y); + s.origin.x = COSINE (angle, radius); + s.origin.y = SINE (angle, radius); + } + s.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_info.icons, 0 + ); + GetFrameRect (s.frame, &r); + s.origin.x += (SIS_SCREEN_WIDTH >> 1) - (r.extent.width >> 1); + s.origin.y += (SIS_SCREEN_HEIGHT >> 1) - (r.extent.height >> 1); + DrawStamp (&s); + + UnlockStarShip (&race_q[1], hStarShip); + } + } + + UnbatchGraphics (); + DestroyDrawable (ReleaseDrawable (SegueFrame)); + + SetResourceIndex (hOldIndex); + + ClearSemaphore (&GraphicsSem); + + { + MENU_STATE MenuState; + + MenuState.InputFunc = DoSelectAction; + MenuState.Initialized = FALSE; + + DrawMenuStateStrings (PM_CONVERSE, MenuState.CurState = HAIL); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + DoInput ((PVOID)&MenuState); + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + return (MenuState.CurState); + } +} + +static void +DrawFadeText (UNICODE *str1, UNICODE *str2, BOOLEAN fade_in, PRECT + pRect) +{ + SIZE i; + DWORD TimeIn; + TEXT t1, t2; + COLOR fade_cycle[] = + { + BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x1D), + BUILD_COLOR (MAKE_RGB15 (0x9, 0x9, 0x9), 0x1E), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + BUILD_COLOR (MAKE_RGB15 (0x6, 0x6, 0x6), 0x20), + BUILD_COLOR (MAKE_RGB15 (0x5, 0x5, 0x5), 0x21), + BUILD_COLOR (MAKE_RGB15 (0x4, 0x4, 0x4), 0x22), + BUILD_COLOR (MAKE_RGB15 (0x3, 0x3, 0x3), 0x23), + }; +#define NUM_FADES (sizeof (fade_cycle) / sizeof (fade_cycle[0])) + + t1.baseline.x = pRect->corner.x + 100; + t1.baseline.y = pRect->corner.y + 45; + t1.align = ALIGN_CENTER; + t1.pStr = str1; + t1.CharCount = (COUNT)~0; + t2 = t1; + t2.baseline.y += 11; + t2.pStr = str2; + + FlushInput (); + TimeIn = GetTimeCounter (); + if (fade_in) + { + for (i = 0; i < (SIZE) NUM_FADES; ++i) + { + ClearSemaphore (&GraphicsSem); + if (AnyButtonPress (TRUE)) + i = NUM_FADES - 1; + SetSemaphore (&GraphicsSem); + + SetContextForeGroundColor (fade_cycle[i]); + DrawText (&t1); + DrawText (&t2); + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 20)); + } + } + else + { + for (i = NUM_FADES - 1; i >= 0; --i) + { + ClearSemaphore (&GraphicsSem); + if (AnyButtonPress (TRUE)) + i = 0; + SetSemaphore (&GraphicsSem); + + SetContextForeGroundColor (fade_cycle[i]); + DrawText (&t1); + DrawText (&t2); + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 20)); + } + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawText (&t1); + DrawText (&t2); + } +} + +COUNT +UninitEncounter (void) +{ + COUNT ships_killed; + + ships_killed = 0; + + SetSemaphore (&GraphicsSem); + free_gravity_well (); + + if ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 + || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE + || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) + goto ExitUninitEncounter; + + if (GET_GAME_STATE (BATTLE_SEGUE) == 0) + { + ReinitQueue (&race_q[0]); + ReinitQueue (&race_q[1]); + } + else + { + BOOLEAN Sleepy; + DWORD Time; + SIZE VictoryState; + COUNT RecycleAmount; + SIZE i; + RECT r, scavenge_r; + TEXT t; + STAMP ship_s; + UNICODE *str1, *str2, buf[20]; + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + COLOR fade_ship_cycle[] = + { + BUILD_COLOR (MAKE_RGB15 (0x7, 0x00, 0x00), 0x2F), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x27), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x14, 0x14), 0x25), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x14, 0x14), 0x25), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x27), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + }; +#define NUM_SHIP_FADES (sizeof (fade_ship_cycle) / sizeof (fade_ship_cycle[0])) + COUNT race_bounty[] = + { + RACE_SHIP_COST + }; + + SET_GAME_STATE (BATTLE_SEGUE, 0); + SET_GAME_STATE (BOMB_CARRIER, 0); + + VictoryState = ( + HIBYTE (battle_counter) || !LOBYTE (battle_counter) + || GET_GAME_STATE (URQUAN_PROTECTING_SAMATRA) + ) ? 0 : 1; + + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); + battle_counter = GET_RACE_ID (FragPtr) + 1; + if (GetStarShipFromIndex ( + &GLOBAL (avail_race_q), + (COUNT)(battle_counter - 1) + ) == 0) + { + VictoryState = -1; + InitSISContexts (); + } + UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); + + Sleepy = TRUE; + for (i = 0; i < NUM_SIDES; ++i) + { + PQUEUE pQueue; + HSTARSHIP hNextShip; + + if (i == 0) + pQueue = &GLOBAL (built_ship_q); + else + { + if (VictoryState < 0) + VictoryState = 0; + else + { + ClearSemaphore (&GraphicsSem); + DrawSISFrame (); + SetSemaphore (&GraphicsSem); + + DrawSISMessage (NULL_PTR); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + DrawHyperCoords ( + GLOBAL (ShipStamp.origin) + ); + else if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) + DrawHyperCoords (CurStarDescPtr->star_pt); + else + DrawSISTitle(GLOBAL_SIS (PlanetName)); + + SetContext (SpaceContext); + if (VictoryState) + DrawArmadaPickShip (TRUE, &scavenge_r); + } + pQueue = &GLOBAL (npc_built_ship_q); + } + + ReinitQueue (&race_q[(NUM_SIDES - 1) - i]); + + for (hStarShip = GetHeadLink (pQueue); hStarShip; hStarShip = hNextShip) + { + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); + hNextShip = _GetSuccLink (FragPtr); + + if (FragPtr->ShipInfo.crew_level == 0 + || (VictoryState && i == NUM_SIDES - 1)) + { + if (i == NUM_SIDES - 1) + { + ++ships_killed; + if (VictoryState) + { +#define MAX_DEAD_DISPLAYED 5 + COUNT j; + + if (ships_killed == 1) + { + RecycleAmount = 0; + + DrawStatusMessage ((UNICODE *)~0); + + ship_s.origin.x = scavenge_r.corner.x + 32; + ship_s.origin.y = scavenge_r.corner.y + 56; + ship_s.frame = IncFrameIndex (FragPtr->ShipInfo.icons); + DrawStamp (&ship_s); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + SetContextFont (TinyFont); + + GetStringContents ( + FragPtr->ShipInfo.race_strings, (STRINGPTR)buf, FALSE + ); + wstrupr (buf); + + t.baseline.x = scavenge_r.corner.x + 100; + t.baseline.y = scavenge_r.corner.y + 68; + t.align = ALIGN_CENTER; + t.pStr = buf; + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 6; + t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 3); + t.CharCount = (COUNT)~0; + DrawText (&t); + + ship_s.frame = FragPtr->ShipInfo.icons; + + SetContextFont (MicroFont); + DrawFadeText ( + str1 = GAME_STRING (ENCOUNTER_STRING_BASE + 4), + str2 = GAME_STRING (ENCOUNTER_STRING_BASE + 5), + TRUE, + &scavenge_r + ); + } + + r.corner.y = scavenge_r.corner.y + 9; + r.extent.height = 22; + + SetContextForeGroundColor (BLACK_COLOR); + + r.extent.width = 34; + r.corner.x = scavenge_r.corner.x + scavenge_r.extent.width + - (10 + r.extent.width); + DrawFilledRectangle (&r); + + /* collect bounty ResUnits */ + j = race_bounty[battle_counter - 1] >> 3; + RecycleAmount += j; + wsprintf (buf, "%u", RecycleAmount); + t.baseline.x = r.corner.x + r.extent.width - 1; + t.baseline.y = r.corner.y + 14; + t.align = ALIGN_RIGHT; + t.pStr = buf; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50) + ); + DrawText (&t); + DeltaSISGauges (0, 0, j); + + if ((VictoryState++ - 1) % MAX_DEAD_DISPLAYED) + ship_s.origin.x += 17; + else + { + SetContextForeGroundColor (BLACK_COLOR); + + r.corner.x = scavenge_r.corner.x + 10; + r.extent.width = 104; + DrawFilledRectangle (&r); + + ship_s.origin.x = r.corner.x + 2; + ship_s.origin.y = scavenge_r.corner.y + 12; + } + + if (Sleepy) + { + Time = GetTimeCounter (); + for (j = 0; j < NUM_SHIP_FADES; ++j) + { + ClearSemaphore (&GraphicsSem); + Sleepy = (BOOLEAN)!AnyButtonPress (TRUE); + SetSemaphore (&GraphicsSem); + if (!Sleepy) + break; + + SetContextForeGroundColor (fade_ship_cycle[j]); + DrawFilledStamp (&ship_s); + + Time = SleepTask (Time + (ONE_SECOND / 15)); + } + } + DrawStamp (&ship_s); + } + } + + UnlockStarShip (pQueue, hStarShip); + RemoveQueue (pQueue, hStarShip); + FreeStarShip (pQueue, hStarShip); + + continue; + } + + UnlockStarShip (pQueue, hStarShip); + } + } + + if (VictoryState) + { + INPUT_STATE InputState; + +#ifdef NEVER + DestroyDrawable (ReleaseDrawable (s.frame)); +#endif /* NEVER */ + + FlushInput (); + Time = GetTimeCounter () + (ONE_SECOND * 3); + ClearSemaphore (&GraphicsSem); + while (!(InputState = AnyButtonPress (TRUE)) && GetTimeCounter () < Time) + ; + SetSemaphore (&GraphicsSem); + if (GetInputUNICODE (InputState) != 0x1B) /* Escape key */ + { + DrawFadeText (str1, str2, FALSE, &scavenge_r); + if (GetInputUNICODE (InputState) != 0x1B) /* Escape key */ + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = scavenge_r.corner.x + 10; + r.extent.width = 132; + DrawFilledRectangle (&r); + wsprintf (buf, "%u RU", RecycleAmount); + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + 14; + t.align = ALIGN_CENTER; + t.pStr = buf; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50) + ); + DrawText (&t); + + DrawFadeText ( + str1 = GAME_STRING (ENCOUNTER_STRING_BASE + 6), + str2 = GAME_STRING (ENCOUNTER_STRING_BASE + 7), + TRUE, + &scavenge_r + ); + Time = GetTimeCounter () + ONE_SECOND * 2; + ClearSemaphore (&GraphicsSem); + while (!(InputState = AnyButtonPress (TRUE)) + && GetTimeCounter () < Time) + ; + SetSemaphore (&GraphicsSem); + if (GetInputUNICODE (InputState) != 0x1B) /* Escape key */ + DrawFadeText (str1, str2, FALSE, &scavenge_r); + } + } + + DrawStatusMessage (NULL_PTR); + } + + if (ships_killed && (battle_counter - 1) == THRADDASH_SHIP + && !GET_GAME_STATE (THRADD_MANNER)) + { + if ((ships_killed += GET_GAME_STATE (THRADDASH_BODY_COUNT)) > + THRADDASH_BODY_THRESHOLD) + ships_killed = THRADDASH_BODY_THRESHOLD; + SET_GAME_STATE (THRADDASH_BODY_COUNT, ships_killed); + } + } +ExitUninitEncounter: + ClearSemaphore (&GraphicsSem); + + return (ships_killed); +} + +void +EncounterBattle (void) +{ + MEM_HANDLE hLastIndex; + ACTIVITY OldActivity; + extern UWORD nth_frame; + extern BOOLEAN LoadSC2Data (void); + extern BOOLEAN FreeSC2Data (void); + + SetSemaphore (&GraphicsSem); + + SET_GAME_STATE (BATTLE_SEGUE, 1); + + hLastIndex = SetResourceIndex (hResIndex); + + OldActivity = GLOBAL (CurrentActivity); + if (LOBYTE (OldActivity) == IN_LAST_BATTLE) + GLOBAL (CurrentActivity) = MAKE_WORD (IN_LAST_BATTLE, 0); + else + GLOBAL (CurrentActivity) = MAKE_WORD (IN_ENCOUNTER, 0); + +// FreeSC2Data (); +// DestroyFont (ReleaseFont (MicroFont)); + while (SoundPlaying ()) + ; +// DestroySound (ReleaseSound (MenuSounds)); + + if (GLOBAL (glob_flags) & CYBORG_ENABLED) + { + BYTE cur_speed; + + cur_speed = (BYTE)(GLOBAL (glob_flags) & COMBAT_SPEED_MASK) + >> COMBAT_SPEED_SHIFT; + if (cur_speed == 1) + cur_speed = 0; + else if (cur_speed == 2) + ++cur_speed; + else /* if (cur_speed == 3) */ + cur_speed = (BYTE)~0; + nth_frame = MAKE_WORD (1, cur_speed); + PlayerControl[0] = CYBORG_CONTROL | AWESOME_RATING; + PlayerInput[0] = ComputerInput; + } + + GameSounds = CaptureSound (LoadSound (GAME_SOUNDS)); + + ClearSemaphore (&GraphicsSem); + Battle (); + SetSemaphore (&GraphicsSem); + + DestroySound (ReleaseSound (GameSounds)); + GameSounds = 0; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; + + if (GLOBAL (glob_flags) & CYBORG_ENABLED) + { + nth_frame = MAKE_WORD (0, 0); + PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING, + PlayerInput[0] = NormalInput; + } + + SetResourceIndex (hResIndex); +// MicroFont = CaptureFont ( +// LoadGraphic (MICRO_FONT) +// ); +// MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS)); +// LoadSC2Data (); + + GLOBAL (CurrentActivity) = OldActivity; + + SetResourceIndex (hLastIndex); + + ClearSemaphore (&GraphicsSem); +} + diff --git a/sc2/src/sc2code/encount.h b/sc2/src/sc2code/encount.h new file mode 100644 index 000000000..1fe22aba8 --- /dev/null +++ b/sc2/src/sc2code/encount.h @@ -0,0 +1,172 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ENCOUNT_H +#define _ENCOUNT_H + +typedef QUEUE_HANDLE HENCOUNTER; + +#define MAX_HYPER_SHIPS 7 +#define ONE_SHOT_ENCOUNTER (1 << 7) +#define ENCOUNTER_REFORMING (1 << 6) + +typedef struct +{ + POINT star_pt; + BYTE Type, Index; + SHIP_INFO ShipList[MAX_HYPER_SHIPS]; +} EXTENDED_STAR_DESC; +typedef EXTENDED_STAR_DESC *PEXTENDED_STAR_DESC; + +typedef struct +{ + HENCOUNTER pred, succ; + + HELEMENT hElement; + + SIZE transition_state; + POINT origin; + COUNT radius; + + EXTENDED_STAR_DESC SD; + + long log_x, log_y; +} ENCOUNTER; +typedef ENCOUNTER *PENCOUNTER; + +#define AllocEncounter() AllocLink (&GLOBAL (encounter_q)) +#define PutEncounter(h) PutQueue (&GLOBAL (encounter_q), h) +#define InsertEncounter(h,i) InsertQueue (&GLOBAL (encounter_q), h, i) +#define GetHeadEncounter() GetHeadLink (&GLOBAL (encounter_q)) +#define GetTailEncounter() GetTailLink (&GLOBAL (encounter_q)) +#define LockEncounter(h,eptr) *(eptr) = (ENCOUNTERPTR)LockLink (&GLOBAL (encounter_q), h) +#define UnlockEncounter(h) UnlockLink (&GLOBAL (encounter_q), h) +#define RemoveEncounter(h) RemoveQueue (&GLOBAL (encounter_q), h) +#define FreeEncounter(h) FreeLink (&GLOBAL (encounter_q), h) +#define GetPredEncounter(l) _GetPredLink (l) +#define GetSuccEncounter(l) _GetSuccLink (l) + +#define ENCOUNTERPTR PENCOUNTER + +enum +{ + SOL_DEFINED = 1, + SHOFIXTI_DEFINED, + MAIDENS_DEFINED, + START_COLONY_DEFINED, + SPATHI_DEFINED, + ZOQFOT_DEFINED, + + MELNORME0_DEFINED, + MELNORME1_DEFINED, + MELNORME2_DEFINED, + MELNORME3_DEFINED, + MELNORME4_DEFINED, + MELNORME5_DEFINED, + MELNORME6_DEFINED, + MELNORME7_DEFINED, + MELNORME8_DEFINED, + + TALKING_PET_DEFINED, + CHMMR_DEFINED, + SYREEN_DEFINED, + BURVIXESE_DEFINED, + SLYLANDRO_DEFINED, + DRUUGE_DEFINED, + BOMB_DEFINED, + AQUA_HELIX_DEFINED, + SUN_DEVICE_DEFINED, + TAALO_PROTECTOR_DEFINED, + SHIP_VAULT_DEFINED, + URQUAN_WRECK_DEFINED, + VUX_BEAST_DEFINED, + SAMATRA_DEFINED, + ZOQ_SCOUT_DEFINED, + MYCON_DEFINED, + EGG_CASE0_DEFINED, + EGG_CASE1_DEFINED, + EGG_CASE2_DEFINED, + PKUNK_DEFINED, + UTWIG_DEFINED, + SUPOX_DEFINED, + YEHAT_DEFINED, + VUX_DEFINED, + ORZ_DEFINED, + THRADD_DEFINED, + RAINBOW_DEFINED, + ILWRATH_DEFINED, + ANDROSYNTH_DEFINED, + MYCON_TRAP_DEFINED +}; + +#define UMGAH_DEFINED TALKING_PET_DEFINED + +#define TEXT_X_OFFS 1 +#define TEXT_Y_OFFS 1 +#define SIS_TEXT_WIDTH (SIS_SCREEN_WIDTH - (TEXT_X_OFFS << 1)) + +extern STAR_DESCPTR CurStarDescPtr; +extern STAR_DESCPTR star_array; + +#define NUM_SOLAR_SYSTEMS 502 + +extern STAR_DESCPTR FindStar (STAR_DESCPTR pLastStar, PPOINT puniverse, + SIZE xbounds, SIZE ybounds); + +extern void GetClusterName (STAR_DESCPTR pSD, UNICODE buf[]); + +enum +{ + HAIL = 0, + ATTACK +}; + +extern void BuildBattle (COUNT which_player); +extern COUNT InitEncounter (void); +extern COUNT UninitEncounter (void); +extern COUNT InitCommunication (RESOURCE which_comm); +extern void RaceCommunication (void); + +extern void GenerateSOL (BYTE control); +extern void GenerateShofixti (BYTE control); +extern void GenerateColony (BYTE control); +extern void GenerateSpathi (BYTE control); +extern void GenerateZoqFotPik (BYTE control); +extern void GenerateMelnorme (BYTE control); +extern void GenerateTalkingPet (BYTE control); +extern void GenerateChmmr (BYTE control); +extern void GenerateSyreen (BYTE control); +extern void GenerateBurvixes (BYTE control); +extern void GenerateSlylandro (BYTE control); +extern void GenerateDruuge (BYTE control); +extern void GenerateUtwig (BYTE control); +extern void GenerateThradd (BYTE control); +extern void GenerateMycon (BYTE control); +extern void GenerateOrz (BYTE control); +extern void GenerateShipVault (BYTE control); +extern void GenerateUrquanWreck (BYTE control); +extern void GenerateVUX (BYTE control); +extern void GenerateSamatra (BYTE control); +extern void GenerateYehat (BYTE control); +extern void GeneratePkunk (BYTE control); +extern void GenerateSupox (BYTE control); +extern void GenerateRainbow (BYTE control); +extern void GenerateIlwrath (BYTE control); + +#endif /* _ENCOUNT_H */ + diff --git a/sc2/src/sc2code/fmv.c b/sc2/src/sc2code/fmv.c new file mode 100644 index 000000000..627d93af7 --- /dev/null +++ b/sc2/src/sc2code/fmv.c @@ -0,0 +1,157 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "vidlib.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void FreeHyperData (void); + +BOOLEAN InitGameKernel (void); + +void LoadMasterShipList (void); + +//End Added by Chris + +static void +DoFMV (char *name, char *loopname, BOOLEAN uninit) +{ + VidPlay ((MEM_HANDLE)name, loopname, uninit); + while (VidPlaying ()) + ; + VidStop (); +} + +void +DoShipSpin (COUNT index, MUSIC_REF hMusic) +{ + char buf[30]; + BYTE clut_buf[1]; + RECT old_r, r; + + SetGraphicUseOtherExtra (1); + LoadIntoExtraScreen (0); + clut_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 4)); + FlushColorXForms (); + + if (hMusic) + StopMusic (); + + FreeHyperData (); + + sprintf (buf, "ship%02d", index); + DoFMV (buf, "spin", FALSE); + + GetContextClipRect (&old_r); + r.corner.x = r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + SetContextClipRect (&r); + DrawFromExtraScreen (0); + SetGraphicUseOtherExtra (0); + SetContextClipRect (&old_r); + + if (hMusic) + PlayMusic (hMusic, TRUE, 1); + + clut_buf[0] = FadeAllToColor; + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 4)); + FlushColorXForms (); +} + +void +Introduction (void) +{ + BYTE xform_buf[1]; + STAMP s; + DWORD TimeOut; + INPUT_STATE InputState; + + int TempInt; + + xform_buf[0] = FadeAllToBlack; + TempInt=XFormColorMap((COLORMAPPTR)xform_buf, 1); + SleepTask(TempInt); + SetSemaphore (&GraphicsSem); + SetContext (ScreenContext); + s.origin.x = s.origin.y = 0; + s.frame = CaptureDrawable (LoadGraphic (TITLE_ANIM)); + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + ClearSemaphore (&GraphicsSem); + + FlushInput (); + + xform_buf[0] = FadeAllToColor; + TimeOut = XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2); + LoadMasterShipList (); + SleepTask (TimeOut); + + GLOBAL (CurrentActivity) |= CHECK_ABORT; + TimeOut += ONE_SECOND * 3; + while + ( + !(InputState = AnyButtonPress (FALSE)) && + TaskSwitch () <= TimeOut + ) + { + // + } + GLOBAL (CurrentActivity) &= ~CHECK_ABORT; + xform_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); + + if (InputState == 0) + { + static BOOLEAN play_intro = TRUE; + + DoFMV (play_intro ? "intro" : "drumall", NULL, TRUE); + play_intro = !play_intro; + } + + InitGameKernel (); +} + +void +Victory (void) +{ + BYTE xform_buf[1]; + + xform_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); + + DoFMV ("victory", NULL, TRUE); + + xform_buf[0] = FadeAllToBlack; + XFormColorMap ((COLORMAPPTR)xform_buf, 0); + + InitGameKernel (); +} + +void +Logo (void) +{ + DoFMV ("logo", NULL, FALSE); +} + + + + diff --git a/sc2/src/sc2code/galaxy.c b/sc2/src/sc2code/galaxy.c new file mode 100644 index 000000000..38fc6ec79 --- /dev/null +++ b/sc2/src/sc2code/galaxy.c @@ -0,0 +1,513 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* background starfield - used to generate agalaxy.asm */ + +#include "starcon.h" + +//Added by Chris + +void InsertPrim (PRIM_LINKS *pLinks, COUNT PI, COUNT iPI); + +//End Added by Chris + +#define BIG_STAR_COUNT 30 +#define MED_STAR_COUNT 60 +#define SML_STAR_COUNT 90 +#define NUM_STARS (BIG_STAR_COUNT \ + + MED_STAR_COUNT \ + + SML_STAR_COUNT) + +POINT SpaceOrg; +static POINT log_star_array[NUM_STARS]; + +#define NUM_STAR_PLANES 3 + +typedef struct +{ + COUNT min_star_index, num_stars; + PPOINT star_array; + PPOINT pmin_star, plast_star; +} STAR_BLOCK; +typedef STAR_BLOCK *PSTAR_BLOCK; + +STAR_BLOCK StarBlock[NUM_STAR_PLANES] = +{ + { + 0, BIG_STAR_COUNT, + &log_star_array[0], + }, + { + 0, MED_STAR_COUNT, + &log_star_array[BIG_STAR_COUNT], + }, + { + 0, SML_STAR_COUNT, + &log_star_array[BIG_STAR_COUNT + MED_STAR_COUNT], + }, +}; + +static void +SortStarBlock (PSTAR_BLOCK pStarBlock) +{ + COUNT i; + + for (i = 0; i < pStarBlock->num_stars; ++i) + { + COUNT j; + + for (j = pStarBlock->num_stars - 1; j > i; --j) + { + if (pStarBlock->star_array[i].y > pStarBlock->star_array[j].y) + { + POINT temp; + + temp = pStarBlock->star_array[i]; + pStarBlock->star_array[i] = pStarBlock->star_array[j]; + pStarBlock->star_array[j] = temp; + } + } + } + + pStarBlock->min_star_index = 0; + pStarBlock->pmin_star = &pStarBlock->star_array[0]; + pStarBlock->plast_star = + &pStarBlock->star_array[pStarBlock->num_stars - 1]; +} + +static void +WrapStarBlock (SIZE plane, register SIZE dx, register SIZE dy) +{ + register COUNT i; + register PPOINT ppt; + register SIZE offs_y; + register COUNT num_stars; + register PSTAR_BLOCK pStarBlock; + + pStarBlock = &StarBlock[plane]; + + i = pStarBlock->min_star_index; + ppt = pStarBlock->pmin_star; + num_stars = pStarBlock->num_stars; + if (dy < 0) + { + register COUNT first; + + first = i; + + dy = -dy; + offs_y = (LOG_SPACE_HEIGHT << plane) - dy; + + while (ppt->y < dy) + { + ppt->y += offs_y; + ppt->x += dx; + if (++i < num_stars) + ++ppt; + else + { + i = 0; + ppt = &pStarBlock->star_array[0]; + } + + if (i == first) + return; + } + pStarBlock->min_star_index = i; + pStarBlock->pmin_star = ppt; + + if (first <= i) + { + i = num_stars - i; + do + { + ppt->y -= dy; + ppt->x += dx; + ++ppt; + } while (--i); + ppt = &pStarBlock->star_array[0]; + } + + if (first > i) + { + i = first - i; + do + { + ppt->y -= dy; + ppt->x += dx; + ++ppt; + } while (--i); + } + } + else + { + register COUNT last; + + --ppt; + if (i-- == 0) + { + i = num_stars - 1; + ppt = pStarBlock->plast_star; + } + + last = i; + + if (dy > 0) + { + offs_y = (LOG_SPACE_HEIGHT << plane) - dy; + + while (ppt->y >= offs_y) + { + ppt->y -= offs_y; + ppt->x += dx; + if (i-- > 0) + --ppt; + else + { + i = num_stars - 1; + ppt = pStarBlock->plast_star; + } + + if (i == last) + return; + } + + pStarBlock->pmin_star = ppt + 1; + if ((pStarBlock->min_star_index = i + 1) == num_stars) + { + pStarBlock->min_star_index = 0; + pStarBlock->pmin_star = &pStarBlock->star_array[0]; + } + } + + if (last >= i) + { + ++i; + do + { + ppt->y += dy; + ppt->x += dx; + --ppt; + } while (--i); + i = num_stars - 1; + ppt = pStarBlock->plast_star; + } + + if (last < i) + { + i = i - last; + do + { + ppt->y += dy; + ppt->x += dx; + --ppt; + } while (--i); + } + } +} + +void +InitGalaxy (void) +{ + COUNT i, factor; + PPOINT ppt; + PRIM_LINKS Links; + +// printf ("transition_width = %d transition_height = %d\n", TRANSITION_WIDTH, TRANSITION_HEIGHT); + + Links = MakeLinks (END_OF_LIST, END_OF_LIST); + factor = ONE_SHIFT + MAX_REDUCTION + (BACKGROUND_SHIFT - 3); + for (i = 0, ppt = log_star_array; i < NUM_STARS; ++i, ++ppt) + { + COUNT p; + + p = AllocDisplayPrim (); + + if (i == BIG_STAR_COUNT || i == BIG_STAR_COUNT + MED_STAR_COUNT) + ++factor; + + ppt->x = (COORD)((UWORD)Random () % SPACE_WIDTH) << factor; + ppt->y = (COORD)((UWORD)Random () % SPACE_HEIGHT) << factor; + + if (i < BIG_STAR_COUNT + MED_STAR_COUNT) + { + SetPrimType (&DisplayArray[p], STAMP_PRIM); + SetPrimColor (&DisplayArray[p], + BUILD_COLOR (MAKE_RGB15 (0xB, 0xB, 0x1F), 0x09)); + DisplayArray[p].Object.Stamp.frame = stars_in_space; + } + else + { + SetPrimType (&DisplayArray[p], POINT_PRIM); + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + SetPrimColor (&DisplayArray[p], + BUILD_COLOR (MAKE_RGB15 (0x15, 0x15, 0x15), 0x07)); + else if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + SetPrimColor (&DisplayArray[p], + BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x8C)); + else + SetPrimColor (&DisplayArray[p], + BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x8C)); + } + + InsertPrim (&Links, p, GetPredLink (Links)); + } + + SortStarBlock (&StarBlock[0]); + SortStarBlock (&StarBlock[1]); + SortStarBlock (&StarBlock[2]); +} + +void +MoveGalaxy (VIEW_STATE view_state, register SIZE dx, register SIZE dy) +{ + register PPRIMITIVE pprim; + + if (view_state != VIEW_STABLE) + { +#ifdef OLD_ZOOM + register BYTE reduction; +#else + register COUNT reduction; +#endif + register COUNT i; + register PPOINT ppt; + +#ifdef OLD_ZOOM + reduction = GLOBAL (cur_state); +#else + { + extern COUNT zoom_out; + + reduction = zoom_out; + } +#endif + if (view_state == VIEW_CHANGE) + { + pprim = DisplayArray; + i = BIG_STAR_COUNT; + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + do + { + pprim->Object.Stamp.frame = + SetAbsFrameIndex (stars_in_space, + ((COUNT)Random () & 31) + (32 + 26)); + ++pprim; + } while (--i); + + i = MED_STAR_COUNT; + do + { + pprim->Object.Stamp.frame = + SetAbsFrameIndex (stars_in_space, + ((COUNT)Random () & 31) + 26); + ++pprim; + } while (--i); + } + else + { + GRAPHICS_PRIM star_object, big_star_obj; + FRAME star_frame; + + star_frame = stars_in_space; +#ifdef OLD_ZOOM + big_star_obj = STAMP_PRIM; + if (reduction > 0) + star_object = POINT_PRIM; + else + { + star_frame = IncFrameIndex (star_frame); + star_object = STAMP_PRIM; + } +#else + if (reduction > (1 << ZOOM_SHIFT)) + big_star_obj = star_object = POINT_PRIM; + else + { + big_star_obj = star_object = STAMP_PRIM; + star_frame = IncFrameIndex (star_frame); + star_object = POINT_PRIM; + } +#endif + + do + { + SetPrimType (pprim, big_star_obj); + pprim->Object.Stamp.frame = star_frame; + ++pprim; + } while (--i); + + pprim = &DisplayArray[BIG_STAR_COUNT]; + i = MED_STAR_COUNT; + do + { + SetPrimType (pprim, star_object); + ++pprim; + } while (--i); + } + } + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + pprim = DisplayArray; + i = BIG_STAR_COUNT + MED_STAR_COUNT; + do + { + COUNT base_index; + + base_index = GetFrameIndex (pprim->Object.Stamp.frame) - 26; + pprim->Object.Stamp.frame = + SetAbsFrameIndex (pprim->Object.Stamp.frame, + ((base_index & ~31) + ((base_index + 1) & 31)) + 26); + ++pprim; + } while (--i); + + dx <<= 3; + dy <<= 3; + } + + WrapStarBlock (2, dx, dy); + WrapStarBlock (1, dx, dy); + WrapStarBlock (0, dx, dy); + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + { + dx = SpaceOrg.x; + dy = SpaceOrg.y; +#ifdef OLD_ZOOM + reduction += ONE_SHIFT; +#else + reduction <<= ONE_SHIFT; +#endif + } + else + { + dx = (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> ((MAX_REDUCTION + 1) + - MAX_VIS_REDUCTION)); + dy = (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> ((MAX_REDUCTION + 1) + - MAX_VIS_REDUCTION)); +#ifdef OLD_ZOOM + reduction = (COUNT)(MAX_VIS_REDUCTION + ONE_SHIFT); +#else + reduction = MAX_ZOOM_OUT << ONE_SHIFT; +#endif + } + + ppt = log_star_array; + pprim = DisplayArray; + + if (view_state == VIEW_CHANGE +#ifdef OLD_ZOOM + || (int)pprim->Object.Point.x != (int)((ppt->x - dx) >> reduction) + || (int)pprim->Object.Point.y != (int)((ppt->y - dy) >> reduction)) +#else + || (int)pprim->Object.Point.x != (int)(((ppt->x - dx) << ZOOM_SHIFT) / reduction) + || (int)pprim->Object.Point.y != (int)(((ppt->y - dy) << ZOOM_SHIFT) / reduction)) +#endif + { + i = BIG_STAR_COUNT; + do + { +// ppt->x &= (LOG_SPACE_WIDTH - 1); +ppt->x = WRAP_VAL (ppt->x, LOG_SPACE_WIDTH); +#ifdef OLD_ZOOM + pprim->Object.Point.x = (ppt->x - dx) >> reduction; + pprim->Object.Point.y = (ppt->y - dy) >> reduction; +#else + pprim->Object.Point.x = ((ppt->x - dx) << ZOOM_SHIFT) / reduction; + pprim->Object.Point.y = ((ppt->y - dy) << ZOOM_SHIFT) / reduction; +#endif + ++pprim, ++ppt; + } while (--i); + dx <<= 1; + dy <<= 1; +#ifdef OLD_ZOOM + ++reduction; +#else + reduction <<= 1; +#endif + + if (view_state == VIEW_CHANGE +#ifdef OLD_ZOOM + || pprim->Object.Point.x != (ppt->x - dx) >> reduction + || pprim->Object.Point.y != (ppt->y - dy) >> reduction) +#else + || (int)(pprim->Object.Point.x) != (int)(((ppt->x - dx) << ZOOM_SHIFT) / reduction) + || (int)(pprim->Object.Point.y) != (int)(((ppt->y - dy) << ZOOM_SHIFT) / reduction)) +#endif + { + i = MED_STAR_COUNT; + do + { +// ppt->x &= ((LOG_SPACE_WIDTH << 1) - 1); +ppt->x = WRAP_VAL (ppt->x, LOG_SPACE_WIDTH << 1); +#ifdef OLD_ZOOM + pprim->Object.Point.x = (ppt->x - dx) >> reduction; + pprim->Object.Point.y = (ppt->y - dy) >> reduction; +#else + pprim->Object.Point.x = ((ppt->x - dx) << ZOOM_SHIFT) / reduction; + pprim->Object.Point.y = ((ppt->y - dy) << ZOOM_SHIFT) / reduction; +#endif + ++pprim, ++ppt; + } while (--i); + dx <<= 1; + dy <<= 1; +#ifdef OLD_ZOOM + ++reduction; +#else + reduction <<= 1; +#endif + + if (view_state == VIEW_CHANGE +#ifdef OLD_ZOOM + || pprim->Object.Point.x != (ppt->x - dx) >> reduction + || pprim->Object.Point.y != (ppt->y - dy) >> reduction) +#else + || (int)(pprim->Object.Point.x) != (int)(((ppt->x - dx) << ZOOM_SHIFT) / reduction) + || (int)(pprim->Object.Point.y) != (int)(((ppt->y - dy) << ZOOM_SHIFT) / reduction)) +#endif + { + i = SML_STAR_COUNT; + do + { +// ppt->x &= ((LOG_SPACE_WIDTH << 2) - 1); +ppt->x = WRAP_VAL (ppt->x, LOG_SPACE_WIDTH << 2); +#ifdef OLD_ZOOM + pprim->Object.Point.x = (ppt->x - dx) >> reduction; + pprim->Object.Point.y = (ppt->y - dy) >> reduction; +#else + pprim->Object.Point.x = ((ppt->x - dx) << ZOOM_SHIFT) / reduction; + pprim->Object.Point.y = ((ppt->y - dy) << ZOOM_SHIFT) / reduction; +#endif + ++pprim, ++ppt; + } while (--i); + } + } + } + } + + { + extern PRIM_LINKS DisplayLinks; + + DisplayLinks = MakeLinks (NUM_STARS - 1, 0); + } +} + diff --git a/sc2/src/sc2code/gameinp.c b/sc2/src/sc2code/gameinp.c new file mode 100644 index 000000000..cc0d1c547 --- /dev/null +++ b/sc2/src/sc2code/gameinp.c @@ -0,0 +1,171 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +typedef struct +{ + BOOLEAN (*InputFunc) (INPUT_STATE InputState, PVOID pInputState); + COUNT MenuRepeatDelay; +} INPUT_STATE_DESC; +typedef INPUT_STATE_DESC *PINPUT_STATE_DESC; + +INPUT_STATE OldInputState; + +void +DoInput (PVOID pInputState) +{ + DWORD NewTime; + INPUT_STATE InputState; + + NewTime = GetTimeCounter (); + ((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay = MENU_REPEAT_DELAY; + do + { + NewTime = TaskSwitch (); + + InputState = GetInputState (NormalInput); + +#if DEMO_MODE || CREATE_JOURNAL + if (ArrowInput != DemoInput) +#endif + { + static DWORD OldTime; + int test1,test2; + + test1=NewTime - OldTime; + test2=(DWORD)((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay; + + if (InputState == OldInputState + && NewTime - OldTime < + (DWORD)((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay) + InputState = 0; + else + { +#define ACCELERATION_INCREMENT 10 + if (InputState != OldInputState) + ((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay = + MENU_REPEAT_DELAY; + else if (((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay + <= ACCELERATION_INCREMENT) + ((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay = + ACCELERATION_INCREMENT; + else + ((PINPUT_STATE_DESC)pInputState)->MenuRepeatDelay -= + ACCELERATION_INCREMENT; + + if (OldInputState != (INPUT_STATE)~0L) + OldInputState = InputState; + else + { + OldInputState = InputState; + InputState = 0; + } + + OldTime = NewTime; + } + +#if CREATE_JOURNAL + JournalInput (InputState); +#endif /* CREATE_JOURNAL */ + } + + if (InputState & DEVICE_EXIT) + InputState = ConfirmExit (); + + if (MenuSounds + && (pSolarSysState == 0 + /* see if in menu */ + || pSolarSysState->MenuState.CurState + || pSolarSysState->MenuState.Initialized > 2) + && ((InputState & DEVICE_BUTTON1) + || GetInputXComponent (InputState) + || GetInputYComponent (InputState)) +#ifdef NEVER + && !PLRPlaying ((MUSIC_REF)~0) +#endif /* NEVER */ + ) + { + SOUND S; + + S = MenuSounds; + if (InputState & DEVICE_BUTTON1) + S = SetAbsSoundIndex (S, 1); + + PlaySoundEffect (S, 0, 0); + } + + } while ((*((PINPUT_STATE_DESC)pInputState)->InputFunc) + (InputState, pInputState)); + + OldInputState = (INPUT_STATE)~0L; +} + +INPUT_STATE +game_input (INPUT_REF InputRef, INPUT_STATE InputState) +{ + if (LastActivity & (CHECK_LOAD | CHECK_RESTART)) + { + InputState = 0; + } + else if (InputState == 0 + && (InputState = GetInputState (ArrowInput)) == 0 + && (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE + || (InputState = GetInputState (CombinedInput[0])) == 0)) + { + if ((InputState = GetInputState (JoystickInput[0])) == 0) + InputState = GetInputState (JoystickInput[1]); + } + (void) InputRef; /* Satisfying compiler (unused parameter) */ + return (InputState); +} + +INPUT_STATE +combined_input0 (INPUT_REF InputRef, INPUT_STATE InputState) +{ + if (LastActivity & (CHECK_LOAD | CHECK_RESTART)) + { + InputState = 0; + } + else if (InputState == 0 + && (InputState = GetInputState (JoystickInput[0])) == 0) + { + InputState = GetInputState (KeyboardInput[0]); + } + + (void) InputRef; /* Satisfying compiler (unused parameter) */ + return (InputState); +} + + +INPUT_STATE +combined_input1 (INPUT_REF InputRef, INPUT_STATE InputState) +{ + if (LastActivity & (CHECK_LOAD | CHECK_RESTART)) + { + InputState = 0; + } + else if (InputState == 0 + && (InputState = GetInputState (JoystickInput[1])) == 0) + { + InputState = GetInputState (KeyboardInput[1]); + } + + (void) InputRef; /* Satisfying compiler (unused parameter) */ + return (InputState); +} diff --git a/sc2/src/sc2code/gameopt.c b/sc2/src/sc2code/gameopt.c new file mode 100644 index 000000000..6b0c942e8 --- /dev/null +++ b/sc2/src/sc2code/gameopt.c @@ -0,0 +1,1311 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "starcon.h" +#include "commglue.h" +#include "SDL_wrapper.h" + +//Added by Chris + +BOOLEAN SaveProblem (void); + +//End Added by Chris + +#define MAX_SAVED_GAMES 10 + +static PMENU_STATE pLocMenuState; + +void +ConfirmSaveLoad (STAMP *MsgStamp) +{ + RECT r, clip_r; + TEXT t; + + SetContextFont (StarConFont); + GetContextClipRect (&clip_r); + if (clip_r.extent.width == 0) + { + clip_r.corner.x = clip_r.corner.y = 0; + clip_r.extent.width = SCREEN_WIDTH; + clip_r.extent.height = SCREEN_HEIGHT; + } + + t.baseline.x = clip_r.extent.width >> 1; + t.baseline.y = (clip_r.extent.height >> 1) + 3; + t.align = ALIGN_CENTER; + t.CharCount = (COUNT)~0; + if (MsgStamp) + t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 0); + else + t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 1); + TextRect (&t, &r, NULL_PTR); + r.corner.x -= 4; + r.corner.y -= 4; + r.extent.width += 8; + r.extent.height += 8; + if (MsgStamp) + { + MsgStamp->origin = r.corner; + r.corner.x += clip_r.corner.x; + r.corner.y += clip_r.corner.y; + MsgStamp->frame = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); + r.corner.x -= clip_r.corner.x; + r.corner.y -= clip_r.corner.y; + } + DrawStarConBox (&r, 2, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x0F)); + DrawText (&t); +} + +enum +{ + SAVE_GAME = 0, + LOAD_GAME, + SETTINGS +}; + +static BOOLEAN DoGameOptions (INPUT_STATE InputState, PMENU_STATE pMS); + +enum +{ + SOUND_ON_SETTING, + SOUND_OFF_SETTING, + MUSIC_ON_SETTING, + MUSIC_OFF_SETTING, + CYBORG_OFF_SETTING, + CYBORG_NORMAL_SETTING, + CYBORG_DOUBLE_SETTING, + CYBORG_SUPER_SETTING, + CHANGE_CAPTAIN_SETTING, + CHANGE_SHIP_SETTING, + EXIT_MENU_SETTING +}; + +static void +FeedbackSetting (BYTE which_setting) +{ + UNICODE buf[20]; + + buf[0] = '\0'; + switch (which_setting) + { + case SOUND_ON_SETTING: + case SOUND_OFF_SETTING: + wsprintf (buf, "%s %s", + GAME_STRING (OPTION_STRING_BASE + 0), + GLOBAL (glob_flags) & SOUND_DISABLED + ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4)); + break; + case MUSIC_ON_SETTING: + case MUSIC_OFF_SETTING: + wsprintf (buf, "%s %s", + GAME_STRING (OPTION_STRING_BASE + 1), + GLOBAL (glob_flags) & MUSIC_DISABLED + ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4)); + break; + case CYBORG_OFF_SETTING: + case CYBORG_NORMAL_SETTING: + case CYBORG_DOUBLE_SETTING: + case CYBORG_SUPER_SETTING: + wsprintf (buf, "%s %s", + GAME_STRING (OPTION_STRING_BASE + 2), + !(GLOBAL (glob_flags) & CYBORG_ENABLED) + ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4)); + break; + case CHANGE_CAPTAIN_SETTING: + case CHANGE_SHIP_SETTING: + wstrcpy (buf, GAME_STRING (NAMING_STRING_BASE + 0)); + break; + } + + SetSemaphore (&GraphicsSem); + DrawStatusMessage (buf); + ClearSemaphore (&GraphicsSem); +} + +static BOOLEAN DoSettings (INPUT_STATE InputState, PMENU_STATE pMS); + +static BOOLEAN +DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) +{ + COUNT rel_index; + RECT r; + TEXT lf; + COLOR BackGround, ForeGround; + FONT Font; + static BOOLEAN DoNaming (INPUT_STATE InputState, PMENU_STATE pMS); + + SetSemaphore (&GraphicsSem); + + rel_index = (COUNT)(which_string - pMS->first_item.y); + + { + r.corner.x = 2; + r.extent.width = SHIP_NAME_WIDTH; + r.extent.height = SHIP_NAME_HEIGHT; + + SetContext (StatusContext); + if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + { + Font = TinyFont; + r.corner.y = 10; + ++r.corner.x; + r.extent.width -= 2; + lf.baseline.x = r.corner.x + (r.extent.width >> 1) - 1; + + BackGround = BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09); + ForeGround = BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B); + } + else + { + Font = StarConFont; + r.corner.y = 20; + lf.baseline.x = r.corner.x + (r.extent.width >> 1); + + BackGround = BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D); + ForeGround = BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7D); + } + + lf.baseline.y = r.corner.y + r.extent.height - 1; + lf.align = ALIGN_CENTER; + } + + SetContextFont (Font); + lf.pStr = ((GAME_DESC *)pMS->CurString)[rel_index]; + lf.CharCount = (COUNT)~0; + + if (state <= 0) + { + if (pMS->InputFunc == DoNaming) + { + if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + DrawCaptainsName (); + else + { + DrawFlagshipName (TRUE); + if (pMenuState && pMenuState->InputFunc == DoOutfit) + DrawFlagshipName (FALSE); + } + } + else + { + if (state == 0) + { + COLOR OldColor; + + OldColor = SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + SetContextForeGroundColor (OldColor); + } + DrawText (&lf); + } + SetFlashRect (&r, (FRAME)0); + SetFlashRect ((PRECT)~0L, (FRAME)0); + } + else + { + COUNT i; + RECT text_r; + BYTE char_deltas[MAX_DESC_CHARS]; + PBYTE pchar_deltas; + + TextRect (&lf, &text_r, char_deltas); + if ((text_r.extent.width + 2) >= r.extent.width) + { + ClearSemaphore (&GraphicsSem); + return (FALSE); + } + + SetContextForeGroundColor (BackGround); + DrawFilledRectangle (&r); + + pchar_deltas = char_deltas; + for (i = pMS->first_item.x; i > 0; --i) + text_r.corner.x += (SIZE)*pchar_deltas++; + if (SerialInput) + { + if ((COUNT)pMS->first_item.x < lf.CharCount) /* end of line */ + --text_r.corner.x; + text_r.extent.width = 1; + } + else + { + if ((COUNT)pMS->first_item.x == lf.CharCount) /* end of line */ + text_r.extent.width = 1; + else + text_r.extent.width = (SIZE)*pchar_deltas; + } + text_r.corner.y = r.corner.y; + text_r.extent.height = r.extent.height; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&text_r); + + SetContextForeGroundColor (ForeGround); + DrawText (&lf); + + SetFlashRect (&r, (FRAME)0); + } + + ClearSemaphore (&GraphicsSem); + return (TRUE); +} + +static UWORD +DoTextEntry (PMENU_STATE pMS, INPUT_STATE InputState) +{ + UWORD ch; + UNICODE *pStr, *pBaseStr; + COUNT len; + + pBaseStr = ((GAME_DESC *)pMS->CurString)[pMS->CurState - pMS->first_item.y]; + pStr = &pBaseStr[pMS->first_item.x]; + len = wstrlen (pStr); + if (SerialInput) + { + ch = GetInputUNICODE (GetInputState (SerialInput)); + } + else + { + extern UWORD GetJoystickChar (INPUT_STATE InputState); + + ch = GetJoystickChar (InputState); + } + + switch (ch) + { + case 0x7F: + if (len) + { + memmove (pStr, pStr + 1, len * sizeof (*pStr)); + len = (COUNT)~0; + } + break; + case '\b': + if (pMS->first_item.x) + { + memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); + --pMS->first_item.x; + + len = (COUNT)~0; + } + break; + default: + if (isprint (ch) && len + (pStr - pBaseStr) < MAX_DESC_CHARS) + { + if (SerialInput) + { + memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); + *pStr++ = ch; + ++pMS->first_item.x; + } + else + { + *pStr = ch; + if (len == 0) + *(pStr + 1) = '\0'; + } + + len = (COUNT)~0; + } + break; + } + + if (len == (COUNT)~0) + { + if (!DrawDescriptionString (pMS, pMS->CurState, 1)) + { + len = wstrlen (pStr); + memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); + --pMS->first_item.x; + } + } + else if (GetInputXComponent (InputState) < 0) + { + if (pMS->first_item.x) + { + --pMS->first_item.x; + DrawDescriptionString (pMS, pMS->CurState, 1); + } + } + else if (GetInputXComponent (InputState) > 0) + { + if (len) + { + ++pMS->first_item.x; + DrawDescriptionString (pMS, pMS->CurState, 1); + } + } + + return (ch); +} + +static BOOLEAN +DoNaming (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (!pMS->Initialized) + { + GAME_DESC GD[1]; + + pMS->Initialized = 1; + pMS->InputFunc = DoNaming; + + GD[0][0] = '\0'; + pMS->delta_item = pMS->CurState; + pMS->first_item.x = pMS->first_item.y = 0; + pMS->CurState = 0; + pMS->CurString = (STRING)&GD[0]; + DrawDescriptionString (pMS, pMS->CurState, 1); + + SetSemaphore (&GraphicsSem); + DrawStatusMessage (GAME_STRING (NAMING_STRING_BASE + 0)); + ClearSemaphore (&GraphicsSem); + + DoInput (pMS); + + pMS->InputFunc = DoSettings; + pMS->CurState = (BYTE)pMS->delta_item; + pMS->delta_item = 0; + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) + FeedbackSetting (pMS->CurState); + } + else + { + UWORD ch; + + if (pMS->Initialized == 1 && SerialInput) + { + FlushInput (); + pMS->Initialized = 2; + return (TRUE); + } + + ch = DoTextEntry (pMS, InputState); + + if (ch == '\n' || ch == 0x1B) + { + if (ch == '\n') + { + if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + wstrcpy (GLOBAL_SIS (CommanderName), + (const UNICODE *)((GAME_DESC *)pMS->CurString)[0]); + else + wstrcpy (GLOBAL_SIS (ShipName), + (const UNICODE *)((GAME_DESC *)pMS->CurString)[0]); + } + else + { + if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + wstrcpy ((UNICODE *)((GAME_DESC *)pMS->CurString)[0], + GLOBAL_SIS (CommanderName)); + else + wstrcpy ((UNICODE *)((GAME_DESC *)pMS->CurString)[0], + GLOBAL_SIS (ShipName)); + } + + DrawDescriptionString (pMS, pMS->CurState, 0); + + return (FALSE); + } + } + + return (TRUE); +} + +static BOOLEAN +DoSettings (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE cur_speed; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + cur_speed = (BYTE)(GLOBAL (glob_flags) & COMBAT_SPEED_MASK) >> COMBAT_SPEED_SHIFT; + if (!pMS->Initialized) + { + DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); + FeedbackSetting (pMS->CurState); + pMS->Initialized = TRUE; + pMS->InputFunc = DoSettings; + } + else if ((InputState & DEVICE_BUTTON2) + || ((InputState & DEVICE_BUTTON1) + && pMS->CurState == EXIT_MENU_SETTING)) + { + SetSemaphore (&GraphicsSem); + DrawStatusMessage (NULL_PTR); + ClearSemaphore (&GraphicsSem); + + pMS->CurState = SETTINGS; + pMS->InputFunc = DoGameOptions; + pMS->Initialized = 0; + } + else if (InputState & DEVICE_BUTTON1) + { + switch (pMS->CurState) + { + case SOUND_ON_SETTING: + case SOUND_OFF_SETTING: + ToggleSoundEffect (); + pMS->CurState ^= 1; + DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); + break; + case MUSIC_ON_SETTING: + case MUSIC_OFF_SETTING: + ToggleMusic (); + pMS->CurState ^= 1; + DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); + break; + case CHANGE_CAPTAIN_SETTING: + case CHANGE_SHIP_SETTING: + pMS->Initialized = FALSE; + pMS->InputFunc = DoNaming; + return (TRUE); + default: + if (cur_speed++ < NUM_COMBAT_SPEEDS - 1) + GLOBAL (glob_flags) |= CYBORG_ENABLED; + else + { + cur_speed = 0; + GLOBAL (glob_flags) &= ~CYBORG_ENABLED; + } + GLOBAL (glob_flags) = + (BYTE)((GLOBAL (glob_flags) & ~COMBAT_SPEED_MASK) + | (cur_speed << COMBAT_SPEED_SHIFT)); + pMS->CurState = CYBORG_OFF_SETTING + cur_speed; + DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); + } + + FeedbackSetting (pMS->CurState); + } + else + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + do + { + if (NewState-- == SOUND_ON_SETTING) + NewState = EXIT_MENU_SETTING; + } while ((NewState == SOUND_ON_SETTING + && (GLOBAL (glob_flags) & SOUND_DISABLED)) + || (NewState == SOUND_OFF_SETTING + && !(GLOBAL (glob_flags) & SOUND_DISABLED)) + || (NewState == MUSIC_ON_SETTING + && (GLOBAL (glob_flags) & MUSIC_DISABLED)) + || (NewState == MUSIC_OFF_SETTING + && !(GLOBAL (glob_flags) & MUSIC_DISABLED)) + || (NewState >= CYBORG_OFF_SETTING + && NewState <= CYBORG_SUPER_SETTING + && NewState != cur_speed + CYBORG_OFF_SETTING) + ); + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + do + { + if (NewState++ == EXIT_MENU_SETTING) + NewState = SOUND_ON_SETTING; + } while ((NewState == SOUND_ON_SETTING + && (GLOBAL (glob_flags) & SOUND_DISABLED)) + || (NewState == SOUND_OFF_SETTING + && !(GLOBAL (glob_flags) & SOUND_DISABLED)) + || (NewState == MUSIC_ON_SETTING + && (GLOBAL (glob_flags) & MUSIC_DISABLED)) + || (NewState == MUSIC_OFF_SETTING + && !(GLOBAL (glob_flags) & MUSIC_DISABLED)) + || (NewState >= CYBORG_OFF_SETTING + && NewState <= CYBORG_SUPER_SETTING + && NewState != cur_speed + CYBORG_OFF_SETTING) + ); + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_SOUND_ON, NewState); + pMS->CurState = NewState; + + FeedbackSetting (pMS->CurState); + } + } + + return (TRUE); +} + +static void +DrawCargo (COUNT redraw_state) +{ + BYTE i; + RECT r; + extern FRAME misc_data; + + SetContext (SpaceContext); + if (redraw_state) + { + STAMP s; + + if (redraw_state == 2) + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = 1; + r.corner.y = 12; + r.extent.width = ((SIS_SCREEN_WIDTH - STATUS_WIDTH) >> 1) - r.corner.x; + r.extent.height = 62 - r.corner.y; + DrawFilledRectangle (&r); + GetFrameRect (SetRelFrameIndex ( + pLocMenuState->ModuleFrame, MAX_SAVED_GAMES * 2 + 1 + ), &r); + DrawFilledRectangle (&r); + } + else + { + s.origin.x = s.origin.y = 0; + s.frame = SetAbsFrameIndex (pLocMenuState->ModuleFrame, + GetFrameCount (pLocMenuState->ModuleFrame) - 1); + if (!pLocMenuState->Initialized) + { + DrawStamp (&s); + s.frame = DecFrameIndex (s.frame); + if (pLocMenuState->delta_item == SAVE_GAME) + s.frame = DecFrameIndex (s.frame); + DrawStamp (&s); + if (((SUMMARY_DESC *)pLocMenuState->CurString) + [pLocMenuState->CurState].year_index == 0) + return; + } + else + { + GetContextClipRect (&r); + r.extent.height = 136; + SetContextClipRect (&r); + DrawStamp (&s); + r.extent.height = SIS_SCREEN_HEIGHT; + SetContextClipRect (&r); + } + } + + s.frame = SetAbsFrameIndex ( + misc_data, + (NUM_SCANDOT_TRANSITIONS << 1) + 3 + ); + if (redraw_state == 2 + || (redraw_state == 1 + && !(((SUMMARY_DESC *)pLocMenuState->CurString) + [pLocMenuState->CurState].Flags & AFTER_BOMB_INSTALLED))) + { + s.origin.x = 7; + s.origin.y = 17; + for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) + { + if (i == NUM_ELEMENT_CATEGORIES >> 1) + { + s.origin.x += 36; + s.origin.y = 17; + } + DrawStamp (&s); + s.frame = SetRelFrameIndex (s.frame, 5); + s.origin.y += 12; + } + } + s.origin.x = 24; + s.origin.y = 68; + s.frame = SetAbsFrameIndex (s.frame, 68); + DrawStamp (&s); + } + else + { + TEXT t; + UNICODE buf[10]; + COLOR cargo_color[] = + { + BUILD_COLOR (MAKE_RGB15 (2, 14, 19), 0x00), + BUILD_COLOR (MAKE_RGB15 (25, 0x00, 0x00), 0x00), + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x00), + BUILD_COLOR (MAKE_RGB15 (3, 5, 30), 0x00), + BUILD_COLOR (MAKE_RGB15 (0x00, 24, 0x00), 0x00), + BUILD_COLOR (MAKE_RGB15 (27, 27, 0x00), 0x00), + BUILD_COLOR (MAKE_RGB15 (30, 13, 0x00), 0x00), + BUILD_COLOR (MAKE_RGB15 (20, 0x00, 20), 0x00), + BUILD_COLOR (MAKE_RGB15 (15, 0x00, 25), 0x00), + }; + + r.extent.width = 20; + r.extent.height = SHIP_NAME_HEIGHT; + SetContextFont (StarConFont); + t.baseline.x = 33; + t.baseline.y = 20; + t.align = ALIGN_RIGHT; + t.pStr = buf; + for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) + { + if (i == NUM_ELEMENT_CATEGORIES >> 1) + { + t.baseline.x += 36; + t.baseline.y = 20; + } + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = t.baseline.x - r.extent.width + 1; + r.corner.y = t.baseline.y - r.extent.height + 1; + DrawFilledRectangle (&r); + SetContextForeGroundColor (cargo_color[i]); + wsprintf (buf, "%u", GLOBAL_SIS (ElementAmounts[i])); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 12; + } + t.baseline.x = 50; + t.baseline.y = 71; + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = t.baseline.x - r.extent.width + 1; + r.corner.y = t.baseline.y - r.extent.height + 1; + DrawFilledRectangle (&r); + SetContextForeGroundColor (cargo_color[i]); + wsprintf (buf, "%u", GLOBAL_SIS (TotalBioMass)); + t.CharCount = (COUNT)~0; + DrawText (&t); + } +} + +static void +ShowSummary (SUMMARY_DESC *pSD) +{ + RECT r; + STAMP s; + + if (pSD->year_index == 0) + { + s.origin.x = s.origin.y = 0; + s.frame = SetAbsFrameIndex (pLocMenuState->ModuleFrame, + GetFrameCount (pLocMenuState->ModuleFrame) - 4); + DrawStamp (&s); + r.corner.x = 1; + r.corner.y = 141; + r.extent.width = SIS_SCREEN_WIDTH - 1; + r.extent.height = 7; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + } + else + { + BYTE i; + RECT OldRect; + TEXT t; + QUEUE player_q; + CONTEXT OldContext; + SIS_STATE SaveSS; + UNICODE buf[80]; + + SaveSS = GlobData.SIS_state; + player_q = GLOBAL (built_ship_q); + + OldContext = SetContext (StatusContext); + GetContextClipRect (&OldRect); + + r.corner.x = SIS_ORG_X + ((SIS_SCREEN_WIDTH - STATUS_WIDTH) >> 1); + r.corner.y = SIS_ORG_Y; + r.extent.width = STATUS_WIDTH; + r.extent.height = STATUS_HEIGHT; + SetContextClipRect (&r); + + GlobData.SIS_state = pSD->SS; + InitQueue (&GLOBAL (built_ship_q), + MAX_BUILT_SHIPS, sizeof (SHIP_FRAGMENT)); + for (i = 0; i < pSD->NumShips; ++i) + CloneShipFragment (pSD->ShipList[i], &GLOBAL (built_ship_q), 0); + DateToString (buf, pSD->month_index, pSD->day_index, pSD->year_index), + ClearSISRect (DRAW_SIS_DISPLAY); + DrawStatusMessage (buf); + UninitQueue (&GLOBAL (built_ship_q)); + + SetContextClipRect (&OldRect); + SetContext (SpaceContext); + BatchGraphics (); + DrawCargo (0); + s.origin.y = 13; + r.extent.width = r.extent.height = 16; + SetContextForeGroundColor (BLACK_COLOR); + for (i = 0; i < 4; ++i) + { + BYTE j; + + s.origin.x = 140; + for (j = 0; j < 4; ++j) + { + if ((i << 2) + j >= pSD->NumDevices) + { + r.corner = s.origin; + DrawFilledRectangle (&r); + } + else + { + extern FRAME misc_data; + + s.frame = SetAbsFrameIndex ( + misc_data, 77 + pSD->DeviceList[(i << 2) + j] + ); + DrawStamp (&s); + } + s.origin.x += 18; + } + s.origin.y += 18; + } + UnbatchGraphics (); + + SetContextFont (StarConFont); + t.baseline.x = 173; + t.align = ALIGN_CENTER; + t.CharCount = (COUNT)~0; + t.pStr = buf; + if (pSD->Flags & AFTER_BOMB_INSTALLED) + { + s.origin.x = s.origin.y = 0; + s.frame = SetRelFrameIndex ( + pLocMenuState->ModuleFrame, MAX_SAVED_GAMES * 2 + ); + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + DrawStamp (&s); + } + else + { + SetContext (RadarContext); + GetContextClipRect (&OldRect); + r.corner.x = SIS_ORG_X + 10; + r.corner.y = SIS_ORG_Y + 84; + r.extent = OldRect.extent; + SetContextClipRect (&r); + ClearSemaphore (&GraphicsSem); + InitLander ((unsigned char)(pSD->Flags | OVERRIDE_LANDER_FLAGS)); + SetSemaphore (&GraphicsSem); + SetContextClipRect (&OldRect); + SetContext (SpaceContext); + + wsprintf (buf, "%lu", GLOBAL_SIS (ResUnits)); + t.baseline.y = 102; + r.extent.width = 30; + r.extent.height = SHIP_NAME_HEIGHT; + r.corner.x = t.baseline.x - (r.extent.width >> 1); + r.corner.y = t.baseline.y - SHIP_NAME_HEIGHT + 1; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x00, 0x10), 0x01)); + DrawText (&t); + t.CharCount = (COUNT)~0; + } + t.baseline.y = 126; + wsprintf (buf, "%u", MAKE_WORD (pSD->MCreditLo, pSD->MCreditHi)); + r.extent.width = 30; + r.extent.height = SHIP_NAME_HEIGHT; + r.corner.x = t.baseline.x - (r.extent.width >> 1); + r.corner.y = t.baseline.y - SHIP_NAME_HEIGHT + 1; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x00, 0x10), 0x01)); + DrawText (&t); + + r.corner.x = 1; + r.corner.y = 141; + r.extent.width = SIS_SCREEN_WIDTH - 1; + r.extent.height = 7; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + t.baseline.x = r.corner.x + (SIS_MESSAGE_WIDTH >> 1); + t.baseline.y = r.corner.y + (r.extent.height - 1); + t.align = ALIGN_CENTER; + t.pStr = buf; + r.corner.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + r.corner.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + switch (pSD->Activity) + { + case IN_LAST_BATTLE: + case IN_INTERPLANETARY: + case IN_PLANET_ORBIT: + case IN_STARBASE: + { + BYTE QuasiState; + STAR_DESCPTR SDPtr; + + QuasiState = GET_GAME_STATE (ARILOU_SPACE_SIDE); + SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); + SDPtr = FindStar (NULL_PTR, &r.corner, 1, 1); + SET_GAME_STATE (ARILOU_SPACE_SIDE, QuasiState); + if (SDPtr) + { + GetClusterName (SDPtr, buf); + r.corner = SDPtr->star_pt; + break; + } + } + default: + buf[0] = '\0'; + break; + case IN_HYPERSPACE: + wstrcpy (buf, GAME_STRING (NAVIGATION_STRING_BASE + 0)); + break; + case IN_QUASISPACE: + wstrcpy (buf, GAME_STRING (NAVIGATION_STRING_BASE + 1)); + break; + } + + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.x = SIS_SCREEN_WIDTH - 57 + 1 + (SIS_TITLE_WIDTH >> 1); + if (pSD->Activity == IN_STARBASE) + wstrcpy (buf, GAME_STRING (STARBASE_STRING_BASE)); + else if (pSD->Activity == IN_PLANET_ORBIT) + wstrcpy (buf, GLOBAL_SIS (PlanetName)); + else + wsprintf (buf, "%03u.%01u:%03u.%01u", + r.corner.x / 10, r.corner.x % 10, + r.corner.y / 10, r.corner.y % 10); + t.CharCount = (COUNT)~0; + DrawText (&t); + + SetContext (OldContext); + + GLOBAL (built_ship_q) = player_q; + GlobData.SIS_state = SaveSS; + } +} + +static void +LoadGameDescriptions (SUMMARY_DESC *pSD) +{ + COUNT i; + + for (i = 0; i < MAX_SAVED_GAMES; ++i, ++pSD) + { + extern BOOLEAN LoadGame (COUNT which_game, + SUMMARY_DESC *summary_desc); + + if (!LoadGame (i, pSD)) + pSD->year_index = 0; + } +} + +static BOOLEAN +DoPickGame (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE NewState; + STAMP s; + SUMMARY_DESC *pSD; + BOOLEAN first_time; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->ModuleFrame = 0; + + return (FALSE); + } + first_time = (BOOLEAN)(pMS->Initialized == 0); + + if (!pMS->Initialized) + { + pMS->delta_item = (SIZE)pMS->CurState; + pMS->CurState = NewState = 0; + + pMS->InputFunc = DoPickGame; + SleepTask ((DWORD)pMS->CurFrame); + pMS->CurFrame = 0; + PauseMusic (); + StopSound (); + FadeMusic (128, 0); + + { + extern FRAME PlayFrame; + + pMS->ModuleFrame = SetAbsFrameIndex (PlayFrame, 38); + } + + SetSemaphore (&GraphicsSem); + BatchGraphics (); +Restart: + SetContext (SpaceContext); + LoadGameDescriptions ((SUMMARY_DESC *)pMS->CurString); + DrawCargo (1); + pMS->Initialized = TRUE; + goto ChangeGameSelection; + } + else if (InputState & DEVICE_BUTTON2) + { + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + s.origin.x = s.origin.y = 0; + s.frame = SetRelFrameIndex (pMS->ModuleFrame, pMS->CurState); + DrawStamp (&s); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + +pMS->ModuleFrame = 0; + pMS->CurState = (BYTE)pMS->delta_item; +ResumeMusic (); +if (pSolarSysState) +{ +#define DRAW_REFRESH (1 << 5) +#define REPAIR_SCAN (1 << 6) + extern BYTE draw_sys_flags; + + if (pSolarSysState->MenuState.Initialized < 3) + draw_sys_flags |= DRAW_REFRESH; + else if (pSolarSysState->MenuState.Initialized == 4) + draw_sys_flags |= REPAIR_SCAN; +} + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + pSD = &((SUMMARY_DESC *)pMS->CurString)[pMS->CurState]; + if (pMS->delta_item == SAVE_GAME || pSD->year_index) + { +RetrySave: + SetSemaphore (&GraphicsSem); + if (pMS->delta_item == SAVE_GAME) + { + STAMP MsgStamp; + extern BOOLEAN SaveGame (COUNT + which_game, SUMMARY_DESC + *summary_desc); + + ConfirmSaveLoad (&MsgStamp); + if (SaveGame ((COUNT)pMS->CurState, pSD)) + { + DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); + GLOBAL (CurrentActivity) |= CHECK_LOAD; + } + else + { + SetFlashRect (NULL_PTR, (FRAME)0); + DrawStamp (&MsgStamp); + DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); + ClearSemaphore (&GraphicsSem); + + if (SaveProblem ()) + goto RetrySave; + + pMS->Initialized = FALSE; + NewState = pMS->CurState; + SetSemaphore (&GraphicsSem); + BatchGraphics (); + goto Restart; + } + ResumeMusic (); +if (pSolarSysState) +{ +#define DRAW_REFRESH (1 << 5) +#define REPAIR_SCAN (1 << 6) + extern BYTE draw_sys_flags; + + if (pSolarSysState->MenuState.Initialized < 3) + draw_sys_flags |= DRAW_REFRESH; + else if (pSolarSysState->MenuState.Initialized == 4) + draw_sys_flags |= REPAIR_SCAN; +} + } + else + { + extern BOOLEAN + LoadGame + (COUNT + which_game, + SUMMARY_DESC + *summary_desc); + + ConfirmSaveLoad (0); + if (LoadGame ((COUNT)pMS->CurState, NULL_PTR)) + GLOBAL (CurrentActivity) |= CHECK_LOAD; + } + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + +pMS->ModuleFrame = 0; + pMS->CurState = (BYTE)pMS->delta_item; + return (FALSE); + } + } + else + { + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0) + { + if (NewState-- == 0) + NewState = MAX_SAVED_GAMES - 1; + } + else if (GetInputXComponent (InputState) > 0) + { + if (++NewState == MAX_SAVED_GAMES) + NewState = 0; + } + + if (NewState != pMS->CurState) + { + SetSemaphore (&GraphicsSem); + BatchGraphics (); + if (((SUMMARY_DESC *)pMS->CurString)[NewState].year_index != 0) + { + if (!(((SUMMARY_DESC *)pMS->CurString)[NewState].Flags + & AFTER_BOMB_INSTALLED)) + { + if (((SUMMARY_DESC *)pMS->CurString)[pMS->CurState].year_index == 0) + DrawCargo (1); + else if (((SUMMARY_DESC *)pMS->CurString)[pMS->CurState].Flags + & AFTER_BOMB_INSTALLED) + DrawCargo (2); + } + else if (((SUMMARY_DESC *)pMS->CurString)[pMS->CurState].year_index == 0) + DrawCargo (3); + } + + SetFlashRect (NULL_PTR, (FRAME)0); + s.origin.x = s.origin.y = 0; + s.frame = SetRelFrameIndex (pMS->ModuleFrame, pMS->CurState); + DrawStamp (&s); +ChangeGameSelection: + pMS->CurState = NewState; + ShowSummary (&((SUMMARY_DESC *)pMS->CurString)[pMS->CurState]); + s.origin.x = s.origin.y = 0; + s.frame = SetRelFrameIndex (pMS->ModuleFrame, pMS->CurState + MAX_SAVED_GAMES); + DrawStamp (&s); + + if (LastActivity == CHECK_LOAD) + { + BYTE clut_buf[] = {FadeAllToColor}; + + UnbatchGraphics (); + + LastActivity = 0; + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); + } + else + { + if (first_time) + { + RECT r; + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + } + UnbatchGraphics (); + } + + { + RECT r; + + r.corner.x = 3 + (NewState * 21); + r.corner.y = 176; + r.extent.width = 18; + r.extent.height = 18; + SetFlashRect (&r, (FRAME)0); + } + ClearSemaphore (&GraphicsSem); + } + } + + return (TRUE); +} + +static BOOLEAN +PickGame (PMENU_STATE + pMS) +{ + BOOLEAN retval; + CONTEXT OldContext; + FRAME OldFrame; + DRAW_STATE OldDrawState; + SUMMARY_DESC desc_array[MAX_SAVED_GAMES]; + + if (pSolarSysState) + { + ++pSolarSysState->MenuState.Initialized; + TaskSwitch (); + } + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + OldFrame = SetContextBGFrame (NULL_PTR); + OldDrawState = SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + pMS->Initialized = FALSE; + pMS->InputFunc = DoPickGame; + pMS->CurString = (STRING)&desc_array[0]; + ClearSemaphore (&GraphicsSem); + + DoInput (pMS); + + SetSemaphore (&GraphicsSem); + pMS->Initialized = -1; + pMS->InputFunc = DoGameOptions; + + retval = TRUE; + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + { + if (pMS->CurState == SAVE_GAME) + GLOBAL (CurrentActivity) &= ~CHECK_LOAD; + + retval = FALSE; + } + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { +if (CommData.ConversationPhrases + || !(pSolarSysState && pSolarSysState->MenuState.Initialized < 3)) +{ + RECT r; + + BatchGraphics (); + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + UnbatchGraphics (); +} + + if (pSolarSysState) + { + --pSolarSysState->MenuState.Initialized; + if (CommData.ConversationPhrases == 0 && !PLRPlaying ((MUSIC_REF)~0)) + { + if (pSolarSysState->MenuState.Initialized < 3) + { + extern MUSIC_REF SpaceMusic; + + PlayMusic (SpaceMusic, TRUE, 1); + } + else + { + extern MUSIC_REF LanderMusic; + + PlayMusic (LanderMusic, TRUE, 1); + } + } + } + } + + SetContextDrawState (OldDrawState); + SetContextBGFrame (OldFrame); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + + return (retval); +} + +static BOOLEAN +DoGameOptions + (INPUT_STATE + InputState, + PMENU_STATE + pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (LastActivity == CHECK_LOAD) + InputState = DEVICE_BUTTON1; + + if (pMS->Initialized <= 0) + { + if (LastActivity == CHECK_LOAD) + pMS->CurState = LOAD_GAME; + DrawMenuStateStrings (PM_SAVE_GAME, pMS->CurState); + + pMS->Initialized = 1; + pMS->InputFunc = DoGameOptions; + } + else if ((InputState & DEVICE_BUTTON2) + || ((InputState & DEVICE_BUTTON1) + && pMS->CurState == SETTINGS + 1)) + { + pMS->CurState = SETTINGS + 1; + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + switch (pMS->CurState) + { + case SAVE_GAME: + case LOAD_GAME: + pMS->CurFrame = (FRAME)FadeMusic (0, ONE_SECOND >> 1); + return (PickGame (pMS)); + case SETTINGS: + pMS->Initialized = FALSE; + pMS->InputFunc = DoSettings; + pMS->CurState = SOUND_ON_SETTING; + break; + } + } + else + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == SAVE_GAME) + NewState = SETTINGS + 1; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == SETTINGS + 1) + NewState = SAVE_GAME; + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_SAVE_GAME, NewState); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +BOOLEAN +GameOptions (void) +{ + MENU_STATE MenuState; + + pLocMenuState = &MenuState; + + memset (pLocMenuState, 0, sizeof (MenuState)); + + MenuState.InputFunc = DoGameOptions; + MenuState.CurState = SAVE_GAME; + DoInput ((PVOID)&MenuState); + + pLocMenuState = 0; + + return ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) ? FALSE : TRUE); +} + diff --git a/sc2/src/sc2code/gendef.c b/sc2/src/sc2code/gendef.c new file mode 100644 index 000000000..1fb837918 --- /dev/null +++ b/sc2/src/sc2code/gendef.c @@ -0,0 +1,131 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +PLAN_GEN_FUNC +GenerateIP (BYTE Index) +{ + PLAN_GEN_FUNC GenFunc; + + switch (Index) + { + case SOL_DEFINED: + GenFunc = GenerateSOL; + break; + case SHOFIXTI_DEFINED: + GenFunc = GenerateShofixti; + break; + case START_COLONY_DEFINED: + GenFunc = GenerateColony; + break; + case SPATHI_DEFINED: + GenFunc = GenerateSpathi; + break; + case MELNORME0_DEFINED: + case MELNORME1_DEFINED: + case MELNORME2_DEFINED: + case MELNORME3_DEFINED: + case MELNORME4_DEFINED: + case MELNORME5_DEFINED: + case MELNORME6_DEFINED: + case MELNORME7_DEFINED: + case MELNORME8_DEFINED: + GenFunc = GenerateMelnorme; + break; + case TALKING_PET_DEFINED: + GenFunc = GenerateTalkingPet; + break; + case CHMMR_DEFINED: + GenFunc = GenerateChmmr; + break; + case SYREEN_DEFINED: + case MYCON_TRAP_DEFINED: + GenFunc = GenerateSyreen; + break; + case BURVIXESE_DEFINED: + GenFunc = GenerateBurvixes; + break; + case SLYLANDRO_DEFINED: + GenFunc = GenerateSlylandro; + break; + case DRUUGE_DEFINED: + GenFunc = GenerateDruuge; + break; + case BOMB_DEFINED: + case UTWIG_DEFINED: + GenFunc = GenerateUtwig; + break; + case AQUA_HELIX_DEFINED: + case THRADD_DEFINED: + GenFunc = GenerateThradd; + break; + case SUN_DEVICE_DEFINED: + case MYCON_DEFINED: + case EGG_CASE0_DEFINED: + case EGG_CASE1_DEFINED: + case EGG_CASE2_DEFINED: + GenFunc = GenerateMycon; + break; + case ANDROSYNTH_DEFINED: + case TAALO_PROTECTOR_DEFINED: + case ORZ_DEFINED: + GenFunc = GenerateOrz; + break; + case SHIP_VAULT_DEFINED: + GenFunc = GenerateShipVault; + break; + case URQUAN_WRECK_DEFINED: + GenFunc = GenerateUrquanWreck; + break; + case MAIDENS_DEFINED: + case VUX_BEAST_DEFINED: + case VUX_DEFINED: + GenFunc = GenerateVUX; + break; + case SAMATRA_DEFINED: + GenFunc = GenerateSamatra; + break; + case ZOQFOT_DEFINED: + case ZOQ_SCOUT_DEFINED: + GenFunc = GenerateZoqFotPik; + break; + case YEHAT_DEFINED: + GenFunc = GenerateYehat; + break; + case PKUNK_DEFINED: + GenFunc = GeneratePkunk; + break; + case SUPOX_DEFINED: + GenFunc = GenerateSupox; + break; + case RAINBOW_DEFINED: + GenFunc = GenerateRainbow; + break; + case ILWRATH_DEFINED: + GenFunc = GenerateIlwrath; + break; + default: + GenFunc = GenerateRandomIP; + break; + } + + return (GenFunc); +} + + diff --git a/sc2/src/sc2code/getchar.c b/sc2/src/sc2code/getchar.c new file mode 100644 index 000000000..247831fae --- /dev/null +++ b/sc2/src/sc2code/getchar.c @@ -0,0 +1,82 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "starcon.h" + +static UWORD cur_char = ' '; + +void +SetJoystickChar (UWORD which_char) +{ + if (!isalnum (cur_char = which_char)) + cur_char = ' '; +} + +UWORD +GetJoystickChar (INPUT_STATE InputState) +{ + int dy; + UWORD old_char; + + if (InputState & DEVICE_BUTTON1) + return ('\n'); + else if (InputState & DEVICE_BUTTON2) + return (0x1B); + else if (InputState & DEVICE_BUTTON3) + return (0x7F); + + old_char = cur_char; + dy = GetInputYComponent (InputState); + if (dy) + { + if (cur_char == ' ') + { + if (dy > 0) + cur_char = 'a'; + else /* if (dy < 0) */ + cur_char = '9'; + } + else if (isdigit (cur_char)) + { + cur_char += dy; + if (cur_char < '0') + cur_char = 'z'; + else if (cur_char > '9') + cur_char = ' '; + } + else if (!isalpha (cur_char += dy)) + { + cur_char -= dy; + if (cur_char == 'a' || cur_char == 'A') + cur_char = ' '; + else + cur_char = '0'; + } + } + + if ((InputState & (DEVICE_LEFTSHIFT | DEVICE_RIGHTSHIFT)) && isalpha (cur_char)) + { + if (islower (cur_char)) + cur_char = toupper (cur_char); + else + cur_char = tolower (cur_char); + } + + return (cur_char == old_char ? 0 : cur_char); +} diff --git a/sc2/src/sc2code/globdata.c b/sc2/src/sc2code/globdata.c new file mode 100644 index 000000000..85fe3df99 --- /dev/null +++ b/sc2/src/sc2code/globdata.c @@ -0,0 +1,326 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "coderes.h" + +//Added by Chris + +void InitGlobData (void); + +//End Added by Chris + +CONTEXT RadarContext; +FRAME PlayFrame; + +GLOBDATA GlobData; + +extern FRAME flagship_status, misc_data; + +void +CreateRadar (void) +{ + if (RadarContext == 0) + { + RECT r; + CONTEXT OldContext; + + RadarContext = CaptureContext (CreateContext ()); + OldContext = SetContext (RadarContext); + SetContextFGFrame (Screen); + r.corner.x = RADAR_X; + r.corner.y = RADAR_Y; + r.extent.width = RADAR_WIDTH; + r.extent.height = RADAR_HEIGHT; + SetContextClipRect (&r); + SetContext (OldContext); + } +} + +BOOLEAN +LoadSC2Data (void) +{ + if (flagship_status == 0) + { + MEM_HANDLE hOldIndex; + + hOldIndex = SetResourceIndex (hResIndex); + + if ((flagship_status = CaptureDrawable ( + LoadGraphic (FLAGSTAT_MASK_PMAP_ANIM) + )) == 0) + return (FALSE); + + if ((misc_data = CaptureDrawable ( + LoadGraphic (MISCDATA_MASK_PMAP_ANIM) + )) == 0) + return (FALSE); + + SetResourceIndex (hOldIndex); + } + + CreateRadar (); + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + GLOBAL (ShipStamp.origin.x) = + GLOBAL (ShipStamp.origin.y) = -1; + } + + return (TRUE); +} + +BOOLEAN +InitSIS (void) +{ + COUNT i; + + InitGlobData (); + + PlayFrame = CaptureDrawable (LoadGraphic (PLAYMENU_ANIM)); + + { + COUNT num_ships; + RES_TYPE rt; + RES_INSTANCE ri; + RES_PACKAGE rp; + + rt = GET_TYPE (ARILOU_SHIP_INDEX); + ri = GET_INSTANCE (ARILOU_SHIP_INDEX); + rp = GET_PACKAGE (ARILOU_SHIP_INDEX); + + num_ships = (GET_PACKAGE (BLACKURQ_SHIP_INDEX) - rp + 1) + + 2; /* Yehat Rebels and Ur-Quan probe */ + + InitQueue (&GLOBAL (avail_race_q), + num_ships, sizeof (EXTENDED_SHIP_FRAGMENT)); + for (i = 0; i < num_ships; ++i) + { + DWORD ship_ref; + HSTARSHIP hStarShip; + + if (i < num_ships - 2) + ship_ref = MAKE_RESOURCE (rp++, rt, ri++); + else if (i == num_ships - 2) + ship_ref = YEHAT_SHIP_INDEX; + else + ship_ref = PROBE_RES_INDEX; + hStarShip = Build (&GLOBAL (avail_race_q), ship_ref, 0, 0); + if (hStarShip) + { + SHIP_FRAGMENTPTR FragPtr; + EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr; + extern HSTARSHIP FindMasterShip (DWORD ship_ref); + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + if (i < num_ships - 1) + { + HSTARSHIP hMasterShip; + STARSHIPPTR MasterShipPtr; + extern QUEUE master_q; + + hMasterShip = FindMasterShip (ship_ref); + MasterShipPtr = LockStarShip (&master_q, hMasterShip); + FragPtr->ShipInfo = ((SHIP_FRAGMENTPTR)MasterShipPtr)->ShipInfo; + UnlockStarShip (&master_q, hMasterShip); + } + else + { + load_ship ((STARSHIPPTR)FragPtr, FALSE); + FragPtr->ShipInfo = FragPtr->RaceDescPtr->ship_info; + FragPtr->RaceDescPtr->ship_info.melee_icon = 0; + FragPtr->RaceDescPtr->ship_info.icons = 0; + FragPtr->RaceDescPtr->ship_info.race_strings = 0; + free_ship ((STARSHIPPTR)FragPtr, FALSE); + } + + FragPtr->ShipInfo.ship_flags = BAD_GUY; + ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr; + ExtFragPtr->ShipInfo.known_strength = 0; + ExtFragPtr->ShipInfo.known_loc = ExtFragPtr->ShipInfo.loc; + if (FragPtr->ShipInfo.var2 == (BYTE)~0) + ExtFragPtr->ShipInfo.actual_strength = (COUNT)~0; + else if (i == YEHAT_REBEL_SHIP) + ExtFragPtr->ShipInfo.actual_strength = 0; + else + ExtFragPtr->ShipInfo.actual_strength = + (COUNT)FragPtr->ShipInfo.var2 << 1; + ExtFragPtr->ShipInfo.growth_fract = 0; + ExtFragPtr->ShipInfo.growth_err_term = 255 >> 1; + ExtFragPtr->ShipInfo.energy_level = 0; + ExtFragPtr->ShipInfo.days_left = 0; + FragPtr->RaceDescPtr = (RACE_DESCPTR)&ExtFragPtr->ShipInfo; + + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + } + } + + InitSISContexts (); + LoadSC2Data (); + + InitPlanetInfo (); + InitGroupInfo (TRUE); + + GLOBAL (glob_flags) = NUM_READ_SPEEDS >> 1; + + GLOBAL (ElementWorth[COMMON]) = 1; + GLOBAL_SIS (ElementAmounts[COMMON]) = 0; + GLOBAL (ElementWorth[CORROSIVE]) = 2; + GLOBAL_SIS (ElementAmounts[CORROSIVE]) = 0; + GLOBAL (ElementWorth[BASE_METAL]) = 3; + GLOBAL_SIS (ElementAmounts[BASE_METAL]) = 0; + GLOBAL (ElementWorth[NOBLE]) = 4; + GLOBAL_SIS (ElementAmounts[NOBLE]) = 0; + GLOBAL (ElementWorth[RARE_EARTH]) = 5; + GLOBAL_SIS (ElementAmounts[RARE_EARTH]) = 0; + GLOBAL (ElementWorth[PRECIOUS]) = 6; + GLOBAL_SIS (ElementAmounts[PRECIOUS]) = 0; + GLOBAL (ElementWorth[RADIOACTIVE]) = 8; + GLOBAL_SIS (ElementAmounts[RADIOACTIVE]) = 0; + GLOBAL (ElementWorth[EXOTIC]) = 25; + GLOBAL_SIS (ElementAmounts[EXOTIC]) = 0; + + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + GLOBAL_SIS (DriveSlots[i]) = EMPTY_SLOT + 0; + GLOBAL_SIS (DriveSlots[5]) = + GLOBAL_SIS (DriveSlots[6]) = FUSION_THRUSTER; + for (i = 0; i < NUM_JET_SLOTS; ++i) + GLOBAL_SIS (JetSlots[i]) = EMPTY_SLOT + 1; + GLOBAL_SIS (JetSlots[0]) = + GLOBAL_SIS (JetSlots[6]) = TURNING_JETS; + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; + GLOBAL_SIS (ModuleSlots[15]) = GUN_WEAPON; + GLOBAL_SIS (ModuleSlots[2]) = CREW_POD; + GLOBAL_SIS (CrewEnlisted) = CREW_POD_CAPACITY; + GLOBAL_SIS (ModuleSlots[8]) = STORAGE_BAY; +#ifndef TESTING + GLOBAL_SIS (ModuleSlots[1]) = FUEL_TANK; + GLOBAL_SIS (FuelOnBoard) = 10 * FUEL_TANK_SCALE; +#else /* TESTING */ +for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + GLOBAL_SIS (DriveSlots[i]) = FUSION_THRUSTER; +for (i = 0; i < NUM_JET_SLOTS; ++i) + GLOBAL_SIS (JetSlots[i]) = TURNING_JETS; +for (i = 0; i < 2; ++i) +{ +GLOBAL_SIS (ModuleSlots[i]) = HIGHEFF_FUELSYS; +GLOBAL_SIS (FuelOnBoard) += HEFUEL_TANK_CAPACITY; +} +for (; i < 7; ++i) +{ +GLOBAL_SIS (ModuleSlots[i]) = CREW_POD; +GLOBAL_SIS (CrewEnlisted) += CREW_POD_CAPACITY; +} +GLOBAL_SIS (ModuleSlots[i++]) = STORAGE_BAY; +GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; +GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; +GLOBAL_SIS (ModuleSlots[i++]) = DYNAMO_UNIT; +GLOBAL_SIS (ModuleSlots[i++]) = TRACKING_SYSTEM; +GLOBAL_SIS (ModuleSlots[i++]) = TRACKING_SYSTEM; +GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; +GLOBAL_SIS (ModuleSlots[i++]) = CANNON_WEAPON; +GLOBAL_SIS (ModuleSlots[i++]) = CANNON_WEAPON; +#endif /* TESTING */ + + InitQueue (&GLOBAL (built_ship_q), + MAX_BUILT_SHIPS, sizeof (SHIP_FRAGMENT)); + InitQueue (&GLOBAL (npc_built_ship_q), + (MAX_BATTLE_GROUPS >> 1), sizeof (SHIP_FRAGMENT)); + InitQueue (&GLOBAL (encounter_q), 16, sizeof (ENCOUNTER)); + + GLOBAL (CurrentActivity) = IN_INTERPLANETARY | START_INTERPLANETARY; + + GLOBAL_SIS (ResUnits) = 0; + GLOBAL (CrewCost) = 3; + GLOBAL (FuelCost) = 20; + GLOBAL (ModuleCost[PLANET_LANDER]) = 500 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[FUSION_THRUSTER]) = 500 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[TURNING_JETS]) = 500 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[CREW_POD]) = 2000 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[STORAGE_BAY]) = 750 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[FUEL_TANK]) = 500 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[DYNAMO_UNIT]) = 2000 / MODULE_COST_SCALE; + GLOBAL (ModuleCost[GUN_WEAPON]) = 2000 / MODULE_COST_SCALE; + + GLOBAL_SIS (NumLanders) = 1; + + wstrcpy (GLOBAL_SIS (ShipName), GAME_STRING (NAMING_STRING_BASE + 2)); + wstrcpy (GLOBAL_SIS (CommanderName), GAME_STRING (NAMING_STRING_BASE + 3)); + + ActivateStarShip (HUMAN_SHIP, 0); + CloneShipFragment (HUMAN_SHIP, &GLOBAL (built_ship_q), 0); + + GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); + GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); + CurStarDescPtr = 0; + GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; + + return (TRUE); +} + +void +FreeSC2Data (void) +{ + DestroyContext (ReleaseContext (RadarContext)); + RadarContext = 0; + DestroyDrawable (ReleaseDrawable (misc_data)); + misc_data = 0; + DestroyDrawable (ReleaseDrawable (flagship_status)); + flagship_status = 0; +} + +void +UninitSIS (void) +{ + HSTARSHIP hStarShip; + + UninitQueue (&GLOBAL (encounter_q)); + UninitQueue (&GLOBAL (npc_built_ship_q)); + UninitQueue (&GLOBAL (built_ship_q)); + UninitGroupInfo (); + UninitPlanetInfo (); + +// FreeSC2Data (); + + hStarShip = GetTailLink (&GLOBAL (avail_race_q)); + if (hStarShip) + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&GLOBAL (avail_race_q), hStarShip); + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.melee_icon)); + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.icons)); + DestroyStringTable (ReleaseStringTable ( + StarShipPtr->RaceDescPtr->ship_info.race_strings)); + UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); + } + + UninitQueue (&GLOBAL (avail_race_q)); + + DestroyDrawable (ReleaseDrawable (PlayFrame)); + PlayFrame = 0; +} + diff --git a/sc2/src/sc2code/globdata.h b/sc2/src/sc2code/globdata.h new file mode 100644 index 000000000..450267cda --- /dev/null +++ b/sc2/src/sc2code/globdata.h @@ -0,0 +1,803 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _GLOBDATA_H +#define _GLOBDATA_H + +#include "clock.h" + +#define RANDOM_ANIM (1 << 0) +#define CIRCULAR_ANIM (1 << 1) +#define YOYO_ANIM (1 << 2) +#define ANIM_MASK (RANDOM_ANIM | CIRCULAR_ANIM | YOYO_ANIM) + +#define WAIT_TALKING (1 << 3) +#define PAUSE_TALKING (1 << 4) +#define TALK_INTRO (1 << 5) +#define TALK_DONE (1 << 6) + +#define ANIM_DISABLED (1 << 7) + +#define COLORXFORM_ANIM PAUSE_TALKING + +typedef struct +{ + COUNT StartIndex; + BYTE NumFrames; + BYTE AnimFlags; + COUNT BaseFrameRate, RandomFrameRate, + BaseRestartRate, RandomRestartRate; + DWORD BlockMask; +} ANIMATION_DESC; +typedef ANIMATION_DESC *PANIMATION_DESC; +#define ANIMATION_DESCPTR PANIMATION_DESC + +#define MAX_ANIMATIONS 20 + +typedef struct +{ + void (*init_encounter_func) (void); + COUNT (*uninit_encounter_func) (void); + + FRAME AlienFrame; + FONT AlienFont; + COLOR AlienTextFColor, AlienTextBColor; + COUNT AlienTextWidth; + COLORMAP AlienColorMap; + DWORD AlienSong; + + STRING ConversationPhrases; + + COUNT NumAnimations; + ANIMATION_DESC AlienAmbientArray[MAX_ANIMATIONS]; + + ANIMATION_DESC AlienTransitionDesc; + ANIMATION_DESC AlienTalkDesc; + + TEXT AlienTextTemplate; +} LOCDATA; +typedef LOCDATA *PLOCDATA; +#define LOCDATAPTR PLOCDATA + +enum +{ + PORTAL_SPAWNER_DEVICE = 0, + TALKING_PET_DEVICE, + UTWIG_BOMB_DEVICE, + SUN_EFFICIENCY_DEVICE, + ROSY_SPHERE_DEVICE, + AQUA_HELIX_DEVICE, + CLEAR_SPINDLE_DEVICE, + ULTRON_0_DEVICE, + ULTRON_1_DEVICE, + ULTRON_2_DEVICE, + ULTRON_3_DEVICE, + MAIDENS_DEVICE, + UMGAH_HYPERWAVE_DEVICE, + BURVIX_HYPERWAVE_DEVICE, + DATA_PLATE_1_DEVICE, + DATA_PLATE_2_DEVICE, + DATA_PLATE_3_DEVICE, + TAALO_PROTECTOR_DEVICE, + EGG_CASING0_DEVICE, + EGG_CASING1_DEVICE, + EGG_CASING2_DEVICE, + SYREEN_SHUTTLE_DEVICE, + VUX_BEAST_DEVICE, + DESTRUCT_CODE_DEVICE, + URQUAN_WARP_DEVICE, + ARTIFACT_2_DEVICE, + ARTIFACT_3_DEVICE, + LUNAR_BASE_DEVICE, + + NUM_DEVICES +}; + +#define YEARS_TO_KOHRAH_VICTORY 4 + +#define START_GAME_STATE enum { +#define ADD_GAME_STATE(SName,NumBits) SName, END_##SName = SName + NumBits - 1, +#define END_GAME_STATE NUM_GAME_STATE_BITS }; + +START_GAME_STATE + /* Shofixti states */ + ADD_GAME_STATE (SHOFIXTI_VISITS, 3) + ADD_GAME_STATE (SHOFIXTI_STACK1, 2) + ADD_GAME_STATE (SHOFIXTI_STACK2, 3) + ADD_GAME_STATE (SHOFIXTI_STACK3, 2) + ADD_GAME_STATE (SHOFIXTI_KIA, 1) + ADD_GAME_STATE (SHOFIXTI_BRO_KIA, 1) + ADD_GAME_STATE (SHOFIXTI_RECRUITED, 1) + + ADD_GAME_STATE (SHOFIXTI_MAIDENS, 1) /* Did you find the babes yet? */ + ADD_GAME_STATE (MAIDENS_ON_SHIP, 1) + ADD_GAME_STATE (BATTLE_SEGUE, 1) /* Does encounter require battle segue? */ + ADD_GAME_STATE (PLANETARY_LANDING, 1) + ADD_GAME_STATE (PLANETARY_CHANGE, 1) + + /* Spathi states */ + ADD_GAME_STATE (SPATHI_VISITS, 3) + ADD_GAME_STATE (SPATHI_HOME_VISITS, 3) + ADD_GAME_STATE (FOUND_PLUTO_SPATHI, 2) + ADD_GAME_STATE (SPATHI_SHIELDED_SELVES, 1) + ADD_GAME_STATE (SPATHI_CREATURES_EXAMINED, 1) + ADD_GAME_STATE (SPATHI_CREATURES_ELIMINATED, 1) + ADD_GAME_STATE (UMGAH_BROADCASTERS, 1) + ADD_GAME_STATE (SPATHI_MANNER, 2) + ADD_GAME_STATE (SPATHI_QUEST, 1) + ADD_GAME_STATE (LIED_ABOUT_CREATURES, 2) + ADD_GAME_STATE (SPATHI_PARTY, 1) + ADD_GAME_STATE (KNOW_SPATHI_PASSWORD, 1) + + ADD_GAME_STATE (ILWRATH_HOME_VISITS, 3) + ADD_GAME_STATE (ILWRATH_CHMMR_VISITS, 1) + + ADD_GAME_STATE (ARILOU_SPACE, 1) /* Opening or Closing */ + ADD_GAME_STATE (ARILOU_SPACE_SIDE, 2) /* In normal or Arilou hyperspace */ + ADD_GAME_STATE (ARILOU_SPACE_COUNTER, 4) + + ADD_GAME_STATE (LANDER_SHIELDS, 4) + + ADD_GAME_STATE (SHOFIXTI_GRPOFFS0, 8) + ADD_GAME_STATE (SHOFIXTI_GRPOFFS1, 8) + ADD_GAME_STATE (SHOFIXTI_GRPOFFS2, 8) + ADD_GAME_STATE (SHOFIXTI_GRPOFFS3, 8) + + ADD_GAME_STATE (ZOQFOT_GRPOFFS0, 8) + ADD_GAME_STATE (ZOQFOT_GRPOFFS1, 8) + ADD_GAME_STATE (ZOQFOT_GRPOFFS2, 8) + ADD_GAME_STATE (ZOQFOT_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME0_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME0_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME0_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME0_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME1_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME1_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME1_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME1_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME2_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME2_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME2_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME2_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME3_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME3_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME3_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME3_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME4_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME4_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME4_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME4_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME5_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME5_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME5_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME5_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME6_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME6_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME6_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME6_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME7_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME7_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME7_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME7_GRPOFFS3, 8) + + ADD_GAME_STATE (MELNORME8_GRPOFFS0, 8) + ADD_GAME_STATE (MELNORME8_GRPOFFS1, 8) + ADD_GAME_STATE (MELNORME8_GRPOFFS2, 8) + ADD_GAME_STATE (MELNORME8_GRPOFFS3, 8) + + ADD_GAME_STATE (MET_MELNORME, 1) + ADD_GAME_STATE (MELNORME_RESCUE_REFUSED, 1) + ADD_GAME_STATE (MELNORME_RESCUE_COUNT, 3) + ADD_GAME_STATE (TRADED_WITH_MELNORME, 1) + ADD_GAME_STATE (WHY_MELNORME_PURPLE, 1) + ADD_GAME_STATE (MELNORME_CREDIT0, 8) + ADD_GAME_STATE (MELNORME_CREDIT1, 8) + ADD_GAME_STATE (MELNORME_BUSINESS_COUNT, 2) + ADD_GAME_STATE (MELNORME_YACK_STACK0, 2) + ADD_GAME_STATE (MELNORME_YACK_STACK1, 2) + ADD_GAME_STATE (MELNORME_YACK_STACK2, 4) + ADD_GAME_STATE (MELNORME_YACK_STACK3, 3) + ADD_GAME_STATE (MELNORME_YACK_STACK4, 2) + ADD_GAME_STATE (WHY_MELNORME_BLUE, 1) + ADD_GAME_STATE (MELNORME_ANGER, 2) + ADD_GAME_STATE (MELNORME_MIFFED_COUNT, 2) + ADD_GAME_STATE (MELNORME_PISSED_COUNT, 2) + ADD_GAME_STATE (MELNORME_HATE_COUNT, 2) + + ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS0, 8) + ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS1, 8) + ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS2, 8) + ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS3, 8) + ADD_GAME_STATE (PROBE_MESSAGE_DELIVERED, 1) + ADD_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1) + + ADD_GAME_STATE (STARBASE_AVAILABLE, 1) + ADD_GAME_STATE (STARBASE_VISITED, 1) + ADD_GAME_STATE (RADIOACTIVES_PROVIDED, 1) + ADD_GAME_STATE (LANDERS_LOST, 1) + ADD_GAME_STATE (GIVEN_FUEL_BEFORE, 1) + + ADD_GAME_STATE (AWARE_OF_SAMATRA, 1) + ADD_GAME_STATE (YEHAT_CAVALRY_ARRIVED, 1) + ADD_GAME_STATE (URQUAN_MESSED_UP, 1) + + ADD_GAME_STATE (MOONBASE_DESTROYED, 1) + ADD_GAME_STATE (WILL_DESTROY_BASE, 1) + + ADD_GAME_STATE (ARTIFACT_2_ON_SHIP, 1) + ADD_GAME_STATE (ARTIFACT_3_ON_SHIP, 1) + + ADD_GAME_STATE (KOHR_AH_KILLED_ALL, 1) + + ADD_GAME_STATE (STARBASE_YACK_STACK1, 1) + + ADD_GAME_STATE (DISCUSSED_PORTAL_SPAWNER, 1) + ADD_GAME_STATE (DISCUSSED_TALKING_PET, 1) + ADD_GAME_STATE (DISCUSSED_UTWIG_BOMB, 1) + ADD_GAME_STATE (DISCUSSED_SUN_EFFICIENCY, 1) + ADD_GAME_STATE (DISCUSSED_ROSY_SPHERE, 1) + ADD_GAME_STATE (DISCUSSED_AQUA_HELIX, 1) + ADD_GAME_STATE (DISCUSSED_CLEAR_SPINDLE, 1) + ADD_GAME_STATE (DISCUSSED_ULTRON, 1) + ADD_GAME_STATE (DISCUSSED_MAIDENS, 1) + ADD_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE, 1) + ADD_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE, 1) + ADD_GAME_STATE (SYREEN_WANT_PROOF, 1) + ADD_GAME_STATE (PLAYER_HAVING_SEX, 1) + ADD_GAME_STATE (MET_ARILOU, 1) + ADD_GAME_STATE (DISCUSSED_TAALO_PROTECTOR, 1) + ADD_GAME_STATE (DISCUSSED_EGG_CASING0, 1) + ADD_GAME_STATE (DISCUSSED_EGG_CASING1, 1) + ADD_GAME_STATE (DISCUSSED_EGG_CASING2, 1) + ADD_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE, 1) + ADD_GAME_STATE (DISCUSSED_VUX_BEAST, 1) + ADD_GAME_STATE (DISCUSSED_DESTRUCT_CODE, 1) + ADD_GAME_STATE (DISCUSSED_URQUAN_WARP, 1) + ADD_GAME_STATE (DISCUSSED_ARTIFACT_2, 1) + ADD_GAME_STATE (DISCUSSED_ARTIFACT_3, 1) + + ADD_GAME_STATE (ATTACKED_DRUUGE, 1) + + ADD_GAME_STATE (NEW_ALLIANCE_NAME, 2) + + ADD_GAME_STATE (PORTAL_COUNTER, 4) + + ADD_GAME_STATE (BURVIXESE_BROADCASTERS, 1) + ADD_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 1) + + ADD_GAME_STATE (UTWIG_BOMB, 1) + ADD_GAME_STATE (UTWIG_BOMB_ON_SHIP, 1) + + ADD_GAME_STATE (AQUA_HELIX, 1) + ADD_GAME_STATE (AQUA_HELIX_ON_SHIP, 1) + + ADD_GAME_STATE (SUN_DEVICE, 1) + ADD_GAME_STATE (SUN_DEVICE_ON_SHIP, 1) + + ADD_GAME_STATE (TAALO_PROTECTOR, 1) + ADD_GAME_STATE (TAALO_PROTECTOR_ON_SHIP, 1) + + ADD_GAME_STATE (SHIP_VAULT_UNLOCKED, 1) + ADD_GAME_STATE (SYREEN_SHUTTLE, 1) + + ADD_GAME_STATE (PORTAL_KEY, 1) + ADD_GAME_STATE (PORTAL_KEY_ON_SHIP, 1) + + ADD_GAME_STATE (VUX_BEAST, 1) + ADD_GAME_STATE (VUX_BEAST_ON_SHIP, 1) + + ADD_GAME_STATE (TALKING_PET, 1) + ADD_GAME_STATE (TALKING_PET_ON_SHIP, 1) + + ADD_GAME_STATE (MOONBASE_ON_SHIP, 1) + + ADD_GAME_STATE (KOHR_AH_FRENZY, 1) + ADD_GAME_STATE (KOHR_AH_VISITS, 2) + ADD_GAME_STATE (KOHR_AH_BYES, 1) + + ADD_GAME_STATE (SLYLANDRO_HOME_VISITS, 3) + ADD_GAME_STATE (DESTRUCT_CODE_ON_SHIP, 1) + + ADD_GAME_STATE (ILWRATH_VISITS, 3) + ADD_GAME_STATE (ILWRATH_DECEIVED, 1) + ADD_GAME_STATE (FLAGSHIP_CLOAKED, 1) + + ADD_GAME_STATE (MYCON_VISITS, 3) + ADD_GAME_STATE (MYCON_HOME_VISITS, 3) + ADD_GAME_STATE (MYCON_AMBUSH, 1) + ADD_GAME_STATE (MYCON_FELL_FOR_AMBUSH, 1) + + ADD_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 8) + + ADD_GAME_STATE (ORZ_VISITS, 3) + ADD_GAME_STATE (TAALO_VISITS, 3) + ADD_GAME_STATE (ORZ_MANNER, 2) + + ADD_GAME_STATE (PROBE_EXHIBITED_BUG, 1) + ADD_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1) + + ADD_GAME_STATE (URQUAN_VISITS, 3) + ADD_GAME_STATE (PLAYER_HYPNOTIZED, 1) + + ADD_GAME_STATE (VUX_VISITS, 3) + ADD_GAME_STATE (VUX_HOME_VISITS, 3) + ADD_GAME_STATE (ZEX_VISITS, 3) + ADD_GAME_STATE (ZEX_IS_DEAD, 1) + ADD_GAME_STATE (KNOW_ZEX_WANTS_MONSTER, 1) + + ADD_GAME_STATE (UTWIG_VISITS, 3) + ADD_GAME_STATE (UTWIG_HOME_VISITS, 3) + ADD_GAME_STATE (BOMB_VISITS, 3) + ADD_GAME_STATE (ULTRON_CONDITION, 3) + ADD_GAME_STATE (UTWIG_HAVE_ULTRON, 1) + ADD_GAME_STATE (BOMB_UNPROTECTED, 1) + + ADD_GAME_STATE (TAALO_UNPROTECTED, 1) + + ADD_GAME_STATE (TALKING_PET_VISITS, 3) + ADD_GAME_STATE (TALKING_PET_HOME_VISITS, 3) + ADD_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 1) + ADD_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1) + + ADD_GAME_STATE (ARILOU_VISITS, 3) + ADD_GAME_STATE (ARILOU_HOME_VISITS, 3) + ADD_GAME_STATE (KNOW_ARILOU_WANT_WRECK, 1) + ADD_GAME_STATE (ARILOU_CHECKED_UMGAH, 2) + ADD_GAME_STATE (PORTAL_SPAWNER, 1) + ADD_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 1) + + ADD_GAME_STATE (UMGAH_VISITS, 3) + ADD_GAME_STATE (UMGAH_HOME_VISITS, 3) + ADD_GAME_STATE (MET_NORMAL_UMGAH, 1) + + ADD_GAME_STATE (SYREEN_HOME_VISITS, 3) + ADD_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1) + ADD_GAME_STATE (KNOW_SYREEN_VAULT, 1) + + ADD_GAME_STATE (EGG_CASE0_ON_SHIP, 1) + ADD_GAME_STATE (SUN_DEVICE_UNGUARDED, 1) + + ADD_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1) + + ADD_GAME_STATE (CHMMR_HOME_VISITS, 3) + ADD_GAME_STATE (CHMMR_EMERGING, 1) + ADD_GAME_STATE (CHMMR_UNLEASHED, 1) + ADD_GAME_STATE (CHMMR_BOMB_STATE, 2) + + ADD_GAME_STATE (DRUUGE_DISCLAIMER, 1) + + ADD_GAME_STATE (YEHAT_VISITS, 3) + ADD_GAME_STATE (YEHAT_REBEL_VISITS, 3) + ADD_GAME_STATE (YEHAT_HOME_VISITS, 3) + ADD_GAME_STATE (YEHAT_CIVIL_WAR, 1) + ADD_GAME_STATE (YEHAT_ABSORBED_PKUNK, 1) + ADD_GAME_STATE (YEHAT_SHIP_MONTH, 4) + ADD_GAME_STATE (YEHAT_SHIP_DAY, 5) + ADD_GAME_STATE (YEHAT_SHIP_YEAR, 5) + + ADD_GAME_STATE (CLEAR_SPINDLE, 1) + ADD_GAME_STATE (PKUNK_VISITS, 3) + ADD_GAME_STATE (PKUNK_HOME_VISITS, 3) + ADD_GAME_STATE (PKUNK_SHIP_MONTH, 4) + ADD_GAME_STATE (PKUNK_SHIP_DAY, 5) + ADD_GAME_STATE (PKUNK_SHIP_YEAR, 5) + ADD_GAME_STATE (PKUNK_MISSION, 3) + + ADD_GAME_STATE (SUPOX_VISITS, 3) + ADD_GAME_STATE (SUPOX_HOME_VISITS, 3) + + ADD_GAME_STATE (THRADD_VISITS, 3) + ADD_GAME_STATE (THRADD_HOME_VISITS, 3) + ADD_GAME_STATE (HELIX_VISITS, 3) + ADD_GAME_STATE (HELIX_UNPROTECTED, 1) + ADD_GAME_STATE (THRADD_CULTURE, 2) + ADD_GAME_STATE (THRADD_MISSION, 3) + + ADD_GAME_STATE (DRUUGE_VISITS, 3) + ADD_GAME_STATE (DRUUGE_HOME_VISITS, 3) + ADD_GAME_STATE (ROSY_SPHERE, 1) + ADD_GAME_STATE (SCANNED_MAIDENS, 1) + ADD_GAME_STATE (SCANNED_FRAGMENTS, 1) + ADD_GAME_STATE (SCANNED_CASTER, 1) + ADD_GAME_STATE (SCANNED_SPAWNER, 1) + ADD_GAME_STATE (SCANNED_ULTRON, 1) + + ADD_GAME_STATE (ZOQFOT_INFO, 2) + ADD_GAME_STATE (ZOQFOT_HOSTILE, 1) + ADD_GAME_STATE (ZOQFOT_HOME_VISITS, 3) + ADD_GAME_STATE (MET_ZOQFOT, 1) + ADD_GAME_STATE (ZOQFOT_DISTRESS, 2) + + ADD_GAME_STATE (EGG_CASE1_ON_SHIP, 1) + ADD_GAME_STATE (EGG_CASE2_ON_SHIP, 1) + ADD_GAME_STATE (MYCON_SUN_VISITS, 3) + ADD_GAME_STATE (ORZ_HOME_VISITS, 3) + + ADD_GAME_STATE (MELNORME_FUEL_PROCEDURE, 1) + ADD_GAME_STATE (MELNORME_TECH_PROCEDURE, 1) + ADD_GAME_STATE (MELNORME_INFO_PROCEDURE, 1) + + ADD_GAME_STATE (MELNORME_TECH_STACK, 4) + ADD_GAME_STATE (MELNORME_EVENTS_INFO_STACK, 5) + ADD_GAME_STATE (MELNORME_ALIEN_INFO_STACK, 5) + ADD_GAME_STATE (MELNORME_HISTORY_INFO_STACK, 5) + + ADD_GAME_STATE (RAINBOW_WORLD0, 8) + ADD_GAME_STATE (RAINBOW_WORLD1, 2) + ADD_GAME_STATE (MELNORME_RAINBOW_COUNT, 4) + + ADD_GAME_STATE (USED_BROADCASTER, 1) + ADD_GAME_STATE (BROADCASTER_RESPONSE, 1) + + ADD_GAME_STATE (IMPROVED_LANDER_SPEED, 1) + ADD_GAME_STATE (IMPROVED_LANDER_CARGO, 1) + ADD_GAME_STATE (IMPROVED_LANDER_SHOT, 1) + + ADD_GAME_STATE (MET_ORZ_BEFORE, 1) + ADD_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1) + ADD_GAME_STATE (PLAYER_HAD_SEX, 1) + ADD_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP, 1) + + ADD_GAME_STATE (LIGHT_MINERAL_LOAD, 3) + ADD_GAME_STATE (MEDIUM_MINERAL_LOAD, 3) + ADD_GAME_STATE (HEAVY_MINERAL_LOAD, 3) + + ADD_GAME_STATE (STARBASE_BULLETS0, 8) + ADD_GAME_STATE (STARBASE_BULLETS1, 8) + ADD_GAME_STATE (STARBASE_BULLETS2, 8) + ADD_GAME_STATE (STARBASE_BULLETS3, 8) + + ADD_GAME_STATE (STARBASE_MONTH, 4) + ADD_GAME_STATE (STARBASE_DAY, 5) + + ADD_GAME_STATE (CREW_SOLD_TO_DRUUGE0, 8) + ADD_GAME_STATE (CREW_PURCHASED0, 8) + ADD_GAME_STATE (CREW_PURCHASED1, 8) + + ADD_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 1) + + ADD_GAME_STATE (COLONY_GRPOFFS0, 8) + ADD_GAME_STATE (COLONY_GRPOFFS1, 8) + ADD_GAME_STATE (COLONY_GRPOFFS2, 8) + ADD_GAME_STATE (COLONY_GRPOFFS3, 8) + +#define THRADDASH_BODY_THRESHOLD 25 + ADD_GAME_STATE (THRADDASH_BODY_COUNT, 5) + + ADD_GAME_STATE (UTWIG_SUPOX_MISSION, 3) + ADD_GAME_STATE (SPATHI_INFO, 3) + + ADD_GAME_STATE (ILWRATH_INFO, 2) + ADD_GAME_STATE (ILWRATH_GODS_SPOKEN, 4) + ADD_GAME_STATE (ILWRATH_WORSHIP, 2) + ADD_GAME_STATE (ILWRATH_FIGHT_THRADDASH, 1) + + ADD_GAME_STATE (SAMATRA_GRPOFFS0, 8) + ADD_GAME_STATE (SAMATRA_GRPOFFS1, 8) + ADD_GAME_STATE (SAMATRA_GRPOFFS2, 8) + ADD_GAME_STATE (SAMATRA_GRPOFFS3, 8) + + ADD_GAME_STATE (READY_TO_CONFUSE_URQUAN, 1) + ADD_GAME_STATE (URQUAN_HYPNO_VISITS, 1) + ADD_GAME_STATE (MENTIONED_PET_COMPULSION, 1) + ADD_GAME_STATE (URQUAN_INFO, 2) + ADD_GAME_STATE (KNOW_URQUAN_STORY, 2) + + ADD_GAME_STATE (MYCON_INFO, 4) + ADD_GAME_STATE (MYCON_RAMBLE, 5) + ADD_GAME_STATE (KNOW_ABOUT_SHATTERED, 2) + ADD_GAME_STATE (MYCON_INSULTS, 3) + ADD_GAME_STATE (MYCON_KNOW_AMBUSH, 1) + + ADD_GAME_STATE (SYREEN_INFO, 2) + ADD_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1) + ADD_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON, 1) + + ADD_GAME_STATE (TALKING_PET_INFO, 3) + ADD_GAME_STATE (TALKING_PET_SUGGESTIONS, 3) + ADD_GAME_STATE (LEARNED_TALKING_PET, 1) + ADD_GAME_STATE (DNYARRI_LIED, 1) + ADD_GAME_STATE (SHIP_TO_COMPEL, 1) + + ADD_GAME_STATE (ORZ_GENERAL_INFO, 2) + ADD_GAME_STATE (ORZ_PERSONAL_INFO, 3) + ADD_GAME_STATE (ORZ_ANDRO_STATE, 2) + ADD_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1) + + ADD_GAME_STATE (PKUNK_MANNER, 2) + ADD_GAME_STATE (PKUNK_ON_THE_MOVE, 1) + ADD_GAME_STATE (PKUNK_FLEET, 2) + ADD_GAME_STATE (PKUNK_MIGRATE, 2) + ADD_GAME_STATE (PKUNK_RETURN, 1) + ADD_GAME_STATE (PKUNK_WORRY, 2) + ADD_GAME_STATE (PKUNK_INFO, 3) + ADD_GAME_STATE (PKUNK_WAR, 2) + ADD_GAME_STATE (PKUNK_FORTUNE, 3) + ADD_GAME_STATE (PKUNK_MIGRATE_VISITS, 3) + ADD_GAME_STATE (PKUNK_REASONS, 4) + ADD_GAME_STATE (PKUNK_SWITCH, 1) + ADD_GAME_STATE (PKUNK_SENSE_VICTOR, 1) + + ADD_GAME_STATE (KOHR_AH_REASONS, 2) + ADD_GAME_STATE (KOHR_AH_PLEAD, 2) + ADD_GAME_STATE (KOHR_AH_INFO, 2) + ADD_GAME_STATE (KNOW_KOHR_AH_STORY, 2) + ADD_GAME_STATE (KOHR_AH_SENSES_EVIL, 1) + ADD_GAME_STATE (URQUAN_SENSES_EVIL, 1) + + ADD_GAME_STATE (SLYLANDRO_PROBE_VISITS, 3) + ADD_GAME_STATE (SLYLANDRO_PROBE_THREAT, 2) + ADD_GAME_STATE (SLYLANDRO_PROBE_WRONG, 2) + ADD_GAME_STATE (SLYLANDRO_PROBE_ID, 2) + ADD_GAME_STATE (SLYLANDRO_PROBE_INFO, 2) + ADD_GAME_STATE (SLYLANDRO_PROBE_EXIT, 2) + + ADD_GAME_STATE (UMGAH_HOSTILE, 1) + ADD_GAME_STATE (UMGAH_EVIL_BLOBBIES, 1) + ADD_GAME_STATE (UMGAH_MENTIONED_TRICKS, 2) + + ADD_GAME_STATE (BOMB_CARRIER, 1) + ADD_GAME_STATE (THRADD_MANNER, 1) + ADD_GAME_STATE (THRADD_INTRO, 2) + ADD_GAME_STATE (THRADD_DEMEANOR, 3) + ADD_GAME_STATE (THRADD_INFO, 2) + ADD_GAME_STATE (THRADD_BODY_LEVEL, 2) + ADD_GAME_STATE (THRADD_MISSION_VISITS, 1) + ADD_GAME_STATE (THRADD_STACK_1, 3) + ADD_GAME_STATE (THRADD_HOSTILE_STACK_2, 1) + ADD_GAME_STATE (THRADD_HOSTILE_STACK_3, 1) + ADD_GAME_STATE (THRADD_HOSTILE_STACK_4, 1) + ADD_GAME_STATE (THRADD_HOSTILE_STACK_5, 1) + + ADD_GAME_STATE (CHMMR_STACK, 2) + + ADD_GAME_STATE (ARILOU_MANNER, 2) + ADD_GAME_STATE (NO_PORTAL_VISITS, 1) + ADD_GAME_STATE (ARILOU_STACK_1, 2) + ADD_GAME_STATE (ARILOU_STACK_2, 1) + ADD_GAME_STATE (ARILOU_STACK_3, 2) + ADD_GAME_STATE (ARILOU_STACK_4, 1) + ADD_GAME_STATE (ARILOU_STACK_5, 2) + ADD_GAME_STATE (ARILOU_INFO, 2) + ADD_GAME_STATE (ARILOU_HINTS, 2) + + ADD_GAME_STATE (DRUUGE_MANNER, 1) + ADD_GAME_STATE (DRUUGE_SPACE_INFO, 2) + ADD_GAME_STATE (DRUUGE_HOME_INFO, 2) + ADD_GAME_STATE (DRUUGE_SALVAGE, 1) + ADD_GAME_STATE (KNOW_DRUUGE_SLAVERS, 2) + ADD_GAME_STATE (FRAGMENTS_BOUGHT, 2) + + ADD_GAME_STATE (ZEX_STACK_1, 2) + ADD_GAME_STATE (ZEX_STACK_2, 2) + ADD_GAME_STATE (ZEX_STACK_3, 2) + + ADD_GAME_STATE (VUX_INFO, 2) + ADD_GAME_STATE (VUX_STACK_1, 4) + ADD_GAME_STATE (VUX_STACK_2, 2) + ADD_GAME_STATE (VUX_STACK_3, 2) + ADD_GAME_STATE (VUX_STACK_4, 2) + + ADD_GAME_STATE (SHOFIXTI_STACK4, 2) + + ADD_GAME_STATE (YEHAT_REBEL_INFO, 3) + ADD_GAME_STATE (YEHAT_ROYALIST_INFO, 1) + ADD_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1) + ADD_GAME_STATE (NO_YEHAT_ALLY_HOME, 1) + ADD_GAME_STATE (NO_YEHAT_HELP_HOME, 1) + ADD_GAME_STATE (NO_YEHAT_INFO, 1) + ADD_GAME_STATE (NO_YEHAT_ALLY_SPACE, 2) + ADD_GAME_STATE (NO_YEHAT_HELP_SPACE, 2) + + ADD_GAME_STATE (ZOQFOT_KNOW_MASK, 4) + + ADD_GAME_STATE (SUPOX_HOSTILE, 1) + ADD_GAME_STATE (SUPOX_INFO, 1) + ADD_GAME_STATE (SUPOX_WAR_NEWS, 2) + ADD_GAME_STATE (SUPOX_ULTRON_HELP, 1) + ADD_GAME_STATE (SUPOX_STACK1, 3) + ADD_GAME_STATE (SUPOX_STACK2, 2) + + ADD_GAME_STATE (UTWIG_HOSTILE, 1) + ADD_GAME_STATE (UTWIG_INFO, 1) + ADD_GAME_STATE (UTWIG_WAR_NEWS, 2) + ADD_GAME_STATE (UTWIG_STACK1, 3) + ADD_GAME_STATE (UTWIG_STACK2, 2) + ADD_GAME_STATE (BOMB_INFO, 1) + ADD_GAME_STATE (BOMB_STACK1, 2) + ADD_GAME_STATE (BOMB_STACK2, 2) + + ADD_GAME_STATE (SLYLANDRO_KNOW_BROKEN, 1) + ADD_GAME_STATE (PLAYER_KNOWS_PROBE, 1) + ADD_GAME_STATE (PLAYER_KNOWS_PROGRAM, 1) + ADD_GAME_STATE (PLAYER_KNOWS_EFFECTS, 1) + ADD_GAME_STATE (PLAYER_KNOWS_PRIORITY, 1) + ADD_GAME_STATE (SLYLANDRO_STACK1, 3) + ADD_GAME_STATE (SLYLANDRO_STACK2, 1) + ADD_GAME_STATE (SLYLANDRO_STACK3, 2) + ADD_GAME_STATE (SLYLANDRO_STACK4, 2) + ADD_GAME_STATE (SLYLANDRO_STACK5, 1) + ADD_GAME_STATE (SLYLANDRO_STACK6, 1) + ADD_GAME_STATE (SLYLANDRO_STACK7, 2) + ADD_GAME_STATE (SLYLANDRO_STACK8, 2) + ADD_GAME_STATE (SLYLANDRO_STACK9, 2) + ADD_GAME_STATE (SLYLANDRO_KNOW_EARTH, 1) + ADD_GAME_STATE (SLYLANDRO_KNOW_EXPLORE, 1) + ADD_GAME_STATE (SLYLANDRO_KNOW_GATHER, 1) + ADD_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 2) + ADD_GAME_STATE (RECALL_VISITS, 2) + + ADD_GAME_STATE (SLYLANDRO_MULTIPLIER, 3) + ADD_GAME_STATE (KNOW_SPATHI_QUEST, 1) + ADD_GAME_STATE (KNOW_SPATHI_EVIL, 1) + + ADD_GAME_STATE (BATTLE_PLANET, 8) + ADD_GAME_STATE (ESCAPE_COUNTER, 8) + + ADD_GAME_STATE (CREW_SOLD_TO_DRUUGE1, 8) + ADD_GAME_STATE (PKUNK_DONE_WAR, 1) + + ADD_GAME_STATE (SYREEN_STACK0, 2) + ADD_GAME_STATE (SYREEN_STACK1, 2) + ADD_GAME_STATE (SYREEN_STACK2, 2) + + ADD_GAME_STATE (REFUSED_ULTRON_AT_BOMB, 1) + ADD_GAME_STATE (NO_TRICK_AT_SUN, 1) + + ADD_GAME_STATE (SPATHI_STACK0, 2) + ADD_GAME_STATE (SPATHI_STACK1, 1) + ADD_GAME_STATE (SPATHI_STACK2, 1) + + ADD_GAME_STATE (ORZ_STACK0, 1) + ADD_GAME_STATE (ORZ_STACK1, 1) +END_GAME_STATE + +#define GET_GAME_STATE(SName) (BYTE)(((SName >> 3) == (END_##SName >> 3) \ + ? (GLOBAL (GameState[SName >> 3]) \ + >> (SName & 7)) \ + : ((GLOBAL (GameState[SName >> 3]) \ + >> (SName & 7)) \ + | (GLOBAL (GameState[END_##SName >> 3]) \ + << (END_##SName - SName - (END_##SName & 7))))) \ + & ((1 << (END_##SName - SName + 1)) - 1)) + +#define SET_GAME_STATE(SName,val) \ +{ \ + GLOBAL (GameState[SName >> 3]) = \ + (GLOBAL (GameState[SName >> 3]) \ + & (BYTE)~(((1 << (END_##SName - SName + 1)) - 1) \ + << (SName & 7))) \ + | (BYTE)((val) << (SName & 7)); \ + if ((SName >> 3) < (END_##SName >> 3)) \ + GLOBAL (GameState[END_##SName >> 3]) = \ + (GLOBAL (GameState[END_##SName >> 3]) \ + & (BYTE)~((1 << ((END_##SName & 7) + 1)) - 1)) \ + | (BYTE)((val) >> (END_##SName - SName - (END_##SName & 7))); \ +} + +#define READ_SPEED_MASK ((1 << 3) - 1) +#define NUM_READ_SPEEDS 5 +#define COMBAT_SPEED_SHIFT 6 +#define COMBAT_SPEED_MASK (((1 << 2) - 1) << COMBAT_SPEED_SHIFT) +#define NUM_COMBAT_SPEEDS 4 + +#define MUSIC_DISABLED (1 << 3) +#define SOUND_DISABLED (1 << 4) +#define CYBORG_ENABLED (1 << 5) + +enum +{ + SUPER_MELEE = 0, + IN_LAST_BATTLE, + IN_ENCOUNTER, + IN_HYPERSPACE, + IN_INTERPLANETARY, + WON_LAST_BATTLE, + + IN_QUASISPACE, + IN_PLANET_ORBIT, + IN_STARBASE, + + CHECK_PAUSE = MAKE_WORD (0, (1 << 0)), + IN_BATTLE = MAKE_WORD (0, (1 << 1)), + START_ENCOUNTER = MAKE_WORD (0, (1 << 2)), + START_INTERPLANETARY = MAKE_WORD (0, (1 << 3)), + CHECK_LOAD = MAKE_WORD (0, (1 << 4)), + CHECK_RESTART = MAKE_WORD (0, (1 << 5)), + CHECK_ABORT = MAKE_WORD (0, (1 << 6)) +}; +typedef UWORD ACTIVITY; + +typedef struct +{ + BYTE cur_state, glob_flags; + + BYTE CrewCost, FuelCost; + BYTE ModuleCost[NUM_MODULES]; + BYTE ElementWorth[NUM_ELEMENT_CATEGORIES]; + + PPRIMITIVE DisplayArray; + ACTIVITY CurrentActivity; + + CLOCK_STATE GameClock; + + POINT autopilot; + POINT ip_location; + STAMP ShipStamp; + VELOCITY_DESC velocity; + + DWORD BattleGroupRef; + QUEUE avail_race_q, npc_built_ship_q; + QUEUE encounter_q, built_ship_q; + + BYTE GameState[(NUM_GAME_STATE_BITS + 7) >> 3]; +} GAME_STATE; + +typedef struct +{ + SIS_STATE SIS_state; + GAME_STATE Game_state; +} GLOBDATA; +typedef GLOBDATA *PGLOBDATA; + +extern GLOBDATA GlobData; +#define GLOBAL(f) GlobData.Game_state.f +#define GLOBAL_SIS(f) GlobData.SIS_state.f + +#define GLOBDATAPTR PGLOBDATA + +extern void DiscardStarMap (PVOID CodeRef); +extern void RetrieveStarMap (void); + +#define STAR_STRING_BASE 0 +#define DEVICE_STRING_BASE 133 +#define CARGO_STRING_BASE 162 +#define ELEMENTS_STRING_BASE 172 +#define SCAN_STRING_BASE 305 +#define STAR_NUMBER_BASE 361 +#define PLANET_NUMBER_BASE 375 +#define MONTHS_STRING_BASE 407 +#define FEEDBACK_STRING_BASE 419 +#define STARBASE_STRING_BASE 420 +#define ENCOUNTER_STRING_BASE 425 +#define NAVIGATION_STRING_BASE 433 +#define NAMING_STRING_BASE 439 +#define MELEE_STRING_BASE 443 +#define SAVEGAME_STRING_BASE 452 +#define OPTION_STRING_BASE 455 + +#define GAME_STRING(i) ((UNICODE *)GetStringAddress (SetAbsStringTableIndex (GameStrings, (i)))) + +#define wsprintf sprintf +#define wstrlen strlen +#define wstrcpy strcpy +#define wstrcat strcat +#define wstrupr strupr +#define wstrncpy strncpy +#define wstricmp stricmp + +#endif /* _GLOBDATA_H */ + diff --git a/sc2/src/sc2code/gravity.c b/sc2/src/sc2code/gravity.c new file mode 100644 index 000000000..9d976b5c4 --- /dev/null +++ b/sc2/src/sc2code/gravity.c @@ -0,0 +1,194 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +BOOLEAN +CalculateGravity (PELEMENT ElementPtr) +{ + BOOLEAN retval, HasGravity; + HELEMENT hTestElement, hSuccElement; + + retval = FALSE; + HasGravity = (BOOLEAN)(CollidingElement (ElementPtr) + && GRAVITY_MASS (ElementPtr->mass_points + 1)); + for (hTestElement = GetHeadElement (); + hTestElement != 0; hTestElement = hSuccElement) + { + BOOLEAN TestHasGravity; + ELEMENTPTR TestElementPtr; + + LockElement (hTestElement, &TestElementPtr); + if (TestElementPtr != ElementPtr + && CollidingElement (TestElementPtr) + && (TestHasGravity = + GRAVITY_MASS (TestElementPtr->mass_points + 1)) != HasGravity) + { + COUNT abs_dx, abs_dy; + SIZE dx, dy; + + if (!(ElementPtr->state_flags & PRE_PROCESS)) + { + dx = ElementPtr->current.location.x + - TestElementPtr->current.location.x; + dy = ElementPtr->current.location.y + - TestElementPtr->current.location.y; + } + else + { + dx = ElementPtr->next.location.x + - TestElementPtr->next.location.x; + dy = ElementPtr->next.location.y + - TestElementPtr->next.location.y; + } +#if 0 //def DEBUG +if (TestElementPtr->state_flags & PLAYER_SHIP) +{ +printf ("CalculateGravity:\n"); +printf ("\tdx = %d, dy = %d\n", dx, dy); +} +#endif /* DEBUG */ + dx = WRAP_DELTA_X (dx); + dy = WRAP_DELTA_Y (dy); +#if 0 //def DEBUG +if (TestElementPtr->state_flags & PLAYER_SHIP) +printf ("\twrap_dx = %d, wrap_dy = %d\n", dx, dy); +#endif /* DEBUG */ + abs_dx = dx >= 0 ? dx : -dx; + abs_dy = dy >= 0 ? dy : -dy; + abs_dx = WORLD_TO_DISPLAY (abs_dx); + abs_dy = WORLD_TO_DISPLAY (abs_dy); +#if 0 //def DEBUG +if (TestElementPtr->state_flags & PLAYER_SHIP) +printf ("\tdisplay_dx = %d, display_dy = %d\n", abs_dx, abs_dy); +#endif /* DEBUG */ + if (abs_dx <= GRAVITY_THRESHOLD + && abs_dy <= GRAVITY_THRESHOLD) + { + DWORD dist_squared; + + dist_squared = (DWORD)(abs_dx * abs_dx) + + (DWORD)(abs_dy * abs_dy); + if (dist_squared <= (DWORD)(GRAVITY_THRESHOLD + * GRAVITY_THRESHOLD)) + { +#ifdef NEVER + COUNT magnitude; + +#define DIFUSE_GRAVITY 175 + dist_squared += (DWORD)abs_dx * (DIFUSE_GRAVITY << 1) + + (DWORD)abs_dy * (DIFUSE_GRAVITY << 1) + + ((DWORD)(DIFUSE_GRAVITY * DIFUSE_GRAVITY) << 1); + if ((magnitude = (COUNT)((DWORD)(GRAVITY_THRESHOLD + * GRAVITY_THRESHOLD) / dist_squared)) == 0) + magnitude = 1; + +#define MAX_MAGNITUDE 6 + else if (magnitude > MAX_MAGNITUDE) + magnitude = MAX_MAGNITUDE; +printf ("magnitude = %u ", magnitude); +#endif /* NEVER */ + +#if 0 //def DEBUG +if (TestElementPtr->state_flags & PLAYER_SHIP) +printf ("dist_squared = %lu\n", dist_squared); +#endif /* DEBUG */ + if (TestHasGravity) + { + retval = TRUE; + UnlockElement (hTestElement); + break; + } + else + { + COUNT angle; + + angle = ARCTAN (dx, dy); + DeltaVelocityComponents (&TestElementPtr->velocity, + COSINE (angle, WORLD_TO_VELOCITY (1)), + SINE (angle, WORLD_TO_VELOCITY (1))); + if (TestElementPtr->state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (TestElementPtr, &StarShipPtr); + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + StarShipPtr->cur_status_flags |= SHIP_IN_GRAVITY_WELL; + } + } + } + } + } + + hSuccElement = GetSuccElement (TestElementPtr); + UnlockElement (hTestElement); + } + + return (retval); +} + +BOOLEAN +TimeSpaceMatterConflict (ELEMENTPTR ElementPtr) +{ + HELEMENT hTestElement, hSuccElement; + INTERSECT_CONTROL ElementControl; + + ElementControl.IntersectStamp.origin.x = + WORLD_TO_DISPLAY (ElementPtr->current.location.x); + ElementControl.IntersectStamp.origin.y = + WORLD_TO_DISPLAY (ElementPtr->current.location.y); + ElementControl.IntersectStamp.frame = + SetEquFrameIndex (ElementPtr->current.image.farray[0], + ElementPtr->current.image.frame); + ElementControl.EndPoint = ElementControl.IntersectStamp.origin; + for (hTestElement = GetHeadElement (); + hTestElement != 0; hTestElement = hSuccElement) + { + ELEMENTPTR TestElementPtr; + + LockElement (hTestElement, &TestElementPtr); + hSuccElement = GetSuccElement (TestElementPtr); + if (TestElementPtr != ElementPtr + && (CollidingElement (TestElementPtr) + /* ship in transition */ + || (TestElementPtr->state_flags & PLAYER_SHIP))) + { + INTERSECT_CONTROL TestElementControl; + + TestElementControl.IntersectStamp.origin.x = + WORLD_TO_DISPLAY (TestElementPtr->current.location.x); + TestElementControl.IntersectStamp.origin.y = + WORLD_TO_DISPLAY (TestElementPtr->current.location.y); + TestElementControl.IntersectStamp.frame = + SetEquFrameIndex (TestElementPtr->current.image.farray[0], + TestElementPtr->current.image.frame); + TestElementControl.EndPoint = TestElementControl.IntersectStamp.origin; + if (DrawablesIntersect (&ElementControl, + &TestElementControl, MAX_TIME_VALUE)) + { + UnlockElement (hTestElement); + + break; + } + } + UnlockElement (hTestElement); + } + + return (hTestElement != 0 ? TRUE : FALSE); +} + diff --git a/sc2/src/sc2code/gravwell.c b/sc2/src/sc2code/gravwell.c new file mode 100644 index 000000000..9b4a6d2bd --- /dev/null +++ b/sc2/src/sc2code/gravwell.c @@ -0,0 +1,80 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +FRAME planet[NUM_VIEWS]; + +void +load_gravity_well (BYTE selector) +{ + COUNT i; + RES_TYPE rt; + RES_INSTANCE ri; + RES_PACKAGE rp; + MEM_HANDLE hLastIndex; + + hLastIndex = SetResourceIndex (hResIndex); + + if (selector == NUMBER_OF_PLANET_TYPES) + { + planet[0] = CaptureDrawable ( + LoadGraphic (SAMATRA_BIG_MASK_PMAP_ANIM) + ); + planet[1] = planet[2] = 0; + } + else + { + if (selector & PLANET_SHIELDED) + { + rt = GET_TYPE (SHIELDED_BIG_MASK_PMAP_ANIM); + ri = GET_INSTANCE (SHIELDED_BIG_MASK_PMAP_ANIM); + rp = GET_PACKAGE (SHIELDED_BIG_MASK_PMAP_ANIM); + } + else + { + rt = GET_TYPE (PLANET00_BIG_MASK_PMAP_ANIM); + ri = GET_INSTANCE (PLANET00_BIG_MASK_PMAP_ANIM) + + (selector * NUM_VIEWS); + rp = GET_PACKAGE (PLANET00_BIG_MASK_PMAP_ANIM) + + selector; + } + + for (i = 0; i < NUM_VIEWS; ++i, ++ri) + { + planet[i] = CaptureDrawable ( + LoadGraphic (MAKE_RESOURCE (rp, rt, ri)) + ); + } + } + + SetResourceIndex (hLastIndex); +} + +void +free_gravity_well (void) +{ + COUNT i; + + for (i = 0; i < NUM_VIEWS; ++i) + { + DestroyDrawable (ReleaseDrawable (planet[i])); + planet[i] = 0; + } +} + diff --git a/sc2/src/sc2code/grpinfo.c b/sc2/src/sc2code/grpinfo.c new file mode 100644 index 000000000..5acc7df57 --- /dev/null +++ b/sc2/src/sc2code/grpinfo.c @@ -0,0 +1,674 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +//#define DEBUG + +typedef struct +{ + BYTE NumGroups, day_index, month_index; + COUNT star_index, year_index; + DWORD GroupOffset[MAX_BATTLE_GROUPS + 1]; +} GROUP_HEADER; + +void +InitGroupInfo (BOOLEAN FirstTime) +{ + PVOID fp; + + fp = OpenResFile (RANDGRPINFO_FILE, "wb"); + if (fp) + { + GROUP_HEADER GH; + + GH.NumGroups = 0; + GH.star_index = (COUNT)~0; + GH.GroupOffset[0] = 0; + WriteResFile (&GH, sizeof (GH), 1, fp); + + CloseResFile (fp); + } + + if (FirstTime && (fp = OpenResFile (DEFGRPINFO_FILE, "wb"))) + { + PutResFileChar (0, fp); + + CloseResFile (fp); + } +} + +void +UninitGroupInfo (void) +{ + unlink (DEFGRPINFO_FILE); + unlink (RANDGRPINFO_FILE); +} + +void +BuildGroups (void) +{ + BYTE Index, BestIndex; + COUNT BestPercent; + POINT universe; + HSTARSHIP hTemplate, hNextShip; + BYTE HomeWorld[] = + { + 0, /* ARILOU_SHIP */ + 0, /* CHMMR_SHIP */ + 0, /* HUMAN_SHIP */ + ORZ_DEFINED, /* ORZ_SHIP */ + PKUNK_DEFINED, /* PKUNK_SHIP */ + 0, /* SHOFIXTI_SHIP */ + SPATHI_DEFINED, /* SPATHI_SHIP */ + SUPOX_DEFINED, /* SUPOX_SHIP */ + THRADD_DEFINED, /* THRADDASH_SHIP */ + UTWIG_DEFINED, /* UTWIG_SHIP */ + VUX_DEFINED, /* VUX_SHIP */ + YEHAT_DEFINED, /* YEHAT_SHIP */ + 0, /* MELNORME_SHIP */ + DRUUGE_DEFINED, /* DRUUGE_SHIP */ + ILWRATH_DEFINED,/* ILWRATH_SHIP */ + MYCON_DEFINED, /* MYCON_SHIP */ + 0, /* SLYLANDRO_SHIP */ + UMGAH_DEFINED, /* UMGAH_SHIP */ + 0, /* URQUAN_SHIP */ + ZOQFOT_DEFINED, /* ZOQFOTPIK_SHIP */ + + 0, /* SYREEN_SHIP */ + 0, /* BLACK_URQUAN_SHIP */ + 0, /* YEHAT_REBEL_SHIP */ + }; + BYTE EncounterPercent[] = + { + RACE_INTERPLANETARY_PERCENT + }; + + EncounterPercent[SLYLANDRO_SHIP] *= GET_GAME_STATE (SLYLANDRO_MULTIPLIER); + Index = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (Index > 1 && Index < 5) + HomeWorld[UTWIG_SHIP] = HomeWorld[SUPOX_SHIP] = 0; + + BestPercent = 0; + universe = CurStarDescPtr->star_pt; + for (hTemplate = GetHeadLink (&GLOBAL (avail_race_q)), Index = 0; + hTemplate; hTemplate = hNextShip, ++Index) + { + COUNT i, encounter_radius; + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hTemplate + ); + hNextShip = _GetSuccLink (TemplatePtr); + + if ((encounter_radius = TemplatePtr->ShipInfo.actual_strength) + && (i = EncounterPercent[Index])) + { + SIZE dx, dy; + DWORD d_squared; + + if ((i = HomeWorld[Index]) && CurStarDescPtr->Index == (BYTE)i) + { + BestIndex = Index; + BestPercent = 70; + if (i == SPATHI_DEFINED || i == SUPOX_DEFINED) + BestPercent = 2; + hNextShip = 0; + + goto FoundHome; + } + + if (encounter_radius == (COUNT)~0) + encounter_radius = (MAX_X_UNIVERSE + 1) << 1; + else + encounter_radius = + (encounter_radius * SPHERE_RADIUS_INCREMENT) >> 1; + if ((dx = universe.x - TemplatePtr->ShipInfo.loc.x) < 0) + dx = -dx; + if ((dy = universe.y - TemplatePtr->ShipInfo.loc.y) < 0) + dy = -dy; + if ((COUNT)dx < encounter_radius + && (COUNT)dy < encounter_radius + && (d_squared = (DWORD)dx * dx + (DWORD)dy * dy) < + (DWORD)encounter_radius * encounter_radius) + { + DWORD rand_val; + + if (TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) + { + i = 70 - (COUNT)((DWORD)square_root (d_squared) + * 60L / encounter_radius); + } + + rand_val = Random (); + if ((int)(LOWORD (rand_val) % 100) < (int)i + && (BestPercent == 0 + || (HIWORD (rand_val) % (i + BestPercent)) < i)) + { + if (TemplatePtr->ShipInfo.actual_strength == (COUNT)~0) + i = 4; + + BestPercent = i; + BestIndex = Index; + } + } + } + +FoundHome: + UnlockStarShip ( + &GLOBAL (avail_race_q), + hTemplate + ); + } + + if (BestPercent) + { + BYTE which_group, num_groups; + BYTE EncounterMakeup[] = + { + RACE_ENCOUNTER_MAKEUP + }; + + which_group = 0; + num_groups = ((COUNT)Random () % (BestPercent >> 1)) + 1; + if (num_groups > (MAX_BATTLE_GROUPS >> 1)) + num_groups = (MAX_BATTLE_GROUPS >> 1); + else if (num_groups < 5 + && (Index = HomeWorld[BestIndex]) + && CurStarDescPtr->Index == Index) + num_groups = 5; + do + { + for (Index = HINIBBLE (EncounterMakeup[BestIndex]); Index; --Index) + { + if (Index <= LONIBBLE (EncounterMakeup[BestIndex]) + || (COUNT)Random () % 100 < 50) + CloneShipFragment ( + BestIndex, &GLOBAL (npc_built_ship_q), 0 + ); + } + + PutGroupInfo (0L, ++which_group); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + } while (--num_groups); + } + + GetGroupInfo (0L, (BYTE)~0); +} + +static void +FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID + fp) +{ + BYTE RaceType, NumShips; + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + + if (which_group == 0) + { + if (pGH->GroupOffset[0] == 0) + pGH->GroupOffset[0] = LengthResFile (fp); + + { + QUEUE temp_q; + HSTARSHIP hNextShip; + + temp_q = GLOBAL (npc_built_ship_q); + SetHeadLink (&GLOBAL (npc_built_ship_q), 0); + SetTailLink (&GLOBAL (npc_built_ship_q), 0); + for (hStarShip = GetHeadLink (&temp_q); + hStarShip; hStarShip = hNextShip) + { + BYTE crew_level; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &temp_q, hStarShip + ); + hNextShip = _GetSuccLink (FragPtr); + crew_level = FragPtr->ShipInfo.crew_level; + which_group = GET_GROUP_ID (FragPtr); + UnlockStarShip ( + &temp_q, hStarShip + ); + + if (crew_level == 0) + { + if (GLOBAL (BattleGroupRef)) + PutGroupInfo (GLOBAL (BattleGroupRef), which_group); + else + FlushGroupInfo (pGH, 0L, which_group, fp); + pGH->GroupOffset[which_group] = 0; + RemoveQueue ( + &temp_q, hStarShip + ); + FreeStarShip ( + &temp_q, hStarShip + ); + } + } + GLOBAL (npc_built_ship_q) = temp_q; + + which_group = 0; + } + } + else if (which_group > pGH->NumGroups) + { + pGH->NumGroups = which_group; + pGH->GroupOffset[which_group] = LengthResFile (fp); + + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + RaceType = GET_RACE_ID (FragPtr); + SeekResFile (fp, pGH->GroupOffset[which_group], SEEK_SET); + WriteResFile ((PBYTE)&RaceType, sizeof (RaceType), 1, fp); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + SeekResFile (fp, offset, SEEK_SET); + WriteResFile (pGH, sizeof (*pGH), 1, fp); +#ifdef DEBUG +printf ("1)FlushGroupInfo(%lu): WG = %u(%lu), NG = %u, SI = %u\n", +offset, which_group, pGH->GroupOffset[which_group], pGH->NumGroups, pGH->star_index); +#endif /* DEBUG */ + + NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q)); + + if (which_group) + SeekResFile (fp, pGH->GroupOffset[which_group] + + sizeof (RaceType), SEEK_SET); + else + { + RaceType = (BYTE)cur_player; + SeekResFile (fp, pGH->GroupOffset[0], SEEK_SET); + WriteResFile (&RaceType, sizeof (RaceType), 1, fp); + } + WriteResFile (&NumShips, sizeof (NumShips), 1, fp); + + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + while (NumShips--) + { + HSTARSHIP hNextShip; + PBYTE Ptr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (FragPtr); + + RaceType = GET_RACE_ID (FragPtr); + WriteResFile ((PBYTE)&RaceType, sizeof (RaceType), 1, fp); + +#ifdef DEBUG +if (which_group == 0) +printf ("F) type %u, loc %u<%d, %d>, task 0x%02x:%u\n", +RaceType, +GET_GROUP_LOC (FragPtr), +FragPtr->ShipInfo.loc.x, +FragPtr->ShipInfo.loc.y, +GET_GROUP_MISSION (FragPtr), +GET_GROUP_DEST (FragPtr)); +#endif /* DEBUG */ + Ptr = (PBYTE)&FragPtr->RaceDescPtr; + WriteResFile ((PBYTE)Ptr, + ((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, + 1, fp); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hStarShip = hNextShip; + } +} + +BOOLEAN +GetGroupInfo (DWORD offset, BYTE which_group) +{ + PVOID fp; + + fp = OpenResFile ( + offset && which_group ? DEFGRPINFO_FILE : RANDGRPINFO_FILE, + "r+b" + ); + if (fp) + { + BYTE RaceType, NumShips; + GROUP_HEADER GH; + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + + SeekResFile (fp, offset, SEEK_SET); + ReadResFile (&GH, sizeof (GH), 1, fp); +#ifdef DEBUG +printf ("GetGroupInfo(%lu): %u(%lu) out of %u\n", offset, which_group, GH.GroupOffset[which_group], GH.NumGroups); +#endif /* DEBUG */ + if (which_group == (BYTE)~0) + { + COUNT month_index, day_index, year_index; + + ReinitQueue (&GLOBAL (npc_built_ship_q)); +#ifdef DEBUG +printf ("%u == %u\n", GH.star_index, (COUNT)(CurStarDescPtr - star_array)); +#endif /* DEBUG */ + day_index = GH.day_index; + month_index = GH.month_index; + year_index = GH.year_index; + if (offset == 0 + && (GH.star_index != (COUNT)(CurStarDescPtr - star_array) + || !ValidateEvent (ABSOLUTE_EVENT, + &month_index, &day_index, &year_index))) + { + CloseResFile (fp); + +#ifdef DEBUG +if (GH.star_index == (COUNT)(CurStarDescPtr - star_array)) +printf ("GetGroupInfo: battle groups out of date %u/%u/%u!\n", +month_index, day_index, year_index); +#endif /* DEBUG */ + fp = OpenResFile (RANDGRPINFO_FILE, "wb"); + GH.NumGroups = 0; + GH.star_index = (COUNT)~0; + GH.GroupOffset[0] = 0; + WriteResFile (&GH, sizeof (GH), 1, fp); + } + else + { + for (which_group = 1; which_group <= GH.NumGroups; ++which_group) + { + if (GH.GroupOffset[which_group] == 0) + continue; + + SeekResFile (fp, GH.GroupOffset[which_group], SEEK_SET); + ReadResFile (&RaceType, sizeof (RaceType), 1, fp); + ReadResFile (&NumShips, sizeof (NumShips), 1, fp); + + if (NumShips) + { + BYTE task, group_loc; + DWORD rand_val; + + hStarShip = CloneShipFragment (RaceType, + &GLOBAL (npc_built_ship_q), 0); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + OwnStarShip (FragPtr, BAD_GUY, 0); + SET_GROUP_ID (FragPtr, which_group); + + rand_val = Random (); + task = (BYTE)(LOBYTE (LOWORD (rand_val)) % ON_STATION); + if (task == FLEE) + task = ON_STATION; + SET_ORBIT_LOC (FragPtr, + NORMALIZE_FACING (LOBYTE (HIWORD (rand_val)))); + + group_loc = pSolarSysState->SunDesc[0].NumPlanets; + if (group_loc == 1 && task == EXPLORE) + task = IN_ORBIT; + else + group_loc = (BYTE)(( + HIBYTE (LOWORD (rand_val)) % group_loc + ) + 1); + SET_GROUP_DEST (FragPtr, group_loc); + rand_val = Random (); + FragPtr->ShipInfo.loc.x = + (LOWORD (rand_val) % 10000) - 5000; + FragPtr->ShipInfo.loc.y = + (HIWORD (rand_val) % 10000) - 5000; + if (task == EXPLORE) + FragPtr->ShipInfo.group_counter = + ((COUNT)Random () + % MAX_REVOLUTIONS) + << FACING_SHIFT; + else + { + FragPtr->ShipInfo.group_counter = 0; + if (task == ON_STATION) + { + COUNT angle; + POINT org; + + XFormIPLoc ( + &pSolarSysState->PlanetDesc[ + group_loc - 1 + ].image.origin, + &org, + FALSE + ); + angle = FACING_TO_ANGLE ( + GET_ORBIT_LOC (FragPtr) + 1 + ); + FragPtr->ShipInfo.loc.x = org.x + + COSINE (angle, STATION_RADIUS); + FragPtr->ShipInfo.loc.y = org.y + + SINE (angle, STATION_RADIUS); + group_loc = 0; + } + } + + SET_GROUP_MISSION (FragPtr, task); + SET_GROUP_LOC (FragPtr, group_loc); + +#ifdef DEBUG +printf ("battle group %u(0x%04x) strength %u, type %u, loc %u<%d, %d>, task %u\n", +which_group, +hStarShip, +NumShips, +RaceType, +group_loc, +FragPtr->ShipInfo.loc.x, +FragPtr->ShipInfo.loc.y, +task); +#endif /* DEBUG */ + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + } + + if (offset) + InitGroupInfo (FALSE); + /* Random battle group */ + else if (ValidateEvent (ABSOLUTE_EVENT, /* still fresh */ + &month_index, &day_index, &year_index)) + { + CloseResFile (fp); + return (TRUE); + } + } + } + else if (GH.GroupOffset[which_group]) + { + BYTE BaseGroup; + COUNT ShipsLeft; + + ShipsLeft = CountLinks (&GLOBAL (npc_built_ship_q)); + if (which_group == 0) + { + SeekResFile (fp, GH.GroupOffset[0], SEEK_SET); + ReadResFile (&BaseGroup, sizeof (BaseGroup), 1, fp); + + if (BaseGroup) + { + if (GLOBAL (BattleGroupRef)) + PutGroupInfo (GLOBAL (BattleGroupRef), BaseGroup); + else + FlushGroupInfo (&GH, offset, BaseGroup, fp); + } + } + else + { + cur_player = (SIZE)which_group; + if (offset) + PutGroupInfo (0L, 0); + else + FlushGroupInfo (&GH, 0L, 0, fp); + + BaseGroup = which_group; + } + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + SeekResFile (fp, GH.GroupOffset[which_group] + + sizeof (BaseGroup), SEEK_SET); + + ReadResFile (&NumShips, sizeof (NumShips), 1, fp); + while (NumShips--) + { + PBYTE Ptr; + + ReadResFile ((PBYTE)&RaceType, sizeof (RaceType), 1, fp); + + hStarShip = CloneShipFragment (RaceType, + &GLOBAL (npc_built_ship_q), 0); + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + Ptr = (PBYTE)&FragPtr->RaceDescPtr; + ReadResFile ((PBYTE)Ptr, + ((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, + 1, fp); + +#ifdef DEBUG +if (which_group == 0) +printf ("G) type %u, loc %u<%d, %d>, task 0x%02x:%u\n", +RaceType, +GET_GROUP_LOC (FragPtr), +FragPtr->ShipInfo.loc.x, +FragPtr->ShipInfo.loc.y, +GET_GROUP_MISSION (FragPtr), +GET_GROUP_DEST (FragPtr)); +#endif /* DEBUG */ + if (GET_GROUP_ID (FragPtr) != BaseGroup + || which_group + || ShipsLeft) + { +#ifdef DEBUG +printf ("\n"); +#endif /* DEBUG */ + if (RaceType == SHOFIXTI_SHIP + && which_group + && !GET_GAME_STATE (SHOFIXTI_RECRUITED)) + { + BYTE captains_name_index; + + if (!GET_GAME_STATE (SHOFIXTI_KIA)) + captains_name_index = + NAME_OFFSET + NUM_CAPTAINS_NAMES; + else + captains_name_index = + NAME_OFFSET + NUM_CAPTAINS_NAMES + 1; + OwnStarShip (FragPtr, BAD_GUY, captains_name_index); + } + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + else + { +#ifdef DEBUG +printf (" -- REMOVING\n"); +#endif /* DEBUG */ + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + RemoveQueue ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + FreeStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + } + } + + CloseResFile (fp); + } + + return (GetHeadLink (&GLOBAL (npc_built_ship_q)) != 0); +} + +DWORD +PutGroupInfo (DWORD offset, BYTE which_group) +{ + PVOID fp; + + fp = OpenResFile ( + offset && which_group ? DEFGRPINFO_FILE : RANDGRPINFO_FILE, + "r+b" + ); + if (fp) + { + GROUP_HEADER GH; + + if (offset == (DWORD) ~0L) + { + offset = LengthResFile (fp); + GH.NumGroups = 0; + GH.GroupOffset[0] = 0; + SeekResFile (fp, offset, SEEK_SET); + WriteResFile (&GH, sizeof (GH), 1, fp); + } + + if (which_group) + { + SeekResFile (fp, offset, SEEK_SET); + if (which_group == (BYTE)~0) + { + cur_player = 0; + which_group = 0; + } + } + ReadResFile (&GH, sizeof (GH), 1, fp); + +#ifdef NEVER + if (GetHeadLink (&GLOBAL (npc_built_ship_q)) + || GH.GroupOffset[0] == 0) +#endif /* NEVER */ + { + COUNT month_index, day_index, year_index; + + month_index = 0; + day_index = 7; + year_index = 0; + ValidateEvent (RELATIVE_EVENT, &month_index, &day_index, &year_index); + GH.day_index = (BYTE)day_index; + GH.month_index = (BYTE)month_index; + GH.year_index = year_index; + } + GH.star_index = CurStarDescPtr - star_array; +#ifdef DEBUG +printf ("PutGroupInfo(%lu): %u out of %u -- %u/%u/%u\n", +offset, which_group, GH.NumGroups, +GH.month_index, GH.day_index, GH.year_index); +#endif /* DEBUG */ + + FlushGroupInfo (&GH, offset, which_group, fp); + + CloseResFile (fp); + } + + return (offset); +} + diff --git a/sc2/src/sc2code/hyper.c b/sc2/src/sc2code/hyper.c new file mode 100644 index 000000000..58365ae56 --- /dev/null +++ b/sc2/src/sc2code/hyper.c @@ -0,0 +1,1587 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +//Added by Chris + +void WaitForNoInput (SIZE Duration); + +//End Added by Chris + +#define XOFFS ((RADAR_SCAN_WIDTH + (UNIT_SCREEN_WIDTH << 2)) >> 1) +#define YOFFS ((RADAR_SCAN_HEIGHT + (UNIT_SCREEN_HEIGHT << 2)) >> 1) + +static FRAME hyperstars[3]; +static COLORMAP hypercmaps[2]; +static BYTE fuel_ticks; +static COUNT hyper_dx, hyper_dy; + +void +MoveSIS (PSIZE pdx, PSIZE pdy) +{ + SIZE new_dx, new_dy; + + new_dx = *pdx; + if ((GLOBAL_SIS (log_x) -= new_dx) < 0) + { + new_dx += (SIZE)GLOBAL_SIS (log_x); + GLOBAL_SIS (log_x) = 0; + } + else if (GLOBAL_SIS (log_x) > MAX_X_LOGICAL) + { + new_dx += (SIZE)(GLOBAL_SIS (log_x) - MAX_X_LOGICAL); + GLOBAL_SIS (log_x) = MAX_X_LOGICAL; + } + + new_dy = *pdy; + if ((GLOBAL_SIS (log_y) -= new_dy) < 0) + { + new_dy += (SIZE)GLOBAL_SIS (log_y); + GLOBAL_SIS (log_y) = 0; + } + else if (GLOBAL_SIS (log_y) > MAX_Y_LOGICAL) + { + new_dy += (SIZE)(GLOBAL_SIS (log_y) - MAX_Y_LOGICAL); + GLOBAL_SIS (log_y) = MAX_Y_LOGICAL; + } + + if (new_dx != *pdx || new_dy != *pdy) + { + HELEMENT hElement, hNextElement; + + *pdx = new_dx; + *pdy = new_dy; + + for (hElement = GetTailElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + hNextElement = GetPredElement (ElementPtr); + else + { + ElementPtr->next.location.x = (LOG_SPACE_WIDTH >> 1) - new_dx; + ElementPtr->next.location.y = (LOG_SPACE_HEIGHT >> 1) - new_dy; + hNextElement = 0; + } + + UnlockElement (hElement); + } + } + + if (GLOBAL_SIS (FuelOnBoard) + && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + COUNT cur_fuel_ticks; + COUNT hyper_dist; + + if (new_dx < 0) + new_dx = -new_dx; + hyper_dx += new_dx; + if (new_dy < 0) + new_dy = -new_dy; + hyper_dy += new_dy; + + hyper_dist = square_root ( + (DWORD)hyper_dx * hyper_dx + + (DWORD)hyper_dy * hyper_dy + ); + cur_fuel_ticks = hyper_dist >> 4; + if (cur_fuel_ticks > (COUNT)fuel_ticks) + { +#ifndef TESTING + DeltaSISGauges (0, fuel_ticks - cur_fuel_ticks, 0); +#endif /* TESTING */ + if (cur_fuel_ticks > 0x00FF) + { + hyper_dx = hyper_dist & ((1 << 4) - 1); + hyper_dy = 0; + cur_fuel_ticks = 0; + } + + fuel_ticks = (BYTE)cur_fuel_ticks; + } + } +} + +void +check_hyperspace_encounter (void) +{ + BYTE Type; + POINT universe; + HSTARSHIP hStarShip, hNextShip; + COUNT EncounterPercent[] = + { + RACE_HYPERSPACE_PERCENT + }; + + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)), Type = 0; + hStarShip && (GLOBAL (CurrentActivity) & IN_BATTLE); + hStarShip = hNextShip, ++Type) + { + COUNT encounter_radius; + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + hNextShip = _GetSuccLink (TemplatePtr); + + encounter_radius = TemplatePtr->ShipInfo.actual_strength; + if (encounter_radius) + { + BYTE encounter_flags; + SIZE dx, dy; + COUNT percent; + HENCOUNTER hEncounter; + ENCOUNTERPTR EncounterPtr; + + encounter_flags = 0; + percent = EncounterPercent[Type]; + if (encounter_radius != (COUNT)~0) + encounter_radius = + (encounter_radius * SPHERE_RADIUS_INCREMENT) >> 1; + else + { + HENCOUNTER hNextEncounter; + + encounter_radius = (MAX_X_UNIVERSE + 1) << 1; + if (Type == SLYLANDRO_SHIP) + { + encounter_flags = ONE_SHOT_ENCOUNTER; + if (!GET_GAME_STATE (STARBASE_AVAILABLE)) + percent = 100; + else +#ifdef TESTING +percent = 0; +#else /* TESTING */ + percent *= GET_GAME_STATE (SLYLANDRO_MULTIPLIER); +#endif /* TESTING */ + } + else if (Type == MELNORME_SHIP + && (GLOBAL_SIS (FuelOnBoard) == 0 + || GET_GAME_STATE (USED_BROADCASTER)) + && GET_GAME_STATE (MELNORME_ANGER) < 3) + { + if (!GET_GAME_STATE (USED_BROADCASTER)) + percent = 30; + else + percent = 100; + encounter_flags = ONE_SHOT_ENCOUNTER; + } + + + for (hEncounter = GetHeadEncounter (); + hEncounter; hEncounter = hNextEncounter) + { + LockEncounter (hEncounter, &EncounterPtr); + hNextEncounter = GetSuccEncounter (EncounterPtr); + if (EncounterPtr->SD.Type == Type) + { + percent = 0; + hNextEncounter = 0; + } + UnlockEncounter (hEncounter); + } + + + if (percent == 100 && Type == MELNORME_SHIP) + { + SET_GAME_STATE (BROADCASTER_RESPONSE, 1); + } + } + + if ((dx = universe.x - TemplatePtr->ShipInfo.loc.x) < 0) + dx = -dx; + if ((dy = universe.y - TemplatePtr->ShipInfo.loc.y) < 0) + dy = -dy; + if ((COUNT)dx < encounter_radius + && (COUNT)dy < encounter_radius + && (DWORD)dx * dx + (DWORD)dy * dy < + (DWORD)encounter_radius * encounter_radius + && ((COUNT)Random () % 100) < percent) + { +#ifndef DEBUG + char buf[20]; + + GetStringContents (SetAbsStringTableIndex ( + TemplatePtr->ShipInfo.race_strings, 1 + ), (STRINGPTR)buf, FALSE); +// printf ("%s encounter\n", buf); +#endif /* DEBUG */ + hEncounter = AllocEncounter (); + if (hEncounter) + { + LockEncounter (hEncounter, &EncounterPtr); + memset (EncounterPtr, 0, sizeof (*EncounterPtr)); + EncounterPtr->origin = TemplatePtr->ShipInfo.loc; + EncounterPtr->radius = encounter_radius; + EncounterPtr->SD.Index = encounter_flags; + EncounterPtr->SD.Type = Type; + UnlockEncounter (hEncounter); + + PutEncounter (hEncounter); + } + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + } + + SET_GAME_STATE (USED_BROADCASTER, 0); +} + +void +FreeHyperData (void) +{ + DestroyDrawable (ReleaseDrawable (hyperstars[0])); + hyperstars[0] = 0; + DestroyDrawable (ReleaseDrawable (hyperstars[1])); + hyperstars[1] = 0; + DestroyDrawable (ReleaseDrawable (hyperstars[2])); + hyperstars[2] = 0; + + DestroyColorMap (ReleaseColorMap (hypercmaps[0])); + hypercmaps[0] = 0; + DestroyColorMap (ReleaseColorMap (hypercmaps[1])); + hypercmaps[1] = 0; +} + +void +LoadHyperData (void) +{ + if (hyperstars[0] == 0) + { + hyperstars[0] = CaptureDrawable ( + LoadGraphic (AMBIENT_MASK_PMAP_ANIM) + ); + hyperstars[1] = CaptureDrawable ( + LoadGraphic (HYPERSTARS_MASK_PMAP_ANIM) + ); + hypercmaps[0] = CaptureColorMap (LoadColorMap (HYPER_COLOR_TAB)); + + hyperstars[2] = CaptureDrawable ( + LoadGraphic (ARISPACE_MASK_PMAP_ANIM) + ); + hypercmaps[1] = CaptureColorMap (LoadColorMap (ARISPACE_COLOR_TAB)); + } +} + +BOOLEAN +LoadHyperspace (void) +{ + hyper_dx = hyper_dy = 0; + fuel_ticks = 1; + + GLOBAL (ShipStamp.origin.x) = -MAX_X_UNIVERSE; + GLOBAL (ShipStamp.origin.y) = -MAX_Y_UNIVERSE; + + LoadHyperData (); + { + FRAME F; + + F = hyperstars[0]; + hyperstars[0] = stars_in_space; + stars_in_space = F; + } + + if (!(LastActivity & CHECK_LOAD)) + RepairSISBorder (); + else + { + if (LOBYTE (LastActivity) == 0) + { + ClearSemaphore (&GraphicsSem); + DrawSISFrame (); + SetSemaphore (&GraphicsSem); + } + else + { + ClearSISRect (DRAW_SIS_DISPLAY); + RepairSISBorder (); + } + } + DrawSISMessage (NULL_PTR); + + SetContext (RadarContext); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0xE, 0x00), 0x6C)); + + SetContext (SpaceContext); + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x7, 0x00, 0x00), 0x2F)); + SetColorMap (GetColorMapAddress (hypercmaps[0])); + } + else + { + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x1A, 0x00), 0x2F)); + SetColorMap (GetColorMapAddress (hypercmaps[1])); + SET_GAME_STATE (USED_BROADCASTER, 0); + SET_GAME_STATE (BROADCASTER_RESPONSE, 0); + } + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); +// ClearDrawable (); + + ClearSISRect (CLEAR_SIS_RADAR); + + return (TRUE); +} + +BOOLEAN +FreeHyperspace (void) +{ + ClearSemaphore (&GraphicsSem); + if (GameClockRunning ()) + SuspendGameClock (); + SetSemaphore (&GraphicsSem); + + { + FRAME F; + + F = hyperstars[0]; + hyperstars[0] = stars_in_space; + stars_in_space = F; + } +// FreeHyperData (); + + return (TRUE); +} + +static void +ElementToUniverse (ELEMENTPTR ElementPtr, PPOINT pPt) +{ + long log_x, log_y; + + log_x = GLOBAL_SIS (log_x) + + (ElementPtr->next.location.x - (LOG_SPACE_WIDTH >> 1)); + log_y = GLOBAL_SIS (log_y) + + (ElementPtr->next.location.y - (LOG_SPACE_HEIGHT >> 1)); + pPt->x = LOGX_TO_UNIVERSE (log_x); + pPt->y = LOGY_TO_UNIVERSE (log_y); +} + +static void +cleanup_hyperspace (void) +{ + HENCOUNTER hEncounter, hNextEncounter; + + for (hEncounter = GetHeadEncounter (); + hEncounter != 0; hEncounter = hNextEncounter) + { + ENCOUNTERPTR EncounterPtr; + + LockEncounter (hEncounter, &EncounterPtr); + hNextEncounter = GetSuccEncounter (EncounterPtr); + if (EncounterPtr->hElement) + { + ELEMENTPTR ElementPtr; + + LockElement (EncounterPtr->hElement, &ElementPtr); + + if (ElementPtr->state_flags & BAD_GUY) + { + RemoveEncounter (hEncounter); + InsertEncounter (hEncounter, GetHeadEncounter ()); + } + + UnlockElement (EncounterPtr->hElement); + } + EncounterPtr->hElement = 0; + UnlockEncounter (hEncounter); + } +} + +enum +{ + RANDOM_ENCOUNTER_TRANSITION, + INTERPLANETARY_TRANSITION, + ARILOU_SPACE_TRANSITION +}; + +static void +unhyper_transition (PELEMENT ElementPtr) +{ + COUNT frame_index; + + ElementPtr->state_flags |= CHANGING; + + frame_index = GetFrameIndex (ElementPtr->current.image.frame); + if (frame_index == 0) + frame_index += ANGLE_TO_FACING (FULL_CIRCLE); + else if (frame_index < ANGLE_TO_FACING (FULL_CIRCLE)) + frame_index = NORMALIZE_FACING (frame_index + 1); + else if (++frame_index == GetFrameCount (ElementPtr->current.image.frame)) + { + cleanup_hyperspace (); + + GLOBAL (ShipStamp.frame) = 0; + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + switch (ElementPtr->turn_wait) + { + case RANDOM_ENCOUNTER_TRANSITION: + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + break; + case INTERPLANETARY_TRANSITION: + SET_GAME_STATE (USED_BROADCASTER, 0); + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) == 0) + { + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (ESCAPE_COUNTER, 0); + } + else + { + POINT pt; + + GLOBAL (autopilot.x) = + GLOBAL (autopilot.y) = ~0; + + ElementToUniverse (ElementPtr, &pt); + CurStarDescPtr = FindStar (NULL_PTR, &pt, 5, 5); + if (CurStarDescPtr->star_pt.x == ARILOU_HOME_X + && CurStarDescPtr->star_pt.y == ARILOU_HOME_Y) + { + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + } + else + { + COUNT index; + POINT portal_pt[] = + { + {4091, 7748}, + {3184, 4906}, + {9211, 6104}, + {5673, 1207}, + {1910, 926}, + {8607, 151}, + { 50, 1647}, + {6117, 4131}, + {5658, 9712}, + {2302, 3988}, + { 112, 9409}, + {7752, 8906}, + { 368, 6332}, + {9735, 3153}, + {5850, 6213}, + }; + + index = CurStarDescPtr + - ((STAR_DESCPTR)&star_array[NUM_SOLAR_SYSTEMS + 1]); + GLOBAL_SIS (log_x) = + UNIVERSE_TO_LOGX (portal_pt[index].x); + GLOBAL_SIS (log_y) = + UNIVERSE_TO_LOGY (portal_pt[index].y); + + SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); + } + } + break; + case ARILOU_SPACE_TRANSITION: + SET_GAME_STATE (USED_BROADCASTER, 0); + GLOBAL (autopilot.x) = + GLOBAL (autopilot.y) = ~0; + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) == 0) + { + GLOBAL_SIS (log_x) = + UNIVERSE_TO_LOGX (QUASI_SPACE_X); + GLOBAL_SIS (log_y) = + UNIVERSE_TO_LOGY (QUASI_SPACE_Y); + if (GET_GAME_STATE (PORTAL_COUNTER) == 0) + { + SET_GAME_STATE (ARILOU_SPACE_SIDE, 2); + } + else + { + SET_GAME_STATE (PORTAL_COUNTER, 0); + SET_GAME_STATE (ARILOU_SPACE_SIDE, 3); + } + } + else + { + GLOBAL_SIS (log_x) = + UNIVERSE_TO_LOGX (ARILOU_SPACE_X); + GLOBAL_SIS (log_y) = + UNIVERSE_TO_LOGY (ARILOU_SPACE_Y); + SET_GAME_STATE (ARILOU_SPACE_SIDE, 1); + } + break; + } + + ZeroVelocityComponents (&ElementPtr->velocity); + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + return; + } + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, frame_index); +} + +static void +init_transition (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1, BYTE + which_transition) +{ + SIZE dx, dy, num_turns; + STARSHIPPTR StarShipPtr; + + dx = WORLD_TO_VELOCITY (ElementPtr0->next.location.x + - ElementPtr1->next.location.x); + dy = WORLD_TO_VELOCITY (ElementPtr0->next.location.y + - ElementPtr1->next.location.y); + + ElementPtr1->state_flags |= NONSOLID; + ElementPtr1->preprocess_func = unhyper_transition; + ElementPtr1->postprocess_func = NULL_PTR; + ElementPtr1->turn_wait = which_transition; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + if ((num_turns = GetFrameCount (ElementPtr1->next.image.frame) + - ANGLE_TO_FACING (FULL_CIRCLE) + + NORMALIZE_FACING (ANGLE_TO_FACING (FULL_CIRCLE) + - StarShipPtr->ShipFacing)) == 0) + num_turns = 1; + + SetVelocityComponents (&ElementPtr1->velocity, + dx / num_turns, dy / num_turns); +} + +BOOLEAN +hyper_transition (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & APPEARING) + { + if (LastActivity & CHECK_LOAD) + { + LastActivity &= ~CHECK_LOAD; + + ElementPtr->current = ElementPtr->next; + SetUpElement (ElementPtr); + + ElementPtr->state_flags |= DEFY_PHYSICS; + + return (FALSE); + } + else + { + ElementPtr->preprocess_func = + (void (*) (struct element + *ElementPtr))hyper_transition; + ElementPtr->postprocess_func = NULL_PTR; + ElementPtr->state_flags |= NONSOLID; + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + GetFrameCount (ElementPtr->current.image.frame) - 1); + } + } + else + { + COUNT frame_index; + + frame_index = GetFrameIndex (ElementPtr->current.image.frame); + if (frame_index-- <= ANGLE_TO_FACING (FULL_CIRCLE)) + { + STARSHIPPTR StarShipPtr; + + if (frame_index == ANGLE_TO_FACING (FULL_CIRCLE) - 1) + frame_index = 0; + else + frame_index = NORMALIZE_FACING (frame_index); + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (frame_index == StarShipPtr->ShipFacing) + { + ElementPtr->preprocess_func = ship_preprocess; + ElementPtr->postprocess_func = ship_postprocess; + ElementPtr->state_flags &= ~NONSOLID; + } + } + + ElementPtr->state_flags |= CHANGING; + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + frame_index); + + if (!(ElementPtr->state_flags & NONSOLID)) + { + ElementPtr->current = ElementPtr->next; + SetUpElement (ElementPtr); + + ElementPtr->state_flags |= DEFY_PHYSICS; + } + } + + return (TRUE); +} + +static void +hyper_collision (PELEMENT ElementPtr0, PPOINT + pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && GET_GAME_STATE (PORTAL_COUNTER) == 0) + { + SIZE dx, dy; + POINT pt; + STAR_DESCPTR SDPtr; + STARSHIPPTR StarShipPtr; + + ElementToUniverse (ElementPtr0, &pt); + + SDPtr = FindStar (NULL_PTR, &pt, 5, 5); + + GetElementStarShip (ElementPtr1, &StarShipPtr); + GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx, &dy); + if (SDPtr == CurStarDescPtr + || (ElementPtr1->state_flags & APPEARING) + || !(dx || dy || (StarShipPtr->cur_status_flags + & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL)))) + { + CurStarDescPtr = SDPtr; + ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION; + } + else if ((GLOBAL (CurrentActivity) & IN_BATTLE) + && (GLOBAL (autopilot.x) == ~0 + || GLOBAL (autopilot.y) == ~0 + || (GLOBAL (autopilot.x) == SDPtr->star_pt.x + && GLOBAL (autopilot.y) == SDPtr->star_pt.y))) + { + CurStarDescPtr = SDPtr; + ElementPtr0->state_flags |= COLLISION; + + init_transition (ElementPtr0, ElementPtr1, + INTERPLANETARY_TRANSITION); + } + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +hyper_death (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & DEFY_PHYSICS) + && (GLOBAL (CurrentActivity) & IN_BATTLE)) + CurStarDescPtr = 0; +} + +static void +arilou_space_death (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & DEFY_PHYSICS) + || GET_GAME_STATE (ARILOU_SPACE_COUNTER) == 0) + { + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); + } + else + { + SET_GAME_STATE (ARILOU_SPACE_SIDE, 3); + } + } +} + +static void +arilou_space_collision (PELEMENT ElementPtr0, + PPOINT pPt0, PELEMENT ElementPtr1, PPOINT + pPt1) +{ + COUNT which_side; + + if (!(ElementPtr1->state_flags & PLAYER_SHIP)) + return; + + which_side = GET_GAME_STATE (ARILOU_SPACE_SIDE); + if (which_side == 0 || which_side == 3) + { + if (ElementPtr1->state_flags & DEFY_PHYSICS) + { + SET_GAME_STATE (ARILOU_SPACE_SIDE, which_side ^ 1); + } + else + { + init_transition (ElementPtr0, ElementPtr1, ARILOU_SPACE_TRANSITION); + } + } + + ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION; + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static HELEMENT +AllocHyperElement (STAR_DESCPTR SDPtr) +{ + HELEMENT hHyperSpaceElement; + + hHyperSpaceElement = AllocElement (); + if (hHyperSpaceElement) + { + ELEMENTPTR HyperSpaceElementPtr; + + LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); + HyperSpaceElementPtr->state_flags = CHANGING | FINITE_LIFE; + HyperSpaceElementPtr->life_span = 1; + HyperSpaceElementPtr->mass_points = 1; + + { + long lx, ly; + + lx = UNIVERSE_TO_LOGX (SDPtr->star_pt.x) + + (LOG_SPACE_WIDTH >> 1) + - GLOBAL_SIS (log_x); + HyperSpaceElementPtr->current.location.x = WRAP_X (lx); + + ly = UNIVERSE_TO_LOGY (SDPtr->star_pt.y) + + (LOG_SPACE_HEIGHT >> 1) + - GLOBAL_SIS (log_y); + HyperSpaceElementPtr->current.location.y = WRAP_Y (ly); + } + + SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex], STAMP_PRIM); + HyperSpaceElementPtr->current.image.farray = + &hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)]; + + UnlockElement (hHyperSpaceElement); + } + + return (hHyperSpaceElement); +} + +static void +AddAmbientElement (void) +{ + HELEMENT hHyperSpaceElement; + + hHyperSpaceElement = AllocElement (); + if (hHyperSpaceElement) + { + SIZE dx, dy; + DWORD rand_val; + ELEMENTPTR HyperSpaceElementPtr; + + LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); + HyperSpaceElementPtr->state_flags = + APPEARING | FINITE_LIFE | NONSOLID; + SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex], STAMP_PRIM); + HyperSpaceElementPtr->preprocess_func = animation_preprocess; + + rand_val = Random (); + dy = LOWORD (rand_val); + dx = (SIZE)(LOBYTE (dy) % SPACE_WIDTH) - (SPACE_WIDTH >> 1); + dy = (SIZE)(HIBYTE (dy) % SPACE_HEIGHT) - (SPACE_HEIGHT >> 1); + HyperSpaceElementPtr->current.location.x = (LOG_SPACE_WIDTH >> 1) + + DISPLAY_TO_WORLD (dx); + HyperSpaceElementPtr->current.location.y = (LOG_SPACE_HEIGHT >> 1) + + DISPLAY_TO_WORLD (dy); + HyperSpaceElementPtr->current.image.farray = &stars_in_space; + + if (HIWORD (rand_val) & 7) + { + HyperSpaceElementPtr->life_span = 14; + HyperSpaceElementPtr->current.image.frame = stars_in_space; + } + else + { + HyperSpaceElementPtr->life_span = 12; + HyperSpaceElementPtr->current.image.frame = + SetAbsFrameIndex (stars_in_space, 14); + } + + UnlockElement (hHyperSpaceElement); + + InsertElement (hHyperSpaceElement, GetHeadElement ()); + } +} + +#define NUM_VORTEX_TRANSITIONS 9 +#define VORTEX_WAIT 1 + +static void +encounter_transition (PELEMENT ElementPtr) +{ + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->life_span = 1; + if (ElementPtr->turn_wait) + { + --ElementPtr->turn_wait; + } + else + { + FRAME f; + + if (ElementPtr->hit_points) + { + f = DecFrameIndex (ElementPtr->current.image.frame); + ElementPtr->next.image.frame = f; + } + else + { + f = IncFrameIndex (ElementPtr->current.image.frame); + if (f != ElementPtr->current.image.farray[0]) + ElementPtr->next.image.frame = f; + else + ElementPtr->death_func = NULL_PTR; + } + + ElementPtr->turn_wait = VORTEX_WAIT; + } +} + +static void +encounter_collision (PELEMENT ElementPtr0, PPOINT + pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && (GLOBAL (CurrentActivity) & IN_BATTLE)) + { + HENCOUNTER hEncounter, hNextEncounter; + + init_transition (ElementPtr0, ElementPtr1, RANDOM_ENCOUNTER_TRANSITION); + + for (hEncounter = GetHeadEncounter (); + hEncounter != 0; hEncounter = hNextEncounter) + { + ENCOUNTERPTR EncounterPtr; + + LockEncounter (hEncounter, &EncounterPtr); + hNextEncounter = GetSuccEncounter (EncounterPtr); + if (EncounterPtr->hElement) + { + ELEMENTPTR ElementPtr; + + LockElement (EncounterPtr->hElement, &ElementPtr); + + ElementPtr->state_flags |= NONSOLID | IGNORE_SIMILAR; + + UnlockElement (EncounterPtr->hElement); + } + UnlockEncounter (hEncounter); + } + + ElementPtr0->state_flags |= BAD_GUY; + ZeroVelocityComponents (&ElementPtr0->velocity); + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static HELEMENT +AddEncounterElement (ENCOUNTERPTR EncounterPtr, + PPOINT puniverse) +{ + BOOLEAN NewEncounter; + HELEMENT hElement; + STAR_DESC SD; + + + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) >= 2) + return (0); + + if (EncounterPtr->SD.Index & ENCOUNTER_REFORMING) + { + EncounterPtr->SD.Index &= ~ENCOUNTER_REFORMING; + + EncounterPtr->transition_state = 100; + if ((EncounterPtr->SD.Index & ONE_SHOT_ENCOUNTER) + || LONIBBLE (EncounterPtr->SD.Index) == 0) + return (0); + } + + if (LONIBBLE (EncounterPtr->SD.Index)) + { + NewEncounter = FALSE; + SD.star_pt = EncounterPtr->SD.star_pt; + } + else + { + BYTE Type; + SIZE dx, dy; + COUNT i, NumShips; + DWORD radius_squared; + BYTE EncounterMakeup[] = + { + RACE_ENCOUNTER_MAKEUP + }; + + NewEncounter = TRUE; + + radius_squared = (DWORD)EncounterPtr->radius * EncounterPtr->radius; + + Type = EncounterPtr->SD.Type; + NumShips = LONIBBLE (EncounterMakeup[Type]); + for (i = HINIBBLE (EncounterMakeup[Type]) - NumShips; i; --i) + { + if ((COUNT)Random () % 100 < 50) + ++NumShips; + } + + if (NumShips > MAX_HYPER_SHIPS) + NumShips = MAX_HYPER_SHIPS; + + + EncounterPtr->SD.Index = MAKE_BYTE ( + NumShips, HINIBBLE (EncounterPtr->SD.Index) + ); + for (i = 0; i < NumShips; ++i) + { + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR TemplatePtr; + + hStarShip = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), Type + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + EncounterPtr->SD.ShipList[i] = TemplatePtr->ShipInfo; + EncounterPtr->SD.ShipList[i].var1 = Type; + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + + + do + { + DWORD rand_val; + + rand_val = Random (); + + SD.star_pt.x = puniverse->x + + (LOWORD (rand_val) % (XOFFS << 1)) - XOFFS; + if (SD.star_pt.x < 0) + SD.star_pt.x = 0; + else if (SD.star_pt.x > MAX_X_UNIVERSE) + SD.star_pt.x = MAX_X_UNIVERSE; + SD.star_pt.y = puniverse->y + + (HIWORD (rand_val) % (YOFFS << 1)) - YOFFS; + if (SD.star_pt.y < 0) + SD.star_pt.y = 0; + else if (SD.star_pt.y > MAX_Y_UNIVERSE) + SD.star_pt.y = MAX_Y_UNIVERSE; + + dx = SD.star_pt.x - EncounterPtr->origin.x; + dy = SD.star_pt.y - EncounterPtr->origin.y; + } while ((DWORD)((long)dx * dx + (long)dy * dy) > radius_squared); + + EncounterPtr->SD.star_pt = SD.star_pt; + EncounterPtr->log_x = UNIVERSE_TO_LOGX (SD.star_pt.x); + EncounterPtr->log_y = UNIVERSE_TO_LOGY (SD.star_pt.y); + } + + hElement = AllocHyperElement (&SD); + if (hElement) + { + SIZE i; + ELEMENTPTR ElementPtr; + + + LockElement (hElement, &ElementPtr); + + if ((i = EncounterPtr->transition_state) || NewEncounter) + { + if (i < 0) + { + i = -i; + ElementPtr->hit_points = 1; + } + if (i == 0 || i > NUM_VORTEX_TRANSITIONS) + i = NUM_VORTEX_TRANSITIONS; + + ElementPtr->current.image.frame = + SetRelFrameIndex ( + ElementPtr->current.image.farray[0], -i + ); + ElementPtr->death_func = encounter_transition; + } + else + { + ElementPtr->current.image.frame = + DecFrameIndex (ElementPtr->current.image.farray[0]); + } + + ElementPtr->turn_wait = VORTEX_WAIT; + ElementPtr->preprocess_func = NULL_PTR; + ElementPtr->postprocess_func = NULL_PTR; + ElementPtr->collision_func = encounter_collision; + + SetUpElement (ElementPtr); + + ElementPtr->IntersectControl.IntersectStamp.frame = + DecFrameIndex (stars_in_space); + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + ElementPtr->state_flags |= NONSOLID | IGNORE_VELOCITY; + + UnlockElement (hElement); + + InsertElement (hElement, GetTailElement ()); + } + + return (EncounterPtr->hElement = hElement); +} + +#define GRID_OFFSET 200 + +static void +DrawHyperGrid (COORD ux, COORD uy, COORD ox, + COORD oy) +{ + COORD sx, sy, ex, ey; + RECT r; + + ClearDrawable (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B)); + + if ((sx = ux - (RADAR_SCAN_WIDTH >> 1)) < 0) + sx = 0; + else + sx -= sx % GRID_OFFSET; + if ((ex = ux + (RADAR_SCAN_WIDTH >> 1)) > MAX_X_UNIVERSE + 1) + ex = MAX_X_UNIVERSE + 1; + + if ((sy = uy - (RADAR_SCAN_HEIGHT >> 1)) < 0) + sy = 0; + else + sy -= sy % GRID_OFFSET; + if ((ey = uy + (RADAR_SCAN_HEIGHT >> 1)) > MAX_Y_UNIVERSE + 1) + ey = MAX_Y_UNIVERSE + 1; + + r.corner.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) + * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; + r.extent.width = 1; + r.extent.height = ((COORD)((long)(MAX_Y_UNIVERSE - sy) + * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy) + - r.corner.y + 1; + for (ux = sx; ux <= ex; ux += GRID_OFFSET) + { + r.corner.x = (COORD)((long)ux + * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; + DrawFilledRectangle (&r); + } while ((ux += GRID_OFFSET) < ex); + + r.corner.x = (COORD)((long)sx + * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; + r.extent.width = ((COORD)((long)ex + * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox) + - r.corner.x + 1; + r.extent.height = 1; + for (uy = sy; uy <= ey; uy += GRID_OFFSET) + { + r.corner.y = (COORD)((long)(MAX_Y_UNIVERSE - uy) + * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; + DrawFilledRectangle (&r); + } while ((uy += GRID_OFFSET) < ey); +} + + +static void +ProcessEncounters (PPOINT puniverse, COORD ox, + COORD oy) +{ + STAMP s; + HENCOUNTER hEncounter, hNextEncounter; + + s.frame = SetAbsFrameIndex (stars_in_space, 91); + for (hEncounter = GetHeadEncounter (); + hEncounter; hEncounter = hNextEncounter) + { + COORD ex, ey; + ENCOUNTERPTR EncounterPtr; + + LockEncounter (hEncounter, &EncounterPtr); + hNextEncounter = GetSuccEncounter (EncounterPtr); + + if (EncounterPtr->hElement == 0 + && AddEncounterElement ( + EncounterPtr, puniverse + ) == 0) + { +DeleteEncounter: + UnlockEncounter (hEncounter); + + RemoveEncounter (hEncounter); + FreeEncounter (hEncounter); + continue; + } + + { + ELEMENTPTR ElementPtr; + + LockElement (EncounterPtr->hElement, &ElementPtr); + + if (ElementPtr->death_func) + { + if (EncounterPtr->transition_state + && ElementPtr->turn_wait == 0) + { + --EncounterPtr->transition_state; + if (EncounterPtr->transition_state >= + NUM_VORTEX_TRANSITIONS) + ++ElementPtr->turn_wait; + else if (EncounterPtr->transition_state == + -NUM_VORTEX_TRANSITIONS) + { + ElementPtr->death_func = NULL_PTR; + UnlockElement (EncounterPtr->hElement); + goto DeleteEncounter; + } + else + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); + } + } + else + { + SIZE delta_x, delta_y; + COUNT encounter_radius; + + ElementPtr->life_span = 1; + GetNextVelocityComponents (&ElementPtr->velocity, + &delta_x, &delta_y, 1); + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + else if (!(ElementPtr->state_flags & BAD_GUY)) + { + COUNT cur_facing, delta_facing; + + cur_facing = ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + ); + delta_facing = NORMALIZE_FACING (cur_facing + - ANGLE_TO_FACING (ARCTAN ( + puniverse->x - EncounterPtr->SD.star_pt.x, + puniverse->y - EncounterPtr->SD.star_pt.y + ))); + if (delta_facing || (delta_x == 0 && delta_y == 0)) + { + SIZE s, RaceHyperSpeed[] = + { + RACE_HYPER_SPEED + }; + +#define ENCOUNTER_TRACK_WAIT 3 + s = RaceHyperSpeed[EncounterPtr->SD.Type]; + if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + --cur_facing; + else + ++cur_facing; + if (NORMALIZE_FACING (delta_facing + + ANGLE_TO_FACING (OCTANT)) > ANGLE_TO_FACING (QUADRANT)) + { + if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + --cur_facing; + else + ++cur_facing; + s >>= 1; + } + cur_facing = FACING_TO_ANGLE (cur_facing); + SetVelocityComponents ( + &ElementPtr->velocity, + COSINE (cur_facing, s), + SINE (cur_facing, s) + ); + GetNextVelocityComponents (&ElementPtr->velocity, + &delta_x, &delta_y, 1); + + ElementPtr->thrust_wait = ENCOUNTER_TRACK_WAIT; + } + } + EncounterPtr->log_x += delta_x; + EncounterPtr->log_y -= delta_y; + EncounterPtr->SD.star_pt.x = + LOGX_TO_UNIVERSE (EncounterPtr->log_x); + EncounterPtr->SD.star_pt.y = + LOGY_TO_UNIVERSE (EncounterPtr->log_y); + + encounter_radius = EncounterPtr->radius + (GRID_OFFSET >> 1); + if ((delta_x = EncounterPtr->SD.star_pt.x + - EncounterPtr->origin.x) < 0) + delta_x = -delta_x; + if ((delta_y = EncounterPtr->SD.star_pt.y + - EncounterPtr->origin.y) < 0) + delta_y = -delta_y; + if ((COUNT)delta_x >= encounter_radius + || (COUNT)delta_y >= encounter_radius + || (DWORD)delta_x * delta_x + (DWORD)delta_y * delta_y >= + (DWORD)encounter_radius * encounter_radius) + { + ElementPtr->state_flags |= NONSOLID; + ElementPtr->life_span = 0; + + if (EncounterPtr->transition_state == 0) + { + ElementPtr->death_func = encounter_transition; + EncounterPtr->transition_state = -1; + ElementPtr->hit_points = 1; + } + else + { + ElementPtr->death_func = NULL_PTR; + UnlockElement (EncounterPtr->hElement); + goto DeleteEncounter; + } + } + } + + ex = EncounterPtr->SD.star_pt.x; + ey = EncounterPtr->SD.star_pt.y; + if (ex - puniverse->x >= -UNIT_SCREEN_WIDTH + && ex - puniverse->x <= UNIT_SCREEN_WIDTH + && ey - puniverse->y >= -UNIT_SCREEN_HEIGHT + && ey - puniverse->y <= UNIT_SCREEN_HEIGHT) + { + ElementPtr->next.location.x = (SIZE)( + EncounterPtr->log_x - GLOBAL_SIS (log_x) + ) + (LOG_SPACE_WIDTH >> 1); + ElementPtr->next.location.y = (SIZE)( + EncounterPtr->log_y - GLOBAL_SIS (log_y) + ) + (LOG_SPACE_HEIGHT >> 1); + if ((ElementPtr->state_flags & NONSOLID) + && EncounterPtr->transition_state == 0) + { + ElementPtr->current.location = + ElementPtr->next.location; + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); + if (ElementPtr->death_func == 0) + { + InitIntersectStartPoint (ElementPtr); + ElementPtr->state_flags &= ~NONSOLID; + } + } + } + else + { + ElementPtr->state_flags |= NONSOLID; + if (ex - puniverse->x < -XOFFS + || ex - puniverse->x > XOFFS + || ey - puniverse->y < -YOFFS + || ey - puniverse->y > YOFFS) + { + ElementPtr->life_span = 0; + ElementPtr->death_func = NULL_PTR; + UnlockElement (EncounterPtr->hElement); + + goto DeleteEncounter; + } + + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + } + + UnlockElement (EncounterPtr->hElement); + } + + s.origin.x = (COORD)((long)ex * RADAR_WIDTH + / RADAR_SCAN_WIDTH) - ox; + s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT + / RADAR_SCAN_HEIGHT) - oy; + DrawStamp (&s); + + UnlockEncounter (hEncounter); + } +} + +void +SeedUniverse (void) +{ + COORD ox, oy; + COORD ux, uy, sx, sy, ex, ey; + POINT universe; + FRAME blip_frame; + STAMP s; + STAR_DESCPTR SDPtr; + HELEMENT hHyperSpaceElement; + ELEMENTPTR HyperSpaceElementPtr; + + ClockTick (); + + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + + blip_frame = SetAbsFrameIndex (stars_in_space, 90); + + SetContext (RadarContext); + BatchGraphics (); + + ox = (COORD)((long)universe.x + * RADAR_WIDTH / RADAR_SCAN_WIDTH) + - (RADAR_WIDTH >> 1); + oy = (COORD)((long)(MAX_Y_UNIVERSE - universe.y) + * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) + - (RADAR_HEIGHT >> 1); + + ex = (COORD)((long)GLOBAL (ShipStamp.origin.x) + * RADAR_WIDTH / RADAR_SCAN_WIDTH) + - (RADAR_WIDTH >> 1); + ey = (COORD)((long)(MAX_Y_UNIVERSE + - GLOBAL (ShipStamp.origin.y)) + * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) + - (RADAR_HEIGHT >> 1); + + ux = GET_GAME_STATE (ARILOU_SPACE_COUNTER); + uy = GET_GAME_STATE (ARILOU_SPACE_SIDE); + +// if (ox != ex || oy != ey) + { + DrawHyperGrid (universe.x, universe.y, ox, oy); + + { + SDPtr = 0; + while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS))) + { + BYTE star_type; + + ex = SDPtr->star_pt.x; + ey = SDPtr->star_pt.y; + star_type = STAR_TYPE (SDPtr->Type); + if (uy >= 2 && ex == ARILOU_HOME_X && ey == ARILOU_HOME_Y) + star_type = SUPER_GIANT_STAR; + + s.origin.x = (COORD)((long)ex * RADAR_WIDTH + / RADAR_SCAN_WIDTH) - ox; + s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT + / RADAR_SCAN_HEIGHT) - oy; + s.frame = SetRelFrameIndex (blip_frame, + star_type + 2); + DrawStamp (&s); + } + } + } + + if ((ex = GET_GAME_STATE (PORTAL_COUNTER)) || ux) + { + COUNT i; + STAR_DESC SD[2]; + + i = 0; + if (ex) + { + static POINT portal_pt; + + SD[i].Index = ((ex - 1) >> 1) + 18; + if (ex == 1) + portal_pt = universe; + SD[i].star_pt = portal_pt; + ++i; + + if (++ex == (10 + 1)) + ex = (9 + 1); + + SET_GAME_STATE (PORTAL_COUNTER, ex); + } + + if (ux) + { + SD[i].Index = ux >> 1; + if (uy <= 1) + { + SD[i].Index += 18; + SD[i].star_pt.x = ARILOU_SPACE_X; + SD[i].star_pt.y = ARILOU_SPACE_Y; + } + else + { + SD[i].star_pt.x = QUASI_SPACE_X; + SD[i].star_pt.y = QUASI_SPACE_Y; + } + ++i; + } + + do + { + --i; + sx = SD[i].star_pt.x - universe.x + XOFFS; + sy = SD[i].star_pt.y - universe.y + YOFFS; + if (sx >= 0 && sy >= 0 + && sx < (XOFFS << 1) && sy < (YOFFS << 1)) + { + ex = SD[i].star_pt.x; + ey = SD[i].star_pt.y; + s.origin.x = (COORD)((long)ex * RADAR_WIDTH + / RADAR_SCAN_WIDTH) - ox; + s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) + * RADAR_HEIGHT + / RADAR_SCAN_HEIGHT) - oy; + s.frame = SetAbsFrameIndex (stars_in_space, 95); + DrawStamp (&s); + + if ((ex -= universe.x) < 0) + ex = -ex; + if ((ey -= universe.y) < 0) + ey = -ey; + if (ex <= (XOFFS / NUM_RADAR_SCREENS) + && ey <= (YOFFS / NUM_RADAR_SCREENS) + && (hHyperSpaceElement = + AllocHyperElement ((STAR_DESCPTR)&SD[i])) != 0) + { + LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); + HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex ( + hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)], + SD[i].Index + ); + HyperSpaceElementPtr->preprocess_func = + HyperSpaceElementPtr->postprocess_func = NULL_PTR; + HyperSpaceElementPtr->collision_func = arilou_space_collision; + + SetUpElement (HyperSpaceElementPtr); + + if (uy == 1 || uy == 2) + HyperSpaceElementPtr->death_func = arilou_space_death; + else + { + HyperSpaceElementPtr->death_func = NULL_PTR; + HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame = + DecFrameIndex (stars_in_space); + } + + UnlockElement (hHyperSpaceElement); + + InsertElement (hHyperSpaceElement, GetHeadElement ()); + } + } + } while (i); + } + + { + SDPtr = 0; + while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS))) + { + ex = SDPtr->star_pt.x; + ey = SDPtr->star_pt.y; + if ((ex -= universe.x) < 0) + ex = -ex; + if ((ey -= universe.y) < 0) + ey = -ey; + if (ex <= (XOFFS / NUM_RADAR_SCREENS) + && ey <= (YOFFS / NUM_RADAR_SCREENS) + && (hHyperSpaceElement = AllocHyperElement (SDPtr)) != 0) + { + BYTE star_type; + + star_type = SDPtr->Type; + + LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); + HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex ( + hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)], + STAR_TYPE (star_type) + * NUM_STAR_COLORS + + STAR_COLOR (star_type) + ); + HyperSpaceElementPtr->preprocess_func = + HyperSpaceElementPtr->postprocess_func = NULL_PTR; + HyperSpaceElementPtr->collision_func = hyper_collision; + + SetUpElement (HyperSpaceElementPtr); + + if (SDPtr == CurStarDescPtr + && GET_GAME_STATE (PORTAL_COUNTER) == 0) + HyperSpaceElementPtr->death_func = hyper_death; + else + { + HyperSpaceElementPtr->death_func = NULL_PTR; + HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame = + DecFrameIndex (stars_in_space); + } + UnlockElement (hHyperSpaceElement); + + InsertElement (hHyperSpaceElement, GetHeadElement ()); + } + } + ProcessEncounters (&universe, ox, oy); + } + + s.origin.x = RADAR_WIDTH >> 1; + s.origin.y = RADAR_HEIGHT >> 1; + s.frame = blip_frame; + DrawStamp (&s); + + UnbatchGraphics (); + + SetContext (StatusContext); + + if (!(LOWORD (Random ()) & 7)) + AddAmbientElement (); + + if (universe.x != GLOBAL (ShipStamp.origin.x) + || universe.y != GLOBAL (ShipStamp.origin.y)) + { + GLOBAL (ShipStamp.origin) = universe; + DrawHyperCoords (universe); + } +} + +void +DoMenuOptions (void) +{ + COLOR OldColor; + CONTEXT OldContext; + DRAW_STATE OldDrawState; + MENU_STATE MenuState; + +UnbatchGraphics (); + + OldContext = SetContext (SpaceContext); + OldDrawState = SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + OldColor = SetContextBackGroundColor (BLACK_COLOR); + + ClearSemaphore (&GraphicsSem); + SuspendGameClock (); + + memset ((PMENU_STATE)&MenuState, 0, sizeof (MenuState)); + MenuState.InputFunc = DoFlagshipCommands; + MenuState.Initialized = 1; + MenuState.CurState = STARMAP + 1; + + DrawMenuStateStrings (PM_SCAN, STARMAP); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + DoInput ((PVOID)&MenuState); + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + + SetContext (SpaceContext); + SetContextBGFrame (0); + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + ClearSISRect (CLEAR_SIS_RADAR); + ClearSemaphore (&GraphicsSem); + WaitForNoInput (ONE_SECOND / 2); + ResumeGameClock (); + SetSemaphore (&GraphicsSem); + } + + SetContextBackGroundColor (OldColor); + SetContextDrawState (OldDrawState); + SetContext (OldContext); + if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) + cleanup_hyperspace (); + +BatchGraphics (); +} + diff --git a/sc2/src/sc2code/hyper.h b/sc2/src/sc2code/hyper.h new file mode 100644 index 000000000..06326bc5e --- /dev/null +++ b/sc2/src/sc2code/hyper.h @@ -0,0 +1,26 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _HYPER_H +#define _HYPER_H + + +extern ENCOUNTER_INFO SISinfo; + +#endif /* _HYPER_H */ + diff --git a/sc2/src/sc2code/ifontres.h b/sc2/src/sc2code/ifontres.h new file mode 100644 index 000000000..8c2e227bd --- /dev/null +++ b/sc2/src/sc2code/ifontres.h @@ -0,0 +1,7 @@ +#define STARCON_FONT 0x03800003L +#define TINY_FONT 0x03800103L +#define MICRO_FONT 0x03c00203L +#define LANDER_FONT 0x11400303L +#define PLAYER_FONT 0x17a00403L + + diff --git a/sc2/src/sc2code/igfxres.h b/sc2/src/sc2code/igfxres.h new file mode 100644 index 000000000..c4e806eed --- /dev/null +++ b/sc2/src/sc2code/igfxres.h @@ -0,0 +1,286 @@ +#define TITLE_ANIM 0x00400002L +#define STATUS_MASK_PMAP_ANIM 0x03800102L +#define ACTIVITY_ANIM 0x03800202L +#define PLAYMENU_ANIM 0x03a00302L +#define FLAGSTAT_MASK_PMAP_ANIM 0x03e00402L +#define MISCDATA_MASK_PMAP_ANIM 0x03e00502L +#define STAR_MASK_PMAP_ANIM 0x04400602L +#define ASTEROID_BIG_MASK_PMAP_ANIM 0x04400702L +#define ASTEROID_MED_MASK_PMAP_ANIM 0x04400802L +#define ASTEROID_SML_MASK_PMAP_ANIM 0x04400902L +#define BLAST_BIG_MASK_PMAP_ANIM 0x04400a02L +#define BLAST_MED_MASK_PMAP_ANIM 0x04400b02L +#define BLAST_SML_MASK_PMAP_ANIM 0x04400c02L +#define BOOM_BIG_MASK_PMAP_ANIM 0x04400d02L +#define BOOM_MED_MASK_PMAP_ANIM 0x04400e02L +#define BOOM_SML_MASK_PMAP_ANIM 0x04400f02L +#define AMBIENT_MASK_PMAP_ANIM 0x04601002L +#define HYPERSTARS_MASK_PMAP_ANIM 0x04801102L +#define ARISPACE_MASK_PMAP_ANIM 0x04a01202L +#define IPBKGND_MASK_PMAP_ANIM 0x05001302L +#define SISIP_MASK_PMAP_ANIM 0x05201402L +#define ORBPLAN_MASK_PMAP_ANIM 0x05201502L +#define SUN_MASK_PMAP_ANIM 0x05201602L +#define LANDER_MASK_PMAP_ANIM 0x05401702L +#define QUAKE_MASK_PMAP_ANIM 0x05401802L +#define LIGHTNING_MASK_ANIM 0x05401902L +#define LAVA_MASK_PMAP_ANIM 0x05401a02L +#define LANDER_SHIELD_MASK_ANIM 0x05401b02L +#define LANDER_LAUNCH_MASK_PMAP_ANIM 0x05401c02L +#define LANDER_RETURN_MASK_PMAP_ANIM 0x05401d02L +#define ORBIT_VIEW_ANIM 0x05601e02L +#define EARTH_MASK_ANIM 0x05801f02L +#define CANNISTER_MASK_PMAP_ANIM 0x05a02002L +#define LIFE00_MASK_PMAP_ANIM 0x05c02102L +#define LIFE01_MASK_PMAP_ANIM 0x05e02202L +#define LIFE02_MASK_PMAP_ANIM 0x06002302L +#define LIFE03_MASK_PMAP_ANIM 0x06202402L +#define LIFE04_MASK_PMAP_ANIM 0x06402502L +#define LIFE05_MASK_PMAP_ANIM 0x06602602L +#define LIFE06_MASK_PMAP_ANIM 0x06802702L +#define LIFE07_MASK_PMAP_ANIM 0x06a02802L +#define LIFE08_MASK_PMAP_ANIM 0x06c02902L +#define LIFE09_MASK_PMAP_ANIM 0x06e02a02L +#define LIFE10_MASK_PMAP_ANIM 0x07002b02L +#define LIFE11_MASK_PMAP_ANIM 0x07202c02L +#define LIFE12_MASK_PMAP_ANIM 0x07402d02L +#define LIFE13_MASK_PMAP_ANIM 0x07602e02L +#define LIFE14_MASK_PMAP_ANIM 0x07802f02L +#define LIFE15_MASK_PMAP_ANIM 0x07a03002L +#define LIFE16_MASK_PMAP_ANIM 0x07c03102L +#define LIFE17_MASK_PMAP_ANIM 0x07e03202L +#define LIFE18_MASK_PMAP_ANIM 0x08003302L +#define LIFE19_MASK_PMAP_ANIM 0x08203402L +#define LIFE20_MASK_PMAP_ANIM 0x08403502L +#define LIFE21_MASK_PMAP_ANIM 0x08603602L +#define LIFE22_MASK_PMAP_ANIM 0x08803702L +#define LIFE23_MASK_PMAP_ANIM 0x08a03802L +#define LIFE24_MASK_PMAP_ANIM 0x08c03902L +#define LIFE25_MASK_PMAP_ANIM 0x08e03a02L +#define MOONBASE_MASK_PMAP_ANIM 0x11603b02L +#define MAIDENS_MASK_PMAP_ANIM 0x11803c02L +#define AQUA_MASK_PMAP_ANIM 0x11c03d02L +#define BURV_BCS_MASK_PMAP_ANIM 0x11e03e02L +#define TAALO_DEVICE_MASK_PMAP_ANIM 0x12003f02L +#define SUN_DEVICE_MASK_PMAP_ANIM 0x12204002L +#define VAULT_MASK_PMAP_ANIM 0x12404102L +#define WRECK_MASK_PMAP_ANIM 0x12604202L +#define BOMB_MASK_PMAP_ANIM 0x12804302L +#define EGG_CASE_MASK_PMAP_ANIM 0x12c04402L +#define SPAPLUTO_MASK_PMAP_ANIM 0x12e04502L +#define RUINS_MASK_PMAP_ANIM 0x13804602L +#define UMGAH_BCS_MASK_PMAP_ANIM 0x13c04702L +#define MELEE_SCREEN_PMAP_ANIM 0x14204802L +#define MELEE_PICK_MASK_PMAP_ANIM 0x14404902L +#define SEGUE_PMAP_ANIM 0x14604a02L +#define SC2_PICK_PMAP_ANIM 0x14804b02L +#define RESTART_PMAP_ANIM 0x18204c02L +#define MODULES_PMAP_ANIM 0x18404d02L +#define SISMODS_MASK_PMAP_ANIM 0x18604e02L +#define OUTFIT_PMAP_ANIM 0x18604f02L +#define SISBLU_MASK_ANIM 0x18a05002L +#define SHIPYARD_PMAP_ANIM 0x18a05102L +#define STARBASE_ANIM 0x18e05202L +#define SAMATRA_BIG_MASK_PMAP_ANIM 0x19005302L +#define SHIELDED_BIG_MASK_PMAP_ANIM 0x19205402L +#define SHIELDED_MED_MASK_PMAP_ANIM 0x19205502L +#define SHIELDED_SML_MASK_PMAP_ANIM 0x19205602L +#define PLANET00_BIG_MASK_PMAP_ANIM 0x19405702L +#define PLANET00_MED_MASK_PMAP_ANIM 0x19405802L +#define PLANET00_SML_MASK_PMAP_ANIM 0x19405902L +#define PLANET01_BIG_MASK_PMAP_ANIM 0x19605a02L +#define PLANET01_MED_MASK_PMAP_ANIM 0x19605b02L +#define PLANET01_SML_MASK_PMAP_ANIM 0x19605c02L +#define PLANET02_BIG_MASK_PMAP_ANIM 0x19805d02L +#define PLANET02_MED_MASK_PMAP_ANIM 0x19805e02L +#define PLANET02_SML_MASK_PMAP_ANIM 0x19805f02L +#define PLANET03_BIG_MASK_PMAP_ANIM 0x19a06002L +#define PLANET03_MED_MASK_PMAP_ANIM 0x19a06102L +#define PLANET03_SML_MASK_PMAP_ANIM 0x19a06202L +#define PLANET04_BIG_MASK_PMAP_ANIM 0x19c06302L +#define PLANET04_MED_MASK_PMAP_ANIM 0x19c06402L +#define PLANET04_SML_MASK_PMAP_ANIM 0x19c06502L +#define PLANET05_BIG_MASK_PMAP_ANIM 0x19e06602L +#define PLANET05_MED_MASK_PMAP_ANIM 0x19e06702L +#define PLANET05_SML_MASK_PMAP_ANIM 0x19e06802L +#define PLANET06_BIG_MASK_PMAP_ANIM 0x1a006902L +#define PLANET06_MED_MASK_PMAP_ANIM 0x1a006a02L +#define PLANET06_SML_MASK_PMAP_ANIM 0x1a006b02L +#define PLANET07_BIG_MASK_PMAP_ANIM 0x1a206c02L +#define PLANET07_MED_MASK_PMAP_ANIM 0x1a206d02L +#define PLANET07_SML_MASK_PMAP_ANIM 0x1a206e02L +#define PLANET08_BIG_MASK_PMAP_ANIM 0x1a406f02L +#define PLANET08_MED_MASK_PMAP_ANIM 0x1a407002L +#define PLANET08_SML_MASK_PMAP_ANIM 0x1a407102L +#define PLANET09_BIG_MASK_PMAP_ANIM 0x1a607202L +#define PLANET09_MED_MASK_PMAP_ANIM 0x1a607302L +#define PLANET09_SML_MASK_PMAP_ANIM 0x1a607402L +#define PLANET10_BIG_MASK_PMAP_ANIM 0x1a807502L +#define PLANET10_MED_MASK_PMAP_ANIM 0x1a807602L +#define PLANET10_SML_MASK_PMAP_ANIM 0x1a807702L +#define PLANET11_BIG_MASK_PMAP_ANIM 0x1aa07802L +#define PLANET11_MED_MASK_PMAP_ANIM 0x1aa07902L +#define PLANET11_SML_MASK_PMAP_ANIM 0x1aa07a02L +#define PLANET12_BIG_MASK_PMAP_ANIM 0x1ac07b02L +#define PLANET12_MED_MASK_PMAP_ANIM 0x1ac07c02L +#define PLANET12_SML_MASK_PMAP_ANIM 0x1ac07d02L +#define PLANET13_BIG_MASK_PMAP_ANIM 0x1ae07e02L +#define PLANET13_MED_MASK_PMAP_ANIM 0x1ae07f02L +#define PLANET13_SML_MASK_PMAP_ANIM 0x1ae08002L +#define PLANET14_BIG_MASK_PMAP_ANIM 0x1b008102L +#define PLANET14_MED_MASK_PMAP_ANIM 0x1b008202L +#define PLANET14_SML_MASK_PMAP_ANIM 0x1b008302L +#define PLANET15_BIG_MASK_PMAP_ANIM 0x1b208402L +#define PLANET15_MED_MASK_PMAP_ANIM 0x1b208502L +#define PLANET15_SML_MASK_PMAP_ANIM 0x1b208602L +#define PLANET16_BIG_MASK_PMAP_ANIM 0x1b408702L +#define PLANET16_MED_MASK_PMAP_ANIM 0x1b408802L +#define PLANET16_SML_MASK_PMAP_ANIM 0x1b408902L +#define PLANET17_BIG_MASK_PMAP_ANIM 0x1b608a02L +#define PLANET17_MED_MASK_PMAP_ANIM 0x1b608b02L +#define PLANET17_SML_MASK_PMAP_ANIM 0x1b608c02L +#define PLANET18_BIG_MASK_PMAP_ANIM 0x1b808d02L +#define PLANET18_MED_MASK_PMAP_ANIM 0x1b808e02L +#define PLANET18_SML_MASK_PMAP_ANIM 0x1b808f02L +#define PLANET19_BIG_MASK_PMAP_ANIM 0x1ba09002L +#define PLANET19_MED_MASK_PMAP_ANIM 0x1ba09102L +#define PLANET19_SML_MASK_PMAP_ANIM 0x1ba09202L +#define PLANET20_BIG_MASK_PMAP_ANIM 0x1bc09302L +#define PLANET20_MED_MASK_PMAP_ANIM 0x1bc09402L +#define PLANET20_SML_MASK_PMAP_ANIM 0x1bc09502L +#define PLANET21_BIG_MASK_PMAP_ANIM 0x1be09602L +#define PLANET21_MED_MASK_PMAP_ANIM 0x1be09702L +#define PLANET21_SML_MASK_PMAP_ANIM 0x1be09802L +#define PLANET22_BIG_MASK_PMAP_ANIM 0x1c009902L +#define PLANET22_MED_MASK_PMAP_ANIM 0x1c009a02L +#define PLANET22_SML_MASK_PMAP_ANIM 0x1c009b02L +#define PLANET23_BIG_MASK_PMAP_ANIM 0x1c209c02L +#define PLANET23_MED_MASK_PMAP_ANIM 0x1c209d02L +#define PLANET23_SML_MASK_PMAP_ANIM 0x1c209e02L +#define PLANET24_BIG_MASK_PMAP_ANIM 0x1c409f02L +#define PLANET24_MED_MASK_PMAP_ANIM 0x1c40a002L +#define PLANET24_SML_MASK_PMAP_ANIM 0x1c40a102L +#define PLANET25_BIG_MASK_PMAP_ANIM 0x1c60a202L +#define PLANET25_MED_MASK_PMAP_ANIM 0x1c60a302L +#define PLANET25_SML_MASK_PMAP_ANIM 0x1c60a402L +#define PLANET26_BIG_MASK_PMAP_ANIM 0x1c80a502L +#define PLANET26_MED_MASK_PMAP_ANIM 0x1c80a602L +#define PLANET26_SML_MASK_PMAP_ANIM 0x1c80a702L +#define PLANET27_BIG_MASK_PMAP_ANIM 0x1ca0a802L +#define PLANET27_MED_MASK_PMAP_ANIM 0x1ca0a902L +#define PLANET27_SML_MASK_PMAP_ANIM 0x1ca0aa02L +#define PLANET28_BIG_MASK_PMAP_ANIM 0x1cc0ab02L +#define PLANET28_MED_MASK_PMAP_ANIM 0x1cc0ac02L +#define PLANET28_SML_MASK_PMAP_ANIM 0x1cc0ad02L +#define PLANET29_BIG_MASK_PMAP_ANIM 0x1ce0ae02L +#define PLANET29_MED_MASK_PMAP_ANIM 0x1ce0af02L +#define PLANET29_SML_MASK_PMAP_ANIM 0x1ce0b002L +#define PLANET30_BIG_MASK_PMAP_ANIM 0x1d00b102L +#define PLANET30_MED_MASK_PMAP_ANIM 0x1d00b202L +#define PLANET30_SML_MASK_PMAP_ANIM 0x1d00b302L +#define PLANET31_BIG_MASK_PMAP_ANIM 0x1d20b402L +#define PLANET31_MED_MASK_PMAP_ANIM 0x1d20b502L +#define PLANET31_SML_MASK_PMAP_ANIM 0x1d20b602L +#define PLANET32_BIG_MASK_PMAP_ANIM 0x1d40b702L +#define PLANET32_MED_MASK_PMAP_ANIM 0x1d40b802L +#define PLANET32_SML_MASK_PMAP_ANIM 0x1d40b902L +#define PLANET33_BIG_MASK_PMAP_ANIM 0x1d60ba02L +#define PLANET33_MED_MASK_PMAP_ANIM 0x1d60bb02L +#define PLANET33_SML_MASK_PMAP_ANIM 0x1d60bc02L +#define PLANET34_BIG_MASK_PMAP_ANIM 0x1d80bd02L +#define PLANET34_MED_MASK_PMAP_ANIM 0x1d80be02L +#define PLANET34_SML_MASK_PMAP_ANIM 0x1d80bf02L +#define PLANET35_BIG_MASK_PMAP_ANIM 0x1da0c002L +#define PLANET35_MED_MASK_PMAP_ANIM 0x1da0c102L +#define PLANET35_SML_MASK_PMAP_ANIM 0x1da0c202L +#define PLANET36_BIG_MASK_PMAP_ANIM 0x1dc0c302L +#define PLANET36_MED_MASK_PMAP_ANIM 0x1dc0c402L +#define PLANET36_SML_MASK_PMAP_ANIM 0x1dc0c502L +#define PLANET37_BIG_MASK_PMAP_ANIM 0x1de0c602L +#define PLANET37_MED_MASK_PMAP_ANIM 0x1de0c702L +#define PLANET37_SML_MASK_PMAP_ANIM 0x1de0c802L +#define PLANET38_BIG_MASK_PMAP_ANIM 0x1e00c902L +#define PLANET38_MED_MASK_PMAP_ANIM 0x1e00ca02L +#define PLANET38_SML_MASK_PMAP_ANIM 0x1e00cb02L +#define PLANET39_BIG_MASK_PMAP_ANIM 0x1e20cc02L +#define PLANET39_MED_MASK_PMAP_ANIM 0x1e20cd02L +#define PLANET39_SML_MASK_PMAP_ANIM 0x1e20ce02L +#define PLANET40_BIG_MASK_PMAP_ANIM 0x1e40cf02L +#define PLANET40_MED_MASK_PMAP_ANIM 0x1e40d002L +#define PLANET40_SML_MASK_PMAP_ANIM 0x1e40d102L +#define PLANET41_BIG_MASK_PMAP_ANIM 0x1e60d202L +#define PLANET41_MED_MASK_PMAP_ANIM 0x1e60d302L +#define PLANET41_SML_MASK_PMAP_ANIM 0x1e60d402L +#define PLANET42_BIG_MASK_PMAP_ANIM 0x1e80d502L +#define PLANET42_MED_MASK_PMAP_ANIM 0x1e80d602L +#define PLANET42_SML_MASK_PMAP_ANIM 0x1e80d702L +#define PLANET43_BIG_MASK_PMAP_ANIM 0x1ea0d802L +#define PLANET43_MED_MASK_PMAP_ANIM 0x1ea0d902L +#define PLANET43_SML_MASK_PMAP_ANIM 0x1ea0da02L +#define PLANET44_BIG_MASK_PMAP_ANIM 0x1ec0db02L +#define PLANET44_MED_MASK_PMAP_ANIM 0x1ec0dc02L +#define PLANET44_SML_MASK_PMAP_ANIM 0x1ec0dd02L +#define PLANET45_BIG_MASK_PMAP_ANIM 0x1ee0de02L +#define PLANET45_MED_MASK_PMAP_ANIM 0x1ee0df02L +#define PLANET45_SML_MASK_PMAP_ANIM 0x1ee0e002L +#define PLANET46_BIG_MASK_PMAP_ANIM 0x1f00e102L +#define PLANET46_MED_MASK_PMAP_ANIM 0x1f00e202L +#define PLANET46_SML_MASK_PMAP_ANIM 0x1f00e302L +#define PLANET47_BIG_MASK_PMAP_ANIM 0x1f20e402L +#define PLANET47_MED_MASK_PMAP_ANIM 0x1f20e502L +#define PLANET47_SML_MASK_PMAP_ANIM 0x1f20e602L +#define PLANET48_BIG_MASK_PMAP_ANIM 0x1f40e702L +#define PLANET48_MED_MASK_PMAP_ANIM 0x1f40e802L +#define PLANET48_SML_MASK_PMAP_ANIM 0x1f40e902L +#define PLANET49_BIG_MASK_PMAP_ANIM 0x1f60ea02L +#define PLANET49_MED_MASK_PMAP_ANIM 0x1f60eb02L +#define PLANET49_SML_MASK_PMAP_ANIM 0x1f60ec02L +#define PLANET50_BIG_MASK_PMAP_ANIM 0x1f80ed02L +#define PLANET50_MED_MASK_PMAP_ANIM 0x1f80ee02L +#define PLANET50_SML_MASK_PMAP_ANIM 0x1f80ef02L +#define PLANET51_BIG_MASK_PMAP_ANIM 0x1fa0f002L +#define PLANET51_MED_MASK_PMAP_ANIM 0x1fa0f102L +#define PLANET51_SML_MASK_PMAP_ANIM 0x1fa0f202L +#define PLANET52_BIG_MASK_PMAP_ANIM 0x1fc0f302L +#define PLANET52_MED_MASK_PMAP_ANIM 0x1fc0f402L +#define PLANET52_SML_MASK_PMAP_ANIM 0x1fc0f502L +#define PLANET53_BIG_MASK_PMAP_ANIM 0x1fe0f602L +#define PLANET53_MED_MASK_PMAP_ANIM 0x1fe0f702L +#define PLANET53_SML_MASK_PMAP_ANIM 0x1fe0f802L +#define PLANET54_BIG_MASK_PMAP_ANIM 0x2000f902L +#define PLANET54_MED_MASK_PMAP_ANIM 0x2000fa02L +#define PLANET54_SML_MASK_PMAP_ANIM 0x2000fb02L +#define PLANET55_BIG_MASK_PMAP_ANIM 0x2020fc02L +#define PLANET55_MED_MASK_PMAP_ANIM 0x2020fd02L +#define PLANET55_SML_MASK_PMAP_ANIM 0x2020fe02L +#define PLANET56_BIG_MASK_PMAP_ANIM 0x2040ff02L +#define PLANET56_MED_MASK_PMAP_ANIM 0x20410002L +#define PLANET56_SML_MASK_PMAP_ANIM 0x20410102L +#define PLANET57_BIG_MASK_PMAP_ANIM 0x20610202L +#define PLANET57_MED_MASK_PMAP_ANIM 0x20610302L +#define PLANET57_SML_MASK_PMAP_ANIM 0x20610402L +#define PLANET58_BIG_MASK_PMAP_ANIM 0x20810502L +#define PLANET58_MED_MASK_PMAP_ANIM 0x20810602L +#define PLANET58_SML_MASK_PMAP_ANIM 0x20810702L +#define CREDIT00_ANIM 0x20c10802L +#define CREDIT01_ANIM 0x20e10902L +#define CREDIT02_ANIM 0x21010a02L +#define CREDIT03_ANIM 0x21210b02L +#define CREDIT04_ANIM 0x21410c02L +#define CREDIT05_ANIM 0x21610d02L +#define CREDIT06_ANIM 0x21810e02L +#define CREDIT07_ANIM 0x21a10f02L +#define CREDIT08_ANIM 0x21c11002L +#define CREDIT09_ANIM 0x21e11102L +#define CREDIT10_ANIM 0x22011202L +#define CREDIT11_ANIM 0x22211302L +#define CREDIT12_ANIM 0x22411402L +#define CREDIT13_ANIM 0x22611502L +#define CREDIT14_ANIM 0x22811602L +#define CREDIT15_ANIM 0x22a11702L +#define CREDIT16_ANIM 0x22c11802L +#define CREDIT17_ANIM 0x22e11902L +#define CREDIT18_ANIM 0x23011a02L +#define CREDIT19_ANIM 0x23211b02L + + diff --git a/sc2/src/sc2code/ikey_con.h b/sc2/src/sc2code/ikey_con.h new file mode 100644 index 000000000..703d117e7 --- /dev/null +++ b/sc2/src/sc2code/ikey_con.h @@ -0,0 +1,3 @@ +#define JOYSTICK_KEYS 0x00200001L + + diff --git a/sc2/src/sc2code/imusicre.h b/sc2/src/sc2code/imusicre.h new file mode 100644 index 000000000..9666f8819 --- /dev/null +++ b/sc2/src/sc2code/imusicre.h @@ -0,0 +1,16 @@ +#define HYPERSPACE_MUSIC 0x04c00006L +#define QUASISPACE_MUSIC 0x04e00106L +#define IP_MUSIC 0x13e00206L +#define ORBIT1_MUSIC 0x14000306L +#define ORBIT2_MUSIC 0x14000406L +#define ORBIT3_MUSIC 0x14000506L +#define ORBIT4_MUSIC 0x14000606L +#define ORBIT5_MUSIC 0x14000706L +#define REDALERT_MUSIC 0x14600806L +#define OUTFIT_MUSIC 0x18800906L +#define SHIPYARD_MUSIC 0x18c00a06L +#define STARBASE_MUSIC 0x18e00b06L +#define BATTLE_MUSIC 0x20a00c06L +#define CREDITS_MUSIC 0x23400d06L + + diff --git a/sc2/src/sc2code/init.c b/sc2/src/sc2code/init.c new file mode 100644 index 000000000..3bf80084e --- /dev/null +++ b/sc2/src/sc2code/init.c @@ -0,0 +1,267 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +FRAME stars_in_space, + asteroid[NUM_VIEWS], + blast[NUM_VIEWS], + explosion[NUM_VIEWS]; + +BOOLEAN +load_animation (PFRAME pixarray, DWORD big_res, DWORD med_res, DWORD + sml_res) +{ + DRAWABLE d; + + if ((d = LoadGraphic (big_res)) == (DRAWABLE)NULL_PTR) + return (FALSE); + pixarray[0] = CaptureDrawable (d); + + if (med_res != 0L && (d = LoadGraphic (med_res)) == (DRAWABLE)NULL_PTR) + return (FALSE); + pixarray[1] = CaptureDrawable (d); + + if (sml_res != 0L && (d = LoadGraphic (sml_res)) == (DRAWABLE)NULL_PTR) + return (FALSE); + pixarray[2] = CaptureDrawable (d); + + return (TRUE); +} + +BOOLEAN +free_image (PFRAME pixarray) +{ + BOOLEAN retval; + COUNT i; + + retval = TRUE; + for (i = 0; i < NUM_VIEWS; ++i) + { + if (pixarray[i] != (FRAME)NULL_PTR) + { + if (!DestroyDrawable (ReleaseDrawable (pixarray[i]))) + retval = FALSE; + pixarray[i] = (FRAME)NULL_PTR; + } + } + + return (retval); +} + +static BYTE space_ini_cnt; + +BOOLEAN +InitSpace (void) +{ + if (space_ini_cnt++ == 0 + && LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) + { + if ((stars_in_space = CaptureDrawable ( + LoadGraphic (STAR_MASK_PMAP_ANIM) + )) == 0) + return (FALSE); + + if (!load_animation (explosion, + BOOM_BIG_MASK_PMAP_ANIM, + BOOM_MED_MASK_PMAP_ANIM, + BOOM_SML_MASK_PMAP_ANIM)) + return (FALSE); + + if (!load_animation (blast, + BLAST_BIG_MASK_PMAP_ANIM, + BLAST_MED_MASK_PMAP_ANIM, + BLAST_SML_MASK_PMAP_ANIM)) + return (FALSE); + + if (!load_animation (asteroid, + ASTEROID_BIG_MASK_PMAP_ANIM, + ASTEROID_MED_MASK_PMAP_ANIM, + ASTEROID_SML_MASK_PMAP_ANIM)) + return (FALSE); + } + + return (TRUE); +} + +void +UninitSpace (void) +{ + if (space_ini_cnt && --space_ini_cnt == 0) + { + free_image (blast); + free_image (explosion); + free_image (asteroid); + + DestroyDrawable (ReleaseDrawable (stars_in_space)); + stars_in_space = 0; + } +} + +SIZE +InitShips (void) +{ + SIZE num_ships; + + InitSpace (); + + SetContext (StatusContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContext (SpaceContext); + + InitDisplayList (); + InitGalaxy (); + + num_ships = NUM_SIDES; + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + ReinitQueue (&race_q[0]); + ReinitQueue (&race_q[1]); + + Build (&race_q[0], SIS_RES_INDEX, GOOD_GUY, 0); + + LoadHyperspace (); + + --num_ships; + } + else + { + COUNT i; + RECT r; + + SetContextFGFrame (Screen); + r.corner.x = SAFE_X; + r.corner.y = SAFE_Y; + r.extent.width = SPACE_WIDTH; + r.extent.height = SPACE_HEIGHT; + SetContextClipRect (&r); + + SetContextBackGroundColor (BLACK_COLOR); + { + CONTEXT OldContext; + + OldContext = SetContext (ScreenContext); + + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContextBackGroundColor (BLACK_COLOR); + ClearDrawable (); + + SetContext (OldContext); + } + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + free_gravity_well (); + else + { +#define NUM_ASTEROIDS 5 + for (i = 0; i < NUM_ASTEROIDS; ++i) + spawn_asteroid (NULL_PTR); +#define NUM_PLANETS 1 + for (i = 0; i < NUM_PLANETS; ++i) + spawn_planet (); + } + } + + FlushInput (); + + return (num_ships); +} + +void +UninitShips (void) +{ + BYTE crew_retrieved; + SIZE i; + HELEMENT hElement, hNextElement; + STARSHIPPTR SPtr[NUM_PLAYERS]; + + StopSound (); + + UninitSpace (); + + for (i = 0; i < NUM_PLAYERS; ++i) + SPtr[i] = 0; + + crew_retrieved = 0; + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + extern void new_ship (PELEMENT ElementPtr); + + LockElement (hElement, &ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + if (ElementPtr->state_flags & CREW_OBJECT) + ++crew_retrieved; + else if ((ElementPtr->state_flags & PLAYER_SHIP) + || ElementPtr->death_func == new_ship) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->ShipFacing = + StarShipPtr->RaceDescPtr->ship_info.var2; + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->ship_info.crew_level; + SPtr[WHICH_SIDE (ElementPtr->state_flags)] = StarShipPtr; + free_ship (StarShipPtr, TRUE); + } + UnlockElement (hElement); + } + + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + } + else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER + && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + for (i = NUM_PLAYERS - 1; i >= 0; --i) + { + if (SPtr[i]) + { + if (SPtr[i]->special_counter) + SPtr[i]->special_counter += crew_retrieved; + + GetEncounterStarShip (SPtr[i], i); + } + } + } + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER) + { + ReinitQueue (&race_q[0]); + ReinitQueue (&race_q[1]); + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + FreeHyperspace (); + } +} + +void +InitGlobData (void) +{ + COUNT i; + + i = GLOBAL (glob_flags); + memset ((PBYTE)&GlobData, 0, sizeof (GlobData)); + GLOBAL (glob_flags) = (BYTE)i; + + GLOBAL (DisplayArray) = DisplayArray; +} diff --git a/sc2/src/sc2code/intel.c b/sc2/src/sc2code/intel.c new file mode 100644 index 000000000..1ea6cfc19 --- /dev/null +++ b/sc2/src/sc2code/intel.c @@ -0,0 +1,53 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +SIZE cur_player; + +INPUT_STATE +computer_intelligence (INPUT_REF InputRef, INPUT_STATE InputState) +{ + if (InputState || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + return (InputState); + + if (CyborgDescPtr) + { + if (PlayerControl[cur_player] & CYBORG_CONTROL) + InputState = tactical_intelligence (); + else + InputState = GetInputState (CombinedInput[cur_player]); + } + else if (!(PlayerControl[cur_player] & PSYTRON_CONTROL)) + InputState = 0; + else + { + switch (LOBYTE (GLOBAL (CurrentActivity))) + { + case SUPER_MELEE: + { + SleepTask (GetTimeCounter () + (ONE_SECOND >> 1)); + InputState = DEVICE_BUTTON1; /* pick a random ship */ + break; + } + } + } + (void) InputRef; /* Satisfying compiler (unused parameter) */ + return (InputState); +} + diff --git a/sc2/src/sc2code/intel.h b/sc2/src/sc2code/intel.h new file mode 100644 index 000000000..f79b00d6f --- /dev/null +++ b/sc2/src/sc2code/intel.h @@ -0,0 +1,76 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _INTEL_H +#define _INTEL_H + +typedef enum +{ + PURSUE = 0, + AVOID, + ENTICE, + NO_MOVEMENT +} MOVEMENT_STATE; + +typedef struct +{ + PELEMENT ObjectPtr; + COUNT facing, which_turn; + MOVEMENT_STATE MoveState; +} EVALUATE_DESC; +typedef EVALUATE_DESC *PEVALUATE_DESC; +#define EVALUATE_DESCPTR PEVALUATE_DESC + +#define MANEUVERABILITY(pi) ((pi)->ManeuverabilityIndex) +#define WEAPON_RANGE(pi) ((pi)->WeaponRange) + +#define WORLD_TO_TURN(d) ((d)>>6) + +#define CLOSE_RANGE_WEAPON DISPLAY_TO_WORLD (50) +#define LONG_RANGE_WEAPON DISPLAY_TO_WORLD (1000) +#define FAST_SHIP 150 +#define MEDIUM_SHIP 45 +#define SLOW_SHIP 25 + +enum +{ + ENEMY_SHIP_INDEX = 0, + CREW_OBJECT_INDEX, + ENEMY_WEAPON_INDEX, + GRAVITY_MASS_INDEX, + FIRST_EMPTY_INDEX +}; + +extern STARSHIPPTR CyborgDescPtr; + +extern INPUT_STATE computer_intelligence (INPUT_REF InputRef, INPUT_STATE + InputState); +extern INPUT_STATE tactical_intelligence (void); +extern void ship_intelligence (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR + ObjectsOfConcern, COUNT ConcernCounter); +extern BOOLEAN ship_weapons (ELEMENTPTR ShipPtr, ELEMENTPTR OtherPtr, + COUNT margin_of_error); + +extern void Pursue (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); +extern void Entice (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); +extern void Avoid (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); +extern BOOLEAN TurnShip (ELEMENTPTR ShipPtr, COUNT angle); +extern BOOLEAN ThrustShip (ELEMENTPTR ShipPtr, COUNT angle); + +#endif /* _INTEL_H */ + diff --git a/sc2/src/sc2code/intro.c b/sc2/src/sc2code/intro.c new file mode 100644 index 000000000..e21b76f69 --- /dev/null +++ b/sc2/src/sc2code/intro.c @@ -0,0 +1,95 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "libs/vidlib.h" + +//Added by Chris + +BOOLEAN InitGameKernel (void); + +void LoadMasterShipList (void); + +//End Added by Chris + +void +DoFMV (char *name, char *loopname) +{ + VidPlay((MEM_HANDLE)name, loopname,FALSE); + while(VidPlaying ()) + ; + VidStop(); +} +/* //Already defined in fmv.c +void +Introduction (void) +{ + BYTE xform_buf[1]; + STAMP s; + DWORD TimeOut; + INPUT_STATE InputState; + + xform_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)xform_buf, 1)); + SetSemaphore (&GraphicsSem); + SetContext (ScreenContext); + s.origin.x = s.origin.y = 0; + s.frame = CaptureDrawable (LoadGraphic (TITLE_ANIM)); + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + ClearSemaphore (&GraphicsSem); + + FlushInput (); + + xform_buf[0] = FadeAllToColor; + TimeOut = XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2); + LoadMasterShipList (); + SleepTask (TimeOut); + + GLOBAL (CurrentActivity) |= CHECK_ABORT; + TimeOut += ONE_SECOND * 3; + while (!(InputState = AnyButtonPress (FALSE)) && TaskSwitch () <= TimeOut) + ; + GLOBAL (CurrentActivity) &= ~CHECK_ABORT; + xform_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); + + if (InputState == 0) + DoFMV ("intro", NULL); + + InitGameKernel (); +} +*/ + +/* //Already defined in fmv.c +void +Victory (void) +{ + BYTE xform_buf[1]; + + xform_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); + + DoFMV ("victory", NULL); + + InitGameKernel (); +} +*/ + + + diff --git a/sc2/src/sc2code/ipdisp.c b/sc2/src/sc2code/ipdisp.c new file mode 100644 index 000000000..fc4dd9a4e --- /dev/null +++ b/sc2/src/sc2code/ipdisp.c @@ -0,0 +1,849 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +NotifyOthers (COUNT which_race, BYTE target_loc) +{ + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + hStarShip; hStarShip = hNextShip) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + if (GET_RACE_ID (StarShipPtr) == which_race) + { + BYTE task; + + task = GET_GROUP_MISSION (StarShipPtr) | IGNORE_FLAGSHIP; + + if (target_loc == 0) + { + task &= ~IGNORE_FLAGSHIP; + SET_ORBIT_LOC (StarShipPtr, GET_GROUP_DEST (StarShipPtr)); +/* task = FLEE | IGNORE_FLAGSHIP; */ + } + else if ((target_loc = GET_GROUP_DEST (StarShipPtr)) == 0) + { + target_loc = GET_ORBIT_LOC (StarShipPtr); + SET_ORBIT_LOC (StarShipPtr, NORMALIZE_FACING (Random ())); +#ifdef OLD + target_loc = (BYTE)(( + (COUNT)Random () + % pSolarSysState->SunDesc[0].NumPlanets + ) + 1); +#endif /* OLD */ + if (!(task & REFORM_GROUP)) + { + if ((task & ~IGNORE_FLAGSHIP) != EXPLORE) + StarShipPtr->ShipInfo.group_counter = 0; + else + StarShipPtr->ShipInfo.group_counter = + ((COUNT)Random () + % MAX_REVOLUTIONS) + << FACING_SHIFT; + } + } + + SET_GROUP_MISSION (StarShipPtr, task); + SET_GROUP_DEST (StarShipPtr, target_loc); + } + + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } +} + +static void +ip_group_preprocess (PELEMENT ElementPtr) +{ +#define TRACK_WAIT 5 + BYTE task; + BYTE target_loc, group_loc, flagship_loc; + SIZE radius; + POINT dest_pt; + SIZE vdx, vdy; + register ELEMENTPTR EPtr; + SHIP_FRAGMENTPTR StarShipPtr; + + EPtr = (ELEMENTPTR)ElementPtr; + EPtr->state_flags &= + ~(DISAPPEARING | NONSOLID); /* "I'm not quite dead." */ + ++EPtr->life_span; /* so that it will 'die' + * again next time. + */ + GetElementStarShip (EPtr, &StarShipPtr); + group_loc = GET_GROUP_LOC (StarShipPtr); + /* save old location */ + DisplayArray[EPtr->PrimIndex].Object.Point = StarShipPtr->ShipInfo.loc; + + if (group_loc != 0) + radius = MAX_ZOOM_RADIUS; + else + radius = pSolarSysState->SunDesc[0].radius; + + dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.x + * (DISPLAY_FACTOR >> 1) / radius); + dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.y + * (DISPLAY_FACTOR >> 1) / radius); + EPtr->current.location.x = DISPLAY_TO_WORLD (dest_pt.x) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + EPtr->current.location.y = DISPLAY_TO_WORLD (dest_pt.y) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + + InitIntersectStartPoint (EPtr); + + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + flagship_loc = 0; + else + flagship_loc = (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc + 1); + + task = GET_GROUP_MISSION (StarShipPtr); + if (pSolarSysState->MenuState.CurState) + goto ExitIPProcess; + + if ((task & REFORM_GROUP) + && --StarShipPtr->ShipInfo.group_counter == 0) + { + task &= ~REFORM_GROUP; + SET_GROUP_MISSION (StarShipPtr, task); + if ((task & ~IGNORE_FLAGSHIP) != EXPLORE) + StarShipPtr->ShipInfo.group_counter = 0; + else + StarShipPtr->ShipInfo.group_counter = + ((COUNT)Random () + % MAX_REVOLUTIONS) + << FACING_SHIFT; + } + + if (!(task & REFORM_GROUP) + && (task & ~(IGNORE_FLAGSHIP | REFORM_GROUP)) != FLEE) + { + if (EPtr->state_flags & BAD_GUY) + EPtr->state_flags &= ~GOOD_GUY; + else + EPtr->state_flags |= BAD_GUY; + } + + target_loc = GET_GROUP_DEST (StarShipPtr); + if (!(task & (IGNORE_FLAGSHIP | REFORM_GROUP))) + { + if (target_loc == 0) + { + /* if intercepting flagship */ + target_loc = flagship_loc; + if (EPtr->thrust_wait > TRACK_WAIT) + { + EPtr->thrust_wait = 0; + ZeroVelocityComponents (&EPtr->velocity); + } + } + else if (group_loc == flagship_loc) + { + long detect_dist; + + detect_dist = 1200; + if (group_loc != 0) /* if in planetary views */ + { + detect_dist *= (MAX_ZOOM_RADIUS / MIN_ZOOM_RADIUS); + if (GET_RACE_ID (StarShipPtr) == URQUAN_PROBE_SHIP) + detect_dist <<= 1; + } + vdx = GLOBAL (ip_location.x) + - StarShipPtr->ShipInfo.loc.x; + vdy = GLOBAL (ip_location.y) + - StarShipPtr->ShipInfo.loc.y; + if ((long)vdx * vdx + + (long)vdy * vdy < (long)detect_dist * detect_dist) + { + EPtr->thrust_wait = 0; + ZeroVelocityComponents (&EPtr->velocity); + + NotifyOthers (GET_RACE_ID (StarShipPtr), 0); + task = GET_GROUP_MISSION (StarShipPtr); + if ((target_loc = GET_GROUP_DEST (StarShipPtr)) == 0) + target_loc = flagship_loc; + } + } + } + + GetCurrentVelocityComponents (&EPtr->velocity, &vdx, &vdy); + + task &= ~IGNORE_FLAGSHIP; + if (task <= ON_STATION) +#ifdef NEVER + if (task <= FLEE || (task == ON_STATION + && GET_GROUP_DEST (StarShipPtr) == 0)) +#endif /* NEVER */ + { + BOOLEAN Transition; + SIZE dx, dy; + SIZE delta_x, delta_y; + COUNT angle; + + Transition = FALSE; + if (task == FLEE) + { + dest_pt.x = StarShipPtr->ShipInfo.loc.x << 1; + dest_pt.y = StarShipPtr->ShipInfo.loc.y << 1; + } + else if (((task != ON_STATION || GET_GROUP_DEST (StarShipPtr) == 0) + && group_loc == target_loc) + || (task == ON_STATION + && GET_GROUP_DEST (StarShipPtr) + && group_loc == 0)) + { + if (GET_GROUP_DEST (StarShipPtr) == 0) + dest_pt = GLOBAL (ip_location); + else + { + COUNT orbit_dist; + POINT org; + + if (task != ON_STATION) + { + orbit_dist = ORBIT_RADIUS; + org.x = org.y = 0; + } + else + { + orbit_dist = STATION_RADIUS; + XFormIPLoc ( + &pSolarSysState->PlanetDesc[ + target_loc - 1 + ].image.origin, + &org, + FALSE + ); + } + + angle = FACING_TO_ANGLE (GET_ORBIT_LOC (StarShipPtr) + 1); + dest_pt.x = org.x + COSINE (angle, orbit_dist); + dest_pt.y = org.y + SINE (angle, orbit_dist); + if (StarShipPtr->ShipInfo.loc.x == dest_pt.x + && StarShipPtr->ShipInfo.loc.y == dest_pt.y) + { + BYTE next_loc; + + SET_ORBIT_LOC (StarShipPtr, + NORMALIZE_FACING (ANGLE_TO_FACING (angle))); + angle += FACING_TO_ANGLE (1); + dest_pt.x = org.x + COSINE (angle, orbit_dist); + dest_pt.y = org.y + SINE (angle, orbit_dist); + + EPtr->thrust_wait = (BYTE)~0; + if (StarShipPtr->ShipInfo.group_counter) + --StarShipPtr->ShipInfo.group_counter; + else if (task == EXPLORE + && (next_loc = (BYTE)(((COUNT)Random () + % pSolarSysState->SunDesc[0].NumPlanets) + + 1)) != target_loc) + { + EPtr->thrust_wait = 0; + SET_GROUP_DEST (StarShipPtr, target_loc = next_loc); + } + } + } + } + else if (group_loc == 0) + { + if (GET_GROUP_DEST (StarShipPtr) == 0) + dest_pt = pSolarSysState->SunDesc[0].location; + else + XFormIPLoc ( + &pSolarSysState->PlanetDesc[target_loc - 1].image.origin, + &dest_pt, + FALSE + ); + } + else + { + if (task == ON_STATION) + target_loc = 0; + + dest_pt.x = StarShipPtr->ShipInfo.loc.x << 1; + dest_pt.y = StarShipPtr->ShipInfo.loc.y << 1; + } + + delta_x = dest_pt.x - StarShipPtr->ShipInfo.loc.x; + delta_y = dest_pt.y - StarShipPtr->ShipInfo.loc.y; + angle = ARCTAN (delta_x, delta_y); + + if (EPtr->thrust_wait && EPtr->thrust_wait != (BYTE)~0) + --EPtr->thrust_wait; + else if ((vdx == 0 && vdy == 0) + || angle != GetVelocityTravelAngle (&EPtr->velocity)) + { + SIZE speed; + + if (EPtr->thrust_wait && GET_GROUP_DEST (StarShipPtr) != 0) + { +#define ORBIT_SPEED 60 + speed = ORBIT_SPEED; + if (task == ON_STATION) + speed >>= 1; + } + else + { + SIZE RaceIPSpeed[] = + { + RACE_IP_SPEED + }; + + speed = RaceIPSpeed[GET_RACE_ID (StarShipPtr)]; + EPtr->thrust_wait = TRACK_WAIT; + } + + SetVelocityComponents (&EPtr->velocity, + vdx = COSINE (angle, speed), + vdy = SINE (angle, speed)); + } + + dx = vdx, dy = vdy; + if (group_loc == target_loc) + { + if (target_loc == 0) + { + if (task == FLEE) + goto CheckGetAway; + } + else if (target_loc == GET_GROUP_DEST (StarShipPtr)) + { +PartialRevolution: + if ((long)((COUNT)(dx * dx) + (COUNT)(dy * dy)) + >= (long)delta_x * delta_x + (long)delta_y * delta_y) + { + StarShipPtr->ShipInfo.loc = dest_pt; + vdx = vdy = 0; + ZeroVelocityComponents (&EPtr->velocity); + } + } + } + else + { + if (group_loc == 0) + { + if (pSolarSysState->SunDesc[0].radius < MAX_ZOOM_RADIUS) + { + dx >>= 1; + dy >>= 1; + if (pSolarSysState->SunDesc[0].radius == MIN_ZOOM_RADIUS) + { + dx >>= 1; + dy >>= 1; + } + } + + if (task == ON_STATION + && GET_GROUP_DEST (StarShipPtr)) + goto PartialRevolution; + else if ((long)((COUNT)(dx * dx) + (COUNT)(dy * dy)) + >= (long)delta_x * delta_x + (long)delta_y * delta_y) + Transition = TRUE; + } + else + { +CheckGetAway: + dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.x + * (DISPLAY_FACTOR >> 1) / MAX_ZOOM_RADIUS); + dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.y + * (DISPLAY_FACTOR >> 1) / MAX_ZOOM_RADIUS); + if (dest_pt.x < 0 + || dest_pt.x >= SIS_SCREEN_WIDTH + || dest_pt.y < 0 + || dest_pt.y >= SIS_SCREEN_HEIGHT) + Transition = TRUE; + } + + if (Transition) + { + /* no collisions during transition */ + EPtr->state_flags |= NONSOLID; + + vdx = vdy = 0; + ZeroVelocityComponents (&EPtr->velocity); + if (group_loc != 0) + { + PPLANET_DESC pCurDesc; + + pCurDesc = &pSolarSysState->PlanetDesc[group_loc - 1]; + XFormIPLoc ( + &pCurDesc->image.origin, + &StarShipPtr->ShipInfo.loc, + FALSE + ); + SET_GROUP_LOC (StarShipPtr, group_loc = 0); + } + else if (target_loc == 0) + { + EPtr->life_span = 0; + EPtr->state_flags |= DISAPPEARING | NONSOLID; + StarShipPtr->ShipInfo.crew_level = 0; + return; + } + else + { + if (target_loc == GET_GROUP_DEST (StarShipPtr)) + { + SET_ORBIT_LOC (StarShipPtr, + NORMALIZE_FACING ( + ANGLE_TO_FACING (angle + HALF_CIRCLE) + )); + StarShipPtr->ShipInfo.group_counter = + ((COUNT)Random () % MAX_REVOLUTIONS) + << FACING_SHIFT; + } + + StarShipPtr->ShipInfo.loc.x = -(SIZE)((long)COSINE ( + angle, SIS_SCREEN_WIDTH * 9 / 16 + ) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); + StarShipPtr->ShipInfo.loc.y = -(SIZE)((long)SINE ( + angle, SIS_SCREEN_WIDTH * 9 / 16 + ) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); + + SET_GROUP_LOC (StarShipPtr, group_loc = target_loc); + } + } + } + } + + if (group_loc != 0) + radius = MAX_ZOOM_RADIUS; + else + { + radius = pSolarSysState->SunDesc[0].radius; + if (radius < MAX_ZOOM_RADIUS) + { + vdx >>= 1; + vdy >>= 1; + if (radius == MIN_ZOOM_RADIUS) + { + vdx >>= 1; + vdy >>= 1; + } + } + } + StarShipPtr->ShipInfo.loc.x += vdx; + StarShipPtr->ShipInfo.loc.y += vdy; + + dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.x + * (DISPLAY_FACTOR >> 1) / radius); + dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.y + * (DISPLAY_FACTOR >> 1) / radius); + +ExitIPProcess: + EPtr->next.location.x = DISPLAY_TO_WORLD (dest_pt.x) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + EPtr->next.location.y = DISPLAY_TO_WORLD (dest_pt.y) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + + if (group_loc != flagship_loc + || ((task & REFORM_GROUP) + && (StarShipPtr->ShipInfo.group_counter & 1))) + { + SetPrimType (&DisplayArray[EPtr->PrimIndex], NO_PRIM); + EPtr->state_flags |= NONSOLID; + } + else + { + SetPrimType (&DisplayArray[EPtr->PrimIndex], STAMP_PRIM); + if (task & REFORM_GROUP) + EPtr->state_flags |= NONSOLID; + } + + EPtr->state_flags |= CHANGING; +} + +static void +flag_ship_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT + ElementPtr1, PPOINT pPt1) +{ + if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) + || pSolarSysState->MenuState.CurState + || (ElementPtr1->state_flags & GOOD_GUY)) + return; + + if (!(ElementPtr1->state_flags & COLLISION)) /* not processed yet */ + ElementPtr0->state_flags |= COLLISION | NONSOLID; + else + { + ElementPtr1->state_flags &= ~COLLISION; + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +ip_group_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT + ElementPtr1, PPOINT pPt1) +{ + SHIP_FRAGMENTPTR StarShipPtr; + + if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) + || pSolarSysState->MenuState.CurState + || (ElementPtr0->state_flags & GOOD_GUY)) + { + ElementPtr0->state_flags &= ~BAD_GUY; + return; + } + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (ElementPtr0->state_flags & ElementPtr1->state_flags & BAD_GUY) + { + if ((ElementPtr0->state_flags & COLLISION) + || (ElementPtr1->current.location.x == ElementPtr1->next.location.x + && ElementPtr1->current.location.y == ElementPtr1->next.location.y)) + ElementPtr0->state_flags &= ~COLLISION; + else + { + ElementPtr1->state_flags |= COLLISION; + + StarShipPtr->ShipInfo.loc = + DisplayArray[ElementPtr0->PrimIndex].Object.Point; + ElementPtr0->next.location = ElementPtr0->current.location; + InitIntersectEndPoint (ElementPtr0); + } + } + else + { + battle_counter = (SIZE)GET_GROUP_ID (StarShipPtr); + + if (GET_RACE_ID (StarShipPtr) == URQUAN_PROBE_SHIP) + { + SET_GROUP_MISSION (StarShipPtr, FLEE | IGNORE_FLAGSHIP); + SET_GROUP_DEST (StarShipPtr, 0); + } + else + { + SET_GROUP_MISSION (StarShipPtr, + GET_GROUP_MISSION (StarShipPtr) | REFORM_GROUP); + StarShipPtr->ShipInfo.group_counter = 100; + NotifyOthers (GET_RACE_ID (StarShipPtr), (BYTE)~0); + } + + if (!(ElementPtr1->state_flags & COLLISION)) /* not processed yet */ + ElementPtr0->state_flags |= COLLISION | NONSOLID; + else + { + ElementPtr1->state_flags &= ~COLLISION; + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + } + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +spawn_ip_group (SHIP_FRAGMENTPTR StarShipPtr) +{ + HELEMENT hIPSHIPElement; + + hIPSHIPElement = AllocElement (); + if (hIPSHIPElement) + { + BYTE task; + ELEMENTPTR IPSHIPElementPtr; + + LockElement (hIPSHIPElement, &IPSHIPElementPtr); + IPSHIPElementPtr->turn_wait = GET_GROUP_ID (StarShipPtr); + IPSHIPElementPtr->mass_points = 1; + IPSHIPElementPtr->hit_points = 1; + IPSHIPElementPtr->state_flags = + CHANGING | FINITE_LIFE | IGNORE_VELOCITY; + + task = GET_GROUP_MISSION (StarShipPtr); + if (!(task & IGNORE_FLAGSHIP)) + IPSHIPElementPtr->state_flags |= BAD_GUY; + else + { + IPSHIPElementPtr->state_flags |= GOOD_GUY; + if (GET_RACE_ID (StarShipPtr) == YEHAT_SHIP + && GET_GAME_STATE (YEHAT_CIVIL_WAR)) + { + SET_GROUP_MISSION (StarShipPtr, FLEE | (task & REFORM_GROUP)); + SET_GROUP_DEST (StarShipPtr, 0); + } + } + + SetPrimType (&DisplayArray[IPSHIPElementPtr->PrimIndex], STAMP_PRIM); + IPSHIPElementPtr->current.image.farray = + &StarShipPtr->ShipInfo.melee_icon; + IPSHIPElementPtr->current.image.frame = + SetAbsFrameIndex (StarShipPtr->ShipInfo.melee_icon, 1); + /* preprocessing has a side effect + * we wish to avoid. So death_func + * is used instead, but will achieve + * same result without the side + * effect (InitIntersectFrame) + */ + IPSHIPElementPtr->death_func = ip_group_preprocess; + IPSHIPElementPtr->collision_func = ip_group_collision; + + { + SIZE radius; + POINT pt; + + if (GET_GROUP_LOC (StarShipPtr) != 0) + radius = MAX_ZOOM_RADIUS; + else + radius = pSolarSysState->SunDesc[0].radius; + + pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.x + * DISPLAY_FACTOR / radius); + pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)StarShipPtr->ShipInfo.loc.y + * (DISPLAY_FACTOR >> 1) / radius); + + IPSHIPElementPtr->current.location.x = + DISPLAY_TO_WORLD (pt.x) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + IPSHIPElementPtr->current.location.y = + DISPLAY_TO_WORLD (pt.y) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + } + + SetElementStarShip (IPSHIPElementPtr, StarShipPtr); + + SetUpElement (IPSHIPElementPtr); + IPSHIPElementPtr->IntersectControl.IntersectStamp.frame = + DecFrameIndex (stars_in_space); + + UnlockElement (hIPSHIPElement); + + PutElement (hIPSHIPElement); + } +} + +#define FLIP_WAIT 42 + +static void +flag_ship_preprocess (PELEMENT ElementPtr) +{ + if (--ElementPtr->thrust_wait == 0) + /* juggle list after flagship */ + { + HELEMENT hSuccElement; + + if ((hSuccElement = GetSuccElement (ElementPtr)) + && hSuccElement != GetTailElement ()) + { + HELEMENT hPredElement; + ELEMENTPTR TailPtr; + + LockElement (GetTailElement (), &TailPtr); + hPredElement = _GetPredLink (TailPtr); + UnlockElement (GetTailElement ()); + + RemoveElement (hSuccElement); + PutElement (hSuccElement); + } + + ElementPtr->thrust_wait = FLIP_WAIT; + } + + if (pSolarSysState->MenuState.CurState == 0) + { + BYTE flagship_loc, ec; + SIZE vdx, vdy, radius; + POINT pt; + + GetCurrentVelocityComponents ( + &GLOBAL (velocity), &vdx, &vdy + ); + + if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) + { + flagship_loc = (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc + 2); + radius = MAX_ZOOM_RADIUS; + } + else + { + flagship_loc = 1; + radius = pSolarSysState->SunDesc[0].radius; + if (radius < MAX_ZOOM_RADIUS) + { + vdx >>= 1; + vdy >>= 1; + if (radius == MIN_ZOOM_RADIUS) + { + vdx >>= 1; + vdy >>= 1; + } + } + } + + pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)GLOBAL (ip_location.x) + * (DISPLAY_FACTOR >> 1) / radius); + pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)GLOBAL (ip_location.y) + * (DISPLAY_FACTOR >> 1) / radius); + ElementPtr->current.location.x = DISPLAY_TO_WORLD (pt.x) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + ElementPtr->current.location.y = DISPLAY_TO_WORLD (pt.y) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + InitIntersectStartPoint (ElementPtr); + + GLOBAL (ip_location.x) += vdx; + GLOBAL (ip_location.y) += vdy; + + pt.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)GLOBAL (ip_location.x) + * (DISPLAY_FACTOR >> 1) / radius); + pt.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)GLOBAL (ip_location.y) + * (DISPLAY_FACTOR >> 1) / radius); + ElementPtr->next.location.x = DISPLAY_TO_WORLD (pt.x) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + ElementPtr->next.location.y = DISPLAY_TO_WORLD (pt.y) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + + GLOBAL (ShipStamp.origin) = pt; + ElementPtr->next.image.frame = GLOBAL (ShipStamp.frame); + + if (ElementPtr->mass_points == flagship_loc) + { + if (ElementPtr->state_flags & NONSOLID) + ElementPtr->state_flags &= ~NONSOLID; + } + else /* no collisions during transition */ + { + ElementPtr->state_flags |= NONSOLID; + ElementPtr->mass_points = flagship_loc; + } + + if ((ec = GET_GAME_STATE (ESCAPE_COUNTER)) + && !(GLOBAL (CurrentActivity) & START_ENCOUNTER)) + { + ElementPtr->state_flags |= NONSOLID; + + --ec; + SET_GAME_STATE (ESCAPE_COUNTER, ec); + } + + ElementPtr->state_flags |= CHANGING; + } +} + +static void +spawn_flag_ship (void) +{ + HELEMENT hFlagShipElement; + + hFlagShipElement = AllocElement (); + if (hFlagShipElement) + { + ELEMENTPTR FlagShipElementPtr; + + LockElement (hFlagShipElement, &FlagShipElementPtr); + FlagShipElementPtr->hit_points = 1; + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + FlagShipElementPtr->mass_points = 1; + else + FlagShipElementPtr->mass_points = + (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc + 2); + FlagShipElementPtr->state_flags = + APPEARING | GOOD_GUY | IGNORE_VELOCITY; + if (GET_GAME_STATE (ESCAPE_COUNTER)) + FlagShipElementPtr->state_flags |= NONSOLID; + FlagShipElementPtr->life_span = NORMAL_LIFE; + FlagShipElementPtr->thrust_wait = FLIP_WAIT; + SetPrimType (&DisplayArray[FlagShipElementPtr->PrimIndex], STAMP_PRIM); + FlagShipElementPtr->current.image.farray = + &GLOBAL (ShipStamp.frame); + FlagShipElementPtr->current.image.frame = + GLOBAL (ShipStamp.frame); + FlagShipElementPtr->preprocess_func = flag_ship_preprocess; + FlagShipElementPtr->collision_func = flag_ship_collision; + + FlagShipElementPtr->current.location.x = + DISPLAY_TO_WORLD (GLOBAL (ShipStamp.origin.x)) + + (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); + FlagShipElementPtr->current.location.y = + DISPLAY_TO_WORLD (GLOBAL (ShipStamp.origin.y)) + + (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); + + UnlockElement (hFlagShipElement); + + PutElement (hFlagShipElement); + } +} + +void +DoMissions (void) +{ + HSTARSHIP hStarShip, hNextShip; + + spawn_flag_ship (); + + if (battle_counter) + { + NotifyOthers ((COUNT)(battle_counter - 1), 0); + battle_counter = 0; + } + + for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + hStarShip; hStarShip = hNextShip) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + if (StarShipPtr->ShipInfo.crew_level) + spawn_ip_group (StarShipPtr); + + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } +} + diff --git a/sc2/src/sc2code/ires_ind.h b/sc2/src/sc2code/ires_ind.h new file mode 100644 index 000000000..f7d3eddd7 --- /dev/null +++ b/sc2/src/sc2code/ires_ind.h @@ -0,0 +1,54 @@ +#define ARILOU_SHIP_INDEX 0x00600007L +#define CHMMR_SHIP_INDEX 0x00800107L +#define EARTHLING_SHIP_INDEX 0x00a00207L +#define ORZ_SHIP_INDEX 0x00c00307L +#define PKUNK_SHIP_INDEX 0x00e00407L +#define SHOFIXTI_SHIP_INDEX 0x01000507L +#define SPATHI_SHIP_INDEX 0x01200607L +#define SUPOX_SHIP_INDEX 0x01400707L +#define THRADD_SHIP_INDEX 0x01600807L +#define UTWIG_SHIP_INDEX 0x01800907L +#define VUX_SHIP_INDEX 0x01a00a07L +#define YEHAT_SHIP_INDEX 0x01c00b07L +#define MELNORME_SHIP_INDEX 0x01e00c07L +#define DRUUGE_SHIP_INDEX 0x02000d07L +#define ILWRATH_SHIP_INDEX 0x02200e07L +#define MYCON_SHIP_INDEX 0x02400f07L +#define SLYLANDRO_SHIP_INDEX 0x02601007L +#define UMGAH_SHIP_INDEX 0x02801107L +#define URQUAN_SHIP_INDEX 0x02a01207L +#define ZOQFOTPIK_SHIP_INDEX 0x02c01307L +#define SYREEN_SHIP_INDEX 0x02e01407L +#define BLACKURQ_SHIP_INDEX 0x03001507L +#define ANDROSYN_SHIP_INDEX 0x03201607L +#define CHENJESU_SHIP_INDEX 0x03401707L +#define MMRNMHRM_SHIP_INDEX 0x03601807L +#define ARILOU_CONVERSATION 0x14a01907L +#define CHMMR_CONVERSATION 0x14c01a07L +#define COMMANDER_CONVERSATION 0x14e01b07L +#define ORZ_CONVERSATION 0x15001c07L +#define PKUNK_CONVERSATION 0x15201d07L +#define SHOFIXTI_CONVERSATION 0x15401e07L +#define SPATHI_CONVERSATION 0x15601f07L +#define SUPOX_CONVERSATION 0x15802007L +#define THRADD_CONVERSATION 0x15a02107L +#define UTWIG_CONVERSATION 0x15c02207L +#define VUX_CONVERSATION 0x15e02307L +#define YEHAT_CONVERSATION 0x16002407L +#define MELNORME_CONVERSATION 0x16202507L +#define DRUUGE_CONVERSATION 0x16402607L +#define ILWRATH_CONVERSATION 0x16602707L +#define MYCON_CONVERSATION 0x16802807L +#define SLYLANDRO_CONVERSATION 0x16a02907L +#define UMGAH_CONVERSATION 0x16c02a07L +#define URQUAN_CONVERSATION 0x16e02b07L +#define ZOQFOTPIK_CONVERSATION 0x17002c07L +#define SYREEN_CONVERSATION 0x17202d07L +#define BLACKURQ_CONVERSATION 0x17402e07L +#define TALKING_PET_CONVERSATION 0x17602f07L +#define SLYLANDRO_HOME_CONVERSATION 0x17803007L +#define SIS_RES_INDEX 0x17c03107L +#define SAMATRA_RES_INDEX 0x17e03207L +#define PROBE_RES_INDEX 0x18003307L + + diff --git a/sc2/src/sc2code/isndres.h b/sc2/src/sc2code/isndres.h new file mode 100644 index 000000000..df8282511 --- /dev/null +++ b/sc2/src/sc2code/isndres.h @@ -0,0 +1,5 @@ +#define MENU_SOUNDS 0x04000005L +#define GAME_SOUNDS 0x04200105L +#define LANDER_SOUNDS 0x05400205L + + diff --git a/sc2/src/sc2code/istrtab.h b/sc2/src/sc2code/istrtab.h new file mode 100644 index 000000000..e16e7bf3e --- /dev/null +++ b/sc2/src/sc2code/istrtab.h @@ -0,0 +1,98 @@ +#define STARCON_COLOR_MAP 0x00200004L +#define STARCON_GAME_STRINGS 0x03800104L +#define HYPER_COLOR_TAB 0x04800204L +#define ARISPACE_COLOR_TAB 0x04a00304L +#define ORBPLAN_COLOR_MAP 0x05200404L +#define OOLITE_COLOR_TAB 0x09000504L +#define OOLITE_XLAT_TAB 0x09000604L +#define YTTRIC_COLOR_TAB 0x09200704L +#define YTTRIC_XLAT_TAB 0x09400804L +#define QUASI_DEGENERATE_COLOR_TAB 0x09600904L +#define QUASI_DEGENERATE_XLAT_TAB 0x09800a04L +#define LANTHANIDE_COLOR_TAB 0x09a00b04L +#define TREASURE_COLOR_TAB 0x09c00c04L +#define UREA_COLOR_TAB 0x09e00d04L +#define UREA_XLAT_TAB 0x0a000e04L +#define METAL_COLOR_TAB 0x0a200f04L +#define METAL_XLAT_TAB 0x0a201004L +#define RADIOACTIVE_COLOR_TAB 0x0a401104L +#define OPALESCENT_COLOR_TAB 0x0a601204L +#define OPALESCENT_XLAT_TAB 0x0a801304L +#define CYANIC_COLOR_TAB 0x0aa01404L +#define ACID_COLOR_TAB 0x0ac01504L +#define ALKALI_COLOR_TAB 0x0ae01604L +#define HALIDE_COLOR_TAB 0x0b001704L +#define GREEN_COLOR_TAB 0x0b201804L +#define COPPER_COLOR_TAB 0x0b401904L +#define CARBIDE_COLOR_TAB 0x0b601a04L +#define ULTRAMARINE_COLOR_TAB 0x0b801b04L +#define NOBLE_COLOR_TAB 0x0ba01c04L +#define AZURE_COLOR_TAB 0x0bc01d04L +#define CHONDRITE_COLOR_TAB 0x0be01e04L +#define CHONDRITE_XLAT_TAB 0x0be01f04L +#define PURPLE_COLOR_TAB 0x0c002004L +#define SUPER_DENSE_COLOR_TAB 0x0c202104L +#define PELLUCID_COLOR_TAB 0x0c402204L +#define DUST_COLOR_TAB 0x0c602304L +#define MAROON_COLOR_TAB 0x0c802404L +#define CIMMERIAN_COLOR_TAB 0x0ca02504L +#define INFRARED_COLOR_TAB 0x0cc02604L +#define SELENIC_COLOR_TAB 0x0ce02704L +#define AURIC_COLOR_TAB 0x0d002804L +#define FLUORESCENT_COLOR_TAB 0x0d202904L +#define ULTRAVIOLET_COLOR_TAB 0x0d402a04L +#define PLUTONIC_COLOR_TAB 0x0d602b04L +#define RAINBOW_COLOR_TAB 0x0d802c04L +#define RAINBOW_XLAT_TAB 0x0d802d04L +#define CRACKED_COLOR_TAB 0x0da02e04L +#define CRACKED_XLAT_TAB 0x0da02f04L +#define SAPPHIRE_COLOR_TAB 0x0dc03004L +#define SAPPHIRE_XLAT_TAB 0x0de03104L +#define ORGANIC_COLOR_TAB 0x0e003204L +#define XENOLITHIC_COLOR_TAB 0x0e203304L +#define REDUX_COLOR_TAB 0x0e403404L +#define REDUX_XLAT_TAB 0x0e403504L +#define PRIMORDIAL_COLOR_TAB 0x0e603604L +#define EMERALD_COLOR_TAB 0x0e803704L +#define CHLORINE_COLOR_TAB 0x0ea03804L +#define CHLORINE_XLAT_TAB 0x0ec03904L +#define MAGNETIC_COLOR_TAB 0x0ee03a04L +#define WATER_COLOR_TAB 0x0f003b04L +#define TELLURIC_COLOR_TAB 0x0f203c04L +#define HYDROCARBON_COLOR_TAB 0x0f403d04L +#define IODINE_COLOR_TAB 0x0f603e04L +#define VINYLOGOUS_COLOR_TAB 0x0f803f04L +#define RUBY_COLOR_TAB 0x0fa04004L +#define MAGMA_COLOR_TAB 0x0fc04104L +#define CRIMSON_COLOR_TAB 0x0fe04204L +#define GAS_XLAT_TAB 0x10004304L +#define BLU_GAS_COLOR_TAB 0x10204404L +#define CYA_GAS_COLOR_TAB 0x10404504L +#define GRN_GAS_COLOR_TAB 0x10604604L +#define GRY_GAS_COLOR_TAB 0x10804704L +#define ORA_GAS_COLOR_TAB 0x10a04804L +#define PUR_GAS_COLOR_TAB 0x10c04904L +#define RED_GAS_COLOR_TAB 0x10e04a04L +#define VIO_GAS_COLOR_TAB 0x11004b04L +#define YEL_GAS_COLOR_TAB 0x11204c04L +#define MOONBASE_STRTAB 0x11604d04L +#define MAIDENS_STRTAB 0x11804e04L +#define CHMMR_BASE_STRTAB 0x11a04f04L +#define AQUA_STRTAB 0x11c05004L +#define BURV_BCS_STRTAB 0x11e05104L +#define TAALO_DEVICE_STRTAB 0x12005204L +#define SUN_DEVICE_STRTAB 0x12205304L +#define VAULT_STRTAB 0x12405404L +#define WRECK_STRTAB 0x12605504L +#define BOMB_STRTAB 0x12805604L +#define BEAST_STRTAB 0x12a05704L +#define EGG_CASE_STRTAB 0x12c05804L +#define SPAPLUTO_STRTAB 0x12e05904L +#define BURV_RUINS_STRTAB 0x13005a04L +#define ANDROSYNTH_RUINS_STRTAB 0x13205b04L +#define DRUUGE_RUINS_STRTAB 0x13405c04L +#define PKUNK_RUINS_STRTAB 0x13605d04L +#define RUINS_STRTAB 0x13a05e04L +#define UMGAH_BCS_STRTAB 0x13c05f04L + + diff --git a/sc2/src/sc2code/libs/Makefile.am b/sc2/src/sc2code/libs/Makefile.am new file mode 100644 index 000000000..95e011850 --- /dev/null +++ b/sc2/src/sc2code/libs/Makefile.am @@ -0,0 +1,23 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +SUBDIRS = decomp graphics input math memory resource sound strings video + +noinst_HEADERS = \ + compiler.h declib.h errlib.h gfxlib.h inplib.h mathlib.h \ + memlib.h reslib.h sndlib.h strlib.h timlib.h vargs.h vidlib.h + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = liblibs.la +liblibs_la_SOURCES = dummy.c +liblibs_la_LIBADD = decomp/libdecomp.la graphics/libgraphics.la \ + input/libinput.la math/libmath.la memory/libmemory.la \ + resource/libresource.la sound/libsound.la \ + strings/libstrings.la video/libvideo.la + diff --git a/sc2/src/sc2code/libs/compiler.h b/sc2/src/sc2code/libs/compiler.h new file mode 100644 index 000000000..0f7dde3e8 --- /dev/null +++ b/sc2/src/sc2code/libs/compiler.h @@ -0,0 +1,81 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _COMPILER_H +#define _COMPILER_H + +typedef unsigned char BYTE; +typedef BYTE *PBYTE; +typedef unsigned char UBYTE; +typedef UBYTE *PUBYTE; +typedef signed char SBYTE; +typedef SBYTE *PSBYTE; +typedef unsigned short UWORD; +typedef UWORD *PUWORD; +typedef signed short SWORD; +typedef SWORD *PSWORD; +typedef unsigned long DWORD; +typedef DWORD *PDWORD; + +typedef SBYTE *PSTR; + +typedef void *PVOID; + +typedef UWORD COUNT; +typedef COUNT *PCOUNT; +typedef SWORD SIZE; +typedef SIZE *PSIZE; + +typedef unsigned char UNICODE; + +#define PARAGRAPH_SHIFT 0 + +typedef PVOID PTR_DESC; + +#define FAR_PTR_ADD(fp,val) (*((PBYTE *) (fp)) += (val)) + +#define PARAGRAPH_SIZE (1 << PARAGRAPH_SHIFT) + +#define NULL_PTR 0L + +typedef enum +{ + FALSE = 0, + TRUE +} BOOLEAN; +typedef BOOLEAN *PBOOLEAN; + +typedef void (*PVOIDFUNC) (); +typedef BOOLEAN (*PBOOLFUNC) (); +typedef BYTE (*PBYTEFUNC) (); +typedef UWORD (*PUWORDFUNC) (); +typedef SWORD (*PSWORDFUNC) (); +typedef DWORD (*PDWORDFUNC) (); + +#define MAKE_BYTE(lo, hi) ((BYTE) (((BYTE) (hi) << (BYTE) 4) | (BYTE) (lo))) +#define MAKE_WORD(lo, hi) ((UWORD) ((BYTE) (hi) << 8) | (BYTE) (lo)) +#define MAKE_DWORD(lo, hi) (((DWORD) (hi) << 16) | (unsigned short) (lo)) +#define LONIBBLE(x) ((BYTE) ((BYTE) (x) & (BYTE) 0x0F)) +#define HINIBBLE(x) ((BYTE) ((BYTE) (x) >> (BYTE) 4)) +#define LOBYTE(x) ((BYTE) ((UWORD) (x))) +#define HIBYTE(x) ((BYTE) ((UWORD) (x) >> 8)) +#define LOWORD(x) ((unsigned short) ((DWORD) (x))) +#define HIWORD(x) ((UWORD) ((DWORD) (x) >> 16)) + +#endif /* _COMPILER_H */ + diff --git a/sc2/src/sc2code/libs/declib.h b/sc2/src/sc2code/libs/declib.h new file mode 100644 index 000000000..bb07d36c0 --- /dev/null +++ b/sc2/src/sc2code/libs/declib.h @@ -0,0 +1,53 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DECLIB_H +#define _DECLIB_H + +#define DECODE_REF PVOID + +enum +{ + FILE_STREAM = 0, + MEMORY_STREAM +}; +typedef BYTE STREAM_TYPE; + +enum +{ + STREAM_READ = 0, + STREAM_WRITE +}; +typedef BYTE STREAM_MODE; + +#endif /* _DECLIB_H */ + +#ifndef _DEC_PROTOS +#define _DEC_PROTOS + +extern DECODE_REF copen (PVOID InStream, STREAM_TYPE SType, STREAM_MODE + SMode); +extern DWORD cclose (DECODE_REF DecodeRef); +extern void cfilelength (DECODE_REF DecodeRef, DWORD *pfilelen); +extern COUNT cread (PVOID pStr, COUNT size, COUNT count, DECODE_REF + DecodeRef); +extern COUNT cwrite (PVOID pStr, COUNT size, COUNT count, DECODE_REF + DecodeRef); + +#endif /* _DEC_PROTOS */ + diff --git a/sc2/src/sc2code/libs/decomp/Makefile.am b/sc2/src/sc2code/libs/decomp/Makefile.am new file mode 100644 index 000000000..0b14bff81 --- /dev/null +++ b/sc2/src/sc2code/libs/decomp/Makefile.am @@ -0,0 +1,13 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libdecomp.la +libdecomp_la_SOURCES = lzdecode.c lzencode.c update.c +noinst_HEADERS = lzh.h \ No newline at end of file diff --git a/sc2/src/sc2code/libs/decomp/lzdecode.c b/sc2/src/sc2code/libs/decomp/lzdecode.c new file mode 100644 index 000000000..473db2bfc --- /dev/null +++ b/sc2/src/sc2code/libs/decomp/lzdecode.c @@ -0,0 +1,425 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /* + * LZHUF.C English version 1.0 + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE + */ + +#include +#include +#include +#include +#include "libs/decomp/lzh.h" +#include "timlib.h" + +PLZHCODE_DESC _lpCurCodeDesc; +STREAM_TYPE _StreamType; +PBYTE _Stream; +UWORD _workbuf; +BYTE _workbuflen; + +static SWORD +GetBit (/* get one bit */ + void) +{ + SWORD i; + + while (_workbuflen <= 8) + { + if ((i = InChar ()) < 0) + i = 0; + _workbuf |= i << (8 - _workbuflen); + _workbuflen += 8; + } + i = (_workbuf & 0xFFFF) >> (16 - 1); + _workbuf = (_workbuf << 1) & 0xFFFF; + _workbuflen--; + + return (i); +} + +static UWORD +GetBits (BYTE num_bits) +{ + SWORD i; + + while (_workbuflen <= 8) + { + if ((i = InChar ()) < 0) + i = 0; + _workbuf |= i << (8 - _workbuflen); + _workbuflen += 8; + } + i = (_workbuf & 0xFFFF) >> (16 - num_bits); + _workbuf = (_workbuf << num_bits) & 0xFFFF; + _workbuflen -= num_bits; + + return (i); +} + +/* initialize freq tree */ + +void +StartHuff (void) +{ + COUNT i, j; + + for (i = 0; i < N_CHAR; i++) + { + _lpCurCodeDesc->freq[i] = 1; + _lpCurCodeDesc->son[i] = i + T; + _lpCurCodeDesc->prnt[i + T] = i; + } + i = 0; j = N_CHAR; + while (j <= R) + { + _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[i + 1]; + _lpCurCodeDesc->son[j] = i; + _lpCurCodeDesc->prnt[i] = _lpCurCodeDesc->prnt[i + 1] = j; + i += 2; j++; + } + _lpCurCodeDesc->freq[T] = 0xffff; + _lpCurCodeDesc->prnt[R] = 0; +} + +DECODE_REF +copen (PVOID InStream, STREAM_TYPE SType, STREAM_MODE SMode) +{ + MEM_HANDLE h; + DWORD StreamLength; + + _StreamType = SType; + _Stream = InStream; + if (SMode == STREAM_WRITE) /* writing */ + { + OutChar (0); /* skip future StreamLength */ + OutChar (0); + OutChar (0); + OutChar (0); + + StreamLength = 0; + } + else /* reading */ + { + BYTE lobyte, hibyte; + UWORD loword, hiword; + + lobyte = (BYTE)InChar (); + hibyte = (BYTE)InChar (); + loword = MAKE_WORD (lobyte, hibyte); + lobyte = (BYTE)InChar (); + hibyte = (BYTE)InChar (); + hiword = MAKE_WORD (lobyte, hibyte); + + StreamLength = MAKE_DWORD (loword, hiword); + } + + h = 0; + if (StreamLength == 0xFFFFFFFF + || (h = AllocCodeDesc ()) == 0 + || (_lpCurCodeDesc = LockCodeDesc (h)) == 0) + { + _lpCurCodeDesc = 0; + FreeCodeDesc (h); + } + else + { + _lpCurCodeDesc->fh = h; + _lpCurCodeDesc->Stream = _Stream; + _lpCurCodeDesc->StreamType = _StreamType; + _lpCurCodeDesc->StreamMode = SMode; + _lpCurCodeDesc->StreamLength = StreamLength; + _lpCurCodeDesc->buf_index = N - F; + memset ((PBYTE)&_lpCurCodeDesc->text_buf[0], ' ', N - F); + + StartHuff (); + } + + return ((DECODE_REF)_lpCurCodeDesc); +} + +DWORD +cclose (PLZHCODE_DESC lpCodeDesc) +{ + _lpCurCodeDesc = lpCodeDesc; + if (_lpCurCodeDesc) + { + DWORD StreamIndex; + + if (_lpCurCodeDesc->CleanupFunc) + (*_lpCurCodeDesc->CleanupFunc) (); + + StreamIndex = lpCodeDesc->StreamIndex; + UnlockCodeDesc (lpCodeDesc->fh); + FreeCodeDesc (lpCodeDesc->fh); + + return (StreamIndex); + } + + return (0); +} + +void +cfilelength (PLZHCODE_DESC lpCodeDesc, DWORD *pfilelen) +{ + if (lpCodeDesc == 0) + *pfilelen = 0; + else + *pfilelen = lpCodeDesc->StreamLength; +} + + /* decoder table */ +static const BYTE d_code[256] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, + 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, + 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, + 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, +}; +static const BYTE d_len[256] = +{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +}; + + /* decode upper 6 bits from given table */ +#define DecodePosition(p) \ +{ \ + while (_workbuflen <= 8) \ + { \ + *(p) = InChar (); \ + _workbuf |= *(p) << (8 - _workbuflen); \ + _workbuflen += 8; \ + } \ + *(p) = HIBYTE (_workbuf); \ + _workbuf = (_workbuf << 8) & 0xFFFF; \ + _workbuflen -= 8; \ + \ + /* input lower 6 bits directly */ \ + j = d_len[*(p)]; \ + *(p) = ((UWORD)d_code[*(p)] << 6) \ + | (((*(p) << j) | GetBits (j)) & 0x3f); \ +} + + /* start searching tree from the root to leaves. + * choose node #(son[]) if input bit == 0 + * else choose #(son[]+1) (input bit == 1) + */ +#define DecodeChar(c) \ +{ \ + for (*(c) = lpCodeDesc->son[R]; \ + *(c) < T; \ + *(c) = lpCodeDesc->son[*(c) + GetBit ()]) \ + ; \ + _update (*(c)); \ + *(c) -= T; \ +} + +COUNT +cread (PVOID buf, COUNT size, COUNT count, register PLZHCODE_DESC + lpCodeDesc) +{ + COUNT r, j, i; + PBYTE lpStr; + + if ((_lpCurCodeDesc = lpCodeDesc) == 0) + return (0); + + size *= count; + if (lpCodeDesc->StreamIndex + size > lpCodeDesc->StreamLength) + { + size /= count; + count = (COUNT)((lpCodeDesc->StreamLength + - lpCodeDesc->StreamIndex) / size); + + size *= count; + } + + if (size == 0) + return (0); + + lpStr = (PBYTE)buf; + _StreamType = lpCodeDesc->StreamType; + + _Stream = lpCodeDesc->Stream; + _workbuf = lpCodeDesc->workbuf; + _workbuflen = lpCodeDesc->workbuflen; + + lpCodeDesc->StreamIndex += size; + r = lpCodeDesc->buf_index; + j = lpCodeDesc->bytes_left; + if (j) + { + lpCodeDesc->bytes_left = 0; + i = lpCodeDesc->restart_index; + + goto ReenterRun; + } + + do + { + COUNT c; + + DecodeChar (&c); + + if (c < 256) + { + size--; + + *lpStr++ = lpCodeDesc->text_buf[r++ & (N - 1)] = (BYTE)c; + } + else + { + COUNT copy_size; + + //i is a COUNT; + DecodePosition(&i); + i = r - i - 1; + j = c - 255 + THRESHOLD; +ReenterRun: + if (j > size) + { + lpCodeDesc->bytes_left = j - size; + lpCodeDesc->restart_index = i + size; + j = size; + } + + size -= j; + do + { + COUNT loc_size; + + i &= (N - 1); + r &= (N - 1); + if ((i < r && i + j > r) || (i > r && i + j > r + N)) + copy_size = (r - i) & (N - 1); + else if ((copy_size = j) > N) + copy_size = N; + + loc_size = copy_size; + if (i + loc_size > N) + { + COUNT k; + + k = N - i; + memcpy (lpStr, &lpCodeDesc->text_buf[i], k); + lpStr += k; + loc_size -= k; + i = 0; + } + + memcpy (lpStr, &lpCodeDesc->text_buf[i], loc_size); + lpStr += loc_size; + i += loc_size; + + lpStr -= copy_size; + + loc_size = copy_size; + if (r + loc_size > N) + { + COUNT k; + + k = N - r; + memcpy (&lpCodeDesc->text_buf[r], lpStr, k); + lpStr += k; + loc_size -= k; + r = 0; + } + + memcpy (&lpCodeDesc->text_buf[r], lpStr, loc_size); + lpStr += loc_size; + r += loc_size; + } while (j -= copy_size); + } + } while (size); + + if (_StreamType == MEMORY_STREAM) + { + FAR_PTR_ADD (&_Stream, 0); + } + + lpCodeDesc->buf_index = r; + lpCodeDesc->Stream = _Stream; + lpCodeDesc->workbuf = _workbuf; + lpCodeDesc->workbuflen = _workbuflen; + + return (count); +} + diff --git a/sc2/src/sc2code/libs/decomp/lzencode.c b/sc2/src/sc2code/libs/decomp/lzencode.c new file mode 100644 index 000000000..4bf19dc66 --- /dev/null +++ b/sc2/src/sc2code/libs/decomp/lzencode.c @@ -0,0 +1,481 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /* + * LZHUF.C English version 1.0 + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE + */ + +#include +#include "lzh.h" + +#define DEBUG + +static UWORD match_position, match_length; +static PSWORD lson, rson, dad; + +#define AllocEncodeArrays() \ + mem_allocate ( \ + (MEM_SIZE)(((N + 1) + (N + 257) + (N + 1)) \ + * sizeof (lson[0]) + sizeof (MEM_HANDLE)), \ + MEM_ZEROINIT, DEFAULT_MEM_PRIORITY, MEM_SIMPLE \ + ) +#define LockCodeArrays (PSWORD)mem_lock +#define UnlockCodeArrays mem_unlock +#define FreeCodeArrays mem_release + +static BOOLEAN +InitTree (void) +{ + MEM_HANDLE h; + + if ((h = AllocEncodeArrays ()) == 0 + || (lson = LockCodeArrays (h)) == 0) + { + FreeCodeArrays (h); + return (FALSE); + } + else + { + SWORD i; + + *(MEM_HANDLE *)lson = h; + lson = (PSWORD)((PBYTE)lson + sizeof (h)); + rson = lson; + FAR_PTR_ADD (&rson, (N + 1) * sizeof (lson[0])); + dad = rson; + FAR_PTR_ADD (&dad, (N + 257) * sizeof (rson[0])); + + for (i = N + 1; i <= N + 256; i++) + rson[i] = NIL; /* root */ + for (i = 0; i < N; i++) + dad[i] = NIL; /* node */ + + return (TRUE); + } +} + +static void +InsertNode (SWORD r) +{ + SWORD p, cmp; + PBYTE lpBuf; + + cmp = 1; + lpBuf = _lpCurCodeDesc->text_buf; + p = N + 1 + lpBuf[r]; + rson[r] = lson[r] = NIL; + match_length = 0; + for (;;) + { + UWORD i; + + if (cmp >= 0) + { + if (rson[p] != NIL) + p = rson[p]; + else + { + rson[p] = r; + dad[r] = p; + return; + } + } + else + { + if (lson[p] != NIL) + p = lson[p]; + else + { + lson[p] = r; + dad[r] = p; + return; + } + } + + i = F; + { + register SWORD _r, _p; + + _r = r; + _p = p; + while (--i && (cmp = lpBuf[++_r] - lpBuf[++_p]) == 0) + ; + } + if ((i = F - i) > THRESHOLD) + { + if (i > match_length) + { + match_position = ((r - p) & (N - 1)) - 1; + if ((match_length = i) >= F) + break; + } + else if (i == match_length) + { + if ((i = ((r - p) & (N - 1)) - 1) < match_position) + { + match_position = i; + } + } + } + } + dad[r] = dad[p]; + lson[r] = lson[p]; + rson[r] = rson[p]; + dad[lson[p]] = r; + dad[rson[p]] = r; + if (rson[dad[p]] == p) + rson[dad[p]] = r; + else + lson[dad[p]] = r; + dad[p] = NIL; /* remove p */ +} + +static void +DeleteNode (SWORD p) +{ + SWORD q; + + if (dad[p] == NIL) + return; /* unregistered */ + if (rson[p] == NIL) + q = lson[p]; + else if (lson[p] == NIL) + q = rson[p]; + else + { + q = lson[p]; + if (rson[q] != NIL) + { + do + { + q = rson[q]; + } while (rson[q] != NIL); + rson[dad[q]] = lson[q]; + dad[lson[q]] = dad[q]; + lson[q] = lson[p]; + dad[lson[p]] = q; + } + rson[q] = rson[p]; + dad[rson[p]] = q; + } + dad[q] = dad[p]; + if (rson[dad[p]] == p) + rson[dad[p]] = q; + else + lson[dad[p]] = q; + dad[p] = NIL; +} + +static void +Putcode (SWORD l, UWORD c) +{ + _workbuf |= c >> _workbuflen; + if ((_workbuflen += l) >= 8) + { + OutChar ((BYTE)(_workbuf >> 8)); + ++_lpCurCodeDesc->StreamIndex; + if ((_workbuflen -= 8) >= 8) + { + OutChar ((BYTE)(_workbuf)); + ++_lpCurCodeDesc->StreamIndex; + _workbuflen -= 8; + _workbuf = c << (l - _workbuflen); + } + else + { + _workbuf <<= 8; + } + _workbuf &= 0xFFFF; + } +} + +static void +EncodeChar (UWORD c) +{ + UWORD i; + SWORD j, k; + + i = 0; + j = 0; + k = _lpCurCodeDesc->prnt[c + T]; + + /* search connections from leaf node to the root */ + do + { + i >>= 1; + + /* + if node's address is odd, output 1 + else output 0 + */ + if (k & 1) + i += 0x8000; + + j++; + } while ((k = _lpCurCodeDesc->prnt[k]) != R); + Putcode (j, i); + _update (c + T); +} + +static void +EncodePosition (UWORD c) +{ + UWORD i; + /* + * Tables for encoding/decoding upper 6 bits of + * sliding dictionary pointer + */ + /* encoder table */ + static const BYTE p_len[64] = + { + 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 + }; + + static const BYTE p_code[64] = + { + 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, + 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, + 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, + 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, + 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, + 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + }; + + /* output upper 6 bits with encoding */ + i = c >> 6; + Putcode (p_len[i], (UWORD)p_code[i] << 8); + + /* output lower 6 bits directly */ + Putcode (6, (c & 0x3f) << 10); +} + +static void +UninitTree (void) +{ + MEM_HANDLE h; + + if (_workbuflen) + { + OutChar ((BYTE)(_workbuf >> 8)); + ++_lpCurCodeDesc->StreamIndex; + } + + lson = (PSWORD)((PBYTE)lson - sizeof (h)); + h = *(MEM_HANDLE *)lson; + UnlockCodeArrays (h); + FreeCodeArrays (h); +} + +static void +_encode_cleanup () +{ + UWORD r, s, last_match_length, len; + + _StreamType = _lpCurCodeDesc->StreamType; + _Stream = _lpCurCodeDesc->Stream; + _workbuf = _lpCurCodeDesc->workbuf; + _workbuflen = _lpCurCodeDesc->workbuflen; + + r = _lpCurCodeDesc->buf_index; + s = _lpCurCodeDesc->restart_index; + last_match_length = _lpCurCodeDesc->bytes_left; + if (_lpCurCodeDesc->StreamLength >= F) + len = F; + else + { + UWORD i; + + for (i = 1; i <= F; i++) + InsertNode (r - i); + InsertNode (r); + + len = (UWORD)_lpCurCodeDesc->StreamLength; + } + + while (1) + { + while (last_match_length--) + { + DeleteNode (s); + if (--len == 0) + { + BYTE lobyte, hibyte; + UWORD loword, hiword; + + UninitTree (); + + _lpCurCodeDesc->StreamIndex += 4; + /* rewind */ + if (_lpCurCodeDesc->StreamType == FILE_STREAM) + SeekResFile ((FILE *)_Stream, + -(int)_lpCurCodeDesc->StreamIndex, SEEK_CUR); + else /* _lpCurCodeDesc->StreamType == MEMORY_STREAM */ + _Stream = (PBYTE)((BYTE *)_Stream + - _lpCurCodeDesc->StreamIndex); + + loword = LOWORD (_lpCurCodeDesc->StreamLength); + lobyte = LOBYTE (loword); + hibyte = HIBYTE (loword); + OutChar (lobyte); + OutChar (hibyte); + hiword = HIWORD (_lpCurCodeDesc->StreamLength); + lobyte = LOBYTE (hiword); + hibyte = HIBYTE (hiword); + OutChar (lobyte); + OutChar (hibyte); + + return; + } + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + InsertNode (r); + } + if (match_length > len) + match_length = len; + if (match_length <= THRESHOLD) + { + match_length = 1; + EncodeChar (_lpCurCodeDesc->text_buf[r]); + } + else + { + EncodeChar (255 - THRESHOLD + match_length); + EncodePosition (match_position); + } + last_match_length = match_length; + } +} + +COUNT +cwrite (PVOID buf, COUNT size, COUNT count, register PLZHCODE_DESC + lpCodeDesc) +{ + UWORD r, s, last_match_length; + PBYTE lpBuf, lpStr; + + if ((_lpCurCodeDesc = lpCodeDesc) == 0 + || (size *= count) == 0) + return (0); + + _StreamType = lpCodeDesc->StreamType; + _Stream = lpCodeDesc->Stream; + _workbuf = lpCodeDesc->workbuf; + _workbuflen = lpCodeDesc->workbuflen; + lpStr = (PBYTE)buf; + lpBuf = lpCodeDesc->text_buf; + + r = lpCodeDesc->buf_index; + s = lpCodeDesc->restart_index; + last_match_length = lpCodeDesc->bytes_left; + if (last_match_length) + { + lpCodeDesc->StreamLength += size; + goto EncodeRestart; + } + else if (lpCodeDesc->StreamLength < F) + { + UWORD i; + + if ((i = (UWORD)lpCodeDesc->StreamLength) == 0) + { + if (!InitTree ()) + return (0); + + _lpCurCodeDesc->StreamIndex = 0; + lpCodeDesc->CleanupFunc = _encode_cleanup; + } + + lpCodeDesc->StreamLength += size; + + for (; i < F && size; ++i, --size) + lpBuf[r + i] = *lpStr++; + if (i < F) + goto EncodeExit; + + for (i = 1; i <= F; i++) + InsertNode (r - i); + InsertNode (r); + if (size == 0) + goto EncodeExit; + } + else + lpCodeDesc->StreamLength += size; + + do + { + if (match_length > F) + match_length = F; + if (match_length <= THRESHOLD) + { + match_length = 1; + EncodeChar (lpBuf[r]); + } + else + { + EncodeChar (255 - THRESHOLD + match_length); + EncodePosition (match_position); + } + last_match_length = match_length; +EncodeRestart: + while (last_match_length && size) + { + BYTE c; + + --size; + --last_match_length; + + DeleteNode (s); + c = *lpStr++; + lpBuf[s] = c; + if (s < F - 1) + lpBuf[s + N] = c; + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + InsertNode (r); + } + } while (last_match_length == 0); + + if (_StreamType == MEMORY_STREAM) + { + FAR_PTR_ADD (&_Stream, 0); + } +EncodeExit: + lpCodeDesc->buf_index = r; + lpCodeDesc->restart_index = s; + lpCodeDesc->bytes_left = last_match_length; + + lpCodeDesc->Stream = _Stream; + lpCodeDesc->workbuf = _workbuf; + lpCodeDesc->workbuflen = _workbuflen; + + return (count); +} + diff --git a/sc2/src/sc2code/libs/decomp/lzh.h b/sc2/src/sc2code/libs/decomp/lzh.h new file mode 100644 index 000000000..740675fd7 --- /dev/null +++ b/sc2/src/sc2code/libs/decomp/lzh.h @@ -0,0 +1,101 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LZH_H +#define _LZH_H + +#include "reslib.h" +#define _DEC_PROTOS +#include "declib.h" + +/* LZSS Parameters */ + +#define N 4096 /* Size of string buffer */ +#define F 16 /* Size of look-ahead buffer */ +//#define F 60 /* Size of look-ahead buffer */ +#define THRESHOLD 2 +#define NIL N /* End of tree's node */ + +/* Huffman coding parameters */ + +#define N_CHAR (256 - THRESHOLD + F) + /* character code (= 0..N_CHAR-1) */ +#define T (N_CHAR * 2 - 1) /* Size of table */ +#define R (T - 1) /* root position */ +#define MAX_FREQ 0x8000 + /* update when cumulative frequency */ + +typedef struct +{ + MEM_HANDLE fh; + + COUNT buf_index, restart_index, bytes_left; + BYTE text_buf[N + F - 1]; + /* reconstruct freq tree */ + COUNT freq[T + 1]; /* cumulative freq table */ + /* + * pointing parent nodes. + * area [T..(T + N_CHAR - 1)] are pointers for leaves + */ + COUNT prnt[T + N_CHAR]; + /* pointing children nodes (son[], son[] + 1)*/ + COUNT son[T]; + UWORD workbuf; + BYTE workbuflen; + + STREAM_TYPE StreamType; + + PVOID Stream; + DWORD StreamIndex, StreamLength; + + STREAM_MODE StreamMode; + PVOIDFUNC CleanupFunc; +} LZHCODE_DESC; +typedef LZHCODE_DESC *PLZHCODE_DESC; + +#define InChar() (_StreamType == FILE_STREAM ? \ + GetResFileChar ((FILE *)_Stream) : \ + (int)*_Stream++) +#define OutChar(c) (_StreamType == FILE_STREAM ? \ + PutResFileChar ((c), (FILE *)_Stream) : \ + (*_Stream++ = (BYTE)(c))) + + +#define AllocCodeDesc() \ + mem_allocate ((MEM_SIZE)sizeof (LZHCODE_DESC), \ + MEM_ZEROINIT, DEFAULT_MEM_PRIORITY, MEM_SIMPLE) +#define LockCodeDesc (PLZHCODE_DESC)mem_lock +#define UnlockCodeDesc mem_unlock +#define FreeCodeDesc mem_release + +extern void _update (COUNT c); +extern void StartHuff (void); + +#undef DECODE_REF +#define DECODE_REF PLZHCODE_DESC +#undef _DEC_PROTOS +#include "declib.h" + +extern PLZHCODE_DESC _lpCurCodeDesc; +extern STREAM_TYPE _StreamType; +extern PBYTE _Stream; +extern UWORD _workbuf; +extern BYTE _workbuflen; + +#endif /* _LZH_H */ + diff --git a/sc2/src/sc2code/libs/decomp/update.c b/sc2/src/sc2code/libs/decomp/update.c new file mode 100644 index 000000000..5ce3651cc --- /dev/null +++ b/sc2/src/sc2code/libs/decomp/update.c @@ -0,0 +1,115 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "lzh.h" + +static void +reconst (void) +{ + COUNT i, j; + + /* halven cumulative freq for leaf nodes */ + j = 0; + for (i = 0; i < T; i++) + { + if (_lpCurCodeDesc->son[i] >= T) + { + _lpCurCodeDesc->freq[j] = (_lpCurCodeDesc->freq[i] + 1) >> 1; + _lpCurCodeDesc->son[j] = _lpCurCodeDesc->son[i]; + j++; + } + } + /* make a tree : first, connect children nodes */ + for (i = 0, j = N_CHAR; j < T; i += 2, j++) + { + SWORD k; + UWORD f, l; + + k = i + 1; + f = _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[k]; + for (k = j - 1; f < _lpCurCodeDesc->freq[k]; k--) + ; + k++; + l = (j - k) << 1; + + memmove ((PBYTE)&_lpCurCodeDesc->freq[k + 1], + (PBYTE)&_lpCurCodeDesc->freq[k], l); + _lpCurCodeDesc->freq[k] = f; + memmove ((PBYTE)&_lpCurCodeDesc->son[k + 1], + (PBYTE)&_lpCurCodeDesc->son[k], l); + _lpCurCodeDesc->son[k] = i; + } + /* connect parent nodes */ + for (i = 0; i < T; i++) + { + if ((j = _lpCurCodeDesc->son[i]) >= T) + _lpCurCodeDesc->prnt[j] = i; + else + _lpCurCodeDesc->prnt[j] = _lpCurCodeDesc->prnt[j + 1] = i; + } +} + + +/* update freq tree */ + +void +_update (COUNT c) +{ + register PLZHCODE_DESC lpCD; + + if ((lpCD = _lpCurCodeDesc)->freq[R] == MAX_FREQ) + reconst (); + + c = lpCD->prnt[c]; + do + { + COUNT i, l; + + i = ++lpCD->freq[c]; + + /* swap nodes to keep the tree freq-ordered */ + if (i > lpCD->freq[l = c + 1]) + { + COUNT j; + + while (i > lpCD->freq[++l]) + ; + l--; + lpCD->freq[c] = lpCD->freq[l]; + lpCD->freq[l] = i; + + i = lpCD->son[c]; + j = lpCD->son[l]; + lpCD->son[l] = i; + lpCD->son[c] = j; + + lpCD->prnt[i] = l; + if (i < T) + lpCD->prnt[i + 1] = l; + + lpCD->prnt[j] = c; + if (j < T) + lpCD->prnt[j + 1] = c; + + c = l; + } + } while ((c = lpCD->prnt[c]) != 0); /* do it until reaching the root */ +} + + diff --git a/sc2/src/sc2code/libs/dummy.c b/sc2/src/sc2code/libs/dummy.c new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/src/sc2code/libs/errlib.h b/sc2/src/sc2code/libs/errlib.h new file mode 100644 index 000000000..2f3873823 --- /dev/null +++ b/sc2/src/sc2code/libs/errlib.h @@ -0,0 +1,48 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ERRLIB_H +#define _ERRLIB_H + +#include "compiler.h" +#include "vargs.h" + +typedef SWORD ERR_ID; +typedef DWORD ERR_NO; + +typedef BOOLEAN ERR_BOOL; +#define ERR_FAILURE FALSE +#define ERR_SUCCESS TRUE + +typedef enum +{ + ERR_IN_MEMORY, + ERR_IN_FILE +} ERR_LOC; + +extern ERR_ID err_register (PSTR module_name, ERR_LOC err_loc, PSTR + err_string_path, COUNT num_errors); +extern ERR_BOOL err_unregister (ERR_ID err_id); +extern ERR_BOOL err_push (ERR_ID err_id, PSTR func_name, ERR_NO err_no, + vararg_dcl alist, ...); +extern ERR_BOOL err_clear (void); +extern ERR_BOOL err_report (ERR_BOOL (*err_func) (COUNT top_stack, PSTR + mname, PSTR fname, PSTR pStr)); + +#endif /* _ERRLIB_H */ + diff --git a/sc2/src/sc2code/libs/gfxlib.h b/sc2/src/sc2code/libs/gfxlib.h new file mode 100644 index 000000000..1563d1d7a --- /dev/null +++ b/sc2/src/sc2code/libs/gfxlib.h @@ -0,0 +1,392 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _GFXLIB_H +#define _GFXLIB_H + +#include "memlib.h" + +#define CONTEXT PVOID +#define FRAME PVOID +#define FONT PVOID +#define CYCLE_REF DWORD + +typedef CONTEXT *PCONTEXT; +typedef FRAME *PFRAME; +typedef FONT *PFONT; + +typedef UWORD TIME_VALUE; +typedef TIME_VALUE *PTIME_VALUE; + +#define TIME_SHIFT 8 +#define MAX_TIME_VALUE ((1 << TIME_SHIFT) + 1) + +typedef SWORD COORD; +typedef COORD *PCOORD; + +typedef UWORD COLOR; +typedef COLOR *PCOLOR; + +#define BUILD_COLOR(c32k,c256) \ + (COLOR)(((DWORD)(c32k)<<8)|(BYTE)(c256)) +#define COLOR_32k(c) (UWORD)((COLOR)(c)>>8) +#define COLOR_256(c) LOBYTE((COLOR)c) +#define MAKE_RGB15(r,g,b) (UWORD)(((r)<<10)|((g)<<5)|(b)) + +typedef BYTE CREATE_FLAGS; +#define WANT_MASK (CREATE_FLAGS)(1 << 0) +#define WANT_PIXMAP (CREATE_FLAGS)(1 << 1) +#define MAPPED_TO_DISPLAY (CREATE_FLAGS)(1 << 2) + +typedef enum +{ + MAP_ISOTROPIC, /* == X/Y scale is the same */ + MAP_ANISOTROPIC, /* == X/Y scale different (e.g. aspect ratio) */ + MAP_NOXFORM /* == X/Y scale is ignored */ +} MAP_TYPE; + +typedef enum +{ + DEST_MASK = MAKE_WORD (0, 0), + DEST_PIXMAP = MAKE_WORD (0, 1) +} DRAW_DESTINATION; + +typedef enum +{ + DRAW_SUBTRACTIVE = 0, /* implied only to active page */ + DRAW_ADDITIVE, /* implied only to active page */ + DRAW_REPLACE +} DRAW_MODE; + +typedef UWORD DRAW_STATE; + +typedef struct extent +{ + COORD width, height; +} EXTENT; +typedef EXTENT *PEXTENT; + +typedef struct point +{ + COORD x, y; +} POINT; +typedef POINT *PPOINT; + +typedef struct stamp +{ + POINT origin; + FRAME frame; +} STAMP; +typedef STAMP *PSTAMP; + +typedef struct rect +{ + POINT corner; + EXTENT extent; +} RECT; +typedef RECT *PRECT; + +typedef struct line +{ + POINT first, second; +} LINE; +typedef LINE *PLINE; + +typedef enum +{ + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT +} TEXT_ALIGN; + +typedef struct text +{ + POINT baseline; + UNICODE *pStr; + TEXT_ALIGN align; + COUNT CharCount; +} TEXT; +typedef TEXT *PTEXT; + +typedef MEM_HANDLE POLYREF; + +typedef PVOID POLYGON; +typedef POLYGON *PPOLYGON; + +#include "strlib.h" + +typedef STRING_TABLE COLORMAP_REF; +typedef STRING COLORMAP; +typedef STRINGPTR COLORMAPPTR; + +typedef struct stamp_cmap +{ + POINT origin; + FRAME frame; + COLORMAPPTR CMap; +} STAMP_CMAP; +typedef STAMP_CMAP *PSTAMP_CMAP; + +typedef struct composite +{ + POINT origin; + PFRAME FrameList; + COUNT NumFrames; +} COMPOSITE; +typedef COMPOSITE *PCOMPOSITE; + +enum gfx_object +{ + POINT_PRIM = 0, + STAMP_PRIM, + STAMPFILL_PRIM, + LINE_PRIM, + TEXT_PRIM, + STAMPCMAP_PRIM, + RECT_PRIM, + RECTFILL_PRIM, + POLY_PRIM, + POLYFILL_PRIM, + COMPOSITE_PRIM, + COMPOSITEFILL_PRIM, + + NUM_PRIMS +}; +typedef BYTE GRAPHICS_PRIM; + +typedef union +{ + POINT Point; + STAMP Stamp; + LINE Line; + TEXT Text; + STAMP_CMAP StampCMap; + RECT Rect; + POLYGON Polygon; + COMPOSITE Composite; +} PRIM_DESC; +typedef PRIM_DESC *PPRIM_DESC; + +typedef DWORD PRIM_LINKS; + +typedef struct +{ + PRIM_LINKS Links; + DWORD TypeAndColor; + PRIM_DESC Object; +} PRIMITIVE; +typedef PRIMITIVE *PPRIMITIVE; + +#define END_OF_LIST ((COUNT)0xFFFF) + +#define PRIM_COLOR_SHIFT 8 +#define PRIM_COLOR_MASK ((DWORD)~0L << PRIM_COLOR_SHIFT) +#define PRIM_TYPE_MASK (~PRIM_COLOR_MASK) + +#define GetPredLink(l) LOWORD(l) +#define GetSuccLink(l) HIWORD(l) +#define MakeLinks MAKE_DWORD +#define SetPrimLinks(pPrim,p,s) ((pPrim)->Links = MakeLinks (p, s)) +#define GetPrimLinks(pPrim) ((pPrim)->Links) +#define SetPrimType(pPrim,t) \ + ((pPrim)->TypeAndColor = ((pPrim)->TypeAndColor & PRIM_COLOR_MASK) \ + | ((t) & PRIM_TYPE_MASK)) +#define GetPrimType(pPrim) \ + ((GRAPHICS_PRIM)LOBYTE ((pPrim)->TypeAndColor)) +#define SetPrimColor(pPrim,c) \ + ((pPrim)->TypeAndColor = ((pPrim)->TypeAndColor & PRIM_TYPE_MASK) \ + | ((c) << PRIM_COLOR_SHIFT)) +#define GetPrimColor(pPrim) \ + ((COLOR)((pPrim)->TypeAndColor >> PRIM_COLOR_SHIFT)) + +typedef BYTE BATCH_FLAGS; + +#define BATCH_BUILD_PAGE (BATCH_FLAGS)(1 << 0) +#define BATCH_SINGLE (BATCH_FLAGS)(1 << 1) + +typedef struct +{ + TIME_VALUE last_time_val; + POINT EndPoint; + STAMP IntersectStamp; +} INTERSECT_CONTROL; +typedef INTERSECT_CONTROL *PINTERSECT_CONTROL; + +typedef MEM_HANDLE CONTEXT_REF; +typedef CONTEXT_REF *PCONTEXT_REF; + +typedef DWORD DRAWABLE; +typedef DRAWABLE *PDRAWABLE; + +#define BUILD_DRAWABLE(h,i) ((DRAWABLE)MAKE_DWORD(h,i)) + +typedef MEM_HANDLE FONT_REF; +typedef FONT_REF *PFONT_REF; + +typedef BYTE INTERSECT_CODE; + +#define INTERSECT_LEFT (INTERSECT_CODE)(1 << 0) +#define INTERSECT_TOP (INTERSECT_CODE)(1 << 1) +#define INTERSECT_RIGHT (INTERSECT_CODE)(1 << 2) +#define INTERSECT_BOTTOM (INTERSECT_CODE)(1 << 3) +#define INTERSECT_NOCLIP (INTERSECT_CODE)(1 << 7) +#define INTERSECT_ALL_SIDES (INTERSECT_CODE)(INTERSECT_LEFT | \ + INTERSECT_TOP | \ + INTERSECT_RIGHT | \ + INTERSECT_BOTTOM) + +typedef DWORD HOT_SPOT; +#define MAKE_HOT_SPOT MAKE_DWORD +#define GET_HOT_X(h) ((short)LOWORD(h)) +#define GET_HOT_Y(h) ((short)HIWORD(h)) + +extern INTERSECT_CODE BoxIntersect (PRECT pr1, PRECT pr2, PRECT + printer); +extern void BoxUnion (PRECT pr1, PRECT pr2, PRECT punion); + +typedef void (*BG_FUNC) (PRECT pClipRect); + +#endif /* _GFXLIB_H */ + + +#ifndef _GFX_PROTOS +#define _GFX_PROTOS + +extern BOOLEAN InitGraphics (int argc, char *argv[], COUNT + KbytesRequired); +extern void UninitGraphics (void); + +extern CONTEXT SetContext (CONTEXT Context); +extern CONTEXT CaptureContext (CONTEXT_REF ContextRef); +extern CONTEXT_REF ReleaseContext (CONTEXT Context); +extern MAP_TYPE SetContextMapType (MAP_TYPE MapType); +extern BOOLEAN SetContextWinOrigin (PPOINT pOrg); +extern BOOLEAN SetContextViewExtents (PEXTENT pExtent); +extern BOOLEAN SetContextWinExtents (PEXTENT pExtent); +extern BOOLEAN GetContextWinOrigin (PPOINT pOrg); +extern BOOLEAN GetContextViewExtents (PEXTENT pExtent); +extern BOOLEAN GetContextWinExtents (PEXTENT pExtent); +extern BOOLEAN LOGtoDEV (PPOINT pSrcPt, PPOINT pDstPt, COUNT NumPoints); +extern BOOLEAN DEVtoLOG (PPOINT pSrcPt, PPOINT pDstPt, COUNT NumPoints); +extern DRAW_STATE GetContextDrawState (void); +extern DRAW_STATE SetContextDrawState (DRAW_STATE DrawState); +extern COLOR SetContextForeGroundColor (COLOR Color); +extern COLOR SetContextBackGroundColor (COLOR Color); +extern FRAME SetContextFGFrame (FRAME Frame); +extern FRAME SetContextBGFrame (FRAME Frame); +extern BG_FUNC SetContextBGFunc (BG_FUNC BGFunc); +extern BOOLEAN SetContextClipping (BOOLEAN ClipStatus); +extern BOOLEAN SetContextClipRect (PRECT pRect); +extern BOOLEAN GetContextClipRect (PRECT pRect); +extern TIME_VALUE DrawablesIntersect (PINTERSECT_CONTROL pControl0, + PINTERSECT_CONTROL pControl1, TIME_VALUE max_time_val); +extern void DrawStamp (PSTAMP pStamp); +extern void DrawFilledStamp (PSTAMP pStamp); +extern void DrawStampCMap (PSTAMP_CMAP pStampCmap); +extern void DrawPoint (PPOINT pPoint); +extern void DrawRectangle (PRECT pRect); +extern void DrawFilledRectangle (PRECT pRect); +extern void DrawLine (PLINE pLine); +extern void DrawText (PTEXT pText); +extern void DrawPolygon (POLYGON Polygon); +extern void DrawFilledPolygon (POLYGON Polygon); +extern void DrawBatch (PPRIMITIVE pBasePrim, PRIM_LINKS PrimLinks, + BATCH_FLAGS BatchFlags); +extern void BatchGraphics (void); +extern void UnbatchGraphics (void); +extern void FlushGraphics (void); +extern void ClearDrawable (void); +extern CONTEXT_REF CreateContext (void); +extern BOOLEAN DestroyContext (CONTEXT_REF ContextRef); +extern DRAWABLE CreateDisplay (CREATE_FLAGS CreateFlags, PSIZE pwidth, + PSIZE pheight); +extern DRAWABLE CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width, + SIZE height, COUNT num_frames); +extern DRAWABLE CopyDrawable (DRAWABLE Drawable); +extern BOOLEAN DestroyDrawable (DRAWABLE Drawable); +extern BOOLEAN GetFrameRect (FRAME Frame, PRECT pRect); + +extern HOT_SPOT SetFrameHot (FRAME Frame, HOT_SPOT HotSpot); +extern HOT_SPOT GetFrameHot (FRAME Frame); +extern BOOLEAN InstallGraphicResTypes (COUNT cel_type, COUNT font_type); +extern DWORD LoadCelFile (PVOID pStr); +extern DWORD LoadFontFile (PVOID pStr); +extern DWORD LoadGraphicInstance (DWORD res); +extern DWORD LoadGraphic (DWORD res); +extern DRAWABLE LoadDisplayPixmap (PRECT area, FRAME frame); +extern FONT SetContextFont (FONT Font); +extern BOOLEAN DestroyFont (FONT_REF FontRef); +extern FONT CaptureFont (FONT_REF FontRef); +extern FONT_REF ReleaseFont (FONT Font); +extern BOOLEAN TextRect (PTEXT pText, PRECT pRect, PBYTE pdelta); +extern BOOLEAN GetContextFontLeading (PSIZE pheight); +extern COUNT GetFrameCount (FRAME Frame); +extern COUNT GetFrameIndex (FRAME Frame); +extern FRAME SetAbsFrameIndex (FRAME Frame, COUNT FrameIndex); +extern FRAME SetRelFrameIndex (FRAME Frame, SIZE FrameOffs); +extern FRAME SetEquFrameIndex (FRAME DstFrame, FRAME SrcFrame); +extern FRAME IncFrameIndex (FRAME Frame); +extern FRAME DecFrameIndex (FRAME Frame); + +extern void XFlipFrame (FRAME Frame); +extern FRAME CaptureDrawable (DRAWABLE Drawable); + +extern DRAWABLE ReleaseDrawable (FRAME Frame); +extern MEM_HANDLE GetFrameHandle (FRAME Frame); + +extern POLYREF CreatePolygon (COUNT PtCount); +extern POLYGON CapturePolygon (POLYREF PolyRef); +extern BOOLEAN SetPolygonPoint (POLYGON Polygon, COUNT PtIndex, COORD x, + COORD y); +extern BOOLEAN GetPolygonPoint (POLYGON Polygon, COUNT PtIndex, PCOORD + px, PCOORD py); +extern POLYREF ReleasePolygon (POLYGON Polygon); +extern BOOLEAN DestroyPolygon (POLYREF PolyRef); + +extern DRAWABLE CreateOverlayWindow (CREATE_FLAGS CreateFlags, FRAME + Display, SIZE height); +extern void ShowOverlayWin (FRAME WinFrame, COUNT TimeInterval); +extern void HideOverlayWin (FRAME WinFrame, COUNT TimeInterval); +extern BOOLEAN DestroyOverlayWindow (FRAME Display, DRAWABLE Drawable); +extern void ScrollDisplay (FRAME Display, COORD x, COORD y); + +extern BOOLEAN ReadColorMap (COLORMAPPTR ColorMapPtr); +extern BOOLEAN SetColorMap (COLORMAPPTR ColorMapPtr); +extern BOOLEAN BatchColorMap (COLORMAPPTR ColorMapPtr); +extern CYCLE_REF CycleColorMap (COLORMAPPTR ColorMapPtr, COUNT Cycles, + SIZE TimeInterval); +extern void StopCycleColorMap (CYCLE_REF CycleRef); +extern DWORD XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval); +extern void FlushColorXForms (void); +#define InitColorMapResources InitStringTableResources +#define LoadColorMapFile LoadStringTableFile +#define LoadColorMapInstance LoadStringTableInstance +#define CaptureColorMap CaptureStringTable +#define ReleaseColorMap ReleaseStringTable +#define DestroyColorMap DestroyStringTable +#define GetColorMapRef GetStringTable +#define GetColorMapCount GetStringTableCount +#define GetColorMapIndex GetStringTableIndex +#define SetAbsColorMapIndex SetAbsStringTableIndex +#define SetRelColorMapIndex SetRelStringTableIndex +#define GetColorMapLength GetStringLength +#define GetColorMapAddress GetStringAddress +#define GetColorMapContents GetStringContents + +#endif /* _GFX_PROTOS */ + diff --git a/sc2/src/sc2code/libs/graphics/Makefile.am b/sc2/src/sc2code/libs/graphics/Makefile.am new file mode 100644 index 000000000..0e2127928 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/Makefile.am @@ -0,0 +1,22 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +CFLAGS = -Wall + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libgraphics.la + +libgraphics_la_SOURCES = clipline.c context.c drawable.c filegfx.c font.c \ + frame.c intersec.c line.c loaddisp.c makepoly.c map.c \ + pixmap.c poly.c rect.c resgfx.c stamp.c boxint.c getbody.c + +#libgraphics_la_LDFLAGS = @SMPEG_LIBS@ + +noinst_HEADERS = context.h display.h drawable.h font.h gfxintrn.h + diff --git a/sc2/src/sc2code/libs/graphics/boxint.c b/sc2/src/sc2code/libs/graphics/boxint.c new file mode 100644 index 000000000..38c7fee6b --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/boxint.c @@ -0,0 +1,159 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +INTERSECT_CODE +BoxIntersect (PRECT pr1, PRECT pr2, PRECT pinter) +{ + register INTERSECT_CODE intersect_code; + register COORD x1; + register SIZE w1, w2, delta; + + intersect_code = INTERSECT_NOCLIP; + + x1 = pr1->corner.x - pr2->corner.x; + + w1 = pr1->extent.width; + w2 = pr2->extent.width; + if ((delta = w2 - x1) <= w1) + { + if (delta != w1) + { + w1 = delta; + intersect_code &= ~INTERSECT_NOCLIP; + } + intersect_code |= INTERSECT_RIGHT; + } + if (x1 <= 0) + { + if (x1 < 0) + { + w1 += x1; + x1 = 0; + intersect_code &= ~INTERSECT_NOCLIP; + } + intersect_code |= INTERSECT_LEFT; + } + + if (w1 > 0) + { +#define h2 w2 + register COORD y1; + register SIZE h1; + + y1 = pr1->corner.y - pr2->corner.y; + + h1 = pr1->extent.height; + h2 = pr2->extent.height; + if ((delta = h2 - y1) <= h1) + { + if (delta != h1) + { + h1 = delta; + intersect_code &= ~INTERSECT_NOCLIP; + } + intersect_code |= INTERSECT_BOTTOM; + } + if (y1 <= 0) + { + if (y1 < 0) + { + h1 += y1; + y1 = 0; + intersect_code &= ~INTERSECT_NOCLIP; + } + intersect_code |= INTERSECT_TOP; + } + + if (h1 > 0) + { + pinter->corner.x = x1 + pr2->corner.x; + pinter->corner.y = y1 + pr2->corner.y; + pinter->extent.width = w1; + pinter->extent.height = h1; + + return (intersect_code); + } +#undef h2 + } + + return ((INTERSECT_CODE)0); +} + +void +BoxUnion (PRECT pr1, PRECT pr2, PRECT punion) +{ + COORD x2, y2, w2, h2; +#if 1 /* alter based on 0 widths */ + + x2 = + (pr1->corner.x < pr2->corner.x)? pr1->corner.x : pr2->corner.x; + + y2 = + (pr1->corner.y < pr2->corner.y)? pr1->corner.y : pr2->corner.y; + + w2 = ( + ((pr1->corner.x + pr1->extent.width) > (pr2->corner.x + pr2->extent.width))? + (pr1->corner.x + pr1->extent.width) : (pr2->corner.x + pr2->extent.width) + ) - punion->corner.x; + + h2 = ( + ((pr1->corner.y + pr1->extent.height) > (pr2->corner.y + pr2->extent.height))? + (pr1->corner.y + pr1->extent.height) : (pr2->corner.y + pr2->extent.height) + ) - punion->corner.y; +#else + SIZE delta; + COORD x1, y1, w1, h1; + + x1 = pr1->corner.x; + w1 = pr1->extent.width; + x2 = pr2->corner.x; + w2 = pr2->extent.width; + if ((delta = x1 - x2) >= 0) + w1 += delta; + else + { + w2 -= delta; + x2 += delta; + } + + y1 = pr1->corner.y; + h1 = pr1->extent.height; + y2 = pr2->corner.y; + h2 = pr2->extent.height; + if ((delta = y1 - y2) >= 0) + h1 += delta; + else + { + h2 -= delta; + y2 += delta; + } + + if ((delta = w1 - w2) > 0) + w2 += delta; + if ((delta = h1 - h2) > 0) + h2 += delta; +#endif + + punion->corner.x = x2; + punion->corner.y = y2; + punion->extent.width = w2; + punion->extent.height = h2; +} + diff --git a/sc2/src/sc2code/libs/graphics/clipline.c b/sc2/src/sc2code/libs/graphics/clipline.c new file mode 100644 index 000000000..8782f741e --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/clipline.c @@ -0,0 +1,241 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +INTERSECT_CODE +_clip_line (PRECT pClipRect, PBRESENHAM_LINE pLine) +{ + COORD p; + COORD x0, y0, xmin, ymin, xmax, ymax; + SIZE abs_delta_x, abs_delta_y; + INTERSECT_CODE intersect_code; + + xmin = pClipRect->corner.x; + ymin = pClipRect->corner.y; + xmax = pClipRect->corner.x + pClipRect->extent.width - 1; + ymax = pClipRect->corner.y + pClipRect->extent.height - 1; + if (pLine->first.x <= pLine->second.x) + pLine->end_points_exchanged = FALSE; + else + { + p = pLine->first.x; + pLine->first.x = pLine->second.x; + pLine->second.x = p; + + p = pLine->first.y; + pLine->first.y = pLine->second.y; + pLine->second.y = p; + + pLine->end_points_exchanged = TRUE; + } + + if (pLine->first.x > xmax || pLine->second.x < xmin || + (pLine->first.y > ymax && pLine->second.y > ymax) || + (pLine->first.y < ymin && pLine->second.y < ymin)) + return ((INTERSECT_CODE)0); + + intersect_code = INTERSECT_NOCLIP; + x0 = y0 = 0; + abs_delta_x = (pLine->second.x - pLine->first.x) << 1; + abs_delta_y = (pLine->second.y - pLine->first.y) << 1; + pLine->abs_delta_x = abs_delta_x; + pLine->abs_delta_y = abs_delta_y; + if (abs_delta_y == 0) + { + if (pLine->first.x < xmin) + { + pLine->first.x = xmin; + intersect_code |= INTERSECT_LEFT; + } + if (pLine->second.x > xmax) + { + pLine->second.x = xmax; + intersect_code |= INTERSECT_RIGHT; + } + } + else if (abs_delta_x == 0) + { + if (abs_delta_y < 0) + { + p = pLine->first.y; + pLine->first.y = pLine->second.y; + pLine->second.y = p; + + pLine->abs_delta_y = + abs_delta_y = -abs_delta_y; + } + + if (pLine->first.y < ymin) + { + pLine->first.y = ymin; + intersect_code |= INTERSECT_TOP; + } + if (pLine->second.y > ymax) + { + pLine->second.y = ymax; + intersect_code |= INTERSECT_BOTTOM; + } + } + else + { + COORD x1, y1; + + p = pLine->first.x; + x1 = pLine->second.x - p; + xmin = xmin - p; + xmax = xmax - p; + + p = pLine->first.y; + if (abs_delta_y > 0) + { + y1 = pLine->second.y - p; + ymin = ymin - p; + ymax = ymax - p; + } + else + { + y1 = p - pLine->second.y; + ymin = p - ymin; + ymax = p - ymax; + + p = ymin; + ymin = ymax; + ymax = p; + abs_delta_y = -abs_delta_y; + } + + if (abs_delta_x > abs_delta_y) + { + SIZE half_dx; + + half_dx = abs_delta_x >> 1; + if (x0 < xmin) + { + if ((y0 = (COORD)(((long)abs_delta_y * + (x0 = xmin) + half_dx) / abs_delta_x)) > ymax) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_LEFT; + } + if (x1 > xmax) + { + if ((y1 = (COORD)(((long)abs_delta_y * + (x1 = xmax) + half_dx) / abs_delta_x)) < ymin) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_RIGHT; + } + if (y0 < ymin) + { + if ((x0 = (COORD)(((long)abs_delta_x * + (y0 = ymin) - half_dx + (abs_delta_y - 1)) / + abs_delta_y)) > xmax) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_TOP; + intersect_code &= ~INTERSECT_LEFT; + } + if (y1 > ymax) + { + if ((x1 = (COORD)(((long)abs_delta_x * + ((y1 = ymax) + 1) - half_dx + (abs_delta_y - 1)) / + abs_delta_y) - 1) < xmin) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_BOTTOM; + intersect_code &= ~INTERSECT_RIGHT; + } + } + else + { + SIZE half_dy; + + half_dy = abs_delta_y >> 1; + if (y0 < ymin) + { + if ((x0 = (COORD)(((long)abs_delta_x * + (y0 = ymin) + half_dy) / abs_delta_y)) > xmax) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_TOP; + } + if (y1 > ymax) + { + if ((x1 = (COORD)(((long)abs_delta_x * + (y1 = ymax) + half_dy) / abs_delta_y)) < xmin) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_BOTTOM; + } + if (x0 < xmin) + { + if ((y0 = (COORD)(((long)abs_delta_y * + (x0 = xmin) - half_dy + (abs_delta_x - 1)) / + abs_delta_x)) > ymax) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_LEFT; + intersect_code &= ~INTERSECT_TOP; + } + if (x1 > xmax) + { + if ((y1 = (COORD)(((long)abs_delta_y * + ((x1 = xmax) + 1) - half_dy + (abs_delta_x - 1)) / + abs_delta_x) - 1) < ymin) + return ((INTERSECT_CODE)0); + intersect_code |= INTERSECT_RIGHT; + intersect_code &= ~INTERSECT_BOTTOM; + } + } + + pLine->second.x = pLine->first.x + x1; + pLine->first.x += x0; + if (pLine->abs_delta_y > 0) + { + pLine->second.y = pLine->first.y + y1; + pLine->first.y += y0; + } + else + { + INTERSECT_CODE y_code; + + pLine->second.y = pLine->first.y - y1; + pLine->first.y -= y0; + + y_code = (INTERSECT_CODE)(intersect_code + & (INTERSECT_TOP | INTERSECT_BOTTOM)); + if (y_code && y_code != (INTERSECT_TOP | INTERSECT_BOTTOM)) + intersect_code ^= (INTERSECT_TOP | INTERSECT_BOTTOM); + } + } + + if (!(intersect_code & INTERSECT_ALL_SIDES)) + { + if (abs_delta_x > abs_delta_y) + pLine->error_term = -(SIZE)(abs_delta_x >> 1); + else + pLine->error_term = -(SIZE)(abs_delta_y >> 1); + } + else + { + intersect_code &= ~INTERSECT_NOCLIP; + if (abs_delta_x > abs_delta_y) + pLine->error_term = (SIZE)((x0 * (long)abs_delta_y) - + (y0 * (long)abs_delta_x)) - (abs_delta_x >> 1); + else + pLine->error_term = (SIZE)((y0 * (long)abs_delta_x) - + (x0 * (long)abs_delta_y)) - (abs_delta_y >> 1); + } + + return (pLine->intersect_code = intersect_code); +} + diff --git a/sc2/src/sc2code/libs/graphics/context.c b/sc2/src/sc2code/libs/graphics/context.c new file mode 100644 index 000000000..c0f6fee00 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/context.c @@ -0,0 +1,257 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +GRAPHICS_STATUS _GraphicsStatusFlags; +CONTEXTPTR _pCurContext; + +PRIMITIVE _locPrim; + +FONTPTR _CurFontPtr; + +CONTEXT +SetContext (CONTEXT Context) +{ + CONTEXT LastContext; + + if (Context != (LastContext = (CONTEXT)_pCurContext)) + { + if (LastContext) + { + UnsetContextFlags ( + MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE) + ); + SetContextFlags ( + MAKE_WORD (0, _GraphicsStatusFlags + & (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)) + ); + + DeactivateContext (); + } + + _pCurContext = (CONTEXTPTR)Context; + if (_pCurContext) + { + ActivateContext (); + + _GraphicsStatusFlags &= ~(GRAPHICS_ACTIVE | DRAWABLE_ACTIVE); + _GraphicsStatusFlags |= HIBYTE (_get_context_flags ()); + + SetPrimColor (&_locPrim, _get_context_fg_color ()); + + _CurFramePtr = (FRAMEPTR)_get_context_fg_frame (); + BGFrame = _get_context_bg_frame (); + _CurFontPtr = (FONTPTR)_get_context_font (); + } + } + + return (LastContext); +} + +CONTEXT_REF +CreateContext (void) +{ + CONTEXT_REF ContextRef; + + ContextRef = AllocContext (); + if (ContextRef) + { + CONTEXT OldContext; + + /* initialize context */ + OldContext = SetContext (CaptureContext (ContextRef)); + SetContextMapType (MAP_NOXFORM); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + ); + SetContextBackGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) + ); + SetContextClipping (TRUE); + ReleaseContext (SetContext (OldContext)); + } + + return (ContextRef); +} + +BOOLEAN +DestroyContext (CONTEXT_REF ContextRef) +{ + if (ContextRef == 0) + return (FALSE); + + if (_pCurContext && _pCurContext->ContextRef == ContextRef) + SetContext ((CONTEXT)0); + + return (FreeContext (ContextRef)); +} + +CONTEXT +CaptureContext (CONTEXT_REF ContextRef) +{ + CONTEXTPTR ContextPtr; + + ContextPtr = LockContext (ContextRef); + if (ContextPtr) + ContextPtr->ContextRef = ContextRef; + + return ((CONTEXT)ContextPtr); +} + +CONTEXT_REF +ReleaseContext (CONTEXT Context) +{ + CONTEXTPTR ContextPtr; + + ContextPtr = (CONTEXTPTR)Context; + if (ContextPtr) + { + CONTEXT_REF ContextRef; + + ContextRef = ContextPtr->ContextRef; + UnlockContext (ContextRef); + + return (ContextRef); + } + + return (0); +} + +DRAW_STATE +GetContextDrawState (void) +{ + if (!ContextActive ()) + return (DEST_PIXMAP | DRAW_REPLACE); + + return (_get_context_draw_state ()); +} + +DRAW_STATE +SetContextDrawState (DRAW_STATE DrawState) +{ + DRAW_STATE oldState; + + if (!ContextActive ()) + return (DEST_PIXMAP | DRAW_REPLACE); + + if ((oldState = _get_context_draw_state ()) != DrawState) + { + SwitchContextDrawState (DrawState); + SetContextGraphicsFunctions (); + } + + return (oldState); +} + +COLOR +SetContextForeGroundColor (COLOR Color) +{ + COLOR oldColor; + + if (!ContextActive ()) + return (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + + if ((oldColor = _get_context_fg_color ()) != Color) + { + SwitchContextForeGroundColor (Color); + } + SetPrimColor (&_locPrim, Color); + + return (oldColor); +} + +COLOR +SetContextBackGroundColor (COLOR Color) +{ + COLOR oldColor; + + if (!ContextActive ()) + return (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); + + if ((oldColor = _get_context_bg_color ()) != Color) + { + SwitchContextBackGroundColor (Color); + } + + return (oldColor); +} + +BG_FUNC +SetContextBGFunc (BG_FUNC BGFunc) +{ + BG_FUNC oldBGFunc; + + if (!ContextActive ()) + return (0); + + if ((oldBGFunc = _get_context_bg_func ()) != BGFunc) + { + SwitchContextBGFunc (BGFunc); + } + + return (oldBGFunc); +} + +BOOLEAN +SetContextClipping (BOOLEAN ClipStatus) +{ + BOOLEAN oldClipStatus; + + if (!ContextActive ()) + return (TRUE); + + oldClipStatus = (_get_context_flags () & BATCH_CLIP_GRAPHICS) != 0; + if (ClipStatus) + { + SetContextFlags (BATCH_CLIP_GRAPHICS); + } + else + { + UnsetContextFlags (BATCH_CLIP_GRAPHICS); + } + + return (oldClipStatus); +} + +BOOLEAN +SetContextClipRect (PRECT lpRect) +{ + if (!ContextActive ()) + return (FALSE); + + if (lpRect) + _pCurContext->ClipRect = *lpRect; + else + _pCurContext->ClipRect.extent.width = 0; + + return (TRUE); +} + +BOOLEAN +GetContextClipRect (PRECT lpRect) +{ + if (!ContextActive ()) + return (FALSE); + + *lpRect = _pCurContext->ClipRect; + return (lpRect->extent.width != 0); +} + + diff --git a/sc2/src/sc2code/libs/graphics/context.h b/sc2/src/sc2code/libs/graphics/context.h new file mode 100644 index 000000000..1b0c5ae97 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/context.h @@ -0,0 +1,189 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CONTEXT_H +#define _CONTEXT_H + +#ifdef MAPPING +typedef struct +{ + MAP_TYPE MapType; + EXTENT ViewExt; /* Device units per inch */ + EXTENT WinExt; /* Logical units per inch */ + POINT WinOrg; + /* Translation to device units relative to + * (0, 0) is as follows: + * x_du = (x_lu - WinOrg.x) * ViewExt.x / WinExt.x; + * y_du = (y_lu - WinOrg.y) * ViewExt.y / WinExt.y; + */ +} MAP_INFO; +typedef MAP_INFO *PMAP_INFO; +#endif /* MAPPING */ + +typedef struct +{ + CONTEXT_REF ContextRef; + UWORD Flags; + + DRAW_STATE DrawState; + COLOR ForeGroundColor, BackGroundColor; + FRAME ForeGroundFrame, BackGroundFrame; + void (**func_array) (PRECT pClipRect, PPRIMITIVE PrimPtr); + FONT Font; + BG_FUNC BackGroundFunc; + + RECT ClipRect; +#ifdef MAPPING + MAP_INFO Map; +#endif /* MAPPING */ +} CONTEXT_DESC; +typedef CONTEXT_DESC *PCONTEXT_DESC; + +#define CONTEXT_PRIORITY DEFAULT_MEM_PRIORITY + +#define CONTEXTPTR PCONTEXT_DESC + +#define AllocContext() \ + (CONTEXT_REF)mem_allocate ((MEM_SIZE)sizeof (CONTEXT_DESC), \ + MEM_ZEROINIT | MEM_PRIMARY, CONTEXT_PRIORITY, MEM_SIMPLE) +#define LockContext (CONTEXTPTR)mem_lock +#define UnlockContext mem_unlock +#define FreeContext mem_release + +extern CONTEXTPTR _pCurContext; +extern PRIMITIVE _locPrim; + +#define _get_context_fg_color() (_pCurContext->ForeGroundColor) +#define _get_context_bg_color() (_pCurContext->BackGroundColor) +#define _get_context_draw_state() (_pCurContext->DrawState) +#define _get_context_draw_dest() ((DRAW_DESTINATION)(_pCurContext->DrawState & 0xFF00)) +#define _get_context_draw_mode() ((DRAW_MODE)LOBYTE (_pCurContext->DrawState)) +#define _get_context_flags() (_pCurContext->Flags) +#define _get_context_fg_frame() (_pCurContext->ForeGroundFrame) +#define _get_context_bg_frame() (_pCurContext->BackGroundFrame) +#define _get_context_font() (_pCurContext->Font) +#define _get_context_bg_func() (_pCurContext->BackGroundFunc) + +#ifdef MAPPING +#define _get_context_map_type() (_pCurContext->Map.MapType) +#define _init_context_map(pmt) \ + COORD worg_x, worg_y; \ + SIZE vext_w, vext_h, wext_w, wext_h; \ + \ + if ((*(pmt) = _get_context_map_type ()) != MAP_NOXFORM) \ + worg_x = _pCurContext->Map.WinOrg.x, \ + worg_y = _pCurContext->Map.WinOrg.y, \ + vext_w = _pCurContext->Map.ViewExt.width, \ + vext_h = _pCurContext->Map.ViewExt.height, \ + wext_w = _pCurContext->Map.WinExt.width, \ + wext_h = _pCurContext->Map.WinExt.height +#define _uninit_context_map() +#define LXtoDX(x) ((((x) - worg_x) * vext_w) / wext_w) +#define LYtoDY(y) ((((y) - worg_y) * vext_h) / wext_h) +#define DXtoLX(x) ((((x) * wext_w) / vext_w) + worg_x) +#define DYtoLY(y) ((((y) * wext_h) / vext_h) + worg_y) +#define SwitchContextMapType(t) \ +{ \ + _pCurContext->Map.MapType = (t); \ +} +#define SwitchContextWinOrigin(org) (_pCurContext->Map.WinOrg = *(org)) +#define SwitchContextViewExtents(ext) (_pCurContext->Map.ViewExt = *(ext)) +#define SwitchContextWinExtents(ext) (_pCurContext->Map.WinExt = *(ext)) +#endif /* MAPPING */ + +#define SwitchContextDrawState(s) \ +{ \ + _pCurContext->DrawState = (s); \ +} +#define SwitchContextForeGroundColor(c) \ +{ \ + _pCurContext->ForeGroundColor = (c); \ +} +#define SwitchContextBackGroundColor(c) \ +{ \ + _pCurContext->BackGroundColor = (c); \ +} +#define SetContextFlags(f) \ +{ \ + _pCurContext->Flags |= (f); \ +} +#define UnsetContextFlags(f) \ +{ \ + _pCurContext->Flags &= ~(f); \ +} +#define SwitchContextFGFrame(f) \ +{ \ + _pCurContext->ForeGroundFrame = (f); \ +} +#define SwitchContextBGFrame(f) \ +{ \ + _pCurContext->BackGroundFrame = (f); \ +} +#define SwitchContextFont(f) \ +{ \ + _pCurContext->Font = (f); \ +} +#define SwitchContextBGFunc(f) \ +{ \ + _pCurContext->BackGroundFunc = (f); \ +} + +/* +#define BATCH_BUILD_PAGE (BATCH_FLAGS)(1 << 0) +#define BATCH_SINGLE (BATCH_FLAGS)(1 << 1) +#define BATCH_UPDATE_DRAWABLE (BATCH_FLAGS)(1 << 2) +*/ +#define BATCH_CLIP_GRAPHICS (BATCH_FLAGS)(1 << 3) +#define BATCH_XFORM (BATCH_FLAGS)(1 << 4) +#define BATCH_DIRTY_TILES (BATCH_FLAGS)(1 << 7) + +typedef BYTE GRAPHICS_STATUS; + +extern GRAPHICS_STATUS _GraphicsStatusFlags; +#define GRAPHICS_ACTIVE (GRAPHICS_STATUS)(1 << 0) +#define GRAPHICS_VISIBLE (GRAPHICS_STATUS)(1 << 1) +#define CONTEXT_ACTIVE (GRAPHICS_STATUS)(1 << 2) +#define DRAWABLE_ACTIVE (GRAPHICS_STATUS)(1 << 3) +#define DISPLAY_ACTIVE (GRAPHICS_STATUS)(1 << 5) +#define DeactivateGraphics() (_GraphicsStatusFlags &= ~GRAPHICS_ACTIVE) +#define ActivateGraphics() (_GraphicsStatusFlags |= GRAPHICS_ACTIVE) +#define GraphicsActive() (_GraphicsStatusFlags & GRAPHICS_ACTIVE) +#define DeactivateVisible() (_GraphicsStatusFlags &= ~GRAPHICS_VISIBLE) +#define ActivateVisible() (_GraphicsStatusFlags |= GRAPHICS_VISIBLE) +#define DeactivateDisplay() (_GraphicsStatusFlags &= ~DISPLAY_ACTIVE) +#define ActivateDisplay() (_GraphicsStatusFlags |= DISPLAY_ACTIVE) +#define DisplayActive() (_GraphicsStatusFlags & DISPLAY_ACTIVE) +#define DeactivateContext() (_GraphicsStatusFlags &= ~CONTEXT_ACTIVE) +#define ActivateContext() (_GraphicsStatusFlags |= CONTEXT_ACTIVE) +#define ContextActive() (_GraphicsStatusFlags & CONTEXT_ACTIVE) +#define DeactivateDrawable() (_GraphicsStatusFlags &= ~DRAWABLE_ACTIVE) +#define ActivateDrawable() (_GraphicsStatusFlags |= DRAWABLE_ACTIVE) +#define DrawableActive() (_GraphicsStatusFlags & DRAWABLE_ACTIVE) + +#define SYSTEM_ACTIVE (GRAPHICS_STATUS)( \ + DISPLAY_ACTIVE | CONTEXT_ACTIVE | \ + DRAWABLE_ACTIVE \ + ) +#define GraphicsSystemActive() \ + ((_GraphicsStatusFlags & SYSTEM_ACTIVE) == SYSTEM_ACTIVE) +#define GraphicsStatus() \ + (_GraphicsStatusFlags & (GRAPHICS_STATUS)(GRAPHICS_ACTIVE \ + | GRAPHICS_VISIBLE)) + +#endif /* _CONTEXT_H */ + diff --git a/sc2/src/sc2code/libs/graphics/display.h b/sc2/src/sc2code/libs/graphics/display.h new file mode 100644 index 000000000..0ead22e17 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/display.h @@ -0,0 +1,74 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DISPLAY_H +#define _DISPLAY_H + +/* +#define WANT_MASK (CREATE_FLAGS)(1 << 0) +#define WANT_PIXMAP (CREATE_FLAGS)(1 << 1) +*/ +#define WANT_COMPRESSED (CREATE_FLAGS)(1 << 2) +#define DOUBLE_RES (CREATE_FLAGS)(1 << 3) + +typedef struct +{ + CREATE_FLAGS DisplayFlags; + + BYTE DisplayDepth; + COUNT DisplayWidth, DisplayHeight; + + DRAWABLE (*alloc_image) (COUNT NumFrames, DRAWABLE_TYPE DrawableType, + CREATE_FLAGS flags, SIZE width, SIZE height); + + void (*read_display) (PRECT pRect, FRAMEPTR DstFramePtr); + + void (**graphics_func_array) (PRECT pClipRect, PRIMITIVEPTR + PrimPtr); +} DISPLAY_INTERFACE; +typedef DISPLAY_INTERFACE *PDISPLAY_INTERFACE; + +extern PDISPLAY_INTERFACE _pCurDisplay; + +extern void (* mask_func_array[]) (PRECT pClipRect, + PRIMITIVEPTR PrimPtr); + +#define AllocDrawableImage (*_pCurDisplay->alloc_image) +#define DrawGraphicsFunc(pRect,pPtr) \ + (*_pCurContext->func_array[GetPrimType(pPtr)]) (pRect, (PRIMITIVEPTR)(pPtr)) +#define ReadDisplay (*_pCurDisplay->read_display) +extern void _bitplane_blt (PRECT pClipRect, FRAMEPTR + DstFramePtr, COORD src_x, COORD src_y, FRAMEPTR + SrcFramePtr, DRAW_MODE DrawMode); + +#define GetDisplayFlags() (_pCurDisplay->DisplayFlags) +#define GetDisplayDepth() (_pCurDisplay->DisplayDepth) +#define GetDisplayWidth() (_pCurDisplay->DisplayWidth) +#define GetDisplayHeight() (_pCurDisplay->DisplayHeight) + +#define SetContextGraphicsFunctions() \ +do \ +{ \ + if (_get_context_draw_dest () == DEST_MASK) \ + _pCurContext->func_array = mask_func_array; \ + else \ + _pCurContext->func_array = _pCurDisplay->graphics_func_array; \ +} while (0) + +#endif /* _DISPLAY_H */ + diff --git a/sc2/src/sc2code/libs/graphics/drawable.c b/sc2/src/sc2code/libs/graphics/drawable.c new file mode 100644 index 000000000..987adf27b --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/drawable.c @@ -0,0 +1,301 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" +#include "SDL_wrapper.h" + +FRAMEPTR _CurFramePtr; + +FRAME +SetContextFGFrame (FRAME Frame) +{ + FRAME LastFrame; + + if (Frame != (LastFrame = (FRAME)_CurFramePtr)) + { + if (LastFrame) + DeactivateDrawable (); + + _CurFramePtr = (FRAMEPTR)Frame; + if (_CurFramePtr) + ActivateDrawable (); + + if (ContextActive ()) + { + SwitchContextFGFrame (Frame); + SetContextGraphicsFunctions (); + } + } + + return (LastFrame); +} + +FRAME +SetContextBGFrame (FRAME Frame) +{ + FRAME LastFrame; + + LastFrame = BGFrame; + BGFrame = Frame; + if (ContextActive ()) + SwitchContextBGFrame (Frame); + + return (LastFrame); +} + +DRAWABLE +_request_drawable (COUNT NumFrames, DRAWABLE_TYPE DrawableType, + CREATE_FLAGS flags, SIZE width, SIZE height) +{ + DRAWABLE Drawable; + + Drawable = AllocDrawableImage ( + NumFrames, DrawableType, flags, width, height + ); + if (Drawable) + { + DRAWABLEPTR DrawablePtr; + + if ((DrawablePtr = LockDrawable (Drawable)) == 0) + { + FreeDrawable (Drawable); + Drawable = 0; + } + else + { + int imgw, imgh; + FRAMEPTR FramePtr; + + DrawablePtr->hDrawable = GetDrawableHandle (Drawable); + TYPE_SET (DrawablePtr->FlagsAndIndex, flags << FTYPE_SHIFT); + INDEX_SET (DrawablePtr->FlagsAndIndex, NumFrames - 1); + + imgw = (flags & MAPPED_TO_DISPLAY) ? width * ScreenWidthActual / ScreenWidth : width; + imgh = (flags & MAPPED_TO_DISPLAY) ? height * ScreenHeightActual / ScreenHeight : height; + FramePtr = &DrawablePtr->Frame[NumFrames - 1]; + while (NumFrames--) + { + TFB_Image *Image; + + + if (DrawableType == RAM_DRAWABLE + && (Image = TFB_LoadImage (SDL_CreateRGBSurface ( + SDL_HWSURFACE, + imgw, + imgh, + 24, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0x00000000 + )))) + FramePtr->DataOffs = (BYTE *)Image - (BYTE *)FramePtr; + + TYPE_SET (FramePtr->TypeIndexAndFlags, DrawableType); + INDEX_SET (FramePtr->TypeIndexAndFlags, NumFrames); + SetFrameBounds (FramePtr, width, height); + --FramePtr; + } + UnlockDrawable (Drawable); + } + } + + return (Drawable); +} + +DRAWABLE +CreateDisplay (CREATE_FLAGS CreateFlags, PSIZE pwidth, PSIZE pheight) +{ + DRAWABLE Drawable; + + if (!DisplayActive ()) + return (0); + + Drawable = _request_drawable ( + (COUNT)1, (DRAWABLE_TYPE)SCREEN_DRAWABLE, + (CREATE_FLAGS)(CreateFlags & (WANT_PIXMAP | (GetDisplayFlags () & WANT_MASK))), + (SIZE)GetDisplayWidth (), + (SIZE)GetDisplayHeight () + ); + if (Drawable) + { + FRAMEPTR F; + + if ((F = CaptureDrawable (Drawable)) == 0) + DestroyDrawable (Drawable); + else + { + *pwidth = GetFrameWidth (F); + *pheight = GetFrameHeight (F); + + ReleaseDrawable (F); + return (Drawable); + } + } + + *pwidth = *pheight = 0; + return (0); +} + +DRAWABLE +CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width, SIZE height, COUNT + num_frames) +{ + DRAWABLE Drawable; + + if (!DisplayActive ()) + return (0); + + Drawable = _request_drawable ( + (COUNT)num_frames, (DRAWABLE_TYPE)RAM_DRAWABLE, + (CREATE_FLAGS)(CreateFlags & (WANT_MASK | WANT_PIXMAP | MAPPED_TO_DISPLAY)), + (SIZE)width, (SIZE)height + ); + if (Drawable) + { + FRAMEPTR F; + + F = CaptureDrawable (Drawable); + if (F) + { + ReleaseDrawable (F); + + return (Drawable); + } + } + + return (0); +} + +DRAWABLE +CopyDrawable (DRAWABLE Drawable) +{ + DRAWABLEPTR DrawablePtr; + + DrawablePtr = LockDrawable (Drawable); + if (DrawablePtr) + { + DRAWABLE CopyDrawable; + DWORD size; + + if (TYPE_GET (DrawablePtr->Frame[0].TypeIndexAndFlags) == SCREEN_DRAWABLE) + CopyDrawable = 0; + else if ((CopyDrawable = AllocDrawable (1, + (size = mem_get_size ((MEM_HANDLE)Drawable)) + - sizeof (DRAWABLE_DESC)))) + { + DRAWABLEPTR CopyDrawablePtr; + + if ((CopyDrawablePtr = LockDrawable (CopyDrawable)) == 0) + { + FreeDrawable (CopyDrawable); + CopyDrawable = 0; + } + else + { + PBYTE lpDst, lpSrc; + + lpDst = (PBYTE)CopyDrawablePtr; + lpSrc = (PBYTE)DrawablePtr; + do + { + COUNT num_bytes; + + num_bytes = size >= 0x7FFF ? 0x7FFF : (COUNT)size; + memcpy (lpDst, lpSrc, num_bytes); + FAR_PTR_ADD (&lpDst, num_bytes); + FAR_PTR_ADD (&lpSrc, num_bytes); + size -= num_bytes; + } while (size); + CopyDrawablePtr->hDrawable = (MEM_HANDLE)CopyDrawable; + UnlockDrawable (CopyDrawable); + } + } + UnlockDrawable (Drawable); + + return (CopyDrawable); + } + + return (0); +} + +BOOLEAN +DestroyDrawable (DRAWABLE Drawable) +{ + DRAWABLEPTR DrawablePtr; + + if (LOWORD (Drawable) == GetFrameHandle (_CurFramePtr)) + SetContextFGFrame ((FRAME)0); + if (LOWORD (Drawable) == GetFrameHandle (BGFrame)) + SetContextBGFrame ((FRAME)0); + + DrawablePtr = LockDrawable (Drawable); + if (DrawablePtr) + { + UnlockDrawable (Drawable); + FreeDrawable (Drawable); + + return (TRUE); + } + + return (FALSE); +} + +BOOLEAN +GetFrameRect (FRAMEPTR FramePtr, PRECT pRect) +{ + if (FramePtr) + { + pRect->corner.x = -GetFrameHotX (FramePtr); + pRect->corner.y = -GetFrameHotY (FramePtr); + pRect->extent.width = GetFrameWidth (FramePtr); + pRect->extent.height = GetFrameHeight (FramePtr); + + return (TRUE); + } + + return (FALSE); +} + +HOT_SPOT +SetFrameHot (FRAMEPTR FramePtr, HOT_SPOT HotSpot) +{ + if (FramePtr) + { + HOT_SPOT OldHot; + + OldHot = GetFrameHotSpot (FramePtr); + SetFrameHotSpot (FramePtr, HotSpot); + + return (OldHot); + } + + return (MAKE_HOT_SPOT (0, 0)); +} + +HOT_SPOT +GetFrameHot (FRAMEPTR FramePtr) +{ + if (FramePtr) + { + return (GetFrameHotSpot (FramePtr)); + } + + return (MAKE_HOT_SPOT (0, 0)); +} + diff --git a/sc2/src/sc2code/libs/graphics/drawable.h b/sc2/src/sc2code/libs/graphics/drawable.h new file mode 100644 index 000000000..0e6d14012 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/drawable.h @@ -0,0 +1,172 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DRAWABLE_H +#define _DRAWABLE_H + +#include + +#define ValidPrimType(pt) ((pt)> 3) +#define BYTE_OFFS(x) ((BYTE)(x) & (BYTE)0x7) +#define BYTE_POS(x) ((x) >> 3) +#define WORD_WIDTH(w) (((w) + 15) >> 4) +#define WORD_OFFS(x) ((UWORD)(x) & (UWORD)0xF) +#define WORD_POS(x) ((x) >> 4) +#ifdef MSDOS +#define SCAN_WIDTH BYTE_WIDTH +#define PAD_WIDTH(w) ((w)+((sizeof (BYTE) << 3) - 1)) +#else /* !MSDOS */ +#define SCAN_WIDTH(w) ((BYTE_WIDTH(w)+1)&~1) +#define PAD_WIDTH(w) (w) +#endif /* MSDOS */ + +#define FTYPE_SHIFT 12 +#define FINDEX_MASK ((1 << FTYPE_SHIFT) - 1) +#define FTYPE_MASK (0xFFFF & ~FINDEX_MASK) + +#define ROM_DRAWABLE (0 << FTYPE_SHIFT) +#define RAM_DRAWABLE (1 << FTYPE_SHIFT) +#define SCREEN_DRAWABLE (2 << FTYPE_SHIFT) + +typedef UWORD DRAWABLE_TYPE; + +#define DATA_HARDWARE (1 << 12) +#define DATA_COPY (1 << 13) +#define DATA_PACKED (1 << 14) +#define X_FLIP (1 << 15) + +typedef struct +{ + DWORD TypeIndexAndFlags; + HOT_SPOT HotSpot; + DWORD Bounds; + long DataOffs; +} FRAME_DESC; +typedef FRAME_DESC *PFRAME_DESC; + +typedef struct +{ + MEM_HANDLE hDrawable; + + UWORD FlagsAndIndex; + FRAME_DESC Frame[1]; +} DRAWABLE_DESC; +typedef DRAWABLE_DESC *PDRAWABLE_DESC; + +#define GetFrameHotX(f) GET_HOT_X(((FRAMEPTR)(f))->HotSpot) +#define GetFrameHotY(f) GET_HOT_Y(((FRAMEPTR)(f))->HotSpot) +#define GetFrameHotSpot(f) (((FRAMEPTR)(f))->HotSpot) +#define SetFrameHotSpot(f,h) (((FRAMEPTR)(f))->HotSpot=(h)) +#define GetFrameWidth(f) LOWORD (((FRAMEPTR)(f))->Bounds) +#define GetFrameHeight(f) HIWORD (((FRAMEPTR)(f))->Bounds) +#define SetFrameBounds(f,w,h) (((FRAMEPTR)(f))->Bounds=MAKE_DWORD(w,h)) +#define GetFrameFlags(f) HIWORD(((FRAMEPTR)(f))->TypeIndexAndFlags) +#define AddFrameFlags(f,v) (((FRAMEPTR)(f))->TypeIndexAndFlags|=((DWORD)(v)<<16)) +#define SubFrameFlags(f,v) (((FRAMEPTR)(f))->TypeIndexAndFlags&=~((DWORD)(v)<<16)) + +#define DRAWABLE_PRIORITY DEFAULT_MEM_PRIORITY + +#define DRAWABLEPTR PDRAWABLE_DESC +#define FRAMEPTR PFRAME_DESC +#define COUNTPTR PCOUNT + +#define AllocDrawable(n,dc) \ + (DRAWABLE)mem_allocate ((MEM_SIZE)(sizeof (DRAWABLE_DESC) \ + + (sizeof (FRAME_DESC) * ((n) - 1))) + (dc), \ + MEM_ZEROINIT | MEM_GRAPHICS, \ + DRAWABLE_PRIORITY, MEM_SIMPLE) +#define LockDrawable(D) ((DRAWABLEPTR)mem_lock (GetDrawableHandle (D))) +#define UnlockDrawable(D) mem_unlock (GetDrawableHandle (D)) +#define FreeDrawable(D) _ReleaseCelData (GetDrawableHandle (D)) +#define GetDrawableHandle(D) ((MEM_HANDLE)LOWORD (D)) +#define GetDrawableIndex(D) ((COUNT)HIWORD (D)) +#define GetFrameParentDrawable(F) ((DRAWABLEPTR)((PBYTE)((F) \ + -((int)INDEX_GET((F)->TypeIndexAndFlags)-1)) \ + -sizeof(DRAWABLE_DESC))) + +#define NULL_DRAWABLE (DRAWABLE)NULL_PTR + +#define TYPE_GET(f) ((f) & FTYPE_MASK) +#define INDEX_GET(f) ((f) & FINDEX_MASK) +#define TYPE_SET(f,t) ((f)|=t) +#define INDEX_SET(f,i) ((f)|=i) + +typedef struct polygon_desc +{ + RECT BoundRect; + + POLYREF hPoly; + + COUNT PtCount; + PPOINT PtList; +} POLYGON_DESC; +typedef POLYGON_DESC *PPOLYGON_DESC; + +#define POLYGON_PRIORITY DEFAULT_MEM_PRIORITY + +#define AllocPolygon(n) \ + mem_allocate ((MEM_SIZE)(sizeof (POLYGON_DESC) + \ + (sizeof (POINT) * (n))), MEM_ZEROINIT, \ + POLYGON_PRIORITY, MEM_SIMPLE) +#define LockPolygon(Polygon) (PPOLYGON_DESC)mem_lock (Polygon) +#define UnlockPolygon(Polygon) mem_unlock (Polygon) +#define FreePolygon(Polygon) mem_release (Polygon) + +typedef struct +{ + RECT Box; + FRAMEPTR FramePtr; +} IMAGE_BOX; +typedef IMAGE_BOX *PIMAGE_BOX; + +extern DRAWABLE _request_drawable (COUNT NumFrames, DRAWABLE_TYPE + DrawableType, CREATE_FLAGS flags, SIZE width, SIZE height); +extern INTERSECT_CODE _clip_line (PRECT pClipRect, PBRESENHAM_LINE + pLine); + +extern MEM_HANDLE _GetCelData (FILE *fp, DWORD length); +extern BOOLEAN _ReleaseCelData (MEM_HANDLE handle); + +typedef PPRIMITIVE PRIMITIVEPTR; +typedef PPOINT POINTPTR; +typedef PRECT RECTPTR; +typedef PSTAMP STAMPPTR; +typedef PTEXT TEXTPTR; + +extern STAMP _save_stamp; +#define BGFrame _save_stamp.frame +extern FRAMEPTR _CurFramePtr; + +extern void _rect_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr); +extern void _text_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr); +extern void _fillpoly_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr); + +#endif /* _DRAWABLE_H */ + diff --git a/sc2/src/sc2code/libs/graphics/filegfx.c b/sc2/src/sc2code/libs/graphics/filegfx.c new file mode 100644 index 000000000..2b5ccf303 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/filegfx.c @@ -0,0 +1,54 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +DWORD +LoadCelFile (PVOID pStr) +{ + FILE *fp; + + if ((fp = OpenResFile (pStr, "rb")) != NULL) + { + MEM_HANDLE hData; + + hData = _GetCelData (fp, LengthResFile (fp)); + CloseResFile (fp); + return ((DWORD)hData); + } + + return (0); +} + +DWORD +LoadFontFile (PVOID pStr) +{ + FILE *fp; + + if ((fp = OpenResFile (pStr, "rb")) != NULL) + { + MEM_HANDLE hData; + + hData = _GetFontData (fp, LengthResFile (fp)); + CloseResFile (fp); + return ((DWORD)hData); + } + + return (0); +} + diff --git a/sc2/src/sc2code/libs/graphics/font.c b/sc2/src/sc2code/libs/graphics/font.c new file mode 100644 index 000000000..3924483e6 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/font.c @@ -0,0 +1,248 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +static BYTE char_delta_array[MAX_DELTAS]; + +FONT +SetContextFont (FONT Font) +{ + FONT LastFont; + + LastFont = (FONT)_CurFontPtr; + _CurFontPtr = (FONTPTR)Font; + if (ContextActive ()) + SwitchContextFont (Font); + + return (LastFont); +} + +BOOLEAN +DestroyFont (FONT_REF FontRef) +{ + if (FontRef == 0) + return (FALSE); + + if (_CurFontPtr && _CurFontPtr->FontRef == FontRef) + SetContextFont ((FONT)0); + + return (FreeFont (FontRef)); +} + +FONT +CaptureFont (FONT_REF FontRef) +{ + FONTPTR FontPtr; + + FontPtr = LockFont (FontRef); + if (FontPtr) + FontPtr->FontRef = FontRef; + + return ((FONT)FontPtr); +} + +FONT_REF +ReleaseFont (FONT Font) +{ + FONTPTR FontPtr; + + FontPtr = (FONTPTR)Font; + if (FontPtr) + { + FONT_REF FontRef; + + FontRef = FontPtr->FontRef; + UnlockFont (FontRef); + + return (FontRef); + } + + return (0); +} + +void +DrawText (PTEXT lpText) +{ + SetPrimType (&_locPrim, TEXT_PRIM); + _locPrim.Object.Text = *lpText; + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +BOOLEAN +GetContextFontLeading (PSIZE pheight) +{ + if (_CurFontPtr != 0) + { + *pheight = (SIZE)_CurFontPtr->Leading; + return (TRUE); + } + + *pheight = 0; + return (FALSE); +} + +BOOLEAN +TextRect (PTEXT lpText, register PRECT pRect, PBYTE pdelta) +{ + COUNT num_chars; + FONTPTR FontPtr; + + if ((FontPtr = _CurFontPtr) != 0 && (num_chars = lpText->CharCount)) + { + COORD top_y, bot_y; + SIZE width; + UNICODE next_ch, *pStr; + + if (pdelta == 0) + { + pdelta = char_delta_array; + if (num_chars > MAX_DELTAS) + num_chars = MAX_DELTAS; + } + + top_y = bot_y = 0; + width = 0; + pStr = lpText->pStr; + if ((next_ch = *pStr++) == '\0') + num_chars = 0; + next_ch -= FIRST_CHAR; + while (num_chars--) + { + UNICODE ch; + SIZE last_width; + + last_width = width; + + ch = next_ch; + if ((next_ch = *pStr++) == '\0') + num_chars = 0; + next_ch -= FIRST_CHAR; + if (ch < MAX_CHARS && GetFrameWidth (&FontPtr->CharDesc[ch])) + { + register COORD y; + + y = -GetFrameHotY (&FontPtr->CharDesc[ch]); + if (y < top_y) + top_y = y; + y += GetFrameHeight (&FontPtr->CharDesc[ch]); + if (y > bot_y) + bot_y = y; + + width += GetFrameWidth (&FontPtr->CharDesc[ch]); +#if 0 + if (num_chars && next_ch < MAX_CHARS + && !(FontPtr->KernTab[ch] + & (FontPtr->KernTab[next_ch] >> 2))) + width -= FontPtr->KernAmount; +#endif + } + + *pdelta++ = (BYTE)(width - last_width); + } + + lpText->CharCount = pStr - lpText->pStr - 1; + + if (width > 0 && (bot_y -= top_y) > 0) + { + /* subtract off default character spacing */ + --pdelta[-1]; + --width; + + if (lpText->align == ALIGN_LEFT) + pRect->corner.x = 0; + else if (lpText->align == ALIGN_CENTER) + pRect->corner.x = -(width >> 1); + else + pRect->corner.x = -width; + pRect->corner.y = top_y; + pRect->extent.width = width; + pRect->extent.height = bot_y; + + pRect->corner.x += lpText->baseline.x; + pRect->corner.y += lpText->baseline.y; + + return (TRUE); + } + } + + pRect->corner = lpText->baseline; + pRect->extent.width = 0; + pRect->extent.height = 0; + + return (FALSE); +} + +void +_text_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ + FONTPTR FontPtr; + + if ((FontPtr = _CurFontPtr) != 0) + { + COUNT num_chars; + UNICODE next_ch, *pStr; + TEXTPTR TextPtr; + PRIMITIVE locPrim; + + SetPrimType (&locPrim, STAMPFILL_PRIM); + SetPrimColor (&locPrim, _get_context_fg_color ()); + + TextPtr = &PrimPtr->Object.Text; + locPrim.Object.Stamp.origin.x = _save_stamp.origin.x; + locPrim.Object.Stamp.origin.y = TextPtr->baseline.y; + num_chars = TextPtr->CharCount; + + pStr = TextPtr->pStr; + if ((next_ch = *pStr++) == '\0') + num_chars = 0; + next_ch -= FIRST_CHAR; + while (num_chars--) + { + UNICODE ch; + + ch = next_ch; + if ((next_ch = *pStr++) == '\0') + num_chars = 0; + next_ch -= FIRST_CHAR; + locPrim.Object.Stamp.frame = &FontPtr->CharDesc[ch]; + if (ch < MAX_CHARS && GetFrameWidth (locPrim.Object.Stamp.frame)) + { + RECT r; + + r.corner.x = locPrim.Object.Stamp.origin.x + - GetFrameHotX (locPrim.Object.Stamp.frame); + r.corner.y = locPrim.Object.Stamp.origin.y + - GetFrameHotY (locPrim.Object.Stamp.frame); + r.extent.width = GetFrameWidth (locPrim.Object.Stamp.frame); + r.extent.height = GetFrameHeight (locPrim.Object.Stamp.frame); + _save_stamp.origin = r.corner; + if (BoxIntersect (&r, pClipRect, &r)) + DrawGraphicsFunc (&r, &locPrim); + + locPrim.Object.Stamp.origin.x += GetFrameWidth (locPrim.Object.Stamp.frame); +#if 0 + if (num_chars && next_ch < MAX_CHARS + && !(FontPtr->KernTab[ch] + & (FontPtr->KernTab[next_ch] >> 2))) + locPrim.Object.Stamp.origin.x -= FontPtr->KernAmount; +#endif + } + } + } +} diff --git a/sc2/src/sc2code/libs/graphics/font.h b/sc2/src/sc2code/libs/graphics/font.h new file mode 100644 index 000000000..14ac22943 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/font.h @@ -0,0 +1,55 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FONT_H +#define _FONT_H + +#define FIRST_CHAR (UNICODE)' ' +#define MAX_CHARS 5000 +#define MAX_DELTAS 100 + +typedef struct +{ + FONT_REF FontRef; + + BYTE Leading; + FRAME_DESC CharDesc[MAX_CHARS]; +} FONT_DESC; +typedef FONT_DESC *PFONT_DESC; + +#define FONTPTR PFONT_DESC +#define CHAR_DESCPTR PCHAR_DESC + +#define FONT_PRIORITY DEFAULT_MEM_PRIORITY + +#define AllocFont(size) \ + (FONT_REF)mem_allocate ((MEM_SIZE)(sizeof (FONT_DESC) + (size)), \ + MEM_ZEROINIT | MEM_GRAPHICS, FONT_PRIORITY, MEM_SIMPLE) +#define LockFont(h) (FONTPTR)mem_lock (h) +#define UnlockFont(h) mem_unlock (h) +#define FreeFont _ReleaseFontData + +#define NULL_FONT (FONTPTR)NULL_PTR + +extern FONTPTR _CurFontPtr; + +extern MEM_HANDLE _GetFontData (FILE *fp, DWORD length); +extern BOOLEAN _ReleaseFontData (MEM_HANDLE handle); + +#endif /* _FONT_H */ + diff --git a/sc2/src/sc2code/libs/graphics/frame.c b/sc2/src/sc2code/libs/graphics/frame.c new file mode 100644 index 000000000..d466cac67 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/frame.c @@ -0,0 +1,399 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" +#include "declib.h" + +typedef union +{ + POINT Point; + STAMP Stamp; + BRESENHAM_LINE Line; + TEXT Text; + STAMP_CMAP StampCMap; + RECT Rect; + POLYGON_DESC Polygon; + struct + { + POINT origin; + FRAME frame; + COUNT NumFrames; + PFRAME FrameList; + } Composite; +} INTERNAL_PRIM_DESC; +typedef INTERNAL_PRIM_DESC *PINTERNAL_PRIM_DESC; + +typedef PINTERNAL_PRIM_DESC INTERNAL_PRIM_DESCPTR; + +typedef struct +{ + PRIM_LINKS Links; + DWORD TypeAndColor; + INTERNAL_PRIM_DESC Object; +} INTERNAL_PRIMITIVE; +typedef INTERNAL_PRIMITIVE *PINTERNAL_PRIMITIVE; + +STAMP _save_stamp; + +static BOOLEAN +GetFrameValidRect (PRECT pValidRect, HOT_SPOT *pOldHot) +{ + COORD hx, hy; + HOT_SPOT OldHot; + + OldHot = GetFrameHotSpot (_CurFramePtr); + hx = GET_HOT_X (OldHot); + hy = GET_HOT_Y (OldHot); + pValidRect->corner.x = hx; + pValidRect->corner.y = hy; + pValidRect->extent.width = GetFrameWidth (_CurFramePtr); + pValidRect->extent.height = GetFrameHeight (_CurFramePtr); + if (_pCurContext->ClipRect.extent.width) + { + if (!BoxIntersect (&_pCurContext->ClipRect, + pValidRect, pValidRect)) + return (FALSE); + + hx -= _pCurContext->ClipRect.corner.x; + hy -= _pCurContext->ClipRect.corner.y; + pValidRect->corner.x += hx; + pValidRect->corner.y += hy; + SetFrameHotSpot (_CurFramePtr, MAKE_HOT_SPOT (hx, hy)); + } + + *pOldHot = OldHot; + return (TRUE); +} + +static void +ClearBackGround (PRECT pClipRect) +{ + if (_get_context_bg_func ()) + { + (*_get_context_bg_func ()) (pClipRect); + } + else + { + RECT locRect; + PRIMITIVE locPrim; + + locPrim.Object.Rect = *pClipRect; + if (BGFrame == 0) + { + SetPrimColor (&locPrim, _get_context_bg_color ()); + SetPrimType (&locPrim, RECTFILL_PRIM); + } + else + { + locRect.corner.x = -GetFrameHotX (BGFrame); + locRect.corner.y = -GetFrameHotY (BGFrame); + locRect.extent.width = GetFrameWidth (BGFrame); + locRect.extent.height = GetFrameHeight (BGFrame); + _save_stamp.origin = locRect.corner; + + if (!BoxIntersect (&locRect, &locPrim.Object.Rect, &locRect)) + return; + + pClipRect = &locRect; + SetPrimType (&locPrim, STAMP_PRIM); + SetPrimColor (&locPrim, _get_context_bg_color ()); + locPrim.Object.Stamp = _save_stamp; + } + + DrawGraphicsFunc (pClipRect, &locPrim); + } +} + +void +DrawBatch (PPRIMITIVE lpBasePrim, PRIM_LINKS PrimLinks, register + BATCH_FLAGS BatchFlags) +{ + RECT ValidRect; + HOT_SPOT OldHot; + + if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) + { + int frame_dir; + COUNT CurIndex; + PRIM_LINKS OldLinks; + register PPRIMITIVE lpPrim; +#ifdef MAPPING + MAP_TYPE MapType; + + _init_context_map (&MapType); + if (MapType != MAP_NOXFORM) + BatchFlags |= BATCH_XFORM; +#endif /* MAPPING */ + + BatchFlags &= BATCH_SINGLE + | BATCH_BUILD_PAGE + | BATCH_XFORM; + + BatchFlags |= _get_context_flags () & BATCH_CLIP_GRAPHICS; + + BatchGraphics (); + + frame_dir = ((GetDisplayFlags () & WANT_MASK) + && _get_context_draw_mode () == DRAW_SUBTRACTIVE) ? -1 : 1; + if (BatchFlags & BATCH_BUILD_PAGE) + { + if (frame_dir == 1) + ClearBackGround (&ValidRect); + } + else if (_get_context_draw_mode () == DRAW_ADDITIVE + && _get_context_bg_func ()) + BatchFlags |= BATCH_DIRTY_TILES; + + CurIndex = frame_dir < 0 + ? GetSuccLink (PrimLinks) + : GetPredLink (PrimLinks); + + if (BatchFlags & BATCH_SINGLE) + { + if (CurIndex == END_OF_LIST) + BatchFlags &= ~BATCH_SINGLE; + else + { + lpBasePrim += CurIndex; + OldLinks = GetPrimLinks (lpBasePrim); + SetPrimLinks (lpBasePrim, END_OF_LIST, END_OF_LIST); + CurIndex = 0; + } + } + + for (; CurIndex != END_OF_LIST; + CurIndex = frame_dir < 0 + ? GetPredLink (GetPrimLinks (lpPrim)) + : GetSuccLink (GetPrimLinks (lpPrim))) + { + register GRAPHICS_PRIM PrimType; + PPRIMITIVE lpWorkPrim; + RECT ClipRect; + INTERNAL_PRIMITIVE Prim; + FRAMEPTR SrcFramePtr; + + lpPrim = &lpBasePrim[CurIndex]; + PrimType = GetPrimType (lpPrim); + if (!ValidPrimType (PrimType)) + continue; + + lpWorkPrim = lpPrim; +#ifdef MAPPING + if (BatchFlags & BATCH_XFORM) + { + COORD x, y; + + Prim = *(PINTERNAL_PRIMITIVE)lpWorkPrim; + lpWorkPrim = (PPRIMITIVE)&Prim; + + x = LXtoDX (Prim.Object.Point.x); + y = LYtoDY (Prim.Object.Point.y); + if (PrimType == RECT_PRIM + || PrimType == RECTFILL_PRIM) + { + Prim.Object.Line.second.x = + LXtoDX (Prim.Object.Rect.corner.x + + Prim.Object.Rect.extent.width - 1); + Prim.Object.Line.second.y = + LYtoDY (Prim.Object.Rect.corner.y + + Prim.Object.Rect.extent.height - 1); + Prim.Object.Rect.extent.width = Prim.Object.Line.second.x - x + 1; + Prim.Object.Rect.extent.height = Prim.Object.Line.second.y - y + 1; + } + + Prim.Object.Point.x = x; + Prim.Object.Point.y = y; + } +#endif /* MAPPING */ + + switch (PrimType) + { + case POINT_PRIM: + ClipRect.corner = lpWorkPrim->Object.Point; + if ((BatchFlags & BATCH_CLIP_GRAPHICS) + && (ClipRect.corner.x < ValidRect.corner.x + || ClipRect.corner.y < ValidRect.corner.y + || ClipRect.corner.x >= ValidRect.corner.x + + ValidRect.extent.width + || ClipRect.corner.y >= ValidRect.corner.y + + ValidRect.extent.height)) + continue; + ClipRect.extent.width = ClipRect.extent.height = 1; + goto DoGraphics; + case STAMPCMAP_PRIM: + BatchColorMap (lpWorkPrim->Object.StampCMap.CMap); + goto ProcessStamp; + case COMPOSITE_PRIM: + case COMPOSITEFILL_PRIM: + Prim = *(PINTERNAL_PRIMITIVE)lpWorkPrim; + if ((Prim.Object.Composite.FrameList = + (PFRAME)Prim.Object.Composite.frame) == 0 + || Prim.Object.Composite.NumFrames == 0) + continue; + if (frame_dir < 0) + Prim.Object.Composite.FrameList += + Prim.Object.Composite.NumFrames - 1; + lpWorkPrim = (PPRIMITIVE)&Prim; + SetPrimType (lpWorkPrim, + STAMP_PRIM + (PrimType - COMPOSITE_PRIM)); +ProcessComposite: + Prim.Object.Composite.frame = + *Prim.Object.Composite.FrameList; + Prim.Object.Composite.FrameList += frame_dir; + if (--Prim.Object.Composite.NumFrames == 0) + PrimType = GetPrimType (&Prim); + case STAMP_PRIM: + case STAMPFILL_PRIM: +ProcessStamp: + SrcFramePtr = (FRAMEPTR)( + lpWorkPrim->Object.Stamp.frame + ); + if (SrcFramePtr == 0) + { + if (PrimType >= COMPOSITE_PRIM) + goto ProcessComposite; + else + continue; + } + + ClipRect.corner = lpWorkPrim->Object.Stamp.origin; + ClipRect.corner.x -= GetFrameHotX (SrcFramePtr); + ClipRect.corner.y -= GetFrameHotY (SrcFramePtr); + ClipRect.extent.width = GetFrameWidth (SrcFramePtr); + ClipRect.extent.height = GetFrameHeight (SrcFramePtr); + + _save_stamp.origin = ClipRect.corner; + break; + case LINE_PRIM: +#ifdef MAPPING + if (BatchFlags & BATCH_XFORM) + { + Prim.Object.Line.second.x = LXtoDX (Prim.Object.Line.second.x); + Prim.Object.Line.second.y = LYtoDY (Prim.Object.Line.second.y); + } + else +#endif /* MAPPING */ + { + Prim = *(PINTERNAL_PRIMITIVE)lpWorkPrim; + lpWorkPrim = (PPRIMITIVE)&Prim; + } + + if (Prim.Object.Line.second.x >= Prim.Object.Line.first.x) + { + ClipRect.corner.x = Prim.Object.Line.first.x; + ClipRect.extent.width = + Prim.Object.Line.second.x + - Prim.Object.Line.first.x + 1; + } + else + { + ClipRect.corner.x = Prim.Object.Line.second.x; + ClipRect.extent.width = + Prim.Object.Line.first.x + - Prim.Object.Line.second.x + 1; + } + if (Prim.Object.Line.second.y >= Prim.Object.Line.first.y) + { + ClipRect.corner.y = Prim.Object.Line.first.y; + ClipRect.extent.height = + Prim.Object.Line.second.y + - Prim.Object.Line.first.y + 1; + } + else + { + ClipRect.corner.y = Prim.Object.Line.second.y; + ClipRect.extent.height = + Prim.Object.Line.first.y + - Prim.Object.Line.second.y + 1; + } + break; + case TEXT_PRIM: + if (!TextRect (&lpWorkPrim->Object.Text, + &ClipRect, NULL_PTR)) + continue; + + _save_stamp.origin = ClipRect.corner; + break; + case RECT_PRIM: + case RECTFILL_PRIM: + ClipRect = lpWorkPrim->Object.Rect; + break; + case POLY_PRIM: + case POLYFILL_PRIM: + ClipRect = ((PPOLYGON_DESC)lpWorkPrim->Object.Polygon)->BoundRect; + break; + } + +#if 0 + if ((BatchFlags & BATCH_CLIP_GRAPHICS) + && BoxIntersect (&ClipRect, + &ValidRect, &ClipRect) == 0) + { + if (PrimType >= COMPOSITE_PRIM) + goto ProcessComposite; + else + continue; + } +#endif + +DoGraphics: + if (BatchFlags & BATCH_DIRTY_TILES) + (*_get_context_bg_func ()) (&ClipRect); + + DrawGraphicsFunc (&ClipRect, lpWorkPrim); + if (PrimType >= COMPOSITE_PRIM) + goto ProcessComposite; + } + + if (BatchFlags & BATCH_BUILD_PAGE) + { + if (frame_dir < 0) + ClearBackGround (&ValidRect); + } + + UnbatchGraphics (); + + SetFrameHotSpot (_CurFramePtr, OldHot); + + if (BatchFlags & BATCH_SINGLE) + SetPrimLinks (lpBasePrim, + GetPredLink (OldLinks), + GetSuccLink (OldLinks)); + +#ifdef MAPPING + _uninit_context_map (); +#endif /* MAPPING */ + } +} + +void +ClearDrawable (void) +{ + RECT ValidRect; + HOT_SPOT OldHot; + + if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) + { + BatchGraphics (); + ClearBackGround (&ValidRect); + UnbatchGraphics (); + + SetFrameHotSpot (_CurFramePtr, OldHot); + } +} + diff --git a/sc2/src/sc2code/libs/graphics/getbody.c b/sc2/src/sc2code/libs/graphics/getbody.c new file mode 100644 index 000000000..0b3266ddb --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/getbody.c @@ -0,0 +1,417 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" +#include "SDL_wrapper.h" +#ifdef WIN32 +#include +#endif +#include + +extern char *_cur_resfile_name; + +static void +process_image (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct) +{ + int hx, hy, h; + + TYPE_SET (FramePtr->TypeIndexAndFlags, WANT_PIXMAP << FTYPE_SHIFT); + INDEX_SET (FramePtr->TypeIndexAndFlags, cel_ct); + + hx = hy = 0; + + SDL_LockSurface (img[cel_ct]); + if (img[cel_ct]->w >= 3 && (h = img[cel_ct]->h)) + { + if (img[cel_ct]->format->palette) + { + int w; + BYTE *pixel, *p, Cknockout, Chotx, Choty; + + img[cel_ct]->clip_rect.x = img[cel_ct]->w; + img[cel_ct]->clip_rect.y = img[cel_ct]->h; + img[cel_ct]->clip_rect.w = img[cel_ct]->clip_rect.h = 0; + p = pixel = img[cel_ct]->pixels; + Cknockout = *p++; + Chotx = *p; + *p++ = Cknockout; + Choty = *p; + *p++ = Cknockout; + SDL_SetColorKey + ( + img[cel_ct], SDL_SRCCOLORKEY, + SDL_MapRGB + ( + img[cel_ct]->format, + img[cel_ct]->format->palette->colors[Cknockout].r, + img[cel_ct]->format->palette->colors[Cknockout].g, + img[cel_ct]->format->palette->colors[Cknockout].b + ) + ); + do + { + w = img[cel_ct]->w - (p - pixel); + if (w) + { + int x, y; + BYTE opval; + + opval = Cknockout; + do + { + BYTE pval; + + pval = *p; + if (pval == Chotx) + { + *p = Cknockout; + hx = img[cel_ct]->w - w; + } + if (pval == Choty) + { + *p = Cknockout; + hy = img[cel_ct]->h - h; + } + + pval = *p; + if (pval == Cknockout) + { + if (opval != Cknockout) + { + x = img[cel_ct]->w - w; + if (x > img[cel_ct]->clip_rect.x + img[cel_ct]->clip_rect.w) + img[cel_ct]->clip_rect.w = x - img[cel_ct]->clip_rect.x; + y = img[cel_ct]->h - h; + if (y >= img[cel_ct]->clip_rect.y + img[cel_ct]->clip_rect.h) + img[cel_ct]->clip_rect.h = y - img[cel_ct]->clip_rect.y + 1; + } + } + else + { + if (opval == Cknockout) + { + x = img[cel_ct]->w - w; + if (x < img[cel_ct]->clip_rect.x) + { + if (img[cel_ct]->clip_rect.w == 0) + img[cel_ct]->clip_rect.w = 1; + else + img[cel_ct]->clip_rect.w += img[cel_ct]->clip_rect.x - x; + img[cel_ct]->clip_rect.x = x; + } + y = img[cel_ct]->h - h; + if (y < img[cel_ct]->clip_rect.y) + { + if (img[cel_ct]->clip_rect.h == 0) + img[cel_ct]->clip_rect.h = 1; + else + img[cel_ct]->clip_rect.h += img[cel_ct]->clip_rect.y - y; + img[cel_ct]->clip_rect.y = y; + } + } + } + opval = pval; + } while (++p, --w); + if (opval != Cknockout) + { + x = img[cel_ct]->w - w; + if (x > img[cel_ct]->clip_rect.x + img[cel_ct]->clip_rect.w) + img[cel_ct]->clip_rect.w = x - img[cel_ct]->clip_rect.x; + y = img[cel_ct]->h - h; + if (y >= img[cel_ct]->clip_rect.y + img[cel_ct]->clip_rect.h) + img[cel_ct]->clip_rect.h = y - img[cel_ct]->clip_rect.y + 1; + } + } + p = (pixel += img[cel_ct]->pitch); + } while (--h); + } + else + { + } + } + SDL_UnlockSurface (img[cel_ct]); + +hx -= img[cel_ct]->clip_rect.x; +hy -= img[cel_ct]->clip_rect.y; + FramePtr->DataOffs = (BYTE *)TFB_LoadImage (img[cel_ct]) - (BYTE *)FramePtr; +img[cel_ct] = ((TFB_Image *)((BYTE *)FramePtr + FramePtr->DataOffs))->SurfaceSDL; +hx += img[cel_ct]->clip_rect.x; +hy += img[cel_ct]->clip_rect.y; + SetFrameHotSpot (FramePtr, MAKE_HOT_SPOT (hx, hy)); + SetFrameBounds (FramePtr, img[cel_ct]->clip_rect.w, img[cel_ct]->clip_rect.h); +#if 0 +printf ("\thot[%d, %d], rect[%d, %d, %d, %d]\n", + hx, hy, + img[cel_ct]->clip_rect.x, + img[cel_ct]->clip_rect.y, + img[cel_ct]->clip_rect.w, + img[cel_ct]->clip_rect.h); +#endif +} + +MEM_HANDLE +_GetCelData (FILE *fp, DWORD length) +{ +#ifdef WIN32 + int omode; +#endif + int cel_ct, n; + DWORD opos; + char CurrentLine[1024], filename[1024]; +#define MAX_CELS 256 + SDL_Surface *img[MAX_CELS]; + DRAWABLE Drawable; + + opos = ftell (fp); + + { + char *s1, *s2; + + if (_cur_resfile_name == 0 + || (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) + && (s2 = strrchr (_cur_resfile_name, '\\')) == 0)) + n = 0; + else + { + if (s2 > s1) + s1 = s2; + n = s1 - _cur_resfile_name + 1; + strncpy (filename, _cur_resfile_name, n); + } + } + +#ifdef WIN32 + omode = _setmode (fileno (fp), O_TEXT); +#endif + cel_ct = 0; + while (fgets (CurrentLine, sizeof (CurrentLine), fp) && cel_ct < MAX_CELS) + { + if + ( + sscanf(CurrentLine, "%s", &filename[n]) == 1 + && (img[cel_ct] = IMG_Load (filename)) + && img[cel_ct]->w > 0 + && img[cel_ct]->h > 0 + && img[cel_ct]->format->BitsPerPixel >= 8 + ) + ++cel_ct; + else if (img[cel_ct]) +printf("_GetCelData: Bad file!\n"), + SDL_FreeSurface (img[cel_ct]); + + if ((int)ftell (fp) - (int)opos >= (int)length) + break; + } +#ifdef WIN32 + _setmode (fileno (fp), omode); +#endif + + Drawable = 0; + if (cel_ct && (Drawable = AllocDrawable (cel_ct, 0))) + { + DRAWABLEPTR DrawablePtr; + + if ((DrawablePtr = LockDrawable (Drawable)) == 0) + { + while (cel_ct--) + SDL_FreeSurface (img[cel_ct]); + + mem_release (Drawable); + Drawable = 0; + } + else + { + FRAMEPTR FramePtr; + + DrawablePtr->hDrawable = GetDrawableHandle (Drawable); + TYPE_SET (DrawablePtr->FlagsAndIndex, + (DRAWABLE_TYPE)ROM_DRAWABLE << FTYPE_SHIFT); + INDEX_SET (DrawablePtr->FlagsAndIndex, cel_ct - 1); + + FramePtr = &DrawablePtr->Frame[cel_ct]; + while (--FramePtr, cel_ct--) + process_image (FramePtr, img, cel_ct); + + UnlockDrawable (Drawable); + } + } + +if (Drawable == 0) + printf ("Couldn't get cel data for '%s'\n", _cur_resfile_name); + return (GetDrawableHandle (Drawable)); +} + +BOOLEAN +_ReleaseCelData (MEM_HANDLE handle) +{ + DRAWABLEPTR DrawablePtr; + + if ((DrawablePtr = LockDrawable (handle)) == 0) + return (FALSE); + + if (TYPE_GET (DrawablePtr->FlagsAndIndex) != SCREEN_DRAWABLE) + { + int cel_ct; + FRAMEPTR FramePtr; + + cel_ct = INDEX_GET (DrawablePtr->FlagsAndIndex); + + FramePtr = &DrawablePtr->Frame[cel_ct]; + while (--FramePtr, cel_ct--) + { + if (FramePtr->DataOffs) + { + TFB_Image *img; + + img = (TFB_Image *)((BYTE *)FramePtr + FramePtr->DataOffs); + FramePtr->DataOffs = 0; + + TFB_FreeImage (img); + } + } + } + + UnlockDrawable (handle); + mem_release (handle); + + return (TRUE); +} + +MEM_HANDLE +_GetFontData (FILE *fp, DWORD length) +{ + DWORD cel_ct; + COUNT num_entries; + FONT_REF FontRef; + DIRENTRY FontDir; + BOOLEAN found_chars; +#define MAX_CELS 256 + SDL_Surface *img[MAX_CELS] = { 0 }; + char pattern[1024]; + + if (_cur_resfile_name == 0) + return (0); + sprintf (pattern, "%s/*.*", _cur_resfile_name); + + found_chars = FALSE; + FontDir = CaptureDirEntryTable (LoadDirEntryTable (pattern, &num_entries)); + while (num_entries--) + { + char *char_name; + + char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex (FontDir, num_entries)); + if (sscanf (char_name, "%u.", (unsigned int) &cel_ct) == 1 + && cel_ct >= FIRST_CHAR + && img[cel_ct -= FIRST_CHAR] == 0 + && sprintf (pattern, "%s/%s", _cur_resfile_name, char_name) + && (img[cel_ct] = IMG_Load (pattern))) + { + if (img[cel_ct]->w > 0 + && img[cel_ct]->h > 0 + && img[cel_ct]->format->BitsPerPixel >= 8) + found_chars = TRUE; + else + { + SDL_FreeSurface (img[cel_ct]); + img[cel_ct] = 0; + } + } + + } + DestroyDirEntryTable (ReleaseDirEntryTable (FontDir)); + + FontRef = 0; + if (found_chars && (FontRef = AllocFont (0))) + { + FONTPTR FontPtr; + + cel_ct = MAX_CELS; // MAX_CHARS; + if ((FontPtr = LockFont (FontRef)) == 0) + { + while (cel_ct--) + { + if (img[cel_ct]) + SDL_FreeSurface (img[cel_ct]); + } + + mem_release (FontRef); + FontRef = 0; + } + else + { + FRAMEPTR FramePtr; + + FontPtr->FontRef = FontRef; + FontPtr->Leading = 0; + FramePtr = &FontPtr->CharDesc[cel_ct]; + while (--FramePtr, cel_ct--) + { + if (img[cel_ct]) + { + process_image (FramePtr, img, cel_ct); + SetFrameBounds (FramePtr, GetFrameWidth (FramePtr) + 1, GetFrameHeight (FramePtr)); + if (img[0]) + SetFrameHotSpot (FramePtr, MAKE_HOT_SPOT (0, img[0]->clip_rect.h)); + if (GetFrameHeight (FramePtr) > FontPtr->Leading) + FontPtr->Leading = GetFrameHeight (FramePtr); + } + } + ++FontPtr->Leading; + + UnlockFont (FontRef); + } + } + (void) fp; /* Satisfying compiler (unused parameter) */ + (void) length; /* Satisfying compiler (unused parameter) */ + return (FontRef); +} + +BOOLEAN +_ReleaseFontData (MEM_HANDLE handle) +{ + FONTPTR FontPtr; + + if ((FontPtr = LockFont (handle)) == 0) + return (FALSE); + + { + int cel_ct; + FRAMEPTR FramePtr; + + cel_ct = MAX_CHARS; + + FramePtr = &FontPtr->CharDesc[cel_ct]; + while (--FramePtr, cel_ct--) + { + if (FramePtr->DataOffs) + { + TFB_Image *img; + + img = (TFB_Image *)((BYTE *)FramePtr + FramePtr->DataOffs); + FramePtr->DataOffs = 0; + + TFB_FreeImage (img); + } + } + } + + UnlockFont (handle); + mem_release (handle); + + return (TRUE); +} diff --git a/sc2/src/sc2code/libs/graphics/gfxintrn.h b/sc2/src/sc2code/libs/graphics/gfxintrn.h new file mode 100644 index 000000000..19e2fe9c9 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/gfxintrn.h @@ -0,0 +1,43 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _GFXINTRN_H +#define _GFXINTRN_H + +#include +#include + +#define _GFX_PROTOS +#include "gfxlib.h" +#include "reslib.h" +#include "context.h" +#include "drawable.h" +#include "font.h" +#include "display.h" + +#undef CONTEXT +#define CONTEXT CONTEXTPTR +#undef FRAME +#define FRAME FRAMEPTR +#undef FONT +#define FONT FONTPTR +#undef _GFX_PROTOS +#include "gfxlib.h" + +#endif /* _GFXINTRN_H */ + diff --git a/sc2/src/sc2code/libs/graphics/intersec.c b/sc2/src/sc2code/libs/graphics/intersec.c new file mode 100644 index 000000000..949b44f61 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/intersec.c @@ -0,0 +1,404 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +static TIME_VALUE +frame_intersect (PINTERSECT_CONTROL pControl0, PRECT pr0, + PINTERSECT_CONTROL pControl1, PRECT pr1, TIME_VALUE t0, + TIME_VALUE t1) +{ + register SIZE time_error0, time_error1; + register SIZE cycle0, cycle1; + SIZE dx_0, dy_0, dx_1, dy_1; + SIZE xincr0, yincr0, xincr1, yincr1; + SIZE xerror0, xerror1, yerror0, yerror1; + RECT r_intersect; + IMAGE_BOX IB0, IB1; + BOOLEAN check0, check1; + + IB0.FramePtr = pControl0->IntersectStamp.frame; + IB0.Box.corner = pr0->corner; + IB0.Box.extent.width = GetFrameWidth (IB0.FramePtr); + IB0.Box.extent.height = GetFrameHeight (IB0.FramePtr); + IB1.FramePtr = pControl1->IntersectStamp.frame; + IB1.Box.corner = pr1->corner; + IB1.Box.extent.width = GetFrameWidth (IB1.FramePtr); + IB1.Box.extent.height = GetFrameHeight (IB1.FramePtr); + + dx_0 = pr0->extent.width; + dy_0 = pr0->extent.height; + if (dx_0 >= 0) + xincr0 = 1; + else + { + xincr0 = -1; + dx_0 = -dx_0; + } + if (dy_0 >= 0) + yincr0 = 1; + else + { + yincr0 = -1; + dy_0 = -dy_0; + } + if (dx_0 >= dy_0) + cycle0 = dx_0; + else + cycle0 = dy_0; + xerror0 = yerror0 = cycle0; + + dx_1 = pr1->extent.width; + dy_1 = pr1->extent.height; + if (dx_1 >= 0) + xincr1 = 1; + else + { + xincr1 = -1; + dx_1 = -dx_1; + } + if (dy_1 >= 0) + yincr1 = 1; + else + { + yincr1 = -1; + dy_1 = -dy_1; + } + if (dx_1 >= dy_1) + cycle1 = dx_1; + else + cycle1 = dy_1; + xerror1 = yerror1 = cycle1; + + check0 = check1 = FALSE; + if (t0 <= 1) + { + time_error0 = time_error1 = 0; + if (t0 == 0) + { + ++t0; + goto CheckFirstIntersection; + } + } + else + { + SIZE delta; + COUNT start; + long error; + + start = (COUNT)cycle0 * (COUNT)(t0 - 1); + time_error0 = start & ((1 << TIME_SHIFT) - 1); + if ((start >>= (COUNT)TIME_SHIFT) > 0) + { + if ((error = (long)xerror0 + - (long)dx_0 * (long)start) > 0) + xerror0 = (SIZE)error; + else + { + delta = -(SIZE)(error / (long)cycle0) + 1; + IB0.Box.corner.x += xincr0 * delta; + xerror0 = (SIZE)(error + (long)cycle0 * (long)delta); + } + if ((error = (long)yerror0 + - (long)dy_0 * (long)start) > 0) + yerror0 = (SIZE)error; + else + { + delta = -(SIZE)(error / (long)cycle0) + 1; + IB0.Box.corner.y += yincr0 * delta; + yerror0 = (SIZE)(error + (long)cycle0 * (long)delta); + } + pr0->corner = IB0.Box.corner; + } + + start = (COUNT)cycle1 * (COUNT)(t0 - 1); + time_error1 = start & ((1 << TIME_SHIFT) - 1); + if ((start >>= (COUNT)TIME_SHIFT) > 0) + { + if ((error = (long)xerror1 + - (long)dx_1 * (long)start) > 0) + xerror1 = (SIZE)error; + else + { + delta = -(SIZE)(error / (long)cycle1) + 1; + IB1.Box.corner.x += xincr1 * delta; + xerror1 = (SIZE)(error + (long)cycle1 * (long)delta); + } + if ((error = (long)yerror1 + - (long)dy_1 * (long)start) > 0) + yerror1 = (SIZE)error; + else + { + delta = -(SIZE)(error / (long)cycle1) + 1; + IB1.Box.corner.y += yincr1 * delta; + yerror1 = (SIZE)(error + (long)cycle1 * (long)delta); + } + pr1->corner = IB1.Box.corner; + } + } + + pControl0->last_time_val = pControl1->last_time_val = t0; + do + { + ++t0; + if ((time_error0 += cycle0) >= (1 << TIME_SHIFT)) + { + if ((xerror0 -= dx_0) <= 0) + { + IB0.Box.corner.x += xincr0; + xerror0 += cycle0; + } + if ((yerror0 -= dy_0) <= 0) + { + IB0.Box.corner.y += yincr0; + yerror0 += cycle0; + } + + check0 = TRUE; + time_error0 -= (1 << TIME_SHIFT); + } + + if ((time_error1 += cycle1) >= (1 << TIME_SHIFT)) + { + if ((xerror1 -= dx_1) <= 0) + { + IB1.Box.corner.x += xincr1; + xerror1 += cycle1; + } + if ((yerror1 -= dy_1) <= 0) + { + IB1.Box.corner.y += yincr1; + yerror1 += cycle1; + } + + check1 = TRUE; + time_error1 -= (1 << TIME_SHIFT); + } + + if (check0 || check1) + { /* if check0 && check1, this may not be quite right -- + * if shapes had a pixel's separation to begin with + * and both moved toward each other, you would actually + * get a pixel overlap but since the last positions were + * separated by a pixel, the shapes wouldn't be touching + * each other. + */ + BOOLEAN _image_intersect (PIMAGE_BOX pImageBox0, PIMAGE_BOX + pImageBox1, PRECT pIRect); + +CheckFirstIntersection: + if (BoxIntersect (&IB0.Box, &IB1.Box, &r_intersect) + && _image_intersect (&IB0, &IB1, &r_intersect)) + return (t0); + + if (check0) + { + pr0->corner = IB0.Box.corner; + pControl0->last_time_val = t0; + check0 = FALSE; + } + if (check1) + { + pr1->corner = IB1.Box.corner; + pControl1->last_time_val = t0; + check1 = FALSE; + } + } + } while (t0 <= t1); + + return ((TIME_VALUE)0); +} + +TIME_VALUE +DrawablesIntersect (PINTERSECT_CONTROL pControl0, + PINTERSECT_CONTROL pControl1, TIME_VALUE + max_time_val) +{ + register SIZE dy; + register SIZE time_y_0, time_y_1; + RECT r0, r1; + FRAMEPTR FramePtr0, FramePtr1; + + if (!ContextActive () || max_time_val == 0) + return ((TIME_VALUE)0); + else if (max_time_val > MAX_TIME_VALUE) + max_time_val = MAX_TIME_VALUE; + + pControl0->last_time_val = pControl1->last_time_val = 0; + + r0.corner = pControl0->IntersectStamp.origin; + r1.corner = pControl1->IntersectStamp.origin; + + r0.extent.width = pControl0->EndPoint.x - r0.corner.x; + r0.extent.height = pControl0->EndPoint.y - r0.corner.y; + r1.extent.width = pControl1->EndPoint.x - r1.corner.x; + r1.extent.height = pControl1->EndPoint.y - r1.corner.y; + + FramePtr0 = (FRAMEPTR)pControl0->IntersectStamp.frame; + if (FramePtr0 == 0) + return(0); + r0.corner.x -= GetFrameHotX (FramePtr0); + r0.corner.y -= GetFrameHotY (FramePtr0); + + FramePtr1 = (FRAMEPTR)pControl1->IntersectStamp.frame; + if (FramePtr1 == 0) + return(0); + r1.corner.x -= GetFrameHotX (FramePtr1); + r1.corner.y -= GetFrameHotY (FramePtr1); + + dy = r1.corner.y - r0.corner.y; + time_y_0 = dy - GetFrameHeight (FramePtr0) + 1; + time_y_1 = dy + GetFrameHeight (FramePtr1) - 1; + dy = r0.extent.height - r1.extent.height; + + if ((time_y_0 <= 0 && time_y_1 >= 0) + || (time_y_0 > 0 && dy >= time_y_0) + || (time_y_1 < 0 && dy <= time_y_1)) + { + register SIZE dx; + register SIZE time_x_0, time_x_1; + + dx = r1.corner.x - r0.corner.x; + time_x_0 = dx - GetFrameWidth (FramePtr0) + 1; + time_x_1 = dx + GetFrameWidth (FramePtr1) - 1; + dx = r0.extent.width - r1.extent.width; + + if ((time_x_0 <= 0 && time_x_1 >= 0) + || (time_x_0 > 0 && dx >= time_x_0) + || (time_x_1 < 0 && dx <= time_x_1)) + { + TIME_VALUE intersect_time; + + if (dx == 0 && dy == 0) + time_y_0 = time_y_1 = 0; + else + { + SIZE t; + long time_beg, time_end, fract; + + if (time_y_1 < 0) + { + t = time_y_0; + time_y_0 = -time_y_1; + time_y_1 = -t; + } + else if (time_y_0 <= 0) + { + if (dy < 0) + time_y_1 = -time_y_0; + time_y_0 = 0; + } + if (dy < 0) + dy = -dy; + if (dy < time_y_1) + time_y_1 = dy; + /* just to be safe, widen search area */ + --time_y_0; + ++time_y_1; + + if (time_x_1 < 0) + { + t = time_x_0; + time_x_0 = -time_x_1; + time_x_1 = -t; + } + else if (time_x_0 <= 0) + { + if (dx < 0) + time_x_1 = -time_x_0; + time_x_0 = 0; + } + if (dx < 0) + dx = -dx; + if (dx < time_x_1) + time_x_1 = dx; + /* just to be safe, widen search area */ + --time_x_0; + ++time_x_1; + +#ifdef DEBUG +printf ("FramePtr0<%d, %d> --> <%d, %d>\nFramePtr1<%d, %d> --> <%d, %d>\n", +GetFrameWidth (FramePtr0), GetFrameHeight (FramePtr0), +r0.corner.x, r0.corner.y, +GetFrameWidth (FramePtr1), GetFrameHeight (FramePtr1), +r1.corner.x, r1.corner.y); +printf ("time_x(%d, %d)-%d, time_y(%d, %d)-%d\n", time_x_0, time_x_1, dx, time_y_0, time_y_1, dy); +#endif /* DEBUG */ + if (dx == 0) + { + time_beg = time_y_0; + time_end = time_y_1; + fract = dy; + } + else if (dy == 0) + { + time_beg = time_x_0; + time_end = time_x_1; + fract = dx; + } + else + { + long time_x, time_y; + + time_x = (long)time_x_0 * (long)dy; + time_y = (long)time_y_0 * (long)dx; + time_beg = time_x < time_y ? time_y : time_x; + + time_x = (long)time_x_1 * (long)dy; + time_y = (long)time_y_1 * (long)dx; + time_end = time_x > time_y ? time_y : time_x; + + fract = (long)dx * (long)dy; + } + + if ((time_beg <<= TIME_SHIFT) < fract) + time_y_0 = 0; + else + time_y_0 = (SIZE)(time_beg / fract); + + if (time_end >= fract /* just in case of overflow */ + || (time_end <<= TIME_SHIFT) >= + fract * (long)max_time_val) + time_y_1 = max_time_val - 1; + else + time_y_1 = (SIZE)((time_end + fract - 1) / fract) - 1; + } + +#ifdef DEBUG +printf ("start_time = %d, end_time = %d\n", time_y_0, time_y_1); +#endif /* DEBUG */ + if (time_y_0 <= time_y_1 + && (intersect_time = frame_intersect ( + pControl0, &r0, pControl1, &r1, + (TIME_VALUE)time_y_0, (TIME_VALUE)time_y_1))) + { + FramePtr0 = (FRAMEPTR)pControl0->IntersectStamp.frame; + pControl0->EndPoint.x = r0.corner.x + GetFrameHotX (FramePtr0); + pControl0->EndPoint.y = r0.corner.y + GetFrameHotY (FramePtr0); + FramePtr1 = (FRAMEPTR)pControl1->IntersectStamp.frame; + pControl1->EndPoint.x = r1.corner.x + GetFrameHotX (FramePtr1); + pControl1->EndPoint.y = r1.corner.y + GetFrameHotY (FramePtr1); + + return (intersect_time); + } + } + } + + return ((TIME_VALUE)0); +} + diff --git a/sc2/src/sc2code/libs/graphics/line.c b/sc2/src/sc2code/libs/graphics/line.c new file mode 100644 index 000000000..bc14d6160 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/line.c @@ -0,0 +1,29 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +void +DrawLine (PLINE lpLine) +{ + SetPrimType (&_locPrim, LINE_PRIM); + _locPrim.Object.Line = *lpLine; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + diff --git a/sc2/src/sc2code/libs/graphics/loaddisp.c b/sc2/src/sc2code/libs/graphics/loaddisp.c new file mode 100644 index 000000000..69004a6c4 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/loaddisp.c @@ -0,0 +1,60 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + + +/* + LoadDisplay---Drawable + + Allocate a chunk of memory and read from the display into that + chunk of memory. + + + LoadDisplayPixmapDrawable() + LoadDisplayMaskDrawable() + LoadDisplayPixmapMaskDrawable() + +*/ + + +DRAWABLE +LoadDisplayPixmap (PRECT area, FRAME frame) +{ + DRAWABLE buffer; + + buffer = BUILD_DRAWABLE ( + GetFrameHandle (frame), + GetFrameIndex (frame) + ); + if (buffer || (buffer = CreateDrawable ( + WANT_PIXMAP | MAPPED_TO_DISPLAY, + area->extent.width, + area->extent.height, + 1)) + ) + { + frame = CaptureDrawable (buffer); + ReadDisplay (area, (FRAMEPTR)frame); + ReleaseDrawable (frame); + } + + return (buffer); +} + + diff --git a/sc2/src/sc2code/libs/graphics/makepoly.c b/sc2/src/sc2code/libs/graphics/makepoly.c new file mode 100644 index 000000000..3d6440f4d --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/makepoly.c @@ -0,0 +1,557 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +/* I don't know yet what the deal is with the __WATCOMC__ delimited + * code, but this will at least make it compile, which is stage 1. - SvdB + */ +#define __WATCOMC__ + +#define AllocGraphicData(size) \ + mem_allocate ((MEM_SIZE)(size), MEM_ZEROINIT | MEM_GRAPHICS, \ + DEFAULT_MEM_PRIORITY, MEM_SIMPLE) +#define LockData (PBYTE)mem_lock +#define UnlockData mem_unlock +#define FreeData mem_release + +typedef enum +{ + UP, + DOWN +} DIRECTION; + +#define POLY_XMIN 1 +#define POLY_YMIN 0 + +static void +xor_dot (FRAMEPTR FramePtr, COORD x, COORD y) +{ + PBYTE lpMaskAddr; + + lpMaskAddr = +#ifndef __WATCOMC__ + GetImageData (&FramePtr->MaskImage) + + (y * GetImageLineBytes (&FramePtr->MaskImage)) + + BYTE_POS (x); +#else /* __WATCOMC__ */ + 0; +#endif /* __WATCOMC__ */ + *lpMaskAddr ^= (BYTE)0x80 >> BYTE_OFFS (x); +} + +static void +xor_line (FRAMEPTR FramePtr, PBRESENHAM_LINE pLine) +{ + COORD dst_x, dst_y; + COORD dst_mask_x; + SIZE dst_mask_incr; + SIZE count; + BYTE dst_bit, bit_shift; + SIZE delta_x, delta_y, error_term; + PBYTE lpMaskAddr; + + dst_x = pLine->first.x; + dst_y = pLine->first.y; + delta_x = pLine->abs_delta_x; + delta_y = pLine->abs_delta_y; + error_term = pLine->error_term; + + dst_mask_x = dst_x; + bit_shift = 1; + +#ifndef __WATCOMC__ + lpMaskAddr = GetImageData (&FramePtr->MaskImage); + dst_mask_incr = GetImageLineBytes (&FramePtr->MaskImage); + lpMaskAddr += (dst_y * dst_mask_incr) + BYTE_POS (dst_mask_x); +#endif /* __WATCOMC__ */ + + if (delta_y < 0) + { + delta_y = -delta_y; + dst_mask_incr = -dst_mask_incr; + } + + dst_bit = (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (dst_mask_x)); + if (delta_x > delta_y) + { + count = pLine->second.x - pLine->first.x; + if (!pLine->end_points_exchanged) + { + do + { + if ((error_term += delta_y) >= 0) + { + *lpMaskAddr ^= dst_bit; + if (count == 0) + break; + + lpMaskAddr += dst_mask_incr; + error_term -= delta_x; + } + if ((dst_bit >>= bit_shift) == 0) + { + dst_bit = (BYTE)0x80; + ++lpMaskAddr; + } + } while (count--); + + if (error_term < 0) + { + if ((dst_bit <<= bit_shift) == 0) + { + dst_bit = (BYTE)0x01; + --lpMaskAddr; + } + *lpMaskAddr ^= dst_bit; + } + } + else + { + *lpMaskAddr ^= dst_bit; + do + { + if ((dst_bit >>= bit_shift) == 0) + { + dst_bit = (BYTE)0x80; + ++lpMaskAddr; + } + if ((error_term += delta_y) >= 0) + { + if (count == 0) + break; + + lpMaskAddr += dst_mask_incr; + *lpMaskAddr ^= dst_bit; + error_term -= delta_x; + } + } while (count--); + } + } + else + { + if ((count = pLine->second.y - pLine->first.y) < 0) + count = -count; + + do + { + *lpMaskAddr ^= dst_bit; + lpMaskAddr += dst_mask_incr; + if ((error_term += delta_x) >= 0) + { + if ((dst_bit >>= bit_shift) == 0) + { + dst_bit = (BYTE)0x80; + ++lpMaskAddr; + } + error_term -= delta_y; + } + } while (count--); + } +} + +static void +or_line (FRAMEPTR FramePtr, PBRESENHAM_LINE pLine) +{ + COORD dst_x, dst_y; + COORD dst_mask_x; + SIZE dst_mask_incr; + SIZE delta_x, delta_y, error_term, count; + BYTE dst_bit, dst_byte, bit_mask, bit_shift; + PBYTE lpMaskAddr; + + dst_x = pLine->first.x; + dst_y = pLine->first.y; + delta_x = pLine->abs_delta_x; + delta_y = pLine->abs_delta_y; + error_term = pLine->error_term; + + dst_mask_x = dst_x; + bit_mask = (BYTE)0x80; + bit_shift = 1; + +#ifndef __WATCOMC__ + lpMaskAddr = GetImageData (&FramePtr->MaskImage); + dst_mask_incr = GetImageLineBytes (&FramePtr->MaskImage); + lpMaskAddr += (dst_y * dst_mask_incr) + BYTE_POS (dst_mask_x); +#endif /* __WATCOMC__ */ + + if (delta_y < 0) + { + delta_y = -delta_y; + dst_mask_incr = -dst_mask_incr; + } + + dst_bit = (BYTE)(bit_mask >> BYTE_OFFS (dst_mask_x)); + if (delta_x > delta_y) + { + count = pLine->second.x - pLine->first.x; + dst_byte = 0; + do + { + dst_byte |= dst_bit; + if ((dst_bit >>= bit_shift) == 0) + { + dst_bit = bit_mask; + *lpMaskAddr++ |= dst_byte; + dst_byte = 0; + } + if ((error_term += delta_y) >= 0) + { + if (dst_byte) + { + *lpMaskAddr |= dst_byte; + dst_byte = 0; + } + lpMaskAddr += dst_mask_incr; + error_term -= delta_x; + } + } while (count--); + if (dst_byte) + *lpMaskAddr |= dst_byte; + } + else + { + if ((count = pLine->second.y - pLine->first.y) < 0) + count = -count; + do + { + *lpMaskAddr |= dst_bit; + lpMaskAddr += dst_mask_incr; + if ((error_term += delta_x) >= 0) + { + if ((dst_bit >>= bit_shift) == 0) + { + dst_bit = bit_mask; + ++lpMaskAddr; + } + error_term -= delta_y; + } + } while (count--); + } +} + +static void +on_off (FRAMEPTR FramePtr) +{ + register SIZE width, height; + register SIZE dst_mask_incr; + register PBYTE lpScan; + + width = GetFrameWidth (FramePtr); + height = GetFrameHeight (FramePtr); +#ifndef __WATCOMC__ + lpScan = GetImageData (&FramePtr->MaskImage); + dst_mask_incr = GetImageLineBytes (&FramePtr->MaskImage); +#endif /* __WATCOMC__ */ + width = BYTE_WIDTH (width); + + do + { + register SIZE byte_width; + register BYTE mask_byte, bit; + register PBYTE lpMask; + + byte_width = width; + lpMask = lpScan; +start_scan: + while (!(mask_byte = *lpMask)) + { + if (--byte_width == 0) + goto done_scan; + ++lpMask; + } + + for (bit = (BYTE)0x80; !(bit & mask_byte); bit >>= 1) + ; + +fill_scan: + while (bit >>= 1) + { +fill_byte: + if (!(bit & mask_byte)) + mask_byte |= bit; + else + { + while (bit >>= 1) + { + if (bit & mask_byte) + goto fill_scan; + } + + *lpMask++ = mask_byte; + if (--byte_width == 0) + goto done_scan; + else + goto start_scan; + } + } + *lpMask++ = mask_byte; + if (--byte_width > 0) + { + while (!(mask_byte = *lpMask)) + { + *lpMask++ = 0xFF; + if (--byte_width == 0) + goto done_scan; + } + bit = (BYTE)0x80; + goto fill_byte; + } + +done_scan: + lpScan += dst_mask_incr; + } while (--height); +} + +static void +create_poly (PRECT pClipRect, PPOLYGON_DESC lpPolygon, FRAMEPTR + FramePtr) +{ + COUNT i; + COORD xoffs, yoffs; + BRESENHAM_LINE Line; + PPOINT pt1; + + xoffs = pClipRect->corner.x - POLY_XMIN; + yoffs = pClipRect->corner.y - POLY_YMIN; + + if (lpPolygon->PtCount > 2) + { + COORD xmax, ymax; + COORD ox, oy; + COORD ystart; + PPOINT pt2; + DIRECTION last_ydir; + BRESENHAM_LINE ShadowLine; + + xmax = POLY_XMIN + pClipRect->extent.width - 1; + ymax = POLY_YMIN + pClipRect->extent.height - 1; + ShadowLine.first.x = ShadowLine.second.x = POLY_XMIN - 1; + ShadowLine.error_term = -1; + ShadowLine.abs_delta_x = 0; + ShadowLine.end_points_exchanged = FALSE; + + pt1 = lpPolygon->PtList; + ystart = pt1->y; + while ((oy = (++pt1)->y) == ystart) + ; + ox = pt1->x; + + last_ydir = oy > ystart ? UP : DOWN; + + i = lpPolygon->PtCount; + pt2 = &lpPolygon->PtList[i - 1]; + do + { + COORD x1, y1; + + if (pt1 != pt2) + ++pt1; + else + pt1 = lpPolygon->PtList; + + x1 = ox; + y1 = oy; + ox = pt1->x; + oy = pt1->y; + + if (oy != y1) + { + COORD y2; + INTERSECT_CODE intersect_code; + + Line.first.x = x1; + Line.first.y = y1; + Line.second.x = ox; + Line.second.y = oy; + LOGtoDEV ((PPOINT)&Line, (PPOINT)&Line, 2); + y1 = Line.first.y - yoffs; + y2 = Line.second.y - yoffs; + + { + DIRECTION ydir; + + ydir = y2 > y1 ? UP : DOWN; + if (ydir != last_ydir) + last_ydir = ydir; + else if (y1 >= POLY_YMIN && y1 <= ymax) + { + x1 = Line.first.x - xoffs; + if (x1 < POLY_XMIN) + xor_dot (FramePtr, POLY_XMIN - 1, y1); + else if (x1 <= xmax) + xor_dot (FramePtr, x1, y1); + } + } + + intersect_code = _clip_line (pClipRect, &Line); + Line.first.x -= xoffs; + Line.first.y -= yoffs; + Line.second.x -= xoffs; + Line.second.y -= yoffs; + if (intersect_code) + { + xor_line (FramePtr, &Line); + + if (intersect_code & INTERSECT_LEFT) + { + if (Line.end_points_exchanged) + y1 = y2; + + y2 = Line.first.y; + if (y2 > POLY_YMIN && y1 < y2) + { + --y2; + if (y1 < POLY_YMIN) + y1 = POLY_YMIN; + ShadowLine.first.y = y1; + ShadowLine.second.y = y2; + ShadowLine.abs_delta_y = y2 - y1; + xor_line (FramePtr, &ShadowLine); + } + else if (y2 < ymax && y1 > y2) + { + ++y2; + if (y1 > ymax) + y1 = ymax; + ShadowLine.first.y = y2; + ShadowLine.second.y = y1; + ShadowLine.abs_delta_y = y1 - y2; + xor_line (FramePtr, &ShadowLine); + } + } + } + else if (Line.first.x < POLY_XMIN + && (Line.first.y >= POLY_YMIN + || Line.second.y >= POLY_YMIN) + && (Line.first.y <= ymax + || Line.second.y <= ymax)) + { +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + if (Line.first.y > Line.second.y) + { + y1 = MAX (Line.second.y, POLY_YMIN); + y2 = MIN (Line.first.y, ymax); + } + else + { + y1 = MAX (Line.first.y, POLY_YMIN); + y2 = MIN (Line.second.y, ymax); + } + + if (Line.first.x == Line.second.x) /* vertical line */ + { + ShadowLine.first.y = y1; + ShadowLine.second.y = y2; + ShadowLine.abs_delta_y = y2 - y1; + xor_line (FramePtr, &ShadowLine); + } + else /* sloped line */ + { + SIZE line_delta_x, line_delta_y; + long yinter; /* y intercept with xmin */ + + line_delta_x = Line.second.x - Line.first.x; + line_delta_y = Line.second.y - Line.first.y; + yinter = ((long)Line.first.y * line_delta_x) + + ((long)(POLY_XMIN - Line.first.x) + * line_delta_y); + if ((Line.first.y < Line.second.y + && yinter >= (long)(POLY_YMIN * line_delta_x)) + || (Line.first.y > Line.second.y + && yinter <= (long)ymax * line_delta_x)) + { + ShadowLine.first.y = y1; + ShadowLine.second.y = y2; + ShadowLine.abs_delta_y = y2 - y1; + xor_line (FramePtr, &ShadowLine); + } + } + } + } + } while (--i); + + on_off (FramePtr); + } + + /* now outline the polygon */ + pt1 = lpPolygon->PtList; + for (i = lpPolygon->PtCount - 1; i > 0; --i) + { + LOGtoDEV (pt1++, (PPOINT)&Line, 2); + if (_clip_line (pClipRect, &Line)) + { + Line.first.x -= xoffs; + Line.first.y -= yoffs; + Line.second.x -= xoffs; + Line.second.y -= yoffs; + or_line (FramePtr, &Line); + } + } + + Line.first = *pt1; + Line.second = lpPolygon->PtList[0]; + LOGtoDEV ((PPOINT)&Line, (PPOINT)&Line, 2); + if (_clip_line (pClipRect, &Line)) + { + Line.first.x -= xoffs; + Line.first.y -= yoffs; + Line.second.x -= xoffs; + Line.second.y -= yoffs; + or_line (FramePtr, &Line); + } +} + +void +_fillpoly_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ +#ifndef __WATCOMC__ + MEM_HANDLE h; + FRAME_DESC PolyFrame; + PRIMITIVE locPrim; + + SetFrameX (&PolyFrame, 0); + SetFrameY (&PolyFrame, 0); + SetFrameWidth (&PolyFrame, pClipRect->extent.width + POLY_XMIN); + SetFrameHeight (&PolyFrame, pClipRect->extent.height + POLY_YMIN); + SetImageShift (&PolyFrame.MaskImage, 0); + AllocMaskImage (&PolyFrame, RAM_DRAWABLE, 0); + SubImageFlags (&PolyFrame.PixmapImage, ~0); + SetImageData (&PolyFrame.PixmapImage, NULL_PTR); + AllocPixmapImage (&PolyFrame, RAM_DRAWABLE, 0); + h = AllocGraphicData (GetImageByteCount (&PolyFrame.MaskImage)); + SetImageData (&PolyFrame.MaskImage, LockData (h)); + + create_poly (pClipRect, + (PPOLYGON_DESC)PrimPtr->Object.Polygon, &PolyFrame); + + _save_stamp.origin.x = pClipRect->corner.x - POLY_XMIN; + _save_stamp.origin.y = pClipRect->corner.y - POLY_YMIN; + locPrim.Object.Stamp.frame = &PolyFrame; + SetPrimType (&locPrim, STAMPFILL_PRIM); + SetPrimColor (&locPrim, GetPrimColor (PrimPtr)); + + DrawGraphicsFunc (pClipRect, &locPrim); + + UnlockData (h); + FreeMaskImage (h); +#endif /* __WATCOMC__ */ +} + diff --git a/sc2/src/sc2code/libs/graphics/map.c b/sc2/src/sc2code/libs/graphics/map.c new file mode 100644 index 000000000..bb0f5548c --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/map.c @@ -0,0 +1,201 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +MAP_TYPE +SetContextMapType (MAP_TYPE MapType) +{ +#ifndef MAPPING + return (MAP_NOXFORM); +#else /* MAPPING */ + MAP_TYPE oldMapType; + + if (!ContextActive ()) + oldMapType = MAP_NOXFORM; + else if ((oldMapType = _get_context_map_type ()) != MapType) + { + SwitchContextMapType (MapType); + } + + return (oldMapType); +#endif /* MAPPING */ +} + +BOOLEAN +SetContextWinOrigin (PPOINT lpOrg) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + SwitchContextWinOrigin (lpOrg); + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +SetContextViewExtents (PEXTENT lpExtent) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + SwitchContextViewExtents (lpExtent); + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +SetContextWinExtents (PEXTENT lpExtent) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + SwitchContextWinExtents (lpExtent); + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +GetContextWinOrigin (PPOINT lpOrg) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + *lpOrg = _pCurContext->Map.WinOrg; + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +GetContextViewExtents (PEXTENT lpExtent) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + *lpExtent = _pCurContext->Map.ViewExt; + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +GetContextWinExtents (PEXTENT lpExtent) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive ()) + return (FALSE); + + *lpExtent = _pCurContext->Map.WinExt; + + return (TRUE); +#endif /* MAPPING */ +} + +BOOLEAN +LOGtoDEV (PPOINT lpSrcPt, PPOINT lpDstPt, COUNT NumPoints) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive () || NumPoints == 0) + return (FALSE); + + { + MAP_TYPE MapType; + + _init_context_map (&MapType); + if (MapType == MAP_NOXFORM) + { + do + *lpDstPt++ = *lpSrcPt++; + while (--NumPoints); + } + else + { + do + { + lpDstPt->x = LXtoDX (lpSrcPt->x); + lpDstPt->y = LYtoDY (lpSrcPt->y); + ++lpSrcPt; + ++lpDstPt; + } while (--NumPoints); + } + _uninit_context_map (); + + return (TRUE); + } +#endif /* MAPPING */ +} + +BOOLEAN +DEVtoLOG (PPOINT lpSrcPt, PPOINT lpDstPt, COUNT NumPoints) +{ +#ifndef MAPPING + return (FALSE); +#else /* MAPPING */ + if (!ContextActive () || NumPoints == 0) + return (FALSE); + + { + MAP_TYPE MapType; + + _init_context_map (&MapType); + if (MapType == MAP_NOXFORM) + { + do + *lpDstPt++ = *lpSrcPt++; + while (--NumPoints); + } + else + { + do + { + lpDstPt->x = DXtoLX (lpSrcPt->x); + lpDstPt->y = DYtoLY (lpSrcPt->y); + ++lpSrcPt; + ++lpDstPt; + } while (--NumPoints); + } + _uninit_context_map (); + + return (TRUE); + } +#endif /* MAPPING */ +} + diff --git a/sc2/src/sc2code/libs/graphics/pixmap.c b/sc2/src/sc2code/libs/graphics/pixmap.c new file mode 100644 index 000000000..cf7ebcf14 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/pixmap.c @@ -0,0 +1,191 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +FRAME +CaptureDrawable (DRAWABLE Drawable) +{ + DRAWABLEPTR DrawablePtr; + + DrawablePtr = LockDrawable (Drawable); + if (DrawablePtr) + { + COUNT FrameIndex; + + FrameIndex = GetDrawableIndex (Drawable); + return ((FRAME)&DrawablePtr->Frame[FrameIndex]); + } + + return (0); +} + +DRAWABLE +ReleaseDrawable (FRAMEPTR FramePtr) +{ + if (FramePtr != 0) + { + DRAWABLE Drawable; + DRAWABLEPTR DrawablePtr; + + DrawablePtr = GetFrameParentDrawable (FramePtr); + Drawable = BUILD_DRAWABLE ( + DrawablePtr->hDrawable, INDEX_GET (FramePtr->TypeIndexAndFlags) + ); + UnlockDrawable (Drawable); + + return (Drawable); + } + + return (0); +} + +MEM_HANDLE +GetFrameHandle (FRAMEPTR FramePtr) +{ + DRAWABLEPTR DrawablePtr; + + if (FramePtr == 0) + return (0); + + DrawablePtr = GetFrameParentDrawable (FramePtr); + return (DrawablePtr->hDrawable); +} + +COUNT +GetFrameCount (FRAMEPTR FramePtr) +{ + DRAWABLEPTR DrawablePtr; + + if (FramePtr == 0) + return (0); + + DrawablePtr = GetFrameParentDrawable (FramePtr); + return (INDEX_GET (DrawablePtr->FlagsAndIndex) + 1); +} + +COUNT +GetFrameIndex (FRAMEPTR FramePtr) +{ + if (FramePtr == 0) + return (0); + + return (INDEX_GET (FramePtr->TypeIndexAndFlags)); +} + +FRAME +SetAbsFrameIndex (FRAMEPTR FramePtr, COUNT FrameIndex) +{ + if (FramePtr != 0) + { + DRAWABLEPTR DrawablePtr; + + DrawablePtr = GetFrameParentDrawable (FramePtr); + + FrameIndex = FrameIndex + % (INDEX_GET (DrawablePtr->FlagsAndIndex) + 1); + FramePtr = (FRAMEPTR)&DrawablePtr->Frame[FrameIndex]; + } + + return ((FRAME)FramePtr); +} + +FRAME +SetRelFrameIndex (FRAMEPTR FramePtr, SIZE FrameOffs) +{ + if (FramePtr != 0) + { + COUNT num_frames; + DRAWABLEPTR DrawablePtr; + + DrawablePtr = GetFrameParentDrawable (FramePtr); + num_frames = INDEX_GET (DrawablePtr->FlagsAndIndex) + 1; + if (FrameOffs < 0) + { + while ((FrameOffs += num_frames) < 0) + ; + } + + FrameOffs = (INDEX_GET (FramePtr->TypeIndexAndFlags) + FrameOffs) % num_frames; + FramePtr = (FRAMEPTR)&DrawablePtr->Frame[FrameOffs]; + } + + return ((FRAME)FramePtr); +} + +FRAME +SetEquFrameIndex (FRAMEPTR DstFramePtr, FRAMEPTR SrcFramePtr) +{ + if (DstFramePtr && SrcFramePtr) + return ((FRAME)( + (PBYTE)((GetFrameParentDrawable (DstFramePtr))->Frame) + + ((PBYTE)SrcFramePtr - + (PBYTE)((GetFrameParentDrawable (SrcFramePtr))->Frame)) + )); + + return (0); +} + +FRAME +IncFrameIndex (FRAMEPTR FramePtr) +{ + DRAWABLEPTR DrawablePtr; + + if (FramePtr == 0) + return (0); + + DrawablePtr = GetFrameParentDrawable (FramePtr); + if (INDEX_GET (FramePtr->TypeIndexAndFlags) < INDEX_GET (DrawablePtr->FlagsAndIndex)) + return ((FRAME)++FramePtr); + else + return ((FRAME)DrawablePtr->Frame); +} + +FRAME +DecFrameIndex (FRAMEPTR FramePtr) +{ + if (FramePtr == 0) + return (0); + + if (INDEX_GET (FramePtr->TypeIndexAndFlags)) + return ((FRAME)--FramePtr); + else + { + DRAWABLEPTR DrawablePtr; + + DrawablePtr = GetFrameParentDrawable (FramePtr); + return ((FRAME)&DrawablePtr->Frame[INDEX_GET (DrawablePtr->FlagsAndIndex)]); + } +} + +void +XFlipFrame (FRAMEPTR FramePtr) +{ + if (FramePtr) + { + if (GetFrameFlags (FramePtr) & X_FLIP) + { + SubFrameFlags (FramePtr, X_FLIP); + } + else + { + AddFrameFlags (FramePtr, X_FLIP); + } + } +} + diff --git a/sc2/src/sc2code/libs/graphics/poly.c b/sc2/src/sc2code/libs/graphics/poly.c new file mode 100644 index 000000000..0624dab0f --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/poly.c @@ -0,0 +1,178 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +void +DrawPolygon (POLYGON Polygon) +{ + SetPrimType (&_locPrim, POLY_PRIM); + _locPrim.Object.Polygon = Polygon; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +DrawFilledPolygon (POLYGON Polygon) +{ + SetPrimType (&_locPrim, POLYFILL_PRIM); + _locPrim.Object.Polygon = Polygon; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +POLYREF +CreatePolygon (COUNT PtCount) +{ + POLYREF hPoly; + + hPoly = (POLYREF)NULL_PTR; + if (PtCount > 0) + { + PPOLYGON_DESC lpPoly; + + if ((hPoly = AllocPolygon (PtCount)) != (POLYREF)NULL_PTR) + { + if ((lpPoly = LockPolygon (hPoly)) == (PPOLYGON_DESC)NULL_PTR) + { + FreePolygon (hPoly); + hPoly = (POLYREF)NULL_PTR; + } + else + { + lpPoly->hPoly = hPoly; + lpPoly->PtCount = PtCount; + UnlockPolygon (hPoly); + } + } + } + + return (hPoly); +} + +BOOLEAN +DestroyPolygon (POLYREF PolyRef) +{ + return (FreePolygon (PolyRef)); +} + +POLYGON +CapturePolygon (POLYREF PolyRef) +{ + PPOLYGON_DESC lpPoly; + + if (PolyRef == (POLYREF)NULL_PTR) + lpPoly = (PPOLYGON_DESC)NULL_PTR; + else + { + lpPoly = LockPolygon (PolyRef); + lpPoly->PtList = (PPOINT)&lpPoly[1]; + } + + return ((POLYGON)lpPoly); +} + +POLYREF +ReleasePolygon (POLYGON Polygon) +{ + POLYREF PolyRef; + + PolyRef = (POLYREF)NULL_PTR; + if (Polygon != (POLYGON)NULL_PTR) + { + PolyRef = ((PPOLYGON_DESC)Polygon)->hPoly; + UnlockPolygon (PolyRef); + } + + return (PolyRef); +} + +BOOLEAN +SetPolygonPoint (POLYGON Polygon, COUNT PtIndex, COORD x, COORD y) +{ + BOOLEAN retval; + + retval = FALSE; + if (Polygon != (POLYGON)NULL_PTR) + { + PPOLYGON_DESC lpPoly; + PPOINT lpPt; + + lpPoly = (PPOLYGON_DESC)Polygon; + if (lpPoly->BoundRect.extent.width == 0) + { + lpPoly->BoundRect.corner.x = x; + lpPoly->BoundRect.corner.y = y; + lpPoly->BoundRect.extent.width = + lpPoly->BoundRect.extent.height = 1; + } + else + { + SIZE delta, width, height; + + width = height = 1; + if ((delta = x - lpPoly->BoundRect.corner.x) >= 0) + width += delta; + else + { + lpPoly->BoundRect.extent.width -= delta; + lpPoly->BoundRect.corner.x = x; + } + if ((delta = y - lpPoly->BoundRect.corner.y) >= 0) + height += delta; + else + { + lpPoly->BoundRect.extent.height -= delta; + lpPoly->BoundRect.corner.y = y; + } + if ((delta = width - lpPoly->BoundRect.extent.width) > 0) + lpPoly->BoundRect.extent.width += delta; + if ((delta = height - lpPoly->BoundRect.extent.height) > 0) + lpPoly->BoundRect.extent.height += delta; + } + + lpPt = &lpPoly->PtList[PtIndex]; + lpPt->x = x; + lpPt->y = y; + + retval = TRUE; + } + + return (retval); +} + +BOOLEAN +GetPolygonPoint (POLYGON Polygon, COUNT PtIndex, PCOORD px, PCOORD py) +{ + BOOLEAN retval; + + retval = FALSE; + if (Polygon != (POLYGON)NULL_PTR) + { + PPOINT lpPt; + + lpPt = &((PPOLYGON_DESC)Polygon)->PtList[PtIndex]; + *px = lpPt->x; + *py = lpPt->y; + + retval = TRUE; + } + + return (retval); +} + diff --git a/sc2/src/sc2code/libs/graphics/rect.c b/sc2/src/sc2code/libs/graphics/rect.c new file mode 100644 index 000000000..a35e4c1a8 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/rect.c @@ -0,0 +1,91 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +void +DrawPoint (PPOINT lpPoint) +{ + SetPrimType (&_locPrim, POINT_PRIM); + _locPrim.Object.Point = *lpPoint; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +DrawRectangle (PRECT lpRect) +{ + SetPrimType (&_locPrim, RECT_PRIM); + _locPrim.Object.Rect = *lpRect; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +DrawFilledRectangle (PRECT lpRect) +{ + SetPrimType (&_locPrim, RECTFILL_PRIM); + _locPrim.Object.Rect = *lpRect; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +_rect_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) +{ + COORD x, y; + RECTPTR RectPtr; + PRIMITIVE locPrim; + + locPrim = *PrimPtr; + SetPrimType (&locPrim, RECTFILL_PRIM); + + RectPtr = &PrimPtr->Object.Rect; + locPrim.Object.Rect = *pClipRect; + if (locPrim.Object.Rect.corner.x == RectPtr->corner.x) + { + locPrim.Object.Rect.extent.width = 1; + DrawGraphicsFunc (&locPrim.Object.Rect, &locPrim); + locPrim.Object.Rect.extent.width = pClipRect->extent.width; + } + if (locPrim.Object.Rect.corner.y == RectPtr->corner.y) + { + locPrim.Object.Rect.extent.height = 1; + DrawGraphicsFunc (&locPrim.Object.Rect, &locPrim); + locPrim.Object.Rect.extent.height = pClipRect->extent.height; + } + if ((x = locPrim.Object.Rect.corner.x + + locPrim.Object.Rect.extent.width) == + RectPtr->corner.x + RectPtr->extent.width) + { + locPrim.Object.Rect.corner.x = x - 1; + locPrim.Object.Rect.extent.width = 1; + DrawGraphicsFunc (&locPrim.Object.Rect, &locPrim); + locPrim.Object.Rect.corner.x = pClipRect->corner.x; + locPrim.Object.Rect.extent.width = pClipRect->extent.width; + } + if ((y = locPrim.Object.Rect.corner.y + + locPrim.Object.Rect.extent.height) == + RectPtr->corner.y + RectPtr->extent.height) + { + locPrim.Object.Rect.corner.y = y - 1; + locPrim.Object.Rect.extent.height = 1; + DrawGraphicsFunc (&locPrim.Object.Rect, &locPrim); + } +} + diff --git a/sc2/src/sc2code/libs/graphics/resgfx.c b/sc2/src/sc2code/libs/graphics/resgfx.c new file mode 100644 index 000000000..6bd40587c --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/resgfx.c @@ -0,0 +1,52 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +static COUNT _gfx_type; + +BOOLEAN +InstallGraphicResTypes (COUNT cel_type, COUNT font_type) +{ + _gfx_type = cel_type; + InstallResTypeVectors (cel_type, _GetCelData, _ReleaseCelData); + InstallResTypeVectors (font_type, _GetFontData, _ReleaseFontData); + return (TRUE); +} + +DWORD +LoadGraphicInstance (DWORD res) +{ + MEM_HANDLE hData; + + hData = GetResource (res); + if (hData) + DetachResource (res); + + return ((DWORD)hData); +} + +DWORD +LoadGraphic (DWORD res) +{ + if (_gfx_type) + return (LoadGraphicInstance (res)); + else + return (LoadCelFile ((PVOID)res)); +} + diff --git a/sc2/src/sc2code/libs/graphics/stamp.c b/sc2/src/sc2code/libs/graphics/stamp.c new file mode 100644 index 000000000..165988ce8 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/stamp.c @@ -0,0 +1,47 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxintrn.h" + +void +DrawStamp (PSTAMP lpStamp) +{ + SetPrimType (&_locPrim, STAMP_PRIM); + _locPrim.Object.Stamp = *lpStamp; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +DrawFilledStamp (PSTAMP lpStamp) +{ + SetPrimType (&_locPrim, STAMPFILL_PRIM); + _locPrim.Object.Stamp = *lpStamp; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + +void +DrawStampCMap (PSTAMP_CMAP lpStampCMap) +{ + SetPrimType (&_locPrim, STAMPCMAP_PRIM); + _locPrim.Object.StampCMap = *lpStampCMap; + + DrawBatch (&_locPrim, 0, BATCH_SINGLE); +} + diff --git a/sc2/src/sc2code/libs/inplib.h b/sc2/src/sc2code/libs/inplib.h new file mode 100644 index 000000000..ffae1a442 --- /dev/null +++ b/sc2/src/sc2code/libs/inplib.h @@ -0,0 +1,124 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _INPLIB_H +#define _INPLIB_H + +#include "memlib.h" + +typedef PVOID INPUT_REF; +typedef MEM_HANDLE INPUT_DEVICE; +typedef DWORD INPUT_STATE; + +typedef enum +{ + KEYBOARD_DEVICE = 0, + JOYSTICK_DEVICE, + MOUSE_DEVICE +} INPUT_DEVTYPE; + +/* Serial Keyboard Pseudo UNICODE Equivalents */ +#define SK_DELETE ((UNICODE)127) +#define SK_LF_ARROW ((UNICODE)128) +#define SK_RT_ARROW ((UNICODE)129) +#define SK_UP_ARROW ((UNICODE)130) +#define SK_DN_ARROW ((UNICODE)131) +#define SK_HOME ((UNICODE)132) +#define SK_PAGE_UP ((UNICODE)133) +#define SK_END ((UNICODE)134) +#define SK_PAGE_DOWN ((UNICODE)135) +#define SK_INSERT ((UNICODE)136) +#define SK_KEYPAD_PLUS ((UNICODE)137) +#define SK_KEYPAD_MINUS ((UNICODE)138) + +#define SK_LF_SHIFT ((UNICODE)139) +#define SK_RT_SHIFT ((UNICODE)140) +#define SK_CTL ((UNICODE)141) +#define SK_ALT ((UNICODE)142) + +#define KEY_DOWN ((BYTE)(1 << 0)) +#define KEY_UP ((BYTE)(1 << 1)) +#define LF_SHIFT_DOWN ((BYTE)(1 << 2)) +#define RT_SHIFT_DOWN ((BYTE)(1 << 3)) +#define CTL_DOWN ((BYTE)(1 << 4)) +#define ALT_DOWN ((BYTE)(1 << 5)) + +#define SK_F1 ((UNICODE)143) +#define SK_F2 ((UNICODE)144) +#define SK_F3 ((UNICODE)145) +#define SK_F4 ((UNICODE)146) +#define SK_F5 ((UNICODE)147) +#define SK_F6 ((UNICODE)148) +#define SK_F7 ((UNICODE)149) +#define SK_F8 ((UNICODE)150) +#define SK_F9 ((UNICODE)151) +#define SK_F10 ((UNICODE)152) +#define SK_F11 ((UNICODE)153) +#define SK_F12 ((UNICODE)154) + +#define DEVTYPE_MASK 0x03 +#define GetInputUNICODE(is) (LOWORD (is)) +#define GetInputXComponent(is) ((SBYTE)(LOBYTE (LOWORD (is)))) +#define GetInputYComponent(is) ((SBYTE)(HIBYTE (LOWORD (is)))) +#define GetInputDevType(is) ((INPUT_DEVTYPE)(HIWORD (is) & DEVTYPE_MASK)) +#define SetInputUNICODE(is,a) \ + (*(is) = (*(is) & ~0x0000FFFFL) | (UNICODE)(a)) +#define SetInputXComponent(is,x) \ + (*(is) = (*(is) & ~0x000000FFL) | (BYTE)(x)) +#define SetInputYComponent(is,y) \ + (*(is) = (*(is) & ~0x0000FF00L) | (UWORD)((BYTE)(y) << 8)) +#define SetInputDevType(is,t) \ + (*(is) = (*(is) & ~0x00030000L) | ((DWORD)((t) & DEVTYPE_MASK) << 16)) +#define DEVICE_BUTTON1 ((INPUT_STATE)1 << 19) +#define DEVICE_BUTTON2 ((INPUT_STATE)1 << 20) +#define DEVICE_BUTTON3 ((INPUT_STATE)1 << 21) +#define DEVICE_PAUSE ((INPUT_STATE)1 << 22) +#define DEVICE_EXIT ((INPUT_STATE)1 << 23) +#define DEVICE_LEFTSHIFT ((INPUT_STATE)1 << 24) +#define DEVICE_RIGHTSHIFT ((INPUT_STATE)1 << 25) + +extern BOOLEAN InitInput (UNICODE PauseKey, UNICODE ExitKey, BOOLEAN + (*PauseFunc) (void)); +extern BOOLEAN UninitInput (void); +extern INPUT_DEVICE CreateSerialKeyboardDevice (void); +extern INPUT_DEVICE CreateJoystickKeyboardDevice (UNICODE lfkey, UNICODE + rtkey, UNICODE topkey, UNICODE botkey, UNICODE but1key, UNICODE + but2key, UNICODE but3key, UNICODE shift1key, UNICODE shift2key); +extern INPUT_DEVICE CreateJoystickDevice (COUNT port); +extern INPUT_DEVICE CreateInternalDevice (INPUT_STATE (*input_func) + (INPUT_REF InputRef, INPUT_STATE InputState)); +extern BOOLEAN DestroyInputDevice (INPUT_DEVICE InputDevice); +extern INPUT_REF CaptureInputDevice (INPUT_DEVICE InputDevice); +extern INPUT_DEVICE ReleaseInputDevice (INPUT_REF InputRef); +extern INPUT_STATE GetInputState (INPUT_REF InputRef); +extern INPUT_STATE AnyButtonPress (BOOLEAN DetectSpecial); + +extern void FlushInput (void); +extern int KeyDown (UNICODE which_scan); +extern UNICODE GetUnicodeKey (void); +extern UNICODE KBDToUNICODE (UNICODE which_key); +extern UNICODE KeyHit (void); +extern BYTE GetKeyState (UNICODE key); + +extern BOOLEAN FindMouse (void); +extern void MoveMouse (SWORD x, SWORD y); +extern BYTE LocateMouse (PSWORD px, PSWORD py); + +#endif /* _INPLIB_H */ + + diff --git a/sc2/src/sc2code/libs/input/Makefile.am b/sc2/src/sc2code/libs/input/Makefile.am new file mode 100644 index 000000000..b799d6b6a --- /dev/null +++ b/sc2/src/sc2code/libs/input/Makefile.am @@ -0,0 +1,14 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libinput.la +libinput_la_SOURCES = input.c +noinst_HEADERS = inpintrn.h + diff --git a/sc2/src/sc2code/libs/input/inpintrn.h b/sc2/src/sc2code/libs/input/inpintrn.h new file mode 100644 index 000000000..642e7ffa9 --- /dev/null +++ b/sc2/src/sc2code/libs/input/inpintrn.h @@ -0,0 +1,86 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _INPINTRN_H +#define _INPINTRN_H + +#include "inplib.h" + +#define NUM_INPUTS 16 + +typedef struct inp_dev +{ + INPUT_DEVICE ThisDevice; + union + { + UNICODE key_equivalent[NUM_INPUTS]; + COUNT joystick_port; + } device; + INPUT_STATE (*input_func) (INPUT_REF InputRef, INPUT_STATE + InputState); +} INPUT_DESC; +typedef INPUT_DESC *PINPUT_DESC; +typedef PINPUT_DESC INPUT_DESCPTR; + +#define INPUT_DEVICE_PRIORITY DEFAULT_MEM_PRIORITY + +typedef PBYTE BYTEPTR; + +#define AllocInputDevice() \ + (INPUT_DEVICE)mem_allocate ((MEM_SIZE)sizeof (INPUT_DESC), \ + MEM_ZEROINIT, INPUT_DEVICE_PRIORITY, MEM_SIMPLE) +#define LockInputDevice(InputDevice) (INPUT_DESCPTR)mem_lock (InputDevice) +#define UnlockInputDevice(InputDevice) mem_unlock (InputDevice) +#define FreeInputDevice(InputDevice) mem_release (InputDevice) + +#define SetInputDeviceHandle(i,h) \ + ((INPUT_DESCPTR)(i))->ThisDevice = (h) +#define SetInputDeviceKeyEquivalents(i,l,r,t,b,b1,b2,b3,s1,s2) \ + (((INPUT_DESCPTR)(i))->device.key_equivalent[0] = KBDToUNICODE (l), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[1] = KBDToUNICODE (r), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[2] = KBDToUNICODE (t), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[3] = KBDToUNICODE (b), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[4] = KBDToUNICODE (b1), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[5] = KBDToUNICODE (b2), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[6] = KBDToUNICODE (b3), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[7] = KBDToUNICODE (s1), \ + ((INPUT_DESCPTR)(i))->device.key_equivalent[8] = KBDToUNICODE (s2)) +#define SetInputDeviceJoystickPort(i,p) \ + ((INPUT_DESCPTR)(i))->device.joystick_port = (p) +#define SetInputDeviceInputFunc(i,f) \ + ((INPUT_DESCPTR)(i))->input_func = (f) + +#define GetInputDeviceHandle(i) \ + ((INPUT_DESCPTR)(i))->ThisDevice +#define GetInputDeviceKeyEquivalentPtr(i) \ + ((INPUT_DESCPTR)(i))->device.key_equivalent +#define GetInputDeviceJoystickPort(i) \ + ((INPUT_DESCPTR)(i))->device.joystick_port +#define GetInputDeviceInputFunc(i) \ + ((INPUT_DESCPTR)(i))->input_func + +extern INPUT_STATE _get_serial_keyboard_state (INPUT_REF InputRef, + INPUT_STATE InputState); +extern INPUT_STATE _get_joystick_keyboard_state (INPUT_REF InputRef, + INPUT_STATE InputState); +extern INPUT_STATE _get_joystick_state (INPUT_REF InputRef, + INPUT_STATE InputState); +extern BOOLEAN _joystick_port_active (COUNT port); +extern INPUT_STATE _get_pause_exit_state (void); + +#endif /* _INPINTRN_H */ diff --git a/sc2/src/sc2code/libs/input/input.c b/sc2/src/sc2code/libs/input/input.c new file mode 100644 index 000000000..2a6fd6ead --- /dev/null +++ b/sc2/src/sc2code/libs/input/input.c @@ -0,0 +1,184 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "inpintrn.h" + +INPUT_DEVICE +CreateSerialKeyboardDevice (void) +{ + INPUT_DEVICE InputDevice; + + if ((InputDevice = AllocInputDevice ()) != (INPUT_DEVICE)NULL_PTR) + { + INPUT_DESCPTR InputPtr; + + if ((InputPtr = + LockInputDevice (InputDevice)) == (INPUT_DESCPTR)NULL_PTR) + { + FreeInputDevice (InputDevice); + InputDevice = (INPUT_DEVICE)NULL_PTR; + } + else + { + SetInputDeviceHandle (InputPtr, InputDevice); + SetInputDeviceInputFunc (InputPtr, _get_serial_keyboard_state); + + UnlockInputDevice (InputDevice); + } + } + + return (InputDevice); +} + +INPUT_DEVICE +CreateJoystickKeyboardDevice (UNICODE lfkey, UNICODE rtkey, UNICODE + topkey, UNICODE botkey, UNICODE but1key, UNICODE but2key, UNICODE + but3key, UNICODE shift1key, UNICODE shift2key) +{ + INPUT_DEVICE InputDevice; + + if ((InputDevice = AllocInputDevice ()) != (INPUT_DEVICE)NULL_PTR) + { + INPUT_DESCPTR InputPtr; + + if ((InputPtr = + LockInputDevice (InputDevice)) == (INPUT_DESCPTR)NULL_PTR) + { + FreeInputDevice (InputDevice); + InputDevice = (INPUT_DEVICE)NULL_PTR; + } + else + { + SetInputDeviceHandle (InputPtr, InputDevice); + SetInputDeviceInputFunc (InputPtr, _get_joystick_keyboard_state); + SetInputDeviceKeyEquivalents (InputPtr, + lfkey, rtkey, topkey, botkey, + but1key, but2key, but3key, + shift1key, shift2key); + + UnlockInputDevice (InputDevice); + } + } + + return (InputDevice); +} + +INPUT_DEVICE +CreateJoystickDevice (COUNT port) +{ + INPUT_DEVICE InputDevice; + + if (!_joystick_port_active (port)) + InputDevice = (INPUT_DEVICE)NULL_PTR; + else if ((InputDevice = AllocInputDevice ()) != (INPUT_DEVICE)NULL_PTR) + { + INPUT_DESCPTR InputPtr; + + if ((InputPtr = + LockInputDevice (InputDevice)) == (INPUT_DESCPTR)NULL_PTR) + { + FreeInputDevice (InputDevice); + InputDevice = (INPUT_DEVICE)NULL_PTR; + } + else + { + SetInputDeviceHandle (InputPtr, InputDevice); + SetInputDeviceInputFunc (InputPtr, _get_joystick_state); + SetInputDeviceJoystickPort (InputPtr, port); + + UnlockInputDevice (InputDevice); + } + } + + return (InputDevice); +} + +INPUT_DEVICE +CreateInternalDevice (INPUT_STATE (*input_func) (INPUT_REF InputRef, + INPUT_STATE InputState)) +{ + INPUT_DEVICE InputDevice; + + if (input_func == NULL_PTR) + InputDevice = (INPUT_DEVICE)NULL_PTR; + else if ((InputDevice = AllocInputDevice ()) != (INPUT_DEVICE)NULL_PTR) + { + INPUT_DESCPTR InputPtr; + + if ((InputPtr = + LockInputDevice (InputDevice)) == (INPUT_DESCPTR)NULL_PTR) + { + FreeInputDevice (InputDevice); + InputDevice = (INPUT_DEVICE)NULL_PTR; + } + else + { + SetInputDeviceHandle (InputPtr, InputDevice); + SetInputDeviceInputFunc (InputPtr, input_func); + + UnlockInputDevice (InputDevice); + } + } + + return (InputDevice); +} + +INPUT_REF +CaptureInputDevice (INPUT_DEVICE InputDevice) +{ + if (InputDevice != (INPUT_DEVICE)NULL_PTR) + return ((INPUT_REF)LockInputDevice (InputDevice)); + + return ((INPUT_REF)NULL_PTR); +} + +INPUT_DEVICE +ReleaseInputDevice (INPUT_REF InputRef) +{ + INPUT_DEVICE InputDevice; + + if (InputRef == (INPUT_REF)NULL_PTR) + InputDevice = (INPUT_DEVICE)NULL_PTR; + else + { + InputDevice = GetInputDeviceHandle (InputRef); + UnlockInputDevice (InputDevice); + } + + return (InputDevice); +} + +BOOLEAN +DestroyInputDevice (INPUT_DEVICE InputDevice) +{ + if (InputDevice != (INPUT_DEVICE)NULL_PTR) + return (FreeInputDevice (InputDevice)); + + return (FALSE); +} + +INPUT_STATE +GetInputState (INPUT_REF InputRef) +{ + if (InputRef == 0) + return (_get_pause_exit_state ()); + else + return ((*GetInputDeviceInputFunc (InputRef)) + (InputRef, _get_pause_exit_state ())); +} + diff --git a/sc2/src/sc2code/libs/math/Makefile.am b/sc2/src/sc2code/libs/math/Makefile.am new file mode 100644 index 000000000..7b190b131 --- /dev/null +++ b/sc2/src/sc2code/libs/math/Makefile.am @@ -0,0 +1,14 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libmath.la +libmath_la_SOURCES = fastrand.c random.c sqrt.c +noinst_HEADERS = mthintrn.h random.h + diff --git a/sc2/src/sc2code/libs/math/fastrand.c b/sc2/src/sc2code/libs/math/fastrand.c new file mode 100644 index 000000000..7a8552ac0 --- /dev/null +++ b/sc2/src/sc2code/libs/math/fastrand.c @@ -0,0 +1,125 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "mthintrn.h" +#include "random.h" /* get the externs for error checking */ + +/* ----------------------------GLOBAL DATA-------------------------------- */ + +DWORD random_table[TABLE_SIZE]; +COUNT fast_index = 0; /* fast random cycling index */ + +/* ----------------------------PROTOTYPES--------------------------------- */ + +DWORD indexed_random_table(COUNT index); +void reseed_fast_random(); +DWORD fast_random(); +DWORD seed_fast_random(DWORD seed); + +/***************************************************************************** +* FUNC: DWORD seed_fast_random(DWORD seed) +* +* DESC:generate a small table of random numbers for later use by fast_random() +* +* NOTES: the table has a prime number of entries +* +* HISTORY: Created By Robert Leyland +* +*****************************************************************************/ + +DWORD +seed_fast_random(DWORD seed) +{ + DWORD retval; + COUNT index; + + retval = SeedRandom(seed); + + for( index = 0; index < TABLE_SIZE; index++ ) + random_table[index] = Random(); + + fast_index = 0; /* must be set to the start of the table for + repeatability... */ + + return (retval); +} + + +/***************************************************************************** +* FUNC: DWORD fast_random() +* +* DESC:return the next random number from the random number table +* +* NOTES: +* +* HISTORY: Created By Robert Leyland +* +*****************************************************************************/ + +DWORD +fast_random() +{ + fast_index++; + if( fast_index == TABLE_SIZE ) + fast_index = 0; + + return( random_table[fast_index] ); +} + +/***************************************************************************** +* FUNC: void reseed_fast_random() +* +* DESC:shifts the table pointer by calling the "real" random +* +* NOTES: +* +* HISTORY: Created By Robert Leyland +* +*****************************************************************************/ + +void +reseed_fast_random() +{ + fast_index = (COUNT)(Random() % TABLE_SIZE); + +} + + +/***************************************************************************** +* FUNC: DWORD indexed_random_table(COUNT index) +* +* DESC:return a "random" number from the random number table, as indexed +* for repeatability +* +* NOTES:used by texturing functions +* +* HISTORY: Created By Robert Leyland +* +*****************************************************************************/ + +DWORD +indexed_random_table(COUNT index) +{ + if( index > TABLE_SIZE ) /* only do % if really needed */ + index = index % TABLE_SIZE; + + return(random_table[index]); +} + + + diff --git a/sc2/src/sc2code/libs/math/mthintrn.h b/sc2/src/sc2code/libs/math/mthintrn.h new file mode 100644 index 000000000..0cd02a3e6 --- /dev/null +++ b/sc2/src/sc2code/libs/math/mthintrn.h @@ -0,0 +1,25 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MTHINTRN_H +#define _MTHINTRN_H + +#include "mathlib.h" + +#endif /* _MTHINTRN_H */ + diff --git a/sc2/src/sc2code/libs/math/random.c b/sc2/src/sc2code/libs/math/random.c new file mode 100644 index 000000000..e9fd9a632 --- /dev/null +++ b/sc2/src/sc2code/libs/math/random.c @@ -0,0 +1,100 @@ +///Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + /**************************************************************************** +* FILE: random.c +* DESC: a library of random number generators for general purpose use. +* +* References: +* "Random Number Generators: Good ones are hard to find" S.K.Park & K.W.Miller +* Communications of the ACM, Vol31 Number 10, October 1988, Pp 1192-1201 +* +* HISTORY: Created 1/23/1989 +* LAST CHANGED: +* +* Copyright (c) 1989, Robert Leyland and Fred Ford +****************************************************************************/ + +/* ----------------------------INCLUDES----------------------------------- */ +#include "mthintrn.h" /* get the externs for error checking */ + +/* ----------------------------DEFINES------------------------------------ */ +/* constants for licongruential random number generator from CACM article + referenced above */ +#define A 16807 /* a relatively prime number -- also M div Q */ +#define M 2147483647L /* 0xFFFFFFFF / 2 */ +#define Q 127773L /* M div A */ +#define R 2836 /* M mod A */ + +/* ----------------------------STATIC DATA-------------------------------- */ + +static DWORD seed = 12345L; /* random number seed */ + +/* ----------------------------CODE--------------------------------------- */ + +/***************************************************************************** +* FUNC: DWORD Random() +* +* DESC: random number generator +* +* NOTES: +* +* HISTORY: Created By Robert leyland +* +*****************************************************************************/ + +DWORD +Random (void) +{ + if ((seed = A * (seed % Q) - R * (seed / Q)) > M) + return (seed -= M); + else if (seed) + return (seed); + else + return (seed = 1L); +} + +/***************************************************************************** +* FUNC: DWORD SeedRandom(DWORD l) +* +* DESC: set the seed for the random number generator to parameter "l", and +* return the value of the previously active seed, to allow for multiple +* random number streams. +* +* NOTES: if the seed is not valid it will be coerced into a valid range +* +* HISTORY: Created By Robert leyland +* +*****************************************************************************/ + +DWORD +SeedRandom (DWORD new_seed) +{ + DWORD old_seed; + + /* coerce the seed to be in the range 1..M */ + if (new_seed == 0L) /* 0 becomes 1 */ + new_seed = 1; + else if (new_seed > M) /* and less than M */ + new_seed -= M; + + old_seed = seed; + seed = new_seed; + return (old_seed); +} + diff --git a/sc2/src/sc2code/libs/math/random.h b/sc2/src/sc2code/libs/math/random.h new file mode 100644 index 000000000..1a98eb808 --- /dev/null +++ b/sc2/src/sc2code/libs/math/random.h @@ -0,0 +1,54 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/**************************************************************************** +* FILE: random.h +* DESC: definitions and externs for random number generators +* +* HISTORY: Created 6/ 6/1989 +* LAST CHANGED: +* +* Copyright (c) 1989, Robert Leyland and Scott Anderson +****************************************************************************/ + +/* ----------------------------DEFINES------------------------------------ */ + +#ifndef SLOW_N_STUPID +#define TABLE_SIZE 1117 /* a "nice" prime number */ +#define _FAST_ fast_random() +#else /* FAST_N_UGLY */ +#define TABLE_SIZE ( (1 << 10) - 1 ) +#define _FAST_ ( random_table[ fast_index++ & TABLE_SIZE ] ) +#endif + + +#define FASTRAND(n) ( (int) ( (unsigned int)_FAST_ % (n) ) ) +#define SFASTRAND(n) ( (int)_FAST_ % (n) ) +#define AND_FASTRAND(n) ( (int)_FAST_ & (n) ) + +#define RAND(n) ( (int) ( (unsigned int)Random() % (n) ) ) +#define SRAND(n) ( (int)Random() % (n) ) +#define AND_RAND(n) ( (int)Random() & (n) ) + +#define INDEXED_RANDOM(x) (random_table[x]) + +/* ----------------------------GLOBALS/EXTERNS---------------------------- */ + +extern DWORD random_table[TABLE_SIZE]; +extern COUNT fast_index; /* fast random cycling index */ + diff --git a/sc2/src/sc2code/libs/math/sqrt.c b/sc2/src/sc2code/libs/math/sqrt.c new file mode 100644 index 000000000..1f02cac42 --- /dev/null +++ b/sc2/src/sc2code/libs/math/sqrt.c @@ -0,0 +1,97 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "mthintrn.h" + +COUNT +square_root (DWORD value) +{ + UWORD sig_word, mask; + COUNT result, shift; + + if ((sig_word = HIWORD (value)) > 0) + { + DWORD mask_squared, result_shift; + + for (mask = 1 << 15, shift = 31; + !(mask & sig_word); mask >>= 1, --shift) + ; + shift >>= 1; + mask = 1 << shift; + + result = mask; + mask_squared = result_shift = (DWORD)mask << shift; + value -= mask_squared; + while (mask >>= 1) + { + DWORD remainder; + + mask_squared >>= 1; + mask_squared >>= 1; + if ((remainder = result_shift + mask_squared) > value) + result_shift >>= 1; + else + { + value -= remainder; + + result_shift = (result_shift >> 1) + mask_squared; + + result |= mask; + } + } + + return (result); + } + else if ((sig_word = LOWORD (value)) > 0) + { + UWORD mask_squared, result_shift; + + for (mask = 1 << 15, shift = 15; + !(mask & sig_word); mask >>= 1, --shift) + ; + shift >>= 1; + mask = 1 << shift; + + result = mask; + mask_squared = result_shift = mask << shift; + sig_word -= mask_squared; + while (mask >>= 1) + { + UWORD remainder; + + mask_squared >>= 1; + mask_squared >>= 1; + if ((remainder = result_shift + mask_squared) > sig_word) + result_shift >>= 1; + else + { + sig_word -= remainder; + + result_shift = (result_shift >> 1) + mask_squared; + + result |= mask; + } + } + + return (result); + } + + return (0); +} + + diff --git a/sc2/src/sc2code/libs/mathlib.h b/sc2/src/sc2code/libs/mathlib.h new file mode 100644 index 000000000..3dd82af14 --- /dev/null +++ b/sc2/src/sc2code/libs/mathlib.h @@ -0,0 +1,30 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MATHLIB_H +#define _MATHLIB_H + +#include "compiler.h" + +extern DWORD SeedRandom (DWORD seed); +extern DWORD Random (void); +extern COUNT square_root (DWORD value); + +#endif /* _MATHLIB_H */ + + diff --git a/sc2/src/sc2code/libs/memlib.h b/sc2/src/sc2code/libs/memlib.h new file mode 100644 index 000000000..2fdd6b480 --- /dev/null +++ b/sc2/src/sc2code/libs/memlib.h @@ -0,0 +1,146 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MEMLIB_H +#define _MEMLIB_H + +#include "compiler.h" + +#define MEM_NULL 0L +#define NULL_HANDLE (MEM_HANDLE)MEM_NULL + +typedef signed long MEM_SIZE; +typedef MEM_SIZE *PMEM_SIZE; +typedef long MEM_OFFS; + +typedef SWORD MEM_HANDLE; +typedef MEM_HANDLE *PMEM_HANDLE; + +typedef BOOLEAN MEM_BOOL; +#define MEM_FAILURE FALSE +#define MEM_SUCCESS TRUE + +enum +{ + SAME_MEM_USAGE = 0, + MEM_SIMPLE, + MEM_COMPLEX +}; +typedef BYTE MEM_USAGE; + +#define NO_MEM_USAGE (MEM_USAGE)SAME_MEM_USAGE +#define DEFAULT_MEM_USAGE (MEM_USAGE)MEM_SIMPLE + +enum +{ + MEM_NO_ACCESS = 0, + MEM_READ_ONLY, + MEM_WRITE_ONLY, + MEM_READ_WRITE +}; +typedef BYTE MEM_ACCESS_MODE; + +enum +{ + MEM_SEEK_REL, + MEM_SEEK_ABS +}; +typedef BYTE MEM_SEEK_MODE; + +enum +{ + MEM_FORWARD, + MEM_BACKWARD +}; +typedef BYTE MEM_DIRECTION; + +typedef struct mem_size_request +{ + MEM_SIZE min_size, size, max_size; + MEM_DIRECTION direction; +} MEM_SIZE_REQUEST; + +typedef MEM_SIZE_REQUEST *PMEM_SIZE_REQUEST; +typedef SBYTE MEM_PRIORITY; +typedef UWORD MEM_FLAGS; + +#define DEFAULT_MEM_FLAGS (MEM_FLAGS)0 +#define SAME_MEM_FLAGS (MEM_FLAGS)0 +#define MEM_CONSTRAINED (MEM_FLAGS)(1 << 2) +#define MEM_DISCARDABLE (MEM_FLAGS)(1 << 3) +#define MEM_NODISCARD (MEM_FLAGS)(1 << 4) +#define MEM_DISCARDED (MEM_FLAGS)(1 << 5) +#define MEM_ACCESSED (MEM_FLAGS)(1 << 6) +#define MEM_STATIC (MEM_FLAGS)(1 << 7) +#define MEM_PRIMARY (MEM_FLAGS)(1 << 8) +#define MEM_ZEROINIT (MEM_FLAGS)(1 << 9) +#define MEM_GRAPHICS (MEM_FLAGS)(1 << 10) +#define MEM_SOUND (MEM_FLAGS)(1 << 11) + +#define DEFAULT_MEM_PRIORITY (MEM_PRIORITY)0 +#define SAME_MEM_PRIORITY (MEM_PRIORITY)0 +#define HIGHEST_MEM_PRIORITY (MEM_PRIORITY)1 +#define LOWEST_MEM_PRIORITY (MEM_PRIORITY)100 + +//Newer verion from w_memlib.c to follow... +/* +extern MEM_BOOL mem_init (MEM_SIZE core_size, PMEM_SIZE pmin_addressable, + PSTR disk_name);*/ + +extern MEM_BOOL mem_init (void); + +extern MEM_BOOL mem_uninit (void); + +extern MEM_HANDLE mem_allocate (MEM_SIZE size, MEM_FLAGS flags, + MEM_PRIORITY priority, MEM_USAGE usage); +#define mem_request(size) \ + mem_allocate((MEM_SIZE)(size), DEFAULT_MEM_FLAGS, DEFAULT_MEM_PRIORITY, DEFAULT_MEM_USAGE) +extern MEM_BOOL mem_release (MEM_HANDLE handle); +extern MEM_HANDLE mem_reallocate (MEM_HANDLE handle, MEM_SIZE size, + MEM_FLAGS flags, MEM_PRIORITY priority, MEM_USAGE usage); +#define mem_resize(h, size) \ + mem_reallocate(h, (MEM_SIZE)size, SAME_MEM_FLAGS, SAME_MEM_PRIORITY, SAME_MEM_USAGE) +extern MEM_HANDLE mem_static (PVOID pVoid, MEM_SIZE size, MEM_USAGE + usage); +extern MEM_HANDLE mem_dup (MEM_HANDLE handle, MEM_USAGE usage); + +extern PVOID mem_simple_access (MEM_HANDLE handle); +extern MEM_BOOL mem_simple_unaccess (MEM_HANDLE handle); + +#define mem_lock mem_simple_access +#define mem_unlock mem_simple_unaccess + +extern PVOID mem_complex_access (MEM_HANDLE handle, MEM_SIZE pos, + PMEM_SIZE_REQUEST pSizeRequest, MEM_ACCESS_MODE access_mode); +extern MEM_BOOL mem_complex_unaccess (MEM_HANDLE handle); +extern PVOID mem_complex_seek (MEM_HANDLE handle, MEM_OFFS offset, + PMEM_SIZE_REQUEST pSizeRequest, MEM_SEEK_MODE seek_mode); + +extern MEM_SIZE mem_get_memavailable (MEM_SIZE size, MEM_PRIORITY + priority); + +extern MEM_SIZE mem_get_size (MEM_HANDLE handle); +extern MEM_USAGE mem_get_usage (MEM_HANDLE handle); +extern MEM_BOOL mem_set_flags (MEM_HANDLE handle, MEM_FLAGS mem_flags); +extern MEM_FLAGS mem_get_flags (MEM_HANDLE handle); +extern MEM_BOOL mem_set_priority (MEM_HANDLE handle, MEM_PRIORITY + mem_priority); +extern MEM_PRIORITY mem_get_priority (MEM_HANDLE handle); + +#endif /* _MEMLIB_H */ + diff --git a/sc2/src/sc2code/libs/memory/Makefile.am b/sc2/src/sc2code/libs/memory/Makefile.am new file mode 100644 index 000000000..b786c6bdb --- /dev/null +++ b/sc2/src/sc2code/libs/memory/Makefile.am @@ -0,0 +1,13 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libmemory.la +libmemory_la_SOURCES = w_memlib.c + diff --git a/sc2/src/sc2code/libs/memory/w_memlib.c b/sc2/src/sc2code/libs/memory/w_memlib.c new file mode 100644 index 000000000..3e38fc12f --- /dev/null +++ b/sc2/src/sc2code/libs/memory/w_memlib.c @@ -0,0 +1,653 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +//#include "3d.h" +//#include "tool.h" +//#include "utils.h" +//#include "pcwin.h" +#include "compiler.h" +#include "timlib.h" + +#define GetToolFrame() 1 + +//#define MEM_DEBUG + +#ifdef MEM_DEBUG +#include +#endif + +#define LEAK_DEBUG + +#ifdef LEAK_DEBUG +BOOLEAN leak_debug; +int leak_idx = -1; +int leak_size = -1; +#endif +void *_MemorySem; + +#define MAX_EXTENTS 100000 + +/* Keep track of memory allocations. */ + +typedef struct _szMemoryNode { + void *memory; + struct _szMemoryNode *next; + MEM_HANDLE handle; + MEM_SIZE size; + int refcount; +} szMemoryNode; + +static szMemoryNode extents[MAX_EXTENTS]; +static szMemoryNode *freeListHead = NULL; + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** Message(format, parms) +** +** DESCRIPTION +** Presents a windows message box to the user and echoes the +** message with printf(). +** +** INPUT +** As for printf(). +** +** OUTPUT +** +** HISTORY +** 10-Jul-96:AKL Creation. +** +** ASSUMPTIONS +**END*/ + +static void Message(char *fmt, ...) +{ + va_list ap; + char buffer[256]; + + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + #ifndef FINAL + printf("%s\n", buffer); + //fflush(stdout); + #endif + +#if 0 + if (GetToolFrame ()) + { + ShowWindow(GetToolFrame (),SW_HIDE); + } + MessageBox(NULL, buffer, "Message From Programmer Dude", MB_OK); + + if (GetToolFrame ()) + { + ShowWindow(GetToolFrame (),SW_NORMAL); + } +#endif +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** ok = MessageWithRetry(format, parms) +** +** DESCRIPTION +** Presents a windows message box to the user and echoes the +** message with printf(). The users gets to choose OK or CANCEL. +** Returns TRUE if the user says OK. +** +** INPUT +** As for printf(). +** +** OUTPUT +** int ok = TRUE for OK, FALSE for CANCEL. +** +** HISTORY +** 6-Nov-96:AKL Creation. +** +** ASSUMPTIONS +**END*/ + +static int MessageWithRetry(char *fmt, ...) +{ + va_list ap; + char buffer[256]; +#if 0 + int ret; +#endif + + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + #ifndef FINAL + printf("%s\n", buffer); + //fflush(stdout); + #endif + +#if 0 + if (GetToolFrame ()) + { + ShowWindow(GetToolFrame (),SW_HIDE); + } + ret = MessageBox(NULL, buffer, "Message From Programmer Dude", + MB_OKCANCEL); + + /* Return value: + 0 => not enough memory for message. Abort game. + IDCANCEL => user selected CANCEL. + IDOK => user selected OK. + */ + + if (GetToolFrame ()) + { + ShowWindow(GetToolFrame (),SW_NORMAL); + } + + if ( ret == IDOK ) + return TRUE; + else +#endif + return FALSE; +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** CheckMemory() +** +** DESCRIPTION +** Checks integrity of memory allocation: diagnostic only. +** Either aborts or spits messages to stdout if there's a +** problem. +** +** INPUT +** +** OUTPUT +** +** HISTORY +** 04-Sept-96:AKL Creation. +** +** ASSUMPTIONS +** +**END*/ + +#ifdef MEM_DEBUG + +void CheckMemory(void) +{ + + // Send all reports to STDOUT + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); + + _CrtCheckMemory(); + fflush(stdout); +} +#endif + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** mem = MallocWithRetry(coreSize, diagnostic) +** +** DESCRIPTION +** Mallocs the required memory. If the malloc fails, the user is prompted +** to shutdown other applications and retry, or kill the game. +** If the game is killed, the diagnostic string is printed. +** +** INPUT +** int coreSize = How much memory to malloc (in bytes). +** char *diagnostic = String identifying the caller. +** +** OUTPUT +** void *mem = Ptr to memory, or NULL if user wants to kill us. +** +** HISTORY +** 06-Nov-96:AKL Creation. +** +** ASSUMPTIONS +** +**END*/ + +void * +MallocWithRetry(int bytes, char *diagStr) +{ + while (1) + { + void *ptr; + + ptr = malloc (bytes); + if (ptr) + return (ptr); +#ifndef FINAL +printf("Malloc failed for %s. #Bytes %d.\n", diagStr, bytes); +//fflush(stdout); +#endif + /* The user gets a chance to close other applications and try again. */ + + if (!MessageWithRetry ("I'm out of memory! " + "Please close other applications and click OK to try again")) + { + if (MessageWithRetry ("Really OK to stop tfbtool?")) + { + /* User says "die". */ + printf ("Killed by the user (%s).\n", diagStr); + exit (0); + } + } + } +} + +MEM_HANDLE +mem_allocate (MEM_SIZE coreSize, MEM_FLAGS flags, MEM_PRIORITY priority, + MEM_USAGE usage) +{ + szMemoryNode *node; + + SetSemaphore (&_MemorySem); + +#ifdef MEM_DEBUG + CheckMemory(); +#endif + + if ((node = freeListHead) == NULL) + Message ("mem_allocate: out of extents."); + else if ((node->memory = MallocWithRetry (coreSize, "mem_allocate:")) == 0 + && coreSize) + Message ("mem_allocate: couldn't allocate %u bytes.", coreSize); + else + { + freeListHead = node->next; + + node->size = coreSize; + node->handle = node - extents + 1; + node->refcount = 0; + if (flags & MEM_ZEROINIT) + memset (node->memory, 0, node->size); +#ifdef LEAK_DEBUG +if (leak_debug) + printf ("alloc %d: %08x, %lu\n", (int) node->handle, (int) node->memory, + node->size); +if (node->handle == leak_idx && node->size == leak_size) + node = node; +if (node->size == leak_size) + node = node; +#endif /* LEAK_DEBUG */ + + ClearSemaphore (&_MemorySem); + return (node->handle); + } + + ClearSemaphore (&_MemorySem); + (void) priority; /* Satisfying compiler (unused parameter) */ + (void) usage; /* Satisfying compiler (unused parameter) */ + return (0); +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** size = mem_get_size(h) +** +** DESCRIPTION +** Returns the number of bytes in the given memory allocation. +** +** INPUT +** int h = Handle to memory allocation. +** +** OUTPUT +** int size = Number of bytes in allocation or zero on error. +** +** HISTORY +** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\DATAINFO.C. +** +** ASSUMPTIONS +** +**END*/ + +MEM_SIZE +mem_get_size (MEM_HANDLE h) +{ + SetSemaphore (&_MemorySem); + if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) + { + ClearSemaphore (&_MemorySem); + return ((int)extents[h - 1].size); + } + ClearSemaphore (&_MemorySem); + + return (0); +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** done = mem_init(coreSize, pma, diskName) +** +** DESCRIPTION +** Initialize data that tracks allocation extents. +** +** INPUT +** int coreSize = IGNORED! +** int * pma = IGNORED! +** PSTR diskName = IGNORED! +** +** OUTPUT +** int done = TRUE. +** +** HISTORY +** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\INIT.C. +** +** ASSUMPTIONS +** +**END*/ + +MEM_BOOL +mem_init (void) +{ + int i; + + SetSemaphore (&_MemorySem); + + freeListHead = &extents[0]; + for (i=0; i= MAX_EXTENTS) + printf("LEAK: attempt to release invalid extent %d\n", h); + else if (extents[h].handle == -1) + printf("LEAK: attempt to release unallocated extent %d\n",h); + else if (extents[h].refcount == 0) + { +#ifdef LEAK_DEBUG +if (leak_debug) printf ("free %d: %08x\n", + extents[h].handle, (unsigned int) extents[h].memory); +#endif + if (extents[h].memory) + { + free (extents[h].memory); + extents[h].memory = 0; + } + extents[h].handle = -1; + extents[h].next = freeListHead; + freeListHead = &extents[h]; + ClearSemaphore (&_MemorySem); + return TRUE; + } + + ClearSemaphore (&_MemorySem); + return FALSE; +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** memp = mem_simple_access(h) +** +** DESCRIPTION +** Obtains access to the given memory allocation. For now, we simply +** return the handle itself, because it is the actual address! +** +** INPUT +** int h = Handle to memory to be accessed. +** +** OUTPUT +** void * memp = Ptr to memory. +** +** HISTORY +** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\SIMPLE.C. +** +** ASSUMPTIONS +** +**END*/ + +void * +mem_simple_access(MEM_HANDLE h) +{ + SetSemaphore (&_MemorySem); + + if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) + { + ++extents[h - 1].refcount; + ClearSemaphore (&_MemorySem); + return (extents[h - 1].memory); + } + + ClearSemaphore (&_MemorySem); + return (0); +} + +/*****************************************************************************/ +/*FUNCTION +** +** SYNOPSIS +** done = mem_simple_unaccess(h) +** +** DESCRIPTION +** Release access to the given memory allocation. For now, we simply +** do nothing! +** +** INPUT +** int h = Handle to memory to be unaccessed. +** +** OUTPUT +** int done = TRUE. +** +** HISTORY +** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\SIMPLE.C. +** +** ASSUMPTIONS +** +**END*/ + +MEM_BOOL +mem_simple_unaccess(MEM_HANDLE h) +{ + SetSemaphore (&_MemorySem); + if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) + { + if (extents[h - 1].refcount) + --extents[h - 1].refcount; + ClearSemaphore (&_MemorySem); + return (1); + } + + ClearSemaphore (&_MemorySem); + return (0); +} + +static void * +_alloc_mem (int size) +{ + void *p; + int h; + + h = mem_allocate (size + sizeof (int),0,0,0); + p = (void *)mem_simple_access (h); + if (p) + { + *(int *)p = h; + p = (int *)p + 1; + } + + return (p); +} + +void * +HMalloc (int size) +{ + if (size == 0) return (0); + + return (_alloc_mem (size)); +} + +void +HFree (void *p) +{ + if (p) + { + int h; + + h = *(int *)((int *)p - 1); + mem_simple_unaccess (h); + mem_release (h); + } +} + +void * +HCalloc (int size) +{ + void *p; + + p = HMalloc (size); + if (p) + memset (p, 0, size); + + return (p); +} + +void * +HRealloc (void *p, int size) +{ + void *np; + int osize; + + if ((np = _alloc_mem (size)) && p) + { + osize = mem_get_size (*(int *)((int *)p - 1)) - sizeof (int); + if (size > osize) + size = osize; + memcpy (np, p, size); + HFree (p); + } + + return (np); +} diff --git a/sc2/src/sc2code/libs/reslib.h b/sc2/src/sc2code/libs/reslib.h new file mode 100644 index 000000000..10f5a0a95 --- /dev/null +++ b/sc2/src/sc2code/libs/reslib.h @@ -0,0 +1,121 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _RESLIB_H +#define _RESLIB_H + +#include +#include "memlib.h" + +typedef DWORD RESOURCE; +typedef RESOURCE *PRESOURCE; + +typedef BYTE RES_TYPE; +typedef COUNT RES_INSTANCE; +typedef COUNT RES_PACKAGE; + +#define TYPE_BITS 8 +#define INSTANCE_BITS 13 +#define PACKAGE_BITS 11 + +#define MAX_TYPES ((1 << TYPE_BITS) - 1) /* zero is invalid */ +#define MAX_INSTANCES (1 << INSTANCE_BITS) +#define MAX_PACKAGES ((1 << PACKAGE_BITS) - 1) /* zero is invalid */ + +#define GET_TYPE(res) \ + ((RES_TYPE)(res) & (RES_TYPE)((1 << TYPE_BITS) - 1)) +#define GET_INSTANCE(res) \ + ((RES_INSTANCE)((res) >> TYPE_BITS) & ((1 << INSTANCE_BITS) - 1)) +#define GET_PACKAGE(res) \ + ((RES_PACKAGE)((res) >> (TYPE_BITS + INSTANCE_BITS)) & \ + ((1 << PACKAGE_BITS) - 1)) +#define MAKE_RESOURCE(p,t,i) \ + (((RESOURCE)(p) << (TYPE_BITS + INSTANCE_BITS)) | \ + ((RESOURCE)(i) << TYPE_BITS) | \ + ((RESOURCE)(t))) + +extern FILE *OpenResFile (PVOID filename, char *mode); +extern int ReadResFile (PVOID lpBuf, COUNT size, COUNT count, FILE *fp); +extern int WriteResFile (PVOID lpBuf, COUNT size, COUNT count, FILE + *fp); +extern int GetResFileChar (FILE *fp); +extern int PutResFileChar (char ch, FILE *fp); +extern long SeekResFile (FILE *fp, long offset, int whence); +extern long TellResFile (FILE *fp); +extern long LengthResFile (FILE *fp); +extern BOOLEAN CloseResFile (FILE *fp); +extern BOOLEAN DeleteResFile (PVOID filename); + +extern MEM_HANDLE InitResourceSystem (PVOID resfile, COUNT resindex_type, + BOOLEAN (*FileErrorFunc) (PVOID filename)); +extern BOOLEAN UninitResourceSystem (void); +extern BOOLEAN InstallResTypeVectors ( + COUNT res_type, + MEM_HANDLE (*load_func) (FILE *fp, DWORD len), + BOOLEAN (*free_func) (MEM_HANDLE handle)); +extern MEM_HANDLE GetResource (RESOURCE res); +extern MEM_HANDLE DetachResource (RESOURCE res); +extern BOOLEAN FreeResource (RESOURCE res); +extern COUNT CountResourceTypes (void); + +extern MEM_HANDLE OpenResourceIndexFile (PVOID + resfile); +extern MEM_HANDLE OpenResourceIndexInstance (DWORD + res); +extern MEM_HANDLE SetResourceIndex (MEM_HANDLE hRH); +extern BOOLEAN CloseResourceIndex (MEM_HANDLE hRH); + +extern MEM_HANDLE GetResourceData (FILE *fp, DWORD + length, MEM_FLAGS mem_flags); + +#define RESOURCE_PRIORITY DEFAULT_MEM_PRIORITY +#define RESOURCE_DATAPTR PBYTE + +#define AllocResourceData(s,mf) \ + mem_allocate ((MEM_SIZE)(s)+(PARAGRAPH_SIZE-1), \ + (mf), RESOURCE_PRIORITY, MEM_SIMPLE) +#define LockResourceData(h,lp) \ +do \ +{ \ + *(lp) = mem_lock ((MEM_HANDLE)(h)); \ +} while (0) +#define UnlockResourceData mem_unlock +#define FreeResourceData mem_release + +#include "strlib.h" + +typedef STRING_TABLE DIRENTRY_REF; +typedef STRING DIRENTRY; +typedef STRINGPTR DIRENTRYPTR; + +extern DIRENTRY_REF LoadDirEntryTable (PSTR pattern, + PCOUNT pnum_entries); +#define CaptureDirEntryTable CaptureStringTable +#define ReleaseDirEntryTable ReleaseStringTable +#define DestroyDirEntryTable DestroyStringTable +#define GetDirEntryTableRef GetStringTable +#define GetDirEntryTableCount GetStringTableCount +#define GetDirEntryTableIndex GetStringTableIndex +#define SetAbsDirEntryTableIndex SetAbsStringTableIndex +#define SetRelDirEntryTableIndex SetRelStringTableIndex +#define GetDirEntryLength GetStringLength +#define GetDirEntryAddress GetStringAddress +#define GetDirEntryContents GetStringContents + +#endif /* _RESLIB_H */ + diff --git a/sc2/src/sc2code/libs/resource/Makefile.am b/sc2/src/sc2code/libs/resource/Makefile.am new file mode 100644 index 000000000..4c0f149bf --- /dev/null +++ b/sc2/src/sc2code/libs/resource/Makefile.am @@ -0,0 +1,15 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs \ + @SDL_CFLAGS@ @SMPEG_CFLAGS@ + +noinst_LTLIBRARIES = libresource.la +libresource_la_SOURCES = getres.c loadres.c resdata.c resinit.c direct.c filecntl.c +noinst_HEADERS = index.h resintrn.h + diff --git a/sc2/src/sc2code/libs/resource/direct.c b/sc2/src/sc2code/libs/resource/direct.c new file mode 100644 index 000000000..759cad036 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/direct.c @@ -0,0 +1,295 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* This file contains two versions of LoadDirEntryTable; one for Windows, and + * one for other systems (POSIX). + * It might be better to split this up in seperate files eventually. + * - SvdB + */ +#ifdef WIN32 +#include +#include +#include "libs/strings/strintrn.h" + +DIRENTRY_REF +LoadDirEntryTable (PSTR pattern, PCOUNT pnum_entries) +{ + COUNT num_entries, length; + STRING_TABLE StringTable; + STRING_TABLEPTR lpST; + PDWORD lpLastOffs; + + num_entries = 0; + StringTable = 0; + do + { + COUNT slen; + long handle; + struct _finddata_t f; + + if (num_entries == 0) + length = 0; + else + { + slen = sizeof (STRING_TABLE_DESC) + + (num_entries * sizeof (DWORD)); + StringTable = AllocResourceData (slen + length, 0); + LockStringTable (StringTable, &lpST); + if (lpST == 0) + { + FreeStringTable (StringTable); + StringTable = 0; + + break; + } + + lpST->StringCount = num_entries; + lpLastOffs = &lpST->StringOffsets[0]; + *lpLastOffs = slen; + + num_entries = 0; + length = slen; + } + + handle = _findfirst (pattern, &f); + if (handle != -1) + { + do + { + if (f.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM)) + continue; + + slen = strlen (f.name) + 1; + length += slen; + + if ((MEM_HANDLE)StringTable) + { + PSTR lpStr; + PDWORD lpLo, lpHi; + + lpLo = &lpST->StringOffsets[0]; + lpHi = lpLastOffs - 1; + while (lpLo <= lpHi) + { + char c1, c2; + PSTR pStr; + COUNT LocLen; + PDWORD lpMid; + + lpMid = lpLo + ((lpHi - lpLo) >> 1); + + LocLen = lpMid[1] - lpMid[0]; + if (LocLen > slen) + LocLen = slen; + + lpStr = (PSTR)lpST + lpMid[0]; + pStr = f.name; + while (LocLen-- + && (c1 = toupper (*lpStr++)) + == (c2 = toupper (*pStr++))) + ; + + if (c1 <= c2) + lpLo = lpMid + 1; + else + lpHi = lpMid - 1; + } + + lpStr = (PSTR)lpST + lpLo[0]; + memmove (lpStr + slen, lpStr, lpLastOffs[0] - lpLo[0]); + strcpy (lpStr, f.name); + + for (lpHi = lpLastOffs++; lpHi >= lpLo; --lpHi) + lpHi[1] = lpHi[0] + slen; + } + + ++num_entries; + } while (_findnext (handle, &f) == 0); + _findclose (handle); + } + } while (num_entries && (MEM_HANDLE)StringTable == 0); + + if ((MEM_HANDLE)StringTable == 0) + *pnum_entries = 0; + else + { + *pnum_entries = num_entries; + + UnlockStringTable (StringTable); + } + + return ((DIRENTRY_REF)StringTable); +} + +#else /* ! defined(WIN32) */ + +#include "libs/strings/strintrn.h" +#include +#include +#include +#include +#include +#include + +DIRENTRY_REF +LoadDirEntryTable (PSTR pattern, PCOUNT pnum_entries) +{ + COUNT num_entries, length; + STRING_TABLE StringTable; + STRING_TABLEPTR lpST; + PDWORD lpLastOffs; + PSTR slash; // Pointer inside pattern to the last / + SBYTE path[PATH_MAX + 1]; // buffer for a filename with path + PSTR file; // Pointer inside path to the filename + size_t pathlen; // length of path, excluding last / and filename + + slash = (PSTR) strrchr ((const char *) pattern, '/'); + if (slash == NULL) + { + pathlen = 1; + path[0] = '.'; + } + else + { + pathlen = slash - pattern; + memcpy (path, pattern, pathlen); + pattern = slash + 1; + } + file = path + pathlen + 1; + + num_entries = 0; + StringTable = 0; + do + { + COUNT slen; + DIR *handle; + + if (num_entries == 0) + length = 0; + else + { + slen = sizeof (STRING_TABLE_DESC) + + (num_entries * sizeof (DWORD)); + StringTable = AllocResourceData (slen + length, 0); + LockStringTable (StringTable, &lpST); + if (lpST == 0) + { + FreeStringTable (StringTable); + StringTable = 0; + + break; + } + + lpST->StringCount = num_entries; + lpLastOffs = &lpST->StringOffsets[0]; + *lpLastOffs = slen; + + num_entries = 0; + length = slen; + } + + + path[pathlen] = '\0'; // strip any file part + handle = opendir((const char *) path); + if (handle != NULL) + { + path[pathlen] = '/'; + // change the 0 char to a slash; a filename will be + // attached here. + while (1) + { + struct dirent *de; + struct stat sb; + + de = readdir(handle); + if (de == NULL) + break; + if (de->d_name[0] == '.') + continue; + strcpy (file, de->d_name); + // attach the filename to path + if (stat(path, &sb) == -1) + continue; + if (!S_ISREG(sb.st_mode)) + continue; + if (fnmatch(pattern, de->d_name, 0) != 0) + continue; + + slen = strlen (de->d_name) + 1; + length += slen; + + if ((MEM_HANDLE)StringTable) + { + PSTR lpStr; + PDWORD lpLo, lpHi; + + lpLo = &lpST->StringOffsets[0]; + lpHi = lpLastOffs - 1; + while (lpLo <= lpHi) + { + char c1, c2; + PSTR pStr; + COUNT LocLen; + PDWORD lpMid; + + lpMid = lpLo + ((lpHi - lpLo) >> 1); + + LocLen = lpMid[1] - lpMid[0]; + if (LocLen > slen) + LocLen = slen; + + lpStr = (PSTR)lpST + lpMid[0]; + pStr = de->d_name; + while (LocLen-- + && (c1 = toupper (*lpStr++)) + == (c2 = toupper (*pStr++))) + ; + + if (c1 <= c2) + lpLo = lpMid + 1; + else + lpHi = lpMid - 1; + } + + lpStr = (PSTR)lpST + lpLo[0]; + memmove (lpStr + slen, lpStr, lpLastOffs[0] - lpLo[0]); + strcpy (lpStr, de->d_name); + + for (lpHi = lpLastOffs++; lpHi >= lpLo; --lpHi) + lpHi[1] = lpHi[0] + slen; + } + + ++num_entries; + } + closedir(handle); + } + } while (num_entries && (MEM_HANDLE)StringTable == 0); + + if ((MEM_HANDLE)StringTable == 0) + *pnum_entries = 0; + else + { + *pnum_entries = num_entries; + + UnlockStringTable (StringTable); + } + + return ((DIRENTRY_REF)StringTable); +} + +#endif diff --git a/sc2/src/sc2code/libs/resource/filecntl.c b/sc2/src/sc2code/libs/resource/filecntl.c new file mode 100644 index 000000000..d8337958e --- /dev/null +++ b/sc2/src/sc2code/libs/resource/filecntl.c @@ -0,0 +1,142 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef WIN32 +#include +#include +#endif +#include +#include +#include +#include +#include "resintrn.h" + +FILE +*OpenResFile (PVOID filename, char *mode) +{ + FILE *fp; + struct stat sb; + +#ifdef WIN32 + if (stat (filename, &sb) == 0 && (sb.st_mode & _S_IFDIR)) +#else + if (stat (filename, &sb) == 0 && S_ISDIR(sb.st_mode)) +#endif + return ((FILE *) ~0); + + fp = fopen (filename, mode); + + return (fp); +} + +BOOLEAN +CloseResFile (FILE *fp) +{ + if (fp) + { + if (fp != (FILE *)~0) + fclose (fp); + return (TRUE); + } + + return (FALSE); +} + +BOOLEAN +DeleteResFile (PVOID filename) +{ + return (remove (filename) == 0); +} + +int +ReadResFile (PVOID lpBuf, COUNT size, COUNT count, FILE *fp) +{ + int retval; + + retval = fread (lpBuf, size, count, fp); + + return (retval); +} + +int +WriteResFile (PVOID lpBuf, COUNT size, COUNT count, FILE *fp) +{ + int retval; + + retval = fwrite (lpBuf, size, count, fp); + + return (retval); +} + +int +GetResFileChar (FILE *fp) +{ + int retval; + + retval = getc (fp); + + return (retval); +} + +int +PutResFileChar (char ch, FILE *fp) +{ + int retval; + + retval = putc (ch, fp); + + return (retval); +} + +long +SeekResFile (FILE *fp, long offset, int whence) +{ + long retval; + + retval = fseek (fp, offset, whence); + + return (retval); +} + +long +TellResFile (FILE *fp) +{ + long retval; + + retval = ftell (fp); + + return (retval); +} + +long +LengthResFile (FILE *fp) +{ +if (fp == (FILE *)~0) + return (1); +#ifdef WIN32 + return filelength (fileno (fp)); +#else + { + struct stat sb; + if (fstat(fileno(fp), &sb) == -1) + return 1; + return sb.st_size; + } +#endif +} + diff --git a/sc2/src/sc2code/libs/resource/getres.c b/sc2/src/sc2code/libs/resource/getres.c new file mode 100644 index 000000000..f446d4266 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/getres.c @@ -0,0 +1,502 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "resintrn.h" +#include "SDL_wrapper.h" + +char *_cur_resfile_name; + +static BOOLEAN +ValidResource (INDEX_HEADERPTR ResHeaderPtr, RESOURCE res) +{ + if (ResHeaderPtr != NULL_PTR) + { + RES_PACKAGE res_package; + + res_package = GET_PACKAGE (res); + if (ValidResPackage (ResHeaderPtr, res_package)) + { + RES_TYPE res_type; + + res_type = GET_TYPE (res); + if (ValidResType (ResHeaderPtr, res_type)) + { + COUNT res_instance; + + res_instance = GET_INSTANCE (res); + if (GetInstanceCount (ResHeaderPtr, res_type) > res_instance) + return (TRUE); + } + } + } + + return (FALSE); +} + +static void +dword_convert (PDWORD dword_array, COUNT num_dwords) +{ + PBYTE p = (PBYTE)dword_array; + + do + { + *dword_array++ = MAKE_DWORD ( + MAKE_WORD (p[0], p[1]), + MAKE_WORD (p[2], p[3]) + ); + p += 4; + } while (--num_dwords); +} + +#define PATHLEN 256 + +void +get_resource_filename (INDEX_HEADERPTR ResHeaderPtr, char *pbuf, COUNT + file_index) +{ + UWORD path_offs; + long file_offs; + FILE_INFO file_info; + + file_offs = (long)ResHeaderPtr->file_list_offs + + (long)file_index * FILE_LIST_SIZE; + if (ResHeaderPtr->res_flags & IS_PACKAGED) + memcpy ((PSTR)&file_info, + (PSTR)ResHeaderPtr + (COUNT)file_offs, FILE_LIST_SIZE); + else + { + SeekResFile (ResHeaderPtr->res_fp, file_offs, SEEK_SET); + ReadResFile (&file_info, FILE_LIST_SIZE, 1, ResHeaderPtr->res_fp); + } + + path_offs = MAKE_WORD (file_info.path_offset[0], file_info.path_offset[1]); + if (path_offs != NO_PATH) + { + file_offs = (long)ResHeaderPtr->path_list_offs + path_offs; + if (ResHeaderPtr->res_flags & IS_PACKAGED) + memcpy (pbuf, + (PSTR)ResHeaderPtr + (COUNT)file_offs, PATHLEN); + else + { + SeekResFile (ResHeaderPtr->res_fp, file_offs, SEEK_SET); + ReadResFile (pbuf, PATHLEN, 1, ResHeaderPtr->res_fp); + } + pbuf += strlen (pbuf); + + *pbuf++ = '/'; + } + + { + COUNT i; + char *pstr; + + pstr = file_info.filename; + for (i = 0; i < FILE_NAME_SIZE; ++i) + { + if ((*pbuf++ = *pstr++) == '\0') + { + --pbuf; + if (i == 0) + { +#ifndef PACKAGING + strcpy (pbuf, ResHeaderPtr->index_file_name); +#endif /* PACKAGING */ + return; + } + + break; + } + } + *pbuf++ = '.'; + + pstr = file_info.extension; + for (i = 0; i < EXTENSION_SIZE && (*pbuf++ = *pstr++); ++i) + ; + *pbuf++ = '\0'; + } +} + +DWORD +get_packmem_offs (INDEX_HEADERPTR ResHeaderPtr, RES_PACKAGE res_package) +{ + DWORD file_offs; + RES_PACKAGE package; + + file_offs = ResHeaderPtr->packmem_list_offs; + for (package = 1; package < res_package; ++package) + { + file_offs += (DWORD)PACKMEM_LIST_SIZE + * GET_TYPE (ResHeaderPtr->PackageList[package - 1].packmem_info) + + (DWORD)INSTANCE_LIST_SIZE + * GET_INSTANCE (ResHeaderPtr->PackageList[package - 1].packmem_info); + } + + return (file_offs); +} + +//#define DEBUG + +MEM_HANDLE +load_package (INDEX_HEADERPTR ResHeaderPtr, RES_PACKAGE res_package) +{ + BOOLEAN DanglingOpen; + MEM_HANDLE hList; + FILE *fp; + COUNT t, num_types, num_instances; + DWORD file_offs, data_len; + RES_HANDLE_LISTPTR ResourceHandleListPtr; + ENCODEPTR TypeEncodePtr; + DATAPTR DataPtr; +#ifdef PACKAGING + extern +#endif /* PACKAGING */ + char file_buf[PATHLEN]; + + num_types = CountPackageTypes (ResHeaderPtr, res_package); + num_instances = CountPackageInstances (ResHeaderPtr, res_package); + + if ((hList = AllocResourceHandleList ( + num_types, num_instances + )) == NULL_HANDLE) +{ +#ifdef DEBUG +printf ("Unable to allocate resource handle list <%d, %d>\n", num_types, num_instances); +#endif /* DEBUG */ + return (NULL_HANDLE); +} + + LockResourceHandleList (ResHeaderPtr, hList, res_package, + &ResourceHandleListPtr, &TypeEncodePtr, &DataPtr); + ResourceHandleListPtr->flags_and_data_loc = + ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc; + + DanglingOpen = FALSE; + file_offs = get_packmem_offs (ResHeaderPtr, res_package); + if (!(ResHeaderPtr->res_flags & IS_PACKAGED)) + { + SeekResFile (ResHeaderPtr->res_fp, (long)file_offs, SEEK_SET); + if (ReadResFile ((PSTR)TypeEncodePtr, + (PACKMEM_LIST_SIZE * num_types) + + (INSTANCE_LIST_SIZE * num_instances), + 1, ResHeaderPtr->res_fp) != 1) + { + UnlockResourceHandleList (hList); + FreeResourceHandleList (hList); + + return (NULL_HANDLE); + } + dword_convert (TypeEncodePtr, num_types); + } + else + { + COUNT file_index; + + memcpy (TypeEncodePtr, + (PSTR)((PSTR)ResHeaderPtr + (COUNT)file_offs), + (PACKMEM_LIST_SIZE * num_types) + + (INSTANCE_LIST_SIZE * num_instances)); + dword_convert (TypeEncodePtr, num_types); + + file_index = GET_PACKAGE ( + ResHeaderPtr->PackageList[res_package - 1].packmem_info + ); + get_resource_filename (ResHeaderPtr, file_buf, file_index); + if (!stricmp (ResHeaderPtr->index_file_name, file_buf)) + fp = ResHeaderPtr->res_fp; + else + { + fp = OpenResFile (file_buf, "rb"); + if (fp) + DanglingOpen = TRUE; + } + + if (fp == NULL) + num_types = 0; + else + { + file_offs = ResourceHandleListPtr->flags_and_data_loc & ~0xFF000000; + if (file_offs) + SeekResFile (fp, (long)file_offs, SEEK_SET); + else if (num_types == 1 && GET_PACKAGE (*TypeEncodePtr) == 1) + { /* if only one thing in this package which is only + * package in its file, let file length be determined + * by the current length of package rather than the + * length at package time. + */ + RES_PACKAGE p; + + for (p = 1; p <= ResHeaderPtr->num_packages; ++p) + { + if (p != res_package + && GET_PACKAGE ( + ResHeaderPtr->PackageList[p - 1].packmem_info) + == file_index) + break; + } + + if (p > ResHeaderPtr->num_packages) + { + data_len = (LengthResFile (fp) + 3) >> 2; + DataPtr[0] = LOBYTE (data_len); + DataPtr[1] = HIBYTE (data_len); + } + } + } + } + + for (t = 0; t < num_types; ++t) + { + RES_TYPE type; + + type = GET_TYPE (*TypeEncodePtr); + num_instances = GET_PACKAGE (*TypeEncodePtr); + while (num_instances--) + { + MEM_HANDLE hData; + + _cur_resfile_name = file_buf; + + hData = NULL_HANDLE; + data_len = MAKE_WORD (DataPtr[0], DataPtr[1]); + if (ResHeaderPtr->res_flags & IS_PACKAGED) + { + if ((data_len <<= 2) == 0) + ; + else if (SeekResFile (fp, (long)file_offs, SEEK_SET)) + ; + else + { + hData = DoLoad (ResHeaderPtr, type, fp, data_len); + if (hData && IsIndexType (ResHeaderPtr, type)) + DanglingOpen = FALSE; +#ifdef DEBUG +if (hData == 0) +printf ("fp = 0x%08lx(%d), type = %u, file_offs = %lu, len = %lu\n", fp, DanglingOpen, type, file_offs, data_len); +#endif /* DEBUG */ + } + file_offs += data_len; + } + else + { + get_resource_filename (ResHeaderPtr, file_buf, (COUNT)data_len); + + fp = OpenResFile (file_buf, "rb"); + if (fp == NULL) +#if 1 // def DEBUG +printf ("Can't open '%s'\n", file_buf) +#endif /* DEBUG */ + ; + else + { + data_len = LengthResFile (fp); +#ifndef PACKAGING +printf ("\t'%s' -- %lu bytes\n", file_buf, data_len); +#endif /* PACKAGING */ + if (data_len == 0) + hData = NULL_HANDLE; + else + hData = DoLoad (ResHeaderPtr, type, fp, data_len); + if (hData == 0 || !IsIndexType (ResHeaderPtr, type)) + CloseResFile (fp); + } + } +#ifdef DEBUG +if (hData == 0) printf ("Can't create data for '%s' <%lu>\n", file_buf, data_len); +#endif /* DEBUG */ + + DataPtr[0] = LOBYTE (hData); + DataPtr[1] = HIBYTE (hData); + DataPtr += 2; + + if (hData) + ++ResourceHandleListPtr->num_valid_handles; + + _cur_resfile_name = 0; + } + ++TypeEncodePtr; + } + + if (DanglingOpen) + CloseResFile (fp); + + num_instances = ResourceHandleListPtr->num_valid_handles; + UnlockResourceHandleList (hList); + + if (num_instances == 0) + { +#ifdef DEBUG +printf ("Nothing in package!\n"); +#endif /* DEBUG */ + FreeResourceHandleList (hList); + hList = NULL_HANDLE; + } + + return (hList); +} + +MEM_HANDLE +GetResource (RESOURCE res) +{ + MEM_HANDLE hData, hList; + RES_PACKAGE res_package; + RES_TYPE res_type; + RES_INSTANCE res_instance; + RES_HANDLE_LISTPTR ResourceHandleListPtr; + ENCODEPTR TypeEncodePtr; + DATAPTR DataPtr; + INDEX_HEADERPTR ResHeaderPtr; + UWORD hi; + + ResHeaderPtr = _get_current_index_header (); + if (!ValidResource (ResHeaderPtr, res)) +{ +#ifdef DEBUG +if (res) printf ("0x%08lx is not a valid resource!\n", res); +#endif /* DEBUG */ + return (NULL_HANDLE); +} + + res_package = GET_PACKAGE (res); + + hi = HIWORD (ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc); + if (HIBYTE (hi) == 0) + hList = (MEM_HANDLE)LOWORD ( + ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc); + else + { + if ((hList = load_package (ResHeaderPtr, res_package)) == NULL_HANDLE) +{ +#ifdef DEBUG +printf ("Unable to load package %u\n", res_package); +#endif /* DEBUG */ + return (NULL_HANDLE); +} + + ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc = + MAKE_DWORD (hList, 0); + } + + res_type = GET_TYPE (res); + res_instance = GET_INSTANCE (res); + + LockResourceHandleList (ResHeaderPtr, hList, res_package, + &ResourceHandleListPtr, &TypeEncodePtr, &DataPtr); + + while (GET_TYPE (*TypeEncodePtr) != res_type) + { + DataPtr += (GET_PACKAGE (*TypeEncodePtr) << 1); + ++TypeEncodePtr; + } + DataPtr += (res_instance - GET_INSTANCE (*TypeEncodePtr)) << 1; + hData = MAKE_WORD (DataPtr[0], DataPtr[1]); + UnlockResourceHandleList (hList); + +#ifdef DEBUG +if (hData == 0) printf ("No data for res 0x%08lx\n", res); +#endif /* DEBUG */ + return (hData); +} + +static MEM_HANDLE +get_res_handle (RESOURCE res, BOOLEAN DoDetach) +{ + MEM_HANDLE hData = NULL_HANDLE; + RES_PACKAGE res_package; + RES_TYPE res_type; + RES_INSTANCE res_instance; + INDEX_HEADERPTR ResHeaderPtr; + UWORD hi; + + ResHeaderPtr = _get_current_index_header (); + if (!ValidResource (ResHeaderPtr, res)) + return (hData); + + res_package = GET_PACKAGE (res); + res_type = GET_TYPE (res); + res_instance = GET_INSTANCE (res); + + hi = HIWORD (ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc); + if (HIBYTE (hi) == 0) + { + MEM_HANDLE hList; + COUNT num_instances; + RES_HANDLE_LISTPTR ResourceHandleListPtr; + ENCODEPTR TypeEncodePtr; + DATAPTR DataPtr; + DWORD flags_and_data_loc; + + hList = LOWORD (ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc); + LockResourceHandleList (ResHeaderPtr, hList, res_package, + &ResourceHandleListPtr, &TypeEncodePtr, &DataPtr); + + while (GET_TYPE (*TypeEncodePtr) != res_type) + { + DataPtr += (GET_PACKAGE (*TypeEncodePtr) << 1); + ++TypeEncodePtr; + } + DataPtr += (res_instance - GET_INSTANCE (*TypeEncodePtr)) << 1; + hData = MAKE_WORD (DataPtr[0], DataPtr[1]); + if (hData && DoDetach) + { + DataPtr[0] = DataPtr[1] = 0; + --ResourceHandleListPtr->num_valid_handles; + + flags_and_data_loc = ResourceHandleListPtr->flags_and_data_loc; + } + num_instances = ResourceHandleListPtr->num_valid_handles; + UnlockResourceHandleList (hList); + + if (num_instances == 0) + { + FreeResourceHandleList (hList); + + ResHeaderPtr->PackageList[res_package - 1].flags_and_data_loc = + flags_and_data_loc; + } + } + + return (hData); +} + +BOOLEAN +FreeResource (RESOURCE res) +{ + MEM_HANDLE hData; + + hData = get_res_handle (res, FALSE); + if (hData) + { + RES_TYPE res_type; + INDEX_HEADERPTR ResHeaderPtr; + + res_type = GET_TYPE (res); + ResHeaderPtr = _get_current_index_header (); + if (DoFree (ResHeaderPtr, res_type, hData) + && get_res_handle (res, TRUE)) + return (TRUE); + } + + return (FALSE); +} + +MEM_HANDLE +DetachResource (RESOURCE res) +{ + return (get_res_handle (res, TRUE)); +} + diff --git a/sc2/src/sc2code/libs/resource/index.h b/sc2/src/sc2code/libs/resource/index.h new file mode 100644 index 000000000..2327d28bf --- /dev/null +++ b/sc2/src/sc2code/libs/resource/index.h @@ -0,0 +1,113 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _INDEX_H +#define _INDEX_H + +#include + +typedef struct +{ + MEM_HANDLE (*load_func) (FILE *fp, DWORD len); + BOOLEAN (*free_func) (MEM_HANDLE handle); +} RES_VECTORS; + +typedef struct +{ + RES_INSTANCE instance_count; + RES_VECTORS func_vectors; +} TYPE_DESC; +typedef TYPE_DESC *PTYPE_DESC; + +typedef struct +{ + RESOURCE packmem_info; + DWORD flags_and_data_loc; + /* data_loc doubles as 3 byte offset into package file or 2 byte + * MEM_HANDLE to package member array with the offset stored in + * the MEM_HANDLE (cuts down on use of near memory). + */ +} PACKAGE_DESC; +typedef PACKAGE_DESC *PPACKAGE_DESC; + +typedef BYTE RES_FLAGS; +#define IS_PACKAGED ((RES_FLAGS)(1 << 0)) + +typedef struct +{ + FILE *res_fp; + + DWORD packmem_list_offs; + DWORD path_list_offs; + DWORD file_list_offs; + + RES_PACKAGE num_packages; + RES_TYPE num_types; + RES_FLAGS res_flags; + + union + { + DWORD header_len; + struct + { + PPACKAGE_DESC package_list; + PTYPE_DESC type_list; + } lists; + } index_info; + +#ifndef PACKAGING + char index_file_name[36]; + DWORD data_offs; + MEM_HANDLE hPredHeader, hSuccHeader; +#endif /* PACKAGING */ +} INDEX_HEADER; +typedef INDEX_HEADER *PINDEX_HEADER; + +typedef PINDEX_HEADER INDEX_HEADERPTR; + +#define PackageList index_info.lists.package_list +#define TypeList index_info.lists.type_list + +#define INDEX_HEADER_PRIORITY DEFAULT_MEM_PRIORITY +#define AllocResourceHeader(s) \ + mem_allocate ((s), MEM_ZEROINIT | MEM_PRIMARY, \ + INDEX_HEADER_PRIORITY, MEM_SIMPLE) +#define LockResourceHeader (INDEX_HEADERPTR)mem_lock +#define UnlockResourceHeader mem_unlock +#define FreeResourceHeader mem_release + +typedef struct +{ + BYTE path_offset[2]; + char filename[8]; + char extension[3]; +} FILE_INFO; + +#define FILE_NAME_SIZE 8 +#define EXTENSION_SIZE 3 +#define NO_PATH 0xFFFF + +#define FILE_LIST_SIZE \ + ((sizeof (BYTE) * 2) + FILE_NAME_SIZE + EXTENSION_SIZE) +#define PACKMEM_LIST_SIZE \ + (sizeof (DWORD)) +#define INSTANCE_LIST_SIZE \ + (sizeof (BYTE) * 2) + +#endif /* _INDEX_H */ + diff --git a/sc2/src/sc2code/libs/resource/loadres.c b/sc2/src/sc2code/libs/resource/loadres.c new file mode 100644 index 000000000..2cf4114be --- /dev/null +++ b/sc2/src/sc2code/libs/resource/loadres.c @@ -0,0 +1,82 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "resintrn.h" +#include "declib.h" + +MEM_HANDLE +GetResourceData (FILE *fp, DWORD length, MEM_FLAGS mem_flags) +{ + MEM_HANDLE RData; + DECODE_REF fh; + + if (length == ~(DWORD)0) + length = LengthResFile (fp), fh = 0; + else if ((fh = copen (fp, FILE_STREAM, STREAM_READ))) + cfilelength (fh, &length); + else + length -= sizeof (DWORD); + + RData = AllocResourceData (length, mem_flags); + if (RData) + { + RESOURCE_DATAPTR RDPtr; + + LockResourceData (RData, &RDPtr); + if (RDPtr == NULL_PTR) + { + FreeResourceData (RData); + RData = 0; + } + else + { + COUNT num_read; + + do + { +#define READ_LENGTH 0x00007FFFL + num_read = length >= READ_LENGTH ? + (COUNT)READ_LENGTH : (COUNT)length; + if (fh) + { + if (cread (RDPtr, 1, num_read, fh) != num_read) + break; + } + else + { + if ((int)(ReadResFile (RDPtr, 1, num_read, fp)) != (int)num_read) + break; + } + FAR_PTR_ADD (&RDPtr, num_read); + } while (length -= num_read); + + UnlockResourceData (RData); + if (length > 0) + { + FreeResourceData (RData); + RData = 0; + } + } + } + + cclose (fh); + + return (RData); +} + + diff --git a/sc2/src/sc2code/libs/resource/resdata.c b/sc2/src/sc2code/libs/resource/resdata.c new file mode 100644 index 000000000..79cff72ff --- /dev/null +++ b/sc2/src/sc2code/libs/resource/resdata.c @@ -0,0 +1,34 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "resintrn.h" + +static INDEX_HEADERPTR CurResHeaderPtr; + +void +_set_current_index_header (INDEX_HEADERPTR ResHeaderPtr) +{ + CurResHeaderPtr = ResHeaderPtr; +} + +INDEX_HEADERPTR +_get_current_index_header (void) +{ + return (CurResHeaderPtr); +} + diff --git a/sc2/src/sc2code/libs/resource/resinit.c b/sc2/src/sc2code/libs/resource/resinit.c new file mode 100644 index 000000000..d2b82bb19 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/resinit.c @@ -0,0 +1,407 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "resintrn.h" + +static MEM_HANDLE hIndexList; + +static void +_add_index_list (MEM_HANDLE hRH) +{ +#ifndef PACKAGING + INDEX_HEADERPTR ResHeaderPtr; + + ResHeaderPtr = LockResourceHeader (hRH); + strncpy (ResHeaderPtr->index_file_name, _cur_resfile_name, + sizeof (ResHeaderPtr->index_file_name) - 1); + ResHeaderPtr->hPredHeader = 0; + ResHeaderPtr->hSuccHeader = hIndexList; + if (ResHeaderPtr->hSuccHeader) + { + INDEX_HEADERPTR SuccResHeaderPtr; + + SuccResHeaderPtr = LockResourceHeader (hIndexList); + SuccResHeaderPtr->hPredHeader = hRH; + UnlockResourceHeader (hIndexList); + } + UnlockResourceHeader (hRH); +#endif /* PACKAGING */ + + hIndexList = hRH; +} + +static void +_sub_index_list (MEM_HANDLE hRH) +{ +#ifdef PACKAGING + hIndexList = 0; +#else /* !PACKAGING */ + INDEX_HEADERPTR ResHeaderPtr; + MEM_HANDLE hPred, hSucc; + + ResHeaderPtr = LockResourceHeader (hRH); + + hPred = ResHeaderPtr->hPredHeader; + hSucc = ResHeaderPtr->hSuccHeader; + if (hRH == hIndexList) + hIndexList = hSucc; + + if (hPred) + { + INDEX_HEADERPTR PredResHeaderPtr; + + PredResHeaderPtr = LockResourceHeader (hPred); + PredResHeaderPtr->hSuccHeader = hSucc; + UnlockResourceHeader (hPred); + } + if (hSucc) + { + INDEX_HEADERPTR SuccResHeaderPtr; + + SuccResHeaderPtr = LockResourceHeader (hSucc); + SuccResHeaderPtr->hPredHeader = hPred; + UnlockResourceHeader (hSucc); + } + + UnlockResourceHeader (hRH); +#endif /* PACKAGING */ +} + +MEM_HANDLE +_GetResFileData (FILE *res_fp, DWORD flen) +{ + UWORD lo_word, hi_word; + DWORD res_offs, remainder; + MEM_SIZE HeaderSize; + INDEX_HEADER h; + INDEX_HEADERPTR ResHeaderPtr; + MEM_HANDLE hRH; + char buf[32]; + + res_offs = TellResFile (res_fp); + + ReadResFile (buf, 1, 22, res_fp); + + h.res_fp = res_fp; + h.res_flags = MAKE_WORD (buf[0], buf[1]) ? IS_PACKAGED : 0; + + lo_word = MAKE_WORD (buf[2], buf[3]); + hi_word = MAKE_WORD (buf[4], buf[5]); + h.packmem_list_offs = MAKE_DWORD (lo_word, hi_word); + + lo_word = MAKE_WORD (buf[6], buf[7]); + hi_word = MAKE_WORD (buf[8], buf[9]); + h.path_list_offs = MAKE_DWORD (lo_word, hi_word); + + lo_word = MAKE_WORD (buf[10], buf[11]); + hi_word = MAKE_WORD (buf[12], buf[13]); + h.file_list_offs = MAKE_DWORD (lo_word, hi_word); + + h.num_packages = (RES_PACKAGE)MAKE_WORD (buf[14], buf[15]); + h.num_types = (RES_TYPE)MAKE_WORD (buf[16], buf[17]); + + lo_word = MAKE_WORD (buf[18], buf[19]); + hi_word = MAKE_WORD (buf[20], buf[21]); + h.index_info.header_len = MAKE_DWORD (lo_word, hi_word); + + HeaderSize = (MEM_SIZE)(sizeof (INDEX_HEADER) + + (sizeof (PACKAGE_DESC) * h.num_packages) + + (sizeof (TYPE_DESC) * h.num_types)); + if (h.res_flags & IS_PACKAGED) + { + DWORD offs; + + remainder = h.index_info.header_len - h.packmem_list_offs; + offs = HeaderSize - h.packmem_list_offs; + HeaderSize += remainder; + h.packmem_list_offs += offs; + h.file_list_offs += offs; + h.path_list_offs += offs; + } + +#ifndef PACKAGING + { + MEM_HANDLE hNextRH; + + h.data_offs = res_offs; + for (hRH = hIndexList; hRH != 0; hRH = hNextRH) + { + ResHeaderPtr = LockResourceHeader (hRH); + if (h.data_offs == ResHeaderPtr->data_offs + && strncmp (ResHeaderPtr->index_file_name, + _cur_resfile_name, + sizeof (ResHeaderPtr->index_file_name) - 1) == 0) + return (hRH); /* DON'T UNLOCK IT */ + + hNextRH = ResHeaderPtr->hSuccHeader; + UnlockResourceHeader (hRH); + } + } +#endif /* PACKAGING */ + + if ((hRH = AllocResourceHeader (HeaderSize)) + && (ResHeaderPtr = LockResourceHeader (hRH))) + { + *ResHeaderPtr = h; + + { + RES_PACKAGE p; + + ResHeaderPtr->PackageList = (PPACKAGE_DESC)&ResHeaderPtr[1]; + for (p = 0; p < ResHeaderPtr->num_packages; ++p) + { + ReadResFile (buf, 1, 8, res_fp); + + lo_word = MAKE_WORD (buf[0], buf[1]); + hi_word = MAKE_WORD (buf[2], buf[3]); + ResHeaderPtr->PackageList[p].packmem_info = + (RESOURCE)MAKE_DWORD (lo_word, hi_word); + + lo_word = MAKE_WORD (buf[4], buf[5]); + hi_word = MAKE_WORD (buf[6], buf[7]); + ResHeaderPtr->PackageList[p].flags_and_data_loc = + MAKE_DWORD (lo_word, hi_word) + res_offs; + } + } + + { + RES_TYPE t; + INDEX_HEADERPTR CurResHeaderPtr; + + CurResHeaderPtr = _get_current_index_header (); + + ResHeaderPtr->TypeList = + (PTYPE_DESC)&ResHeaderPtr->PackageList[ResHeaderPtr->num_packages]; + for (t = 0; t < ResHeaderPtr->num_types; ++t) + { + ReadResFile (buf, 1, 2, res_fp); + + ResHeaderPtr->TypeList[t].instance_count = + MAKE_WORD (buf[0], buf[1]); + if (CurResHeaderPtr) + ResHeaderPtr->TypeList[t].func_vectors = + CurResHeaderPtr->TypeList[t].func_vectors; + } + } + + if (h.res_flags & IS_PACKAGED) + ReadResFile (&ResHeaderPtr->TypeList[ResHeaderPtr->num_types], + 1, (COUNT)remainder, res_fp); + + _add_index_list (hRH); + + return (hRH); /* DON'T UNLOCK IT */ + } + + FreeResourceHeader (hRH); + (void) flen; /* Satisfy compiler (unused parameter) */ + return (NULL_HANDLE); +} + +MEM_HANDLE +InitResourceSystem (PVOID resfile, COUNT resindex_type, BOOLEAN + (*FileErrorFunc) (PVOID filename)) +{ + MEM_HANDLE h; + + h = OpenResourceIndexFile (resfile); + if (h) + { + SetResourceIndex (h); + + InstallResTypeVectors (resindex_type, + _GetResFileData, FreeResourceHeader); + } + + (void) FileErrorFunc; /* Satisfy compiler (unused parameter) */ + return (h); +} + +BOOLEAN +UninitResourceSystem (void) +{ + if (hIndexList) + { + do + CloseResourceIndex (hIndexList); + while (hIndexList); + + return (TRUE); + } + + return (FALSE); +} + +MEM_HANDLE +OpenResourceIndexFile (PVOID resfile) +{ + FILE *res_fp; + char fullname[256]; + + strcpy (fullname, resfile); + if ((res_fp = OpenResFile (fullname, "rb")) == 0) + { + sprintf (fullname, "%s.pkg", (char *) resfile); + if ((res_fp = OpenResFile (fullname, "rb")) == 0) + { + sprintf (fullname, "%s.ndx", (char *) resfile); + res_fp = OpenResFile (fullname, "rb"); + } + } + + if (res_fp) + { + MEM_HANDLE hRH; + + _cur_resfile_name = fullname; + + hRH = _GetResFileData (res_fp, LengthResFile (res_fp)); + /* DO NOT CloseResFile!!! */ + + return (hRH); + } + + return (0); +} + +MEM_HANDLE +OpenResourceIndexInstance (DWORD res) +{ + MEM_HANDLE hRH; + + hRH = GetResource (res); + if (hRH) + DetachResource (res); + + return (hRH); +} + +MEM_HANDLE +SetResourceIndex (MEM_HANDLE hRH) +{ + MEM_HANDLE hOldRH; + static MEM_HANDLE hCurResHeader; + + if ((hOldRH = hCurResHeader) != hRH) + { + INDEX_HEADERPTR ResHeaderPtr; + + ResHeaderPtr = LockResourceHeader (hRH); + UnlockResourceHeader (hRH); + _set_current_index_header (ResHeaderPtr); + hCurResHeader = hRH; + } + + return (hOldRH); +} + +BOOLEAN +CloseResourceIndex (MEM_HANDLE hRH) +{ + if (UnlockResourceHeader (hRH)) + { + FILE *res_fp; + INDEX_HEADERPTR ResHeaderPtr; + + ResHeaderPtr = LockResourceHeader (hRH); +#ifdef DEBUG +{ +COUNT i; + +for (i = 0; i < ResHeaderPtr->num_packages; ++i) +{ + UWORD hi; + + hi = HIWORD (ResHeaderPtr->PackageList[i].flags_and_data_loc); + if (HIBYTE (hi) == 0) + { + MEM_HANDLE hList; + RES_HANDLE_LISTPTR ResourceHandleListPtr; + ENCODEPTR TypeEncodePtr; + DATAPTR DataPtr; + + hList = (MEM_HANDLE)LOWORD ( + ResHeaderPtr->PackageList[i].flags_and_data_loc); + LockResourceHandleList (ResHeaderPtr, hList, i + 1, + &ResourceHandleListPtr, &TypeEncodePtr, &DataPtr); + printf ("Package %u has %u instances left\n", + i + 1, ResourceHandleListPtr->num_valid_handles); + UnlockResourceHandleList (hList); + } +} +} +#endif /* DEBUG */ + + _sub_index_list (hRH); + res_fp = ResHeaderPtr->res_fp; + if (ResHeaderPtr == _get_current_index_header ()) + SetResourceIndex (hIndexList); + UnlockResourceHeader (hRH); + FreeResourceHeader (hRH); + + if (res_fp) + { + MEM_HANDLE hNextRH; + + for (hRH = hIndexList; hRH && res_fp; hRH = hNextRH) + { + ResHeaderPtr = LockResourceHeader (hRH); + if (res_fp == ResHeaderPtr->res_fp) + res_fp = 0; + hNextRH = ResHeaderPtr->hSuccHeader; + UnlockResourceHeader (hRH); + } + + if (res_fp) + CloseResFile (res_fp); + } + + return (TRUE); + } + + return (FALSE); +} + +BOOLEAN +InstallResTypeVectors (COUNT res_type, + MEM_HANDLE (*load_func) (FILE *fp, DWORD len), + BOOLEAN (*free_func) (MEM_HANDLE handle)) +{ + INDEX_HEADERPTR ResHeaderPtr; + + ResHeaderPtr = _get_current_index_header (); + if (ValidResType (ResHeaderPtr, res_type)) + { + ResHeaderPtr->TypeList[res_type - 1].func_vectors.load_func = load_func; + ResHeaderPtr->TypeList[res_type - 1].func_vectors.free_func = free_func; + + return (TRUE); + } + + return (FALSE); +} + +COUNT +CountResourceTypes (void) +{ + INDEX_HEADERPTR ResHeaderPtr; + + ResHeaderPtr = _get_current_index_header (); + return ((COUNT)ResHeaderPtr->num_types); +} + diff --git a/sc2/src/sc2code/libs/resource/resintrn.h b/sc2/src/sc2code/libs/resource/resintrn.h new file mode 100644 index 000000000..68d5a7c6d --- /dev/null +++ b/sc2/src/sc2code/libs/resource/resintrn.h @@ -0,0 +1,80 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _RESINTRN_H +#define _RESINTRN_H + +#include +#include "reslib.h" +#include "index.h" + +typedef struct +{ + DWORD flags_and_data_loc; + COUNT num_valid_handles; +} RES_HANDLE_LIST; +typedef RES_HANDLE_LIST *PRES_HANDLE_LIST; +typedef PRES_HANDLE_LIST RES_HANDLE_LISTPTR; + +typedef PDWORD ENCODEPTR; +typedef PBYTE DATAPTR; + +#define RES_HANDLE_LIST_PRIORITY DEFAULT_MEM_PRIORITY + +#define AllocResourceHandleList(nt,ni) \ + mem_allocate ((MEM_SIZE)(sizeof (RES_HANDLE_LIST) \ + + (PACKMEM_LIST_SIZE * (nt)) \ + + (INSTANCE_LIST_SIZE * (ni))), MEM_ZEROINIT | MEM_PRIMARY, \ + RES_HANDLE_LIST_PRIORITY, MEM_SIMPLE) +#define LockResourceHandleList(pRH,h,p,rp,tp,dp) \ +do \ +{ \ + *(rp) = (RES_HANDLE_LISTPTR)mem_lock ((MEM_HANDLE)h); \ + *(tp) = (ENCODEPTR)&(*(rp))[1]; \ + *(dp) = (DATAPTR)&(*(tp))[CountPackageTypes (pRH,p)]; \ +} while (0) +#define UnlockResourceHandleList(h) mem_unlock((MEM_HANDLE)h) +#define FreeResourceHandleList(h) mem_release((MEM_HANDLE)h) + +#define DoLoad(pRH, t,fp,len) (*(pRH)->TypeList[t-1].func_vectors.load_func)(fp,len) +#define DoFree(pRH, t,h) (*(pRH)->TypeList[t-1].func_vectors.free_func)(h) + +extern MEM_HANDLE _GetResFileData (FILE *res_fp, DWORD flen); +#define IsIndexType(pRH, t) ((pRH)->TypeList[t-1].func_vectors.load_func \ + ==_GetResFileData) + +#define LastResPackage(pRH) ((pRH)->num_packages) +#define LastResType(pRH) ((pRH)->num_types) +#define GetInstanceCount(pRH,t) \ + ((pRH)->TypeList[(t)-1].instance_count) + +#define ValidResPackage(pRH,p) ((p)<=LastResPackage(pRH)) +#define ValidResType(pRH,t) ((t)!=0&&(t)<=LastResType(pRH)) + +#define CountPackageTypes(pRH,p) \ + (COUNT)GET_TYPE ((pRH)->PackageList[(p)-1].packmem_info) +#define CountPackageInstances(pRH,p) \ + (COUNT)GET_INSTANCE ((pRH)->PackageList[(p)-1].packmem_info) + +extern void _set_current_index_header (INDEX_HEADERPTR ResHeaderPtr); +extern INDEX_HEADERPTR _get_current_index_header (void); + +extern char *_cur_resfile_name; + +#endif /* _RESINTRN_H */ + diff --git a/sc2/src/sc2code/libs/sndlib.h b/sc2/src/sc2code/libs/sndlib.h new file mode 100644 index 000000000..5cdccd6a9 --- /dev/null +++ b/sc2/src/sc2code/libs/sndlib.h @@ -0,0 +1,88 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SNDLIB_H +#define _SNDLIB_H + +#include "strlib.h" +#include "memlib.h" + +typedef STRING_TABLE SOUND_REF; +typedef STRING SOUND; +typedef STRINGPTR SOUNDPTR; + +#define InitSoundResources InitStringTableResources +#define CaptureSound CaptureStringTable +#define ReleaseSound ReleaseStringTable +#define GetSoundRef GetStringTable +#define GetSoundCount GetStringTableCount +#define GetSoundIndex GetStringTableIndex +#define SetAbsSoundIndex SetAbsStringTableIndex +#define SetRelSoundIndex SetRelStringTableIndex +#define GetSoundLength GetStringLength +#define GetSoundAddress GetStringAddress +#define GetSoundContents GetStringContents + +typedef MEM_HANDLE MUSIC_REF; + +extern BOOLEAN InitSound (int argc, char *argv[]); +extern void UninitSound (void); +extern SOUND_REF LoadSoundFile (PVOID pStr); +extern MUSIC_REF LoadMusicFile (PVOID pStr); +extern BOOLEAN InstallAudioResTypes (COUNT sound_type, COUNT + music_type); +extern SOUND_REF LoadSoundInstance (DWORD res); +extern MUSIC_REF LoadMusicInstance (DWORD res); +extern BOOLEAN DestroySound (SOUND_REF SoundRef); +extern BOOLEAN DestroyMusic (MUSIC_REF MusicRef); + +#define MAX_CHANNELS 8 +#define MAX_VOLUME 255 + +extern void PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE + Priority); +extern void PLRStop (MUSIC_REF MusicRef); +extern BOOLEAN PLRPlaying (MUSIC_REF MusicRef); +extern void PLRPause (MUSIC_REF MusicRef); +extern void PLRResume (MUSIC_REF MusicRef); +extern void PlayChannel (COUNT Channel, PVOID lpSample, COUNT SampLen, + COUNT LoopBegin, COUNT LoopLen, BYTE Priority); +extern BOOLEAN ChannelPlaying (COUNT Channel); +extern void StopChannel (COUNT Channel, BYTE Priority); +extern void SetMusicVolume (COUNT Volume); +extern void SetChannelVolume (COUNT Channel, COUNT Volume, BYTE + Priority); +extern void SetChannelRate (COUNT Channel, DWORD Rate, BYTE Priority); + +extern void StopSound (void); +extern BOOLEAN SoundPlaying (void); + +extern BOOLEAN AllocHardwareSample (PBYTE lpSnd, DWORD SampleRate, COUNT + SampleLength, COUNT LoopBegin, COUNT LoopLen); +extern BOOLEAN FreeHardwareSample (PBYTE lpSnd, COUNT SampleLength); + +extern COUNT GetSampleRate (SOUND Sound); +extern COUNT GetSampleLength (SOUND Sound); +extern PBYTE GetSampleAddress (SOUND Sound); +extern DWORD FadeMusic (BYTE end_vol, SIZE TimeInterval); + +extern void SetSoundTracking (BOOLEAN toggle); +extern void GetSoundTrackingBuf (PSBYTE pdigi_buf); + +#endif /* _SNDLIB_H */ + diff --git a/sc2/src/sc2code/libs/sound/Makefile.am b/sc2/src/sc2code/libs/sound/Makefile.am new file mode 100644 index 000000000..becdefb1c --- /dev/null +++ b/sc2/src/sc2code/libs/sound/Makefile.am @@ -0,0 +1,13 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libsound.la +libsound_la_SOURCES = fileinst.c play.c resinst.c modfuncs.c +noinst_HEADERS = play.h redbook.h sndintrn.h diff --git a/sc2/src/sc2code/libs/sound/fileinst.c b/sc2/src/sc2code/libs/sound/fileinst.c new file mode 100644 index 000000000..2a9065869 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/fileinst.c @@ -0,0 +1,60 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "sndintrn.h" + +SOUND_REF +LoadSoundFile (PVOID pStr) +{ + FILE *fp; + + fp = OpenResFile (pStr, "rb"); + if (fp) + { + MEM_HANDLE hData; + + hData = _GetSoundBankData (fp, LengthResFile (fp)); + + CloseResFile (fp); + + return ((SOUND_REF)hData); + } + + return (0); +} + +MUSIC_REF +LoadMusicFile (PVOID pStr) +{ + FILE *fp; + + fp = OpenResFile (pStr, "rb"); + if (fp) + { + MEM_HANDLE hData; + + hData = _GetMusicData (fp, LengthResFile (fp)); + + CloseResFile (fp); + + return ((MUSIC_REF)hData); + } + + return (0); +} + diff --git a/sc2/src/sc2code/libs/sound/modfuncs.c b/sc2/src/sc2code/libs/sound/modfuncs.c new file mode 100644 index 000000000..50ab74eaa --- /dev/null +++ b/sc2/src/sc2code/libs/sound/modfuncs.c @@ -0,0 +1,202 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "libs/strings/strintrn.h" +#include "sndintrn.h" +#ifdef WIN32 +#include +#endif +#include + +#include "SDL_wrapper.h" + +MEM_HANDLE +_GetSoundBankData (FILE *fp, DWORD length) +{ +#ifdef WIN32 + int omode; +#endif + int snd_ct, n; + DWORD opos; + char CurrentLine[1024], filename[1024]; +#define MAX_FX 256 + Mix_Chunk *sndfx[MAX_FX]; + STRING_TABLE Snd; + + opos = ftell (fp); + + { + char *s1, *s2; + extern char *_cur_resfile_name; + + if (_cur_resfile_name == 0 + || (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) + && (s2 = strrchr (_cur_resfile_name, '\\')) == 0)) + n = 0; + else + { + if (s2 > s1) + s1 = s2; + n = s1 - _cur_resfile_name + 1; + strncpy (filename, _cur_resfile_name, n); + } + } + +#ifdef WIN32 + omode = _setmode (fileno (fp), O_TEXT); +#endif + snd_ct = 0; + while (fgets (CurrentLine, sizeof (CurrentLine), fp) && snd_ct < MAX_FX) + { + if + ( + sscanf(CurrentLine, "%s", &filename[n]) == 1 && + (sndfx[snd_ct] = Mix_LoadWAV (filename)) + ) + { + ++snd_ct; + } + else + { + printf("_GetSoundBankData: Bad file!\n"); + } + + if (ftell (fp) - opos >= length) + break; + } +#ifdef WIN32 + _setmode (fileno (fp), omode); +#endif + + Snd = 0; + if (snd_ct && (Snd = AllocStringTable ( + sizeof (STRING_TABLE_DESC) + + (sizeof (DWORD) * snd_ct) + + (sizeof (sndfx[0]) * snd_ct) + ))) + { + STRING_TABLEPTR fxTab; + + LockStringTable (Snd, &fxTab); + if (fxTab == 0) + { + while (snd_ct--) + Mix_FreeChunk (sndfx[snd_ct]); + FreeStringTable (Snd); + Snd = 0; + } + else + { + DWORD *offs, StringOffs; + + fxTab->StringCount = snd_ct; + fxTab->flags = 0; + offs = fxTab->StringOffsets; + StringOffs = sizeof (STRING_TABLE_DESC) + (sizeof (DWORD) * snd_ct); + memcpy ((BYTE *)fxTab + StringOffs, sndfx, sizeof (sndfx[0]) * snd_ct); + do + { + *offs++ = StringOffs; + StringOffs += sizeof (sndfx[0]); + } while (snd_ct--); + UnlockStringTable (Snd); + } + } + + return ((MEM_HANDLE)Snd); +} + +BOOLEAN +_ReleaseSoundBankData (MEM_HANDLE Snd) +{ + STRING_TABLEPTR fxTab; + + LockStringTable (Snd, &fxTab); + if (fxTab) + { + int snd_ct; + Mix_Chunk **sptr; + + snd_ct = fxTab->StringCount; + sptr = (Mix_Chunk **)((BYTE *)fxTab + fxTab->StringOffsets[0]); + while (snd_ct--) + { + Mix_FreeChunk (*sptr); + *sptr++ = 0; + } + UnlockStringTable (Snd); + FreeStringTable (Snd); + + return (TRUE); + } + + return (FALSE); +} + +MEM_HANDLE +_GetMusicData (FILE *fp, DWORD length) +{ + MEM_HANDLE h; + extern char *_cur_resfile_name; + + h = 0; + if (_cur_resfile_name && (h = AllocMusicData (sizeof (void *)))) + { + Mix_Music **pmus; + + LockMusicData (h, &pmus); + if (pmus == 0 || (*pmus = Mix_LoadMUS (_cur_resfile_name)) == 0) + { + UnlockMusicData (h); + mem_release (h); + h = 0; + } + else + { + // + } + UnlockMusicData (h); + } + + (void) fp; /* satisfy compiler (unused parameter) */ + (void) length; /* satisfy compiler (unused parameter) */ + return (h); +} + +BOOLEAN +_ReleaseMusicData (MEM_HANDLE handle) +{ + Mix_Music **pmus; + + LockMusicData (handle, &pmus); + if (pmus == 0) + return (FALSE); + + Mix_FreeMusic (*pmus); + + UnlockMusicData (handle); + mem_release (handle); + + return (TRUE); +} + +BOOLEAN +DestroySound(SOUND_REF target) +{ + return (_ReleaseSoundBankData (target)); +} diff --git a/sc2/src/sc2code/libs/sound/play.c b/sc2/src/sc2code/libs/sound/play.c new file mode 100644 index 000000000..2113964c0 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/play.c @@ -0,0 +1,91 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "sndintrn.h" +#include "timlib.h" + +#include "SDL_wrapper.h" + +static MUSIC_REF curMusicRef; + +void +PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) +{ + Mix_Music **pmus; + + LockMusicData (MusicRef, &pmus); + if (pmus) + { + PLRStop (curMusicRef); + + curMusicRef = MusicRef; + Mix_PlayMusic (*pmus, Continuous ? -1 : 1); + } + (void) Priority; /* Satisfy compiler because of unused variable */ +} + +void +PLRStop (MUSIC_REF MusicRef) +{ + if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) + { + Mix_HaltMusic (); + + UnlockMusicData (curMusicRef); + curMusicRef = 0; + } +} + +BOOLEAN +PLRPlaying (MUSIC_REF MusicRef) +{ + if (curMusicRef && (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)) + { + if (Mix_PlayingMusic ()) + return (TRUE); + PLRStop (curMusicRef); + } + + return (FALSE); +} + +void +PLRPause (MUSIC_REF MusicRef) +{ + if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) + { +// Mix_FadeOutMusic (1 * 1000); + Mix_PauseMusic (); + } +} + +void +PLRResume (MUSIC_REF MusicRef) +{ + if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) + { +// Mix_FadeInMusic (1 * 1000); + Mix_ResumeMusic (); + } +} + +BOOLEAN +DestroyMusic (MUSIC_REF MusicRef) +{ + return (FreeMusicData (MusicRef)); +} diff --git a/sc2/src/sc2code/libs/sound/play.h b/sc2/src/sc2code/libs/sound/play.h new file mode 100644 index 000000000..024e5d078 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/play.h @@ -0,0 +1,74 @@ +#ifndef _PLAY_H +#define _PLAY_H + +enum +{ + MOD_TRACK, + RED_BOOK_TRACK, + + NUM_TRACK_TYPES +}; + +typedef struct +{ + MUSIC_REF TrackRef; + PBYTE TrackPtr; +} TRACK_DESC; +extern TRACK_DESC volatile _TrackList[NUM_TRACK_TYPES]; + +#define MAX_CHANNELS 4 +#define MAX_TRACKS 16 +#define MAX_INSTRUMENTS 63 +#define MAX_BLOCKS 256 +#define MAX_TRACK_VOLUME 64 + +typedef unsigned short SAMPLE_RATE; + +typedef struct +{ + COUNT LoopBegin, LoopLength; + COUNT SampleLength; + BYTE volume, transposition; +} INSTRUMENT_DESC; + +typedef struct +{ + BYTE LineCommands[MAX_CHANNELS][3]; +} LINE_DESC; +typedef LINE_DESC *PLINE_DESC; +#define LINE_DESCPTR PLINE_DESC + +typedef struct +{ + BYTE NumTracks, LastLine; + LINE_DESC LineList[1]; +} BLOCK_DESC; +typedef BLOCK_DESC *PBLOCK_DESC; +#define BLOCK_DESCPTR PBLOCK_DESC + +#define PLAY_CONTINUOUS (1 << 0) + +typedef struct +{ + INSTRUMENT_DESC PresetList[MAX_INSTRUMENTS]; + BYTE NumPhysicalBlocks, NumLogicalBlocks; + BYTE LogToPhysBlockList[MAX_BLOCKS]; + BYTE Tempo, NumSteps; + BYTE Priority, Flags; + BYTE TrackVolumeList[MAX_TRACKS]; + BYTE MasterVolume; + BYTE NumInstruments; + + DWORD InstrumentList[MAX_INSTRUMENTS]; + DWORD BlockList[1]; +} SONG_DESC; +typedef SONG_DESC *PSONG_DESC; +#define SONG_DESCPTR PSONG_DESC + +extern void _download_effects (SOUND_REF SoundRef); +extern BOOLEAN _download_instruments (MUSIC_REF MusicRef); + +#include "redbook.h" + +#endif /* _PLAY_H */ + diff --git a/sc2/src/sc2code/libs/sound/redbook.h b/sc2/src/sc2code/libs/sound/redbook.h new file mode 100644 index 000000000..760e86e99 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/redbook.h @@ -0,0 +1,29 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _REDBOOK_H +#define _REDBOOK_H + +extern BOOLEAN _is_red_book (PBYTE TrackInfo); +extern BOOLEAN _play_red_book (PBYTE TrackInfo, BOOLEAN Loop); +extern void _stop_red_book (void); +extern BOOLEAN _red_book_playing (void); +extern void _pause_red_book (void); +extern void _resume_red_book (void); + +#endif /* _REDBOOK_H */ diff --git a/sc2/src/sc2code/libs/sound/resinst.c b/sc2/src/sc2code/libs/sound/resinst.c new file mode 100644 index 000000000..d8796ce9e --- /dev/null +++ b/sc2/src/sc2code/libs/sound/resinst.c @@ -0,0 +1,52 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "sndintrn.h" + +BOOLEAN +InstallAudioResTypes (COUNT sound_type, COUNT music_type) +{ + InstallResTypeVectors (sound_type, _GetSoundBankData, _ReleaseSoundBankData); + InstallResTypeVectors (music_type, _GetMusicData, _ReleaseMusicData); + return (TRUE); +} + +SOUND_REF +LoadSoundInstance (DWORD res) +{ + MEM_HANDLE hData; + + hData = GetResource (res); + if (hData) + DetachResource (res); + + return ((SOUND_REF)hData); +} + +MUSIC_REF +LoadMusicInstance (DWORD res) +{ + MEM_HANDLE hData; + + hData = GetResource (res); + if (hData) + DetachResource (res); + + return ((MUSIC_REF)hData); +} + diff --git a/sc2/src/sc2code/libs/sound/sndintrn.h b/sc2/src/sc2code/libs/sound/sndintrn.h new file mode 100644 index 000000000..63e1d59ca --- /dev/null +++ b/sc2/src/sc2code/libs/sound/sndintrn.h @@ -0,0 +1,38 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SNDINTRN_H +#define _SNDINTRN_H + +#include +#include "sndlib.h" +#include "reslib.h" + +extern MEM_HANDLE _GetMusicData (FILE *fp, DWORD length); +extern BOOLEAN _ReleaseMusicData (MEM_HANDLE handle); + +extern MEM_HANDLE _GetSoundBankData (FILE *fp, DWORD length); +extern BOOLEAN _ReleaseSoundBankData (MEM_HANDLE handle); + +#define AllocMusicData(s) AllocResourceData((s),MEM_ZEROINIT) +#define LockMusicData LockResourceData +#define UnlockMusicData UnlockResourceData +#define FreeMusicData _ReleaseMusicData + +#endif /* _SNDINTRN_H */ + diff --git a/sc2/src/sc2code/libs/strings/Makefile.am b/sc2/src/sc2code/libs/strings/Makefile.am new file mode 100644 index 000000000..31b22f9da --- /dev/null +++ b/sc2/src/sc2code/libs/strings/Makefile.am @@ -0,0 +1,15 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs \ + @SDL_CFLAGS@ @SMPEG_CFLAGS@ + +noinst_LTLIBRARIES = libstrings.la +libstrings_la_SOURCES = getstr.c sfileins.c sresins.c strings.c +noinst_HEADERS = strintrn.h + diff --git a/sc2/src/sc2code/libs/strings/getstr.c b/sc2/src/sc2code/libs/strings/getstr.c new file mode 100644 index 000000000..5808bedae --- /dev/null +++ b/sc2/src/sc2code/libs/strings/getstr.c @@ -0,0 +1,257 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "strintrn.h" +#include "SDL_wrapper.h" +#ifdef WIN32 +#include +#endif +#include + +static void +dword_convert (PDWORD dword_array, COUNT num_dwords) +{ + PBYTE p = (PBYTE)dword_array; + + do + { + *dword_array++ = MAKE_DWORD ( + MAKE_WORD (p[3], p[2]), + MAKE_WORD (p[1], p[0]) + ); + p += 4; + } while (--num_dwords); +} + +MEM_HANDLE +_GetStringData (FILE *fp, DWORD length) +{ + MEM_HANDLE hData; + + { + char *s; + extern char *_cur_resfile_name; + + if (_cur_resfile_name && (s = strrchr (_cur_resfile_name, '.')) && stricmp (s, ".txt") == 0) + { +#define MAX_STRINGS 2048 +#define POOL_SIZE 4096 +#ifdef WIN32 + int omode; +#endif + int n, path_len; + DWORD opos, + slen[MAX_STRINGS], StringOffs, tot_string_size, + clen[MAX_STRINGS], ClipOffs, tot_clip_size; + char CurrentLine[1024], clip_path[1024], *strdata, *clipdata; + + if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0) + return (0); + + if ((clipdata = HMalloc (tot_clip_size = POOL_SIZE)) == 0) + { + HFree (strdata); + return (0); + } + + { + char *s1, *s2; + + if (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) + && (s2 = strrchr (_cur_resfile_name, '\\')) == 0) + n = 0; + else + { + if (s2 > s1) + s1 = s2; + n = s1 - _cur_resfile_name + 1; + strncpy (clip_path, _cur_resfile_name, n); + } + clip_path[n] = '\0'; + path_len = strlen (clip_path); + } + + opos = ftell (fp); +#ifdef WIN32 + omode = _setmode (fileno (fp), O_TEXT); +#endif + n = -1; + StringOffs = ClipOffs = 0; + while (fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1) + { + int l; + + if (CurrentLine[0] == '#') + { + char CopyLine[1024]; + + strcpy (CopyLine, CurrentLine); + s = strtok (&CopyLine[1], "()"); + if (s) + { + if (n >= 0) + { + while (slen[n] > 1 && strdata[StringOffs - 2] == '\n') + { + --slen[n]; + --StringOffs; + strdata[StringOffs - 1] = '\0'; + } + } + + slen[++n] = 0; + clen[n] = 0; + s = strtok (NULL, " \t\n)"); + if (s) + { + l = path_len + strlen (s) + 1; + if (ClipOffs + l > tot_clip_size + && (clipdata = HRealloc (clipdata, + tot_clip_size += POOL_SIZE)) == 0) + { + HFree (strdata); + return (0); + } + + strcpy (&clipdata[ClipOffs], clip_path); + strcpy (&clipdata[ClipOffs + path_len], s); + ClipOffs += l; + clen[n] = l; + } + } + } + else if (n >= 0) + { + l = strlen (CurrentLine) + 1; + if (StringOffs + l > tot_string_size + && (strdata = HRealloc (strdata, + tot_string_size += POOL_SIZE)) == 0) + { + HFree (clipdata); + return (0); + } + + if (slen[n]) + { + --slen[n]; + --StringOffs; + } + s = &strdata[StringOffs]; + slen[n] += l; + StringOffs += l; + + strcpy (s, CurrentLine); + } + + if ((int)ftell (fp) - (int)opos >= (int)length) + break; + } +#ifdef WIN32 + _setmode (fileno (fp), omode); +#endif + if (n >= 0) + { + while (slen[n] > 1 && strdata[StringOffs - 2] == '\n') + { + --slen[n]; + --StringOffs; + strdata[StringOffs - 1] = '\0'; + } + } + + hData = 0; + if (++n && (hData = AllocStringTable ( + (sizeof (STRING_TABLE_DESC) - sizeof (DWORD)) + + (sizeof (DWORD) * ((n + 1) << (ClipOffs ? 1 : 0))) + + StringOffs + + ClipOffs + ))) + { + PDWORD lpStringOffs, lpClipOffs; + STRING_TABLEPTR lpST; + + LockStringTable (hData, &lpST); + lpST->StringCount = n; + lpST->flags = 0; + if (ClipOffs) + lpST->flags |= HAS_SOUND_CLIPS; + + memcpy (&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)], strdata, StringOffs); + memcpy ((BYTE *)&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)] + StringOffs, + clipdata, ClipOffs); + ClipOffs = ((BYTE *)&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)] + - (BYTE *)lpST) + StringOffs; + StringOffs = ClipOffs - StringOffs; + + for (n = 0, lpStringOffs = lpST->StringOffsets, + lpClipOffs = &lpST->StringOffsets[lpST->StringCount + 1]; + n < (int)lpST->StringCount; ++n, ++lpStringOffs, ++lpClipOffs) + { + *lpStringOffs = StringOffs; + StringOffs += slen[n]; + if (lpST->flags & HAS_SOUND_CLIPS) + { + *lpClipOffs = ClipOffs; + ClipOffs += clen[n]; + } + } + *lpStringOffs = StringOffs; + if (lpST->flags & HAS_SOUND_CLIPS) + *lpClipOffs = ClipOffs; + + UnlockStringTable (hData); + } + + HFree (strdata); + + return (hData); + } + } + + hData = GetResourceData (fp, length, MEM_SOUND); + if (hData) + { + COUNT StringCount; + DWORD StringOffs; + PDWORD lpStringOffs; + STRING_TABLEPTR lpST; + + LockStringTable (hData, &lpST); +length = *(DWORD *)&lpST->StringCount; +dword_convert (&length, 1); +lpST->StringCount = (unsigned short)length; + StringCount = lpST->StringCount; + lpST->flags = 0; + + lpStringOffs = lpST->StringOffsets; +dword_convert (lpStringOffs, StringCount + 1); + StringOffs = sizeof (STRING_TABLE_DESC) + + (sizeof (DWORD) * StringCount); + do + { + StringOffs += *lpStringOffs; + *lpStringOffs++ = StringOffs; + } while (StringCount--); + + UnlockStringTable (hData); + } + + return (hData); +} + + diff --git a/sc2/src/sc2code/libs/strings/sfileins.c b/sc2/src/sc2code/libs/strings/sfileins.c new file mode 100644 index 000000000..821900e96 --- /dev/null +++ b/sc2/src/sc2code/libs/strings/sfileins.c @@ -0,0 +1,39 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "strintrn.h" + +STRING_TABLE +LoadStringTableFile (PVOID pStr) +{ + FILE *fp; + + fp = OpenResFile (pStr, "rb"); + if (fp) + { + MEM_HANDLE hData; + + hData = _GetStringData (fp, LengthResFile (fp)); + CloseResFile (fp); + + return (BUILD_STRING_TABLE (hData)); + } + + return (0); +} + diff --git a/sc2/src/sc2code/libs/strings/sresins.c b/sc2/src/sc2code/libs/strings/sresins.c new file mode 100644 index 000000000..29b0bb2e8 --- /dev/null +++ b/sc2/src/sc2code/libs/strings/sresins.c @@ -0,0 +1,41 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "strintrn.h" + +BOOLEAN +InstallStringTableResType (COUNT string_type) +{ + return (InstallResTypeVectors (string_type, + _GetStringData, FreeResourceData)); +} + +STRING_TABLE +LoadStringTableInstance (DWORD res) +{ + MEM_HANDLE hData; + + hData = GetResource (res); + if (hData) + { + DetachResource (res); + } + + return (BUILD_STRING_TABLE (hData)); +} + diff --git a/sc2/src/sc2code/libs/strings/strings.c b/sc2/src/sc2code/libs/strings/strings.c new file mode 100644 index 000000000..36e38b212 --- /dev/null +++ b/sc2/src/sc2code/libs/strings/strings.c @@ -0,0 +1,232 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "strintrn.h" + +BOOLEAN +DestroyStringTable (STRING_TABLE StringTable) +{ + return (FreeStringTable (StringTable)); +} + +STRING +CaptureStringTable (STRING_TABLE StringTable) +{ + if (StringTable != 0) + { + COUNT StringTableIndex; + STRING_TABLEPTR StringTablePtr; + + LockStringTable (StringTable, &StringTablePtr); + StringTableIndex = GetStringTableIndex (StringTable); + return (BUILD_STRING (StringTable, StringTableIndex)); + } + + return ((STRING)NULL_PTR); +} + +STRING_TABLE +ReleaseStringTable (STRING String) +{ + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) != 0) + UnlockStringTable (StringTable); + + return (StringTable); +} + +STRING_TABLE +GetStringTable (STRING String) +{ + return ((STRING_TABLE)LOWORD (String)); +} + +COUNT +GetStringTableCount (STRING String) +{ + COUNT StringCount; + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + StringCount = 0; + else + { + STRING_TABLEPTR StringTablePtr; + + LockStringTable (StringTable, &StringTablePtr); + StringCount = StringTablePtr->StringCount; + UnlockStringTable (StringTable); + } + + return (StringCount); +} + +COUNT +GetStringTableIndex (STRING String) +{ + return (STRING_INDEX (String)); +} + +STRING +SetAbsStringTableIndex (STRING String, COUNT StringTableIndex) +{ + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + String = 0; + else + { + STRING_TABLEPTR StringTablePtr; + + LockStringTable (StringTable, &StringTablePtr); + StringTableIndex = StringTableIndex % StringTablePtr->StringCount; + UnlockStringTable (StringTable); + + String = BUILD_STRING (StringTable, StringTableIndex); + } + + return (String); +} + +STRING +SetRelStringTableIndex (STRING String, SIZE StringTableOffs) +{ + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + String = 0; + else + { + STRING_TABLEPTR StringTablePtr; + COUNT StringTableIndex; + + LockStringTable (StringTable, &StringTablePtr); + while (StringTableOffs < 0) + StringTableOffs += StringTablePtr->StringCount; + StringTableIndex = (STRING_INDEX (String) + StringTableOffs) + % StringTablePtr->StringCount; + UnlockStringTable (StringTable); + + String = BUILD_STRING (StringTable, StringTableIndex); + } + + return (String); +} + +COUNT +GetStringLength (STRING String) +{ + COUNT StringLength; + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + StringLength = 0; + else + { + COUNT StringIndex; + STRING_TABLEPTR StringTablePtr; + + StringIndex = STRING_INDEX (String); + LockStringTable (StringTable, &StringTablePtr); + StringLength = (COUNT)( + StringTablePtr->StringOffsets[StringIndex + 1] + - StringTablePtr->StringOffsets[StringIndex] + ); + UnlockStringTable (StringTable); + } + + return (StringLength); +} + +STRINGPTR +GetStringSoundClip (STRING String) +{ + STRINGPTR StringAddr; + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + StringAddr = 0; + else + { + COUNT StringIndex; + STRING_TABLEPTR StringTablePtr; + + StringIndex = STRING_INDEX (String); + LockStringTable (StringTable, &StringTablePtr); + if (!(StringTablePtr->flags & HAS_SOUND_CLIPS) + || ((StringIndex += StringTablePtr->StringCount + 1), + StringTablePtr->StringOffsets[StringIndex + 1] + == StringTablePtr->StringOffsets[StringIndex])) + StringAddr = 0; + else + { + StringAddr = (STRINGPTR)StringTablePtr; + FAR_PTR_ADD (&StringAddr, StringTablePtr->StringOffsets[StringIndex]); + } + UnlockStringTable (StringTable); + } + + return (StringAddr); +} + +STRINGPTR +GetStringAddress (STRING String) +{ + STRINGPTR StringAddr; + STRING_TABLE StringTable; + + if ((StringTable = GetStringTable (String)) == 0) + StringAddr = 0; + else + { + COUNT StringIndex; + STRING_TABLEPTR StringTablePtr; + + StringIndex = STRING_INDEX (String); + LockStringTable (StringTable, &StringTablePtr); + StringAddr = (STRINGPTR)StringTablePtr; + FAR_PTR_ADD (&StringAddr, StringTablePtr->StringOffsets[StringIndex]); + UnlockStringTable (StringTable); + } + + return (StringAddr); +} + +BOOLEAN +GetStringContents (STRING String, STRINGPTR StringBuf, BOOLEAN + AppendSpace) +{ + STRINGPTR StringAddr; + COUNT StringLength; + + if ((StringAddr = GetStringAddress (String)) != 0 && + (StringLength = GetStringLength (String)) != 0) + { + memcpy (StringBuf, StringAddr, StringLength); + if (AppendSpace) + StringBuf[StringLength++] = ' '; + StringBuf[StringLength] = '\0'; + + return (TRUE); + } + + *StringBuf = '\0'; + return (FALSE); +} + diff --git a/sc2/src/sc2code/libs/strings/strintrn.h b/sc2/src/sc2code/libs/strings/strintrn.h new file mode 100644 index 000000000..aa002ed54 --- /dev/null +++ b/sc2/src/sc2code/libs/strings/strintrn.h @@ -0,0 +1,51 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINTRN_H +#define _STRINTRN_H + +#include +#include +#include "strlib.h" +#include "memlib.h" +#include "reslib.h" + +typedef struct string_table +{ + unsigned short StringCount; + unsigned short flags; + DWORD StringOffsets[1]; +} STRING_TABLE_DESC; +typedef STRING_TABLE_DESC *PSTRING_TABLE_DESC; + +#define HAS_SOUND_CLIPS (1 << 0) +#define STRING_TABLEPTR PSTRING_TABLE_DESC + +#define AllocStringTable(s) AllocResourceData((s),MEM_SOUND) +#define LockStringTable(h,ps) LockResourceData((MEM_HANDLE)LOWORD(h),ps) +#define UnlockStringTable(h) UnlockResourceData ((MEM_HANDLE)LOWORD(h)) +#define FreeStringTable(h) FreeResourceData ((MEM_HANDLE)LOWORD(h)) + +#define STRING_INDEX(S) ((COUNT)HIWORD (S)) +#define BUILD_STRING(h,i) ((STRING_TABLE)MAKE_DWORD(h,i)) +#define BUILD_STRING_TABLE(h) (STRING_TABLE)(h) + +extern MEM_HANDLE _GetStringData (FILE *fp, DWORD length); + +#endif /* _STRINTRN_H */ + diff --git a/sc2/src/sc2code/libs/strlib.h b/sc2/src/sc2code/libs/strlib.h new file mode 100644 index 000000000..bb123bf90 --- /dev/null +++ b/sc2/src/sc2code/libs/strlib.h @@ -0,0 +1,48 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRLIB_H +#define _STRLIB_H + +#include "compiler.h" + +typedef DWORD STRING_TABLE; +typedef DWORD STRING; +typedef PBYTE STRINGPTR; + +extern BOOLEAN InstallStringTableResType (COUNT string_type); +extern STRING_TABLE LoadStringTableInstance (DWORD res); +extern STRING_TABLE LoadStringTableFile (PVOID pStr); +extern BOOLEAN DestroyStringTable (STRING_TABLE StringTable); +extern STRING CaptureStringTable (STRING_TABLE StringTable); +extern STRING_TABLE ReleaseStringTable (STRING String); +extern STRING_TABLE GetStringTable (STRING String); +extern COUNT GetStringTableCount (STRING String); +extern COUNT GetStringTableIndex (STRING String); +extern STRING SetAbsStringTableIndex (STRING String, COUNT + StringTableIndex); +extern STRING SetRelStringTableIndex (STRING String, SIZE + StringTableOffs); +extern COUNT GetStringLength (STRING String); +extern STRINGPTR GetStringAddress (STRING String); +extern STRINGPTR GetStringSoundClip (STRING String); +extern BOOLEAN GetStringContents (STRING String, STRINGPTR StringBuf, + BOOLEAN AppendSpace); + +#endif /* _STRLIB_H */ + diff --git a/sc2/src/sc2code/libs/timlib.h b/sc2/src/sc2code/libs/timlib.h new file mode 100644 index 000000000..910c326f7 --- /dev/null +++ b/sc2/src/sc2code/libs/timlib.h @@ -0,0 +1,47 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _TIMLIB_H +#define _TIMLIB_H + +#include "memlib.h" + +#define ONE_SECOND 120 + +typedef void *TASK; + +typedef void *SEMAPHORE; +typedef SEMAPHORE *PSEMAPHORE; + +typedef int (*TASK_FUNC) (void *Blah); +extern TASK AddTask (TASK_FUNC TaskFunc, COUNT TaskStack); +extern void DeleteTask (TASK Task); +extern DWORD SetSemaphore (PSEMAPHORE pSem); +extern void ClearSemaphore (PSEMAPHORE pSem); +extern void SuspendTasking (void); +extern void ResumeTasking (void); +extern DWORD SleepTask (DWORD wake_time); +#define TaskSwitch() SleepTask(0L) + +extern void InitTimer (void); +extern void UninitTimer (void); +extern DWORD GetTimeCounter (void); +extern void WaitVBlank (void); + +#endif /* _TIMLIB_H */ + diff --git a/sc2/src/sc2code/libs/vargs.h b/sc2/src/sc2code/libs/vargs.h new file mode 100644 index 000000000..0c45a070e --- /dev/null +++ b/sc2/src/sc2code/libs/vargs.h @@ -0,0 +1,45 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VARARGS_H +#define _VARARGS_H + +typedef char *vararg_list; +typedef char *vararg_dcl; +#define vararg_start(list,alist) (list) = (vararg_list)&(alist) +#define vararg_end(list) +#define vararg_val(list,type) \ + (sizeof (type) >= sizeof (int) ? \ + (((type *)((list) += sizeof (type)))[-1]) : \ + ((type)((int *)((list) += sizeof (int)))[-1])) +#define vararg_farval(list,type) \ + (sizeof (type) >= sizeof (int) ? \ + (((type *)((list) += sizeof (type)))[-1]) : \ + (((int *)((list) += sizeof (int)))[-1])) +#define begin_arg_stack(name) char name[0 +#define add_to_arg_stack(type) + (sizeof (type) > sizeof (int) ? \ + sizeof (type) : sizeof (int)) +#define end_arg_stack ]; +#define arg_stack_push(list,type,val) \ + (sizeof (type) >= sizeof (int) ? \ + (((type *)((list) += sizeof (type)))[-1] = (val)) : \ + (((int *)((list) += sizeof (int)))[-1] = (int)(val))) + + +#endif /* _VARARGS_H */ + diff --git a/sc2/src/sc2code/libs/video/Makefile.am b/sc2/src/sc2code/libs/video/Makefile.am new file mode 100644 index 000000000..a9d401ab2 --- /dev/null +++ b/sc2/src/sc2code/libs/video/Makefile.am @@ -0,0 +1,13 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libvideo.la +libvideo_la_SOURCES = vfileins.c + diff --git a/sc2/src/sc2code/libs/video/vfileins.c b/sc2/src/sc2code/libs/video/vfileins.c new file mode 100644 index 000000000..7c3843437 --- /dev/null +++ b/sc2/src/sc2code/libs/video/vfileins.c @@ -0,0 +1,29 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "vidlib.h" + +VIDEO_REF +LoadVideoFile (PVOID pStr) +{ + extern VIDEO_REF _init_video_file (PVOID pStr); + + return (_init_video_file (pStr)); +} + + diff --git a/sc2/src/sc2code/libs/vidlib.h b/sc2/src/sc2code/libs/vidlib.h new file mode 100644 index 000000000..5b686c56d --- /dev/null +++ b/sc2/src/sc2code/libs/vidlib.h @@ -0,0 +1,49 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VIDLIB_H +#define _VIDLIB_H + +#include "compiler.h" + +typedef enum +{ + NO_FMV = 0, + HARDWARE_FMV, + SOFTWARE_FMV +} VIDEO_TYPE; + +#define MODES_UNDEFINED ((BYTE)~0) + +typedef DWORD VIDEO_REF; + +extern BOOLEAN InitVideo (BOOLEAN UseCDROM); +extern void UninitVideo (void); + +extern BYTE SetVideoMode (BYTE new_mode); +extern BYTE GetVideoMode (void); + +extern VIDEO_REF LoadVideoFile (PVOID pStr); +extern BOOLEAN DestroyVideo (VIDEO_REF VideoRef); +extern VIDEO_TYPE VidPlay (VIDEO_REF VidRef, char *loopname, BOOLEAN + uninit); +extern void VidStop (void); +/* +extern BOOLEAN VidPlaying (void);*/ + +#endif /* _VIDLIB_H */ diff --git a/sc2/src/sc2code/load.c b/sc2/src/sc2code/load.c new file mode 100644 index 000000000..d3437883c --- /dev/null +++ b/sc2/src/sc2code/load.c @@ -0,0 +1,297 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "declib.h" + +ACTIVITY NextActivity; + +static void +LoadShipQueue (DECODE_REF fh, PQUEUE pQueue, BOOLEAN MakeQ) +{ + COUNT num_links; + + cread ((PBYTE)&num_links, sizeof (num_links), 1, fh); + if (num_links) + { + if (MakeQ) + InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT)); + + do + { + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + COUNT Index, Offset; + PBYTE Ptr; + + cread ((PBYTE)&Index, sizeof (Index), 1, fh); + + if (pQueue == &GLOBAL (avail_race_q)) + { + hStarShip = GetStarShipFromIndex (pQueue, Index); + Offset = 0; + } + else + { + hStarShip = CloneShipFragment (Index, pQueue, 0); + Offset = (PBYTE)&FragPtr->ShipInfo + - (PBYTE)&FragPtr->RaceDescPtr; + } + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); + Ptr = ((PBYTE)&FragPtr->ShipInfo) - Offset; + cread ((PBYTE)Ptr, + ((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, + 1, fh); + if (Offset == 0) + { + EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr; + + ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr; + Ptr = (PBYTE)&ExtFragPtr->ShipInfo.actual_strength; + cread ((PBYTE)Ptr, ((PBYTE)&ExtFragPtr[1]) - Ptr, 1, fh); + } + UnlockStarShip (pQueue, hStarShip); + } while (--num_links); + } +} + +BOOLEAN +LoadSummary (FILE *in_fp) +{ + SUMMARY_DESC S; + + return (ReadResFile (&S, sizeof (S), 1, in_fp) == sizeof (S)); +} + +BOOLEAN +LoadGame (COUNT which_game, SUMMARY_DESC *summary_desc) +{ + FILE *in_fp; + char buf[256]; + + sprintf (buf, "starcon2.%02u", which_game); + in_fp = OpenResFile (buf, "rb"); + if (in_fp) + { + FILE *fp; + DECODE_REF fh; + COUNT num_links; + TASK clock_task; + QUEUE event_q, encounter_q, avail_q, npc_q, player_q; + STAR_DESC SD; + ACTIVITY Activity; + + ReadResFile (buf, sizeof (*summary_desc), 1, in_fp); + + if (summary_desc == 0) + summary_desc = (SUMMARY_DESC *)buf; + else + { + memcpy (summary_desc, buf, sizeof (*summary_desc)); + CloseResFile (in_fp); + return (TRUE); + } + + GlobData.SIS_state = summary_desc->SS; + + if ((fh = copen (in_fp, FILE_STREAM, STREAM_READ)) == 0) + { + CloseResFile (in_fp); + return (FALSE); + } + + ReinitQueue (&GLOBAL (GameClock.event_q)); + ReinitQueue (&GLOBAL (encounter_q)); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + ReinitQueue (&GLOBAL (built_ship_q)); + + clock_task = GLOBAL (GameClock.clock_task); + event_q = GLOBAL (GameClock.event_q); + encounter_q = GLOBAL (encounter_q); + avail_q = GLOBAL (avail_race_q); + npc_q = GLOBAL (npc_built_ship_q); + player_q = GLOBAL (built_ship_q); + + memset ((PBYTE)&GLOBAL (GameState[0]), + 0, sizeof (GLOBAL (GameState))); + Activity = GLOBAL (CurrentActivity); + cread ((PBYTE)&GlobData.Game_state, sizeof (GlobData.Game_state), 1, fh); + NextActivity = GLOBAL (CurrentActivity); + GLOBAL (CurrentActivity) = Activity; + + GLOBAL (GameClock.clock_task) = clock_task; + GLOBAL (GameClock.event_q) = event_q; + GLOBAL (encounter_q) = encounter_q; + GLOBAL (avail_race_q) = avail_q; + GLOBAL (npc_built_ship_q) = npc_q; + GLOBAL (built_ship_q) = player_q; + + LoadShipQueue (fh, &GLOBAL (avail_race_q), FALSE); + if (!(NextActivity & START_INTERPLANETARY)) + LoadShipQueue (fh, &GLOBAL (npc_built_ship_q), FALSE); + LoadShipQueue (fh, &GLOBAL (built_ship_q), FALSE); + + cread ((PBYTE)&num_links, sizeof (num_links), 1, fh); + { +#ifdef DEBUG +printf ("EVENTS:\n"); +#endif /* DEBUG */ + while (num_links--) + { + HEVENT hEvent; + EVENTPTR EventPtr; + + hEvent = AllocEvent (); + LockEvent (hEvent, &EventPtr); + + cread ((PBYTE)EventPtr, sizeof (*EventPtr), 1, fh); + +#ifdef DEBUG +printf ("\t%u/%u/%u -- %u\n", +EventPtr->month_index, +EventPtr->day_index, +EventPtr->year_index, +EventPtr->func_index); +#endif /* DEBUG */ + UnlockEvent (hEvent); + PutEvent (hEvent); + } + } + + cread ((PBYTE)&num_links, sizeof (num_links), 1, fh); + { + while (num_links--) + { + BYTE i, NumShips; + HENCOUNTER hEncounter; + ENCOUNTERPTR EncounterPtr; + + hEncounter = AllocEncounter (); + LockEncounter (hEncounter, &EncounterPtr); + + cread ((PBYTE)EncounterPtr, sizeof (*EncounterPtr), 1, fh); + EncounterPtr->hElement = 0; + NumShips = LONIBBLE (EncounterPtr->SD.Index); + for (i = 0; i < NumShips; ++i) + { + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR TemplatePtr; + + hStarShip = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), + EncounterPtr->SD.ShipList[i].var1 + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + EncounterPtr->SD.ShipList[i].race_strings = + TemplatePtr->ShipInfo.race_strings; + EncounterPtr->SD.ShipList[i].icons = + TemplatePtr->ShipInfo.icons; + EncounterPtr->SD.ShipList[i].melee_icon = + TemplatePtr->ShipInfo.melee_icon; + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + + UnlockEncounter (hEncounter); + PutEncounter (hEncounter); + } + } + + fp = OpenResFile (STARINFO_FILE, "wb"); + if (fp) + { + DWORD flen; + + cread ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + cread ((PBYTE)buf, num_bytes, 1, fh); + WriteResFile (buf, num_bytes, 1, fp); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + fp = OpenResFile (DEFGRPINFO_FILE, "wb"); + if (fp) + { + DWORD flen; + + cread ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + cread ((PBYTE)buf, num_bytes, 1, fh); + WriteResFile (buf, num_bytes, 1, fp); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + fp = OpenResFile (RANDGRPINFO_FILE, "wb"); + if (fp) + { + DWORD flen; + + cread ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + cread ((PBYTE)buf, num_bytes, 1, fh); + WriteResFile (buf, num_bytes, 1, fp); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + cread ((PBYTE)&SD, sizeof (SD), 1, fh); + + cclose (fh); + CloseResFile (in_fp); + + battle_counter = 0; + ReinitQueue (&race_q[0]); + ReinitQueue (&race_q[1]); + CurStarDescPtr = FindStar (NULL_PTR, &SD.star_pt, 0, 0); + if (!(NextActivity & START_ENCOUNTER) + && LOBYTE (NextActivity) == IN_INTERPLANETARY) + NextActivity |= START_INTERPLANETARY; + + GLOBAL (DisplayArray) = DisplayArray; + + return (TRUE); + } + + return (FALSE); +} + + diff --git a/sc2/src/sc2code/loadship.c b/sc2/src/sc2code/loadship.c new file mode 100644 index 000000000..86beee0fe --- /dev/null +++ b/sc2/src/sc2code/loadship.c @@ -0,0 +1,167 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "coderes.h" + +MEM_HANDLE +load_ship (STARSHIPPTR StarShipPtr, BOOLEAN LoadBattleData) +{ + BOOLEAN retval; + MEM_HANDLE h; + + h = OpenResourceIndexInstance (StarShipPtr->RaceResIndex); + + retval = FALSE; + if (h) + { +#define INITIAL_CODE_RES MAKE_RESOURCE (1, CODE, 0) + BYTE captains_name_index; + PVOID CodeRef; + MEM_HANDLE hOldIndex; + COUNT which_player; + + captains_name_index = StarShipCaptain (StarShipPtr); + which_player = StarShipPlayer (StarShipPtr); + hOldIndex = SetResourceIndex (h); + + CodeRef = CaptureCodeRes (LoadCodeRes (INITIAL_CODE_RES), + (PVOID)&GlobData, (PVOID)&StarShipPtr->RaceDescPtr, race_glue); + + if (CodeRef == 0) + goto BadLoad; + StarShipPtr->RaceDescPtr->CodeRef = CodeRef; + + if ((StarShipPtr->RaceDescPtr->ship_info.icons = + CaptureDrawable (LoadGraphic ( + (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.icons + ))) == 0) + /* goto BadLoad */; + + if ((StarShipPtr->RaceDescPtr->ship_info.melee_icon = + CaptureDrawable (LoadGraphic ( + (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.melee_icon + ))) == 0) + /* goto BadLoad */; + + if ((StarShipPtr->RaceDescPtr->ship_info.race_strings = + CaptureStringTable (LoadStringTable ( + (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.race_strings + ))) == 0) + /* goto BadLoad */; + + if (LoadBattleData) + { + DATA_STUFFPTR RawPtr; + + StarShipPtr->captains_name_index = captains_name_index; + StarShipPtr->RaceDescPtr->ship_info.ship_flags |= which_player; + + RawPtr = &StarShipPtr->RaceDescPtr->ship_data; + if (!load_animation (RawPtr->ship, + (RESOURCE)RawPtr->ship[0], + (RESOURCE)RawPtr->ship[1], + (RESOURCE)RawPtr->ship[2])) + goto BadLoad; + + if (RawPtr->weapon[0] != 0) + { + if (!load_animation (RawPtr->weapon, + (RESOURCE)RawPtr->weapon[0], + (RESOURCE)RawPtr->weapon[1], + (RESOURCE)RawPtr->weapon[2])) + goto BadLoad; + } + + if (RawPtr->special[0] != 0) + { + if (!load_animation (RawPtr->special, + (RESOURCE)RawPtr->special[0], + (RESOURCE)RawPtr->special[1], + (RESOURCE)RawPtr->special[2])) + goto BadLoad; + } + + if (RawPtr->captain_control.background + && (RawPtr->captain_control.background = + CaptureDrawable (LoadGraphic ( + (RESOURCE)RawPtr->captain_control.background + ))) == 0) + goto BadLoad; + + if (RawPtr->victory_ditty + && (RawPtr->victory_ditty = + LoadMusic ( + (RESOURCE)RawPtr->victory_ditty + )) == 0) + goto BadLoad; + + if (RawPtr->ship_sounds + && (RawPtr->ship_sounds = + CaptureSound (LoadSound ( + (RESOURCE)RawPtr->ship_sounds + ))) == 0) + goto BadLoad; + + if (StarShipPtr->RaceDescPtr->ship_info.icons) + StarShipPtr->silhouette = IncFrameIndex ( + StarShipPtr->RaceDescPtr->ship_info.icons + ); + } + + retval = TRUE; +BadLoad: + SetResourceIndex (hOldIndex); + CloseResourceIndex (h); + } + + return (retval); +} + +void +free_ship (STARSHIPPTR StarShipPtr, BOOLEAN FreeBattleData) +{ + if (FreeBattleData) + { + free_image (StarShipPtr->RaceDescPtr->ship_data.special); + free_image (StarShipPtr->RaceDescPtr->ship_data.weapon); + free_image (StarShipPtr->RaceDescPtr->ship_data.ship); + + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_data.captain_control.background)); + + DestroyMusic ((MUSIC_REF)StarShipPtr->RaceDescPtr->ship_data.victory_ditty); + + DestroySound (ReleaseSound ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds)); + } + + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.melee_icon)); + + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.icons)); + + DestroyStringTable (ReleaseStringTable ( + StarShipPtr->RaceDescPtr->ship_info.race_strings)); + + DestroyCodeRes (ReleaseCodeRes (StarShipPtr->RaceDescPtr->CodeRef)); + StarShipPtr->RaceDescPtr = 0; +} + + diff --git a/sc2/src/sc2code/master.c b/sc2/src/sc2code/master.c new file mode 100644 index 000000000..3acb324a0 --- /dev/null +++ b/sc2/src/sc2code/master.c @@ -0,0 +1,145 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "melee.h" + +QUEUE master_q; + +void +LoadMasterShipList (void) +{ + COUNT num_entries; + RES_TYPE rt; + RES_INSTANCE ri; + RES_PACKAGE rp; + +if (master_q.head != 0) + return; + + rt = GET_TYPE (ARILOU_SHIP_INDEX); + ri = GET_INSTANCE (ARILOU_SHIP_INDEX); + rp = GET_PACKAGE (ARILOU_SHIP_INDEX); + InitQueue (&master_q, num_entries = NUM_MELEE_SHIPS, sizeof (SHIP_FRAGMENT)); + while (num_entries--) + { + HSTARSHIP hBuiltShip; + + hBuiltShip = Build (&master_q, MAKE_RESOURCE (rp++, rt, ri++), 0, 0); + if (hBuiltShip) + { + char built_buf[30]; + HSTARSHIP hStarShip, hNextShip; + STARSHIPPTR BuiltShipPtr; + SHIP_INFOPTR ShipInfoPtr; + + TaskSwitch (); + + BuiltShipPtr = LockStarShip (&master_q, hBuiltShip); + load_ship (BuiltShipPtr, FALSE); + ShipInfoPtr = &((SHIP_FRAGMENTPTR)BuiltShipPtr)->ShipInfo; + *ShipInfoPtr = BuiltShipPtr->RaceDescPtr->ship_info; + BuiltShipPtr->RaceDescPtr->ship_info.melee_icon = 0; + BuiltShipPtr->RaceDescPtr->ship_info.icons = 0; + BuiltShipPtr->RaceDescPtr->ship_info.race_strings = 0; + free_ship (BuiltShipPtr, FALSE); + BuiltShipPtr->RaceDescPtr = (RACE_DESCPTR)ShipInfoPtr; + + GetStringContents (SetAbsStringTableIndex ( + BuiltShipPtr->RaceDescPtr->ship_info.race_strings, 2 + ), (STRINGPTR)built_buf, FALSE); + UnlockStarShip (&master_q, hBuiltShip); + + RemoveQueue (&master_q, hBuiltShip); + for (hStarShip = GetHeadLink (&master_q); + hStarShip; hStarShip = hNextShip) + { + char ship_buf[30]; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (StarShipPtr); + GetStringContents (SetAbsStringTableIndex ( + StarShipPtr->RaceDescPtr->ship_info.race_strings, 2 + ), (STRINGPTR)ship_buf, FALSE); + UnlockStarShip (&master_q, hStarShip); + + if (strcmp (built_buf, ship_buf) < 0) + break; + } + InsertQueue (&master_q, hBuiltShip, hStarShip); + } + } + + TaskSwitch (); +} + +void +FreeMasterShipList (void) +{ + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&master_q); + hStarShip != 0; hStarShip = hNextShip) + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (StarShipPtr); + + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.melee_icon)); + DestroyDrawable (ReleaseDrawable ( + StarShipPtr->RaceDescPtr->ship_info.icons)); + DestroyStringTable (ReleaseStringTable ( + StarShipPtr->RaceDescPtr->ship_info.race_strings)); + + UnlockStarShip (&master_q, hStarShip); + } + + UninitQueue (&master_q); +} + +HSTARSHIP +FindMasterShip (DWORD ship_ref) +{ + HSTARSHIP hStarShip; + + hStarShip = GetHeadLink (&master_q); + if (hStarShip) + { + do + { + DWORD ref; + HSTARSHIP hNextShip; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (StarShipPtr); + ref = StarShipPtr->RaceResIndex; + UnlockStarShip (&master_q, hStarShip); + + if (ref == ship_ref) + break; + + hStarShip = hNextShip; + } while (hStarShip); + } + + return (hStarShip); +} diff --git a/sc2/src/sc2code/melee.c b/sc2/src/sc2code/melee.c new file mode 100644 index 000000000..0bd29bf22 --- /dev/null +++ b/sc2/src/sc2code/melee.c @@ -0,0 +1,1830 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "starcon.h" +#include "melee.h" + +//Added by Chris + +#include "string.h" + +void ConfirmSaveLoad (STAMP *MsgStamp); + +BOOLEAN SaveProblem (void); + +void DoShipSpin (COUNT index, MUSIC_REF hMusic); + +BOOLEAN InitSpace (void); + +void UninitSpace (void); + +void InitGlobData (void); + +//End Added by Chris + +enum +{ + CONTROLS_TOP, + SAVE_TOP, + LOAD_TOP, + START_MELEE, + LOAD_BOT, + SAVE_BOT, + CONTROLS_BOT, + EDIT_MELEE +}; + +#define MELEE_X_OFFS 4 +#define MELEE_Y_OFFS 21 +#define MELEE_BOX_WIDTH 34 +#define MELEE_BOX_HEIGHT 34 +#define MELEE_BOX_SPACE 1 + +#define INFO_ORIGIN_X 3 +#define INFO_WIDTH 58 +#define TEAM_INFO_ORIGIN_Y 3 +#define TEAM_INFO_HEIGHT (SHIP_INFO_HEIGHT + 75) +#define MODE_INFO_ORIGIN_Y (TEAM_INFO_HEIGHT + 6) +#define MODE_INFO_HEIGHT ((STATUS_HEIGHT - 3) - MODE_INFO_ORIGIN_Y) +#define RACE_INFO_ORIGIN_Y (SHIP_INFO_HEIGHT + 6) +#define RACE_INFO_HEIGHT ((STATUS_HEIGHT - 3) - RACE_INFO_ORIGIN_Y) + +#define MELEE_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) +#define MELEE_TITLE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) +#define MELEE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) +#define MELEE_TEAM_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) + +#define STATE_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) +#define STATE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03) +#define ACTIVE_STATE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) +#define UNAVAILABLE_STATE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) +#define HI_STATE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) +#define HI_STATE_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) + +#define LIST_INFO_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05) +#define LIST_INFO_TITLE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) +#define LIST_INFO_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) +#define LIST_INFO_CURENTRY_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) +#define HI_LIST_INFO_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) +#define HI_LIST_INFO_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x1F), 0x0D) + +#define TEAM_NAME_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00) +#define TEAM_NAME_EDIT_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (23, 24, 29), 0x00) +#define TEAM_NAME_EDIT_RECT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05) +#define TEAM_NAME_EDIT_CURS_COLOR WHITE_COLOR + +FRAME PickMeleeFrame; +static FRAME MeleeFrame; +extern QUEUE master_q; +extern DWORD InTime; +PMELEE_STATE volatile pMeleeState; + +static BOOLEAN DoMelee (INPUT_STATE InputState, PMELEE_STATE pMS); +static BOOLEAN DoEdit (INPUT_STATE InputState, PMELEE_STATE pMS); +static BOOLEAN DoPickShip (INPUT_STATE InputState, PMELEE_STATE pMS); +static void DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState); +static BOOLEAN DoLoadTeam (INPUT_STATE InputState, PMELEE_STATE pMS); +static void DrawFileStrings (PMELEE_STATE pMS, int HiLiteState); + +static void +DrawMeleeIcon (COUNT which_icon) +{ + STAMP s; + + s.origin.x = s.origin.y = 0; + s.frame = SetAbsFrameIndex (MeleeFrame, which_icon); + DrawStamp (&s); +} + +static void +GetShipBox (PRECT pRect, COUNT side, COUNT row, COUNT col) +{ + pRect->corner.x = MELEE_X_OFFS + + (col * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE)); + pRect->corner.y = MELEE_Y_OFFS + + (side * (MELEE_Y_OFFS + MELEE_BOX_SPACE + + (NUM_MELEE_ROWS * (MELEE_BOX_HEIGHT + MELEE_BOX_SPACE)))) + + (row * (MELEE_BOX_HEIGHT + MELEE_BOX_SPACE)); + pRect->extent.width = MELEE_BOX_WIDTH; + pRect->extent.height = MELEE_BOX_HEIGHT; +} + +static void +DrawShipBox (PMELEE_STATE pMS, BOOLEAN HiLite) +{ + RECT r; + BYTE StarShip; + + GetShipBox (&r, pMS->side, pMS->row, pMS->col); + + BatchGraphics (); + StarShip = pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col]; + if (HiLite) + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x7, 0x00, 0xC), 0x3E), + BUILD_COLOR (MAKE_RGB15 (0xC, 0x00, 0x14), 0x3C), + (BOOLEAN)(StarShip != (BYTE)~0), BUILD_COLOR (MAKE_RGB15 (0xA, 0x00, 0x11), 0x3D)); + else + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x9), 0x56), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xE), 0x54), + (BOOLEAN)(StarShip != (BYTE)~0), BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xC), 0x55)); + + if (StarShip != (BYTE)~0) + { + STAMP s; + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + + hStarShip = GetStarShipFromIndex (&master_q, StarShip); + StarShipPtr = LockStarShip (&master_q, hStarShip); + s.origin.x = r.corner.x + (r.extent.width >> 1); + s.origin.y = r.corner.y + (r.extent.height >> 1); + s.frame = StarShipPtr->RaceDescPtr->ship_info.melee_icon; + + DrawStamp (&s); + UnlockStarShip (&master_q, hStarShip); + } + UnbatchGraphics (); +} + +static void +DrawControls (COUNT which_side, BOOLEAN HiLite) +{ + COUNT which_icon; + + if (PlayerControl[which_side] & HUMAN_CONTROL) + which_icon = 0; + else + { + switch (PlayerControl[which_side] + & (STANDARD_RATING | GOOD_RATING | AWESOME_RATING)) + { + case STANDARD_RATING: + which_icon = 1; + break; + case GOOD_RATING: + which_icon = 2; + break; + case AWESOME_RATING: + which_icon = 3; + break; + } + } + + DrawMeleeIcon (1 + (8 * (1 - which_side)) + (HiLite ? 4 : 0) + which_icon); +} + +static void +DrawPickFrame (PMELEE_STATE pMS) +{ + FRAME F; + RECT r, r0, r1, ship_r; + static void DrawMeleeShipStrings (PMELEE_STATE pMS, BYTE + NewStarShip); + + GetShipBox (&r0, 0, 0, 0), + GetShipBox (&r1, 1, NUM_MELEE_ROWS - 1, NUM_MELEE_COLUMNS - 1), + BoxUnion (&r0, &r1, &ship_r); + + F = SetAbsFrameIndex (MeleeFrame, 27); + GetFrameRect (F, &r); + r.corner.x = -(ship_r.corner.x + + ((ship_r.extent.width - r.extent.width) >> 1)); + if (pMS->side) + r.corner.y = -ship_r.corner.y; + else + r.corner.y = -(ship_r.corner.y + + (ship_r.extent.height - r.extent.height)); + SetFrameHot (F, MAKE_HOT_SPOT (r.corner.x, r.corner.y)); + DrawMeleeIcon (27); + ClearSemaphore (&GraphicsSem); + DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex); + SetSemaphore (&GraphicsSem); +} + +static void +RepairMeleeFrame (PRECT pRect) +{ + RECT r; + CONTEXT OldContext; + RECT OldRect; + + r.corner.x = pRect->corner.x + SAFE_X; + r.corner.y = pRect->corner.y + SAFE_Y; + r.extent = pRect->extent; + if (r.corner.y & 1) + { + --r.corner.y; + ++r.extent.height; + } + + OldContext = SetContext (SpaceContext); + GetContextClipRect (&OldRect); + SetContextClipRect (&r); + SetFrameHot (Screen, MAKE_HOT_SPOT (r.corner.x - SAFE_X, r.corner.y - SAFE_Y)); + BatchGraphics (); + + DrawMeleeIcon (0); + DrawMeleeIcon (26); + { + COUNT old_side, old_row, old_col; + + old_side = pMeleeState->side; + old_row = pMeleeState->row; + old_col = pMeleeState->col; + for (pMeleeState->side = 0; + pMeleeState->side < NUM_SIDES; + ++pMeleeState->side) + { + DrawControls (pMeleeState->side, FALSE); + for (pMeleeState->row = 0; + pMeleeState->row < NUM_MELEE_ROWS; + ++pMeleeState->row) + { + for (pMeleeState->col = 0; + pMeleeState->col < NUM_MELEE_COLUMNS; + ++pMeleeState->col) + DrawShipBox (pMeleeState, FALSE); + } + + DrawTeamString (pMeleeState, 0); + } + pMeleeState->side = old_side; + pMeleeState->row = old_row; + pMeleeState->col = old_col; + } + + if (pMeleeState->InputFunc == DoPickShip) + DrawPickFrame (pMeleeState); + + UnbatchGraphics (); + SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); + SetContextClipRect (&OldRect); + SetContext (OldContext); +} + +static void +DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) +{ + RECT r; + TEXT lfText; + + r.corner.x = MELEE_X_OFFS - 1; + r.corner.y = + (pMS->side + 1) + * (MELEE_Y_OFFS + + ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) + * NUM_MELEE_ROWS + 2)); + r.extent.width = NUM_MELEE_COLUMNS + * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE); + r.extent.height = 13; + if (HiLiteState == 4) + { + RepairMeleeFrame (&r); + return; + } + + if (HiLiteState & 1) + r.extent.width -= 29; + + SetContextFont (MicroFont); + + lfText.pStr = pMS->TeamImage[pMS->side].TeamName; + lfText.baseline.y = r.corner.y + r.extent.height - 3; + + lfText.baseline.x = r.corner.x + 1; + lfText.align = ALIGN_LEFT; + lfText.CharCount = wstrlen (lfText.pStr); // (COUNT)~0; + + BatchGraphics (); + if (!(HiLiteState & 1)) + { + TEXT rtText; + UNICODE buf[10]; + + wsprintf (buf, "%d", pMS->star_bucks[pMS->side]); + rtText.pStr = buf; + rtText.align = ALIGN_RIGHT; + rtText.CharCount = (COUNT)~0; + rtText.baseline.y = lfText.baseline.y; + rtText.baseline.x = lfText.baseline.x + r.extent.width - 1; + + SetContextForeGroundColor (HiLiteState == 0 + ? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR); + DrawText (&lfText); + DrawText (&rtText); + } + else + { + COUNT i; + RECT text_r; + BYTE char_deltas[MAX_TEAM_CHARS]; + PBYTE pchar_deltas; + + TextRect (&lfText, &text_r, char_deltas); + + text_r = r; + SetContextForeGroundColor (TEAM_NAME_EDIT_RECT_COLOR); + DrawFilledRectangle (&text_r); + + pchar_deltas = char_deltas; + for (i = pMS->CurIndex; i > 0; --i) + text_r.corner.x += (SIZE)*pchar_deltas++; + if (SerialInput) + { + if (pMS->CurIndex < lfText.CharCount) /* end of line */ + --text_r.corner.x; + text_r.extent.width = 1; + } + else + { + if (pMS->CurIndex == lfText.CharCount) /* end of line */ + text_r.extent.width = 1; + else + text_r.extent.width = (SIZE)*pchar_deltas; + } + ++text_r.corner.x; + ++text_r.corner.y; + text_r.extent.height -= 2; + SetContextForeGroundColor (TEAM_NAME_EDIT_CURS_COLOR); + DrawFilledRectangle (&text_r); + + SetContextForeGroundColor (BLACK_COLOR); // TEAM_NAME_EDIT_TEXT_COLOR); + DrawText (&lfText); + } + UnbatchGraphics (); +} + +static void +Deselect (BYTE opt) +{ + switch (opt) + { + case START_MELEE: + DrawMeleeIcon (25); + break; + case LOAD_TOP: + case LOAD_BOT: + if (pMeleeState->InputFunc != DoLoadTeam) + DrawMeleeIcon (opt == LOAD_TOP ? 17 : 22); + else + DrawFileStrings (pMeleeState, 0); + break; + case SAVE_TOP: + DrawMeleeIcon (18); + break; + case SAVE_BOT: + DrawMeleeIcon (21); + break; + case CONTROLS_TOP: + case CONTROLS_BOT: + { + COUNT which_side; + + which_side = opt == CONTROLS_TOP ? 1 : 0; + DrawControls (which_side, FALSE); + break; + } + case EDIT_MELEE: + if (pMeleeState->InputFunc == DoEdit) + { + if (pMeleeState->row < NUM_MELEE_ROWS) + DrawShipBox (pMeleeState, FALSE); + else if (pMeleeState->CurIndex == (BYTE)~0) + DrawTeamString (pMeleeState, 0); + } + else if (pMeleeState->InputFunc == DoPickShip) + { + STAMP s; + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + RECT r; + + GetFrameRect (SetAbsFrameIndex (MeleeFrame, 27), &r); + + hStarShip = GetStarShipFromIndex (&master_q, pMeleeState->CurIndex); + StarShipPtr = LockStarShip (&master_q, hStarShip); + s.origin.x = r.corner.x + 20 + + (pMeleeState->CurIndex % NUM_PICK_COLS) * 18; + s.origin.y = r.corner.y + 5 + + (pMeleeState->CurIndex / NUM_PICK_COLS) * 18; + s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + DrawStamp (&s); + UnlockStarShip (&master_q, hStarShip); + } + break; + } +} + +static void +Select (BYTE opt) +{ + switch (opt) + { + case START_MELEE: + DrawMeleeIcon (26); + break; + case LOAD_TOP: + case LOAD_BOT: + if (pMeleeState->InputFunc != DoLoadTeam) + DrawMeleeIcon (opt == LOAD_TOP ? 19 : 24); + else + DrawFileStrings (pMeleeState, 1); + break; + case SAVE_TOP: + DrawMeleeIcon (20); + break; + case SAVE_BOT: + DrawMeleeIcon (23); + break; + case CONTROLS_TOP: + case CONTROLS_BOT: + { + COUNT which_side; + + which_side = opt == CONTROLS_TOP ? 1 : 0; + DrawControls (which_side, TRUE); + break; + } + case EDIT_MELEE: + if (pMeleeState->InputFunc == DoEdit) + { + if (pMeleeState->row < NUM_MELEE_ROWS) + DrawShipBox (pMeleeState, TRUE); + else if (pMeleeState->CurIndex == (BYTE)~0) + DrawTeamString (pMeleeState, 2); + } + else if (pMeleeState->InputFunc == DoPickShip) + { + COLOR OldColor; + STAMP s; + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + RECT r; + + GetFrameRect (SetAbsFrameIndex (MeleeFrame, 27), &r); + + hStarShip = GetStarShipFromIndex (&master_q, pMeleeState->CurIndex); + StarShipPtr = LockStarShip (&master_q, hStarShip); + s.origin.x = r.corner.x + 20 + + (pMeleeState->CurIndex % NUM_PICK_COLS) * 18; + s.origin.y = r.corner.y + 5 + + (pMeleeState->CurIndex / NUM_PICK_COLS) * 18; + s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + OldColor = SetContextForeGroundColor (BLACK_COLOR); + DrawFilledStamp (&s); + SetContextForeGroundColor (OldColor); + UnlockStarShip (&master_q, hStarShip); + } + break; + } +} + +int flash_selection_func(void* blah) +{ + DWORD TimeIn; + + TimeIn = GetTimeCounter (); + for (;;) + { +#define FLASH_RATE (ONE_SECOND / 8) + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + Deselect (pMeleeState->MeleeOption); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + TimeIn = SleepTask (TimeIn + FLASH_RATE); + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + Select (pMeleeState->MeleeOption); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + TimeIn = SleepTask (TimeIn + FLASH_RATE); + } + + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static void +InitMelee (PMELEE_STATE pMS) +{ + RECT r; + + SetContext (SpaceContext); + SetContextFGFrame (Screen); + SetContextClipRect (NULL_PTR); + SetContextBackGroundColor (BLACK_COLOR); + ClearDrawable (); + r.corner.x = SAFE_X; + r.corner.y = SAFE_Y; + r.extent.width = SCREEN_WIDTH - (SAFE_X * 2); + r.extent.height = SCREEN_HEIGHT - (SAFE_Y * 2); + SetContextClipRect (&r); + + r.corner.x = r.corner.y = 0; + RepairMeleeFrame (&r); + + pMS->flash_task = AddTask (flash_selection_func, 2048); +} + +static void +DrawMeleeShipStrings (PMELEE_STATE pMS, BYTE NewStarShip) +{ + RECT r, OldRect; + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + + OldContext = SetContext (StatusContext); + GetContextClipRect (&OldRect); + r = OldRect; + r.corner.y += 76; + r.extent.height = SHIP_INFO_HEIGHT; + SetContextClipRect (&r); + BatchGraphics (); + + if (NewStarShip == (BYTE)~0) + { + RECT r; + TEXT t; + + ClearShipStatus (BAD_GUY_YOFFS); + SetContextFont (StarConFont); + r.corner.x = 3; + r.corner.y = 4; + r.extent.width = 57; + r.extent.height = 60; + SetContextForeGroundColor (BLACK_COLOR); + DrawRectangle (&r); + t.baseline.x = STATUS_WIDTH >> 1; + t.baseline.y = 32; + t.align = ALIGN_CENTER; + if (pMS->row < NUM_MELEE_ROWS) + { + t.pStr = GAME_STRING (MELEE_STRING_BASE + 0); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.pStr = GAME_STRING (MELEE_STRING_BASE + 1); + } + else + { + t.pStr = GAME_STRING (MELEE_STRING_BASE + 2); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.pStr = GAME_STRING (MELEE_STRING_BASE + 3); + } + t.baseline.y += TINY_TEXT_HEIGHT; + t.CharCount = (COUNT)~0; + DrawText (&t); + } + else + { + hStarShip = GetStarShipFromIndex (&master_q, NewStarShip); + StarShipPtr = LockStarShip (&master_q, hStarShip); + + InitShipStatus (StarShipPtr, NULL_PTR); + + UnlockStarShip (&master_q, hStarShip); + } + + UnbatchGraphics (); + SetContextClipRect (&OldRect); + SetContext (OldContext); + + ClearSemaphore (&GraphicsSem); +} + +static COUNT +GetTeamValue (TEAM_IMAGE *pTI) +{ + COUNT row, col, val; + + val = 0; + for (row = 0; row < NUM_MELEE_ROWS; ++row) + { + for (col = 0; col < NUM_MELEE_COLUMNS; ++col) + { + BYTE StarShip; + + if ((StarShip = pTI->ShipList[row][col]) != (BYTE)~0) + { + HSTARSHIP hStarShip; + + if ((hStarShip = GetStarShipFromIndex (&master_q, StarShip)) == 0) + pTI->ShipList[row][col] = (BYTE)~0; + else + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&master_q, hStarShip); + val += StarShipPtr->RaceDescPtr->ship_info.ship_cost; + UnlockStarShip (&master_q, hStarShip); + } + } + } + } + + return (val); +} + +static int +ReadTeamImage (TEAM_IMAGE *pTI, FILE *load_fp) +{ + return (ReadResFile (pTI, sizeof (*pTI), 1, load_fp) == 1 ? 0 : -1); +} + +static void +DrawFileStrings (PMELEE_STATE pMS, int HiLiteState) +{ +#define ENTRY_HEIGHT 32 + COORD y; + COUNT top, bot; + TEXT Text, rtText; + CONTEXT OldContext; + UNICODE buf[60]; + + Text.baseline.x = 5; + y = 34; + Text.align = ALIGN_LEFT; + + rtText.pStr = buf; + rtText.align = ALIGN_RIGHT; + rtText.baseline.x = Text.baseline.x + NUM_MELEE_COLUMNS + * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE) - 1; + + top = pMS->TopTeamIndex; + + if (HiLiteState == 1) + { + COUNT new_; + + new_ = pMS->CurIndex; + bot = pMS->BotTeamIndex; + + if (new_ < top || new_ > bot) + { + if (new_ < top) + top = new_; + else + top += new_ - bot; + pMS->TopTeamIndex = top; + + HiLiteState = -1; + } + } + + OldContext = SetContext (SpaceContext); + SetContextFont (MicroFont); + BatchGraphics (); + if (HiLiteState != -1) + { + bot = pMS->CurIndex - top; + Text.baseline.y = y + bot * ENTRY_HEIGHT; + Text.pStr = pMS->FileList[bot].TeamName; + Text.CharCount = (COUNT)~0; + SetContextForeGroundColor ( + HiLiteState == 0 + ? BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00) + : BUILD_COLOR (MAKE_RGB15 (23, 24, 29), 0x00) + ); + DrawText (&Text); + + rtText.baseline.y = Text.baseline.y; + wsprintf (buf, "%d", GetTeamValue (&pMS->FileList[bot])); + rtText.CharCount = (COUNT)~0; + DrawText (&rtText); + } + else + { + COUNT teams_left; + + DrawMeleeIcon (28); + + Text.baseline.y = y; + teams_left = (COUNT)( + GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - top + ); + if (teams_left) + { + bot = top - 1; + do + { + COUNT row, col; + STAMP s; + + if (++bot < NUM_PREBUILT) + pMS->FileList[bot - top] = pMS->PreBuiltList[bot]; + else + { + FILE *load_fp; + + GetDirEntryContents (SetAbsDirEntryTableIndex ( + pMS->TeamDE, bot - NUM_PREBUILT + ), (STRINGPTR)buf, FALSE); + load_fp = OpenResFile (buf, "rb"); + if (load_fp) + { + if (LengthResFile (load_fp) != sizeof (pMS->FileList[bot - top]) + || ReadTeamImage (&pMS->FileList[bot - top], load_fp) == -1) + pMS->FileList[bot - top] = pMS->PreBuiltList[0]; + CloseResFile (load_fp); + } + } + + { + Text.pStr = pMS->FileList[bot - top].TeamName; + Text.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00)); + DrawText (&Text); + + rtText.baseline.y = Text.baseline.y; + wsprintf (buf, "%d", GetTeamValue (&pMS->FileList[bot - top])); + rtText.CharCount = (COUNT)~0; + DrawText (&rtText); + } + + s.origin.x = Text.baseline.x + 1; + s.origin.y = Text.baseline.y + 4; + for (row = 0; row < NUM_MELEE_ROWS; ++row) + { + for (col = 0; col < NUM_MELEE_COLUMNS; ++col) + { + BYTE StarShip; + + if ((StarShip = pMS->FileList[bot - top].ShipList[row][col]) + != (BYTE)~0) + { + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + + hStarShip = GetStarShipFromIndex (&master_q, StarShip); + StarShipPtr = LockStarShip (&master_q, hStarShip); + s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + DrawStamp (&s); + s.origin.x += 18; + UnlockStarShip (&master_q, hStarShip); + } + } + } + + Text.baseline.y += ENTRY_HEIGHT; + } while (--teams_left && bot - top < MAX_VIS_TEAMS - 1); + pMS->BotTeamIndex = bot; + } + } + UnbatchGraphics (); + SetContext (OldContext); +} + +static BOOLEAN +DoLoadTeam (INPUT_STATE InputState, PMELEE_STATE pMS) +{ + SIZE index; + + if (InputState & DEVICE_EXIT) + return (FALSE); + + if (!pMS->Initialized) + { + SetSemaphore (&GraphicsSem); + Select (pMS->MeleeOption); + if ((pMS->TopTeamIndex = pMS->CurIndex) == (COUNT)~0) + pMS->TopTeamIndex = pMS->CurIndex = 0; + else if (pMS->TopTeamIndex <= MAX_VIS_TEAMS / 2) + pMS->TopTeamIndex = 0; + else + pMS->TopTeamIndex -= MAX_VIS_TEAMS / 2; + + DrawFileStrings (pMS, -1); + pMS->Initialized = TRUE; + pMS->InputFunc = DoLoadTeam; + ClearSemaphore (&GraphicsSem); + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + if (!(InputState & DEVICE_BUTTON2)) + { + pMS->TeamImage[pMS->side] = pMS->FileList[ + pMS->CurIndex - pMS->TopTeamIndex + ]; + pMS->star_bucks[pMS->side] = + GetTeamValue (&pMS->TeamImage[pMS->side]); + } + + pMS->InputFunc = DoMelee; + { + RECT r; + + GetFrameRect (SetAbsFrameIndex (MeleeFrame, 28), &r); + SetSemaphore (&GraphicsSem); + RepairMeleeFrame (&r); + ClearSemaphore (&GraphicsSem); + } + InTime = GetTimeCounter (); + } + else + { + SIZE old_index, NewTop; + + NewTop = pMS->TopTeamIndex; + index = old_index = pMS->CurIndex; + if (GetInputYComponent (InputState) < 0) + { + if (index-- == 0) + index = 0; + + if (index < NewTop && (NewTop -= MAX_VIS_TEAMS) < 0) + NewTop = 0; + } + else if (GetInputYComponent (InputState) > 0) + { + if ((int)index < (int)GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - 1) + ++index; + + if ((int)index > (int)pMS->BotTeamIndex) + NewTop = index; + } + else if (InputState & DEVICE_LEFTSHIFT) + { + if ((index -= MAX_VIS_TEAMS) < 0) + index = NewTop = 0; + else + { + if ((NewTop -= MAX_VIS_TEAMS) < 0) + NewTop = 0; + } + } + else if (InputState & DEVICE_RIGHTSHIFT) + { + if ((int)(index += MAX_VIS_TEAMS) < + (int)(GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT)) + NewTop += MAX_VIS_TEAMS; + else + { + index = GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - 1; + if (index - (MAX_VIS_TEAMS - 1) > NewTop) + { + if ((NewTop = index - (MAX_VIS_TEAMS - 1)) < 0) + NewTop = 0; + } + } + } + + if (index != old_index) + { + SetSemaphore (&GraphicsSem); + if ((int)NewTop == (int)pMS->TopTeamIndex) + Deselect (pMS->MeleeOption); + else + { + pMS->TopTeamIndex = NewTop; + DrawFileStrings (pMS, -1); + } + pMS->CurIndex = index; + ClearSemaphore (&GraphicsSem); + } + } + + return (TRUE); +} + +static UWORD +DoTextEntry (PMELEE_STATE pMS, INPUT_STATE InputState) +{ + UWORD ch; + UNICODE *pStr, *pBaseStr; + COUNT len, max_chars; + + if (pMS->MeleeOption == EDIT_MELEE) + { + pBaseStr = pMS->TeamImage[pMS->side].TeamName; + max_chars = MAX_TEAM_CHARS; + } + + if (SerialInput) + { + ch = GetInputUNICODE (GetInputState (SerialInput)); + } + else + { + extern UWORD GetJoystickChar (INPUT_STATE InputState); + + ch = GetJoystickChar (InputState); + } + + pStr = &pBaseStr[pMS->CurIndex]; + len = wstrlen (pStr); + switch (ch) + { + case 0x7F: + if (len) + { + memmove (pStr, pStr + 1, len * sizeof (*pStr)); + len = (COUNT)~0; + } + break; + case '\b': + if (pMS->CurIndex) + { + memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); + --pMS->CurIndex; + + len = (COUNT)~0; + } + break; + default: + if (isprint (ch) && len + pStr - pBaseStr < (int)(max_chars)) + { + if (SerialInput) + { + memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); + *pStr++ = ch; + ++pMS->CurIndex; + } + else + { + *pStr = ch; + if (len == 0) + *(pStr + 1) = '\0'; + } + + len = (COUNT)~0; + } + break; + } + + if (len == (COUNT)~0) + DrawTeamString (pMS, 1); + else if (GetInputXComponent (InputState) < 0) + { + if (pMS->CurIndex) + { + --pMS->CurIndex; + DrawTeamString (pMS, 1); + } + } + else if (GetInputXComponent (InputState) > 0) + { + if (len) + { + ++pMS->CurIndex; + DrawTeamString (pMS, 1); + } + } + + return (ch); +} + +static int +WriteTeamImage (TEAM_IMAGE *pTI, FILE *save_fp) +{ + return (WriteResFile (pTI, sizeof (*pTI), 1, save_fp)); +} + +static void +LoadTeamList (PMELEE_STATE pMS, UNICODE *pbuf) +{ + COUNT num_entries; + +GetNewList: + DestroyDirEntryTable (ReleaseDirEntryTable (pMS->TeamDE)); + pMS->TeamDE = CaptureDirEntryTable ( + LoadDirEntryTable ("*.mle", &num_entries) + ); + + pMS->CurIndex = 0; + while (num_entries--) + { + int status; + FILE *load_fp; + TEAM_IMAGE TI; + UNICODE loc_buf[60]; + + GetDirEntryContents (pMS->TeamDE, (STRINGPTR)loc_buf, FALSE); + if ((load_fp = OpenResFile (loc_buf, "rb")) == 0) + status = -1; + else + { + if (LengthResFile (load_fp) != sizeof (TI)) + status = -1; + else + status = ReadTeamImage (&TI, load_fp); + CloseResFile (load_fp); + } + if (status == -1) + { + DeleteResFile (loc_buf); + goto GetNewList; + } + + if (pbuf && wstricmp (loc_buf, pbuf) == 0) + { + pMS->CurIndex = GetDirEntryTableIndex (pMS->TeamDE) + NUM_PREBUILT; + pbuf = 0; + } + pMS->TeamDE = SetRelDirEntryTableIndex (pMS->TeamDE, 1); + } + pMS->TeamDE = SetAbsDirEntryTableIndex (pMS->TeamDE, 0); +} + +static BOOLEAN +DoSaveTeam (PMELEE_STATE pMS) +{ + STAMP MsgStamp; + UNICODE buf[60]; + FILE *save_fp; + CONTEXT OldContext; + +RetrySave: + SetSemaphore (&GraphicsSem); + OldContext = SetContext (ScreenContext); + ConfirmSaveLoad (&MsgStamp); + wsprintf (buf, "%s.mle", pMS->TeamImage[pMS->side].TeamName); + save_fp = OpenResFile (buf, "wb"); + if (save_fp) + { + BOOLEAN err; + + err = (BOOLEAN)(WriteTeamImage (&pMS->TeamImage[pMS->side], save_fp) == 0); + if (CloseResFile (save_fp) == 0) + err = TRUE; + if (err) + save_fp = 0; + } + + pMS->CurIndex = 0; + if (save_fp == 0) + { + DrawStamp (&MsgStamp); + DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + + DeleteResFile (buf); + if (SaveProblem ()) + goto RetrySave; + } + + LoadTeamList (pMS, buf); + + if (save_fp) + { + DrawStamp (&MsgStamp); + DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + } + + return (save_fp != 0); +} + +static BOOLEAN +DoEdit (INPUT_STATE InputState, PMELEE_STATE pMS) +{ + if (InputState & DEVICE_EXIT) + return (FALSE); + + if (!pMS->Initialized) + { + pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col]; + DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex); + + pMS->Initialized = TRUE; + pMS->InputFunc = DoEdit; + } + else if ((pMS->row < NUM_MELEE_ROWS || pMS->CurIndex == (BYTE)~0) + && ((InputState & DEVICE_BUTTON2) + || (GetInputXComponent (InputState) > 0 + && (pMS->col == NUM_MELEE_COLUMNS - 1 || pMS->row == NUM_MELEE_ROWS)))) + { + SetSemaphore (&GraphicsSem); + Deselect (EDIT_MELEE); + pMS->CurIndex = (COUNT)~0; + pMS->MeleeOption = START_MELEE; + pMS->InputFunc = DoMelee; + ClearSemaphore (&GraphicsSem); + InTime = GetTimeCounter (); + } + else if (pMS->row < NUM_MELEE_ROWS + && (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON3))) + { + if (InputState & DEVICE_BUTTON1) + pMS->Initialized = 0; + else + pMS->Initialized = -1; + DoPickShip (0, pMS); + } + else + { + COUNT side, row, col; + + side = pMS->side; + row = pMS->row; + col = pMS->col; + + if (row == NUM_MELEE_ROWS) + { + if (pMS->CurIndex != (BYTE)~0) + { + SetSemaphore (&GraphicsSem); + if (pMS->Initialized == 1 && SerialInput) + { + FlushInput (); + pMS->Initialized = 2; + } + else if ((SerialInput == 0 && (InputState & DEVICE_BUTTON2)) + || DoTextEntry (pMS, InputState) == '\n') + { + pMS->CurIndex = (BYTE)~0; + DrawTeamString (pMS, 4); + pMS->Initialized = 1; + } + ClearSemaphore (&GraphicsSem); + return (TRUE); + } + else if (InputState & DEVICE_BUTTON1) + { + pMS->CurIndex = 0; + SetSemaphore (&GraphicsSem); + DrawTeamString (pMS, 1); + ClearSemaphore (&GraphicsSem); + return (TRUE); + } + } + + { + if (GetInputXComponent (InputState) < 0) + { + if (col-- == 0) + col = 0; + } + else if (GetInputXComponent (InputState) > 0) + { + if (++col == NUM_MELEE_COLUMNS) + col = NUM_MELEE_COLUMNS - 1; + } + + if (GetInputYComponent (InputState) < 0) + { + if (row-- == 0) + { + if (side == 0) + row = 0; + else + { + row = NUM_MELEE_ROWS; + side = !side; + } + } + } + else if (GetInputYComponent (InputState) > 0) + { + if (row++ == NUM_MELEE_ROWS) + { + if (side == 1) + row = NUM_MELEE_ROWS; + else + { + row = 0; + side = !side; + } + } + } + } + + if (col != pMS->col || row != pMS->row || side != pMS->side) + { + SetSemaphore (&GraphicsSem); + Deselect (EDIT_MELEE); + pMS->side = side; + pMS->row = row; + pMS->col = col; + if (row == NUM_MELEE_ROWS) + pMS->CurIndex = (BYTE)~0; + else + pMS->CurIndex = pMS->TeamImage[side].ShipList[row][col]; + ClearSemaphore (&GraphicsSem); + + DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex)); + } + } + + return (TRUE); +} + +static BOOLEAN +DoPickShip (INPUT_STATE InputState, PMELEE_STATE pMS) +{ + STARSHIPPTR StarShipPtr; + + if (InputState & DEVICE_EXIT) + return (FALSE); + + if (pMS->Initialized <= 0) + { + if (pMS->CurIndex == (BYTE)~0 && pMS->Initialized == 0) + pMS->CurIndex = 0; + else if (pMS->CurIndex != (BYTE)~0) + { + RECT r; + HSTARSHIP hStarShip; + + hStarShip = GetStarShipFromIndex (&master_q, pMS->CurIndex); + StarShipPtr = LockStarShip (&master_q, hStarShip); + pMS->star_bucks[pMS->side] -= + StarShipPtr->RaceDescPtr->ship_info.ship_cost; + UnlockStarShip (&master_q, hStarShip); + + pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col] = (BYTE)~0; + + SetSemaphore (&GraphicsSem); + GetShipBox (&r, pMS->side, pMS->row, pMS->col); + RepairMeleeFrame (&r); + + DrawTeamString (pMS, 4); + ClearSemaphore (&GraphicsSem); + } + + if (pMS->Initialized == 0) + { + SetSemaphore (&GraphicsSem); + Deselect (EDIT_MELEE); + pMS->InputFunc = DoPickShip; + DrawPickFrame (pMS); + pMS->Initialized = TRUE; + ClearSemaphore (&GraphicsSem); + } + else + { + SetSemaphore (&GraphicsSem); + Deselect (EDIT_MELEE); + pMS->Initialized = TRUE; + if (++pMS->col == NUM_MELEE_COLUMNS) + { + if (++pMS->row < NUM_MELEE_ROWS) + pMS->col = 0; + else + { + pMS->col = NUM_MELEE_COLUMNS - 1; + pMS->row = NUM_MELEE_ROWS - 1; + } + } + pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col]; + ClearSemaphore (&GraphicsSem); + + DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex)); + } + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + pMS->InputFunc = 0; /* disable ship flashing */ + + if (!(InputState & DEVICE_BUTTON2)) + { + HSTARSHIP hStarShip; + + hStarShip = GetStarShipFromIndex (&master_q, pMS->CurIndex); + StarShipPtr = LockStarShip (&master_q, hStarShip); + pMS->star_bucks[pMS->side] += + StarShipPtr->RaceDescPtr->ship_info.ship_cost; + UnlockStarShip (&master_q, hStarShip); + + pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col] = pMS->CurIndex; + SetSemaphore (&GraphicsSem); + DrawTeamString (pMS, 4); + DrawShipBox (pMS, FALSE); + ClearSemaphore (&GraphicsSem); + if (++pMS->col == NUM_MELEE_COLUMNS) + { + if (++pMS->row < NUM_MELEE_ROWS) + pMS->col = 0; + else + { + pMS->col = NUM_MELEE_COLUMNS - 1; + pMS->row = NUM_MELEE_ROWS - 1; + } + } + } + + { + RECT r; + + GetFrameRect (SetAbsFrameIndex (MeleeFrame, 27), &r); + SetSemaphore (&GraphicsSem); + RepairMeleeFrame (&r); + ClearSemaphore (&GraphicsSem); + } + + pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col]; + DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex); + + pMS->InputFunc = DoEdit; + + return (TRUE); + } + else if (InputState & DEVICE_BUTTON3) + { + DoShipSpin (pMS->CurIndex, (MUSIC_REF)0); + + return (TRUE); + } + + { + BYTE NewStarShip; + + NewStarShip = pMS->CurIndex; + + if (GetInputXComponent (InputState) < 0) + { + if (NewStarShip-- % NUM_PICK_COLS == 0) + NewStarShip += NUM_PICK_COLS; + } + else if (GetInputXComponent (InputState) > 0) + { + if (++NewStarShip % NUM_PICK_COLS == 0) + NewStarShip -= NUM_PICK_COLS; + } + + if (GetInputYComponent (InputState) < 0) + { + if (NewStarShip >= NUM_PICK_COLS) + NewStarShip -= NUM_PICK_COLS; + else + NewStarShip += NUM_PICK_COLS * (NUM_PICK_ROWS - 1); + } + else if (GetInputYComponent (InputState) > 0) + { + if (NewStarShip < NUM_PICK_COLS * (NUM_PICK_ROWS - 1)) + NewStarShip += NUM_PICK_COLS; + else + NewStarShip -= NUM_PICK_COLS * (NUM_PICK_ROWS - 1); + } + + if (NewStarShip != pMS->CurIndex) + { + SetSemaphore (&GraphicsSem); + Deselect (EDIT_MELEE); + pMS->CurIndex = NewStarShip; + ClearSemaphore (&GraphicsSem); + DrawMeleeShipStrings (pMS, NewStarShip); + } + } + + return (TRUE); +} + +static void +LoadMeleeInfo (PMELEE_STATE pMS) +{ + PickMeleeFrame = CaptureDrawable ( + LoadGraphic (MELEE_PICK_MASK_PMAP_ANIM) + ); + MeleeFrame = CaptureDrawable ( + LoadGraphic (MELEE_SCREEN_PMAP_ANIM) + ); + + InitSpace (); + + LoadTeamList (pMS, 0); +} + +static void +FreeMeleeInfo (PMELEE_STATE pMS) +{ + if (pMS->flash_task) + { + SetSemaphore (&GraphicsSem); + DeleteTask (pMS->flash_task); + ClearSemaphore (&GraphicsSem); + pMS->flash_task = 0; + } + DestroyDirEntryTable (ReleaseDirEntryTable (pMS->TeamDE)); + pMS->TeamDE = 0; + + UninitSpace (); + + DestroyDrawable (ReleaseDrawable (MeleeFrame)); + MeleeFrame = 0; + DestroyDrawable (ReleaseDrawable (PickMeleeFrame)); + PickMeleeFrame = 0; +} + +static BOOLEAN +DoMelee (INPUT_STATE InputState, PMELEE_STATE pMS) +{ + if (InputState) + { + if (InputState & DEVICE_EXIT) + return (FALSE); + InTime = GetTimeCounter (); + } + + if (!pMS->Initialized) + { + pMS->Initialized = TRUE; + pMS->MeleeOption = START_MELEE; + SetSemaphore (&GraphicsSem); + InitMelee (pMS); + ClearSemaphore (&GraphicsSem); + { + BYTE clut_buf[] = {FadeAllToColor}; + + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); + } + InTime = GetTimeCounter (); + } + else if ((InputState & DEVICE_BUTTON2) + || GetInputXComponent (InputState) < 0) + { + SetSemaphore (&GraphicsSem); + Deselect (pMS->MeleeOption); + ClearSemaphore (&GraphicsSem); + pMS->MeleeOption = EDIT_MELEE; + pMS->Initialized = FALSE; + if (InputState & DEVICE_BUTTON2) + pMS->side = pMS->row = pMS->col = 0; + else + pMS->side = 0, + pMS->row = NUM_MELEE_ROWS - 1, + pMS->col = NUM_MELEE_COLUMNS - 1; + DoEdit (InputState, pMS); + } + else + { + MELEE_OPTIONS NewMeleeOption; + + NewMeleeOption = pMS->MeleeOption; + if (GetInputYComponent (InputState) < 0) + { + if (NewMeleeOption-- == CONTROLS_TOP) + NewMeleeOption = CONTROLS_TOP; + } + else if (GetInputYComponent (InputState) > 0) + { + if (NewMeleeOption++ == CONTROLS_BOT) + NewMeleeOption = CONTROLS_BOT; + } + + if ((PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL) + && GetTimeCounter () - InTime > ONE_SECOND * 10) + { + InputState = DEVICE_BUTTON1; + NewMeleeOption = START_MELEE; + } + + if (NewMeleeOption != pMS->MeleeOption) + { + SetSemaphore (&GraphicsSem); + Deselect (pMS->MeleeOption); + pMS->MeleeOption = NewMeleeOption; + Select (pMS->MeleeOption); + ClearSemaphore (&GraphicsSem); + } + + if (InputState & DEVICE_BUTTON1) + { + switch (pMS->MeleeOption) + { + case START_MELEE: + if (pMS->star_bucks[0] == 0 || pMS->star_bucks[1] == 0) + { + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 2), + 0, GAME_SOUND_PRIORITY); + break; + } + + if (pMS->flash_task) + { + SetSemaphore (&GraphicsSem); + DeleteTask (pMS->flash_task); + ClearSemaphore (&GraphicsSem); + pMS->flash_task = 0; + } + + { + BYTE black_buf[] = {FadeAllToBlack}; + + SleepTask (XFormColorMap ( + (COLORMAPPTR)black_buf, ONE_SECOND / 2 + ) + 2); + FlushColorXForms (); + } + do + { + COUNT i; + + SetContext (OffScreenContext); + for (i = 0; i < NUM_SIDES; ++i) + { + COUNT j, side; + + side = !i; + for (j = 0; j < NUM_MELEE_ROWS; ++j) + { + COUNT k; + + for (k = 0; k < NUM_MELEE_COLUMNS; ++k) + { + BYTE StarShip; + + if ((StarShip = pMS->TeamImage[i].ShipList[j][k]) != (BYTE)~0) + { + BYTE ship_cost; + HSTARSHIP hStarShip, hBuiltShip; + STARSHIPPTR StarShipPtr, + BuiltShipPtr; + + hStarShip = GetStarShipFromIndex (&master_q, StarShip); + StarShipPtr = LockStarShip ( + &master_q, hStarShip + ); + hBuiltShip = Build (&race_q[side], + StarShipPtr->RaceResIndex, + 1 << side, + NameCaptain (&race_q[side], StarShipPtr)); + ship_cost = StarShipPtr->RaceDescPtr-> + ship_info.ship_cost; + UnlockStarShip ( + &master_q, hStarShip + ); + + BuiltShipPtr = LockStarShip ( + &race_q[side], hBuiltShip + ); + BuiltShipPtr->ShipFacing = + (j * NUM_MELEE_COLUMNS) + k; + BuiltShipPtr->special_counter = ship_cost; + BuiltShipPtr->captains_name_index = + StarShipCaptain (BuiltShipPtr); + BuiltShipPtr->RaceDescPtr = + StarShipPtr->RaceDescPtr; + UnlockStarShip ( + &race_q[side], hBuiltShip + ); + } + } + } + } + + while (SoundPlaying ()) + ; + + SeedRandomNumbers (); + load_gravity_well ((BYTE)((COUNT)Random () % NUMBER_OF_PLANET_TYPES)); + Battle (); + free_gravity_well (); + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); + + { + BYTE black_buf[] = {FadeAllToBlack}; + + SleepTask (XFormColorMap ( + (COLORMAPPTR)black_buf, ONE_SECOND / 2 + ) + 2); + FlushColorXForms (); + } + } while (0 /* !(GLOBAL (CurrentActivity) & CHECK_ABORT) */); + GLOBAL (CurrentActivity) = SUPER_MELEE; + + pMS->Initialized = FALSE; + break; + case LOAD_TOP: + case LOAD_BOT: + pMS->Initialized = FALSE; + pMS->side = pMS->MeleeOption == LOAD_TOP ? 0 : 1; + DoLoadTeam (InputState, pMS); + break; + case SAVE_TOP: + case SAVE_BOT: + pMS->side = pMS->MeleeOption == SAVE_TOP ? 0 : 1; + if (pMS->star_bucks[pMS->side]) + DoSaveTeam (pMS); + else + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 2), + 0, GAME_SOUND_PRIORITY); + break; + case CONTROLS_TOP: + case CONTROLS_BOT: + { + COUNT which_side; + + which_side = pMS->MeleeOption == CONTROLS_TOP ? 1 : 0; + if (PlayerControl[which_side] & HUMAN_CONTROL) + PlayerControl[which_side] = COMPUTER_CONTROL | STANDARD_RATING; + else if (PlayerControl[which_side] & AWESOME_RATING) + PlayerControl[which_side] = HUMAN_CONTROL | STANDARD_RATING; + else + PlayerControl[which_side] = (( + PlayerControl[which_side] + & (STANDARD_RATING | GOOD_RATING | AWESOME_RATING) + ) << 1) | COMPUTER_CONTROL; + SetPlayerInput (); + DrawControls (which_side, TRUE); + break; + } + } + } + } + + return (TRUE); +} + +static void +InitPreBuilt (PMELEE_STATE pMS) +{ + wstrcpy (pMS->PreBuiltList[0].TeamName, GAME_STRING (MELEE_STRING_BASE + 4)); + pMS->PreBuiltList[0].ShipList[0][0] = MELEE_ANDROSYNTH; + pMS->PreBuiltList[0].ShipList[0][1] = MELEE_CHMMR; + pMS->PreBuiltList[0].ShipList[0][2] = MELEE_DRUUGE; + pMS->PreBuiltList[0].ShipList[0][3] = MELEE_URQUAN; + pMS->PreBuiltList[0].ShipList[0][4] = MELEE_MELNORME; + pMS->PreBuiltList[0].ShipList[0][5] = MELEE_ORZ; + pMS->PreBuiltList[0].ShipList[1][0] = MELEE_SPATHI; + pMS->PreBuiltList[0].ShipList[1][1] = MELEE_SYREEN; + pMS->PreBuiltList[0].ShipList[1][2] = MELEE_UTWIG; + pMS->PreBuiltList[0].ShipList[1][3] = (BYTE)~0; + pMS->PreBuiltList[0].ShipList[1][4] = (BYTE)~0; + pMS->PreBuiltList[0].ShipList[1][5] = (BYTE)~0; + + wstrcpy (pMS->PreBuiltList[1].TeamName, GAME_STRING (MELEE_STRING_BASE + 5)); + pMS->PreBuiltList[1].ShipList[0][0] = MELEE_ARILOU; + pMS->PreBuiltList[1].ShipList[0][1] = MELEE_CHENJESU; + pMS->PreBuiltList[1].ShipList[0][2] = MELEE_EARTHLING; + pMS->PreBuiltList[1].ShipList[0][3] = MELEE_KOHR_AH; + pMS->PreBuiltList[1].ShipList[0][4] = MELEE_MYCON; + pMS->PreBuiltList[1].ShipList[0][5] = MELEE_YEHAT; + pMS->PreBuiltList[1].ShipList[1][0] = MELEE_PKUNK; + pMS->PreBuiltList[1].ShipList[1][1] = MELEE_SUPOX; + pMS->PreBuiltList[1].ShipList[1][2] = MELEE_THRADDASH; + pMS->PreBuiltList[1].ShipList[1][3] = MELEE_ZOQFOTPIK; + pMS->PreBuiltList[1].ShipList[1][4] = MELEE_SHOFIXTI; + pMS->PreBuiltList[1].ShipList[1][5] = (BYTE)~0; + + wstrcpy (pMS->PreBuiltList[2].TeamName, GAME_STRING (MELEE_STRING_BASE + 6)); + pMS->PreBuiltList[2].ShipList[0][0] = MELEE_ANDROSYNTH; + pMS->PreBuiltList[2].ShipList[0][1] = MELEE_CHMMR; + pMS->PreBuiltList[2].ShipList[0][2] = MELEE_DRUUGE; + pMS->PreBuiltList[2].ShipList[0][3] = MELEE_MELNORME; + pMS->PreBuiltList[2].ShipList[0][4] = MELEE_EARTHLING; + pMS->PreBuiltList[2].ShipList[0][5] = MELEE_KOHR_AH; + pMS->PreBuiltList[2].ShipList[1][0] = MELEE_SUPOX; + pMS->PreBuiltList[2].ShipList[1][1] = MELEE_ORZ; + pMS->PreBuiltList[2].ShipList[1][2] = MELEE_SPATHI; + pMS->PreBuiltList[2].ShipList[1][3] = MELEE_ILWRATH; + pMS->PreBuiltList[2].ShipList[1][4] = MELEE_VUX; + pMS->PreBuiltList[2].ShipList[1][5] = (BYTE)~0; + + wstrcpy (pMS->PreBuiltList[3].TeamName, GAME_STRING (MELEE_STRING_BASE + 7)); + pMS->PreBuiltList[3].ShipList[0][0] = MELEE_CHENJESU; + pMS->PreBuiltList[3].ShipList[0][1] = MELEE_CHENJESU; + pMS->PreBuiltList[3].ShipList[0][2] = MELEE_CHMMR; + pMS->PreBuiltList[3].ShipList[0][3] = MELEE_CHMMR; + pMS->PreBuiltList[3].ShipList[0][4] = MELEE_KOHR_AH; + pMS->PreBuiltList[3].ShipList[0][5] = MELEE_KOHR_AH; + pMS->PreBuiltList[3].ShipList[1][0] = MELEE_URQUAN; + pMS->PreBuiltList[3].ShipList[1][1] = MELEE_URQUAN; + pMS->PreBuiltList[3].ShipList[1][2] = MELEE_UTWIG; + pMS->PreBuiltList[3].ShipList[1][3] = MELEE_UTWIG; + pMS->PreBuiltList[3].ShipList[1][4] = (BYTE)~0; + pMS->PreBuiltList[3].ShipList[1][5] = (BYTE)~0; + + wstrcpy (pMS->PreBuiltList[4].TeamName, GAME_STRING (MELEE_STRING_BASE + 8)); + pMS->PreBuiltList[4].ShipList[0][0] = MELEE_URQUAN; + pMS->PreBuiltList[4].ShipList[0][1] = MELEE_CHENJESU; + pMS->PreBuiltList[4].ShipList[0][2] = MELEE_MYCON; + pMS->PreBuiltList[4].ShipList[0][3] = MELEE_SYREEN; + pMS->PreBuiltList[4].ShipList[0][4] = MELEE_ZOQFOTPIK; + pMS->PreBuiltList[4].ShipList[0][5] = MELEE_SHOFIXTI; + pMS->PreBuiltList[4].ShipList[1][0] = MELEE_EARTHLING; + pMS->PreBuiltList[4].ShipList[1][1] = MELEE_KOHR_AH; + pMS->PreBuiltList[4].ShipList[1][2] = MELEE_MELNORME; + pMS->PreBuiltList[4].ShipList[1][3] = MELEE_DRUUGE; + pMS->PreBuiltList[4].ShipList[1][4] = MELEE_PKUNK; + pMS->PreBuiltList[4].ShipList[1][5] = MELEE_ORZ; +} + +void +Melee (void) +{ + InitGlobData (); + { + MELEE_STATE MenuState; + + pMeleeState = &MenuState; + memset (pMeleeState, 0, sizeof (*pMeleeState)); + + MenuState.InputFunc = DoMelee; + MenuState.Initialized = FALSE; + + MenuState.CurIndex = (COUNT)~0; + InitPreBuilt (&MenuState); + + GLOBAL (CurrentActivity) = SUPER_MELEE; + + GameSounds = CaptureSound (LoadSound (GAME_SOUNDS)); + LoadMeleeInfo (&MenuState); + { + FILE *load_fp; + + load_fp = OpenResFile ("melee.cfg", "rb"); + if (load_fp) + { + int status; + + if (LengthResFile (load_fp) != (1 + sizeof (TEAM_IMAGE)) * 2) + status = -1; + else if ((status = GetResFileChar (load_fp)) != -1) + { + PlayerControl[0] = (BYTE)status; + status = ReadTeamImage (&MenuState.TeamImage[0], load_fp); + if (status != -1) + { + if ((status = GetResFileChar (load_fp)) != -1) + { + PlayerControl[1] = (BYTE)status; + status = ReadTeamImage (&MenuState.TeamImage[1], load_fp); + } + } + } + CloseResFile (load_fp); + if (status == -1) + load_fp = 0; + } + + if (load_fp == 0) + { + PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; + MenuState.TeamImage[0] = MenuState.PreBuiltList[0]; + PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING; + MenuState.TeamImage[1] = MenuState.PreBuiltList[1]; + } + } + SetPlayerInput (); + + MenuState.side = 0; + MenuState.star_bucks[0] = GetTeamValue (&MenuState.TeamImage[0]); + MenuState.star_bucks[1] = GetTeamValue (&MenuState.TeamImage[1]); + DoInput ((PVOID)&MenuState); + + while (SoundPlaying ()) + ; + + { + FILE *save_fp; + BOOLEAN err; + + err = FALSE; + save_fp = OpenResFile ("melee.cfg", "wb"); + if (save_fp) + { + if (PutResFileChar (PlayerControl[0], save_fp) == -1) + err = TRUE; + if (!err && WriteTeamImage (&MenuState.TeamImage[0], save_fp) == 0) + err = TRUE; + if (!err && PutResFileChar (PlayerControl[1], save_fp) == -1) + err = TRUE; + if (!err && WriteTeamImage (&MenuState.TeamImage[1], save_fp) == 0) + err = TRUE; + if (CloseResFile (save_fp) == 0) + err = TRUE; + } + else + err = TRUE; + + if (err) + { + DeleteResFile ("melee.cfg"); + } + } + FreeMeleeInfo (&MenuState); + DestroySound (ReleaseSound (GameSounds)); + GameSounds = 0; + + FlushInput (); + } +} + diff --git a/sc2/src/sc2code/melee.h b/sc2/src/sc2code/melee.h new file mode 100644 index 000000000..994c69c35 --- /dev/null +++ b/sc2/src/sc2code/melee.h @@ -0,0 +1,101 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MELEE_H +#define _MELEE_H + +enum +{ + MELEE_ANDROSYNTH, + MELEE_ARILOU, + MELEE_CHENJESU, + MELEE_CHMMR, + MELEE_DRUUGE, + MELEE_EARTHLING, + MELEE_ILWRATH, + MELEE_KOHR_AH, + MELEE_MELNORME, + MELEE_MMRNMHRM, + MELEE_MYCON, + MELEE_ORZ, + MELEE_PKUNK, + MELEE_SHOFIXTI, + MELEE_SLYLANDRO, + MELEE_SPATHI, + MELEE_SUPOX, + MELEE_SYREEN, + MELEE_THRADDASH, + MELEE_UMGAH, + MELEE_URQUAN, + MELEE_UTWIG, + MELEE_VUX, + MELEE_YEHAT, + MELEE_ZOQFOTPIK, + + NUM_MELEE_SHIPS +}; + +#define NUM_MELEE_ROWS 2 +// #define NUM_MELEE_COLUMNS 7 +#define NUM_MELEE_COLUMNS 6 +#define ICON_WIDTH 16 +#define ICON_HEIGHT 16 + +extern FRAME PickMeleeFrame; + +#define PICK_BG_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x0F), 0x1) + +#define MAX_TEAM_CHARS 15 +#define MAX_VIS_TEAMS 5 +#define NUM_PREBUILT 5 +#define NUM_PICK_COLS 5 +#define NUM_PICK_ROWS 5 + +typedef BYTE MELEE_OPTIONS; + +typedef struct +{ + BYTE ShipList[NUM_MELEE_ROWS][NUM_MELEE_COLUMNS]; + UNICODE TeamName[MAX_TEAM_CHARS + 25]; /* in case default names in starcon.txt + are unknowingly mangled */ +} TEAM_IMAGE; + +typedef struct melee_state +{ + BOOLEAN (*InputFunc) (INPUT_STATE InputState, struct melee_state * + pInputState); + COUNT MenuRepeatDelay; + + BOOLEAN Initialized; + MELEE_OPTIONS MeleeOption; + DIRENTRY TeamDE; + COUNT TopTeamIndex, BotTeamIndex; + COUNT side, row, col; + TEAM_IMAGE TeamImage[NUM_SIDES]; + COUNT star_bucks[NUM_SIDES]; + COUNT CurIndex; + TASK flash_task; + TEAM_IMAGE FileList[MAX_VIS_TEAMS]; + TEAM_IMAGE PreBuiltList[NUM_PREBUILT]; +} MELEE_STATE; +typedef MELEE_STATE *PMELEE_STATE; + +extern PMELEE_STATE volatile pMeleeState; + +#endif /* _MELEE_H */ + diff --git a/sc2/src/sc2code/misc.c b/sc2/src/sc2code/misc.c new file mode 100644 index 000000000..ba8f4bcf5 --- /dev/null +++ b/sc2/src/sc2code/misc.c @@ -0,0 +1,399 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +spawn_planet (void) +{ + HELEMENT hPlanetElement; + + hPlanetElement = AllocElement (); + if (hPlanetElement) + { + POINT loc; + ELEMENTPTR PlanetElementPtr; + extern FRAME planet[]; + + LockElement (hPlanetElement, &PlanetElementPtr); + PlanetElementPtr->hit_points = 200; + PlanetElementPtr->state_flags = APPEARING; + PlanetElementPtr->life_span = NORMAL_LIFE + 1; + SetPrimType (&DisplayArray[PlanetElementPtr->PrimIndex], NO_PRIM); + PlanetElementPtr->current.image.farray = planet; + PlanetElementPtr->current.image.frame = + SetAbsFrameIndex (PlanetElementPtr->current.image.farray[0], 1); + PlanetElementPtr->collision_func = collision; + PlanetElementPtr->postprocess_func = + (void (*) (struct element *ElementPtr))CalculateGravity; + ZeroVelocityComponents (&PlanetElementPtr->velocity); + do + { + PlanetElementPtr->current.location.x = + WRAP_X (DISPLAY_ALIGN_X (Random ())); + PlanetElementPtr->current.location.y = + WRAP_Y (DISPLAY_ALIGN_Y (Random ())); + } while (CalculateGravity (PlanetElementPtr) + || TimeSpaceMatterConflict (PlanetElementPtr)); + loc = PlanetElementPtr->current.location; + PlanetElementPtr->mass_points = PlanetElementPtr->hit_points; + UnlockElement (hPlanetElement); + + PutElement (hPlanetElement); + hPlanetElement = AllocElement (); + if (hPlanetElement) + { + LockElement (hPlanetElement, &PlanetElementPtr); + PlanetElementPtr->hit_points = 1; + PlanetElementPtr->mass_points = PlanetElementPtr->hit_points; + PlanetElementPtr->state_flags = APPEARING | NONSOLID; + PlanetElementPtr->life_span = NORMAL_LIFE + 1; + SetPrimType (&DisplayArray[PlanetElementPtr->PrimIndex], STAMP_PRIM); + PlanetElementPtr->current.image.farray = planet; + PlanetElementPtr->current.image.frame = + PlanetElementPtr->current.image.farray[0]; + ZeroVelocityComponents (&PlanetElementPtr->velocity); + PlanetElementPtr->current.location = loc; + UnlockElement (hPlanetElement); + + PutElement (hPlanetElement); + } + } +} + +extern FRAME asteroid[]; + +static void +spawn_rubble (PELEMENT AsteroidElementPtr) +{ + HELEMENT hRubbleElement; + + hRubbleElement = AllocElement (); + if (hRubbleElement) + { + ELEMENTPTR RubbleElementPtr; + + PutElement (hRubbleElement); + LockElement (hRubbleElement, &RubbleElementPtr); + RubbleElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + RubbleElementPtr->life_span = 5; + RubbleElementPtr->turn_wait = RubbleElementPtr->next_turn = 0; + SetPrimType (&DisplayArray[RubbleElementPtr->PrimIndex], STAMP_PRIM); + RubbleElementPtr->current.image.farray = asteroid; + RubbleElementPtr->current.image.frame = + SetAbsFrameIndex (asteroid[0], ANGLE_TO_FACING (FULL_CIRCLE)); + RubbleElementPtr->current.location = AsteroidElementPtr->current.location; + RubbleElementPtr->preprocess_func = animation_preprocess; + RubbleElementPtr->death_func = spawn_asteroid; + UnlockElement (hRubbleElement); + } +} + +static void +asteroid_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT frame_index; + + frame_index = GetFrameIndex (ElementPtr->current.image.frame); + if (ElementPtr->thrust_wait & (1 << 7)) + --frame_index; + else + ++frame_index; + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + NORMALIZE_FACING (frame_index)); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = (unsigned char)(ElementPtr->thrust_wait & ((1 << 7) - 1)); + } +} + +void +spawn_asteroid (PELEMENT ElementPtr) +{ + HELEMENT hAsteroidElement; + + if ((hAsteroidElement = AllocElement ()) == 0) + { + if (ElementPtr != 0) + { + ElementPtr->state_flags &= ~DISAPPEARING; + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + ElementPtr->life_span = 1; + } + } + else + { + ELEMENTPTR AsteroidElementPtr; + COUNT val; + + LockElement (hAsteroidElement, &AsteroidElementPtr); + AsteroidElementPtr->hit_points = 1; + AsteroidElementPtr->mass_points = 3; + AsteroidElementPtr->state_flags = APPEARING; + AsteroidElementPtr->life_span = NORMAL_LIFE; + SetPrimType (&DisplayArray[AsteroidElementPtr->PrimIndex], STAMP_PRIM); + if ((val = (COUNT)Random ()) & (1 << 0)) + { + if (!(val & (1 << 1))) + AsteroidElementPtr->current.location.x = 0; + else + AsteroidElementPtr->current.location.x = LOG_SPACE_WIDTH; + AsteroidElementPtr->current.location.y = + WRAP_Y (DISPLAY_ALIGN_Y (Random ())); + } + else + { + AsteroidElementPtr->current.location.x = + WRAP_X (DISPLAY_ALIGN_X (Random ())); + if (!(val & (1 << 1))) + AsteroidElementPtr->current.location.y = 0; + else + AsteroidElementPtr->current.location.y = LOG_SPACE_HEIGHT; + } + + SetVelocityVector (&AsteroidElementPtr->velocity, + DISPLAY_TO_WORLD (((SIZE)Random () & 7) + 4), + (COUNT)Random ()); + AsteroidElementPtr->current.image.farray = asteroid; + AsteroidElementPtr->current.image.frame = + SetAbsFrameIndex (asteroid[0], + NORMALIZE_FACING (Random ())); + AsteroidElementPtr->turn_wait = + AsteroidElementPtr->thrust_wait = + (BYTE)Random () & (BYTE)((1 << 2) - 1); + AsteroidElementPtr->thrust_wait |= (BYTE)Random () & (BYTE)(1 << 7); + AsteroidElementPtr->preprocess_func = asteroid_preprocess; + AsteroidElementPtr->death_func = spawn_rubble; + AsteroidElementPtr->collision_func = collision; + UnlockElement (hAsteroidElement); + + PutElement (hAsteroidElement); + } +} + +void +do_damage (ELEMENTPTR ElementPtr, SIZE damage) +{ + if (ElementPtr->state_flags & PLAYER_SHIP) + { + if (!DeltaCrew (ElementPtr, -damage)) + { + ElementPtr->life_span = 0; + ElementPtr->state_flags |= NONSOLID; + } + } + else if (!GRAVITY_MASS (ElementPtr->mass_points)) + { + if ((BYTE)damage < ElementPtr->hit_points) + ElementPtr->hit_points -= (BYTE)damage; + else + { + ElementPtr->hit_points = 0; + ElementPtr->life_span = 0; + ElementPtr->state_flags |= NONSOLID; + } + } +} + +void +crew_preprocess (PELEMENT ElementPtr) +{ + HELEMENT hTarget; + + SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], + GetPrimColor (&DisplayArray[ElementPtr->PrimIndex]) + ^ BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + ElementPtr->state_flags |= CHANGING; + + if ((hTarget = ElementPtr->hTarget) == 0) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr && StarShipPtr->RaceDescPtr->ship_info.crew_level) + ElementPtr->hTarget = StarShipPtr->hShip; + else + { + COUNT facing; + + facing = 0; + TrackShip ((ELEMENTPTR)ElementPtr, &facing); + } + } + + if (hTarget) + { +#define CREW_DELTA SCALED_ONE + SIZE delta; + ELEMENTPTR ShipPtr; + + LockElement (hTarget, &ShipPtr); + delta = ShipPtr->current.location.x + - ElementPtr->current.location.x; + delta = WRAP_DELTA_X (delta); + if (delta > 0) + ElementPtr->next.location.x += CREW_DELTA; + else if (delta < 0) + ElementPtr->next.location.x -= CREW_DELTA; + + delta = ShipPtr->current.location.y - + ElementPtr->current.location.y; + delta = WRAP_DELTA_Y (delta); + if (delta > 0) + ElementPtr->next.location.y += CREW_DELTA; + else if (delta < 0) + ElementPtr->next.location.y -= CREW_DELTA; + UnlockElement (hTarget); + } +} + +void +crew_collision (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1) +{ + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && ElementPtr1->life_span >= NORMAL_LIFE + && ElementPtr0->hit_points > 0) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE)) + { + ProcessSound (SetAbsSoundIndex (GameSounds, GRAB_CREW)); + DeltaCrew ((ELEMENTPTR)ElementPtr1, 1); + } + } + + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + ElementPtr0->state_flags |= COLLISION | DISAPPEARING | NONSOLID; + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +void +AbandonShip (ELEMENTPTR ShipPtr, ELEMENTPTR TargetPtr, + COUNT crew_loss) +{ + SIZE dx, dy; + COUNT direction; + RECT r; + STARSHIPPTR StarShipPtr; + HELEMENT hCrew; + INTERSECT_CONTROL ShipIntersect; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) + return; + + ShipIntersect = ShipPtr->IntersectControl; + GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); + + if ((direction = GetVelocityTravelAngle ( + &ShipPtr->velocity)) == FULL_CIRCLE) + dx = dy = 0; + else + { +#define MORE_THAN_ENOUGH 100 + direction += HALF_CIRCLE; + dx = COSINE (direction, MORE_THAN_ENOUGH); + dy = SINE (direction, MORE_THAN_ENOUGH); + } + + while (crew_loss-- && (hCrew = AllocElement ())) + { +#define CREW_LIFE 300 + ELEMENTPTR CrewPtr; + + DeltaCrew (ShipPtr, -1); + + PutElement (hCrew); + LockElement (hCrew, &CrewPtr); + CrewPtr->hit_points = 1; + CrewPtr->state_flags = + APPEARING | FINITE_LIFE | CREW_OBJECT; + CrewPtr->life_span = CREW_LIFE; + SetPrimType (&DisplayArray[CrewPtr->PrimIndex], POINT_PRIM); + SetPrimColor (&DisplayArray[CrewPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); + CrewPtr->current.image.frame = DecFrameIndex (stars_in_space); + CrewPtr->current.image.farray = &stars_in_space; + CrewPtr->preprocess_func = crew_preprocess; + CrewPtr->collision_func = crew_collision; + + SetElementStarShip (CrewPtr, StarShipPtr); + + GetElementStarShip (TargetPtr, &StarShipPtr); + CrewPtr->hTarget = StarShipPtr->hShip; + + { + SIZE w, h; + INTERSECT_CONTROL CrewIntersect; + + ShipIntersect.IntersectStamp.origin = + ShipPtr->IntersectControl.EndPoint; + + w = (SIZE)((COUNT)Random () % r.extent.width); + h = (SIZE)((COUNT)Random () % r.extent.height); + CrewIntersect.EndPoint = ShipIntersect.EndPoint; + CrewIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); + if (dx == 0 && dy == 0) + { + CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); + CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); + CrewIntersect.IntersectStamp.origin = + TargetPtr->IntersectControl.EndPoint; + } + else + { + if (dx == 0) + CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); + else if (dx > 0) + CrewIntersect.EndPoint.x += w; + else + CrewIntersect.EndPoint.x -= w; + if (dy == 0) + CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); + else if (dy > 0) + CrewIntersect.EndPoint.y += h; + else + CrewIntersect.EndPoint.y -= h; + CrewIntersect.IntersectStamp.origin.x = + CrewIntersect.EndPoint.x + dx; + CrewIntersect.IntersectStamp.origin.y = + CrewIntersect.EndPoint.y + dy; + } + + DrawablesIntersect (&CrewIntersect, + &ShipIntersect, MAX_TIME_VALUE); + + CrewPtr->current.location.x = + DISPLAY_TO_WORLD (CrewIntersect.EndPoint.x); + CrewPtr->current.location.y = + DISPLAY_TO_WORLD (CrewIntersect.EndPoint.y); + } + UnlockElement (hCrew); + } +} + diff --git a/sc2/src/sc2code/nameref.h b/sc2/src/sc2code/nameref.h new file mode 100644 index 000000000..3f65b5c77 --- /dev/null +++ b/sc2/src/sc2code/nameref.h @@ -0,0 +1,36 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _NAMEREF_H +#define _NAMEREF_H + +#define LoadCodeRes(r) LoadCodeResInstance (r) +#define LoadColorMap(r) LoadColorMapInstance (r) +#define LoadStringTable(r) LoadStringTableInstance(r) +#define LoadSound(r) LoadSoundInstance(r) +#define LoadMusic(r) LoadMusicInstance(r) + +#define INIT_INSTANCES() \ + InstallGraphicResTypes (GFXRES, FONTRES); \ + InstallStringTableResType (STRTAB); \ + InstallAudioResTypes (SNDRES, MUSICRES); \ + InstallCodeResType (CODE) +#define UNINIT_INSTANCES() + +#endif /* _NAMEREF_H */ + diff --git a/sc2/src/sc2code/oscill.c b/sc2/src/sc2code/oscill.c new file mode 100644 index 000000000..c4ddc9fba --- /dev/null +++ b/sc2/src/sc2code/oscill.c @@ -0,0 +1,267 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//#include "Portfolio.h" //3DO Library we don't get access to +//#include "Init3DO.h" +//#include "Parse3DO.h" +//#include "Utils3DO.h" +//#include "filefunctions.h" +//#include "BlockFile.h" + +#include "SDL_wrapper.h" + +//Added by Chris + +#include "SDL/SDL.h" + +typedef Uint8 uint8; +typedef Uint8 uchar; +typedef Sint8 sint8; +typedef Uint16 uint16; +typedef Sint16 sint16; +typedef Uint32 uint32; +typedef Sint32 int32; +typedef Sint32 sint32; + +//End Added by Chris + +#define CEL_FLAGS \ + (CCB_SPABS | CCB_PPABS | CCB_YOXY | CCB_ACW | CCB_ACCW \ + | CCB_LDSIZE | CCB_CCBPRE | CCB_LDPRS | CCB_LDPPMP | CCB_ACE \ + | CCB_LCE | CCB_PLUTPOS | CCB_BGND | CCB_NPABS) + +#define PIXC_DUP(v) (((v) << PPMP_0_SHIFT) | ((v) << PPMP_1_SHIFT)) +#define PIXC_UNCODED16 (PIXC_DUP (PPMPC_MF_8 | PPMPC_SF_8)) +#define PIXC_CODED8 (PIXC_DUP (PPMPC_MS_PIN | PPMPC_SF_8)) + +#define NUMBER_OF_PLUTVALS 32 +#define NUMBER_OF_PLUT_UINT32s (NUMBER_OF_PLUTVALS >> 1) +#define GET_VAR_PLUT(i) (_varPLUTs + (i) * NUMBER_OF_PLUT_UINT32s) + +extern uint32 *_varPLUTs; + +#define NUM_THINGS 256 + +static CCB *plCCB; +static UBYTE flatline; + +void +//InitOscilloscope (int32 x, int32 y, int32 width, int32 height, FRAME_DESC *f) +InitOscilloscope (int32 x, int32 y, int32 width, int32 height, void *f) +{ +#if 0 + CCB *ccb; + int32 xpos, xerr; + uint32 *cel_plut; + extern CCB *GetCelArray (); + + cel_plut = GET_VAR_PLUT ((f->TypeIndexAndFlags >> 16) & 0xFF); + + plCCB = GetCelArray (); + + memset (plCCB, 0, sizeof (CCB) * (NUM_THINGS + 1)); + + ccb = plCCB; + ccb->ccb_Flags = CEL_FLAGS | CCB_PACKED | CCB_LDPLUT; + + ccb->ccb_HDX = 1 << 20; + ccb->ccb_HDY = 0; + ccb->ccb_VDX = 0; + ccb->ccb_VDY = 1 << 16; + + ccb->ccb_PIXC = PIXC_CODED8; + ccb->ccb_SourcePtr = (void *)((uchar *)f + f->DataOffs); + ccb->ccb_PLUTPtr = cel_plut; + ccb->ccb_Width = f->Bounds & 0xFFFF; + ccb->ccb_Height = (f->Bounds >> 16); + ccb->ccb_PRE0 = + PRE0_LITERAL | + ((ccb->ccb_Height - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT) | + (PRE0_BPP_8 << PRE0_BPP_SHIFT); + ccb->ccb_NextPtr = ccb + 1; + ++ccb; + + ccb->ccb_Width = y; + ccb->ccb_Height = height >> 1; + xpos = x; + xerr = NUM_THINGS; + do + { + int32 color; + + ccb->ccb_XPos = xpos << 16; + if ((xerr -= width) <= 0) + { + ++xpos; + xerr += NUM_THINGS; + } + ccb->ccb_HDX = 1 << 20; + ccb->ccb_VDY = 1 << 16; + + ccb->ccb_Flags = CEL_FLAGS; + ccb->ccb_PRE0 = + (PRE0_BPP_16 << PRE0_BPP_SHIFT) | + PRE0_BGND | + PRE0_LINEAR; + ccb->ccb_PRE1 = PRE1_TLLSB_PDC0; + ccb->ccb_PIXC = PIXC_UNCODED16; + + color = ((16 << 10) | (9 << 5) | 31) | 0x8000; + ccb->ccb_PLUTPtr = (void *)((color << 16) | color); + ccb->ccb_SourcePtr = (void *)&ccb->ccb_PLUTPtr; + + ccb->ccb_NextPtr = ccb + 1; + } while (++ccb != &plCCB[NUM_THINGS + 1]); +#endif + + flatline = 0; +} + +void +Oscilloscope (int32 grab_data) +{ +#if 0 + CCB *ccb; + signed char buf[NUM_THINGS * 2], *data; + int32 size, ypos, max; + + if (!grab_data + || !(size = GetSoundData (buf))) + { + if (flatline) + return; + + flatline = 1; + memset (buf, 0, sizeof (buf)); + } + else + flatline = 0; + + ccb = plCCB + 1; + max = ccb->ccb_Height; + ypos = ccb->ccb_Width + max; + data = buf; + do + { + ccb->ccb_YPos = (ypos + ((*data * max) >> 7)) << 16; +#ifndef READ_SAMPLE_DIRECTLY + data += 2; +#else + data++; +#endif + } while (++ccb != &plCCB[NUM_THINGS + 1]); + + add_cels (plCCB, ccb - 1); +// ClearDrawable (); + + FlushGraphics (TRUE); +#endif +} + +static CCB slider_cels[2]; + +void +InitSlider (int32 x, int32 y, int32 width, int32 height, + int32 bwidth, int32 bheight, void *f) +// int32 bwidth, int32 bheight, FRAME_DESC *f) +{ +#if 0 +#define SLIDER_X x +#define SLIDER_Y y +#define SLIDER_WIDTH width +#define SLIDER_HEIGHT height +#define BUTTON_WIDTH bwidth +#define BUTTON_HEIGHT bheight + int32 i; + CCB *ccb; + uint32 *cel_plut; + + cel_plut = GET_VAR_PLUT ((f->TypeIndexAndFlags >> 16) & 0xFF); + +slider_cels[0].ccb_Width = SLIDER_X; +slider_cels[0].ccb_Height = SLIDER_WIDTH; +slider_cels[0].ccb_SourcePtr = (void *)((uchar *)f + f->DataOffs); +slider_cels[1].ccb_Width = BUTTON_WIDTH; + + ccb = slider_cels; + for (i = 0; i < 2; i++, ccb++) + { + ccb->ccb_Flags = CEL_FLAGS | CCB_PACKED | CCB_LDPLUT; + + ccb->ccb_HDX = 1 << 20; + ccb->ccb_HDY = 0; + ccb->ccb_VDX = 0; + ccb->ccb_VDY = 1 << 16; + + ccb->ccb_PIXC = PIXC_CODED8; + ccb->ccb_PLUTPtr = cel_plut; + if (i == 0) + { + ccb->ccb_XPos = SLIDER_X << 16; + ccb->ccb_YPos = SLIDER_Y << 16; + ccb->ccb_PRE0 = + PRE0_LITERAL | + ((SLIDER_HEIGHT - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT) | + (PRE0_BPP_8 << PRE0_BPP_SHIFT); + } + else + { + ccb->ccb_XPos = SLIDER_X << 16; + ccb->ccb_YPos = (SLIDER_Y - ((BUTTON_HEIGHT - SLIDER_HEIGHT) >> 1)) << 16; + ccb->ccb_PRE0 = + PRE0_LITERAL | + ((BUTTON_HEIGHT - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT) | + (PRE0_BPP_8 << PRE0_BPP_SHIFT); + } + + ccb->ccb_NextPtr = ccb + 1; + } +#endif +} + +void +SetSliderImage (void *f) +//SetSliderImage (FRAME_DESC *f) +{ +#if 0 + slider_cels[1].ccb_SourcePtr = (void *)((uchar *)f + f->DataOffs); +#endif +} + +void +Slider (void) +{ +#if 0 +#undef SLIDER_X +#undef SLIDER_WIDTH +#undef BUTTON_WIDTH +#define SLIDER_X slider_cels[0].ccb_Width +#define SLIDER_WIDTH slider_cels[0].ccb_Height +#define BUTTON_WIDTH slider_cels[1].ccb_Width + int32 len, offs; + + if (GetSoundInfo (&len, &offs)) + { + if (offs > len) offs = len; + + slider_cels[1].ccb_XPos = (SLIDER_X + ((SLIDER_WIDTH - BUTTON_WIDTH) * offs / len)) << 16; + add_cels (slider_cels, &slider_cels[1]); + } +#endif +} + diff --git a/sc2/src/sc2code/outfit.c b/sc2/src/sc2code/outfit.c new file mode 100644 index 000000000..f98d2db8b --- /dev/null +++ b/sc2/src/sc2code/outfit.c @@ -0,0 +1,769 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void GetGaugeRect (PRECT pRect, BOOLEAN IsCrewRect); + +//End Added by Chris + +enum +{ + OUTFIT_FUEL, + OUTFIT_MODULES, + OUTFIT_SAVELOAD, + OUTFIT_EXIT, + OUTFIT_DOFUEL +}; + +static void +DrawModuleStrings (PMENU_STATE pMS, BYTE NewModule) +{ + RECT r; + STAMP s; + CONTEXT OldContext; + + OldContext = SetContext (StatusContext); + GetContextClipRect (&r); + s.origin.x = RADAR_X - r.corner.x; + s.origin.y = RADAR_Y - r.corner.y; + r.corner.x = s.origin.x - 1; + r.corner.y = s.origin.y - 11; + r.extent.width = RADAR_WIDTH + 2; + r.extent.height = 11; + BatchGraphics (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawFilledRectangle (&r); + if (NewModule >= EMPTY_SLOT) + { + r.corner = s.origin; + r.extent.width = RADAR_WIDTH; + r.extent.height = RADAR_HEIGHT; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); + DrawFilledRectangle (&r); + } + else if (pMS->CurFrame) + { + TEXT t; + UNICODE buf[10]; + + s.frame = SetAbsFrameIndex (pMS->CurFrame, NewModule); + DrawStamp (&s); + t.baseline.x = s.origin.x + RADAR_WIDTH - 2; + t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; + t.align = ALIGN_RIGHT; + t.CharCount = (COUNT)~0; + t.pStr = buf; + wsprintf (buf, "%u", GLOBAL (ModuleCost[NewModule]) * MODULE_COST_SCALE); + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); + DrawText (&t); + } + UnbatchGraphics (); + SetContext (OldContext); +} + +static void +RedistributeFuel (void) +{ + COUNT m; + DWORD FuelVolume; + RECT r; + + if ((FuelVolume = GLOBAL_SIS (FuelOnBoard)) <= FUEL_RESERVE) + return; + + GLOBAL_SIS (FuelOnBoard) = 0; + m = FUEL_VOLUME_PER_ROW; + + r.extent.width = 3; + r.extent.height = 1; + while (FuelVolume -= m) + { + GLOBAL_SIS (FuelOnBoard) += FUEL_VOLUME_PER_ROW; + GetFTankCapacity (&r.corner); + DrawPoint (&r.corner); + r.corner.x += r.extent.width + 1; + DrawPoint (&r.corner); + r.corner.x -= r.extent.width; + SetContextForeGroundColor (SetContextBackGroundColor (BLACK_COLOR)); + DrawFilledRectangle (&r); + if (FuelVolume < FUEL_VOLUME_PER_ROW) + m = (COUNT)FuelVolume; + } + + FuelVolume = GLOBAL_SIS (FuelOnBoard) + m; + + r.extent.width = 5; + while ((GLOBAL_SIS (FuelOnBoard) += FUEL_VOLUME_PER_ROW) < + GetFTankCapacity (&r.corner)) + { + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2E)); + DrawFilledRectangle (&r); + } + + GLOBAL_SIS (FuelOnBoard) = FuelVolume; +} + +#define LANDER_X 11 +#define LANDER_Y 67 +#define LANDER_WIDTH 15 + +static void +DisplayLanders (PMENU_STATE pMS) +{ + STAMP s; + + s.frame = pMS->ModuleFrame; + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) + { + s.origin.x = s.origin.y = 0; + s.frame = DecFrameIndex (s.frame); + DrawStamp (&s); + } + else + { + COUNT i; + + s.origin.x = LANDER_X; + s.origin.y = LANDER_Y; + for (i = 0; i < GLOBAL_SIS (NumLanders); ++i) + { + DrawStamp (&s); + s.origin.x += LANDER_WIDTH; + } + + SetContextForeGroundColor (BLACK_COLOR); + for (; i < MAX_LANDERS; ++i) + { + DrawFilledStamp (&s); + s.origin.x += LANDER_WIDTH; + } + } +} + +static BOOLEAN +DoInstallModule (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE NewState, new_slot_piece, old_slot_piece; + SIZE FirstItem, LastItem; + //STAMP s; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->InputFunc = DoOutfit; + return (TRUE); + } + + FirstItem = 0; + switch (NewState = pMS->CurState) + { + case PLANET_LANDER: + case EMPTY_SLOT + 3: + old_slot_piece = pMS->delta_item < GLOBAL_SIS (NumLanders) + ? PLANET_LANDER : (EMPTY_SLOT + 3); + LastItem = MAX_LANDERS - 1; + break; + case FUSION_THRUSTER: + case EMPTY_SLOT + 0: + old_slot_piece = + GLOBAL_SIS (DriveSlots[pMS->delta_item]); + LastItem = NUM_DRIVE_SLOTS - 1; + break; + case TURNING_JETS: + case EMPTY_SLOT + 1: + old_slot_piece = + GLOBAL_SIS (JetSlots[pMS->delta_item]); + LastItem = NUM_JET_SLOTS - 1; + break; + default: + old_slot_piece = + GLOBAL_SIS (ModuleSlots[pMS->delta_item]); + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) + FirstItem = NUM_BOMB_MODULES; + LastItem = NUM_MODULE_SLOTS - 1; + break; + } + + if (NewState < CREW_POD) + FirstItem = LastItem = NewState; + else if (NewState < EMPTY_SLOT) + FirstItem = CREW_POD, LastItem = NUM_PURCHASE_MODULES - 1; + + if (!pMS->Initialized) + { + new_slot_piece = old_slot_piece; + pMS->Initialized = TRUE; + + pMS->InputFunc = DoInstallModule; + + SetSemaphore (&GraphicsSem); + + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + SetFlashRect (NULL_PTR, (FRAME)0); + goto InitFlash; + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + new_slot_piece = pMS->CurState; + if (InputState & DEVICE_BUTTON1) + { + if (new_slot_piece < EMPTY_SLOT) + { + if (GLOBAL_SIS (ResUnits) < + (DWORD)(GLOBAL (ModuleCost[new_slot_piece]) + * MODULE_COST_SCALE)) + return (TRUE); + } + else if (new_slot_piece == EMPTY_SLOT + 2) + { + if (old_slot_piece == CREW_POD) + { + if (GLOBAL_SIS (CrewEnlisted) > CREW_POD_CAPACITY + * (CountSISPieces (CREW_POD) - 1)) + return (TRUE); + } + else if (old_slot_piece == FUEL_TANK + || old_slot_piece == HIGHEFF_FUELSYS) + { + DWORD volume; + + volume = (DWORD)CountSISPieces (FUEL_TANK) + * FUEL_TANK_CAPACITY + + (DWORD)CountSISPieces (HIGHEFF_FUELSYS) + * HEFUEL_TANK_CAPACITY; + volume -= (old_slot_piece == FUEL_TANK + ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY); + if (GLOBAL_SIS (FuelOnBoard) > volume + FUEL_RESERVE) + return (TRUE); + } + else if (old_slot_piece == STORAGE_BAY) + { + if (GLOBAL_SIS (TotalElementMass) > STORAGE_BAY_CAPACITY + * (CountSISPieces (STORAGE_BAY) - 1)) + return (TRUE); + } + } + } + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + + SetFlashRect (NULL_PTR, (FRAME)0); + + if (InputState & DEVICE_BUTTON1) + { + if (new_slot_piece >= EMPTY_SLOT && old_slot_piece >= EMPTY_SLOT) + { + new_slot_piece -= EMPTY_SLOT - 1; + if (new_slot_piece > CREW_POD) + new_slot_piece = PLANET_LANDER; + } + else + { + switch (pMS->CurState) + { + case PLANET_LANDER: + ++GLOBAL_SIS (NumLanders); + break; + case EMPTY_SLOT + 3: + --GLOBAL_SIS (NumLanders); + break; + case FUSION_THRUSTER: + case EMPTY_SLOT + 0: + GLOBAL_SIS (DriveSlots[pMS->delta_item]) = + new_slot_piece; + break; + case TURNING_JETS: + case EMPTY_SLOT + 1: + GLOBAL_SIS (JetSlots[pMS->delta_item]) = + new_slot_piece; + break; + default: + GLOBAL_SIS (ModuleSlots[pMS->delta_item]) = + new_slot_piece; + break; + } + + if (new_slot_piece < EMPTY_SLOT) + DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, + -(GLOBAL (ModuleCost[new_slot_piece]) + * MODULE_COST_SCALE)); + else /* if (old_slot_piece < EMPTY_SLOT) */ + DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, + GLOBAL (ModuleCost[old_slot_piece]) + * MODULE_COST_SCALE); + + if (WRAP_VAL (pMS->CurState, EMPTY_SLOT + 3) == PLANET_LANDER) + DisplayLanders (pMS); + else + { + DrawShipPiece (pMS, new_slot_piece, pMS->delta_item, FALSE); + + if (new_slot_piece > TURNING_JETS + && old_slot_piece > TURNING_JETS) + RedistributeFuel (); + } + } + + InputState &= ~DEVICE_BUTTON2; + } + + if (pMS->CurState < EMPTY_SLOT) + { + pMS->CurState += EMPTY_SLOT - 1; + if (pMS->CurState < EMPTY_SLOT) + pMS->CurState = EMPTY_SLOT + 3; + else if (pMS->CurState > EMPTY_SLOT + 2) + pMS->CurState = EMPTY_SLOT + 2; + if (InputState & DEVICE_BUTTON2) + new_slot_piece = pMS->CurState; + goto InitFlash; + } + else if (!(InputState & DEVICE_BUTTON2)) + { + pMS->CurState = new_slot_piece; + goto InitFlash; + } + else + { + SetContext (StatusContext); + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings (PM_FUEL, pMS->CurState = OUTFIT_MODULES); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + + pMS->InputFunc = DoOutfit; + ClearSISRect (DRAW_SIS_DISPLAY); + } + ClearSemaphore (&GraphicsSem); + } + else if (InputState) + { + SIZE NewItem; + + NewItem = NewState < EMPTY_SLOT ? pMS->CurState : pMS->delta_item; + do + { + SBYTE dy; + + dy = GetInputYComponent (InputState); + if (NewState >= EMPTY_SLOT && dy) + { + if (dy < 0) + { + if (NewState-- == EMPTY_SLOT) + NewState = EMPTY_SLOT + 3; + } + else + { + if (NewState++ == EMPTY_SLOT + 3) + NewState = EMPTY_SLOT; + } + NewItem = 0; + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) + { + if (NewState == EMPTY_SLOT + 3) + NewState = dy < 0 ? EMPTY_SLOT + 2 : EMPTY_SLOT; + if (NewState == EMPTY_SLOT + 2) + NewItem = NUM_BOMB_MODULES; + } + pMS->delta_item = NewItem; + } + else if (GetInputXComponent (InputState) < 0 || dy < 0) + { + if (NewItem-- == FirstItem) + NewItem = LastItem; + } + else if (GetInputXComponent (InputState) > 0 || dy > 0) + { + if (NewItem++ == LastItem) + NewItem = FirstItem; + } + } while (NewState < EMPTY_SLOT + && (GLOBAL (ModuleCost[NewItem]) == 0 + || (NewItem >= GUN_WEAPON && NewItem <= CANNON_WEAPON + && pMS->delta_item > 0 && pMS->delta_item < 13))); + + SetSemaphore (&GraphicsSem); + if (NewState < EMPTY_SLOT) + { + if (NewItem != pMS->CurState) + { + DrawModuleStrings (pMS, pMS->CurState = NewItem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + } + } + else if (NewItem != pMS->delta_item || NewState != pMS->CurState) + { + SIZE w; + + switch (NewState) + { + case PLANET_LANDER: + case EMPTY_SLOT + 3: + new_slot_piece = NewItem < GLOBAL_SIS (NumLanders) + ? PLANET_LANDER : (EMPTY_SLOT + 3); + break; + case FUSION_THRUSTER: + case EMPTY_SLOT + 0: + new_slot_piece = GLOBAL_SIS (DriveSlots[NewItem]); + break; + case TURNING_JETS: + case EMPTY_SLOT + 1: + new_slot_piece = GLOBAL_SIS (JetSlots[NewItem]); + break; + default: + new_slot_piece = GLOBAL_SIS (ModuleSlots[NewItem]); + break; + } + + SetContext (SpaceContext); + + if (NewState == pMS->CurState) + { + if (NewState == PLANET_LANDER || NewState == EMPTY_SLOT + 3) + w = LANDER_WIDTH; + else + w = SHIP_PIECE_OFFSET; + + w *= (NewItem - pMS->delta_item); + pMS->flash_rect0.corner.x += w; + pMS->delta_item = NewItem; + } + else + { + pMS->CurState = NewState; +InitFlash: + w = SHIP_PIECE_OFFSET; + switch (pMS->CurState) + { + case PLANET_LANDER: + case EMPTY_SLOT + 3: + pMS->flash_rect0.corner.x = LANDER_X - 1; + pMS->flash_rect0.corner.y = LANDER_Y - 1; + pMS->flash_rect0.extent.width = 11 + 2; + pMS->flash_rect0.extent.height = 13 + 2; + + w = LANDER_WIDTH; + break; + case FUSION_THRUSTER: + case EMPTY_SLOT + 0: + pMS->flash_rect0.corner.x = DRIVE_TOP_X - 1; + pMS->flash_rect0.corner.y = DRIVE_TOP_Y - 1; + pMS->flash_rect0.extent.width = 8; + pMS->flash_rect0.extent.height = 6; + + break; + case TURNING_JETS: + case EMPTY_SLOT + 1: + pMS->flash_rect0.corner.x = JET_TOP_X - 1; + pMS->flash_rect0.corner.y = JET_TOP_Y - 1; + pMS->flash_rect0.extent.width = 9; + pMS->flash_rect0.extent.height = 10; + + break; + default: + pMS->flash_rect0.corner.x = MODULE_TOP_X - 1; + pMS->flash_rect0.corner.y = MODULE_TOP_Y - 1; + pMS->flash_rect0.extent.width = 15; + pMS->flash_rect0.extent.height = 34; + + break; + } + + w *= pMS->delta_item; + pMS->flash_rect0.corner.x += w; + } + + DrawModuleStrings (pMS, new_slot_piece); + if (pMS->CurState < EMPTY_SLOT) + SetFlashRect ((PRECT)~0L, (FRAME)0); + else + SetFlashRect (&pMS->flash_rect0, (FRAME)0); + } + ClearSemaphore (&GraphicsSem); + } + + return (TRUE); +} + +BOOLEAN +DoOutfit (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + goto ExitOutfit; + + if (!pMS->Initialized) + { + pMS->InputFunc = DoOutfit; + pMS->Initialized = TRUE; + + { + COUNT num_frames; + STAMP s; + extern void DrawFlagshipName (BOOLEAN InStatusArea); + + pMS->CurFrame = CaptureDrawable ( + LoadGraphic (MODULES_PMAP_ANIM) + ); + pMS->hMusic = LoadMusicInstance (OUTFIT_MUSIC); + pMS->CurState = OUTFIT_FUEL; + pMS->ModuleFrame = CaptureDrawable ( + LoadGraphic (SISMODS_MASK_PMAP_ANIM) + ); + s.origin.x = s.origin.y = 0; + s.frame = CaptureDrawable ( + LoadGraphic (OUTFIT_PMAP_ANIM) + ); + + BatchGraphics (); + DrawSISFrame (); + DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 2)); + DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE)); + + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + + for (num_frames = 0; num_frames < NUM_DRIVE_SLOTS; ++num_frames) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (DriveSlots[num_frames])) < EMPTY_SLOT) + DrawShipPiece (pMS, which_piece, num_frames, FALSE); + } + for (num_frames = 0; num_frames < NUM_JET_SLOTS; ++num_frames) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (JetSlots[num_frames])) < EMPTY_SLOT) + DrawShipPiece (pMS, which_piece, num_frames, FALSE); + } + for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (ModuleSlots[num_frames])) < EMPTY_SLOT) + DrawShipPiece (pMS, which_piece, num_frames, FALSE); + } + + RedistributeFuel (); + DisplayLanders (pMS); + if (GET_GAME_STATE (CHMMR_BOMB_STATE) < 3) + { + BYTE ShieldFlags; + + ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); + + s.frame = SetAbsFrameIndex (pMS->ModuleFrame, + GetFrameCount (pMS->ModuleFrame) - 5); + if (ShieldFlags & (1 << EARTHQUAKE_DISASTER)) + DrawStamp ((PSTAMP)&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << BIOLOGICAL_DISASTER)) + DrawStamp ((PSTAMP)&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << LIGHTNING_DISASTER)) + DrawStamp ((PSTAMP)&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << LAVASPOT_DISASTER)) + DrawStamp ((PSTAMP)&s); + } + + DrawMenuStateStrings (PM_FUEL, pMS->CurState); + DrawFlagshipName (FALSE); + +{ + RECT r; + + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + ScreenTransition (3, &r); +} + PlayMusic (pMS->hMusic, TRUE, 1); + UnbatchGraphics (); + + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + GLOBAL_SIS (FuelOnBoard) = + (GLOBAL_SIS (FuelOnBoard) + + (FUEL_TANK_SCALE >> 1)) / FUEL_TANK_SCALE; + GLOBAL_SIS (FuelOnBoard) *= FUEL_TANK_SCALE; + } + + SetContext (StatusContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + } + else if ((InputState & DEVICE_BUTTON2) + || ((InputState & DEVICE_BUTTON1) + && pMS->CurState == OUTFIT_EXIT)) + { + if (pMS->CurState == OUTFIT_DOFUEL) + { + pMS->CurState = OUTFIT_FUEL; + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + else + { +ExitOutfit: + DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); + pMS->CurFrame = 0; + DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); + pMS->ModuleFrame = 0; + + return (FALSE); + } + } + else if (InputState & DEVICE_BUTTON1) + { + switch (pMS->CurState) + { + case OUTFIT_FUEL: + { + RECT r; + + pMS->CurState = OUTFIT_DOFUEL; + SetSemaphore (&GraphicsSem); + SetContext (StatusContext); + GetGaugeRect (&r, FALSE); + SetFlashRect (&r, (FRAME)0); + ClearSemaphore (&GraphicsSem); + break; + } + case OUTFIT_DOFUEL: + pMS->CurState = OUTFIT_FUEL; + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + break; + case OUTFIT_MODULES: + pMS->CurState = EMPTY_SLOT + 2; + if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) + pMS->delta_item = 0; + else + pMS->delta_item = NUM_BOMB_MODULES; + pMS->first_item.y = 0; + pMS->Initialized = 0; + DoInstallModule (InputState, pMS); + break; + case OUTFIT_SAVELOAD: + if (GameOptions () == 0) + goto ExitOutfit; + DrawMenuStateStrings (PM_FUEL, pMS->CurState); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + break; + } + } + else + { + BYTE NewState; + RECT r; + + r.extent.height = 1; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState == OUTFIT_DOFUEL) + { + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + if (GetFTankCapacity (&r.corner) > GLOBAL_SIS (FuelOnBoard) + && GLOBAL_SIS (ResUnits) >= + (DWORD)GLOBAL (FuelCost)) + { + if (GLOBAL_SIS (FuelOnBoard) >= + FUEL_RESERVE - FUEL_TANK_SCALE) + { + r.extent.width = 3; + DrawPoint (&r.corner); + r.corner.x += r.extent.width + 1; + DrawPoint (&r.corner); + r.corner.x -= r.extent.width; + SetContextForeGroundColor (SetContextBackGroundColor (BLACK_COLOR)); + DrawFilledRectangle (&r); + } + DeltaSISGauges (0, FUEL_TANK_SCALE, -GLOBAL (FuelCost)); + SetContext (StatusContext); + GetGaugeRect (&r, FALSE); + SetFlashRect (&r, (FRAME)0); + } + ClearSemaphore (&GraphicsSem); + } + else if (NewState-- == OUTFIT_FUEL) + NewState = OUTFIT_EXIT; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState == OUTFIT_DOFUEL) + { + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + if (GLOBAL_SIS (FuelOnBoard)) + { + DeltaSISGauges (0, -FUEL_TANK_SCALE, + GLOBAL (FuelCost)); + if (GLOBAL_SIS (FuelOnBoard) + % FUEL_VOLUME_PER_ROW == 0) + { + GetFTankCapacity (&r.corner); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2E)); + r.extent.width = 5; + DrawFilledRectangle (&r); + } + } + SetContext (StatusContext); + GetGaugeRect (&r, FALSE); + SetFlashRect (&r, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + else if (NewState++ == OUTFIT_EXIT) + NewState = OUTFIT_FUEL; + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_FUEL, NewState); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + diff --git a/sc2/src/sc2code/pickmele.c b/sc2/src/sc2code/pickmele.c new file mode 100644 index 000000000..0b2feda45 --- /dev/null +++ b/sc2/src/sc2code/pickmele.c @@ -0,0 +1,363 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "melee.h" + +#define NUM_MELEE_COLS_ORIG 6 +#define PICK_X_OFFS 57 +#define PICK_Y_OFFS 24 +#define PICK_SIDE_OFFS 100 + +#define NAME_AREA_HEIGHT 7 +#define MELEE_WIDTH 133 +#define MELEE_HEIGHT (48 + NAME_AREA_HEIGHT) + +static void +DrawMeleeFrame (STARSHIPPTR LastStarShipPtr, COUNT which_player) +{ + TEXT t; + UNICODE buf[10]; + STAMP s; + RECT r; + + GetFrameRect (PickMeleeFrame, &r); + r.corner.x = PICK_X_OFFS - 3; + r.corner.y = PICK_Y_OFFS - 9 + ((1 - which_player) * PICK_SIDE_OFFS); + + s.origin = r.corner; + s.frame = PickMeleeFrame; + DrawStamp (&s); + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + (r.extent.height - NAME_AREA_HEIGHT + 4); + r.corner.x += 2; + r.corner.y += 2; + r.extent.width -= (2 * 2) + (ICON_WIDTH + 2) + 1; + r.extent.height -= (2 * 2) + NAME_AREA_HEIGHT; + SetContextForeGroundColor (PICK_BG_COLOR); + DrawFilledRectangle (&r); + r.corner.x += 2; + r.extent.width += (ICON_WIDTH + 2) - (2 * 2); + r.corner.y += r.extent.height; + r.extent.height = NAME_AREA_HEIGHT; + DrawFilledRectangle (&r); + t.align = ALIGN_CENTER; + t.pStr = pMeleeState->TeamImage[which_player].TeamName; + t.CharCount = (COUNT)~0; + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x9)); + DrawText (&t); + + r.corner.x = PICK_X_OFFS - 3; + r.corner.y = PICK_Y_OFFS - 9 + ((1 - which_player) * PICK_SIDE_OFFS); + + wsprintf (buf, "%d", pMeleeState->star_bucks[which_player]); + t.baseline.x = r.corner.x + 4; + t.baseline.y = r.corner.y + 7; + t.align = ALIGN_LEFT; + t.pStr = buf; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x4, 0x5, 0x1F), 0x4B)); + DrawText (&t); + + if (LastStarShipPtr == 0 || LastStarShipPtr->special_counter == 0) + { + COUNT cur_bucks; + HSTARSHIP hBattleShip, hNextShip; + + cur_bucks = 0; + for (hBattleShip = GetHeadLink (&race_q[which_player]); + hBattleShip != 0; hBattleShip = hNextShip) + { + int col; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip); + if (StarShipPtr == LastStarShipPtr) + LastStarShipPtr->RaceResIndex = 0; + + col = StarShipPtr->ShipFacing; + s.origin.x = r.corner.x + 4 + + ((ICON_WIDTH + 2) * (col % NUM_MELEE_COLS_ORIG)); + s.origin.y = r.corner.y + 10 + + ((ICON_HEIGHT + 2) * (col / NUM_MELEE_COLS_ORIG)); + s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + DrawStamp (&s); + + if (StarShipPtr->RaceResIndex) + cur_bucks += StarShipPtr->special_counter; + else + { + extern FRAME status; + + --s.origin.x; + --s.origin.y; + s.frame = SetAbsFrameIndex (status, 3); + DrawStamp (&s); + } + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (&race_q[which_player], hBattleShip); + } + + r.extent.width -= 4; + t.baseline.x = r.corner.x + r.extent.width; + t.baseline.y = r.corner.y + 7; + r.corner.x += r.extent.width - (6 * 3); + r.corner.y += 2; + r.extent.width = (6 * 3); + r.extent.height = 7 - 2; + SetContextForeGroundColor (PICK_BG_COLOR); + DrawFilledRectangle (&r); + + wsprintf (buf, "%d", cur_bucks); + t.align = ALIGN_RIGHT; + t.pStr = buf; + t.CharCount = (COUNT)~0; + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)); + DrawText (&t); + } +} + +HSTARSHIP +GetMeleeStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player) +{ + COUNT ships_left, row, col; + DWORD NewTime, OldTime, LastTime; + INPUT_STATE OldInputState; + HSTARSHIP hBattleShip, hNextShip; + STARSHIPPTR StarShipPtr; + RECT flash_rect; + + if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) + return (0); + + SetContext (SpaceContext); + + DrawMeleeFrame (LastStarShipPtr, which_player); + + if (LOBYTE (battle_counter) == 0 || HIBYTE (battle_counter) == 0) + { + DWORD TimeOut; + INPUT_STATE PressState, ButtonState; + + DrawMeleeFrame (LastStarShipPtr, 1 - which_player); + + TimeOut = GetTimeCounter () + (ONE_SECOND * 4); + ClearSemaphore (&GraphicsSem); + + PressState = AnyButtonPress (TRUE); + do + { + ButtonState = AnyButtonPress (TRUE); + if (PressState) + { + PressState = ButtonState; + ButtonState = 0; + } + } while (!ButtonState + && (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL) + || TaskSwitch () < TimeOut)); + + if (ButtonState) + ButtonState = GetInputState (NormalInput); + if (ButtonState & DEVICE_EXIT) + ConfirmExit (); + + SetSemaphore (&GraphicsSem); + + return (0); + } + + if (LastStarShipPtr == 0 && which_player) + { + BYTE fade_buf[] = {FadeAllToColor}; + + SleepTask (XFormColorMap ( + (COLORMAPPTR)fade_buf, ONE_SECOND / 2 + ) + 2); + FlushColorXForms (); + } + + row = 0; + col = NUM_MELEE_COLS_ORIG; + if (which_player == 0) + ships_left = LOBYTE (battle_counter); + else + ships_left = HIBYTE (battle_counter); + + flash_rect.extent.width = (ICON_WIDTH + 2); + flash_rect.extent.height = (ICON_HEIGHT + 2); + + NewTime = OldTime = LastTime = GetTimeCounter (); + OldInputState = 0; + goto ChangeSelection; + for (;;) + { + INPUT_STATE InputState; + + NewTime = SleepTask (GetTimeCounter () + 1); + + if ((InputState = GetInputState (PlayerInput[which_player])) == 0) + InputState = GetInputState (ArrowInput); + if (InputState) + LastTime = NewTime; + else if (!(PlayerControl[1 - which_player] & PSYTRON_CONTROL) + && NewTime - LastTime >= ONE_SECOND * 3) + InputState = GetInputState (PlayerInput[1 - which_player]); + if (InputState & DEVICE_EXIT) + { + if (ConfirmExit ()) + { + hBattleShip = 0; + break; + } + continue; + } + + if (InputState == OldInputState + && NewTime - OldTime < (DWORD)MENU_REPEAT_DELAY) + InputState = 0; + else + { + OldInputState = InputState; + OldTime = NewTime; + } + + if (InputState & DEVICE_BUTTON1) + { + if (hBattleShip || (col == NUM_MELEE_COLS_ORIG && ConfirmExit ())) + { + GLOBAL (CurrentActivity) &= ~CHECK_ABORT; + break; + } + } + else + { + COUNT new_row, new_col; + + new_row = row; + new_col = col; + if (GetInputXComponent (InputState) < 0) + { + if (new_col-- == 0) + new_col = NUM_MELEE_COLS_ORIG; + } + else if (GetInputXComponent (InputState) > 0) + { + if (new_col++ == NUM_MELEE_COLS_ORIG) + new_col = 0; + } + if (GetInputYComponent (InputState) < 0) + { + if (new_row-- == 0) + new_row = NUM_MELEE_ROWS - 1; + } + else if (GetInputYComponent (InputState) > 0) + { + if (++new_row == NUM_MELEE_ROWS) + new_row = 0; + } + + if (new_row != row || new_col != col) + { + COUNT ship_index; + + row = new_row; + col = new_col; + + PlaySoundEffect (MenuSounds, 0, 0); + SetSemaphore (&GraphicsSem); +ChangeSelection: + flash_rect.corner.x = PICK_X_OFFS + + ((ICON_WIDTH + 2) * col); + flash_rect.corner.y = PICK_Y_OFFS + + ((ICON_HEIGHT + 2) * row) + + ((1 - which_player) * PICK_SIDE_OFFS); + SetFlashRect (&flash_rect, (FRAME)0); + + hBattleShip = GetHeadLink (&race_q[which_player]); + if (col == NUM_MELEE_COLS_ORIG) + { + if (row) + hBattleShip = 0; + else + { + ship_index = (COUNT)Random () % ships_left; + for (hBattleShip = GetHeadLink (&race_q[which_player]); + hBattleShip != 0; hBattleShip = hNextShip) + { + StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip); + if (StarShipPtr->RaceResIndex && ship_index-- == 0) + { + UnlockStarShip (&race_q[which_player], hBattleShip); + break; + } + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (&race_q[which_player], hBattleShip); + } + } + } + else + { + ship_index = (row * NUM_MELEE_COLS_ORIG) + col; + for (hBattleShip = GetHeadLink (&race_q[which_player]); + hBattleShip != 0; hBattleShip = hNextShip) + { + StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip); + if (StarShipPtr->ShipFacing == ship_index) + { + hNextShip = hBattleShip; + if (StarShipPtr->RaceResIndex == 0) + hBattleShip = 0; + UnlockStarShip (&race_q[which_player], hNextShip); + break; + } + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (&race_q[which_player], hBattleShip); + } + } + ClearSemaphore (&GraphicsSem); + } + } + } + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + + if (hBattleShip == 0) + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + else + { + StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip); + OwnStarShip (StarShipPtr, + 1 << which_player, StarShipPtr->captains_name_index); + StarShipPtr->captains_name_index = 0; + UnlockStarShip (&race_q[which_player], hBattleShip); + + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 1), 0, 0); + + while (ChannelPlaying (0)) + ; + } + + return (hBattleShip); +} + + diff --git a/sc2/src/sc2code/pickship.c b/sc2/src/sc2code/pickship.c new file mode 100644 index 000000000..000e77b1c --- /dev/null +++ b/sc2/src/sc2code/pickship.c @@ -0,0 +1,511 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +#define NUM_PICK_SHIP_ROWS 2 +#define NUM_PICK_SHIP_COLUMNS 6 + +#define ICON_WIDTH 16 +#define ICON_HEIGHT 16 + +#define FLAGSHIP_X_OFFS 65 +#define FLAGSHIP_Y_OFFS 4 +#define FLAGSHIP_WIDTH 22 +#define FLAGSHIP_HEIGHT 48 + +static BOOLEAN +DoPickBattleShip (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->CurFrame = 0; + return (FALSE); + } + + if (!pMS->Initialized) + { + pMS->Initialized = TRUE; + pMS->InputFunc = DoPickBattleShip; + + SetSemaphore (&GraphicsSem); + + goto ChangeSelection; + } + else if (InputState & DEVICE_BUTTON1) + { + if ((HSTARSHIP)pMS->CurFrame) + return (FALSE); + } + else + { + COORD new_row, new_col; + + new_col = pMS->first_item.x + GetInputXComponent (InputState); + new_row = pMS->first_item.y + GetInputYComponent (InputState); + if (new_row != pMS->first_item.y + || new_col != pMS->first_item.x) + { + RECT r; + TEXT t; + COUNT crew_level, max_crew; + COUNT ship_index; + HSTARSHIP hBattleShip, hNextShip; + STARSHIPPTR StarShipPtr; + + if (new_col < 0) + new_col = NUM_PICK_SHIP_COLUMNS; + else if (new_col > NUM_PICK_SHIP_COLUMNS) + new_col = 0; + + if (new_row < 0) + new_row = NUM_PICK_SHIP_ROWS - 1; + else if (new_row == NUM_PICK_SHIP_ROWS) + new_row = 0; + + SetSemaphore (&GraphicsSem); + +#ifdef NEVER + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x1D)); + DrawRectangle (&pMS->flash_rect0); +#endif /* NEVER */ + pMS->first_item.y = new_row; + pMS->first_item.x = new_col; + +ChangeSelection: + if (pMS->first_item.x == (NUM_PICK_SHIP_COLUMNS >> 1)) + { + pMS->flash_rect0.corner.x = pMS->flash_rect1.corner.x - 2 + FLAGSHIP_X_OFFS; + pMS->flash_rect0.corner.y = pMS->flash_rect1.corner.y - 2 + FLAGSHIP_Y_OFFS; + pMS->flash_rect0.extent.width = FLAGSHIP_WIDTH + 4; + pMS->flash_rect0.extent.height = FLAGSHIP_HEIGHT + 4; + + hBattleShip = GetTailLink (&race_q[0]); /* Flagship */ + } + else + { + new_col = pMS->first_item.x; + pMS->flash_rect0.corner.x = 5 + pMS->flash_rect1.corner.x - 2 + + ((ICON_WIDTH + 4) * new_col); + if (new_col > (NUM_PICK_SHIP_COLUMNS >> 1)) + { + --new_col; + pMS->flash_rect0.corner.x += FLAGSHIP_WIDTH - ICON_WIDTH; + } + pMS->flash_rect0.corner.y = 16 + pMS->flash_rect1.corner.y - 2 + + ((ICON_HEIGHT + 4) * pMS->first_item.y); + pMS->flash_rect0.extent.width = ICON_WIDTH + 4; + pMS->flash_rect0.extent.height = ICON_HEIGHT + 4; + + ship_index = (pMS->first_item.y * NUM_PICK_SHIP_COLUMNS) + + new_col; + + for (hBattleShip = GetHeadLink (&race_q[0]); + hBattleShip != GetTailLink (&race_q[0]); + hBattleShip = hNextShip) + { + StarShipPtr = LockStarShip (&race_q[0], hBattleShip); + if ((COUNT)LONIBBLE ( + StarShipPtr->RaceDescPtr->ship_info.var2 + ) == ship_index && StarShipPtr->RaceResIndex) + { + UnlockStarShip (&race_q[0], hBattleShip); + break; + } + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (&race_q[0], hBattleShip); + } + + if (hBattleShip == GetTailLink (&race_q[0])) + hBattleShip = 0; + } + + pMS->CurFrame = (FRAME)hBattleShip; + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = pMS->flash_rect1.corner.x + 6; + r.corner.y = pMS->flash_rect1.corner.y + 5; + r.extent.width = ((ICON_WIDTH + 4) * 3) - 4; + r.extent.height = 7; + DrawFilledRectangle (&r); + + if (hBattleShip == 0) + crew_level = 0; + else + { + SetContextFont (TinyFont); + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + (r.extent.height - 1); + t.align = ALIGN_CENTER; + + StarShipPtr = LockStarShip (&race_q[0], hBattleShip); + if (StarShipPtr->captains_name_index == 0) + { + t.pStr = GLOBAL_SIS (CommanderName); + t.CharCount = (COUNT)~0; + crew_level = GLOBAL_SIS (CrewEnlisted); + max_crew = GetCPodCapacity (NULL_PTR); + } + else + { + STRING locString; + + locString = SetAbsStringTableIndex ( + StarShipPtr->RaceDescPtr->ship_info.race_strings, + StarShipPtr->captains_name_index + ); + t.pStr = (UNICODE *)GetStringAddress (locString); + t.CharCount = GetStringLength (locString); + crew_level = StarShipPtr->RaceDescPtr->ship_info.crew_level; + max_crew = StarShipPtr->RaceDescPtr->ship_info.max_crew; + } + UnlockStarShip (&race_q[0], hBattleShip); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x0C)); + DrawText (&t); + SetContextForeGroundColor (BLACK_COLOR); + } + + r.corner.x += (ICON_WIDTH + 4) + * ((NUM_PICK_SHIP_COLUMNS >> 1) + 1) + + FLAGSHIP_WIDTH - ICON_WIDTH; + DrawFilledRectangle (&r); + + if (crew_level) + { + char buf[20]; + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.pStr = buf; + t.CharCount = (COUNT)~0; + if (crew_level >= max_crew) + wsprintf (buf, "%u", crew_level); + else + wsprintf (buf, "%u/%u", crew_level, max_crew); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); + DrawText (&t); + } + + SetFlashRect (&pMS->flash_rect0, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + } + + return (TRUE); +} + +static HSTARSHIP +GetArmadaStarShip (void) +{ + RECT pick_r; + CONTEXT OldContext; + HSTARSHIP hBattleShip; + + if (HIBYTE (battle_counter) == 0) + { + return (0); + } + +// MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS)); + +OldContext = SetContext (SpaceContext); + DrawArmadaPickShip (FALSE, &pick_r); + + { + MENU_STATE MenuState; + + MenuState.InputFunc = DoPickBattleShip; + MenuState.Initialized = FALSE; + MenuState.first_item.x = NUM_PICK_SHIP_COLUMNS >> 1; + MenuState.first_item.y = 0; + MenuState.flash_task = 0; + MenuState.CurFrame = 0; + MenuState.flash_rect1.corner = pick_r.corner; + MenuState.flash_rect1.extent.width = 0; + + ClearSemaphore (&GraphicsSem); + pMenuState = &MenuState; + DoInput ((PVOID)&MenuState); + pMenuState = 0; + SetSemaphore (&GraphicsSem); + + SetFlashRect (NULL_PTR, (FRAME)0); + + hBattleShip = (HSTARSHIP)MenuState.CurFrame; + } + + if (hBattleShip) + { + if (hBattleShip == GetTailLink (&race_q[0])) + battle_counter = MAKE_WORD (1, HIBYTE (battle_counter)); + + while (ChannelPlaying (0)) + ; + } + +// DestroySound (ReleaseSound (MenuSounds)); + +SetContext (OldContext); + + return (hBattleShip); +} + +HSTARSHIP +GetEncounterStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player) +{ + HSTARSHIP hBattleShip; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + hBattleShip = GetHeadLink (&race_q[which_player]); + else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) + { + extern HSTARSHIP GetMeleeStarShip (STARSHIPPTR LastStarShipPtr, + COUNT which_player); + + hBattleShip = GetMeleeStarShip (LastStarShipPtr, which_player); + } + else + { + HSTARSHIP hStarShip; + STARSHIPPTR SPtr; + SHIP_FRAGMENTPTR FragPtr; + + if (LastStarShipPtr == 0) + { + if (which_player == 0 && LOBYTE (battle_counter) > 1) + hBattleShip = GetArmadaStarShip (); + else + { + hBattleShip = GetHeadLink (&race_q[which_player]); + if (which_player == 1) + { + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + if (FragPtr->ShipInfo.crew_level == (BYTE)~0) + battle_counter += MAKE_WORD (0, 1); + UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); + } + } + } + else + { + PQUEUE pQueue; + HSTARSHIP hNextShip; + + if (which_player == 0) + pQueue = &GLOBAL (built_ship_q); + else + pQueue = &GLOBAL (npc_built_ship_q); + + hBattleShip = GetHeadLink (&race_q[which_player]); + for (hStarShip = GetHeadLink (pQueue); + hStarShip != 0; hStarShip = hNextShip) + { + SPtr = LockStarShip (&race_q[which_player], hBattleShip); + hNextShip = _GetSuccLink (SPtr); + UnlockStarShip (&race_q[which_player], hBattleShip); + hBattleShip = hNextShip; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); + if (SPtr == LastStarShipPtr) + { + if (FragPtr->ShipInfo.crew_level != (BYTE)~0) + { + FragPtr->ShipInfo.crew_level = SPtr->special_counter; + SPtr->RaceDescPtr = (RACE_DESCPTR)&FragPtr->ShipInfo; + if (GLOBAL (CurrentActivity) & IN_BATTLE) + SPtr->RaceResIndex = 0; + } + else /* if infinite ships */ + { + hBattleShip = GetTailLink (&race_q[which_player]); + SPtr->special_counter = FragPtr->ShipInfo.max_crew; + SPtr->cur_status_flags = 1 << which_player; + SPtr->captains_name_index = PickCaptainName (); + + battle_counter += MAKE_WORD (0, 1); + } + UnlockStarShip (pQueue, hStarShip); + break; + } + hNextShip = _GetSuccLink (FragPtr); + UnlockStarShip (pQueue, hStarShip); + } + + if (which_player == 0) + { + if (LOBYTE (battle_counter)) + hBattleShip = GetArmadaStarShip (); + else /* last ship was flagship */ + { +#define RUN_AWAY_FUEL_COST (5 * FUEL_TANK_SCALE) + hBattleShip = 0; + if (LastStarShipPtr->special_counter == 0) + /* died in the line of duty */ + GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; +#ifndef TESTING + else if (GLOBAL_SIS (FuelOnBoard) > + RUN_AWAY_FUEL_COST) + GLOBAL_SIS (FuelOnBoard) -= + RUN_AWAY_FUEL_COST; + else + GLOBAL_SIS (FuelOnBoard) = 0; +#endif /* TESTING */ + } + } + } + + if (hBattleShip) + { + SPtr = LockStarShip (&race_q[which_player], hBattleShip); + OwnStarShip (SPtr, + SPtr->cur_status_flags, + SPtr->captains_name_index); + UnlockStarShip (&race_q[which_player], hBattleShip); + } + } + + return (hBattleShip); +} + +void +DrawArmadaPickShip (BOOLEAN draw_salvage_frame, PRECT pPickRect) +{ +#define PICK_NAME_HEIGHT 6 + //COUNT i; + HSTARSHIP hBattleShip, hNextShip; + STARSHIPPTR StarShipPtr; + RECT r, pick_r; + STAMP s; + TEXT t; + CONTEXT OldContext; + MEM_HANDLE hLastIndex; + FRAME PickFrame; + + hLastIndex = SetResourceIndex (hResIndex); + OldContext = SetContext (SpaceContext); + + PickFrame = CaptureDrawable ( + LoadGraphic (SC2_PICK_PMAP_ANIM) + ); + + BatchGraphics (); + + s.frame = PickFrame; + SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0)); + GetFrameRect (s.frame, &pick_r); + GetContextClipRect (&r); + pick_r.corner.x = (r.extent.width >> 1) - (pick_r.extent.width >> 1); + pick_r.corner.y = (r.extent.height >> 1) - (pick_r.extent.height >> 1); + + if (!draw_salvage_frame) + *pPickRect = pick_r; + else + { + s.origin.x = r.extent.width >> 1; + s.frame = IncFrameIndex (s.frame); + SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0)); + GetFrameRect (s.frame, &r); + s.origin.x -= r.extent.width >> 1; + s.origin.y = pick_r.corner.y - (r.extent.height >> 1); + DrawStamp (&s); + s.frame = DecFrameIndex (s.frame); + pick_r.corner.y = s.origin.y + r.extent.height; + + r.corner.x = pick_r.corner.x; + r.corner.y = s.origin.y; + *pPickRect = r; + } + s.origin = pick_r.corner; + DrawStamp (&s); + + t.baseline.x = pick_r.corner.x + (pick_r.extent.width >> 1); + t.baseline.y = pick_r.corner.y + pick_r.extent.height - 5; + t.align = ALIGN_CENTER; + t.pStr = GLOBAL_SIS (ShipName); + t.CharCount = (COUNT)~0; +SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x12, 0x12, 0x12), 0x17)); + SetContextFont (StarConFont); + DrawText (&t); + + r.extent.width = ICON_WIDTH; + r.extent.height = ICON_HEIGHT; + for (hBattleShip = GetHeadLink (&race_q[0]); + hBattleShip != 0; hBattleShip = hNextShip) + { + StarShipPtr = LockStarShip (&race_q[0], hBattleShip); + + if (StarShipPtr->captains_name_index) + { + COUNT ship_index; + + ship_index = (COUNT)LONIBBLE ( + StarShipPtr->RaceDescPtr->ship_info.var2 + ); + + s.origin.x = pick_r.corner.x + + (5 + ((ICON_WIDTH + 4) + * (ship_index % NUM_PICK_SHIP_COLUMNS))); + if ((ship_index % NUM_PICK_SHIP_COLUMNS) >= + (NUM_PICK_SHIP_COLUMNS >> 1)) + s.origin.x += FLAGSHIP_WIDTH + 4; + s.origin.y = pick_r.corner.y + + (16 + ((ICON_HEIGHT + 4) + * (ship_index / NUM_PICK_SHIP_COLUMNS))); + s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + r.corner = s.origin; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + if (StarShipPtr->RaceResIndex + || StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + { + DrawStamp (&s); + if (StarShipPtr->RaceResIndex == 0) + { + extern FRAME status; + + /* Dead ship - mark with an X. */ + s.origin.x -= 1; + s.frame = SetAbsFrameIndex (status, 3); + DrawStamp (&s); + } + } + else + { + /* Ship ran away */ + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledStamp (&s); + } + } + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip (&race_q[0], hBattleShip); + } + + UnbatchGraphics (); + + DestroyDrawable (ReleaseDrawable (PickFrame)); + + SetContext (OldContext); + SetResourceIndex (hLastIndex); +} + diff --git a/sc2/src/sc2code/plandata.c b/sc2/src/sc2code/plandata.c new file mode 100644 index 000000000..42cc66251 --- /dev/null +++ b/sc2/src/sc2code/plandata.c @@ -0,0 +1,1846 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "planets/elemdata.h" + +STAR_DESC starmap_array[] = +{ + {{5007, 35}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 74}, + {{ 708, 41}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 7, 91}, + {{4714, 78}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 74}, + {{2187, 83}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 126}, + {{2814, 89}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 82}, + {{4244, 91}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 125}, + {{5652, 98}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 124}, + {{2939, 116}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 82}, + {{2771, 146}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 82}, + {{5313, 150}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 73}, + {{ 265, 156}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 92}, + {{4529, 169}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 8, 74}, + {{4911, 180}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 74}, + {{4747, 221}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 74}, + {{9708, 250}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 112}, + {{4861, 262}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 74}, + {{2908, 269}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), SHOFIXTI_DEFINED, 4, 82}, + {{1855, 270}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 81}, + {{7958, 270}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 8}, + {{5160, 280}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 73}, + {{ 570, 289}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 92}, + {{4923, 294}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), YEHAT_DEFINED, 3, 74}, + {{2820, 301}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 82}, + {{7934, 318}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 8}, + {{8062, 318}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 8}, + {{1116, 334}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 91}, + {{ 803, 337}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 91}, + {{1787, 338}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 81}, + {{ 877, 340}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 91}, + {{5338, 355}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 73}, + {{5039, 373}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 73}, + {{ 843, 380}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 91}, + {{4872, 408}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 74}, + {{1740, 423}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 7, 81}, + {{4596, 429}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 9, 74}, + {{ 843, 431}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 91}, + {{2156, 440}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 81}, + {{2004, 441}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 81}, + {{ 530, 442}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 92}, + {{ 958, 468}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 91}, + {{2058, 475}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 81}, + {{ 304, 477}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 92}, + {{ 522, 525}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), PKUNK_DEFINED, 3, 92}, + {{2100, 554}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 81}, + {{ 134, 565}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 92}, + {{6858, 577}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), MYCON_TRAP_DEFINED, 0, 123}, + {{5014, 584}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 73}, + {{5256, 608}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 73}, + {{2411, 718}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 9}, + {{2589, 741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 9}, + {{ 675, 742}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 8, 91}, + {{9292, 750}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 5}, + {{1463, 779}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 6, 80}, + {{3089, 782}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 9}, + {{2854, 787}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 9}, + {{3333, 801}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 9}, + {{9237, 821}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 5}, + {{9339, 843}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 5}, + {{ 242, 857}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 3, 90}, + {{1515, 866}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 80}, + {{4770, 895}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 75}, + {{1412, 905}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 80}, + {{4681, 916}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 6, 75}, + {{9333, 937}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME0_DEFINED, 2, 5}, + {{9419, 942}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 5}, + {{ 230, 952}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 90}, + {{ 146, 955}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 90}, + {{4873, 968}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 75}, + {{1559, 993}, MAKE_STAR (SUPER_GIANT_STAR, RED_BODY, -1), MELNORME1_DEFINED, 1, 80}, + {{1895, 1041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 93}, + {{4337, 1066}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 75}, + {{3732, 1067}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 0, 122}, + {{1579, 1115}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 80}, + {{4875, 1145}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 75}, + {{4604, 1187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 75}, + {{5812, 1208}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 72}, + {{1312, 1260}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 80}, + {{1916, 1270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 93}, + {{6562, 1270}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 121}, + {{ 416, 1301}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 120}, + {{3958, 1354}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 89}, + {{4000, 1363}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 89}, + {{1752, 1450}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), SOL_DEFINED, 0, 129}, + {{2187, 1500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 127}, + {{1806, 1507}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 0, 128}, + {{5708, 1520}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 72}, + {{9469, 1548}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 6}, + {{4333, 1562}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 88}, + {{6041, 1562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 72}, + {{9375, 1583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 6}, + {{2881, 1614}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 96}, + {{6083, 1625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 72}, + {{4250, 1645}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 88}, + {{ 650, 1646}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 85}, + {{9477, 1670}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 6}, + {{2840, 1676}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 96}, + {{9541, 1687}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 4, 6}, + {{7395, 1687}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 69}, + {{4333, 1687}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), VUX_DEFINED, 2, 88}, + {{9559, 1735}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 6}, + {{ 736, 1737}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 6, 85}, + {{1601, 1746}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 94}, + {{7395, 1750}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 69}, + {{ 951, 1770}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 85}, + {{1666, 1812}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 94}, + {{7187, 1833}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 69}, + {{ 705, 1838}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 85}, + {{1140, 1847}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 85}, + {{6467, 1878}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 71}, + {{2791, 1895}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 96}, + {{6500, 1916}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 71}, + {{5458, 1916}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 0, 119}, + {{1048, 1919}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 85}, + {{3678, 1926}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 99}, + {{3345, 1931}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), START_COLONY_DEFINED, 0, 98}, + {{8187, 1937}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 7}, + {{3352, 1940}, MAKE_STAR (SUPER_GIANT_STAR, WHITE_BODY, -1), MELNORME2_DEFINED, 0, 97}, + {{ 977, 1953}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 85}, + {{4221, 1986}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), MAIDENS_DEFINED, 1, 100}, + {{4500, 2000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 100}, + {{6833, 2000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 70}, + {{8163, 2009}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 7}, + {{8080, 2011}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 7}, + {{6036, 2035}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 71}, + {{6479, 2062}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), EGG_CASE1_DEFINED, 3, 71}, + {{2104, 2083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), ZOQ_SCOUT_DEFINED, 0, 118}, + {{8062, 2083}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 7}, + {{ 270, 2187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 79}, + {{6500, 2208}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 6, 71}, + {{6291, 2208}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), MYCON_DEFINED, 5, 71}, + {{ 125, 2229}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 79}, + {{ 312, 2250}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 79}, + {{3884, 2262}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 99}, + {{ 742, 2268}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), CHMMR_DEFINED, 0, 117}, + {{2306, 2285}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 95}, + {{2402, 2309}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 95}, + {{6395, 2312}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SUN_DEVICE_DEFINED, 2, 12}, + {{8875, 2312}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 9, 61}, + {{3551, 2320}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 99}, + {{6208, 2333}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 12}, + {{3354, 2354}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 99}, + {{9909, 2359}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 111}, + {{2298, 2385}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 95}, + {{7020, 2395}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 70}, + {{9038, 2407}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 61}, + {{9375, 2416}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 61}, + {{6500, 2458}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 12}, + {{ 217, 2509}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 78}, + {{3641, 2512}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 86}, + {{5625, 2520}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 14}, + {{3713, 2537}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ORZ_DEFINED, 3, 86}, + {{3587, 2566}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ANDROSYNTH_DEFINED, 7, 86}, + {{9291, 2583}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 61}, + {{3654, 2587}, MAKE_STAR (SUPER_GIANT_STAR, GREEN_BODY, -1), MELNORME3_DEFINED, 1, 86}, + {{3721, 2619}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), TAALO_PROTECTOR_DEFINED, 4, 86}, + {{5791, 2625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 14}, + {{6416, 2625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 12}, + {{6008, 2631}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), EGG_CASE0_DEFINED, 2, 14}, + {{3608, 2637}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 86}, + {{3499, 2648}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 87}, + {{9479, 2666}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 61}, + {{3668, 2666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 86}, + {{ 229, 2666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 78}, + {{8895, 2687}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 61}, + {{ 138, 2696}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 78}, + {{5375, 2729}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 116}, + {{6354, 2729}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), EGG_CASE2_DEFINED, 3, 12}, + {{6458, 2750}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 12}, + {{2458, 2750}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 106}, + {{ 351, 2758}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 78}, + {{7083, 2770}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 70}, + {{3759, 2778}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 87}, + {{9333, 2791}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 61}, + {{3400, 2804}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 87}, + {{9469, 2806}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), DRUUGE_DEFINED, 6, 61}, + {{3619, 2830}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 87}, + {{2208, 2854}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 106}, + {{9250, 2854}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 61}, + {{ 672, 2863}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 78}, + {{ 167, 2875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 78}, + {{4030, 2887}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 105}, + {{ 384, 2900}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 78}, + {{2727, 2951}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 106}, + {{4645, 2958}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 105}, + {{5625, 2958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 13}, + {{8270, 2958}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 66}, + {{8291, 2979}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 66}, + {{6020, 2979}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 3, 13}, + {{6562, 3020}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 70}, + {{2011, 3043}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 8, 106}, + {{8125, 3083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 66}, + {{2354, 3166}, MAKE_STAR (GIANT_STAR, YELLOW_BODY, -1), 0, 4, 106}, + {{3833, 3187}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 105}, + {{5812, 3208}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 13}, + {{9000, 3250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 113}, + {{ 291, 3250}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 84}, + {{ 501, 3259}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 84}, + {{ 791, 3270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 84}, + {{2354, 3291}, MAKE_STAR (SUPER_GIANT_STAR, RED_BODY, -1), MELNORME4_DEFINED, 1, 106}, + {{1104, 3333}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 84}, + {{2687, 3333}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 106}, + {{3187, 3375}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 107}, + {{1758, 3418}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 108}, + {{2520, 3437}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 106}, + {{8437, 3458}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 64}, + {{8770, 3458}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 64}, + {{3000, 3500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 107}, + {{ 149, 3519}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 76}, + {{8791, 3541}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 64}, + {{2148, 3551}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 109}, + {{7375, 3562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 115}, + {{9312, 3562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 63}, + {{9599, 3583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 63}, + {{9375, 3604}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 63}, + {{ 90, 3614}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 6, 76}, + {{2770, 3625}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 107}, + {{8708, 3625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 64}, + {{ 267, 3645}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 76}, + {{1604, 3645}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 108}, + {{2274, 3663}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 109}, + {{ 229, 3666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ILWRATH_DEFINED, 1, 76}, + {{3083, 3674}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 107}, + {{2416, 3687}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), SPATHI_DEFINED, 5, 109}, + {{9333, 3708}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 63}, + {{2250, 3708}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 109}, + {{ 288, 3735}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 76}, + {{2354, 3741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 109}, + {{2583, 3750}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 109}, + {{4125, 3770}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), SYREEN_DEFINED, 0, 114}, + {{ 166, 3770}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 76}, + {{6270, 3833}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 10}, + {{2145, 3916}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 110}, + {{6125, 3937}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 10}, + {{6291, 3937}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 9, 10}, + {{5937, 3937}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), SHIP_VAULT_DEFINED, 5, 10}, + {{2479, 3958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 109}, + {{ 926, 3972}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 83}, + {{2062, 3991}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 110}, + {{5895, 4020}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 10}, + {{ 285, 4020}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 77}, + {{6062, 4041}, MAKE_STAR (GIANT_STAR, YELLOW_BODY, -1), 0, 1, 10}, + {{2875, 4041}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 20}, + {{8645, 4062}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 65}, + {{ 860, 4065}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 83}, + {{5958, 4083}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 10}, + {{3038, 4083}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 20}, + {{ 291, 4104}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 77}, + {{6166, 4125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 10}, + {{9812, 4145}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 62}, + {{8520, 4166}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 65}, + {{9573, 4182}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 62}, + {{ 500, 4187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 77}, + {{2145, 4208}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 110}, + {{6208, 4229}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 10}, + {{2812, 4250}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 20}, + {{2937, 4306}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 20}, + {{9416, 4395}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 62}, + {{2875, 4479}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 20}, + {{ 250, 4583}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 26}, + {{7250, 4583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 68}, + {{ 479, 4583}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 26}, + {{5708, 4604}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 104}, + {{ 479, 4645}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 26}, + {{2895, 4687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 20}, + {{2708, 4708}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 20}, + {{ 562, 4708}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 26}, + {{ 416, 4717}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 26}, + {{5094, 4931}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 11}, + {{9000, 5000}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 67}, + {{8958, 5000}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 67}, + {{5006, 5011}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 11}, + {{7312, 5062}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 68}, + {{3679, 5068}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 17}, + {{9062, 5083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 67}, + {{7416, 5083}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), RAINBOW_DEFINED, 3, 68}, + {{5155, 5122}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 11}, + {{3875, 5145}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 17}, + {{4937, 5145}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 11}, + {{2979, 5166}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 15}, + {{3035, 5178}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 15}, + {{3994, 5185}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 17}, + {{3541, 5187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 17}, + {{5977, 5246}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 102}, + {{3770, 5250}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 17}, + {{1520, 5261}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 55}, + {{1613, 5279}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 55}, + {{7020, 5291}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 68}, + {{1416, 5315}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 55}, + {{2993, 5318}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 15}, + {{1425, 5404}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 55}, + {{1854, 5416}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 55}, + {{3625, 5437}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 16}, + {{3416, 5437}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 16}, + {{4000, 5437}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ZOQFOT_DEFINED, 1, 18}, + {{6270, 5479}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 102}, + {{3583, 5479}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 16}, + {{4083, 5513}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 18}, + {{2159, 5614}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 55}, + {{3937, 5625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 18}, + {{6014, 5632}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 21}, + {{ 250, 5687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 25}, + {{3625, 5750}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 2, 19}, + {{ 371, 5772}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 25}, + {{6107, 5785}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 21}, + {{9645, 5791}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), BURVIXESE_DEFINED, 0, 130}, + {{1545, 5818}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 54}, + {{3750, 5833}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 19}, + {{6301, 5875}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 21}, + {{1923, 5878}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 54}, + {{4625, 5895}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 131}, + {{ 152, 5900}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 25}, + {{5437, 5916}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 33}, + {{1714, 5926}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 54}, + {{6200, 5935}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), SAMATRA_DEFINED, 4, 21}, + {{6429, 5958}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 21}, + {{4729, 5958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 131}, + {{1978, 5968}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), TALKING_PET_DEFINED, 2, 54}, + {{ 395, 5979}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 22}, + {{ 563, 5980}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 22}, + {{ 456, 5989}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 22}, + {{4625, 6000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 131}, + {{6166, 6000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 21}, + {{6496, 6032}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 21}, + {{2228, 6038}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 12, 54}, + {{4583, 6041}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 131}, + {{1558, 6058}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 6, 54}, + {{1902, 6065}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 54}, + {{2159, 6073}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 11, 54}, + {{ 365, 6093}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 22}, + {{ 541, 6145}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 22}, + {{2200, 6176}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 10, 54}, + {{ 729, 6208}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 23}, + {{5250, 6229}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 33}, + {{8166, 6250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 40}, + {{6215, 6255}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 21}, + {{ 437, 6270}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 22}, + {{5583, 6291}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 33}, + {{1881, 6308}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 54}, + {{1795, 6329}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 7, 54}, + {{2118, 6379}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 9, 54}, + {{ 750, 6458}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 23}, + {{3716, 6458}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 30}, + {{1360, 6489}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 56}, + {{7333, 6500}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 40}, + {{3770, 6500}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 30}, + {{4500, 6500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 37}, + {{ 187, 6520}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 24}, + {{ 125, 6541}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 1, 24}, + {{7812, 6562}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 40}, + {{ 770, 6602}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 23}, + {{5910, 6624}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 29}, + {{ 208, 6625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 24}, + {{2604, 6645}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 101}, + {{1578, 6668}, MAKE_STAR (SUPER_GIANT_STAR, GREEN_BODY, -1), MELNORME5_DEFINED, 1, 56}, + {{5479, 6687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 33}, + {{ 375, 6716}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 24}, + {{ 312, 6728}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 24}, + {{6020, 6729}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 29}, + {{5062, 6750}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 10, 28}, + {{4208, 6854}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 31}, + {{5145, 6875}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 9, 28}, + {{4291, 6937}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 31}, + {{5145, 6958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 8, 28}, + {{7208, 7000}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 39}, + {{8625, 7000}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), RAINBOW_DEFINED, 1, 41}, + {{4955, 7034}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 28}, + {{4895, 7041}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 28}, + {{4971, 7104}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 28}, + {{8666, 7104}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 41}, + {{4854, 7125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 28}, + {{5083, 7145}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 7, 28}, + {{7360, 7184}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 39}, + {{1020, 7187}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 58}, + {{3875, 7187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 32}, + {{4879, 7201}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 28}, + {{4958, 7229}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 28}, + {{7125, 7250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 39}, + {{7532, 7258}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 39}, + {{2416, 7291}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 101}, + {{3854, 7291}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 32}, + {{9687, 7333}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 44}, + {{ 395, 7458}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), RAINBOW_DEFINED, 2, 60}, + {{4895, 7458}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 36}, + {{4645, 7479}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 36}, + {{6940, 7514}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 11, 39}, + {{7443, 7538}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 39}, + {{6479, 7541}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 38}, + {{7208, 7541}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 39}, + {{5791, 7583}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 34}, + {{ 333, 7625}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 60}, + {{5958, 7645}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 34}, + {{1041, 7708}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 58}, + {{5875, 7729}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME6_DEFINED, 1, 34}, + {{1125, 7791}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 58}, + {{4979, 7791}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 36}, + {{4958, 7791}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 36}, + {{6889, 7803}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 10, 39}, + {{7200, 7849}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 39}, + {{7395, 7854}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 39}, + {{9437, 7854}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 44}, + {{2836, 7857}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), RAINBOW_DEFINED, 5, 53}, + {{5375, 7875}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 35}, + {{6187, 7875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 35}, + {{6041, 7916}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 35}, + {{5979, 7979}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 35}, + {{7083, 7993}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 9, 39}, + {{3270, 8000}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 8, 53}, + {{6104, 8000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 35}, + {{ 687, 8000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 59}, + {{ 562, 8000}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), URQUAN_WRECK_DEFINED, 1, 59}, + {{5645, 8020}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 35}, + {{1395, 8041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 58}, + {{8229, 8041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 43}, + {{2518, 8056}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 53}, + {{5875, 8062}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 35}, + {{8416, 8083}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 43}, + {{9000, 8229}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 44}, + {{3562, 8250}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 9, 53}, + {{5437, 8270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), RAINBOW_DEFINED, 5, 48}, + {{1520, 8333}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 58}, + {{2771, 8351}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 53}, + {{2535, 8358}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), THRADD_DEFINED, 4, 53}, + {{3151, 8390}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 53}, + {{2362, 8395}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 11, 53}, + {{2822, 8395}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 53}, + {{5500, 8395}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 48}, + {{2536, 8504}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 2}, + {{2582, 8507}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME7_DEFINED, 1, 2}, + {{8625, 8562}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 3}, + {{4375, 8562}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 50}, + {{2593, 8569}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 2}, + {{2562, 8572}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 2}, + {{8492, 8578}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 7, 3}, + {{1125, 8583}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 58}, + {{8073, 8588}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 46}, + {{8560, 8638}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 3}, + {{8750, 8645}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 3}, + {{5562, 8645}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 48}, + {{2588, 8653}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 14, 53}, + {{2458, 8666}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 10, 53}, + {{7666, 8666}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 2, 46}, + {{2776, 8673}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), AQUA_HELIX_DEFINED, 6, 53}, + {{8630, 8693}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), UTWIG_DEFINED, 2, 3}, + {{2310, 8702}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 12, 53}, + {{ 437, 8770}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 57}, + {{8534, 8797}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 3, 3}, + {{8588, 8812}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 3}, + {{7187, 8812}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 46}, + {{5475, 8823}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 48}, + {{3050, 8833}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 1}, + {{2831, 8854}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 1}, + {{2300, 8861}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 13, 53}, + {{ 479, 8875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 57}, + {{2706, 8910}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 1}, + {{ 333, 8916}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 57}, + {{2535, 8917}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 1}, + {{8322, 8934}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 45}, + {{8249, 8958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 45}, + {{8375, 8958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 45}, + {{5645, 8979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 48}, + {{2687, 9000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 1}, + {{8375, 9041}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 45}, + {{9960, 9042}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), RAINBOW_DEFINED, 0, 42}, + {{7354, 9062}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 47}, + {{7833, 9083}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 47}, + {{2581, 9105}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 1}, + {{7545, 9107}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 47}, + {{7414, 9124}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SUPOX_DEFINED, 2, 47}, + {{8500, 9125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 45}, + {{ 104, 9125}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 27}, + {{7889, 9181}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 47}, + {{7791, 9187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 47}, + {{7791, 9229}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 47}, + {{4812, 9270}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 51}, + {{8500, 9372}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), BOMB_DEFINED, 6, 45}, + {{7255, 9374}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 11, 45}, + {{8458, 9393}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 7, 45}, + {{1000, 9395}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 27}, + {{5711, 9475}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 49}, + {{ 62, 9479}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 27}, + {{5989, 9496}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 49}, + {{8000, 9505}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 9, 45}, + {{5329, 9538}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 49}, + {{2916, 9541}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 103}, + {{8296, 9548}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 45}, + {{5600, 9552}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 49}, + {{7664, 9589}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 10, 45}, + {{6125, 9604}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 49}, + {{9144, 9686}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 4}, + {{5781, 9711}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 49}, + {{5229, 9729}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 49}, + {{9120, 9741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 4}, + {{9186, 9741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 4}, + {{9159, 9745}, MAKE_STAR (SUPER_GIANT_STAR, BLUE_BODY, -1), MELNORME8_DEFINED, 1, 4}, + {{ 333, 9750}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 0}, + {{9147, 9790}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 4}, + {{5704, 9795}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), VUX_BEAST_DEFINED, 4, 49}, + {{ 333, 9812}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SLYLANDRO_DEFINED, 2, 27}, + {{1020, 9937}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 27}, + {{ 83, 9979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 27}, + {{1937, 9979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 103}, + {{4395, 9979}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 0, 52}, + + {{MAX_X_UNIVERSE << 1, MAX_Y_UNIVERSE << 1}, 0, 0, 0, 0}, + +#define VORTEX_SCALE 20 + {{(-12* VORTEX_SCALE) + 5000, (-21 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{( 1 * VORTEX_SCALE) + 5000, (-20 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-16 * VORTEX_SCALE) + 5000, (-18 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{( 8 * VORTEX_SCALE) + 5000, (-17 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{( 3 * VORTEX_SCALE) + 5000, (-13 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-21 * VORTEX_SCALE) + 5000, (-4 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-4 * VORTEX_SCALE) + 5000, (-4 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-12 * VORTEX_SCALE) + 5000, (-2 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-26 * VORTEX_SCALE) + 5000, (2 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-17 * VORTEX_SCALE) + 5000, (7 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(10 * VORTEX_SCALE) + 5000, (7 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(15 * VORTEX_SCALE) + 5000, (14 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(22 * VORTEX_SCALE) + 5000, (16 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(-6 * VORTEX_SCALE) + 5000, (19 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + {{(10 * VORTEX_SCALE) + 5000, (20 * VORTEX_SCALE) + 5000}, + MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, + + {{6134, 5900}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 0, 132}, + + {{MAX_X_UNIVERSE << 1, MAX_Y_UNIVERSE << 1}, 0, 0, 0, 0}, +}; + +const BYTE element_array[NUMBER_OF_ELEMENTS] = +{ + COMMON, /* HYDROGEN */ + COMMON, /* HELIUM */ + COMMON, /* LITHIUM */ + BASE_METAL, /* BERYLLIUM */ + BASE_METAL, /* BORON */ + COMMON, /* CARBON */ + COMMON, /* NITROGEN */ + CORROSIVE, /* OXYGEN */ + CORROSIVE, /* FLUORINE */ + NOBLE, /* NEON */ + BASE_METAL, /* SODIUM */ + BASE_METAL, /* MAGNESIUM */ + BASE_METAL, /* ALUMINUM */ + COMMON, /* SILICON */ + COMMON, /* PHOSPHORUS */ + CORROSIVE, /* SULFUR */ + CORROSIVE, /* CHLORINE */ + NOBLE, /* ARGON */ + BASE_METAL, /* POTASSIUM */ + BASE_METAL, /* CALCIUM */ + BASE_METAL, /* SCANDIUM */ + BASE_METAL, /* TITANIUM */ + BASE_METAL, /* VANADIUM */ + BASE_METAL, /* CHROMIUM */ + BASE_METAL, /* MANGANESE */ + BASE_METAL, /* IRON */ + BASE_METAL, /* COBALT */ + BASE_METAL, /* NICKEL */ + BASE_METAL, /* COPPER */ + BASE_METAL, /* ZINC */ + BASE_METAL, /* GALLIUM */ + BASE_METAL, /* GERMANIUM */ + COMMON, /* ARSENIC */ + COMMON, /* SELENIUM */ + CORROSIVE, /* BROMINE */ + NOBLE, /* KRYPTON */ + BASE_METAL, /* RUBIDIUM */ + BASE_METAL, /* STRONTIUM */ + BASE_METAL, /* YTTRIUM */ + BASE_METAL, /* ZIRCONIUM */ + BASE_METAL, /* NIOBIUM */ + BASE_METAL, /* MOLYBDENUM */ + RADIOACTIVE, /* TECHNETIUM */ + BASE_METAL, /* RUTHENIUM */ + BASE_METAL, /* RHODIUM */ + PRECIOUS, /* PALLADIUM */ + PRECIOUS, /* SILVER */ + BASE_METAL, /* CADMIUM */ + BASE_METAL, /* INDIUM */ + BASE_METAL, /* TIN */ + BASE_METAL, /* ANTIMONY */ + BASE_METAL, /* TELLURIUM */ + CORROSIVE, /* IODINE */ + NOBLE, /* XENON */ + BASE_METAL, /* CESIUM */ + BASE_METAL, /* BARIUM */ + RARE_EARTH, /* LANTHANUM */ + RARE_EARTH, /* CERIUM */ + RARE_EARTH, /* PRASEODYMIUM */ + RARE_EARTH, /* NEODYMIUM */ + RARE_EARTH, /* PROMETHIUM */ + RARE_EARTH, /* SAMARIUM */ + RARE_EARTH, /* EUROPIUM */ + RARE_EARTH, /* GADOLINIUM */ + RARE_EARTH, /* TERBIUM */ + RARE_EARTH, /* DYPROSIUM */ + RARE_EARTH, /* HOLMIUM */ + RARE_EARTH, /* ERBIUM */ + RARE_EARTH, /* THULIUM */ + RARE_EARTH, /* YTTERBIUM */ + RARE_EARTH, /* LUTETIUM */ + BASE_METAL, /* HAFNIUM */ + BASE_METAL, /* TANTALUM */ + BASE_METAL, /* TUNGSTEN */ + BASE_METAL, /* RHENIUM */ + BASE_METAL, /* OSMIUM */ + PRECIOUS, /* IRIDIUM */ + PRECIOUS, /* PLATINUM */ + PRECIOUS, /* GOLD */ + BASE_METAL, /* MERCURY */ + BASE_METAL, /* THALLIUM */ + BASE_METAL, /* LEAD */ + BASE_METAL, /* BISMUTH */ + RADIOACTIVE, /* POLONIUM */ + RADIOACTIVE, /* ASTATINE */ + NOBLE, /* RADON */ + RADIOACTIVE, /* FRANCIUM */ + RADIOACTIVE, /* RADIUM */ + RADIOACTIVE, /* ACTINIUM */ + RADIOACTIVE, /* THORIUM */ + RADIOACTIVE, /* PROTACTINIUM */ + RADIOACTIVE, /* URANIUM */ + RADIOACTIVE, /* NEPTUNIUM */ + RADIOACTIVE, /* PLUTONIUM */ + + COMMON, /* OZONE */ + COMMON, /* FREE RADICALS */ + COMMON, /* CARBON DIOXIDE */ + COMMON, /* CARBON MONOXIDE */ + COMMON, /* AMMONIA */ + COMMON, /* METHANE */ + COMMON, /* SULFURIC ACID */ + COMMON, /* HYDROCHLORIC ACID */ + COMMON, /* HYDROCYANIC ACID */ + COMMON, /* FORMIC ACID */ + COMMON, /* PHOSPHORIC ACID */ + COMMON, /* FORMALDEHYDE */ + COMMON, /* CYANOACETYLENE */ + COMMON, /* METHANOL */ + COMMON, /* ETHANOL */ + COMMON, /* SILICON MONOXIDE */ + COMMON, /* TITANIUM OXIDE */ + COMMON, /* ZIRCONIUM OXIDE */ + COMMON, /* WATER */ + COMMON, /* SILICON COMPOUNDS */ + COMMON, /* METAL OXIDES */ + EXOTIC, /* QUANTUM BLACK HOLES */ + EXOTIC, /* NEUTRONIUM */ + EXOTIC, /* MAGNETIC MONOPOLES */ + EXOTIC, /* DEGENERATE MATTER */ + EXOTIC, /* SUPER FLUIDS */ + EXOTIC, /* AGUUTI NODULES */ + COMMON, /* IRON COMPOUNDS */ + COMMON, /* ALUMINUM COMPOUNDS */ + COMMON, /* NITROUS OXIDE */ + COMMON, /* RADIOACTIVES */ + COMMON, /* HYDROCARBONS */ + COMMON, /* CARBON COMPOUNDS */ + EXOTIC, /* ANTIMATTER */ + EXOTIC, /* CHARON DUST */ + EXOTIC, /* REISBURG HELICES */ + EXOTIC, /* TZO CRYSTALS */ + COMMON, /* CALCIUM COMPOUNDS */ + COMMON, /* NITRIC ACID */ +}; + +/*------------------------------ Global Data ------------------------------ */ +#define NO_TECTONICS 0 +#define LOW_TECTONICS 40 +#define MED_TECTONICS 80 +#define HIGH_TECTONICS 140 +#define SUPER_TECTONICS 200 + +#define NO_DEPOSIT 0 + +#define TRACE_USEFUL MINERAL_DEPOSIT (FEW, LIGHT) +#define LIGHT_USEFUL MINERAL_DEPOSIT (MODERATE, LIGHT) +#define MEDIUM_USEFUL MINERAL_DEPOSIT (MODERATE, MEDIUM) +#define HEAVY_USEFUL MINERAL_DEPOSIT (MODERATE, HEAVY) +#define HUGE_USEFUL MINERAL_DEPOSIT (NUMEROUS, HEAVY) + +const PlanetFrame planet_array[NUMBER_OF_PLANET_TYPES] = +{ + { /* OOLITE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + VIOLET_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ + { + {HOLMIUM, MEDIUM_USEFUL}, + {ERBIUM, MEDIUM_USEFUL}, + {THULIUM, MEDIUM_USEFUL}, + {YTTERBIUM, MEDIUM_USEFUL}, + {LUTETIUM, MEDIUM_USEFUL}, + {PALLADIUM, MEDIUM_USEFUL}, + {SILVER, MEDIUM_USEFUL}, + {IRIDIUM, MEDIUM_USEFUL}, + }, + OOLITE_COLOR_TAB, + OOLITE_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* YTTRIC_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + VIOLET_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {YTTERBIUM, HUGE_USEFUL}, + {YTTRIUM, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + YTTRIC_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* QUASI_DEGENERATE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ + { + {DEGENERATE_MATTER, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + QUASI_DEGENERATE_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* LANTHANIDE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ + { + {LANTHANUM, MEDIUM_USEFUL}, + {CERIUM, MEDIUM_USEFUL}, + {PRASEODYMIUM, MEDIUM_USEFUL}, + {NEODYMIUM, MEDIUM_USEFUL}, + {PROMETHIUM, MEDIUM_USEFUL}, + {SAMARIUM, MEDIUM_USEFUL}, + {GADOLINIUM, MEDIUM_USEFUL}, + {TERBIUM, MEDIUM_USEFUL}, + }, + LANTHANIDE_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* TREASURE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (SUPER_DENSITY, LIGHT), /* Atmosphere and density */ + { + {PALLADIUM, HEAVY_USEFUL}, + {SILVER, HEAVY_USEFUL}, + {SILVER, HEAVY_USEFUL}, + {IRIDIUM, HEAVY_USEFUL}, + {GOLD, HEAVY_USEFUL}, + {PLATINUM, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + TREASURE_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* UREA_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, HEAVY), /* Atmosphere and density */ + { + {AMMONIA, LIGHT_USEFUL}, + {FORMALDEHYDE, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + UREA_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* METAL_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + ORANGE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ + { + {IRON, HUGE_USEFUL}, + {NICKEL, HEAVY_USEFUL}, + {VANADIUM, MEDIUM_USEFUL}, + {SILVER, MEDIUM_USEFUL}, + {URANIUM, HEAVY_USEFUL}, + {SULFUR, MEDIUM_USEFUL}, + {COPPER, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + }, + METAL_COLOR_TAB, + METAL_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* RADIOACTIVE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + ORANGE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (SUPER_DENSITY, LIGHT), /* Atmosphere and density */ + { + {ASTATINE, MEDIUM_USEFUL}, + {FRANCIUM, MEDIUM_USEFUL}, + {RADIUM, MEDIUM_USEFUL}, + {ACTINIUM, MEDIUM_USEFUL}, + {THORIUM, MEDIUM_USEFUL}, + {PROTACTINIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + RADIOACTIVE_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* OPALESCENT_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + CYAN_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ + { + {SAMARIUM, LIGHT_USEFUL}, + {GADOLINIUM, LIGHT_USEFUL}, + {ARGON, LIGHT_USEFUL}, + {LITHIUM, LIGHT_USEFUL}, + {SILICON, LIGHT_USEFUL}, + {ARSENIC, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + OPALESCENT_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* CYANIC_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LIGHT_DENSITY, LIGHT), /* Atmosphere and density */ + { + {CYANOACETYLENE, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CYANIC_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* ACID_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {SULFURIC_ACID, HEAVY_USEFUL}, + {HYDROCHLORIC_ACID, HEAVY_USEFUL}, + {FORMIC_ACID, HEAVY_USEFUL}, + {HYDROCYANIC_ACID, HEAVY_USEFUL}, + {PHOSPHORIC_ACID, HEAVY_USEFUL}, + {NITRIC_ACID, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ACID_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* ALKALI_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {CALCIUM, MEDIUM_USEFUL}, + {BARIUM, MEDIUM_USEFUL}, + {STRONTIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ALKALI_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* HALIDE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {FLUORINE, MEDIUM_USEFUL}, + {BROMINE, MEDIUM_USEFUL}, + {BROMINE, MEDIUM_USEFUL}, + {ASTATINE, MEDIUM_USEFUL}, + {IODINE, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + HALIDE_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* GREEN_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ + { + {PRASEODYMIUM, HEAVY_USEFUL}, + {NEODYMIUM, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + GREEN_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* COPPER_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {COPPER, HUGE_USEFUL}, + {COPPER, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + COPPER_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* CARBIDE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + RED_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {CARBON, HEAVY_USEFUL}, + {CARBON, HEAVY_USEFUL}, + {CARBON, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CARBIDE_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* ULTRAMARINE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LIGHT_DENSITY, HEAVY), /* Atmosphere and density */ + { + {KRYPTON, MEDIUM_USEFUL}, + {COBALT, MEDIUM_USEFUL}, + {HOLMIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ULTRAMARINE_COLOR_TAB, + UREA_XLAT_TAB, + 200, 2, 100, 100, + }, + { /* NOBLE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LIGHT_DENSITY, LIGHT), /* Atmosphere and density */ + { + {NEON, LIGHT_USEFUL}, + {RADON, LIGHT_USEFUL}, + {ARGON, LIGHT_USEFUL}, + {KRYPTON, LIGHT_USEFUL}, + {XENON, LIGHT_USEFUL}, + {HELIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + NOBLE_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* AZURE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {INDIUM, LIGHT_USEFUL}, + {MOLYBDENUM, LIGHT_USEFUL}, + {VANADIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + AZURE_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* CHONDRITE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ + { + {ETHANOL, HEAVY_USEFUL}, + {FREE_RADICALS, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CHONDRITE_COLOR_TAB, + CHONDRITE_XLAT_TAB, + 500, 1, 100, 190, + }, + { /* PURPLE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {RHENIUM, MEDIUM_USEFUL}, + {CADMIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + PURPLE_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* SUPER_DENSE_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (SUPER_DENSITY, HEAVY), /* Atmosphere and density */ + { + {LEAD, MEDIUM_USEFUL}, + {OSMIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + SUPER_DENSE_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* PELLUCID_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {TZO_CRYSTALS, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + PELLUCID_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* DUST_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + RED_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {BISMUTH, LIGHT_USEFUL}, + {ALUMINUM, LIGHT_USEFUL}, + {POTASSIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + DUST_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* CRIMSON_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + RED_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ + { + {BARIUM, LIGHT_USEFUL}, + {BORON, LIGHT_USEFUL}, + {BERYLLIUM, LIGHT_USEFUL}, + {BISMUTH, LIGHT_USEFUL}, + {BROMINE, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + MAROON_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* CIMMERIAN_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + RED_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ + { + {METHANE, MEDIUM_USEFUL}, + {AMMONIA, MEDIUM_USEFUL}, + {METHANOL, MEDIUM_USEFUL}, + {LITHIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CIMMERIAN_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* INFRARED_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + RED_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ + { + {MERCURY, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + INFRARED_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* SELENIC_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, + WHITE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {IRON, LIGHT_USEFUL}, + {ALUMINUM, LIGHT_USEFUL}, + {CALCIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + SELENIC_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* AURIC_WORLD */ + MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {GOLD, HUGE_USEFUL}, + {GOLD, HUGE_USEFUL}, + {GOLD, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + AURIC_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + + + { /* FLUORESCENT_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + VIOLET_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ + { + {TECHNETIUM, HUGE_USEFUL}, + {NEON, HUGE_USEFUL}, + {RADON, LIGHT_USEFUL}, + {POTASSIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + FLUORESCENT_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* ULTRAVIOLET_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + VIOLET_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ + { + {POLONIUM, HUGE_USEFUL}, + {GOLD, HUGE_USEFUL}, + {PHOSPHORUS, HUGE_USEFUL}, + {SCANDIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ULTRAVIOLET_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* PLUTONIC_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ + { + {BERYLLIUM, HUGE_USEFUL}, + {BORON, HUGE_USEFUL}, + {LANTHANUM, MEDIUM_USEFUL}, + {ASTATINE, MEDIUM_USEFUL}, + {FRANCIUM, MEDIUM_USEFUL}, + {TITANIUM, LIGHT_USEFUL}, + {CERIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + }, + PLUTONIC_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* RAINBOW_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {ACTINIUM, HEAVY_USEFUL}, + {THORIUM, HEAVY_USEFUL}, + {PROTACTINIUM, HEAVY_USEFUL}, + {NEPTUNIUM, HEAVY_USEFUL}, + {PLUTONIUM, HEAVY_USEFUL}, + {OZONE, HUGE_USEFUL}, + {OZONE, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + }, + RAINBOW_COLOR_TAB, + RAINBOW_XLAT_TAB, + 500, 1, 20, 100, + }, + { /* CRACKED_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + ORANGE_BODY), /* Color and type/size of planet */ + SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ + { + {PALLADIUM, HUGE_USEFUL}, + {IRIDIUM, HUGE_USEFUL}, + {TECHNETIUM, HUGE_USEFUL}, + {POLONIUM, HUGE_USEFUL}, + {SODIUM, HUGE_USEFUL}, + {MANGANESE, HUGE_USEFUL}, + {CHROMIUM, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + }, + CRACKED_COLOR_TAB, + CRACKED_XLAT_TAB, + 500, 1, 0, 185, + }, + { /* SAPPHIRE_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + CYAN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ + { + {REISBURG_HELICES, HUGE_USEFUL}, + {RT_SUPER_FLUID, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + SAPPHIRE_COLOR_TAB, + SAPPHIRE_XLAT_TAB, + 80, 1, 0, 128, + }, + { /* ORGANIC_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + CYAN_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {FREE_RADICALS, HEAVY_USEFUL}, + {FORMALDEHYDE, HEAVY_USEFUL}, + {CARBON, HEAVY_USEFUL}, + {CARBON_DIOXIDE, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ORGANIC_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* XENOLITHIC_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + CYAN_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {ALUMINUM, HUGE_USEFUL}, + {PLATINUM, LIGHT_USEFUL}, + {GERMANIUM, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + XENOLITHIC_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* REDUX_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {BROMINE, MEDIUM_USEFUL}, + {OXYGEN, MEDIUM_USEFUL}, + {FLUORINE, MEDIUM_USEFUL}, + {SULFUR, MEDIUM_USEFUL}, + {CHLORINE, MEDIUM_USEFUL}, + {IODINE, MEDIUM_USEFUL}, + {ZIRCONIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + }, + REDUX_COLOR_TAB, + REDUX_XLAT_TAB, + 500, 1, 0, 190, + }, + { /* PRIMORDIAL_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ + { + {CESIUM, MEDIUM_USEFUL}, + {BARIUM, MEDIUM_USEFUL}, + {RUBIDIUM, MEDIUM_USEFUL}, + {METHANE, HUGE_USEFUL}, + {AMMONIA, HUGE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + PRIMORDIAL_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 10, 200, + }, + { /* EMERALD_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ + { + {AGUUTI_NODULES, HUGE_USEFUL}, + {ANTIMATTER, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + EMERALD_COLOR_TAB, + SAPPHIRE_XLAT_TAB, + 80, 1, 0, 128, + }, + { /* CHLORINE_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {CHLORINE, HEAVY_USEFUL}, + {CHLORINE, HEAVY_USEFUL}, + {HYDROCHLORIC_ACID, HEAVY_USEFUL}, + {HYDROCHLORIC_ACID, HEAVY_USEFUL}, + {ZINC, LIGHT_USEFUL}, + {GALLIUM, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CHLORINE_COLOR_TAB, + CHLORINE_XLAT_TAB, + 500, 1, 0, 190, + }, + { /* MAGNETIC_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ + { + {ZINC, HEAVY_USEFUL}, + {NICKEL, MEDIUM_USEFUL}, + {MAGNETIC_MONOPOLES, TRACE_USEFUL}, + {NIOBIUM, LIGHT_USEFUL}, + {IRON, HEAVY_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + MAGNETIC_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* WATER_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {IRON, LIGHT_USEFUL}, + {ALUMINUM, LIGHT_USEFUL}, + {TIN, LIGHT_USEFUL}, + {LEAD, LIGHT_USEFUL}, + {URANIUM, TRACE_USEFUL}, + {MOLYBDENUM, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + WATER_COLOR_TAB, + CHLORINE_XLAT_TAB, + 500, 1, 0, 190, + }, + { /* TELLURIC_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ + { + {IRIDIUM, MEDIUM_USEFUL}, + {RUTHENIUM, MEDIUM_USEFUL}, + {THALLIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + TELLURIC_COLOR_TAB, + YTTRIC_XLAT_TAB, + 250, 2, 80, 200, + }, + { /* HYDROCARBON_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ + { + {HYDROCARBONS, HUGE_USEFUL}, + {BISMUTH, LIGHT_USEFUL}, + {TANTALUM, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + HYDROCARBON_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* IODINE_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {IODINE, HEAVY_USEFUL}, + {MAGNESIUM, LIGHT_USEFUL}, + {TUNGSTEN, TRACE_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + IODINE_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + { /* VINYLOGOUS_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ + { + {TITANIUM, LIGHT_USEFUL}, + {ARSENIC, LIGHT_USEFUL}, + {POTASSIUM, LIGHT_USEFUL}, + {RHENIUM, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + VINYLOGOUS_COLOR_TAB, + OPALESCENT_XLAT_TAB, + 400, 1, 100, 190, + }, + { /* RUBY_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + RED_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ + { + {TZO_CRYSTALS, HUGE_USEFUL}, + {NEUTRONIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + RUBY_COLOR_TAB, + SAPPHIRE_XLAT_TAB, + 80, 1, 0, 128, + }, + { /* MAGMA_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, + RED_BODY), /* Color and type/size of planet */ + SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ + { + {LEAD, LIGHT_USEFUL}, + {NICKEL, LIGHT_USEFUL}, + {IRON, LIGHT_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + MAGMA_COLOR_TAB, + QUASI_DEGENERATE_XLAT_TAB, + 500, 1, 0, 160, + }, + { /* MAROON_WORLD */ + MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, + RED_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ + { + {CESIUM, MEDIUM_USEFUL}, + {SILICON, MEDIUM_USEFUL}, + {PHOSPHORUS, MEDIUM_USEFUL}, + {RHODIUM, MEDIUM_USEFUL}, + {CADMIUM, MEDIUM_USEFUL}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CRIMSON_COLOR_TAB, + UREA_XLAT_TAB, + 230, 2, 200, 150, + }, + + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + BLUE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + BLU_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + CYAN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + CYA_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + GREEN_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + GRN_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + GRAY_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + GRY_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + ORANGE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + ORA_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + PURPLE_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + PUR_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + RED_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + RED_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + VIOLET_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + VIO_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, + { /* A Jupiter-like World */ + MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, + YELLOW_BODY), /* Color and type/size of planet */ + NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ + MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ + { + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + {NOTHING, NO_DEPOSIT}, + }, + YEL_GAS_COLOR_TAB, + GAS_XLAT_TAB, + 10, 2, 8, 29, + }, +}; + diff --git a/sc2/src/sc2code/planets/Makefile.am b/sc2/src/sc2code/planets/Makefile.am new file mode 100644 index 000000000..c39ca1396 --- /dev/null +++ b/sc2/src/sc2code/planets/Makefile.am @@ -0,0 +1,25 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I/usr/include/SDL \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libplanets.la + +libplanets_la_SOURCES = \ + cargo.c devices.c genburv.c genchmmr.c gencol.c gendru.c genilw.c \ + genmel.c genmyc.c genorz.c genpet.c genpku.c genrain.c gensam.c \ + genshof.c gensly.c gensol.c genspa.c gensup.c gensyr.c genthrad.c \ + gentopo.c genutw.c genvault.c genvux.c genwreck.c genzoq.c \ + genyeh.c lander.c lander.h lifeform.h oval.c planets.c plangen.c \ + planmap.c planscan.c pl_stuff.c pstarmap.c report.c roster.c \ + scan.c scan.h solarsys.c calc.c orbits.c surface.c + +noinst_HEADERS = \ + planets.h elemdata.h plandata.h sundata.h + diff --git a/sc2/src/sc2code/planets/calc.c b/sc2/src/sc2code/planets/calc.c new file mode 100644 index 000000000..eea9aa551 --- /dev/null +++ b/sc2/src/sc2code/planets/calc.c @@ -0,0 +1,398 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ----------------------------- INCLUDES ---------------------------- */ +#include "starcon.h" +/* -------------------------------- DATA -------------------------------- */ + +/* -------------------------------- CODE -------------------------------- */ + +#define CalcMass(b) CalcFromBase (b, b) +#define CalcRadius(b) CalcFromBase (b, ((b) >> 1) + 1) + +#define LOW_TEMP 0 +#define MED_TEMP 500 +#define HIGH_TEMP 1500 +#define LOW_TEMP_BONUS 10 +#define MED_TEMP_BONUS 25 +#define HIGH_TEMP_BONUS 50 +#define MAX_TECTONICS 255 +#ifdef OLD +#define CalcTectonics(b,t) (CalcFromBase(b, 3 << 5) \ + + (UWORD)((t) < LOW_TEMP ? 0 : \ + ((t) < MED_TEMP ? LOW_TEMP_BONUS : \ + ((t) < HIGH_TEMP ? MED_TEMP_BONUS : \ + HIGH_TEMP_BONUS)))) +#else /* OLD */ +#define CalcTectonics(b,t) CalcFromBase(b, 3 << 5) +#endif /* OLD */ + +enum +{ + RED_SUN_INTENSITY = 0, + ORANGE_SUN_INTENSITY, + YELLOW_SUN_INTENSITY, + GREEN_SUN_INTENSITY, + BLUE_SUN_INTENSITY, + WHITE_SUN_INTENSITY +}; + +static void +CalcSysInfo (SYSTEM_INFOPTR SysInfoPtr) +{ + SysInfoPtr->StarSize = pSolarSysState->SunDesc[0].data_index; + switch (STAR_COLOR (CurStarDescPtr->Type)) + { + case BLUE_BODY: + SysInfoPtr->StarIntensity = BLUE_SUN_INTENSITY; + break; + case GREEN_BODY: + SysInfoPtr->StarIntensity = GREEN_SUN_INTENSITY; + break; + case ORANGE_BODY: + SysInfoPtr->StarIntensity = ORANGE_SUN_INTENSITY; + break; + case RED_BODY: + SysInfoPtr->StarIntensity = RED_SUN_INTENSITY; + break; + case WHITE_BODY: + SysInfoPtr->StarIntensity = WHITE_SUN_INTENSITY; + break; + case YELLOW_BODY: + SysInfoPtr->StarIntensity = YELLOW_SUN_INTENSITY; + break; + } + + switch (STAR_TYPE (CurStarDescPtr->Type)) + { + case DWARF_STAR: + SysInfoPtr->StarEnergy = + (SysInfoPtr->StarIntensity + 1) * DWARF_ENERGY; + break; + case GIANT_STAR: + SysInfoPtr->StarEnergy = + (SysInfoPtr->StarIntensity + 1) * GIANT_ENERGY; + break; + case SUPER_GIANT_STAR: + SysInfoPtr->StarEnergy = + (SysInfoPtr->StarIntensity + 1) * SUPERGIANT_ENERGY; + break; + } +} + +static UWORD +GeneratePlanetComposition (PLANET_INFOPTR PlanetInfoPtr, SIZE + SurfaceTemp, SIZE radius) +{ + if (PLANSIZE (PlanetInfoPtr->PlanDataPtr->Type) == GAS_GIANT) + { + PlanetInfoPtr->Weather = 7 << 5; + return (GAS_GIANT_ATMOSPHERE); + } + else + { + BYTE range; + UWORD atmo; + + PlanetInfoPtr->Weather = 0; + atmo = 0; + if ((range = HINIBBLE (PlanetInfoPtr->PlanDataPtr->AtmoAndDensity)) <= HEAVY) + { + if (SurfaceTemp < COLD_THRESHOLD) + --range; + else if (SurfaceTemp > HOT_THRESHOLD) + ++range; + + if (range <= HEAVY + 1) + { + switch (range) + { + case LIGHT: + atmo = THIN_ATMOSPHERE; + PlanetInfoPtr->Weather = 1 << 5; + break; + case MEDIUM: + atmo = NORMAL_ATMOSPHERE; + PlanetInfoPtr->Weather = 2 << 5; + break; + case HEAVY: + atmo = THICK_ATMOSPHERE; + PlanetInfoPtr->Weather = 4 << 5; + break; + default: + atmo = SUPER_THICK_ATMOSPHERE; + PlanetInfoPtr->Weather = 6 << 5; + break; + } + + radius /= EARTH_RADIUS; + if (radius < 2) + PlanetInfoPtr->Weather += 1 << 5; + else if (radius > 10) + PlanetInfoPtr->Weather -= 1 << 5; + atmo = CalcFromBase (atmo, (atmo >> 1) + 1); + } + } + + return (atmo); + } +} + +static SIZE +CalcTemp (SYSTEM_INFOPTR SysInfoPtr, SIZE radius) +{ +#define GENERIC_ALBEDO 33 /* In %, 0=black, 100 is reflective */ +#define ADJUST_FOR_KELVIN 273 +#define PLANET_TEMP_CONSTANT 277L + DWORD alb; + SIZE centigrade, bonus; + + alb = 100 - GENERIC_ALBEDO; + alb = square_root (square_root (alb * 100 * 10000)) + * PLANET_TEMP_CONSTANT * SysInfoPtr->StarEnergy + / ((YELLOW_SUN_INTENSITY + 1) * DWARF_ENERGY); + + centigrade = (SIZE)(alb / square_root (radius * 10000L / EARTH_RADIUS)) + - ADJUST_FOR_KELVIN; + + bonus = 0; + if (SysInfoPtr == &pSolarSysState->SysInfo + && HINIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity) <= HEAVY) + { +#define COLD_BONUS 20 +#define HOT_BONUS 200 + if (centigrade >= HOT_THRESHOLD) + bonus = HOT_BONUS; + else if (centigrade >= COLD_THRESHOLD) + bonus = COLD_BONUS; + + bonus <<= HINIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity); + bonus = CalcFromBase (bonus, (bonus >> 1) + 1); + } + + return (centigrade + bonus); +} + +static COUNT +CalcRotation (PLANET_INFOPTR PlanetInfoPtr) +{ + if (PLANSIZE (PlanetInfoPtr->PlanDataPtr->Type) == GAS_GIANT) + return ((COUNT)CalcFromBase (80, 80)); + else if (((BYTE)Random () % 10) == 0) + return ((COUNT)CalcFromBase ((UWORD)50 * 240, (UWORD)200 * 240)); + else + return ((COUNT)CalcFromBase (150, 150)); +} + +static SIZE +CalcTilt (void) +{ /* Calculate Axial Tilt */ + SIZE tilt; + BYTE i; + +#define NUM_TOSSES 10 +#define TILT_RANGE 180 + tilt = -(TILT_RANGE / 2); + i = NUM_TOSSES; + do /* Using added Randomom values to give bell curve */ + { + tilt += (UWORD)Random () % ((TILT_RANGE / NUM_TOSSES) + 1); + } while (--i); + + return (tilt); +} + +DWORD +DoPlanetaryAnalysis (SYSTEM_INFOPTR SysInfoPtr, PPLANET_DESC + pPlanetDesc) +{ + DWORD old_seed; + + /* Earth Starbase */ + if (pPlanetDesc->data_index == (BYTE)~0) + return (0); + + old_seed = SeedRandom (pPlanetDesc->rand_seed); + + CalcSysInfo (SysInfoPtr); + +#ifdef DEBUG +{ + BYTE ColorClass[6][8] = { + "Red", + "Orange", + "Yellow", + "Green", + "Blue", + "White", + } ; + BYTE SizeName[3][12] = { + "Dwarf", + "Giant", + "Supergiant", + }; + + printf ("%s %s\n", + ColorClass[SysInfoPtr->StarIntensity], + SizeName[SysInfoPtr->StarSize]); + printf ("Stellar Energy: %d (sol = 3)\n", SysInfoPtr->StarEnergy); +} +#endif /* DEBUG */ + + { + SIZE radius; + + SysInfoPtr->PlanetInfo.PlanDataPtr = + &PlanData[pPlanetDesc->data_index & ~PLANET_SHIELDED]; + + if (pPlanetDesc->pPrevDesc == pSolarSysState->SunDesc) + radius = pPlanetDesc->radius; + else + radius = pPlanetDesc->pPrevDesc->radius; + SysInfoPtr->PlanetInfo.PlanetToSunDist = radius; + + SysInfoPtr->PlanetInfo.SurfaceTemperature = + CalcTemp (SysInfoPtr, radius); + switch (LONIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity)) + { + case GAS_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 20; + break; + case LIGHT_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 33; + break; + case LOW_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 60; + break; + case NORMAL_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 100; + break; + case HIGH_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 150; + break; + case SUPER_DENSITY: + SysInfoPtr->PlanetInfo.PlanetDensity = 200; + break; + } + SysInfoPtr->PlanetInfo.PlanetDensity += + (SysInfoPtr->PlanetInfo.PlanetDensity / 20) + - ((COUNT)Random () + % (SysInfoPtr->PlanetInfo.PlanetDensity / 10)); + + switch (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type)) + { + case SMALL_ROCKY_WORLD: +#define SMALL_RADIUS 25 + SysInfoPtr->PlanetInfo.PlanetRadius = CalcRadius (SMALL_RADIUS); + break; + case LARGE_ROCKY_WORLD: +#define LARGE_RADIUS 75 + SysInfoPtr->PlanetInfo.PlanetRadius = CalcRadius (LARGE_RADIUS); + break; + case GAS_GIANT: +#define MIN_GAS_RADIUS 300 +#define MAX_GAS_RADIUS 1500 + SysInfoPtr->PlanetInfo.PlanetRadius = + CalcFromBase (MIN_GAS_RADIUS, MAX_GAS_RADIUS - MIN_GAS_RADIUS); + break; + } + + SysInfoPtr->PlanetInfo.RotationPeriod = CalcRotation (&SysInfoPtr->PlanetInfo); + SysInfoPtr->PlanetInfo.SurfaceGravity = + CalcGravity (SysInfoPtr->PlanetInfo.PlanetDensity, + SysInfoPtr->PlanetInfo.PlanetRadius); + SysInfoPtr->PlanetInfo.AxialTilt = CalcTilt (); + if ((SysInfoPtr->PlanetInfo.Tectonics = + CalcTectonics (SysInfoPtr->PlanetInfo.PlanDataPtr->BaseTectonics, + SysInfoPtr->PlanetInfo.SurfaceTemperature)) > MAX_TECTONICS) + SysInfoPtr->PlanetInfo.Tectonics = MAX_TECTONICS; + + SysInfoPtr->PlanetInfo.AtmoDensity = + GeneratePlanetComposition (&SysInfoPtr->PlanetInfo, + SysInfoPtr->PlanetInfo.SurfaceTemperature, radius); + + SysInfoPtr->PlanetInfo.Tectonics >>= 5; + SysInfoPtr->PlanetInfo.Weather >>= 5; + +#ifdef DEBUG + radius = (SIZE)((DWORD)UNSCALE_RADIUS (radius) * 100 / UNSCALE_RADIUS (EARTH_RADIUS)); + printf ("\tOrbital Distance : %d.%02d AU\n", radius / 100, radius % 100); + //printf ("\tPlanetary Mass : %d.%02d Earth masses\n", + // SysInfoPtr->PlanetInfo.PlanetMass / 100, + // SysInfoPtr->PlanetInfo.PlanetMass % 100); + printf ("\tPlanetary Radius : %d.%02d Earth radii\n", + SysInfoPtr->PlanetInfo.PlanetRadius / 100, + SysInfoPtr->PlanetInfo.PlanetRadius % 100); + printf ("\tSurface Gravity: %d.%02d gravities\n", + SysInfoPtr->PlanetInfo.SurfaceGravity / 100, + SysInfoPtr->PlanetInfo.SurfaceGravity % 100); + printf ("\tSurface Temperature: %d degrees C\n", + SysInfoPtr->PlanetInfo.SurfaceTemperature ); + printf ("\tAxial Tilt : %d degrees\n", + abs (SysInfoPtr->PlanetInfo.AxialTilt)); + printf ("\tTectonics : Class %u\n", + SysInfoPtr->PlanetInfo.Tectonics + 1); + printf ("\tAtmospheric Density: %u.%02u ", + SysInfoPtr->PlanetInfo.AtmoDensity / EARTH_ATMOSPHERE, + (SysInfoPtr->PlanetInfo.AtmoDensity * 100 / EARTH_ATMOSPHERE) % 100); + if (SysInfoPtr->PlanetInfo.AtmoDensity == 0) + { + printf ("(Vacuum)\n"); + } + else if (SysInfoPtr->PlanetInfo.AtmoDensity < THIN_ATMOSPHERE) + { + printf ("(Thin)\n"); + } + else if (SysInfoPtr->PlanetInfo.AtmoDensity < NORMAL_ATMOSPHERE) + { + printf ("(Normal)\n"); + } + else if (SysInfoPtr->PlanetInfo.AtmoDensity < THICK_ATMOSPHERE) + { + printf ("(Thick)\n"); + } + else if (SysInfoPtr->PlanetInfo.AtmoDensity < SUPER_THICK_ATMOSPHERE) + { + printf ("(Super thick)\n"); + } + else + { + printf ("(Gas Giant atmosphere)\n"); + } + + printf ("\tWeather : Class %u\n", + SysInfoPtr->PlanetInfo.Weather + 1); + + if (SysInfoPtr->PlanetInfo.RotationPeriod >= 480) + { + printf ("\tLength of day : %d.%d Earth days\n", + SysInfoPtr->PlanetInfo.RotationPeriod / 240, + SysInfoPtr->PlanetInfo.RotationPeriod % 240); + } + else + { + printf ("\tLength of day : %d.%d Earth hours\n", + SysInfoPtr->PlanetInfo.RotationPeriod / 10, + SysInfoPtr->PlanetInfo.RotationPeriod % 10); + } +#endif /* DEBUG */ + } + + return (SeedRandom (old_seed)); +} + diff --git a/sc2/src/sc2code/planets/cargo.c b/sc2/src/sc2code/planets/cargo.c new file mode 100644 index 000000000..6329162db --- /dev/null +++ b/sc2/src/sc2code/planets/cargo.c @@ -0,0 +1,362 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +//Added by Chris + +void DrawCargoStrings (BYTE OldElement, BYTE NewElement); + +//End Added by Chris + +void +ShowRemainingCapacity (void) +{ + RECT r; + TEXT rt; + CONTEXT OldContext; + UNICODE rt_amount_buf[10]; + + OldContext = SetContext (StatusContext); + SetContextFont (TinyFont); + + wsprintf (rt_amount_buf, "%u", + GetSBayCapacity (NULL_PTR) + - GLOBAL_SIS (TotalElementMass)); + rt.baseline.x = 59; + rt.baseline.y = 113; + rt.align = ALIGN_RIGHT; + rt.pStr = rt_amount_buf; + rt.CharCount = (COUNT)~0; + + r.corner.x = 40; + r.corner.y = rt.baseline.y - 6; + r.extent.width = rt.baseline.x - r.corner.x + 1; + r.extent.height = 7; + + BatchGraphics (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + DrawText (&rt); + UnbatchGraphics (); + + SetContext (OldContext); +} + +void +DrawCargoStrings (BYTE OldElement, BYTE NewElement) +{ + COORD y, cy; + TEXT rt; + RECT r; + CONTEXT OldContext; + UNICODE rt_amount_buf[10]; + + SetSemaphore (&GraphicsSem); + + OldContext = SetContext (StatusContext); + SetContextFont (TinyFont); + + BatchGraphics (); + + y = 41; + rt.align = ALIGN_RIGHT; + rt.pStr = rt_amount_buf; + + if (OldElement > NUM_ELEMENT_CATEGORIES) + { + STAMP s; + extern FRAME misc_data; + + r.corner.x = 2; + r.extent.width = FIELD_WIDTH + 1; + + { + TEXT ct; + + r.corner.y = 20; + r.extent.height = 109; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + + SetContextFont (StarConFont); + ct.baseline.x = (STATUS_WIDTH >> 1) - 1; + ct.baseline.y = 27; + ct.align = ALIGN_CENTER; + ct.pStr = GAME_STRING (CARGO_STRING_BASE); + ct.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + DrawText (&ct); + + SetContextFont (TinyFont); + } + + r.corner.x = 7; + r.extent.width = 7; + r.extent.height = 7; + + s.origin.x = r.corner.x + (r.extent.width >> 1); + s.frame = SetAbsFrameIndex ( + misc_data, + (NUM_SCANDOT_TRANSITIONS << 1) + 3 + ); + cy = y; + + rt.baseline.y = cy - 7; + rt.CharCount = 1; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + rt.baseline.x = 32; + rt_amount_buf[0] = '$'; + DrawText (&rt); + + rt.baseline.x = 58; + rt_amount_buf[0] = '#'; + DrawText (&rt); + + for (OldElement = 0; + OldElement < NUM_ELEMENT_CATEGORIES; ++OldElement) + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = cy - 6; + DrawFilledRectangle (&r); + + s.origin.y = r.corner.y + (r.extent.height >> 1); + DrawStamp (&s); + s.frame = SetRelFrameIndex (s.frame, 5); + + if (OldElement != NewElement) + { + rt.baseline.y = cy; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + rt.baseline.x = 32; + wsprintf (rt_amount_buf, "%u", + GLOBAL (ElementWorth[OldElement])); + rt.CharCount = (COUNT)~0; + DrawText (&rt); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + rt.baseline.x = 58; + wsprintf (rt_amount_buf, "%u", + GLOBAL_SIS (ElementAmounts[OldElement])); + rt.CharCount = (COUNT)~0; + DrawText (&rt); + } + + cy += 9; + } + + OldElement = NewElement; + + rt.baseline.y = 125; + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = rt.baseline.y - 6; + DrawFilledRectangle (&r); + + s.origin.y = r.corner.y + (r.extent.height >> 1); + s.frame = SetAbsFrameIndex (s.frame, 68); + DrawStamp (&s); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + rt.baseline.x = 58; + wsprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); + rt.CharCount = (COUNT)~0; + DrawText (&rt); + + r.corner.x = 4; + r.corner.y = 117; + r.extent.width = 56; + r.extent.height = 1; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + DrawFilledRectangle (&r); + + { + TEXT lt; + + lt.baseline.x = 5; + lt.baseline.y = 113; + lt.align = ALIGN_LEFT; + lt.pStr = GAME_STRING (CARGO_STRING_BASE + 1); + lt.CharCount = (COUNT)~0; + DrawText (<); + } + + ShowRemainingCapacity (); + } + + r.corner.x = 19; + r.extent.width = 40; + r.extent.height = 7; + + if (OldElement != NewElement) + { + if (OldElement == NUM_ELEMENT_CATEGORIES) + cy = 125; + else + cy = y + (OldElement * 9); + r.corner.y = cy - 6; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + + rt.baseline.y = cy; + + if (OldElement == NUM_ELEMENT_CATEGORIES) + wsprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); + else + { + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + rt.baseline.x = 32; + wsprintf (rt_amount_buf, "%u", GLOBAL (ElementWorth[OldElement])); + rt.CharCount = (COUNT)~0; + DrawText (&rt); + wsprintf (rt_amount_buf, "%u", GLOBAL_SIS (ElementAmounts[OldElement])); + } + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + rt.baseline.x = 58; + rt.CharCount = (COUNT)~0; + DrawText (&rt); + } + + if (NewElement != (BYTE)~0) + { + if (NewElement == NUM_ELEMENT_CATEGORIES) + cy = 125; + else + cy = y + (NewElement * 9); + r.corner.y = cy - 6; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + DrawFilledRectangle (&r); + + rt.baseline.y = cy; + + if (NewElement == NUM_ELEMENT_CATEGORIES) + wsprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); + else + { + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + rt.baseline.x = 32; + wsprintf (rt_amount_buf, "%u", GLOBAL (ElementWorth[NewElement])); + rt.CharCount = (COUNT)~0; + DrawText (&rt); + wsprintf (rt_amount_buf, "%u", GLOBAL_SIS (ElementAmounts[NewElement])); + } + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + rt.baseline.x = 58; + rt.CharCount = (COUNT)~0; + DrawText (&rt); + } + + UnbatchGraphics (); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); +} + +static BOOLEAN +DoDiscardCargo (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE NewState; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (!(pMS->Initialized & 1)) + { + pMS->InputFunc = DoDiscardCargo; + ++pMS->Initialized; + + NewState = pMS->CurState; + pMS->CurState = (BYTE)~0; + goto SelectCargo; + } + else if (InputState & DEVICE_BUTTON2) + { + SetSemaphore (&GraphicsSem); + ClearSISRect (DRAW_SIS_DISPLAY); + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + if (GLOBAL_SIS (ElementAmounts[pMS->CurState - 1])) + { + --GLOBAL_SIS (ElementAmounts[pMS->CurState - 1]); + DrawCargoStrings ((BYTE)(pMS->CurState - 1), (BYTE)(pMS->CurState - 1)); + + SetSemaphore (&GraphicsSem); + --GLOBAL_SIS (TotalElementMass); + ShowRemainingCapacity (); + ClearSemaphore (&GraphicsSem); + } + } + else + { + NewState = pMS->CurState - 1; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == 0) + NewState = NUM_ELEMENT_CATEGORIES - 1; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (++NewState == NUM_ELEMENT_CATEGORIES) + NewState = 0; + } + + if (++NewState != pMS->CurState) + { +SelectCargo: + DrawCargoStrings ((BYTE)(pMS->CurState - 1), (BYTE)(NewState - 1)); + SetSemaphore (&GraphicsSem); + DrawStatusMessage (GAME_STRING (NewState - 1 + (CARGO_STRING_BASE + 2))); + ClearSemaphore (&GraphicsSem); + + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +void +Cargo (PMENU_STATE pMS) +{ + pMS->InputFunc = DoDiscardCargo; + --pMS->Initialized; + pMS->CurState = 1; + + SetSemaphore (&GraphicsSem); + DrawStatusMessage ((UNICODE *)~0); + ClearSemaphore (&GraphicsSem); + + DoInput ((PVOID)pMS); + + pMS->InputFunc = DoFlagshipCommands; + pMS->CurState = CARGO + 1; +} + diff --git a/sc2/src/sc2code/planets/devices.c b/sc2/src/sc2code/planets/devices.c new file mode 100644 index 000000000..66eb4d525 --- /dev/null +++ b/sc2/src/sc2code/planets/devices.c @@ -0,0 +1,646 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static COUNT +lpstrchr (UNICODE *pStr, UNICODE ch) +{ + COUNT skip_chars; + + skip_chars = 0; + while (*pStr++ != ch) + ++skip_chars; + + return (skip_chars); +} + +static void +DrawDevices (PMENU_STATE pMS, BYTE OldDevice, BYTE NewDevice) +{ +#define MAX_VIS_DEVICES 5 + COORD y, cy; + TEXT t; + RECT r; + PBYTE pDeviceMap; + + SetSemaphore (&GraphicsSem); + + SetContext (StatusContext); + SetContextFont (TinyFont); + + y = 41; + t.baseline.x = 40; + t.align = ALIGN_CENTER; + t.CharCount = 3; + + pDeviceMap = (PBYTE)pMS->CurFrame; + if (OldDevice > NUM_DEVICES + || (NewDevice < NUM_DEVICES + && (NewDevice < (BYTE)pMS->first_item.y + || NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)))) + { + STAMP s; + extern FRAME misc_data; + + r.corner.x = 2; + r.extent.width = FIELD_WIDTH + 1; + + if (!(pMS->Initialized & 1)) + { + ++r.corner.x; + r.extent.width -= 2; + r.corner.y = 33; + r.extent.height = 89; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + } + else + { + TEXT ct; + + r.corner.y = 20; + r.extent.height = 109; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + + SetContextFont (StarConFont); + ct.baseline.x = (STATUS_WIDTH >> 1) - 1; + ct.baseline.y = 27; + ct.align = ALIGN_CENTER; + ct.pStr = GAME_STRING (DEVICE_STRING_BASE); + ct.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + DrawText (&ct); + + SetContextFont (TinyFont); + } + + if (NewDevice < (BYTE)pMS->first_item.y) + pMS->first_item.y = NewDevice; + else if (NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)) + pMS->first_item.y = NewDevice - (MAX_VIS_DEVICES - 1); + + s.origin.x = 4; + s.origin.y = 34; + cy = y; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + for (OldDevice = (BYTE)pMS->first_item.y; + OldDevice < (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES) + && OldDevice < (BYTE)pMS->first_item.x; + ++OldDevice) + { + s.frame = SetAbsFrameIndex ( + misc_data, 77 + pDeviceMap[OldDevice] + ); + DrawStamp (&s); + + if (OldDevice != NewDevice) + { + t.baseline.y = cy; + t.pStr = GAME_STRING (pDeviceMap[OldDevice] + DEVICE_STRING_BASE + 1); + t.CharCount = lpstrchr (t.pStr, ' '); + DrawText (&t); + t.baseline.y += 7; + t.pStr += t.CharCount + 1; + t.CharCount = (COUNT)~0; + DrawText (&t); + } + + cy += 18; + s.origin.y += 18; + } + + OldDevice = NewDevice; + } + + r.extent.width = 41; + r.extent.height = 14; + r.corner.x = t.baseline.x - (r.extent.width >> 1); + + if (OldDevice != NewDevice) + { + cy = y + ((OldDevice - pMS->first_item.y) * 18); + r.corner.y = cy - 6; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + t.baseline.y = cy; + t.pStr = GAME_STRING (pDeviceMap[OldDevice] + DEVICE_STRING_BASE + 1); + t.CharCount = lpstrchr (t.pStr, ' '); + DrawText (&t); + t.baseline.y += 7; + t.pStr += t.CharCount + 1; + t.CharCount = (COUNT)~0; + DrawText (&t); + } + + if (NewDevice < NUM_DEVICES) + { + cy = y + ((NewDevice - pMS->first_item.y) * 18); + r.corner.y = cy - 6; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + t.baseline.y = cy; + t.pStr = GAME_STRING (pDeviceMap[NewDevice] + DEVICE_STRING_BASE + 1); + t.CharCount = lpstrchr (t.pStr, ' '); + DrawText (&t); + t.baseline.y += 7; + t.pStr += t.CharCount + 1; + t.CharCount = (COUNT)~0; + DrawText (&t); + } + + ClearSemaphore (&GraphicsSem); +} + +static UWORD +DeviceFailed (BYTE which_device) +{ + BYTE val; + extern ACTIVITY NextActivity; + extern void SaveFlagshipState (void); + + switch (which_device) + { + case ROSY_SPHERE_DEVICE: + val = GET_GAME_STATE (ULTRON_CONDITION); + if (val) + { + SET_GAME_STATE (ULTRON_CONDITION, val + 1); + SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 0); + SET_GAME_STATE (DISCUSSED_ULTRON, 0); + SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); + return (FALSE); + } + break; + case ARTIFACT_2_DEVICE: + break; + case ARTIFACT_3_DEVICE: + break; + case SUN_EFFICIENCY_DEVICE: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && pSolarSysState + && pSolarSysState->pOrbitalDesc + && pSolarSysState->MenuState.Initialized == 3) + { + BYTE fade_buf[1]; + + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 3), + 0, GAME_SOUND_PRIORITY); + fade_buf[0] = FadeAllToWhite; + SleepTask (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND * 1) + + (ONE_SECOND * 2)); + if (CurStarDescPtr->Index != CHMMR_DEFINED + || pSolarSysState->pOrbitalDesc != + &pSolarSysState->PlanetDesc[1]) + { + fade_buf[0] = FadeAllToColor; + XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND * 2); + } + else + { + SET_GAME_STATE (CHMMR_EMERGING, 1); + + battle_counter = 0; + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (CHMMR_SHIP, + &GLOBAL (npc_built_ship_q), 0); + } + return (MAKE_WORD (0, 1)); + } + break; + case UTWIG_BOMB_DEVICE: + SET_GAME_STATE (UTWIG_BOMB, 0); + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; + return (FALSE); + case ULTRON_0_DEVICE: + break; + case ULTRON_1_DEVICE: + break; + case ULTRON_2_DEVICE: + break; + case ULTRON_3_DEVICE: + break; + case MAIDENS_DEVICE: + break; + case TALKING_PET_DEVICE: + NextActivity |= CHECK_LOAD; /* fake a load game */ + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + if (GetHeadEncounter ()) + { + SET_GAME_STATE (SHIP_TO_COMPEL, 1); + } + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + } + else + { + battle_counter = 0; + if (GetHeadLink (&GLOBAL (npc_built_ship_q))) + { + SET_GAME_STATE (SHIP_TO_COMPEL, 1); + + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + } + + if (CurStarDescPtr->Index == SAMATRA_DEFINED) + { + SET_GAME_STATE (READY_TO_CONFUSE_URQUAN, 1); + } + if (pSolarSysState->MenuState.Initialized < 3) + return (FALSE); + } + SaveFlagshipState (); + return (FALSE); + case AQUA_HELIX_DEVICE: + val = GET_GAME_STATE (ULTRON_CONDITION); + if (val) + { + SET_GAME_STATE (ULTRON_CONDITION, val + 1); + SET_GAME_STATE (AQUA_HELIX_ON_SHIP, 0); + SET_GAME_STATE (DISCUSSED_ULTRON, 0); + SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); + return (FALSE); + } + break; + case CLEAR_SPINDLE_DEVICE: + val = GET_GAME_STATE (ULTRON_CONDITION); + if (val) + { + SET_GAME_STATE (ULTRON_CONDITION, val + 1); + SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 0); + SET_GAME_STATE (DISCUSSED_ULTRON, 0); + SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); + return (FALSE); + } + break; + case UMGAH_HYPERWAVE_DEVICE: + case BURVIX_HYPERWAVE_DEVICE: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + SET_GAME_STATE (USED_BROADCASTER, 1); + return (FALSE); + } + } + else if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && pSolarSysState) + { + if (pSolarSysState->pOrbitalDesc == + &pSolarSysState->PlanetDesc[1] + && pSolarSysState->MenuState.Initialized == 3 + && CurStarDescPtr->Index == CHMMR_DEFINED + && !GET_GAME_STATE (CHMMR_UNLEASHED)) + { + NextActivity |= CHECK_LOAD; /* fake a load game */ + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + + battle_counter = 0; + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + SaveFlagshipState (); + return (FALSE); + } + else + { + BOOLEAN FoundIlwrath; + HSTARSHIP hStarShip; + + FoundIlwrath = (BOOLEAN)( + CurStarDescPtr->Index == ILWRATH_DEFINED + ); + if (!FoundIlwrath && (hStarShip = + GetHeadLink (&GLOBAL (npc_built_ship_q)))) + { + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + FoundIlwrath = (BOOLEAN)( + GET_RACE_ID (FragPtr) == ILWRATH_SHIP + ); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + + if (FoundIlwrath) + { + NextActivity |= CHECK_LOAD; /* fake a load game */ + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + + battle_counter = 0; + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (CurStarDescPtr->Index == ILWRATH_DEFINED) + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 4); + } + else + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 5); + } + if (pSolarSysState->MenuState.Initialized >= 3) + SaveFlagshipState (); + return (FALSE); + } + } + } + break; + case TAALO_PROTECTOR_DEVICE: + break; + case EGG_CASING0_DEVICE: + case EGG_CASING1_DEVICE: + case EGG_CASING2_DEVICE: + break; + case SYREEN_SHUTTLE_DEVICE: + break; + case VUX_BEAST_DEVICE: + break; + case DESTRUCT_CODE_DEVICE: + break; + case PORTAL_SPAWNER_DEVICE: +#define PORTAL_FUEL_COST (10 * FUEL_TANK_SCALE) + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE + && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1 + && GLOBAL_SIS (FuelOnBoard) >= PORTAL_FUEL_COST) + { + /* don't want to DeltaSISGauges + * because the flagship picture + * is currently obscured + */ + GLOBAL_SIS (FuelOnBoard) -= PORTAL_FUEL_COST; + SET_GAME_STATE (PORTAL_COUNTER, 1); + return (FALSE); + } + break; + case URQUAN_WARP_DEVICE: + break; + case LUNAR_BASE_DEVICE: + break; + } + + return (TRUE); +} + +static BOOLEAN +DoManipulateDevices (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE NewState; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (!(pMS->Initialized & 1)) + { + DrawDevices (pMS, (BYTE)~0, (BYTE)~0); + + pMS->InputFunc = DoManipulateDevices; + ++pMS->Initialized; + NewState = pMS->CurState; + goto SelectDevice; + } + else if (InputState & DEVICE_BUTTON2) + { + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + UWORD status; + + SetSemaphore (&GraphicsSem); + status = DeviceFailed ( + ((PBYTE)pMS->CurFrame)[pMS->CurState - 1] + ); + NewState = LOBYTE (status); + if (NewState) + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 2), + 0, GAME_SOUND_PRIORITY); + else if (HIBYTE (status) == 0) + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 3), + 0, GAME_SOUND_PRIORITY); + ClearSemaphore (&GraphicsSem); + + return ((BOOLEAN)NewState); + } + else + { + SIZE NewTop; + + NewTop = pMS->first_item.y; + NewState = pMS->CurState - 1; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == 0) + NewState = 0; + + if ((SIZE)NewState < NewTop && (NewTop -= MAX_VIS_DEVICES) < 0) + NewTop = 0; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (++NewState == (BYTE)pMS->first_item.x) + NewState = (BYTE)(pMS->first_item.x - 1); + + if (NewState >= NewTop + MAX_VIS_DEVICES) + NewTop = NewState; + } + + if (++NewState != pMS->CurState) + { + if (NewTop != pMS->first_item.y) + { + pMS->first_item.y = NewTop; + pMS->CurState = (BYTE)~0; + } +SelectDevice: + DrawDevices (pMS, (BYTE)(pMS->CurState - 1), (BYTE)(NewState - 1)); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +SIZE +InventoryDevices (BYTE *pDeviceMap) +{ + BYTE i; + SIZE DevicesOnBoard; + + DevicesOnBoard = 0; + for (i = 0; i < NUM_DEVICES; ++i) + { + BYTE DeviceState; + + DeviceState = 0; + switch (i) + { + case ROSY_SPHERE_DEVICE: + DeviceState = GET_GAME_STATE (ROSY_SPHERE_ON_SHIP); + break; + case ARTIFACT_2_DEVICE: + DeviceState = GET_GAME_STATE (ARTIFACT_2_ON_SHIP); + break; + case ARTIFACT_3_DEVICE: + DeviceState = GET_GAME_STATE (ARTIFACT_3_ON_SHIP); + break; + case SUN_EFFICIENCY_DEVICE: + DeviceState = GET_GAME_STATE (SUN_DEVICE_ON_SHIP); + break; + case UTWIG_BOMB_DEVICE: + DeviceState = GET_GAME_STATE (UTWIG_BOMB_ON_SHIP); + break; + case ULTRON_0_DEVICE: + DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 1); + break; + case ULTRON_1_DEVICE: + DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 2); + break; + case ULTRON_2_DEVICE: + DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 3); + break; + case ULTRON_3_DEVICE: + DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 4); + break; + case MAIDENS_DEVICE: + DeviceState = GET_GAME_STATE (MAIDENS_ON_SHIP); + break; + case TALKING_PET_DEVICE: + DeviceState = GET_GAME_STATE (TALKING_PET_ON_SHIP); + break; + case AQUA_HELIX_DEVICE: + DeviceState = GET_GAME_STATE (AQUA_HELIX_ON_SHIP); + break; + case CLEAR_SPINDLE_DEVICE: + DeviceState = GET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP); + break; + case UMGAH_HYPERWAVE_DEVICE: + DeviceState = GET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP); + break; + case TAALO_PROTECTOR_DEVICE: + DeviceState = GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP); + break; + case EGG_CASING0_DEVICE: + DeviceState = GET_GAME_STATE (EGG_CASE0_ON_SHIP); + break; + case EGG_CASING1_DEVICE: + DeviceState = GET_GAME_STATE (EGG_CASE1_ON_SHIP); + break; + case EGG_CASING2_DEVICE: + DeviceState = GET_GAME_STATE (EGG_CASE2_ON_SHIP); + break; + case SYREEN_SHUTTLE_DEVICE: + DeviceState = GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP); + break; + case VUX_BEAST_DEVICE: + DeviceState = GET_GAME_STATE (VUX_BEAST_ON_SHIP); + break; + case DESTRUCT_CODE_DEVICE: +#ifdef NEVER + DeviceState = GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP); +#endif /* NEVER */ + break; + case PORTAL_SPAWNER_DEVICE: + DeviceState = GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP); + break; + case URQUAN_WARP_DEVICE: + DeviceState = GET_GAME_STATE (PORTAL_KEY_ON_SHIP); + break; + case BURVIX_HYPERWAVE_DEVICE: + DeviceState = GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP); + break; + case LUNAR_BASE_DEVICE: + DeviceState = GET_GAME_STATE (MOONBASE_ON_SHIP); + break; + } + +#ifndef DEBUG + if (DeviceState) +#endif /* DEBUG */ + { + *pDeviceMap++ = i; + ++DevicesOnBoard; + } + } + + return (DevicesOnBoard); +} + +BOOLEAN +Devices (PMENU_STATE pMS) +{ + BYTE DeviceMap[NUM_DEVICES]; + + pMS->first_item.x = InventoryDevices (DeviceMap); + if (pMS->first_item.x) + { + pMS->InputFunc = DoManipulateDevices; + --pMS->Initialized; + pMS->CurState = 1; + pMS->first_item.y = 0; + + pMS->CurFrame = (FRAME)DeviceMap; + DoManipulateDevices (0, pMS); /* to make sure it's initialized */ + DoInput ((PVOID)pMS); + pMS->CurFrame = 0; + + pMS->InputFunc = DoFlagshipCommands; + pMS->CurState = EQUIP_DEVICE + 1; + + if (GLOBAL_SIS (CrewEnlisted) != (COUNT)~0 + && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + SetSemaphore (&GraphicsSem); + ClearSISRect (DRAW_SIS_DISPLAY); + ClearSemaphore (&GraphicsSem); + + if (!GET_GAME_STATE (PORTAL_COUNTER) + && !(GLOBAL (CurrentActivity) & START_ENCOUNTER) + && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) +// DrawMenuStateStrings (PM_SCAN, pMS->CurState - 1); + return (TRUE); + } + } + + return (FALSE); +} + diff --git a/sc2/src/sc2code/planets/elemdata.h b/sc2/src/sc2code/planets/elemdata.h new file mode 100644 index 000000000..175346060 --- /dev/null +++ b/sc2/src/sc2code/planets/elemdata.h @@ -0,0 +1,206 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ELEMDATA_H +#define _ELEMDATA_H + +/*------------------------------ Type Defines ----------------------------- */ +enum +{ + COMMON = 0, + CORROSIVE, + BASE_METAL, + NOBLE, + RARE_EARTH, + PRECIOUS, + RADIOACTIVE, + EXOTIC, + + NUM_ELEMENT_CATEGORIES +}; + +#define ElementCategory(et) (Elements[et] & 0x7) + +/*------------------------------ Global Data ------------------------------ */ + +enum +{ + HYDROGEN, + HELIUM, + LITHIUM, + BERYLLIUM, + BORON, + CARBON, + NITROGEN, + OXYGEN, + FLUORINE, + NEON, + SODIUM, + MAGNESIUM, + ALUMINUM, + SILICON, + PHOSPHORUS, + SULFUR, + CHLORINE, + ARGON, + POTASSIUM, + CALCIUM, + SCANDIUM, + TITANIUM, + VANADIUM, + CHROMIUM, + MANGANESE, + IRON, + COBALT, + NICKEL, + COPPER, + ZINC, + GALLIUM, + GERMANIUM, + ARSENIC, + SELENIUM, + BROMINE, + KRYPTON, + RUBIDIUM, + STRONTIUM, + YTTRIUM, + ZIRCONIUM, + NIOBIUM, + MOLYBDENUM, + TECHNETIUM, + RUTHENIUM, + RHODIUM, + PALLADIUM, + SILVER, + CADMIUM, + INDIUM, + TIN, + ANTIMONY, + TELLURIUM, + IODINE, + XENON, + CESIUM, + BARIUM, + LANTHANUM, + CERIUM, + PRASEODYMIUM, + NEODYMIUM, + PROMETHIUM, + SAMARIUM, + EUROPIUM, + GADOLINIUM, + TERBIUM, + DYPROSIUM, + HOLMIUM, + ERBIUM, + THULIUM, + YTTERBIUM, + LUTETIUM, + HAFNIUM, + TANTALUM, + TUNGSTEN, + RHENIUM, + OSMIUM, + IRIDIUM, + PLATINUM, + GOLD, + MERCURY, + THALLIUM, + LEAD, + BISMUTH, + POLONIUM, + ASTATINE, + RADON, + FRANCIUM, + RADIUM, + ACTINIUM, + THORIUM, + PROTACTINIUM, + URANIUM, + NEPTUNIUM, + PLUTONIUM, + NUMBER_OF_NORMAL, + + OZONE = NUMBER_OF_NORMAL, + FREE_RADICALS, + CARBON_DIOXIDE, + CARBON_MONOXIDE, + AMMONIA, + METHANE, + SULFURIC_ACID, + HYDROCHLORIC_ACID, + HYDROCYANIC_ACID, + FORMIC_ACID, + PHOSPHORIC_ACID, + FORMALDEHYDE, + CYANOACETYLENE, + METHANOL, + ETHANOL, + SILICON_MONOXIDE, + TITANIUM_OXIDE, + ZIRCONIUM_OXIDE, + WATER, + SILICON_COMPOUNDS, + METAL_OXIDES, + QUANTUM_BH, + NEUTRONIUM, + MAGNETIC_MONOPOLES, + DEGENERATE_MATTER, + RT_SUPER_FLUID, + AGUUTI_NODULES, + IRON_COMPOUNDS, + ALUMINUM_COMPOUNDS, + NITROUS_OXIDE, + RADIOACTIVE_COMPOUNDS, + HYDROCARBONS, + CARBON_COMPOUNDS, + ANTIMATTER, + CHARON_DUST, + REISBURG_HELICES, + TZO_CRYSTALS, + CALCIUM_COMPOUNDS, + NITRIC_ACID, + + NUMBER_OF_ELEMENTS +}; +#define NUMBER_OF_SPECIAL (NUMBER_OF_ELEMENTS - NUMBER_OF_NORMAL) + +#define CHANCE_MASK ((1 << 2) - 1) + +#define FEW 1 +#define MODERATE 4 +#define NUMEROUS 8 + +enum +{ + LIGHT = 0, + MEDIUM, + HEAVY +}; +#define NOTHING (BYTE)(~0) + +#define MINERAL_DEPOSIT(qn,ql) MAKE_BYTE (qn, ql) +#define DEPOSIT_QUANTITY(md) LONIBBLE (md) +#define DEPOSIT_QUALITY(md) HINIBBLE (md) + +#define MAX_ELEMENT_UNITS 0xF + +extern const BYTE *Elements; + +#endif /* _ELEMDATA_H */ + diff --git a/sc2/src/sc2code/planets/genburv.c b/sc2/src/sc2code/planets/genburv.c new file mode 100644 index 000000000..c4ba23ac5 --- /dev/null +++ b/sc2/src/sc2code/planets/genburv.c @@ -0,0 +1,187 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateBurvixes (BYTE control) +{ + COUNT i; + DWORD rand_val; + + switch (control) + { + case GENERATE_ENERGY: + { + DWORD rand_val, old_rand; + + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT which_node; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] + && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) + { + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (BURVIXESE_BROADCASTERS, 1); + SET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 1); + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + } + case GENERATE_MOONS: + GenerateRandomIP (GENERATE_MOONS); + if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT angle; + + pSolarSysState->MoonDesc[0].data_index = SELENIC_WORLD; + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + + (MAX_MOONS - 1) * MOON_DELTA; + rand_val = Random (); + angle = NORMALIZE_ANGLE (LOWORD (rand_val)); + pSolarSysState->MoonDesc[0].location.x = + COSINE (angle, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (angle, pSolarSysState->MoonDesc[0].radius); + } + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + + pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 39L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + { + rand_val = DoPlanetaryAnalysis ( + &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc + ); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + i = (COUNT)~0; + rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; + i = (COUNT)~0; + GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont (LoadGraphic (LANDER_FONT)); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (BURV_RUINS_STRTAB) + ); + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + } + else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] + && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont (LoadGraphic (LANDER_FONT)); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (BURV_BCS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (BURV_BCS_STRTAB) + ); + } + LoadPlanet (FALSE); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genchmmr.c b/sc2/src/sc2code/planets/genchmmr.c new file mode 100644 index 000000000..9e8f9bf98 --- /dev/null +++ b/sc2/src/sc2code/planets/genchmmr.c @@ -0,0 +1,141 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GenerateChmmr (BYTE control) +{ + switch (control) + { + case GENERATE_MOONS: + GenerateRandomIP (GENERATE_MOONS); + if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[1]) + { + COUNT angle; + DWORD rand_val; + + pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; + rand_val = Random (); + angle = NORMALIZE_ANGLE (LOWORD (rand_val)); + pSolarSysState->MoonDesc[0].location.x = + COSINE (angle, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (angle, pSolarSysState->MoonDesc[0].radius); + } + break; + case GENERATE_PLANETS: + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[1].data_index = SAPPHIRE_WORLD; + if (!GET_GAME_STATE (CHMMR_UNLEASHED)) + pSolarSysState->PlanetDesc[1].data_index |= PLANET_SHIELDED; + pSolarSysState->PlanetDesc[1].NumPlanets = 1; + break; + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) + { + if (GET_GAME_STATE (CHMMR_UNLEASHED)) + { + pSolarSysState->MenuState.Initialized += 2; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (CHMMR_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + GLOBAL (CurrentActivity) |= END_INTERPLANETARY; + } + break; + } + else if (GET_GAME_STATE (SUN_DEVICE_ON_SHIP) + && !GET_GAME_STATE (ILWRATH_DECEIVED) + && ActivateStarShip (ILWRATH_SHIP, SPHERE_TRACKING)) + { + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (ILWRATH_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + InitCommunication (ILWRATH_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + } + /* Starbase */ + else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + RECT r; + + SetSemaphore (&GraphicsSem); + + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (CHMMR_BASE_STRTAB) + ); + + ScanContext = CaptureContext (CreateContext ()); + SetContext (ScanContext); + SetContextFGFrame (Screen); + r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; + r.extent.width = MAP_WIDTH; + r.extent.height = MAP_HEIGHT; + SetContextClipRect (&r); + + DoDiscoveryReport (MenuSounds); + + SetContext (SpaceContext); + DestroyContext (ReleaseContext (ScanContext)); + ScanContext = 0; + + DestroyStringTable (ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + )); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; + DestroyFont (ReleaseFont ( + pSolarSysState->SysInfo.PlanetInfo.LanderFont + )); + pSolarSysState->SysInfo.PlanetInfo.LanderFont = 0; + + ClearSemaphore (&GraphicsSem); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/gencol.c b/sc2/src/sc2code/planets/gencol.c new file mode 100644 index 000000000..ba5cb7c73 --- /dev/null +++ b/sc2/src/sc2code/planets/gencol.c @@ -0,0 +1,114 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateColony (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + { + BYTE b0, b1, b2, b3; + HSTARSHIP hStarShip; + + b0 = GET_GAME_STATE (COLONY_GRPOFFS0); + b1 = GET_GAME_STATE (COLONY_GRPOFFS1); + b2 = GET_GAME_STATE (COLONY_GRPOFFS2); + b3 = GET_GAME_STATE (COLONY_GRPOFFS3); + GLOBAL (BattleGroupRef) = MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + if (GLOBAL (BattleGroupRef) == 0) + { + CloneShipFragment (URQUAN_SHIP, + &GLOBAL (npc_built_ship_q), 0); + + GLOBAL (BattleGroupRef) = PutGroupInfo (~0L, 1); + b0 = LOBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b1 = HIBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b2 = LOBYTE (HIWORD (GLOBAL (BattleGroupRef))); + b3 = HIBYTE (HIWORD (GLOBAL (BattleGroupRef))); + SET_GAME_STATE (COLONY_GRPOFFS0, b0); + SET_GAME_STATE (COLONY_GRPOFFS1, b1); + SET_GAME_STATE (COLONY_GRPOFFS2, b2); + SET_GAME_STATE (COLONY_GRPOFFS3, b3); + } + + GenerateRandomIP (INIT_NPCS); + + if (GLOBAL (BattleGroupRef) + && (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)))) + { + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + SET_GROUP_MISSION (FragPtr, IN_ORBIT); + SET_GROUP_LOC (FragPtr, 0 + 1); /* orbitting colony */ + SET_GROUP_DEST (FragPtr, 0 + 1); /* orbitting colony */ + FragPtr->ShipInfo.loc.x = FragPtr->ShipInfo.loc.y = 0; + FragPtr->ShipInfo.group_counter = 0; + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + break; + } + case GENERATE_PLANETS: + { + COUNT angle; + PPLANET_DESC pMinPlanet; + + pMinPlanet = &pSolarSysState->PlanetDesc[0]; + FillOrbits ((BYTE)~0, pMinPlanet, FALSE); + + pMinPlanet->radius = EARTH_RADIUS * 115L / 100; + angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); + pMinPlanet->location.x = + COSINE (angle, pMinPlanet->radius); + pMinPlanet->location.y = + SINE (angle, pMinPlanet->radius); + pMinPlanet->data_index = WATER_WORLD | PLANET_SHIELDED; + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + DoPlanetaryAnalysis ( + &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc + ); + + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = + EARTH_ATMOSPHERE * 98 / 100; + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; + + LoadPlanet (FALSE); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/gendru.c b/sc2/src/sc2code/planets/gendru.c new file mode 100644 index 000000000..0ef84f7df --- /dev/null +++ b/sc2/src/sc2code/planets/gendru.c @@ -0,0 +1,155 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GenerateDruuge (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + if (!GET_GAME_STATE (ROSY_SPHERE)) + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + else + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << i); + + if (!GET_GAME_STATE (ROSY_SPHERE)) + { + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + + SET_GAME_STATE (ROSY_SPHERE, 1); + SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); + } + } + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + + memmove (&pSolarSysState->PlanetDesc[1], + &pSolarSysState->PlanetDesc[0], + sizeof (pSolarSysState->PlanetDesc[0]) + * pSolarSysState->SunDesc[0].NumPlanets); + ++pSolarSysState->SunDesc[0].NumPlanets; + + pSolarSysState->PlanetDesc[0].data_index = DUST_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; + pSolarSysState->PlanetDesc[0].NumPlanets = 0; + angle = HALF_CIRCLE - OCTANT; + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].rand_seed = MAKE_DWORD ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (DRUUGE_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (DRUUGE_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (DRUUGE_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (DRUUGE_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (DRUUGE_RUINS_STRTAB) + ); + if (GET_GAME_STATE (ROSY_SPHERE)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genilw.c b/sc2/src/sc2code/planets/genilw.c new file mode 100644 index 000000000..df4b9ee91 --- /dev/null +++ b/sc2/src/sc2code/planets/genilw.c @@ -0,0 +1,130 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateIlwrath (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = PRIMORDIAL_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 204L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (ILWRATH_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (ILWRATH_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (ILWRATH_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (ILWRATH_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + GenerateRandomIP (GENERATE_ORBITAL); + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.Weather = 2; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 3; + } + break; + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genmel.c b/sc2/src/sc2code/planets/genmel.c new file mode 100644 index 000000000..98ed2258f --- /dev/null +++ b/sc2/src/sc2code/planets/genmel.c @@ -0,0 +1,177 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static DWORD +GetMelnormeRef (void) +{ + BYTE b0, b1, b2, b3; + + switch (CurStarDescPtr->Index) + { + case MELNORME0_DEFINED: + b0 = GET_GAME_STATE (MELNORME0_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME0_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME0_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME0_GRPOFFS3); + break; + case MELNORME1_DEFINED: + b0 = GET_GAME_STATE (MELNORME1_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME1_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME1_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME1_GRPOFFS3); + break; + case MELNORME2_DEFINED: + b0 = GET_GAME_STATE (MELNORME2_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME2_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME2_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME2_GRPOFFS3); + break; + case MELNORME3_DEFINED: + b0 = GET_GAME_STATE (MELNORME3_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME3_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME3_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME3_GRPOFFS3); + break; + case MELNORME4_DEFINED: + b0 = GET_GAME_STATE (MELNORME4_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME4_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME4_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME4_GRPOFFS3); + break; + case MELNORME5_DEFINED: + b0 = GET_GAME_STATE (MELNORME5_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME5_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME5_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME5_GRPOFFS3); + break; + case MELNORME6_DEFINED: + b0 = GET_GAME_STATE (MELNORME6_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME6_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME6_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME6_GRPOFFS3); + break; + case MELNORME7_DEFINED: + b0 = GET_GAME_STATE (MELNORME7_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME7_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME7_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME7_GRPOFFS3); + break; + case MELNORME8_DEFINED: + b0 = GET_GAME_STATE (MELNORME8_GRPOFFS0); + b1 = GET_GAME_STATE (MELNORME8_GRPOFFS1); + b2 = GET_GAME_STATE (MELNORME8_GRPOFFS2); + b3 = GET_GAME_STATE (MELNORME8_GRPOFFS3); + break; + } + + return (MAKE_DWORD (MAKE_WORD (b0, b1), MAKE_WORD (b2, b3))); +} + +static void +SetMelnormeRef (DWORD Ref) +{ + BYTE b0, b1, b2, b3; + + b0 = LOBYTE (LOWORD (Ref)); + b1 = HIBYTE (LOWORD (Ref)); + b2 = LOBYTE (HIWORD (Ref)); + b3 = HIBYTE (HIWORD (Ref)); + switch (CurStarDescPtr->Index) + { + case MELNORME0_DEFINED: + SET_GAME_STATE (MELNORME0_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME0_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME0_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME0_GRPOFFS3, b3); + break; + case MELNORME1_DEFINED: + SET_GAME_STATE (MELNORME1_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME1_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME1_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME1_GRPOFFS3, b3); + break; + case MELNORME2_DEFINED: + SET_GAME_STATE (MELNORME2_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME2_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME2_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME2_GRPOFFS3, b3); + break; + case MELNORME3_DEFINED: + SET_GAME_STATE (MELNORME3_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME3_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME3_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME3_GRPOFFS3, b3); + break; + case MELNORME4_DEFINED: + SET_GAME_STATE (MELNORME4_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME4_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME4_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME4_GRPOFFS3, b3); + break; + case MELNORME5_DEFINED: + SET_GAME_STATE (MELNORME5_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME5_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME5_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME5_GRPOFFS3, b3); + break; + case MELNORME6_DEFINED: + SET_GAME_STATE (MELNORME6_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME6_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME6_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME6_GRPOFFS3, b3); + break; + case MELNORME7_DEFINED: + SET_GAME_STATE (MELNORME7_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME7_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME7_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME7_GRPOFFS3, b3); + break; + case MELNORME8_DEFINED: + SET_GAME_STATE (MELNORME8_GRPOFFS0, b0); + SET_GAME_STATE (MELNORME8_GRPOFFS1, b1); + SET_GAME_STATE (MELNORME8_GRPOFFS2, b2); + SET_GAME_STATE (MELNORME8_GRPOFFS3, b3); + break; + } +} + +void +GenerateMelnorme (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + GLOBAL (BattleGroupRef) = GetMelnormeRef (); + if (GLOBAL (BattleGroupRef) == 0) + { + CloneShipFragment (MELNORME_SHIP, + &GLOBAL (npc_built_ship_q), 0); + GLOBAL (BattleGroupRef) = PutGroupInfo (~0L, 1); + SetMelnormeRef (GLOBAL (BattleGroupRef)); + } + GenerateRandomIP (INIT_NPCS); + break; + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genmyc.c b/sc2/src/sc2code/planets/genmyc.c new file mode 100644 index 000000000..de8234b4f --- /dev/null +++ b/sc2/src/sc2code/planets/genmyc.c @@ -0,0 +1,232 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateMycon (BYTE control) +{ + switch (control) + { + case GENERATE_LIFE: + pSolarSysState->CurNode = 0; + break; + case GENERATE_ENERGY: + if (CurStarDescPtr->Index != MYCON_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (CurStarDescPtr->Index == SUN_DEVICE_DEFINED) + { + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (SUN_DEVICE, 1); + SET_GAME_STATE (SUN_DEVICE_ON_SHIP, 1); + SET_GAME_STATE (MYCON_VISITS, 0); + } + } + } + else + { + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if ((pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->SysInfo.PlanetInfo.DiscoveryString) + { + switch (CurStarDescPtr->Index) + { + case EGG_CASE0_DEFINED: + SET_GAME_STATE (EGG_CASE0_ON_SHIP, 1); + break; + case EGG_CASE1_DEFINED: + SET_GAME_STATE (EGG_CASE1_ON_SHIP, 1); + break; + case EGG_CASE2_DEFINED: + SET_GAME_STATE (EGG_CASE2_ON_SHIP, 1); + break; + } + } + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = CRACKED_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 80L / 100; + if (pSolarSysState->PlanetDesc[0].NumPlanets > 2) + pSolarSysState->PlanetDesc[0].NumPlanets = 2; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if ((CurStarDescPtr->Index == MYCON_DEFINED + || CurStarDescPtr->Index == SUN_DEVICE_DEFINED) + && ActivateStarShip (MYCON_SHIP, SPHERE_TRACKING)) + { + if (CurStarDescPtr->Index == MYCON_DEFINED + || !GET_GAME_STATE (SUN_DEVICE_UNGUARDED)) + { + NotifyOthers (MYCON_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (CurStarDescPtr->Index == MYCON_DEFINED + || !GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) + CloneShipFragment (MYCON_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + else + { + COUNT i; + + for (i = 0; i < 5; ++i) + CloneShipFragment (MYCON_SHIP, + &GLOBAL (npc_built_ship_q), 0); + } + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + if (CurStarDescPtr->Index == MYCON_DEFINED) + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + } + else + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + } + InitCommunication (MYCON_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + + { + BOOLEAN MyconSurvivors; + + MyconSurvivors = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ) != 0; + + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + if (MyconSurvivors) + break; + + SET_GAME_STATE (SUN_DEVICE_UNGUARDED, 1); + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + } + } + } + + switch (CurStarDescPtr->Index) + { + case SUN_DEVICE_DEFINED: + if (!GET_GAME_STATE (SUN_DEVICE)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (SUN_DEVICE_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (SUN_DEVICE_STRTAB) + ); + } + break; + case EGG_CASE0_DEFINED: + case EGG_CASE1_DEFINED: + case EGG_CASE2_DEFINED: + if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 0) + { + SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 1); + } + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0))) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (EGG_CASE_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (EGG_CASE_STRTAB) + ); + } + break; + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genorz.c b/sc2/src/sc2code/planets/genorz.c new file mode 100644 index 000000000..3a8e490d6 --- /dev/null +++ b/sc2/src/sc2code/planets/genorz.c @@ -0,0 +1,380 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +static void +GenerateAndrosynth (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + { + DWORD rand_val, old_rand; + + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) + { + COUNT i, which_node; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << i); + /* so won't get freed in lander.c */ + CaptureStringTable (GetStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + )); + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << (i + 16)))) + { + SET_GAME_STATE (PLANETARY_CHANGE, 1); + + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + |= (1L << (i + 16)); + if (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString) + { + PPLANETSIDE_DESC pPSD; + + pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; + UnbatchGraphics (); + DoDiscoveryReport (pPSD->OldMenuSounds); + BatchGraphics (); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetRelStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + if (GetStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + ) == 0) + /* so will get freed in lander.c */ + ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + ); + } + } + } + + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + } + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[1].data_index = TELLURIC_WORLD; + pSolarSysState->PlanetDesc[1].radius = EARTH_RADIUS * 204L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[1].location.x, + pSolarSysState->PlanetDesc[1].location.y + ); + pSolarSysState->PlanetDesc[1].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[1].radius); + pSolarSysState->PlanetDesc[1].location.y = + SINE (angle, pSolarSysState->PlanetDesc[1].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) + { + UWORD retval; + + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (ANDROSYNTH_RUINS_STRTAB) + ); + retval = HIWORD ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + ); + while (retval) + { + if (retval & 1) + { + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetRelStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + if (GetStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + ) == 0) + { + DestroyStringTable (ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + )); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; + } + } + + retval >>= 1; + } + } + GenerateRandomIP (GENERATE_ORBITAL); + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) + { + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = + EARTH_ATMOSPHERE * 144 / 100; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; + pSolarSysState->SysInfo.PlanetInfo.Weather = 1; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + } + break; + default: + GenerateRandomIP (control); + break; + } +} + +void +GenerateOrz (BYTE control) +{ + if (CurStarDescPtr->Index == ANDROSYNTH_DEFINED) + { + GenerateAndrosynth (control); + return; + } + + switch (control) + { + case GENERATE_ENERGY: + { + DWORD rand_val, old_rand; + + if (CurStarDescPtr->Index != ORZ_DEFINED + && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[2] + && !GET_GAME_STATE (TAALO_PROTECTOR)) + { + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (TAALO_PROTECTOR, 1); + SET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP, 1); + } + } + + SeedRandom (old_rand); + break; + } + else if (CurStarDescPtr->Index == ORZ_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + } + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + if (CurStarDescPtr->Index == ORZ_DEFINED) + { + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 156L / 100; + pSolarSysState->PlanetDesc[0].NumPlanets = 0; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + } + break; + } + case GENERATE_ORBITAL: + if ((CurStarDescPtr->Index == ORZ_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + || (CurStarDescPtr->Index == TAALO_PROTECTOR_DEFINED + && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[2] + && !GET_GAME_STATE (TAALO_PROTECTOR))) + { + COUNT i; + + if ((CurStarDescPtr->Index == ORZ_DEFINED + || !GET_GAME_STATE (TAALO_UNPROTECTED)) + && ActivateStarShip (ORZ_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (ORZ_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (CurStarDescPtr->Index == ORZ_DEFINED) + { + CloneShipFragment (ORZ_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + } + else + { + for (i = 0; i < 14; ++i) + CloneShipFragment (ORZ_SHIP, + &GLOBAL (npc_built_ship_q), 0); + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + } + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + InitCommunication (ORZ_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + else + { + BOOLEAN OrzSurvivors; + + OrzSurvivors = GetHeadLink (&GLOBAL (npc_built_ship_q)) + && (CurStarDescPtr->Index == ORZ_DEFINED + || !GET_GAME_STATE (TAALO_UNPROTECTED)); + + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + if (OrzSurvivors) + break; + + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + } + } + + SET_GAME_STATE (TAALO_UNPROTECTED, 1); + if (CurStarDescPtr->Index == TAALO_PROTECTOR_DEFINED) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (TAALO_DEVICE_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (TAALO_DEVICE_STRTAB) + ); + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genpet.c b/sc2/src/sc2code/planets/genpet.c new file mode 100644 index 000000000..f40dfe352 --- /dev/null +++ b/sc2/src/sc2code/planets/genpet.c @@ -0,0 +1,238 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static void +ZapToUrquanEncounter (void) +{ + HENCOUNTER hEncounter; + + if ((hEncounter = AllocEncounter ()) || (hEncounter = GetHeadEncounter ())) + { + SIZE dx, dy; + ENCOUNTERPTR EncounterPtr; + HSTARSHIP hStarShip; + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + LockEncounter (hEncounter, &EncounterPtr); + + if (hEncounter == GetHeadEncounter ()) + RemoveEncounter (hEncounter); + memset (EncounterPtr, 0, sizeof (*EncounterPtr)); + + InsertEncounter (hEncounter, GetHeadEncounter ()); + + hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), URQUAN_SHIP); + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + EncounterPtr->origin = TemplatePtr->ShipInfo.loc; + EncounterPtr->radius = TemplatePtr->ShipInfo.actual_strength; + EncounterPtr->SD.Type = URQUAN_SHIP; + EncounterPtr->SD.Index = MAKE_BYTE (1, 0) | ONE_SHOT_ENCOUNTER; + EncounterPtr->SD.ShipList[0] = + ((SHIP_FRAGMENTPTR)TemplatePtr)->ShipInfo; + EncounterPtr->SD.ShipList[0].var1 = URQUAN_SHIP; + EncounterPtr->SD.star_pt.x = 5288; + EncounterPtr->SD.star_pt.y = 4892; + EncounterPtr->log_x = UNIVERSE_TO_LOGX (EncounterPtr->SD.star_pt.x); + EncounterPtr->log_y = UNIVERSE_TO_LOGY (EncounterPtr->SD.star_pt.y); + GLOBAL_SIS (log_x) = EncounterPtr->log_x; + GLOBAL_SIS (log_y) = EncounterPtr->log_y; + UnlockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + + { +#define LOST_DAYS 15 + COUNT i; + BYTE black_buf[] = {FadeAllToBlack}; + + SleepTask (XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND * 2)); + for (i = 0; i < LOST_DAYS; ++i) + { + while (ClockTick () > 0) + ; + + ResumeGameClock (); + SleepTask (GetTimeCounter () + 2); + SuspendGameClock (); + } + } + + GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0) | START_ENCOUNTER; + + dx = CurStarDescPtr->star_pt.x - EncounterPtr->SD.star_pt.x; + dy = CurStarDescPtr->star_pt.y - EncounterPtr->SD.star_pt.y; + dx = (SIZE)square_root ((long)dx * dx + (long)dy * dy) + + (FUEL_TANK_SCALE >> 1); + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, -dx, 0); + if (GLOBAL_SIS (FuelOnBoard) < 5 * FUEL_TANK_SCALE) + { + dx = ((5 + ((COUNT)Random () % 5)) * FUEL_TANK_SCALE) + - (SIZE)GLOBAL_SIS (FuelOnBoard); + DeltaSISGauges (0, dx, 0); + } + DrawSISMessage (NULL_PTR); + DrawHyperCoords (EncounterPtr->SD.star_pt); + ClearSemaphore (&GraphicsSem); + + UnlockEncounter (hEncounter); + } +} + +void +GenerateTalkingPet (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = TELLURIC_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 204L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] + && (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES) + || !GET_GAME_STATE (TALKING_PET) + || ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING))) + { + NotifyOthers (UMGAH_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING)) + { + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + if (!GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) + { + CloneShipFragment (UMGAH_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + InitCommunication (UMGAH_CONVERSATION); + } + else + { + COUNT i; + + for (i = 0; i < 10; ++i) + CloneShipFragment (UMGAH_SHIP, + &GLOBAL (npc_built_ship_q), 0); + InitCommunication (TALKING_PET_CONVERSATION); + } + pSolarSysState->MenuState.Initialized -= 2; + } + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + BOOLEAN UmgahSurvivors; + + UmgahSurvivors = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ) != 0; + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + + if (GET_GAME_STATE (PLAYER_HYPNOTIZED)) + ZapToUrquanEncounter (); + else if (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES) + && !UmgahSurvivors) + InitCommunication (TALKING_PET_CONVERSATION); + + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + + GenerateRandomIP (GENERATE_ORBITAL); + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + break; + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genpku.c b/sc2/src/sc2code/planets/genpku.c new file mode 100644 index 000000000..94994af54 --- /dev/null +++ b/sc2/src/sc2code/planets/genpku.c @@ -0,0 +1,148 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GeneratePkunk (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + if (!GET_GAME_STATE (CLEAR_SPINDLE)) + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + else + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << i); + + if (!GET_GAME_STATE (CLEAR_SPINDLE)) + { + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + + SET_GAME_STATE (CLEAR_SPINDLE, 1); + SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); + } + } + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 104L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (PKUNK_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (PKUNK_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (PKUNK_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (PKUNK_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (PKUNK_RUINS_STRTAB) + ); + if (GET_GAME_STATE (CLEAR_SPINDLE)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genrain.c b/sc2/src/sc2code/planets/genrain.c new file mode 100644 index 000000000..f9d9aea7f --- /dev/null +++ b/sc2/src/sc2code/planets/genrain.c @@ -0,0 +1,77 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateRainbow (BYTE control) +{ + switch (control) + { + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = RAINBOW_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 0; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + if (angle <= QUADRANT) + angle += QUADRANT; + else if (angle >= FULL_CIRCLE - QUADRANT) + angle -= QUADRANT; + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + BYTE which_rainbow; + UWORD rainbow_mask; + STAR_DESCPTR SDPtr; + + rainbow_mask = MAKE_WORD ( + GET_GAME_STATE (RAINBOW_WORLD0), + GET_GAME_STATE (RAINBOW_WORLD1) + ); + + which_rainbow = 0; + SDPtr = &star_array[0]; + while (SDPtr != CurStarDescPtr) + { + if (SDPtr->Index == RAINBOW_DEFINED) + ++which_rainbow; + ++SDPtr; + } + rainbow_mask |= 1 << which_rainbow; + SET_GAME_STATE (RAINBOW_WORLD0, LOBYTE (rainbow_mask)); + SET_GAME_STATE (RAINBOW_WORLD1, HIBYTE (rainbow_mask)); + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/gensam.c b/sc2/src/sc2code/planets/gensam.c new file mode 100644 index 000000000..91bdcbfbf --- /dev/null +++ b/sc2/src/sc2code/planets/gensam.c @@ -0,0 +1,297 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static void +BuildUrquanGuard (void) +{ + BYTE ship1, ship2; + BYTE b0, b1, b2, b3; + POINT org; + HSTARSHIP hStarShip, hNextShip; + + b0 = GET_GAME_STATE (SAMATRA_GRPOFFS0); + b1 = GET_GAME_STATE (SAMATRA_GRPOFFS1); + b2 = GET_GAME_STATE (SAMATRA_GRPOFFS2); + b3 = GET_GAME_STATE (SAMATRA_GRPOFFS3); + GLOBAL (BattleGroupRef) = MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + + if (!GET_GAME_STATE (KOHR_AH_FRENZY)) + ship1 = URQUAN_SHIP, ship2 = BLACK_URQUAN_SHIP; + else + ship1 = BLACK_URQUAN_SHIP, ship2 = URQUAN_SHIP; + + for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) + CloneShipFragment (ship1, + &GLOBAL (npc_built_ship_q), 0); + + if (GLOBAL (BattleGroupRef) == 0) + { + GLOBAL (BattleGroupRef) = PutGroupInfo (~0L, 1); + b0 = LOBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b1 = HIBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b2 = LOBYTE (HIWORD (GLOBAL (BattleGroupRef))); + b3 = HIBYTE (HIWORD (GLOBAL (BattleGroupRef))); + SET_GAME_STATE (SAMATRA_GRPOFFS0, b0); + SET_GAME_STATE (SAMATRA_GRPOFFS1, b1); + SET_GAME_STATE (SAMATRA_GRPOFFS2, b2); + SET_GAME_STATE (SAMATRA_GRPOFFS3, b3); + } + +#define NUM_URQUAN_GUARDS0 12 + for (b0 = 1; b0 <= NUM_URQUAN_GUARDS0; ++b0) + PutGroupInfo (GLOBAL (BattleGroupRef), b0); + + ReinitQueue (&GLOBAL (npc_built_ship_q)); + for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) + CloneShipFragment (ship2, + &GLOBAL (npc_built_ship_q), 0); +#define NUM_URQUAN_GUARDS1 4 + for (b0 = 1; b0 <= NUM_URQUAN_GUARDS1; ++b0) + PutGroupInfo (GLOBAL (BattleGroupRef), (BYTE)(NUM_URQUAN_GUARDS0 + b0)); + + GetGroupInfo (GLOBAL (BattleGroupRef), (BYTE)~0); + + XFormIPLoc ( + &pSolarSysState->PlanetDesc[4].image.origin, + &org, + FALSE + ); + hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + for (b0 = 0, b1 = 0; + b0 < NUM_URQUAN_GUARDS0; + ++b0, b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1)) + { + SHIP_FRAGMENTPTR FragPtr; + + if (b1 % (FULL_CIRCLE / NUM_URQUAN_GUARDS1) == 0) + b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1); + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (FragPtr); + SET_GROUP_MISSION (FragPtr, ON_STATION | IGNORE_FLAGSHIP); + SET_GROUP_LOC (FragPtr, 0); + SET_GROUP_DEST (FragPtr, 4 + 1); + SET_ORBIT_LOC (FragPtr, + NORMALIZE_FACING (ANGLE_TO_FACING (b1))); + FragPtr->ShipInfo.group_counter = 0; + FragPtr->ShipInfo.loc.x = org.x + + COSINE (b1, STATION_RADIUS); + FragPtr->ShipInfo.loc.y = org.y + + SINE (b1, STATION_RADIUS); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hStarShip = hNextShip; + } + + for (b0 = 0, b1 = 0; + b0 < NUM_URQUAN_GUARDS1; + ++b0, b1 += FULL_CIRCLE / NUM_URQUAN_GUARDS1) + { + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (FragPtr); + SET_GROUP_MISSION (FragPtr, ON_STATION | IGNORE_FLAGSHIP); + SET_GROUP_LOC (FragPtr, 0); + SET_GROUP_DEST (FragPtr, 4 + 1); + SET_ORBIT_LOC (FragPtr, + NORMALIZE_FACING (ANGLE_TO_FACING (b1))); + FragPtr->ShipInfo.group_counter = 0; + FragPtr->ShipInfo.loc.x = org.x + + COSINE (b1, STATION_RADIUS); + FragPtr->ShipInfo.loc.y = org.y + + SINE (b1, STATION_RADIUS); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hStarShip = hNextShip; + } +} + +void +GenerateSamatra (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + if (!GET_GAME_STATE (URQUAN_MESSED_UP)) + BuildUrquanGuard (); + break; + case REINIT_NPCS: + GetGroupInfo (0L, 0); + battle_counter = 0; + { + BOOLEAN GuardEngaged; + HSTARSHIP hStarShip, hNextShip; + + GuardEngaged = FALSE; + for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); + hStarShip; hStarShip = hNextShip) + { + BYTE task; + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (FragPtr); + + task = GET_GROUP_MISSION (FragPtr); + if (GET_GAME_STATE (URQUAN_MESSED_UP)) + { + SET_GROUP_MISSION (FragPtr, + FLEE | IGNORE_FLAGSHIP | (task & REFORM_GROUP)); + SET_GROUP_DEST (FragPtr, 0); + } + else if (task & REFORM_GROUP) + { + task &= ~REFORM_GROUP; + FragPtr->ShipInfo.group_counter = 0; + SET_GROUP_MISSION (FragPtr, task); + + GuardEngaged = TRUE; + } + + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + + if (GuardEngaged) + { + COUNT angle; + POINT org; + + XFormIPLoc ( + &pSolarSysState->PlanetDesc[4].image.origin, + &org, + FALSE + ); + angle = ARCTAN ( + GLOBAL (ip_location.x) - org.x, + GLOBAL (ip_location.y) - org.y + ); + GLOBAL (ip_location.x) = org.x + + COSINE (angle, 3000); + GLOBAL (ip_location.y) = org.y + + SINE (angle, 3000); + XFormIPLoc ( + &GLOBAL (ip_location), + &GLOBAL (ShipStamp.origin), + TRUE + ); + } + } + break; + case GENERATE_MOONS: + GenerateRandomIP (GENERATE_MOONS); + if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[4]) + { + COUNT angle; + DWORD rand_val; + + pSolarSysState->MoonDesc[0].data_index = (BYTE)(~0 - 1); + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + + (2 * MOON_DELTA); + rand_val = Random (); + angle = NORMALIZE_ANGLE (LOWORD (rand_val)); + pSolarSysState->MoonDesc[0].location.x = + COSINE (angle, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (angle, pSolarSysState->MoonDesc[0].radius); + } + break; + case GENERATE_PLANETS: + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[4].NumPlanets = 1; + break; + case GENERATE_ORBITAL: + /* Samatra */ + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[4] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (!GET_GAME_STATE (URQUAN_MESSED_UP)) + CloneShipFragment (!GET_GAME_STATE (KOHR_AH_FRENZY) ? + URQUAN_SHIP : BLACK_URQUAN_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + else + { +#define URQUAN_REMNANTS 3 + BYTE i; + + for (i = 0; i < URQUAN_REMNANTS; ++i) + { + CloneShipFragment (URQUAN_SHIP, + &GLOBAL (npc_built_ship_q), 0); + CloneShipFragment (BLACK_URQUAN_SHIP, + &GLOBAL (npc_built_ship_q), 0); + } + } + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + SET_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 1); + InitCommunication (URQUAN_CONVERSATION); + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + BOOLEAN UrquanSurvivors; + + UrquanSurvivors = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ) != 0; + + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + if (UrquanSurvivors) + { + SET_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 0); + } + else + { + battle_counter = 0; + GLOBAL (CurrentActivity) = IN_LAST_BATTLE | START_ENCOUNTER; + if (GET_GAME_STATE (YEHAT_CIVIL_WAR) + && ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING) + && ActivateStarShip (YEHAT_REBEL_SHIP, FEASIBILITY_STUDY)) + InitCommunication (YEHAT_REBEL_CONVERSATION); + } + } + pSolarSysState->MenuState.Initialized -= 2; + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genshof.c b/sc2/src/sc2code/planets/genshof.c new file mode 100644 index 000000000..675706c3c --- /dev/null +++ b/sc2/src/sc2code/planets/genshof.c @@ -0,0 +1,141 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static void +check_old_shofixti (void) +{ + HSTARSHIP hStarShip; + + if (GLOBAL (BattleGroupRef) + && (hStarShip = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + )) + && GET_GAME_STATE (SHOFIXTI_RECRUITED)) + { + BYTE task; + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + task = GET_GROUP_MISSION (FragPtr); + + SET_GROUP_MISSION (FragPtr, + FLEE | IGNORE_FLAGSHIP | (task & REFORM_GROUP)); + SET_GROUP_DEST (FragPtr, 0); + + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } +} + +void +GenerateShofixti (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + if (!GET_GAME_STATE (SHOFIXTI_RECRUITED) + && (!GET_GAME_STATE (SHOFIXTI_KIA) + || (!GET_GAME_STATE (SHOFIXTI_BRO_KIA) + && GET_GAME_STATE (MAIDENS_ON_SHIP)))) + { + BYTE b0, b1, b2, b3; + + b0 = GET_GAME_STATE (SHOFIXTI_GRPOFFS0); + b1 = GET_GAME_STATE (SHOFIXTI_GRPOFFS1); + b2 = GET_GAME_STATE (SHOFIXTI_GRPOFFS2); + b3 = GET_GAME_STATE (SHOFIXTI_GRPOFFS3); + GLOBAL (BattleGroupRef) = MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + if (GLOBAL (BattleGroupRef) == 0 + || !GetGroupInfo ( + GLOBAL (BattleGroupRef), (BYTE)~0 + )) + { + if (GLOBAL (BattleGroupRef) == 0) + GLOBAL (BattleGroupRef) = ~0L; + + CloneShipFragment (SHOFIXTI_SHIP, + &GLOBAL (npc_built_ship_q), 1); + + GLOBAL (BattleGroupRef) = PutGroupInfo ( + GLOBAL (BattleGroupRef), 1 + ); + b0 = LOBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b1 = HIBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b2 = LOBYTE (HIWORD (GLOBAL (BattleGroupRef))); + b3 = HIBYTE (HIWORD (GLOBAL (BattleGroupRef))); + SET_GAME_STATE (SHOFIXTI_GRPOFFS0, b0); + SET_GAME_STATE (SHOFIXTI_GRPOFFS1, b1); + SET_GAME_STATE (SHOFIXTI_GRPOFFS2, b2); + SET_GAME_STATE (SHOFIXTI_GRPOFFS3, b3); + } + } + case REINIT_NPCS: + GenerateRandomIP (control); + check_old_shofixti (); + break; + case UNINIT_NPCS: + if (GLOBAL (BattleGroupRef) + && !GET_GAME_STATE (SHOFIXTI_RECRUITED) + && GetHeadLink (&GLOBAL (npc_built_ship_q)) == 0) + { + if (!GET_GAME_STATE (SHOFIXTI_KIA)) + { + SET_GAME_STATE (SHOFIXTI_KIA, 1); + SET_GAME_STATE (SHOFIXTI_VISITS, 0); + } + else if (GET_GAME_STATE (MAIDENS_ON_SHIP)) + { + SET_GAME_STATE (SHOFIXTI_BRO_KIA, 1); + } + } + GenerateRandomIP (UNINIT_NPCS); + break; + case GENERATE_PLANETS: + { + COUNT i; + PPLANET_DESC pCurDesc; + +#define NUM_PLANETS 6 + pSolarSysState->SunDesc[0].NumPlanets = NUM_PLANETS; + for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; + i < NUM_PLANETS; ++i, ++pCurDesc) + { + pCurDesc->NumPlanets = 0; + if (i < (NUM_PLANETS >> 1)) + pCurDesc->data_index = SELENIC_WORLD; + else + pCurDesc->data_index = METAL_WORLD; + } + + FillOrbits (NUM_PLANETS, &pSolarSysState->PlanetDesc[0], TRUE); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/gensly.c b/sc2/src/sc2code/planets/gensly.c new file mode 100644 index 000000000..894615cbb --- /dev/null +++ b/sc2/src/sc2code/planets/gensly.c @@ -0,0 +1,44 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateSlylandro (BYTE control) +{ + switch (control) + { + case GENERATE_PLANETS: + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[3].data_index = RED_GAS_GIANT; + pSolarSysState->PlanetDesc[3].NumPlanets = 1; + break; + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[3]) + { + pSolarSysState->MenuState.Initialized += 2; + InitCommunication (SLYLANDRO_HOME_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/gensol.c b/sc2/src/sc2code/planets/gensol.c new file mode 100644 index 000000000..b316c4f7b --- /dev/null +++ b/sc2/src/sc2code/planets/gensol.c @@ -0,0 +1,570 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lifeform.h" +#include "lander.h" + +static void +init_probe (void) +{ + BYTE b0, b1, b2, b3; + HSTARSHIP hStarShip; + + b0 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS0); + b1 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS1); + b2 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS2); + b3 = GET_GAME_STATE (URQUAN_PROBE_GRPOFFS3); + GLOBAL (BattleGroupRef) = MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + if (GLOBAL (BattleGroupRef) == 0) + { + CloneShipFragment (URQUAN_PROBE_SHIP, + &GLOBAL (npc_built_ship_q), 0); + + GLOBAL (BattleGroupRef) = PutGroupInfo (~0L, 1); + b0 = LOBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b1 = HIBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b2 = LOBYTE (HIWORD (GLOBAL (BattleGroupRef))); + b3 = HIBYTE (HIWORD (GLOBAL (BattleGroupRef))); + SET_GAME_STATE (URQUAN_PROBE_GRPOFFS0, b0); + SET_GAME_STATE (URQUAN_PROBE_GRPOFFS1, b1); + SET_GAME_STATE (URQUAN_PROBE_GRPOFFS2, b2); + SET_GAME_STATE (URQUAN_PROBE_GRPOFFS3, b3); + } + + if (!GET_GAME_STATE (PROBE_MESSAGE_DELIVERED) + && GetGroupInfo (GLOBAL (BattleGroupRef), (BYTE)~0) + && (hStarShip = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ))) + { + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + SET_GROUP_MISSION (FragPtr, IN_ORBIT); + SET_GROUP_LOC (FragPtr, 2 + 1); /* orbitting earth */ + SET_GROUP_DEST (FragPtr, 2 + 1); /* orbitting earth */ + FragPtr->ShipInfo.loc.x = FragPtr->ShipInfo.loc.y = 0; + FragPtr->ShipInfo.group_counter = 0; + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } +} + +static void +generate_energy_nodes (void) +{ + /* Pluto */ + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[8]) + { + if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) + { + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = 20; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT - 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 2; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (FOUND_PLUTO_SPATHI, 1); + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << 0); + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + } + else if (pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + return; + } + } + /* Earth Moon */ + else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[2] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] + && !GET_GAME_STATE (MOONBASE_DESTROYED)) + { + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = MAP_WIDTH * 3 / 4; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT * 1 / 4; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (MOONBASE_DESTROYED, 1); + SET_GAME_STATE (MOONBASE_ON_SHIP, 1); + } + } + return; + } + pSolarSysState->CurNode = 0; +} + +static void +generate_tractors (void) +{ + if (pSolarSysState->pOrbitalDesc->pPrevDesc != &pSolarSysState->PlanetDesc[2] + || pSolarSysState->pOrbitalDesc != &pSolarSysState->MoonDesc[1]) + pSolarSysState->CurNode = 0; + else /* Earth Moon */ + { + COUNT i, which_node; + DWORD old_rand, rand_val; + + old_rand = SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES + 1; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 10); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + } +} + +static void +generate_orbital (void) +{ + COUNT i; + DWORD rand_val; + + /* Starbase */ + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[2] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + battle_counter = 0; + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); + return; + } + + rand_val = DoPlanetaryAnalysis (&pSolarSysState->SysInfo, + pSolarSysState->pOrbitalDesc); + if (rand_val) + { + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = + rand_val; + i = (COUNT)~0; + rand_val = GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); + } + + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) + { + i = pSolarSysState->pOrbitalDesc - pSolarSysState->PlanetDesc; + switch (i) + { + case 0: /* MERCURY */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 98; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 38; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 3; + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 2; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 59 * 240; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 165; + break; + case 1: /* VENUS */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 9000; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 95; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 95; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 177; + pSolarSysState->SysInfo.PlanetInfo.Weather = 7; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 243 * 240; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 457; + break; + case 2: /* EARTH */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 100; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 100; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 23; + pSolarSysState->SysInfo.PlanetInfo.Weather = 1; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 240; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 22; + break; + case 3: /* MARS */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 1; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 72; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 53; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 24; + pSolarSysState->SysInfo.PlanetInfo.Weather = 1; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 246; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -53; + break; + case 4: /* JUPITER */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0xFFFF; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 24; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 1120; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 3; + pSolarSysState->SysInfo.PlanetInfo.Weather = 7; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 98; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -143; + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 520L / 100; + break; + case 5: /* SATURN */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0xFFFF; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 13; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 945; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 27; + pSolarSysState->SysInfo.PlanetInfo.Weather = 7; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 102; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -197; + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 952L / 100; + break; + case 6: /* URANUS */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0xFFFF; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 21; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 411; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 98; + pSolarSysState->SysInfo.PlanetInfo.Weather = 7; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 172; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -217; + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 1916L / 100; + break; + case 7: /* NEPTUNE */ + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0xFFFF; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 28; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 396; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 30; + pSolarSysState->SysInfo.PlanetInfo.Weather = 7; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 182; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -229; + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 2999L / 100; + break; + case 8: /* PLUTO */ + if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (SPAPLUTO_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (SPAPLUTO_STRTAB) + ); + } + + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 33; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 18; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 119; + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 1533; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -235; + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 3937L / 100; + break; + } + + pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = + CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); + LoadPlanet (i == 2); + } + else + { + i = pSolarSysState->pOrbitalDesc->pPrevDesc + - pSolarSysState->PlanetDesc; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 0; + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + switch (i) + { + case 2: /* moons of EARTH */ + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + + if (!GET_GAME_STATE (MOONBASE_DESTROYED)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (MOONBASE_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (MOONBASE_STRTAB) + ); + } + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 60; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; + pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 240 * 29; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -18; + break; + case 4: /* moons of JUPITER */ + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 520L / 100; + switch (pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc) + { + case 0: + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 69; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 3; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 390; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -163; + break; + case 1: + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 54; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 840; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -161; + break; + case 2: + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 35; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 41; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 1728; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -164; + break; + case 3: + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 35; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 38; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 4008; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -167; + break; + } + break; + case 5: /* moons of SATURN */ + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 952L / 100; + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 160; + pSolarSysState->SysInfo.PlanetInfo.Weather = 2; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 34; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 40; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 3816; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -178; + break; + case 7: /* moons of NEPTUNE */ + pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 2999L / 100; + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 10; + pSolarSysState->SysInfo.PlanetInfo.Weather = 1; + pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 95; + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 27; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 4300; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -216; + break; + } + + pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = + CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); + LoadPlanet (FALSE); + } +} + +void +GenerateSOL (BYTE control) +{ + COUNT i; + DWORD rand_val; + PPLANET_DESC pCurDesc; + + switch (control) + { + case INIT_NPCS: + init_probe (); + break; + case REINIT_NPCS: + if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) + GenerateRandomIP (REINIT_NPCS); + else + { + GLOBAL (BattleGroupRef) = 0; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + } + break; + case GENERATE_ENERGY: + generate_energy_nodes (); + break; + case GENERATE_LIFE: + generate_tractors (); + break; + case GENERATE_ORBITAL: + generate_orbital (); + break; + case GENERATE_NAME: + i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; + wstrcpy (GLOBAL_SIS (PlanetName), GAME_STRING (PLANET_NUMBER_BASE + i)); + SET_GAME_STATE (BATTLE_PLANET, + pSolarSysState->PlanetDesc[i].data_index); + break; + case GENERATE_MOONS: + { + GenerateRandomIP (GENERATE_MOONS); + + i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; + switch (i) + { + case 2: /* moons of EARTH */ + { + COUNT angle; + + pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; + angle = HALF_CIRCLE + QUADRANT; + pSolarSysState->MoonDesc[0].location.x = + COSINE (angle, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (angle, pSolarSysState->MoonDesc[0].radius); + + pSolarSysState->MoonDesc[1].data_index = SELENIC_WORLD; + pSolarSysState->MoonDesc[1].radius = MIN_MOON_RADIUS + + (MAX_MOONS - 1) * MOON_DELTA; + rand_val = Random (); + angle = NORMALIZE_ANGLE (LOWORD (rand_val)); + pSolarSysState->MoonDesc[1].location.x = + COSINE (angle, pSolarSysState->MoonDesc[1].radius); + pSolarSysState->MoonDesc[1].location.y = + SINE (angle, pSolarSysState->MoonDesc[1].radius); + break; + } + case 4: /* moons of JUPITER */ + pSolarSysState->MoonDesc[0].data_index = RADIOACTIVE_WORLD; + pSolarSysState->MoonDesc[1].data_index = HALIDE_WORLD; + pSolarSysState->MoonDesc[2].data_index = CYANIC_WORLD; + pSolarSysState->MoonDesc[3].data_index = PELLUCID_WORLD; + break; + case 5: /* moons of SATURN */ + pSolarSysState->MoonDesc[0].data_index = ALKALI_WORLD; + break; + case 7: /* moons of NEPTUNE */ + pSolarSysState->MoonDesc[0].data_index = VINYLOGOUS_WORLD; + break; + } + break; + } + case GENERATE_PLANETS: + { +#define SOL_SEED 334241042L + SeedRandom (SOL_SEED); + + pSolarSysState->SunDesc[0].NumPlanets = 9; + for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; i < 9; ++i, ++pCurDesc) + { + COUNT angle; + UWORD word_val; + + pCurDesc->rand_seed = rand_val = Random (); + word_val = LOWORD (rand_val); + angle = NORMALIZE_ANGLE ((COUNT)HIBYTE (word_val)); + + switch (i) + { + case 0: /* MERCURY */ + pCurDesc->data_index = METAL_WORLD; + pCurDesc->radius = EARTH_RADIUS * 39L / 100; + pCurDesc->NumPlanets = 0; + break; + case 1: /* VENUS */ + pCurDesc->data_index = PRIMORDIAL_WORLD; + pCurDesc->radius = EARTH_RADIUS * 72L / 100; + pCurDesc->NumPlanets = 0; + angle = NORMALIZE_ANGLE (FULL_CIRCLE - angle); + break; + case 2: /* EARTH */ + pCurDesc->data_index = WATER_WORLD | PLANET_SHIELDED; + pCurDesc->radius = EARTH_RADIUS; + pCurDesc->NumPlanets = 2; + break; + case 3: /* MARS */ + pCurDesc->data_index = DUST_WORLD; + pCurDesc->radius = EARTH_RADIUS * 152L / 100; + pCurDesc->NumPlanets = 0; + break; + case 4: /* JUPITER */ + pCurDesc->data_index = RED_GAS_GIANT; + pCurDesc->radius = EARTH_RADIUS * 500L /* 520L */ / 100; + pCurDesc->NumPlanets = 4; + break; + case 5: /* SATURN */ + pCurDesc->data_index = ORA_GAS_GIANT; + pCurDesc->radius = EARTH_RADIUS * 750L /* 952L */ / 100; + pCurDesc->NumPlanets = 1; + break; + case 6: /* URANUS */ + pCurDesc->data_index = GRN_GAS_GIANT; + pCurDesc->radius = EARTH_RADIUS * 1000L /* 1916L */ / 100; + pCurDesc->NumPlanets = 0; + break; + case 7: /* NEPTUNE */ + pCurDesc->data_index = BLU_GAS_GIANT; + pCurDesc->radius = EARTH_RADIUS * 1250L /* 2999L */ / 100; + pCurDesc->NumPlanets = 1; + break; + case 8: /* PLUTO */ + pCurDesc->data_index = PELLUCID_WORLD; + pCurDesc->radius = EARTH_RADIUS * 1550L /* 3937L */ / 100; + pCurDesc->NumPlanets = 0; + angle = FULL_CIRCLE - OCTANT; + break; + } + + pCurDesc->location.x = + COSINE (angle, pCurDesc->radius); + pCurDesc->location.y = + SINE (angle, pCurDesc->radius); + } + break; + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genspa.c b/sc2/src/sc2code/planets/genspa.c new file mode 100644 index 000000000..397e386e2 --- /dev/null +++ b/sc2/src/sc2code/planets/genspa.c @@ -0,0 +1,235 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lifeform.h" + +void +GenerateSpathi (BYTE control) +{ + COUNT i, angle; + DWORD rand_val; + + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] + && !GET_GAME_STATE (UMGAH_BROADCASTERS)) + { + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (UMGAH_BROADCASTERS, 1); + SET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP, 1); + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_MOONS: + GenerateRandomIP (GENERATE_MOONS); + if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) + { +#ifdef NOTYET + wstrcpy (GLOBAL_SIS (PlanetName), "Spathiwa"); +#endif /* NOTYET */ + + pSolarSysState->MoonDesc[0].data_index = PELLUCID_WORLD; + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + MOON_DELTA; + angle = NORMALIZE_ANGLE (LOWORD (Random ())); + pSolarSysState->MoonDesc[0].location.x = + COSINE (angle, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (angle, pSolarSysState->MoonDesc[0].radius); + } + break; + case GENERATE_PLANETS: + { + PPLANET_DESC pMinPlanet; + + pMinPlanet = &pSolarSysState->PlanetDesc[0]; + FillOrbits (pSolarSysState->SunDesc[0].NumPlanets = 1, pMinPlanet, FALSE); + + pMinPlanet->radius = EARTH_RADIUS * 1150L / 100; + angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); + pMinPlanet->location.x = + COSINE (angle, pMinPlanet->radius); + pMinPlanet->location.y = + SINE (angle, pMinPlanet->radius); + pMinPlanet->data_index = WATER_WORLD; + if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) + pMinPlanet->data_index |= PLANET_SHIELDED; + pMinPlanet->NumPlanets = 1; + break; + } + case GENERATE_LIFE: + /* visiting Spathiwa */ + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] + && !GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) + { + COUNT which_node; + DWORD old_rand; + + old_rand = SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 32); + pSolarSysState->CurNode = which_node; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN]) + { + SET_GAME_STATE (SPATHI_CREATURES_EXAMINED, 1); + if (pSolarSysState->SysInfo. + PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] == 0xFFFFFFFF) + SET_GAME_STATE (SPATHI_CREATURES_ELIMINATED, 1); + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + if (!GET_GAME_STATE (SPATHI_SHIELDED_SELVES) + && ActivateStarShip (SPATHI_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (SPATHI_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (SPATHI_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + InitCommunication (SPATHI_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + rand_val = DoPlanetaryAnalysis ( + &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc + ); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + i = (COUNT)~0; + rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; + i = (COUNT)~0; + GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; + + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; + if (!GET_GAME_STATE (UMGAH_BROADCASTERS)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (UMGAH_BCS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (UMGAH_BCS_STRTAB) + ); + } + LoadPlanet (FALSE); + break; + } + else if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + /* visiting Spathiwa */ + rand_val = DoPlanetaryAnalysis ( + &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc + ); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; + i = (COUNT)~0; + rand_val = GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 120; + pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = + CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, + pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 31; + + LoadPlanet (FALSE); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/gensup.c b/sc2/src/sc2code/planets/gensup.c new file mode 100644 index 000000000..376a8a4d9 --- /dev/null +++ b/sc2/src/sc2code/planets/gensup.c @@ -0,0 +1,147 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GenerateSupox (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + if (!GET_GAME_STATE (ULTRON_CONDITION)) + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + else + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << i); + + if (!GET_GAME_STATE (ULTRON_CONDITION)) + { + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + + SET_GAME_STATE (ULTRON_CONDITION, 1); + } + } + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 2; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 152L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (SUPOX_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (SUPOX_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (SUPOX_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (SUPOX_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + if (!GET_GAME_STATE (ULTRON_CONDITION)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/gensyr.c b/sc2/src/sc2code/planets/gensyr.c new file mode 100644 index 000000000..d7d7e7674 --- /dev/null +++ b/sc2/src/sc2code/planets/gensyr.c @@ -0,0 +1,116 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static void +GenerateTrap (BYTE control) +{ + switch (control) + { + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = TELLURIC_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 203L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + GenerateRandomIP (GENERATE_ORBITAL); + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE * 2; + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 35; + pSolarSysState->SysInfo.PlanetInfo.Weather = 3; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + } + break; + default: + GenerateRandomIP (control); + break; + } +} + +void +GenerateSyreen (BYTE control) +{ + if (CurStarDescPtr->Index == MYCON_TRAP_DEFINED) + { + GenerateTrap (control); + return; + } + + switch (control) + { + case GENERATE_MOONS: + GenerateRandomIP (GENERATE_MOONS); + if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; + pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; + pSolarSysState->MoonDesc[0].location.x = + COSINE (QUADRANT, pSolarSysState->MoonDesc[0].radius); + pSolarSysState->MoonDesc[0].location.y = + SINE (QUADRANT, pSolarSysState->MoonDesc[0].radius); + } + break; + case GENERATE_PLANETS: + { + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = + WATER_WORLD | PLANET_SHIELDED; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + GenerateRandomIP (GENERATE_ORBITAL); + pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 19; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + pSolarSysState->SysInfo.PlanetInfo.Weather = 0; + pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = + EARTH_ATMOSPHERE * 9 / 10; + break; + } + /* Starbase */ + else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + pSolarSysState->MenuState.Initialized += 2; + InitCommunication (SYREEN_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genthrad.c b/sc2/src/sc2code/planets/genthrad.c new file mode 100644 index 000000000..1ee21ae5d --- /dev/null +++ b/sc2/src/sc2code/planets/genthrad.c @@ -0,0 +1,211 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateThradd (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + DWORD rand_val, old_rand; + + if (CurStarDescPtr->Index != AQUA_HELIX_DEFINED) + { + COUNT i, which_node; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + else if (!GET_GAME_STATE (AQUA_HELIX)) + { + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (HELIX_VISITS, 0); + SET_GAME_STATE (AQUA_HELIX, 1); + SET_GAME_STATE (AQUA_HELIX_ON_SHIP, 1); + SET_GAME_STATE (HELIX_UNPROTECTED, 1); + } + } + + SeedRandom (old_rand); + break; + } + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + if (CurStarDescPtr->Index == AQUA_HELIX_DEFINED) + { + pSolarSysState->PlanetDesc[0].data_index = PRIMORDIAL_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 65L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + } + else + { + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 0; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 98L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + } + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (THRADDASH_SHIP, SPHERE_TRACKING) + && (CurStarDescPtr->Index == THRADD_DEFINED + || (!GET_GAME_STATE (HELIX_UNPROTECTED) + && (BYTE)(GET_GAME_STATE (THRADD_MISSION) - 1) >= 3))) + { + NotifyOthers (THRADDASH_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (THRADDASH_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + if (CurStarDescPtr->Index == THRADD_DEFINED) + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + } + else + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + } + InitCommunication (THRADD_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + if (CurStarDescPtr->Index == THRADD_DEFINED + || (!GET_GAME_STATE (HELIX_UNPROTECTED) + && (BYTE)(GET_GAME_STATE (THRADD_MISSION) - 1) >= 3)) + break; + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + } + + if (CurStarDescPtr->Index == AQUA_HELIX_DEFINED + && !GET_GAME_STATE (AQUA_HELIX)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (AQUA_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (AQUA_STRTAB) + ); + } + else if (CurStarDescPtr->Index == THRADD_DEFINED) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/gentopo.c b/sc2/src/sc2code/planets/gentopo.c new file mode 100644 index 000000000..8915e2a8f --- /dev/null +++ b/sc2/src/sc2code/planets/gentopo.c @@ -0,0 +1,202 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxlib.h" +#include "mathlib.h" + +void +DeltaTopography (COUNT num_iterations, PSBYTE DepthArray, PRECT pRect, + SIZE depth_delta) +{ + SIZE width, height, delta_y; + struct + { + COORD x_top, x_bot; + SIZE x_incr, delta_x, error_term; + } LineDDA0, LineDDA1; + + width = pRect->extent.width; + height = pRect->extent.height; + delta_y = (height - 1) << 1; + do + { + SIZE d; + COUNT h, w1, w2; + DWORD rand_val; + register PSBYTE lpDst; + + depth_delta = ((((SIZE)Random () & 1) << 1) - 1) * depth_delta; + + rand_val = Random (); + w1 = LOWORD (rand_val); + w2 = HIWORD (rand_val); + + LineDDA0.x_top = LOBYTE (w1) % width; + LineDDA0.x_bot = HIBYTE (w1) % width; + LineDDA0.delta_x = (LineDDA0.x_bot - LineDDA0.x_top) << 1; + if (LineDDA0.delta_x >= 0) + LineDDA0.x_incr = 1; + else + { + LineDDA0.x_incr = -1; + LineDDA0.delta_x = -LineDDA0.delta_x; + } + if (LineDDA0.delta_x > delta_y) + LineDDA0.error_term = -(LineDDA0.delta_x >> 1); + else + LineDDA0.error_term = -(delta_y >> 1); + + LineDDA1.x_top = (LOBYTE (w2) % (width - 1)) + LineDDA0.x_top + 1; + LineDDA1.x_bot = (HIBYTE (w2) % (width - 1)) + LineDDA0.x_bot + 1; + LineDDA1.delta_x = (LineDDA1.x_bot - LineDDA1.x_top) << 1; + if (LineDDA1.delta_x >= 0) + LineDDA1.x_incr = 1; + else + { + LineDDA1.x_incr = -1; + LineDDA1.delta_x = -LineDDA1.delta_x; + } + if (LineDDA1.delta_x > delta_y) + LineDDA1.error_term = -(LineDDA1.delta_x >> 1); + else + LineDDA1.error_term = -(delta_y >> 1); + + lpDst = &DepthArray[LineDDA0.x_top]; + h = height; + do + { + COUNT w; + + w1 = LineDDA1.x_top - LineDDA0.x_top; + w2 = width - w1; + + if ((int)(LineDDA0.x_top + w1) > (int)width) + w = width - LineDDA0.x_top; + else + { + w = w1; + LineDDA0.x_top += w1; + } + w1 -= w; + while (w--) + { + d = *lpDst + depth_delta; + if (d >= -128 && d <= 127) + *lpDst = (SBYTE)d; + ++lpDst; + } + if (w1 == 0) + { + if (LineDDA0.x_top == width) + { + LineDDA0.x_top = 0; + lpDst -= width; + } + } + else + { + LineDDA0.x_top = w1; + lpDst -= width; + do + { + d = *lpDst + depth_delta; + if (d >= -128 && d <= 127) + *lpDst = (SBYTE)d; + ++lpDst; + } while (--w1); + } + + if ((int)(LineDDA0.x_top + w2) > (int)width) + w = width - LineDDA0.x_top; + else + { + w = w2; + LineDDA0.x_top += w2; + } + w2 -= w; + while (w--) + { + d = *lpDst - depth_delta; + if (d >= -128 && d <= 127) + *lpDst = (SBYTE)d; + ++lpDst; + } + if (w2 == 0) + { + if (LineDDA0.x_top == width) + { + LineDDA0.x_top = 0; + lpDst -= width; + } + } + else + { + LineDDA0.x_top = w2; + lpDst -= width; + do + { + d = *lpDst - depth_delta; + if (d >= -128 && d <= 127) + *lpDst = (SBYTE)d; + ++lpDst; + } while (--w2); + } + + lpDst += pRect->extent.width; + + if (delta_y >= LineDDA0.delta_x) + { + if ((LineDDA0.error_term += LineDDA0.delta_x) >= 0) + { + lpDst += LineDDA0.x_incr; + LineDDA0.x_top += LineDDA0.x_incr; + LineDDA0.error_term -= delta_y; + } + } + else + { + do + { + lpDst += LineDDA0.x_incr; + LineDDA0.x_top += LineDDA0.x_incr; + } while ((LineDDA0.error_term += delta_y) < 0); + LineDDA0.error_term -= LineDDA0.delta_x; + } + + if (delta_y >= LineDDA1.delta_x) + { + if ((LineDDA1.error_term += LineDDA1.delta_x) >= 0) + { + LineDDA1.x_top += LineDDA1.x_incr; + LineDDA1.error_term -= delta_y; + } + } + else + { + do + { + LineDDA1.x_top += LineDDA1.x_incr; + } while ((LineDDA1.error_term += delta_y) < 0); + LineDDA1.error_term -= LineDDA1.delta_x; + } + } while (--h); + } while (--num_iterations); +} + + + diff --git a/sc2/src/sc2code/planets/genutw.c b/sc2/src/sc2code/planets/genutw.c new file mode 100644 index 000000000..788556a8b --- /dev/null +++ b/sc2/src/sc2code/planets/genutw.c @@ -0,0 +1,255 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateUtwig (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + if (CurStarDescPtr->Index == BOMB_DEFINED + && !GET_GAME_STATE (UTWIG_BOMB)) + ReinitQueue (&GLOBAL (npc_built_ship_q)); + else + GenerateRandomIP (INIT_NPCS); + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + if (CurStarDescPtr->Index == UTWIG_DEFINED) + { + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 174L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + } + break; + } + case GENERATE_ENERGY: + { + DWORD rand_val, old_rand; + + if (CurStarDescPtr->Index == UTWIG_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + else if (CurStarDescPtr->Index == BOMB_DEFINED + && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[5] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] + && !GET_GAME_STATE (UTWIG_BOMB)) + { + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (UTWIG_BOMB, 1); + SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 1); + SET_GAME_STATE (DRUUGE_MANNER, 1); + SET_GAME_STATE (DRUUGE_VISITS, 0); + SET_GAME_STATE (DRUUGE_HOME_VISITS, 0); + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + } + case GENERATE_ORBITAL: + if ((CurStarDescPtr->Index == UTWIG_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + || (CurStarDescPtr->Index == BOMB_DEFINED + && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[5] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] + && !GET_GAME_STATE (UTWIG_BOMB))) + { + if ((CurStarDescPtr->Index == UTWIG_DEFINED + || !GET_GAME_STATE (UTWIG_HAVE_ULTRON)) + && ActivateStarShip (UTWIG_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (UTWIG_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (UTWIG_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + if (CurStarDescPtr->Index == UTWIG_DEFINED) + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + } + else + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + } + InitCommunication (UTWIG_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else if (CurStarDescPtr->Index == BOMB_DEFINED + && !GET_GAME_STATE (BOMB_UNPROTECTED) + && ActivateStarShip (DRUUGE_SHIP, SPHERE_TRACKING)) + { + COUNT i; + + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + for (i = 0; i < 5; ++i) + CloneShipFragment (DRUUGE_SHIP, + &GLOBAL (npc_built_ship_q), 0); + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + InitCommunication (DRUUGE_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + else + { + BOOLEAN DruugeSurvivors; + + DruugeSurvivors = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ) != 0; + + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + if (DruugeSurvivors) + break; + + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + SET_GAME_STATE (BOMB_UNPROTECTED, 1); + } + } + + if (CurStarDescPtr->Index == BOMB_DEFINED) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (BOMB_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (BOMB_STRTAB) + ); + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + GenerateRandomIP (GENERATE_ORBITAL); + if (CurStarDescPtr->Index == UTWIG_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.Weather = 1; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; + } + break; + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genvault.c b/sc2/src/sc2code/planets/genvault.c new file mode 100644 index 000000000..c0c37da1b --- /dev/null +++ b/sc2/src/sc2code/planets/genvault.c @@ -0,0 +1,108 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GenerateShipVault (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (!GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + else + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->CurNode = 1; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << 0); + if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) + { + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + + SET_GAME_STATE (SHIP_VAULT_UNLOCKED, 1); + SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 0); + SET_GAME_STATE (SYREEN_HOME_VISITS, 0); + } + else if (!GET_GAME_STATE (KNOW_SYREEN_VAULT)) + { + SET_GAME_STATE (KNOW_SYREEN_VAULT, 1); + SET_GAME_STATE (SYREEN_HOME_VISITS, 0); + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] + && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (VAULT_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (VAULT_STRTAB) + ); + if (GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 2 + ); + else if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genvux.c b/sc2/src/sc2code/planets/genvux.c new file mode 100644 index 000000000..53bf9d8c9 --- /dev/null +++ b/sc2/src/sc2code/planets/genvux.c @@ -0,0 +1,336 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" +#include "lifeform.h" + +void +GenerateVUX (BYTE control) +{ + DWORD rand_val; + + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] + && CurStarDescPtr->Index != VUX_BEAST_DEFINED) + { + if (CurStarDescPtr->Index == MAIDENS_DEFINED + && !GET_GAME_STATE (SHOFIXTI_MAIDENS)) + { + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = MAP_WIDTH / 3; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT * 5 / 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + && pSolarSysState->CurNode == (COUNT)~0) + pSolarSysState->CurNode = 1; + else + { + pSolarSysState->CurNode = 0; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + SET_GAME_STATE (SHOFIXTI_MAIDENS, 1); + SET_GAME_STATE (MAIDENS_ON_SHIP, 1); + } + } + break; + } + else if (CurStarDescPtr->Index == VUX_DEFINED) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + + if (CurStarDescPtr->Index == MAIDENS_DEFINED) + { + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 212L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + } + else + { + if (CurStarDescPtr->Index == VUX_DEFINED) + { + pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 42L / 100; + angle = HALF_CIRCLE + OCTANT; + } + else /* if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) */ + { + memmove (&pSolarSysState->PlanetDesc[1], + &pSolarSysState->PlanetDesc[0], + sizeof (pSolarSysState->PlanetDesc[0]) + * pSolarSysState->SunDesc[0].NumPlanets); + ++pSolarSysState->SunDesc[0].NumPlanets; + + angle = HALF_CIRCLE - OCTANT; + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 110L / 100; + pSolarSysState->PlanetDesc[0].NumPlanets = 0; + } + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].rand_seed = MAKE_DWORD ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + } + break; + } + case GENERATE_ORBITAL: + { + if ((pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] + && (CurStarDescPtr->Index == VUX_DEFINED + || (CurStarDescPtr->Index == MAIDENS_DEFINED + && !GET_GAME_STATE (ZEX_IS_DEAD)))) + && ActivateStarShip (VUX_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (VUX_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (VUX_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + if (CurStarDescPtr->Index == VUX_DEFINED) + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + } + else + { + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); + } + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + InitCommunication (VUX_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + else + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + if (CurStarDescPtr->Index == VUX_DEFINED + || !GET_GAME_STATE (ZEX_IS_DEAD)) + break; + + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + ClearSemaphore (&GraphicsSem); + } + } + + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (CurStarDescPtr->Index == MAIDENS_DEFINED) + { + if (!GET_GAME_STATE (SHOFIXTI_MAIDENS)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (MAIDENS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (MAIDENS_STRTAB) + ); + } + } + else if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) + { + if (!GET_GAME_STATE (VUX_BEAST)) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = 0; + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (BEAST_STRTAB) + ); + } + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + GenerateRandomIP (GENERATE_ORBITAL); + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + pSolarSysState->SysInfo.PlanetInfo.Weather = 2; + pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; + } + break; + } + case GENERATE_LIFE: + if (CurStarDescPtr->Index == MAIDENS_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i; + DWORD old_rand; + + old_rand = SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); + + i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + if (i < 4) + pSolarSysState->SysInfo.PlanetInfo.CurType = 9; + else if (i < 8) + pSolarSysState->SysInfo.PlanetInfo.CurType = 14; + else /* if (i < 12) */ + pSolarSysState->SysInfo.PlanetInfo.CurType = 18; + if (i >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << i))) + break; + } while (++i < 12); + pSolarSysState->CurNode = i; + + SeedRandom (old_rand); + break; + } + else if (CurStarDescPtr->Index == VUX_BEAST_DEFINED + && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i; + DWORD old_rand; + + old_rand = SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); + + i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + if (i == 0) + pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES + 2; + else if (i <= 5) + /* {SPEED_MOTIONLESS | DANGER_NORMAL, MAKE_BYTE (5, 3)}, */ + pSolarSysState->SysInfo.PlanetInfo.CurType = 3; + else /* if (i <= 10) */ + /* {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_NORMAL, MAKE_BYTE (3, 8)}, */ + pSolarSysState->SysInfo.PlanetInfo.CurType = 8; + if (i >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << i))) + break; + else if (i == 0 + && (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << i)) + && !GET_GAME_STATE (VUX_BEAST)) + { + PPLANETSIDE_DESC pPSD; + + pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; + UnbatchGraphics (); + DoDiscoveryReport (pPSD->OldMenuSounds); + BatchGraphics (); + pPSD->InTransit = TRUE; + + SET_GAME_STATE (VUX_BEAST, 1); + SET_GAME_STATE (VUX_BEAST_ON_SHIP, 1); + } + } while (++i < 11); + pSolarSysState->CurNode = i; + + SeedRandom (old_rand); + break; + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genwreck.c b/sc2/src/sc2code/planets/genwreck.c new file mode 100644 index 000000000..4ca8642b8 --- /dev/null +++ b/sc2/src/sc2code/planets/genwreck.c @@ -0,0 +1,95 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" + +void +GenerateUrquanWreck (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[6]) + { + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (!GET_GAME_STATE (PORTAL_KEY)) + pSolarSysState->SysInfo.PlanetInfo.CurType = 0; + else + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->CurNode = 1; + if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << 0)) + { + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + &= ~(1L << 0); + + if (!GET_GAME_STATE (PORTAL_KEY)) + { + ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; + + SET_GAME_STATE (PORTAL_KEY, 1); + SET_GAME_STATE (PORTAL_KEY_ON_SHIP, 1); + } + } + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[6]) + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (WRECK_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (WRECK_STRTAB) + ); + if (GET_GAME_STATE (PORTAL_KEY)) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + SetAbsStringTableIndex ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, + 1 + ); + } + default: + GenerateRandomIP (control); + break; + } +} + + diff --git a/sc2/src/sc2code/planets/genyeh.c b/sc2/src/sc2code/planets/genyeh.c new file mode 100644 index 000000000..8f0b14b28 --- /dev/null +++ b/sc2/src/sc2code/planets/genyeh.c @@ -0,0 +1,124 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +GenerateYehat (BYTE control) +{ + switch (control) + { + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 106L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING)) + { + NotifyOthers (YEHAT_SHIP, (BYTE)~0); + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + CloneShipFragment (YEHAT_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (YEHAT_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/genzoq.c b/sc2/src/sc2code/planets/genzoq.c new file mode 100644 index 000000000..df73cc44f --- /dev/null +++ b/sc2/src/sc2code/planets/genzoq.c @@ -0,0 +1,232 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static void +check_scout (void) +{ + HSTARSHIP hStarShip; + + if (GLOBAL (BattleGroupRef) + && (hStarShip = GetHeadLink ( + &GLOBAL (npc_built_ship_q) + ))) + { + BYTE task; + SHIP_FRAGMENTPTR FragPtr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + task = GET_GROUP_MISSION (FragPtr); + + if (task & REFORM_GROUP) + { + SET_GROUP_MISSION (FragPtr, + FLEE | IGNORE_FLAGSHIP | REFORM_GROUP); + SET_GROUP_DEST (FragPtr, 0); + } + + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } +} + +static void +GenerateScout (BYTE control) +{ + switch (control) + { + case INIT_NPCS: + if (!GET_GAME_STATE (MET_ZOQFOT)) + { + BYTE b0, b1, b2, b3; + + b0 = GET_GAME_STATE (ZOQFOT_GRPOFFS0); + b1 = GET_GAME_STATE (ZOQFOT_GRPOFFS1); + b2 = GET_GAME_STATE (ZOQFOT_GRPOFFS2); + b3 = GET_GAME_STATE (ZOQFOT_GRPOFFS3); + GLOBAL (BattleGroupRef) = MAKE_DWORD ( + MAKE_WORD (b0, b1), MAKE_WORD (b2, b3) + ); + if (GLOBAL (BattleGroupRef) == 0) + { + CloneShipFragment (ZOQFOTPIK_SHIP, + &GLOBAL (npc_built_ship_q), 0); + + GLOBAL (BattleGroupRef) = PutGroupInfo (~0L, 1); + b0 = LOBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b1 = HIBYTE (LOWORD (GLOBAL (BattleGroupRef))); + b2 = LOBYTE (HIWORD (GLOBAL (BattleGroupRef))); + b3 = HIBYTE (HIWORD (GLOBAL (BattleGroupRef))); + SET_GAME_STATE (ZOQFOT_GRPOFFS0, b0); + SET_GAME_STATE (ZOQFOT_GRPOFFS1, b1); + SET_GAME_STATE (ZOQFOT_GRPOFFS2, b2); + SET_GAME_STATE (ZOQFOT_GRPOFFS3, b3); + } + } + GenerateRandomIP (INIT_NPCS); + break; + case REINIT_NPCS: + GenerateRandomIP (REINIT_NPCS); + check_scout (); + break; + default: + GenerateRandomIP (control); + break; + } +} + +void +GenerateZoqFotPik (BYTE control) +{ + if (CurStarDescPtr->Index == ZOQ_SCOUT_DEFINED) + { + GenerateScout (control); + return; + } + + switch (control) + { + case INIT_NPCS: + if (GET_GAME_STATE (ZOQFOT_DISTRESS) != 1) + GenerateRandomIP (INIT_NPCS); + break; + case GENERATE_ENERGY: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + COUNT i, which_node; + DWORD rand_val, old_rand; + + old_rand = SeedRandom ( + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] + ); + + which_node = i = 0; + do + { + rand_val = Random (); + pSolarSysState->SysInfo.PlanetInfo.CurPt.x = + (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurPt.y = + (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; + pSolarSysState->SysInfo.PlanetInfo.CurType = 1; + pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; + if (which_node >= pSolarSysState->CurNode + && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] + & (1L << i))) + break; + ++which_node; + } while (++i < 16); + pSolarSysState->CurNode = which_node; + + SeedRandom (old_rand); + break; + } + pSolarSysState->CurNode = 0; + break; + case GENERATE_PLANETS: + { + COUNT angle; + + GenerateRandomIP (GENERATE_PLANETS); + pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; + pSolarSysState->PlanetDesc[0].NumPlanets = 1; + pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 138L / 100; + angle = ARCTAN ( + pSolarSysState->PlanetDesc[0].location.x, + pSolarSysState->PlanetDesc[0].location.y + ); + pSolarSysState->PlanetDesc[0].location.x = + COSINE (angle, pSolarSysState->PlanetDesc[0].radius); + pSolarSysState->PlanetDesc[0].location.y = + SINE (angle, pSolarSysState->PlanetDesc[0].radius); + break; + } + case GENERATE_ORBITAL: + if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) + { + if (ActivateStarShip (ZOQFOTPIK_SHIP, SPHERE_TRACKING)) + { + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + if (GET_GAME_STATE (ZOQFOT_DISTRESS)) + { + CloneShipFragment (BLACK_URQUAN_SHIP, + &GLOBAL (npc_built_ship_q), 0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (BLACKURQ_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + break; + + if (GetHeadLink (&GLOBAL (npc_built_ship_q))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + + break; + } + } + + CloneShipFragment (ZOQFOTPIK_SHIP, + &GLOBAL (npc_built_ship_q), (BYTE)~0); + + pSolarSysState->MenuState.Initialized += 2; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); + InitCommunication (ZOQFOTPIK_CONVERSATION); + pSolarSysState->MenuState.Initialized -= 2; + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + GetGroupInfo (0L, 0); + } + break; + } + else + { + pSolarSysState->SysInfo.PlanetInfo.LanderFont = + CaptureFont ( + LoadGraphic (LANDER_FONT) + ); + pSolarSysState->PlanetSideFrame[1] = + CaptureDrawable ( + LoadGraphic (RUINS_MASK_PMAP_ANIM) + ); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = + CaptureStringTable ( + LoadStringTable (RUINS_STRTAB) + ); + } + } + default: + GenerateRandomIP (control); + break; + } +} + diff --git a/sc2/src/sc2code/planets/lander.c b/sc2/src/sc2code/planets/lander.c new file mode 100644 index 000000000..5ea9241d7 --- /dev/null +++ b/sc2/src/sc2code/planets/lander.c @@ -0,0 +1,2140 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lander.h" +#include "lifeform.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void InsertPrim (PRIM_LINKS *pLinks, COUNT PI, COUNT iPI); + +void +DrawPlanet(int x, int y, int dy, unsigned int rgb); + +void RepairBackRect (PRECT pRect); + +void +SetPlanetTilt (int da); + +//End Added by Chris + +extern void DrawScannedObjects (BOOLEAN Reversed); + +FRAME LanderFrame[8]; +static SOUND LanderSounds; +MUSIC_REF LanderMusic; +#define NUM_ORBIT_THEMES 5 +static MUSIC_REF OrbitMusic[NUM_ORBIT_THEMES]; +const LIFEFORM_DESC CreatureData[] = +{ + {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (1, 1)}, + {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (6, 1)}, + {SPEED_MOTIONLESS | DANGER_WEAK, MAKE_BYTE (3, 1)}, + {SPEED_MOTIONLESS | DANGER_NORMAL, MAKE_BYTE (5, 3)}, + {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (2, 10)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (1, 2)}, + {BEHAVIOR_FLEE | AWARENESS_MEDIUM | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (8, 5)}, + {BEHAVIOR_HUNT | AWARENESS_LOW | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (2, 2)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_NORMAL, MAKE_BYTE (3, 8)}, + {BEHAVIOR_HUNT | AWARENESS_MEDIUM | SPEED_SLOW | DANGER_MONSTROUS, MAKE_BYTE (10, 15)}, + {BEHAVIOR_HUNT | AWARENESS_MEDIUM | SPEED_MEDIUM | DANGER_WEAK, MAKE_BYTE (3, 3)}, + {BEHAVIOR_FLEE | AWARENESS_MEDIUM | SPEED_MEDIUM | DANGER_HARMLESS, MAKE_BYTE (2, 1)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_MEDIUM | DANGER_WEAK, MAKE_BYTE (2, 2)}, + {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_MEDIUM | DANGER_NORMAL, MAKE_BYTE (4, 6)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_MEDIUM | DANGER_MONSTROUS, MAKE_BYTE (9, 12)}, + {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (3, 1)}, + {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_FAST | DANGER_HARMLESS, MAKE_BYTE (1, 1)}, + {BEHAVIOR_HUNT | AWARENESS_LOW | SPEED_FAST | DANGER_NORMAL, MAKE_BYTE (7, 8)}, + {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (15, 2)}, + {BEHAVIOR_FLEE | AWARENESS_LOW | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (1, 1)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (6, 2)}, + {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (4, 2)}, + {SPEED_MOTIONLESS | DANGER_WEAK, MAKE_BYTE (8, 5)}, + + {SPEED_MOTIONLESS | DANGER_MONSTROUS, MAKE_BYTE (1, 1)}, + {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (0, 1)}, + {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_FAST | DANGER_MONSTROUS, MAKE_BYTE (15, 15)}, +}; + +#define FLASH_WIDTH 9 +#define FLASH_HEIGHT 9 + +extern PRIM_LINKS DisplayLinks; + +#define DAMAGE_CYCLE 6 +#define EXPLOSION_LIFE 10 + +#define SHIELD_BIT (1 << 7) + +#define DEATH_EXPLOSION 0 + +#define SURFACE_X SIS_ORG_X +#define SURFACE_Y SIS_ORG_Y +#define SURFACE_WIDTH SIS_SCREEN_WIDTH +#define SURFACE_HEIGHT (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 5) + +#define REPAIR_LANDER (1 << 7) +#define REPAIR_TRANSITION (1 << 6) +#define KILL_CREW (1 << 5) +#define ADD_AT_END (1 << 4) +#define REPAIR_COUNT (0xf) + +#define LANDER_SPEED_DENOM 10 + +static BYTE lander_flags; + +static COLOR +DamageColorCycle (COLOR c, COUNT i) +{ + COLOR damage_tab[DAMAGE_CYCLE + 1] = + { + WHITE_COLOR, + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7E), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7C), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E), + }; + + if (i) + c = damage_tab[i]; + else if (c == WHITE_COLOR) + c = damage_tab[6]; + else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E)) + c = damage_tab[5]; + else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78)) + c = damage_tab[4]; + else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A)) + c = damage_tab[3]; + else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7C)) + c = damage_tab[2]; + else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7E)) + c = damage_tab[1]; + else + c = damage_tab[0]; + + return (c); +} + +#define MAGNIFICATION (1 << MAG_SHIFT) + +static BOOLEAN +RepairTopography (ELEMENTPTR ElementPtr) +{ + //BOOLEAN CursorIntersect; + SIZE delta; + RECT r; + STAMP s; + + s.origin = ElementPtr->current.location; + + GetFrameRect (ElementPtr->next.image.frame, &r); + r.corner.x += ElementPtr->current.location.x; + r.corner.y += ElementPtr->current.location.y; + + delta = (ElementPtr->next.location.x >> MAG_SHIFT) - r.corner.x; + if (delta >= 0) + r.extent.width += delta; + else + { + r.corner.x += delta; + r.extent.width -= delta; + } + if ((ElementPtr->current.location.x += delta) < 0) + ElementPtr->current.location.x += MAP_WIDTH; + else if (ElementPtr->current.location.x >= MAP_WIDTH) + ElementPtr->current.location.x -= MAP_WIDTH; + + delta = (ElementPtr->next.location.y >> MAG_SHIFT) - r.corner.y; + if (delta >= 0) + r.extent.height += delta; + else + { + r.corner.y += delta; + r.extent.height -= delta; + } + ElementPtr->current.location.y += delta; + + return (FALSE); +} + +static HELEMENT AddGroundDisaster (COUNT which_disaster); + +void +object_animation (PELEMENT ElementPtr) +{ + COUNT frame_index, angle; + PPRIMITIVE pPrim; + + pPrim = &DisplayArray[ElementPtr->PrimIndex]; + if (GetPrimType (pPrim) == STAMPFILL_PRIM + && !((ElementPtr->state_flags & FINITE_LIFE) + && ElementPtr->mass_points == EARTHQUAKE_DISASTER)) + { + COLOR c; + + if ((c = DamageColorCycle ( + GetPrimColor (pPrim), 0 + )) == WHITE_COLOR) + { + SetPrimType (pPrim, STAMP_PRIM); + if (ElementPtr->hit_points == 0) + { + ZeroVelocityComponents (&ElementPtr->velocity); + pPrim->Object.Stamp.frame = + SetAbsFrameIndex (pPrim->Object.Stamp.frame, 0); + + PlaySound (SetAbsSoundIndex (LanderSounds, LIFEFORM_CANNED), + GAME_SOUND_PRIORITY); + } + } + + SetPrimColor (pPrim, c); + } + + frame_index = GetFrameIndex (pPrim->Object.Stamp.frame) + 1; + if (LONIBBLE (ElementPtr->turn_wait)) + --ElementPtr->turn_wait; + else + { + ElementPtr->turn_wait += HINIBBLE (ElementPtr->turn_wait); + + pPrim->Object.Stamp.frame = + IncFrameIndex (pPrim->Object.Stamp.frame); + if (ElementPtr->state_flags & FINITE_LIFE) + { + if (ElementPtr->mass_points == DEATH_EXPLOSION) + { + if (++pMenuState->CurState >= EXPLOSION_LIFE) + pPrim->Object.Stamp.frame = + DecFrameIndex (pPrim->Object.Stamp.frame); + } + else if (ElementPtr->mass_points == EARTHQUAKE_DISASTER) + { + SIZE s; + + if (frame_index >= 13) + s = 0; + else + s = (14 - frame_index) >> 1; + SetPrimColor (pPrim, BUILD_COLOR (0x8000 | MAKE_RGB15 (0x1F, 0x1F, 0x1F), s)); + if (frame_index == 13) + PlaySound (SetAbsSoundIndex (LanderSounds, EARTHQUAKE_DISASTER), + GAME_SOUND_PRIORITY); + } + + if (ElementPtr->mass_points == LAVASPOT_DISASTER + && frame_index == 5 + && (BYTE)Random () < 256 * 90 / 100) + { + HELEMENT hLavaElement; + + hLavaElement = AddGroundDisaster (LAVASPOT_DISASTER); + if (hLavaElement) + { + ELEMENTPTR LavaElementPtr; + + angle = FACING_TO_ANGLE (ElementPtr->hit_points); + LockElement (hLavaElement, &LavaElementPtr); + LavaElementPtr->next.location = ElementPtr->next.location; + LavaElementPtr->next.location.x += COSINE (angle, 4); + LavaElementPtr->next.location.y += SINE (angle, 4); + if (LavaElementPtr->next.location.y < 0) + LavaElementPtr->next.location.y = 0; + else if (LavaElementPtr->next.location.y >= (MAP_HEIGHT << MAG_SHIFT)) + LavaElementPtr->next.location.y = (MAP_HEIGHT << MAG_SHIFT) - 1; + if (LavaElementPtr->next.location.x < 0) + LavaElementPtr->next.location.x += MAP_WIDTH << MAG_SHIFT; + else + LavaElementPtr->next.location.x %= MAP_WIDTH << MAG_SHIFT; + LavaElementPtr->hit_points = NORMALIZE_FACING ( + ElementPtr->hit_points + ((COUNT)Random () % 3) - 1 + ); + UnlockElement (hLavaElement); + } + } + } + else if (!(frame_index & 3) && ElementPtr->hit_points) + { + BYTE index; + COUNT speed; + + index = ElementPtr->mass_points & ~CREATURE_AWARE; + speed = CreatureData[index].Attributes & SPEED_MASK; + if (speed) + { + SIZE dx, dy; + COUNT old_angle; + + dx = pSolarSysState->MenuState.first_item.x + - ElementPtr->next.location.x; + if (dx < 0 && dx < -(MAP_WIDTH << (MAG_SHIFT - 1))) + dx += MAP_WIDTH << MAG_SHIFT; + else if (dx > (MAP_WIDTH << (MAG_SHIFT - 1))) + dx -= MAP_WIDTH << MAG_SHIFT; + dy = pSolarSysState->MenuState.first_item.y + - ElementPtr->next.location.y; + angle = ARCTAN (dx, dy); + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + + if (dx >= SURFACE_WIDTH || dy >= SURFACE_WIDTH + || dx * dx + dy * dy >= SURFACE_WIDTH * SURFACE_WIDTH) + ElementPtr->mass_points &= ~CREATURE_AWARE; + else if (!(ElementPtr->mass_points & CREATURE_AWARE)) + { + BYTE DetectPercent; + + DetectPercent = (((BYTE)(CreatureData[index].Attributes + & AWARENESS_MASK) >> AWARENESS_SHIFT) + 1) + * (30 / 6); + if (((BYTE)Random () % 100) < DetectPercent) + { + ElementPtr->thrust_wait = 0; + ElementPtr->mass_points |= CREATURE_AWARE; + } + } + + if (ElementPtr->next.location.y == 0 + || ElementPtr->next.location.y == + (MAP_HEIGHT << MAG_SHIFT) - 1) + ElementPtr->thrust_wait = 0; + + old_angle = GetVelocityTravelAngle (&ElementPtr->velocity); + if (ElementPtr->thrust_wait) + { + --ElementPtr->thrust_wait; + angle = old_angle; + } + else if (!(ElementPtr->mass_points & CREATURE_AWARE) + || (CreatureData[index].Attributes + & BEHAVIOR_MASK) == BEHAVIOR_UNPREDICTABLE) + { + COUNT rand_val; + + rand_val = (COUNT)Random (); + angle = NORMALIZE_ANGLE (LOBYTE (rand_val)); + ElementPtr->thrust_wait = + (HIBYTE (rand_val) >> 2) + 10; + } + else if ((CreatureData[index].Attributes + & BEHAVIOR_MASK) == BEHAVIOR_FLEE) + { + if (ElementPtr->next.location.y == 0 + || ElementPtr->next.location.y == + (MAP_HEIGHT << MAG_SHIFT) - 1) + { + if (angle & (HALF_CIRCLE - 1)) + angle = HALF_CIRCLE - angle; + else if (old_angle == QUADRANT + || old_angle == (FULL_CIRCLE - QUADRANT)) + angle = old_angle; + else + angle = (((COUNT)Random () & 1) + * HALF_CIRCLE) - QUADRANT; + ElementPtr->thrust_wait = 5; + } + angle = NORMALIZE_ANGLE (angle + HALF_CIRCLE); + } + + switch (speed) + { + case SPEED_SLOW: + speed = WORLD_TO_VELOCITY (2 * 1) >> 2; + break; + case SPEED_MEDIUM: + speed = WORLD_TO_VELOCITY (2 * 1) >> 1; + break; + case SPEED_FAST: + speed = WORLD_TO_VELOCITY (2 * 1) * 9 / 10; + break; + } + + SetVelocityComponents ( + &ElementPtr->velocity, + COSINE (angle, speed), + SINE (angle, speed) + ); + } + } + } + + if ((ElementPtr->state_flags & FINITE_LIFE) + && ElementPtr->mass_points == DEATH_EXPLOSION + && GetSuccLink (DisplayLinks) != ElementPtr->PrimIndex) + lander_flags |= ADD_AT_END; +} + +#define NUM_CREW_COLS 6 +#define NUM_CREW_ROWS 2 + +static void +DeltaLanderCrew (SIZE crew_delta, COUNT which_disaster) +{ + STAMP s; + CONTEXT OldContext; + + if (crew_delta > 0) + { + crew_delta = HIBYTE (pMenuState->delta_item); + pMenuState->delta_item += MAKE_WORD (0, 1); + + s.frame = SetAbsFrameIndex (LanderFrame[0], 55); + } + else /* if (crew_delta < 0) */ + { + BYTE ShieldFlags; + + ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); + ShieldFlags &= 1 << which_disaster; + crew_delta = HIBYTE (pMenuState->delta_item); + if (ShieldFlags && (BYTE)Random () < 256 * 95 / 100) + pMenuState->delta_item = SHIELD_BIT; + else + { + ShieldFlags = 0; + if (--crew_delta == 0) + pMenuState->CurState = 0; + pMenuState->delta_item = 0; + } + + pMenuState->delta_item |= MAKE_WORD (DAMAGE_CYCLE, crew_delta); + if (ShieldFlags) + return; + + s.frame = SetAbsFrameIndex (LanderFrame[0], 56); + + PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_INJURED), + GAME_SOUND_PRIORITY); + } + + s.origin.x = 11 + (6 * (crew_delta % NUM_CREW_COLS)); + s.origin.y = 35 - (6 * (crew_delta / NUM_CREW_COLS)); + + OldContext = SetContext (RadarContext); + DrawStamp (&s); + SetContext (OldContext); +} + +static void +FillLanderHold (PPLANETSIDE_DESC pPSD, COUNT scan, COUNT NumRetrieved) +{ + COUNT start_count; + STAMP s; + CONTEXT OldContext; + + PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_PICKUP), + GAME_SOUND_PRIORITY); + + if (scan == BIOLOGICAL_SCAN) + { + start_count = pPSD->BiologicalLevel; + + s.frame = SetAbsFrameIndex (LanderFrame[0], 41); + + pPSD->BiologicalLevel += NumRetrieved; + } + else + { + start_count = pPSD->ElementLevel; + pPSD->ElementLevel += NumRetrieved; + if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) + { + start_count >>= 1; + NumRetrieved = (pPSD->ElementLevel >> 1) - start_count; + } + + s.frame = SetAbsFrameIndex (LanderFrame[0], 43); + } + + s.origin.x = 0; + s.origin.y = -(int)start_count; + if (!(start_count & 1)) + s.frame = IncFrameIndex (s.frame); + + OldContext = SetContext (RadarContext); + while (NumRetrieved--) + { + if (start_count++ & 1) + s.frame = IncFrameIndex (s.frame); + else + s.frame = DecFrameIndex (s.frame); + DrawStamp (&s); + --s.origin.y; + } + SetContext (OldContext); +} + +static void +CheckObjectCollision (COUNT index) +{ + INTERSECT_CONTROL LanderControl; + MEM_HANDLE LanderHandle; + PPRIMITIVE pPrim, pLanderPrim; + PPLANETSIDE_DESC pPSD; + + if (index != END_OF_LIST) + { + pLanderPrim = &DisplayArray[index]; + LanderControl.IntersectStamp = pLanderPrim->Object.Stamp; + index = GetPredLink (GetPrimLinks (pLanderPrim)); + } + else + { + pLanderPrim = 0; + LanderControl.IntersectStamp.origin.x = SURFACE_WIDTH >> 1; + LanderControl.IntersectStamp.origin.y = SURFACE_HEIGHT >> 1; + LanderControl.IntersectStamp.frame = LanderFrame[0]; + index = GetSuccLink (DisplayLinks); + } + + pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; + LanderControl.EndPoint = LanderControl.IntersectStamp.origin; + LanderHandle = GetFrameHandle (LanderControl.IntersectStamp.frame); + + for (; index != END_OF_LIST; index = GetPredLink (GetPrimLinks (pPrim))) + { + INTERSECT_CONTROL ElementControl; + + pPrim = &DisplayArray[index]; + ElementControl.IntersectStamp = pPrim->Object.Stamp; + ElementControl.EndPoint = + ElementControl.IntersectStamp.origin; + + if (GetFrameHandle ( + ElementControl.IntersectStamp.frame + ) == LanderHandle) + CheckObjectCollision (index); + else if (DrawablesIntersect (&LanderControl, + &ElementControl, MAX_TIME_VALUE)) + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + + if (&DisplayArray[ElementPtr->PrimIndex] == pLanderPrim) + { + ElementPtr->state_flags |= DISAPPEARING; + UnlockElement (hElement); + + continue; + } + else if (&DisplayArray[ElementPtr->PrimIndex] == pPrim + && (ElementPtr->state_flags & BAD_GUY)) + { + COUNT scan, NumRetrieved; + SIZE which_node; + + scan = LOBYTE (ElementPtr->life_span); + if (pLanderPrim == 0) + { + if (HIBYTE (pMenuState->delta_item) == 0 + || pPSD->InTransit) + break; + + /* if a natural disaster */ + if (ElementPtr->state_flags & FINITE_LIFE) + { + scan = ElementPtr->mass_points; + switch (scan) + { + case EARTHQUAKE_DISASTER: + case LAVASPOT_DISASTER: + if ((BYTE)Random () < (256 >> 2)) + DeltaLanderCrew (-1, scan); + break; + } + + UnlockElement (hElement); + continue; + } + else if (scan == ENERGY_SCAN) + { + if (ElementPtr->mass_points == 1) + { + DWORD TimeIn; + + /* ran into Spathi on Pluto */ + TimeIn = GetTimeCounter (); + which_node = 8; + do + { + DeltaLanderCrew (-1, LANDER_INJURED); + TimeIn = SleepTask (TimeIn + 6); + } while (HIBYTE (pMenuState->delta_item) && --which_node); + } + + if (HIBYTE (pMenuState->delta_item) + && pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + && CurStarDescPtr->Index != ANDROSYNTH_DEFINED) + { + UnbatchGraphics (); + DoDiscoveryReport (pPSD->OldMenuSounds); + BatchGraphics (); + } + if (ElementPtr->mass_points == 0) + { + DestroyStringTable (ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + )); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; + UnlockElement (hElement); + continue; + } + } + else if (scan == BIOLOGICAL_SCAN + && ElementPtr->hit_points) + { + BYTE danger_vals[] = + { + 0, 6, 13, 26 + }; + + if (((COUNT)Random () & 127) < danger_vals[ + (CreatureData[ + ElementPtr->mass_points + & ~CREATURE_AWARE + ].Attributes & DANGER_MASK) + >> DANGER_SHIFT + ]) + { + PlaySound (SetAbsSoundIndex ( + LanderSounds, BIOLOGICAL_DISASTER + ), GAME_SOUND_PRIORITY); + DeltaLanderCrew (-1, BIOLOGICAL_DISASTER); + } + UnlockElement (hElement); + continue; + } + + NumRetrieved = ElementPtr->mass_points; + } + /* if a natural disaster */ + else if (ElementPtr->state_flags & FINITE_LIFE) + { + UnlockElement (hElement); + continue; + } + else + { + BYTE value; + + if (scan == ENERGY_SCAN) + { + UnlockElement (hElement); + break; + } + else if (scan == BIOLOGICAL_SCAN + && (value = LONIBBLE (CreatureData[ + ElementPtr->mass_points + & ~CREATURE_AWARE + ].ValueAndHitPoints))) + { + if (ElementPtr->hit_points) + { + if (--ElementPtr->hit_points == 0) + { + ElementPtr->mass_points = value; + DisplayArray[ + ElementPtr->PrimIndex + ].Object.Stamp.frame = + pSolarSysState->PlanetSideFrame[0]; + } + else if (CreatureData[ + ElementPtr->mass_points + & ~CREATURE_AWARE + ].Attributes & SPEED_MASK) + { + COUNT angle; + + angle = FACING_TO_ANGLE (GetFrameIndex ( + LanderControl.IntersectStamp.frame + ) - ANGLE_TO_FACING (FULL_CIRCLE)); + DeltaVelocityComponents ( + &ElementPtr->velocity, + COSINE (angle, WORLD_TO_VELOCITY (1)), + SINE (angle, WORLD_TO_VELOCITY (1)) + ); + ElementPtr->thrust_wait = 0; + ElementPtr->mass_points |= CREATURE_AWARE; + } + + SetPrimType (pPrim, STAMPFILL_PRIM); + SetPrimColor (pPrim, WHITE_COLOR); + + PlaySound (SetAbsSoundIndex ( + LanderSounds, LANDER_HITS + ), GAME_SOUND_PRIORITY); + } + UnlockElement (hElement); + break; + } + + NumRetrieved = 0; + } + + if (NumRetrieved) + { + switch (scan) + { + case ENERGY_SCAN: + break; + case MINERAL_SCAN: + if (pPSD->ElementLevel < pPSD->MaxElementLevel) + { + if (pPSD->ElementLevel + + NumRetrieved > pPSD->MaxElementLevel) + NumRetrieved = (COUNT)( + pPSD->MaxElementLevel + - pPSD->ElementLevel + ); + FillLanderHold (pPSD, scan, NumRetrieved); + if (scan == MINERAL_SCAN) + { + BYTE EType; + UNICODE ch, *pStr; + + EType = ElementPtr->turn_wait; + pPSD->ElementAmounts[ + ElementCategory (EType) + ] += NumRetrieved; + + pPSD->NumFrames = NUM_TEXT_FRAMES; + wsprintf (pPSD->AmountBuf, "%u", NumRetrieved); + pStr = GAME_STRING (EType + ELEMENTS_STRING_BASE); + + pPSD->MineralText[0].baseline.x = + (SURFACE_WIDTH >> 1) + + (ElementControl.EndPoint.x + - LanderControl.EndPoint.x); + pPSD->MineralText[0].baseline.y = + (SURFACE_HEIGHT >> 1) + + (ElementControl.EndPoint.y + - LanderControl.EndPoint.y); + pPSD->MineralText[0].CharCount = (COUNT)~0; + pPSD->MineralText[1].pStr = pStr; + while ((ch = *pStr++) && ch != ' ') + ; + if (ch == '\0') + { + pPSD->MineralText[1].CharCount = (COUNT)~0; + pPSD->MineralText[2].CharCount = 0; + } + else + { + pPSD->MineralText[1].CharCount = + (pStr - pPSD->MineralText[1].pStr) - 1; + pPSD->MineralText[2].pStr = pStr; + pPSD->MineralText[2].CharCount = (COUNT)~0; + } + } + break; + } + PlaySound (SetAbsSoundIndex ( + LanderSounds, LANDER_FULL + ), GAME_SOUND_PRIORITY); + continue; + case BIOLOGICAL_SCAN: + if (pPSD->BiologicalLevel < MAX_SCROUNGED) + { + if (pPSD->BiologicalLevel + + NumRetrieved > MAX_SCROUNGED) + NumRetrieved = (COUNT)( + MAX_SCROUNGED + - pPSD->BiologicalLevel + ); + FillLanderHold (pPSD, scan, NumRetrieved); + break; + } + PlaySound (SetAbsSoundIndex ( + LanderSounds, LANDER_FULL + ), GAME_SOUND_PRIORITY); + continue; + } + } + + which_node = HIBYTE (ElementPtr->life_span) - 1; + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] |= + (1L << which_node); + pSolarSysState->CurNode = (COUNT)~0; + (*pSolarSysState->GenFunc) ((BYTE)(scan + GENERATE_MINERAL)); + + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] & + (1L << which_node))) + { + if (DestroyStringTable (ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + ))) + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; + } + else + { + if (NumRetrieved && scan == ENERGY_SCAN) + pPSD->InTransit = TRUE; + + SET_GAME_STATE (PLANETARY_CHANGE, 1); + ElementPtr->state_flags |= DISAPPEARING; + } + UnlockElement (hElement); + } + else + { + UnlockElement (hElement); + } + } + } + } +} + +static void +lightning_process (PELEMENT ElementPtr) +{ + PPRIMITIVE pPrim; + + pPrim = &DisplayArray[ElementPtr->PrimIndex]; + if (LONIBBLE (ElementPtr->turn_wait)) + --ElementPtr->turn_wait; + else + { + COUNT num_frames; + + num_frames = GetFrameCount (pPrim->Object.Stamp.frame) - 7; + if (GetFrameIndex (pPrim->Object.Stamp.frame) >= num_frames) + pPrim->Object.Stamp.frame = + IncFrameIndex (pPrim->Object.Stamp.frame); + else + { + SIZE s; + + s = 7 - ((SIZE)ElementPtr->crew_level - (SIZE)ElementPtr->life_span); + if (s < 0) + s = 0; + SetPrimColor (pPrim, BUILD_COLOR (0x8000 | MAKE_RGB15 (0x1F, 0x1F, 0x1F), s)); + + if (ElementPtr->mass_points == LIGHTNING_DISASTER) + { + if (HIBYTE (pMenuState->delta_item) + && (BYTE)Random () < (256 / 10) + && !( + (PPLANETSIDE_DESC)pMenuState->ModuleFrame + )->InTransit) + lander_flags |= KILL_CREW; + + ElementPtr->next.location = + pSolarSysState->MenuState.first_item; + } + + pPrim->Object.Stamp.frame = + SetAbsFrameIndex (pPrim->Object.Stamp.frame, + (COUNT)Random () % num_frames); + } + + ElementPtr->turn_wait += HINIBBLE (ElementPtr->turn_wait); + } + + if (GetSuccLink (DisplayLinks) != ElementPtr->PrimIndex) + lander_flags |= ADD_AT_END; +} + +static void +AddLightning (void) +{ + HELEMENT hLightningElement; + + hLightningElement = AllocElement (); + if (hLightningElement) + { + DWORD rand_val; + ELEMENTPTR LightningElementPtr; + + LockElement (hLightningElement, &LightningElementPtr); + + LightningElementPtr->state_flags = FINITE_LIFE | BAD_GUY; + LightningElementPtr->preprocess_func = lightning_process; + if ((BYTE)Random () >= (256 >> 2)) + LightningElementPtr->mass_points = 0; + else + LightningElementPtr->mass_points = LIGHTNING_DISASTER; + + rand_val = Random (); + LightningElementPtr->life_span = 10 + (HIWORD (rand_val) % 10) + 1; + LightningElementPtr->next.location.x = ( + pSolarSysState->MenuState.first_item.x + + ((MAP_WIDTH << MAG_SHIFT) - ((SURFACE_WIDTH >> 1) - 6)) + + (LOBYTE (rand_val) % (SURFACE_WIDTH - 12)) + ) % (MAP_WIDTH << MAG_SHIFT); + LightningElementPtr->next.location.y = ( + pSolarSysState->MenuState.first_item.y + + ((MAP_HEIGHT << MAG_SHIFT) - ((SURFACE_HEIGHT >> 1) - 6)) + + (HIBYTE (rand_val) % (SURFACE_HEIGHT - 12)) + ) % (MAP_HEIGHT << MAG_SHIFT); + + LightningElementPtr->crew_level = LightningElementPtr->life_span; + + SetPrimType (&DisplayArray[LightningElementPtr->PrimIndex], STAMPFILL_PRIM); + SetPrimColor (&DisplayArray[LightningElementPtr->PrimIndex], WHITE_COLOR); + DisplayArray[LightningElementPtr->PrimIndex].Object.Stamp.frame = + LanderFrame[2]; + + UnlockElement (hLightningElement); + + PutElement (hLightningElement); + + PlaySound (SetAbsSoundIndex (LanderSounds, LIGHTNING_DISASTER), + GAME_SOUND_PRIORITY); + } +} + +static HELEMENT +AddGroundDisaster (COUNT which_disaster) +{ + HELEMENT hGroundDisasterElement; + + hGroundDisasterElement = AllocElement (); + if (hGroundDisasterElement) + { + DWORD rand_val; + ELEMENTPTR GroundDisasterElementPtr; + PPRIMITIVE pPrim; + + LockElement (hGroundDisasterElement, &GroundDisasterElementPtr); + + pPrim = &DisplayArray[GroundDisasterElementPtr->PrimIndex]; + GroundDisasterElementPtr->mass_points = which_disaster; + GroundDisasterElementPtr->state_flags = FINITE_LIFE | BAD_GUY; + GroundDisasterElementPtr->preprocess_func = object_animation; + + rand_val = Random (); + GroundDisasterElementPtr->next.location.x = ( + pSolarSysState->MenuState.first_item.x + + ((MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 8)) + + (LOWORD (rand_val) % (SURFACE_WIDTH * 3 / 4)) + ) % (MAP_WIDTH << MAG_SHIFT); + GroundDisasterElementPtr->next.location.y = ( + pSolarSysState->MenuState.first_item.y + + ((MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT * 3 / 8)) + + (HIWORD (rand_val) % (SURFACE_HEIGHT * 3 / 4)) + ) % (MAP_HEIGHT << MAG_SHIFT); + + + if (which_disaster == EARTHQUAKE_DISASTER) + { + SetPrimType (pPrim, STAMPFILL_PRIM); + pPrim->Object.Stamp.frame = LanderFrame[1]; + GroundDisasterElementPtr->turn_wait = MAKE_BYTE (2, 2); + } + else + { + SetPrimType (pPrim, STAMP_PRIM); + GroundDisasterElementPtr->hit_points = + NORMALIZE_FACING (Random ()); + pPrim->Object.Stamp.frame = LanderFrame[3]; + GroundDisasterElementPtr->turn_wait = MAKE_BYTE (0, 0); + } + GroundDisasterElementPtr->life_span = + GetFrameCount (pPrim->Object.Stamp.frame) + * (LONIBBLE (GroundDisasterElementPtr->turn_wait) + 1) - 1; + + UnlockElement (hGroundDisasterElement); + + PutElement (hGroundDisasterElement); + } + + return (hGroundDisasterElement); +} + +static void +BuildObjectList (void) +{ + DWORD rand_val; + POINT org; + HELEMENT hElement, hNextElement; + PPLANETSIDE_DESC pPSD; + + DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); + + lander_flags &= ~KILL_CREW; + + pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; + rand_val = Random (); + if (LOBYTE (HIWORD (rand_val)) < pPSD->FireChance) + { + AddGroundDisaster (LAVASPOT_DISASTER); + PlaySound (SetAbsSoundIndex (LanderSounds, LAVASPOT_DISASTER), + GAME_SOUND_PRIORITY); + } + + if (HIBYTE (LOWORD (rand_val)) < pPSD->TectonicsChance) + AddGroundDisaster (EARTHQUAKE_DISASTER); + + if (LOBYTE (LOWORD (rand_val)) < pPSD->WeatherChance) + AddLightning (); + + org = pSolarSysState->MenuState.first_item; + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + SIZE dx, dy; + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + + if (ElementPtr->life_span == 0 + || (ElementPtr->state_flags & DISAPPEARING)) + { + hNextElement = GetSuccElement (ElementPtr); + UnlockElement (hElement); + + if (ElementPtr->state_flags & APPEARING) + { + ElementPtr->current.location.x |= 0x8000; + ElementPtr->current.location.y |= 0x8000; + } + else + { + RemoveElement (hElement); + FreeElement (hElement); + } + + continue; + } + else if (ElementPtr->state_flags & FINITE_LIFE) + --ElementPtr->life_span; + + lander_flags &= ~ADD_AT_END; + + if (ElementPtr->preprocess_func) + (*ElementPtr->preprocess_func) (ElementPtr); + + GetNextVelocityComponents ( + &ElementPtr->velocity, &dx, &dy, 1 + ); + if (dx || dy) + { + ElementPtr->next.location.x += dx; + ElementPtr->next.location.y += dy; + /* if not lander's shot */ + if (ElementPtr->state_flags != (FINITE_LIFE | GOOD_GUY)) + { + if (ElementPtr->next.location.y < 0) + ElementPtr->next.location.y = 0; + else if (ElementPtr->next.location.y >= (MAP_HEIGHT << MAG_SHIFT)) + ElementPtr->next.location.y = (MAP_HEIGHT << MAG_SHIFT) - 1; + } + if (ElementPtr->state_flags & APPEARING) + ElementPtr->current.location.x |= 0x8000; + if (ElementPtr->next.location.x < 0) + ElementPtr->next.location.x += MAP_WIDTH << MAG_SHIFT; + else + ElementPtr->next.location.x %= MAP_WIDTH << MAG_SHIFT; + } + + { + PPRIMITIVE pPrim; + + pPrim = &DisplayArray[ElementPtr->PrimIndex]; + pPrim->Object.Stamp.origin.x = + ElementPtr->next.location.x + - org.x + (SURFACE_WIDTH >> 1); + if (pPrim->Object.Stamp.origin.x >= + (MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 2)) + pPrim->Object.Stamp.origin.x -= MAP_WIDTH << MAG_SHIFT; + else if (pPrim->Object.Stamp.origin.x <= + -((MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 2))) + pPrim->Object.Stamp.origin.x += MAP_WIDTH << MAG_SHIFT; + + pPrim->Object.Stamp.origin.y = + ElementPtr->next.location.y + - org.y + (SURFACE_HEIGHT >> 1); + + if (lander_flags & ADD_AT_END) + InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, END_OF_LIST); + else + InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, GetPredLink (DisplayLinks)); + } + + hNextElement = GetSuccElement (ElementPtr); + UnlockElement (hElement); + } +} + +static void +RepairScan (void) +{ + CONTEXT OldContext; + HELEMENT hElement, hNextElement; + extern void DrawScannedObjects (BOOLEAN Reversed); + + OldContext = SetContext (ScanContext); + + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + if (ElementPtr->current.location.x & 0x8000) + { + BOOLEAN remove; + + ElementPtr->current.location.x &= ~0x8000; + if (ElementPtr->current.location.y & 0x8000) + { + remove = TRUE; + ElementPtr->current.location.y &= ~0x8000; + } + else + remove = FALSE; + RepairTopography (ElementPtr); + if (remove) + { + UnlockElement (hElement); + RemoveElement (hElement); + FreeElement (hElement); + continue; + } + } + + UnlockElement (hElement); + } + + BatchGraphics (); +#if 1 + DrawPlanet (0, 0, 0, 0); +#endif + DrawScannedObjects (TRUE); + { +#define FLASH_INDEX 105 + STAMP s; + extern FRAME misc_data; + + s.origin = pMenuState->flash_rect0.corner; + s.frame = SetAbsFrameIndex (misc_data, FLASH_INDEX); + DrawStamp (&s); + } + UnbatchGraphics (); + + SetContext (OldContext); +} + +static void +ScrollPlanetSide (SIZE dx, SIZE dy, SIZE CountDown) +{ + POINT old_pt, new_pt; + STAMP lander_s, shadow_s, shield_s; + CONTEXT OldContext; + signed char lander_pos[] = { -10, 1, 12, 22, 31, 39, 45, 50, 54, 57, 59 }; + + old_pt.x = pSolarSysState->MenuState.first_item.x - (SURFACE_WIDTH >> 1); + old_pt.y = pSolarSysState->MenuState.first_item.y - (SURFACE_HEIGHT >> 1); + + new_pt.y = old_pt.y + dy; + if (new_pt.y < -(SURFACE_HEIGHT >> 1)) + { + new_pt.y = -(SURFACE_HEIGHT >> 1); + dy = new_pt.y - old_pt.y; + dx = 0; + ZeroVelocityComponents (&GLOBAL (velocity)); + } + else if (new_pt.y > (MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT >> 1)) + { + new_pt.y = (MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT >> 1); + dy = new_pt.y - old_pt.y; + dx = 0; + ZeroVelocityComponents (&GLOBAL (velocity)); + } + + new_pt.x = old_pt.x + dx; + if (new_pt.x < 0) + new_pt.x += MAP_WIDTH << MAG_SHIFT; + else if (new_pt.x >= MAP_WIDTH << MAG_SHIFT) + new_pt.x -= MAP_WIDTH << MAG_SHIFT; + + new_pt.x = pSolarSysState->MenuState.first_item.x + dx; + if (new_pt.x < 0) + new_pt.x += MAP_WIDTH << MAG_SHIFT; + else if (new_pt.x >= MAP_WIDTH << MAG_SHIFT) + new_pt.x -= MAP_WIDTH << MAG_SHIFT; + new_pt.y = pSolarSysState->MenuState.first_item.y + dy; + + pSolarSysState->MenuState.first_item = new_pt; + + { + DWORD TimeIn; + + TimeIn = SleepTask (MAKE_DWORD ( + pSolarSysState->MenuState.flash_rect1.corner.x, + pSolarSysState->MenuState.flash_rect1.corner.y + )) + 2; + pSolarSysState->MenuState.flash_rect1.corner.x = LOWORD (TimeIn); + pSolarSysState->MenuState.flash_rect1.corner.y = HIWORD (TimeIn); + } + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + + BatchGraphics (); + + { + STAMP s; + + ClearDrawable (); + + s.origin.x = -new_pt.x + (SURFACE_WIDTH >> 1); + s.origin.y = -new_pt.y + (SURFACE_HEIGHT >> 1); + s.frame = pSolarSysState->TopoFrame; + SetGraphicScale (1 << (MAG_SHIFT + 8)); + DrawStamp (&s); + SetGraphicScale (0); + } + + BuildObjectList (); + + DrawBatch (DisplayArray, DisplayLinks, 0); + + if (pMenuState->delta_item || pMenuState->CurState < 3) + { + BYTE damage_index; + + lander_s.origin.x = SURFACE_WIDTH >> 1; + lander_s.frame = LanderFrame[0]; + if (CountDown < 0) + lander_s.origin.y = SURFACE_HEIGHT >> 1; + else + lander_s.origin.y = lander_pos[CountDown]; + + if (CountDown >= 0) + { + shadow_s.origin.x = lander_s.origin.y + (SURFACE_WIDTH >> 1) - (SURFACE_HEIGHT >> 1);//2; + shadow_s.origin.y = lander_s.origin.y; + shadow_s.frame = lander_s.frame; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledStamp (&shadow_s); + } + + if ((damage_index = LOBYTE (pMenuState->delta_item)) == 0) + DrawStamp (&lander_s); + else + { + --pMenuState->delta_item; + if (!(damage_index & SHIELD_BIT)) + { + SetContextForeGroundColor (DamageColorCycle (0, damage_index)); + DrawFilledStamp (&lander_s); + } + else + { + if ((damage_index = + (BYTE)((damage_index & ~SHIELD_BIT) - 1)) == 0) + pMenuState->delta_item &= ~SHIELD_BIT; + else + { + shield_s.origin = lander_s.origin; + shield_s.frame = SetEquFrameIndex ( + LanderFrame[4], + lander_s.frame + ); + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F) | 0x8000, damage_index) + ); + DrawFilledStamp (&shield_s); + } + DrawStamp (&lander_s); + } + } + } + + if (CountDown < 0 + && HIBYTE (pMenuState->delta_item) + && GetPredLink (DisplayLinks) != END_OF_LIST) + CheckObjectCollision (END_OF_LIST); + + { + PPLANETSIDE_DESC pPSD; + + pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; + if (pPSD->NumFrames) + { + --pPSD->NumFrames; + SetContextForeGroundColor (pPSD->ColorCycle[pPSD->NumFrames >> 1]); + + pPSD->MineralText[0].baseline.x -= dx; + pPSD->MineralText[0].baseline.y -= dy; + DrawText (&pPSD->MineralText[0]); + pPSD->MineralText[1].baseline.x = pPSD->MineralText[0].baseline.x; + pPSD->MineralText[1].baseline.y = pPSD->MineralText[0].baseline.y + 7; + DrawText (&pPSD->MineralText[1]); + pPSD->MineralText[2].baseline.x = pPSD->MineralText[1].baseline.x; + pPSD->MineralText[2].baseline.y = pPSD->MineralText[1].baseline.y + 7; + DrawText (&pPSD->MineralText[2]); + } + } + + pMenuState->flash_rect0.corner.x = new_pt.x >> MAG_SHIFT; + pMenuState->flash_rect0.corner.y = new_pt.y >> MAG_SHIFT; + RepairScan (); + + if (lander_flags & KILL_CREW) + DeltaLanderCrew (-1, LIGHTNING_DISASTER); + + UnbatchGraphics (); + + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); +} + +static void +AnimateLaunch (FRAME farray, BOOLEAN ShowPlanetSide) +{ + RECT r; + STAMP s; + COUNT num_frames; + DWORD Time; + + Time = GetTimeCounter (); + + s.origin.x = s.origin.y = 0; + s.frame = DecFrameIndex (farray); + + num_frames = GetFrameCount (s.frame); + do + { + GetFrameRect (s.frame, &r); + s.frame = IncFrameIndex (s.frame); + RepairBackRect (&r); + DrawStamp (&s); + + ClearSemaphore (&GraphicsSem); + +#if 0 + if (ShowPlanetSide) + { + do + { + ScrollPlanetSide (0, 0, 0); + } while (GetTimeCounter () < Time + (ONE_SECOND / 22)); + } +#else + (void) ShowPlanetSide; /* Satisfying compiler (unused parameter) */ +#endif + + Time = SleepTask (Time + (ONE_SECOND / 22)); + + SetSemaphore (&GraphicsSem); + } while (--num_frames); + + GetFrameRect (s.frame, &r); + RepairBackRect (&r); +} + +static void +InitPlanetSide (void) +{ + SIZE num_crew; + POINT pt; + STAMP s; + CONTEXT OldContext; + DWORD Time; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (RadarContext); + ClearSemaphore (&GraphicsSem); + + Time = GetTimeCounter (); + + s.origin.x = 0; + s.origin.y = 0; + s.frame = SetAbsFrameIndex (LanderFrame[0], + (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 1); + + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + Time = SleepTask (Time + (ONE_SECOND / 15)); + + for (num_crew = 0; num_crew < (NUM_CREW_COLS * NUM_CREW_ROWS) + && GLOBAL_SIS (CrewEnlisted); ++num_crew) + { + Time = SleepTask (Time + 4); + SetSemaphore (&GraphicsSem); + DeltaSISGauges (-1, 0, 0); + DeltaLanderCrew (1, 0); + ClearSemaphore (&GraphicsSem); + } + + Time = SleepTask (Time + (ONE_SECOND / 15)); + + if (GET_GAME_STATE (IMPROVED_LANDER_SHOT)) + s.frame = SetAbsFrameIndex (s.frame, 59); + else + s.frame = SetAbsFrameIndex (s.frame, + (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 2); + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + Time = SleepTask (Time + (ONE_SECOND / 15)); + + if (GET_GAME_STATE (IMPROVED_LANDER_SPEED)) + s.frame = SetAbsFrameIndex (s.frame, 57); + else + { + s.frame = SetAbsFrameIndex (s.frame, + (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 3); + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + Time = SleepTask (Time + (ONE_SECOND / 15)); + + s.frame = IncFrameIndex (s.frame); + } + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) + { + Time = SleepTask (Time + (ONE_SECOND / 15)); + + s.frame = SetAbsFrameIndex (s.frame, 58); + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + } + SleepTask (Time + (ONE_SECOND / 15)); + + SetSemaphore (&GraphicsSem); + PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_DEPARTS), + GAME_SOUND_PRIORITY + 1); + SetContext (SpaceContext); + AnimateLaunch (LanderFrame[5], FALSE); + +#define RANDOM_MISS 64 + pt.x = pSolarSysState->MenuState.first_item.x + - RANDOM_MISS + (SIZE)(LOWORD (Random ()) % (RANDOM_MISS << 1)); + if (pt.x < 0) + pt.x += (MAP_WIDTH << MAG_SHIFT); + else if (pt.x >= (MAP_WIDTH << MAG_SHIFT)) + pt.x -= (MAP_WIDTH << MAG_SHIFT); + + pt.y = pSolarSysState->MenuState.first_item.y + - RANDOM_MISS + (SIZE)(LOWORD (Random ()) % (RANDOM_MISS << 1)); + if (pt.y < 0) + pt.y = 0; + else if (pt.y >= (MAP_HEIGHT << MAG_SHIFT)) + pt.y = (MAP_HEIGHT << MAG_SHIFT) - 1; + + pSolarSysState->MenuState.first_item = pt; + pt.x >>= MAG_SHIFT; + pt.y >>= MAG_SHIFT; + +#ifdef NEVER + SetContext (ScanContext); + s.origin = pMenuState->flash_rect0.corner; + s.origin.x -= (FLASH_WIDTH >> 1); + s.origin.y -= (FLASH_HEIGHT >> 1); + s.frame = pMenuState->flash_frame0; + DrawStamp (&s); +#endif /* NEVER */ + + pMenuState->flash_rect0.corner = pt; + SetContext (SpaceContext); + SetContextFont (TinyFont); + + pt.x = pSolarSysState->MenuState.first_item.x - (SURFACE_WIDTH >> 1); // was SPACE_ + if (pt.x < 0) + pt.x += MAP_WIDTH << MAG_SHIFT; + pt.y = pSolarSysState->MenuState.first_item.y - (SURFACE_HEIGHT >> 1); // was SPACE_ + + { + RECT r; + + r.corner.x = SURFACE_X; + r.corner.y = SURFACE_Y; + r.extent.width = SURFACE_WIDTH; + r.extent.height = SURFACE_HEIGHT; + SetContextClipRect (&r); + SetContextClipping (TRUE); + + BatchGraphics (); + + { + STAMP s; + + ClearDrawable (); + + s.origin.x = -pt.x + (SURFACE_WIDTH >> 1); + s.origin.y = -pt.y + (SURFACE_HEIGHT >> 1); + s.frame = pSolarSysState->TopoFrame; + SetGraphicScale (1 << (MAG_SHIFT + 8)); + DrawStamp (&s); + SetGraphicScale (0); + } + + ScreenTransition (3, &r); + UnbatchGraphics (); + + LoadIntoExtraScreen (&r); + } + + SetContext (OldContext); + + ClearSISRect (CLEAR_SIS_RADAR); + + ClearSemaphore (&GraphicsSem); + + SET_GAME_STATE (PLANETARY_LANDING, 1); +} + +static BOOLEAN +DoPlanetSide (INPUT_STATE InputState, PMENU_STATE pMS) +{ +#define NUM_LANDING_DELTAS 10 +#define SHUTTLE_TURN_WAIT 2 +#define SHUTTLE_FIRE_WAIT 15 + SIZE index; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + pMS->MenuRepeatDelay = 0; + if (!pMS->Initialized) + { + pMS->Initialized = TRUE; + pMS->CurState = 0; + + index = FACING_TO_ANGLE (GetFrameIndex (LanderFrame[0])); + if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) + SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (index, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM, + SINE (index, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM + ); + else + SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (index, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM, + SINE (index, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM + ); +#ifdef FAST_FAST +SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (index, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM, + SINE (index, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM + ); +#endif + } + else if (pMS->delta_item == 0 + || (HIBYTE (pMS->delta_item) && ((InputState & (DEVICE_BUTTON3 | DEVICE_LEFTSHIFT)) + || ( + (PPLANETSIDE_DESC)pMenuState->ModuleFrame + )->InTransit))) + { + if (pMS->delta_item || pMS->CurState > EXPLOSION_LIFE + 60) + return (FALSE); + else + { + if (pMS->CurState > EXPLOSION_LIFE) + ++pMS->CurState; + else if (pMS->CurState == 0) + { + HELEMENT hExplosionElement; + + ++pMS->CurState; + hExplosionElement = AllocElement (); + if (hExplosionElement) + { + ELEMENTPTR ExplosionElementPtr; + + LockElement (hExplosionElement, &ExplosionElementPtr); + + ExplosionElementPtr->mass_points = DEATH_EXPLOSION; + ExplosionElementPtr->state_flags = FINITE_LIFE | GOOD_GUY; + ExplosionElementPtr->next.location = + pSolarSysState->MenuState.first_item; + ExplosionElementPtr->preprocess_func = object_animation; + ExplosionElementPtr->turn_wait = MAKE_BYTE (2, 2); + ExplosionElementPtr->life_span = + EXPLOSION_LIFE + * (LONIBBLE (ExplosionElementPtr->turn_wait) + 1); + + SetPrimType (&DisplayArray[ExplosionElementPtr->PrimIndex], STAMP_PRIM); + DisplayArray[ExplosionElementPtr->PrimIndex].Object.Stamp.frame = + SetAbsFrameIndex ( + LanderFrame[0], 46 + ); + + UnlockElement (hExplosionElement); + + InsertElement (hExplosionElement, GetHeadElement ()); + + PlaySound (SetAbsSoundIndex ( + LanderSounds, LANDER_DESTROYED + ), GAME_SOUND_PRIORITY + 1); + } + } + + ScrollPlanetSide (0, 0, -1); + } + } + else + { + SIZE dx, dy; + + if (HIBYTE (pMS->delta_item) == 0) + dx = dy = 0; + else + { + index = GetFrameIndex (LanderFrame[0]); + if (LONIBBLE (pMS->CurState)) + pMS->CurState -= MAKE_BYTE (1, 0); + else if ((dx = GetInputXComponent (InputState))) + { + if (dx < 0) + --index; + else + ++index; + + index = NORMALIZE_FACING (index); + LanderFrame[0] = + SetAbsFrameIndex (LanderFrame[0], index); + + dx = FACING_TO_ANGLE (index); + if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) + SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (dx, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM, + SINE (dx, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM + ); + else + SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (dx, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM, + SINE (dx, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM + ); +#ifdef FAST_FAST +SetVelocityComponents ( + &GLOBAL (velocity), + COSINE (dx, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM, + SINE (dx, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM + ); +#endif + + pMS->CurState = MAKE_BYTE ( + SHUTTLE_TURN_WAIT, HINIBBLE (pMS->CurState) + ); + } + + if (!(InputState & DEVICE_BUTTON1) + && GetInputYComponent (InputState) >= 0) + dx = dy = 0; + else + GetNextVelocityComponents ( + &GLOBAL (velocity), &dx, &dy, 1 + ); + + if (HINIBBLE (pMS->CurState)) + pMS->CurState -= MAKE_BYTE (0, 1); + else if (InputState & (DEVICE_BUTTON2 | DEVICE_RIGHTSHIFT)) + { + HELEMENT hWeaponElement; + + hWeaponElement = AllocElement (); + if (hWeaponElement) + { + SIZE wdx, wdy; + ELEMENTPTR WeaponElementPtr; + + LockElement (hWeaponElement, &WeaponElementPtr); + + WeaponElementPtr->mass_points = 1; + WeaponElementPtr->life_span = 12; + WeaponElementPtr->state_flags = FINITE_LIFE | GOOD_GUY; + WeaponElementPtr->next.location = + pSolarSysState->MenuState.first_item; + WeaponElementPtr->current.location.x = + WeaponElementPtr->next.location.x >> MAG_SHIFT; + WeaponElementPtr->current.location.y = + WeaponElementPtr->next.location.y >> MAG_SHIFT; + + SetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex], STAMP_PRIM); + DisplayArray[WeaponElementPtr->PrimIndex].Object.Stamp.frame = + SetAbsFrameIndex ( + LanderFrame[0], + index + ANGLE_TO_FACING (FULL_CIRCLE) + ); + + if (!(InputState & DEVICE_BUTTON1) + && GetInputYComponent (InputState) >= 0) + wdx = wdy = 0; + else + GetCurrentVelocityComponents ( + &GLOBAL (velocity), &wdx, &wdy + ); + index = FACING_TO_ANGLE (index); + SetVelocityComponents ( + &WeaponElementPtr->velocity, + COSINE (index, WORLD_TO_VELOCITY (2 * 3)) + wdx, + SINE (index, WORLD_TO_VELOCITY (2 * 3)) + wdy + ); + + UnlockElement (hWeaponElement); + + InsertElement (hWeaponElement, GetHeadElement ()); + + PlaySound (SetAbsSoundIndex ( + LanderSounds, LANDER_SHOOTS + ), GAME_SOUND_PRIORITY); + + wdx = SHUTTLE_FIRE_WAIT; + if (GET_GAME_STATE (IMPROVED_LANDER_SHOT)) + wdx >>= 1; + pMS->CurState = MAKE_BYTE (LONIBBLE (pMS->CurState), wdx); + } + } + } + + ScrollPlanetSide (dx, dy, -1); + } + + return (TRUE); +} + +void +FreeLanderData (void) +{ + if (LanderFrame[0]) + { + COUNT i; + + for (i = 0; i < NUM_ORBIT_THEMES; ++i) + { + DestroyMusic (OrbitMusic[i]); + OrbitMusic[i] = 0; + } + DestroySound (ReleaseSound (LanderSounds)); + LanderSounds = 0; + + for (i = 0; i < sizeof (LanderFrame) + / sizeof (LanderFrame[0]); ++i) + { + DestroyDrawable (ReleaseDrawable (LanderFrame[i])); + LanderFrame[i] = 0; + } + } +} + +void +LoadLanderData (void) +{ + if (LanderFrame[0] == 0) + { + LanderFrame[0] = + CaptureDrawable ( + LoadGraphic (LANDER_MASK_PMAP_ANIM) + ); + LanderFrame[1] = + CaptureDrawable ( + LoadGraphic (QUAKE_MASK_PMAP_ANIM) + ); + LanderFrame[2] = + CaptureDrawable ( + LoadGraphic (LIGHTNING_MASK_ANIM) + ); + LanderFrame[3] = + CaptureDrawable ( + LoadGraphic (LAVA_MASK_PMAP_ANIM) + ); + LanderFrame[4] = + CaptureDrawable ( + LoadGraphic (LANDER_SHIELD_MASK_ANIM) + ); + LanderFrame[5] = + CaptureDrawable ( + LoadGraphic (LANDER_LAUNCH_MASK_PMAP_ANIM) + ); + LanderFrame[6] = + CaptureDrawable ( + LoadGraphic (LANDER_RETURN_MASK_PMAP_ANIM) + ); + LanderSounds = CaptureSound (LoadSound (LANDER_SOUNDS)); + + LanderFrame[7] = + CaptureDrawable ( + LoadGraphic (ORBIT_VIEW_ANIM) + ); + + { + COUNT i; + RES_TYPE rt; + RES_INSTANCE ri; + RES_PACKAGE rp; + + rt = GET_TYPE (ORBIT1_MUSIC); + ri = GET_INSTANCE (ORBIT1_MUSIC); + rp = GET_PACKAGE (ORBIT1_MUSIC); + for (i = 0; i < NUM_ORBIT_THEMES; ++i, ++ri) + OrbitMusic[i] = LoadMusicInstance (MAKE_RESOURCE (rp, rt, ri)); + } + } +} + +void +SetPlanetMusic (BYTE planet_type) +{ + LanderMusic = OrbitMusic[planet_type % NUM_ORBIT_THEMES]; +} + +static void +ReturnToOrbit (PRECT pRect) +{ + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + SetContextClipRect (pRect); + + BatchGraphics (); + DrawStarBackGround (TRUE); + SetContext (ScanContext); + DrawPlanet (0, 0, 0, 0); + DrawScannedObjects (TRUE); + ScreenTransition (3, pRect); + UnbatchGraphics (); + + LoadIntoExtraScreen (pRect); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + + SetPlanetTilt (0); +} + +void +PlanetSide (PMENU_STATE pMS) +{ + SIZE index; + DWORD TimeIn; + PLANETSIDE_DESC PSD; + BYTE TectonicsChanceTab[] = {0*3, 0*3, 1*3, 2*3, 4*3, 8*3, 16*3, 32*3}; + BYTE WeatherChanceTab[] = {0*3, 0*3, 1*3, 2*3, 3*3, 6*3, 12*3, 24*3}; + BYTE FireChanceTab[] = {0*3, 0*3, 1*3, 2*3, 4*3, 12*3, 24*3, 48*3}; + + memset ((PPLANETSIDE_DESC)&PSD, 0, sizeof (PSD)); + PSD.InTransit = TRUE; + PSD.OldMenuSounds = MenuSounds; + MenuSounds = 0; + + PSD.TectonicsChance = + TectonicsChanceTab[pSolarSysState->SysInfo.PlanetInfo.Tectonics]; + PSD.WeatherChance = + WeatherChanceTab[pSolarSysState->SysInfo.PlanetInfo.Weather]; + index = pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature; + if (index < 50) + PSD.FireChance = FireChanceTab[0]; + else if (index < 100) + PSD.FireChance = FireChanceTab[1]; + else if (index < 150) + PSD.FireChance = FireChanceTab[2]; + else if (index < 250) + PSD.FireChance = FireChanceTab[3]; + else if (index < 350) + PSD.FireChance = FireChanceTab[4]; + else if (index < 550) + PSD.FireChance = FireChanceTab[5]; + else if (index < 800) + PSD.FireChance = FireChanceTab[6]; + else + PSD.FireChance = FireChanceTab[7]; + + PSD.ElementLevel = GetSBayCapacity (NULL_PTR) + - GLOBAL_SIS (TotalElementMass); + PSD.MaxElementLevel = MAX_SCROUNGED; + if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) + PSD.MaxElementLevel <<= 1; + if (PSD.ElementLevel < PSD.MaxElementLevel) + PSD.MaxElementLevel = PSD.ElementLevel; + PSD.ElementLevel = 0; + + PSD.MineralText[0].align = ALIGN_CENTER; + PSD.MineralText[0].pStr = PSD.AmountBuf; + PSD.MineralText[1] = PSD.MineralText[0]; + PSD.MineralText[2] = PSD.MineralText[1]; + + PSD.ColorCycle[0] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F); + PSD.ColorCycle[1] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7D); + PSD.ColorCycle[2] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B); + PSD.ColorCycle[3] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71); + for (index = 4; index < (NUM_TEXT_FRAMES >> 1) - 4; ++index) + PSD.ColorCycle[index] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); + PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 4] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71); + PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 3] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B); + PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 2] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x000), 0x7D); + PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 1] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F); + pMS->ModuleFrame = (FRAME)&PSD; + + index = NORMALIZE_FACING ((COUNT)Random ()); + LanderFrame[0] = SetAbsFrameIndex ( + LanderFrame[0], index + ); + pMS->delta_item = 0; + pSolarSysState->MenuState.Initialized += 4; + + InitPlanetSide (); + + TimeIn = GetTimeCounter (); + for (index = 0; index <= NUM_LANDING_DELTAS; ++index) + { + if (index == 0) + TimeIn += ONE_SECOND; + else + TimeIn += 2; + + do + { + ScrollPlanetSide (0, 0, index); + } while (GetTimeCounter () < TimeIn); + } + PSD.InTransit = FALSE; + + TimeIn += 2; + pSolarSysState->MenuState.flash_rect1.corner.x = LOWORD (TimeIn); + pSolarSysState->MenuState.flash_rect1.corner.y = HIWORD (TimeIn); + + pMS->Initialized = FALSE; + pMS->InputFunc = DoPlanetSide; + DoInput ((PVOID)pMS); + + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + SIZE crew_left; + RECT r; + //CONTEXT OldContext; + + crew_left = HIBYTE (pMS->delta_item); + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + if (crew_left == 0) + { +#ifdef NEVER + ScrollPlanetSide (0, 0, 0); +#endif /* NEVER */ + + --GLOBAL_SIS (NumLanders); + SetSemaphore (&GraphicsSem); + DrawLanders (); + ClearSemaphore (&GraphicsSem); + + ReturnToOrbit (&r); + } + else + { + PSD.InTransit = TRUE; + PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_RETURNS), + GAME_SOUND_PRIORITY + 1); + + TimeIn = GetTimeCounter (); + for (index = NUM_LANDING_DELTAS; index >= 0; --index) + { + if (index == 0) + TimeIn += (ONE_SECOND >> 1); + else + TimeIn += 2; + + do + { + ScrollPlanetSide (0, 0, index); + } while (GetTimeCounter () < TimeIn); + } + + ReturnToOrbit (&r); + + pSolarSysState->MenuState.Initialized -= 4; + SleepTask (GetTimeCounter () + 1); + pSolarSysState->MenuState.Initialized += 4; + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + AnimateLaunch (LanderFrame[6], TRUE); + DeltaSISGauges (crew_left, 0, 0); + + if (PSD.ElementLevel) + { + for (index = 0; index < NUM_ELEMENT_CATEGORIES; ++index) + { + GLOBAL_SIS (ElementAmounts[index]) += + PSD.ElementAmounts[index]; + GLOBAL_SIS (TotalElementMass) += + PSD.ElementAmounts[index]; + } + DrawStorageBays (FALSE); + } + + ClearSemaphore (&GraphicsSem); + + GLOBAL_SIS (TotalBioMass) += PSD.BiologicalLevel; + } + } + + pMS->ModuleFrame = 0; + + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = _GetSuccLink (ElementPtr); + if (ElementPtr->state_flags & FINITE_LIFE) + { + UnlockElement (hElement); + + RemoveElement (hElement); + FreeElement (hElement); + + continue; + } + UnlockElement (hElement); + } + } + + ZeroVelocityComponents (&GLOBAL (velocity)); + MenuSounds = PSD.OldMenuSounds; + + pSolarSysState->MenuState.Initialized -= 4; +} + +void +InitLander (BYTE LanderFlags) +{ + RECT r; + + SetSemaphore (&GraphicsSem); + + SetContext (RadarContext); + + BatchGraphics (); + + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = RADAR_WIDTH; + r.extent.height = RADAR_HEIGHT; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + + if (GLOBAL_SIS (NumLanders) || LanderFlags) + { + BYTE ShieldFlags, capacity_shift; + COUNT free_space; + STAMP s; + + s.origin.x = 0; /* set up powered-down lander */ + s.origin.y = 0; + s.frame = SetAbsFrameIndex (LanderFrame[0], + ANGLE_TO_FACING (FULL_CIRCLE) << 1); + DrawStamp (&s); + if (LanderFlags == 0) + { + ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); + capacity_shift = GET_GAME_STATE (IMPROVED_LANDER_CARGO); + } + else + { + ShieldFlags = (unsigned char)(LanderFlags & + ((1 << EARTHQUAKE_DISASTER) + | (1 << BIOLOGICAL_DISASTER) + | (1 << LIGHTNING_DISASTER) + | (1 << LAVASPOT_DISASTER))); + s.frame = IncFrameIndex (s.frame); + DrawStamp (&s); + if (LanderFlags & (1 << (4 + 0))) + s.frame = SetAbsFrameIndex (s.frame, 57); + else + { + s.frame = SetAbsFrameIndex (s.frame, + (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 3); + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + } + DrawStamp (&s); + if (!(LanderFlags & (1 << (4 + 1)))) + capacity_shift = 0; + else + { + capacity_shift = 1; + s.frame = SetAbsFrameIndex (s.frame, 58); + DrawStamp (&s); + } + if (LanderFlags & (1 << (4 + 2))) + s.frame = SetAbsFrameIndex (s.frame, 57); + else + s.frame = SetAbsFrameIndex (s.frame, + (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 2); + DrawStamp (&s); + } + + if ((int)(free_space = GetSBayCapacity (NULL_PTR) + - GLOBAL_SIS (TotalElementMass)) < + (int)(MAX_SCROUNGED << capacity_shift)) + { + r.corner.x = 1; + r.extent.width = 4; + r.extent.height = MAX_SCROUNGED + - (free_space >> capacity_shift) + 1; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + } + + s.frame = SetAbsFrameIndex (s.frame, 37); + if (ShieldFlags & (1 << EARTHQUAKE_DISASTER)) + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << BIOLOGICAL_DISASTER)) + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << LIGHTNING_DISASTER)) + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + if (ShieldFlags & (1 << LAVASPOT_DISASTER)) + DrawStamp (&s); + } + + UnbatchGraphics (); + + ClearSemaphore (&GraphicsSem); +} diff --git a/sc2/src/sc2code/planets/lander.h b/sc2/src/sc2code/planets/lander.h new file mode 100644 index 000000000..286b0595b --- /dev/null +++ b/sc2/src/sc2code/planets/lander.h @@ -0,0 +1,49 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LANDER_H +#define _LANDER_H + +#define NUM_TEXT_FRAMES 32 + +typedef struct +{ + BOOLEAN InTransit; + + SOUND OldMenuSounds; + + COUNT ElementLevel, MaxElementLevel, + BiologicalLevel; + COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES]; + + COUNT NumFrames; + UNICODE AmountBuf[10]; + TEXT MineralText[3]; + + COLOR ColorCycle[NUM_TEXT_FRAMES >> 1]; + + BYTE TectonicsChance, WeatherChance, FireChance; +} PLANETSIDE_DESC; +typedef PLANETSIDE_DESC *PPLANETSIDE_DESC; + +extern CONTEXT ScanContext; + +extern void DoDiscoveryReport (SOUND ReadOutSounds); + +#endif /* _LANDER_H */ + diff --git a/sc2/src/sc2code/planets/lifeform.h b/sc2/src/sc2code/planets/lifeform.h new file mode 100644 index 000000000..b711a8706 --- /dev/null +++ b/sc2/src/sc2code/planets/lifeform.h @@ -0,0 +1,65 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LIFEFORM_H +#define _LIFEFORM_H + +#define BEHAVIOR_HUNT (0 << 0) +#define BEHAVIOR_FLEE (1 << 0) +#define BEHAVIOR_UNPREDICTABLE (2 << 0) + +#define BEHAVIOR_MASK 0x03 +#define BEHAVIOR_SHIFT 0 + +#define AWARENESS_LOW (0 << 2) +#define AWARENESS_MEDIUM (1 << 2) +#define AWARENESS_HIGH (2 << 2) + +#define AWARENESS_MASK 0x0C +#define AWARENESS_SHIFT (BEHAVIOR_SHIFT + 2) + +#define SPEED_MOTIONLESS (0 << 4) +#define SPEED_SLOW (1 << 4) +#define SPEED_MEDIUM (2 << 4) +#define SPEED_FAST (3 << 4) + +#define SPEED_MASK 0x30 +#define SPEED_SHIFT (AWARENESS_SHIFT + 2) + +#define DANGER_HARMLESS (0 << 6) +#define DANGER_WEAK (1 << 6) +#define DANGER_NORMAL (2 << 6) +#define DANGER_MONSTROUS (3 << 6) + +#define DANGER_MASK 0xC0 +#define DANGER_SHIFT (SPEED_SHIFT + 2) + +#define NUM_CREATURE_TYPES 23 +#define MAX_LIFE_VARIATION 3 + +#define CREATURE_AWARE (BYTE)(1 << 7) + +typedef struct +{ + BYTE Attributes, ValueAndHitPoints; +} LIFEFORM_DESC; + +extern const LIFEFORM_DESC CreatureData[]; + +#endif /* _LIFEFORM_H */ + diff --git a/sc2/src/sc2code/planets/mapcel.s b/sc2/src/sc2code/planets/mapcel.s new file mode 100644 index 000000000..aeed2f16c --- /dev/null +++ b/sc2/src/sc2code/planets/mapcel.s @@ -0,0 +1,139 @@ +; generated by Norcroft ARM C vsn 4.41 (Advanced RISC Machines) [Feb 17 1993] + + AREA |C$$code|, CODE, READONLY +|x$codeseg| + + IMPORT |__rt_sdiv| + EXPORT myMapCel +myMapCel + MOV ip,sp + STMDB sp!,{a1-a4,v1-v6,r10,fp,ip,lr} + MOV fp,ip + + LDMIA a2,{v1-v6,r10,ip} ; load pts + + MOV a2,#&8000 + ADD a3,v1,a2 ; a3 = p0.x + (1 << 15) + ADD a4,v2,a2 ; a4 = p0.y + (1 << 15) + ADD a2,a1,#&10 + STMIA a2,{a3,a4} ; store ccb_XPos, ccb_YPos + + SUB v3,v3,v1 + MOV v3,v3,LSL #4 ; v3 = (p1.x - p0.x) << 4 + SUB v4,v4,v2 + MOV v4,v4,LSL #4 ; v4 = (p1.y - p0.y) << 4 + + SUB v1,r10,v1 ; v1 = p3.x - p0.x + SUB v2,ip,v2 ; v2 = p3.y - p0.y + + MOV v5,v5,LSL #4 + SUB v5,v5,v3 + SUB v5,v5,r10,LSL #4 ; v5 = (p2.x << 4) - (p1.x - p0.x) - (p3.x << 4) + + MOV v6,v6,LSL #4 + SUB v6,v6,v4 + SUB v6,v6,ip,LSL #4 ; v6 = (p2.y << 4) - (p1.y - p0.y) - (p3.y << 4) + + ADD ip,a1,#&3c + LDMIA ip,{a2,r10} + ADD r10,a2,r10,LSL #16 ; r10 HI -- height, LO -- width + + STR a1,[sp] + SUB sp,sp,#4 ; grow stack + + MOV a1,v3 + MOV a2,v4 + MOV v3,v1 + MOV v4,v2 + MOV v1,a1 + MOV v2,a2 + + MOVS a2,v1 + MOVNE a1,r10,LSL #16 + MOVNE a1,a1,LSR #16 + BLNE |__rt_sdiv| + MOVNE v1,a1 + + MOVS a2,v2 + MOVNE a1,r10,LSL #16 + MOVNE a1,a1,LSR #16 + BLNE |__rt_sdiv| + MOVNE v2,a1 + + MOVS a2,v3 + MOVNE a1,r10,LSR #16 + BLNE |__rt_sdiv| + MOVNE v3,a1 + + MOVS a2,v4 + MOVNE a1,r10,LSR #16 + BLNE |__rt_sdiv| + MOVNE v4,a1 + + MOVS a2,v5 + MOVNE a3,r10,LSL #16 + MOVNE a3,a3,LSR #16 + MOVNE a4,r10,LSR #16 + MULNE a1,a3,a4 + BLNE |__rt_sdiv| + MOVNE v5,a1 + + MOVS a2,v6 + MOVNE a3,r10,LSL #16 + MOVNE a3,a3,LSR #16 + MOVNE a4,r10,LSR #16 + MULNE a1,a3,a4 + BLNE |__rt_sdiv| + MOVNE v6,a1 + +; CMP v1,#0 +; CMPEQ v2,#0 +; MOVNE a2,#&80000 +; MOVNE a1,r10,LSL #16 +; MOVNE a1,a1,LSR #16 +; BLNE |__rt_sdiv| +; CMPNE v1,#0 +; SUBLT v1,v1,a1 +; ADDGT v1,v1,a1 +; CMP v2,#0 +; SUBLT v2,v2,a1 +; ADDGT v2,v2,a1 + +; CMP v3,#0 +; CMPEQ v4,#0 +; MOVNE a2,#&8000 +; MOVNE a1,r10,LSR #16 +; BLNE |__rt_sdiv| +; CMPNE v3,#0 +; SUBLT v3,v3,a1 +; ADDGT v3,v3,a1 +; CMP v4,#0 +; SUBLT v4,v4,a1 +; ADDGT v4,v4,a1 + +; CMP v5,#0 +; CMPEQ v6,#0 +; MOVNE a2,#&80000 +; MOVNE a3,r10,LSL #16 +; MOVNE a3,a3,LSR #16 +; MOVNE a4,r10,LSR #16 +; MULNE a1,a3,a4 +; BLNE |__rt_sdiv| +; CMPNE v5,#0 +; SUBLT v5,v5,a1 +; ADDGT v5,v5,a1 +; CMP v6,#0 +; SUBLT v6,v6,a1 +; ADDGT v6,v6,a1 + + LDR a1,[sp,#4] + ADD a1,a1,#&18 + STMIA a1,{v1-v6} + + LDMDB fp,{a1-a4,v1-v6,r10,fp,sp,pc} + + AREA |C$$data|,DATA + +|x$dataseg| + + END diff --git a/sc2/src/sc2code/planets/orbits.c b/sc2/src/sc2code/planets/orbits.c new file mode 100644 index 000000000..de9db15a1 --- /dev/null +++ b/sc2/src/sc2code/planets/orbits.c @@ -0,0 +1,624 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +enum +{ + PLANET_NEVER = 0, + PLANET_RARE = 15, + PLANET_FEW = 63, + PLANET_COMMON = 127, + PLANET_ALWAYS = 255 +}; + +static BYTE +BlueDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_ALWAYS, /* OOLITE_WORLD */ + PLANET_ALWAYS, /* YTTRIC_WORLD */ + PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ + PLANET_ALWAYS, /* LANTHANIDE_WORLD */ + PLANET_ALWAYS, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_ALWAYS, /* METAL_WORLD */ + PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ + PLANET_ALWAYS, /* OPALESCENT_WORLD */ + PLANET_ALWAYS, /* CYANIC_WORLD */ + PLANET_ALWAYS, /* ACID_WORLD */ + PLANET_ALWAYS, /* ALKALI_WORLD */ + PLANET_ALWAYS, /* HALIDE_WORLD */ + PLANET_ALWAYS, /* GREEN_WORLD */ + PLANET_ALWAYS, /* COPPER_WORLD */ + PLANET_ALWAYS, /* CARBIDE_WORLD */ + PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ + PLANET_ALWAYS, /* NOBLE_WORLD */ + PLANET_ALWAYS, /* AZURE_WORLD */ + PLANET_NEVER, /* CHONDRITE_WORLD */ + PLANET_NEVER, /* PURPLE_WORLD */ + PLANET_NEVER, /* SUPER_DENSE_WORLD */ + PLANET_NEVER, /* PELLUCID_WORLD */ + PLANET_NEVER, /* DUST_WORLD */ + PLANET_NEVER, /* CRIMSON_WORLD */ + PLANET_NEVER, /* CIMMERIAN_WORLD */ + PLANET_NEVER, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_ALWAYS, /* AURIC_WORLD */ + + PLANET_ALWAYS, /* FLUORESCENT_WORLD */ + PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ + PLANET_ALWAYS, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_ALWAYS, /* SAPPHIRE_WORLD */ + PLANET_ALWAYS, /* ORGANIC_WORLD */ + PLANET_ALWAYS, /* XENOLITHIC_WORLD */ + PLANET_ALWAYS, /* REDUX_WORLD */ + PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ + PLANET_NEVER, /* EMERALD_WORLD */ + PLANET_ALWAYS, /* CHLORINE_WORLD */ + PLANET_ALWAYS, /* MAGNETIC_WORLD */ + PLANET_ALWAYS, /* WATER_WORLD */ + PLANET_ALWAYS, /* TELLURIC_WORLD */ + PLANET_NEVER, /* HYDROCARBON_WORLD */ + PLANET_NEVER, /* IODINE_WORLD */ + PLANET_NEVER, /* VINYLOGOUS_WORLD */ + PLANET_NEVER, /* RUBY_WORLD */ + PLANET_NEVER, /* MAGMA_WORLD */ + PLANET_NEVER, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +static BYTE +GreenDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_NEVER, /* OOLITE_WORLD */ + PLANET_NEVER, /* YTTRIC_WORLD */ + PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ + PLANET_ALWAYS, /* LANTHANIDE_WORLD */ + PLANET_ALWAYS, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_ALWAYS, /* METAL_WORLD */ + PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ + PLANET_ALWAYS, /* OPALESCENT_WORLD */ + PLANET_ALWAYS, /* CYANIC_WORLD */ + PLANET_ALWAYS, /* ACID_WORLD */ + PLANET_ALWAYS, /* ALKALI_WORLD */ + PLANET_ALWAYS, /* HALIDE_WORLD */ + PLANET_ALWAYS, /* GREEN_WORLD */ + PLANET_ALWAYS, /* COPPER_WORLD */ + PLANET_ALWAYS, /* CARBIDE_WORLD */ + PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ + PLANET_ALWAYS, /* NOBLE_WORLD */ + PLANET_ALWAYS, /* AZURE_WORLD */ + PLANET_ALWAYS, /* CHONDRITE_WORLD */ + PLANET_ALWAYS, /* PURPLE_WORLD */ + PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ + PLANET_ALWAYS, /* PELLUCID_WORLD */ + PLANET_NEVER, /* DUST_WORLD */ + PLANET_NEVER, /* CRIMSON_WORLD */ + PLANET_NEVER, /* CIMMERIAN_WORLD */ + PLANET_NEVER, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_ALWAYS, /* AURIC_WORLD */ + + PLANET_ALWAYS, /* FLUORESCENT_WORLD */ + PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ + PLANET_ALWAYS, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_NEVER, /* SAPPHIRE_WORLD */ + PLANET_ALWAYS, /* ORGANIC_WORLD */ + PLANET_ALWAYS, /* XENOLITHIC_WORLD */ + PLANET_ALWAYS, /* REDUX_WORLD */ + PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ + PLANET_ALWAYS, /* EMERALD_WORLD */ + PLANET_ALWAYS, /* CHLORINE_WORLD */ + PLANET_ALWAYS, /* MAGNETIC_WORLD */ + PLANET_ALWAYS, /* WATER_WORLD */ + PLANET_ALWAYS, /* TELLURIC_WORLD */ + PLANET_ALWAYS, /* HYDROCARBON_WORLD */ + PLANET_ALWAYS, /* IODINE_WORLD */ + PLANET_NEVER, /* VINYLOGOUS_WORLD */ + PLANET_NEVER, /* RUBY_WORLD */ + PLANET_NEVER, /* MAGMA_WORLD */ + PLANET_NEVER, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +static BYTE +OrangeDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_NEVER, /* OOLITE_WORLD */ + PLANET_NEVER, /* YTTRIC_WORLD */ + PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ + PLANET_NEVER, /* LANTHANIDE_WORLD */ + PLANET_NEVER, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_NEVER, /* METAL_WORLD */ + PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ + PLANET_NEVER, /* OPALESCENT_WORLD */ + PLANET_NEVER, /* CYANIC_WORLD */ + PLANET_ALWAYS, /* ACID_WORLD */ + PLANET_ALWAYS, /* ALKALI_WORLD */ + PLANET_ALWAYS, /* HALIDE_WORLD */ + PLANET_ALWAYS, /* GREEN_WORLD */ + PLANET_ALWAYS, /* COPPER_WORLD */ + PLANET_ALWAYS, /* CARBIDE_WORLD */ + PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ + PLANET_ALWAYS, /* NOBLE_WORLD */ + PLANET_ALWAYS, /* AZURE_WORLD */ + PLANET_ALWAYS, /* CHONDRITE_WORLD */ + PLANET_ALWAYS, /* PURPLE_WORLD */ + PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ + PLANET_ALWAYS, /* PELLUCID_WORLD */ + PLANET_ALWAYS, /* DUST_WORLD */ + PLANET_ALWAYS, /* CRIMSON_WORLD */ + PLANET_ALWAYS, /* CIMMERIAN_WORLD */ + PLANET_ALWAYS, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_NEVER, /* AURIC_WORLD */ + + PLANET_NEVER, /* FLUORESCENT_WORLD */ + PLANET_NEVER, /* ULTRAVIOLET_WORLD */ + PLANET_NEVER, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_NEVER, /* SAPPHIRE_WORLD */ + PLANET_NEVER, /* ORGANIC_WORLD */ + PLANET_NEVER, /* XENOLITHIC_WORLD */ + PLANET_NEVER, /* REDUX_WORLD */ + PLANET_NEVER, /* PRIMORDIAL_WORLD */ + PLANET_NEVER, /* EMERALD_WORLD */ + PLANET_ALWAYS, /* CHLORINE_WORLD */ + PLANET_ALWAYS, /* MAGNETIC_WORLD */ + PLANET_ALWAYS, /* WATER_WORLD */ + PLANET_ALWAYS, /* TELLURIC_WORLD */ + PLANET_ALWAYS, /* HYDROCARBON_WORLD */ + PLANET_ALWAYS, /* IODINE_WORLD */ + PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ + PLANET_NEVER, /* RUBY_WORLD */ + PLANET_ALWAYS, /* MAGMA_WORLD */ + PLANET_ALWAYS, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +static BYTE +RedDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_NEVER, /* OOLITE_WORLD */ + PLANET_NEVER, /* YTTRIC_WORLD */ + PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ + PLANET_NEVER, /* LANTHANIDE_WORLD */ + PLANET_NEVER, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_ALWAYS, /* METAL_WORLD */ + PLANET_NEVER, /* RADIOACTIVE_WORLD */ + PLANET_NEVER, /* OPALESCENT_WORLD */ + PLANET_NEVER, /* CYANIC_WORLD */ + PLANET_NEVER, /* ACID_WORLD */ + PLANET_NEVER, /* ALKALI_WORLD */ + PLANET_NEVER, /* HALIDE_WORLD */ + PLANET_NEVER, /* GREEN_WORLD */ + PLANET_NEVER, /* COPPER_WORLD */ + PLANET_NEVER, /* CARBIDE_WORLD */ + PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ + PLANET_ALWAYS, /* NOBLE_WORLD */ + PLANET_ALWAYS, /* AZURE_WORLD */ + PLANET_ALWAYS, /* CHONDRITE_WORLD */ + PLANET_ALWAYS, /* PURPLE_WORLD */ + PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ + PLANET_ALWAYS, /* PELLUCID_WORLD */ + PLANET_ALWAYS, /* DUST_WORLD */ + PLANET_ALWAYS, /* CRIMSON_WORLD */ + PLANET_ALWAYS, /* CIMMERIAN_WORLD */ + PLANET_ALWAYS, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_NEVER, /* AURIC_WORLD */ + + PLANET_NEVER, /* FLUORESCENT_WORLD */ + PLANET_NEVER, /* ULTRAVIOLET_WORLD */ + PLANET_NEVER, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_NEVER, /* SAPPHIRE_WORLD */ + PLANET_NEVER, /* ORGANIC_WORLD */ + PLANET_NEVER, /* XENOLITHIC_WORLD */ + PLANET_NEVER, /* REDUX_WORLD */ + PLANET_NEVER, /* PRIMORDIAL_WORLD */ + PLANET_NEVER, /* EMERALD_WORLD */ + PLANET_NEVER, /* CHLORINE_WORLD */ + PLANET_ALWAYS, /* MAGNETIC_WORLD */ + PLANET_ALWAYS, /* WATER_WORLD */ + PLANET_ALWAYS, /* TELLURIC_WORLD */ + PLANET_ALWAYS, /* HYDROCARBON_WORLD */ + PLANET_ALWAYS, /* IODINE_WORLD */ + PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ + PLANET_ALWAYS, /* RUBY_WORLD */ + PLANET_ALWAYS, /* MAGMA_WORLD */ + PLANET_ALWAYS, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +static BYTE +WhiteDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_ALWAYS, /* OOLITE_WORLD */ + PLANET_ALWAYS, /* YTTRIC_WORLD */ + PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ + PLANET_ALWAYS, /* LANTHANIDE_WORLD */ + PLANET_ALWAYS, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_ALWAYS, /* METAL_WORLD */ + PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ + PLANET_ALWAYS, /* OPALESCENT_WORLD */ + PLANET_ALWAYS, /* CYANIC_WORLD */ + PLANET_ALWAYS, /* ACID_WORLD */ + PLANET_ALWAYS, /* ALKALI_WORLD */ + PLANET_ALWAYS, /* HALIDE_WORLD */ + PLANET_NEVER, /* GREEN_WORLD */ + PLANET_NEVER, /* COPPER_WORLD */ + PLANET_NEVER, /* CARBIDE_WORLD */ + PLANET_NEVER, /* ULTRAMARINE_WORLD */ + PLANET_NEVER, /* NOBLE_WORLD */ + PLANET_NEVER, /* AZURE_WORLD */ + PLANET_NEVER, /* CHONDRITE_WORLD */ + PLANET_NEVER, /* PURPLE_WORLD */ + PLANET_NEVER, /* SUPER_DENSE_WORLD */ + PLANET_NEVER, /* PELLUCID_WORLD */ + PLANET_NEVER, /* DUST_WORLD */ + PLANET_NEVER, /* CRIMSON_WORLD */ + PLANET_NEVER, /* CIMMERIAN_WORLD */ + PLANET_NEVER, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_ALWAYS, /* AURIC_WORLD */ + + PLANET_ALWAYS, /* FLUORESCENT_WORLD */ + PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ + PLANET_ALWAYS, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_ALWAYS, /* SAPPHIRE_WORLD */ + PLANET_ALWAYS, /* ORGANIC_WORLD */ + PLANET_ALWAYS, /* XENOLITHIC_WORLD */ + PLANET_ALWAYS, /* REDUX_WORLD */ + PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ + PLANET_ALWAYS, /* EMERALD_WORLD */ + PLANET_NEVER, /* CHLORINE_WORLD */ + PLANET_NEVER, /* MAGNETIC_WORLD */ + PLANET_NEVER, /* WATER_WORLD */ + PLANET_NEVER, /* TELLURIC_WORLD */ + PLANET_NEVER, /* HYDROCARBON_WORLD */ + PLANET_NEVER, /* IODINE_WORLD */ + PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ + PLANET_ALWAYS, /* RUBY_WORLD */ + PLANET_NEVER, /* MAGMA_WORLD */ + PLANET_NEVER, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +static BYTE +YellowDistribution (BYTE which_world) +{ + BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = + { + PLANET_NEVER, /* OOLITE_WORLD */ + PLANET_NEVER, /* YTTRIC_WORLD */ + PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ + PLANET_NEVER, /* LANTHANIDE_WORLD */ + PLANET_ALWAYS, /* TREASURE_WORLD */ + PLANET_ALWAYS, /* UREA_WORLD */ + PLANET_ALWAYS, /* METAL_WORLD */ + PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ + PLANET_ALWAYS, /* OPALESCENT_WORLD */ + PLANET_ALWAYS, /* CYANIC_WORLD */ + PLANET_ALWAYS, /* ACID_WORLD */ + PLANET_ALWAYS, /* ALKALI_WORLD */ + PLANET_ALWAYS, /* HALIDE_WORLD */ + PLANET_ALWAYS, /* GREEN_WORLD */ + PLANET_ALWAYS, /* COPPER_WORLD */ + PLANET_ALWAYS, /* CARBIDE_WORLD */ + PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ + PLANET_ALWAYS, /* NOBLE_WORLD */ + PLANET_ALWAYS, /* AZURE_WORLD */ + PLANET_ALWAYS, /* CHONDRITE_WORLD */ + PLANET_ALWAYS, /* PURPLE_WORLD */ + PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ + PLANET_ALWAYS, /* PELLUCID_WORLD */ + PLANET_ALWAYS, /* DUST_WORLD */ + PLANET_ALWAYS, /* CRIMSON_WORLD */ + PLANET_ALWAYS, /* CIMMERIAN_WORLD */ + PLANET_ALWAYS, /* INFRARED_WORLD */ + PLANET_ALWAYS, /* SELENIC_WORLD */ + PLANET_ALWAYS, /* AURIC_WORLD */ + + PLANET_NEVER, /* FLUORESCENT_WORLD */ + PLANET_NEVER, /* ULTRAVIOLET_WORLD */ + PLANET_NEVER, /* PLUTONIC_WORLD */ + PLANET_NEVER, /* RAINBOW_WORLD */ + PLANET_NEVER, /* CRACKED_WORLD */ + PLANET_NEVER, /* SAPPHIRE_WORLD */ + PLANET_ALWAYS, /* ORGANIC_WORLD */ + PLANET_ALWAYS, /* XENOLITHIC_WORLD */ + PLANET_ALWAYS, /* REDUX_WORLD */ + PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ + PLANET_NEVER, /* EMERALD_WORLD */ + PLANET_ALWAYS, /* CHLORINE_WORLD */ + PLANET_ALWAYS, /* MAGNETIC_WORLD */ + PLANET_ALWAYS, /* WATER_WORLD */ + PLANET_ALWAYS, /* TELLURIC_WORLD */ + PLANET_ALWAYS, /* HYDROCARBON_WORLD */ + PLANET_ALWAYS, /* IODINE_WORLD */ + PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ + PLANET_NEVER, /* RUBY_WORLD */ + PLANET_ALWAYS, /* MAGMA_WORLD */ + PLANET_ALWAYS, /* MAROON_WORLD */ + + PLANET_ALWAYS, /* BLU_GAS_GIANT */ + PLANET_ALWAYS, /* CYA_GAS_GIANT */ + PLANET_ALWAYS, /* GRN_GAS_GIANT */ + PLANET_ALWAYS, /* GRY_GAS_GIANT */ + PLANET_ALWAYS, /* ORA_GAS_GIANT */ + PLANET_ALWAYS, /* PUR_GAS_GIANT */ + PLANET_ALWAYS, /* RED_GAS_GIANT */ + PLANET_ALWAYS, /* VIO_GAS_GIANT */ + PLANET_ALWAYS, /* YEL_GAS_GIANT */ + }; + + return (PlanetDistribution[which_world]); +} + +#define DWARF_ROCK_DIST MIN_PLANET_RADIUS +#define DWARF_GASG_DIST SCALE_RADIUS (12) + +#define GIANT_ROCK_DIST SCALE_RADIUS (8) +#define GIANT_GASG_DIST SCALE_RADIUS (13) + +#define SUPERGIANT_ROCK_DIST SCALE_RADIUS (16) +#define SUPERGIANT_GASG_DIST SCALE_RADIUS (33) + +void +FillOrbits (BYTE NumPlanets, PPLANET_DESC pBaseDesc, BOOLEAN + TypesDefined) +{ /* Generate Planets in orbit around star */ + BYTE StarColor, PlanetCount, MaxPlanet; + BOOLEAN GeneratingMoons; + COUNT StarSize; + PPLANET_DESC pPD; + struct + { + COUNT MinRockyDist, MinGasGDist; + } Suns[] = + { + {DWARF_ROCK_DIST, DWARF_GASG_DIST}, + {GIANT_ROCK_DIST, GIANT_GASG_DIST}, + {SUPERGIANT_ROCK_DIST, SUPERGIANT_GASG_DIST}, + }; +#ifdef DEBUG +UNICODE buf[40]; +char stype[] = {'D', 'G', 'S'}; +char scolor[] = {'B', 'G', 'O', 'R', 'W', 'Y'}; +#endif /* DEBUG */ + + pPD = pBaseDesc; + StarSize = pSolarSysState->SunDesc[0].data_index; + StarColor = STAR_COLOR (CurStarDescPtr->Type); + + if (NumPlanets == (BYTE)~0) + { +#define MAX_GENERATED_PLANETS 10 + while ((NumPlanets = (BYTE)(LOWORD (Random()) + % MAX_GENERATED_PLANETS)) == 0) + ; + pSolarSysState->SunDesc[0].NumPlanets = NumPlanets; + } + +#ifdef DEBUG +GetClusterName (CurStarDescPtr, buf); +printf ("cluster name = %s color = %c type = %c\n", buf, + scolor[STAR_COLOR (CurStarDescPtr->Type)], + stype[STAR_TYPE (CurStarDescPtr->Type)]); +#endif /* DEBUG */ + GeneratingMoons = (BOOLEAN) (pBaseDesc == pSolarSysState->MoonDesc); + if (GeneratingMoons) + MaxPlanet = FIRST_LARGE_ROCKY_WORLD; + else + MaxPlanet = NUMBER_OF_PLANET_TYPES; + PlanetCount = NumPlanets; + while (NumPlanets--) + { + BYTE chance; + DWORD rand_val; + COUNT min_radius, angle; + SIZE delta_r; + PPLANET_DESC pLocPD; + + do + { + rand_val = Random (); + if (TypesDefined) + rand_val = 0; + else + pPD->data_index = (BYTE)( + HIBYTE (LOWORD (rand_val)) + % MaxPlanet + ); + + chance = PLANET_NEVER; + switch (StarColor) + { + case BLUE_BODY: + chance = BlueDistribution (pPD->data_index); + break; + case GREEN_BODY: + chance = GreenDistribution (pPD->data_index); + break; + case ORANGE_BODY: + chance = OrangeDistribution (pPD->data_index); + break; + case RED_BODY: + chance = RedDistribution (pPD->data_index); + break; + case WHITE_BODY: + chance = WhiteDistribution (pPD->data_index); + break; + case YELLOW_BODY: + chance = YellowDistribution (pPD->data_index); + break; + } + } while (LOBYTE (LOWORD (rand_val)) >= chance); + + if (pPD->data_index < FIRST_GAS_GIANT) + min_radius = Suns[StarSize].MinRockyDist; + else + min_radius = Suns[StarSize].MinGasGDist; +RelocatePlanet: + rand_val = Random (); + if (GeneratingMoons) + { + pPD->radius = MIN_MOON_RADIUS + + ((LOWORD (rand_val) % MAX_MOONS) * MOON_DELTA); + for (pLocPD = pPD - 1; pLocPD >= pBaseDesc; --pLocPD) + { + if (pPD->radius == pLocPD->radius) + goto RelocatePlanet; + } + pPD->NumPlanets = 0; + } + else + { + pPD->radius = (LOWORD (rand_val) + % (MAX_PLANET_RADIUS - min_radius)) + + min_radius; + for (pLocPD = pPD - 1; pLocPD >= pBaseDesc; --pLocPD) + { + delta_r = UNSCALE_RADIUS (pLocPD->radius) / 5 + - UNSCALE_RADIUS (pPD->radius) / 5; + if (delta_r < 0) + delta_r = -delta_r; + if (delta_r <= 1) + goto RelocatePlanet; + } + } + + rand_val = Random (); + angle = NORMALIZE_ANGLE (LOWORD (rand_val)); + pPD->location.x = + COSINE (angle, pPD->radius); + pPD->location.y = + SINE (angle, pPD->radius); + pPD->rand_seed = MAKE_DWORD ( + pPD->location.x, + pPD->location.y + ); + + ++pPD; + } + + { + BYTE i; + + for (i = 0; i < PlanetCount; ++i) + { + BYTE j; + + for (j = (BYTE)(PlanetCount - 1); j > i; --j) + { + if (pBaseDesc[i].radius > pBaseDesc[j].radius) + { + PLANET_DESC temp; + + temp = pBaseDesc[i]; + pBaseDesc[i] = pBaseDesc[j]; + pBaseDesc[j] = temp; + } + } + } + } +} + diff --git a/sc2/src/sc2code/planets/oval.c b/sc2/src/sc2code/planets/oval.c new file mode 100644 index 000000000..7506a384c --- /dev/null +++ b/sc2/src/sc2code/planets/oval.c @@ -0,0 +1,325 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "graphics/gfxintrn.h" +#include "starcon.h" + +#define NUM_QUADS 4 + +void +DrawOval (PRECT pRect, BYTE num_off_pixels) +{ +#define FIRST_QUAD (1 << 0) +#define SECOND_QUAD (1 << 1) +#define THIRD_QUAD (1 << 2) +#define FOURTH_QUAD (1 << 3) + COUNT off; + COORD x, y; + SIZE A, B; + long Asquared, TwoAsquared, + Bsquared, TwoBsquared; + long d, dx, dy; + BYTE quad_visible; + LINE corners; + POINT mp; + PRIMITIVE prim[NUM_QUADS]; + COUNT StartPrim; + RECT ClipRect; + BRESENHAM_LINE ClipLine; + + ClipRect.corner.x = ClipRect.corner.y = 0; + + corners.first.x = pRect->corner.x - ClipRect.corner.x; + corners.first.y = pRect->corner.y - ClipRect.corner.y; + corners.second.x = corners.first.x + pRect->extent.width - 1; + corners.second.y = corners.first.y + pRect->extent.height - 1; + if (corners.second.x <= corners.first.x + || corners.second.y <= corners.first.y) + { + if (corners.second.x < corners.first.x) + corners.second.x = corners.first.x; + if (corners.second.y < corners.first.y) + corners.second.y = corners.first.y; + + DrawLine (&corners); + return; + } + + ClipRect.extent.width = SIS_SCREEN_WIDTH; + ClipRect.extent.height = SIS_SCREEN_HEIGHT; + + quad_visible = 0; + mp.x = (corners.first.x + corners.second.x) >> 1; + mp.y = (corners.first.y + corners.second.y) >> 1; + ClipRect.corner.x = ClipRect.corner.y = 0; + + if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height + && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) + quad_visible |= FIRST_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.first.y; + ClipLine.second.x = corners.second.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= FIRST_QUAD; + } + + if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height + && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) + quad_visible |= SECOND_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.first.y; + ClipLine.second.x = corners.first.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= SECOND_QUAD; + } + + if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height + && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) + quad_visible |= THIRD_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.second.y; + ClipLine.second.x = corners.first.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= THIRD_QUAD; + } + + if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height + && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) + quad_visible |= FOURTH_QUAD; + else + { + ClipLine.first.x = mp.x; + ClipLine.first.y = corners.second.y; + ClipLine.second.x = corners.second.x; + ClipLine.second.y = mp.y; + if (_clip_line (&ClipRect, &ClipLine)) + quad_visible |= FOURTH_QUAD; + } + + if (!quad_visible) + return; + + StartPrim = END_OF_LIST; + for (x = 0; x < NUM_QUADS; ++x) + { + if (quad_visible & (1 << x)) + { + SetPrimNextLink (&prim[x], StartPrim); + SetPrimType (&prim[x], POINT_PRIM); + SetPrimColor (&prim[x], _get_context_fg_color ()); + + StartPrim = x; + } + } + + A = pRect->extent.width >> 1; + B = pRect->extent.height >> 1; + + x = 0; + y = B; + + Asquared = ((long)A * A) << 1; + Bsquared = ((long)B * B) << 1; + do + { + Asquared >>= 1; + Bsquared >>= 1; + TwoAsquared = Asquared << 1; + dy = TwoAsquared * B; + } while (dy / B != TwoAsquared); + TwoBsquared = Bsquared << 1; + + dx = 0; + d = Bsquared - (dy >> 1) + (Asquared >> 2); + + off = 0; + A += pRect->corner.x; + B += pRect->corner.y; + while (dx < dy) + { + if (off-- == 0) + { + prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; + prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; + prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; + prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; + + DrawBatch (prim, StartPrim, 0); + off = num_off_pixels; + } + + if (d > 0) + { + --y; + dy -= TwoAsquared; + d -= dy; + } + + ++x; + dx += TwoBsquared; + d += Bsquared + dx; + } + + d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; + + while (y >= 0) + { + if (off-- == 0) + { + prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; + prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; + prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; + prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; + + DrawBatch (prim, StartPrim, 0); + off = num_off_pixels; + } + + if (d < 0) + { + ++x; + dx += TwoBsquared; + d += dx; + } + + --y; + dy -= TwoAsquared; + d += Asquared - dy; + } +} + +void +DrawFilledOval (PRECT pRect) +{ + COORD x, y; + SIZE A, B; + long Asquared, TwoAsquared, + Bsquared, TwoBsquared; + long d, dx, dy; + LINE corners; + PRIMITIVE prim[NUM_QUADS >> 1]; + COUNT StartPrim; + + corners.first.x = pRect->corner.x; + corners.first.y = pRect->corner.y; + corners.second.x = corners.first.x + pRect->extent.width - 1; + corners.second.y = corners.first.y + pRect->extent.height - 1; + if (corners.second.x <= corners.first.x + || corners.second.y <= corners.first.y) + { + if (corners.second.x < corners.first.x) + corners.second.x = corners.first.x; + if (corners.second.y < corners.first.y) + corners.second.y = corners.first.y; + + DrawLine (&corners); + return; + } + + StartPrim = END_OF_LIST; + for (x = 0; x < (NUM_QUADS >> 1); ++x) + { + SetPrimNextLink (&prim[x], StartPrim); + SetPrimType (&prim[x], RECTFILL_PRIM); + SetPrimColor (&prim[x], _get_context_fg_color ()); + prim[x].Object.Rect.extent.height = 1; + + StartPrim = x; + } + + A = pRect->extent.width >> 1; + B = pRect->extent.height >> 1; + + x = 0; + y = B; + + Asquared = ((long)A * A) << 1; + Bsquared = ((long)B * B) << 1; + do + { + Asquared >>= 1; + Bsquared >>= 1; + TwoAsquared = Asquared << 1; + dy = TwoAsquared * B; + } while (dy / B != TwoAsquared); + TwoBsquared = Bsquared << 1; + + dx = 0; + d = Bsquared - (dy >> 1) + (Asquared >> 2); + + A += pRect->corner.x; + B += pRect->corner.y; + while (dx < dy) + { + if (d > 0) + { + prim[0].Object.Rect.corner.x = + prim[1].Object.Rect.corner.x = A - x; + prim[0].Object.Rect.extent.width = + prim[1].Object.Rect.extent.width = (x << 1) + 1; + prim[0].Object.Rect.corner.y = B - y; + prim[1].Object.Rect.corner.y = B + y; + + DrawBatch (prim, StartPrim, 0); + + --y; + dy -= TwoAsquared; + d -= dy; + } + + ++x; + dx += TwoBsquared; + d += Bsquared + dx; + } + + d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; + + while (y >= 0) + { + prim[0].Object.Rect.corner.x = + prim[1].Object.Rect.corner.x = A - x; + prim[0].Object.Rect.extent.width = + prim[1].Object.Rect.extent.width = (x << 1) + 1; + prim[0].Object.Rect.corner.y = B - y; + prim[1].Object.Rect.corner.y = B + y; + + DrawBatch (prim, StartPrim, 0); + + if (d < 0) + { + ++x; + dx += TwoBsquared; + d += dx; + } + + --y; + dy -= TwoAsquared; + d += Asquared - dy; + } +} + + diff --git a/sc2/src/sc2code/planets/pl_stuff.c b/sc2/src/sc2code/planets/pl_stuff.c new file mode 100644 index 000000000..59978cef8 --- /dev/null +++ b/sc2/src/sc2code/planets/pl_stuff.c @@ -0,0 +1,751 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//#include "Portfolio.h" //A 3DO library we don't care about +//#include "Init3DO.h" +//#include "Parse3DO.h" +//#include "Utils3DO.h" +//#include "filefunctions.h" +//#include "BlockFile.h" +#include "starcon.h" +#include "SDL.h" +#include "SDL_wrapper.h" + +//Added by Chris + +//End Added by Chris + +//#define KDEBUG +#define SCALE_ROTATE + +//#define SCREEN_WIDTH 320 + +#define WIDTH 210 +#define HEIGHT 67 +#define XBANDS 6 + +#define SPHERE_HEIGHT (HEIGHT + 10) +#define SPHERE_WIDTH SPHERE_HEIGHT + +#define WRAP_EXTRA 20 + +#define LINE_PIXELS ((WIDTH + WRAP_EXTRA + 3) & ~3) + +#define SURFACE_WIDTH 210 +#define SURFACE_HEIGHT 124 + +#define SURFACE_SHIFT 2 +#define SURFACE_UNIT (1 << SURFACE_SHIFT) +#define SURFACE_ADD (SURFACE_UNIT - 1) + +#define NUM_TINTS 4 + +#define PIXC_DUP(v) (((Uint32)(v) << PPMP_0_SHIFT) | ((Uint32)(v) << PPMP_1_SHIFT)) +#define PIXC_UNCODED16 (PIXC_DUP (PPMPC_MF_8 | PPMPC_SF_8)) +#define PIXC_UNCODED8 (PIXC_DUP (PPMPC_MF_8 | PPMPC_SF_8)) +#define PIXC_CODED (PIXC_DUP (PPMPC_MS_PIN | PPMPC_SF_8)) + +#define SET_CEL_FLAGS(c,f) ((c)->ccb_Flags |= (f)) +#define CLR_CEL_FLAGS(c,f) ((c)->ccb_Flags &= ~(f)) + +#define CEL_FLAGS \ + (CCB_SPABS | CCB_PPABS | CCB_YOXY | CCB_ACW | CCB_ACCW | CCB_LDSIZE | CCB_CCBPRE \ + | CCB_LDPRS | CCB_LDPPMP | CCB_ACE | CCB_LCE | CCB_PLUTPOS | CCB_BGND | CCB_NPABS \ + /*| CCB_NOBLK*/) + +#define MAP_CEL myMapCel + +#define NUM_ROTATE_CELS (138) // derived empirically! + +#define NUM_CELS (NUM_ROTATE_CELS * 2) // must be at least 257 for oscilloscope + +#define MIN_Y (-(SURFACE_HEIGHT >> 1)) +#define MAX_Y ((HEIGHT << SURFACE_SHIFT) - (SURFACE_HEIGHT >> 1)) + +#define PULSE_SCALE (2) +#define SCALE_PULSE_RED(r) ((r)<x0) +#define x1 (planet_stuff->x1) +#define y0 (planet_stuff->y0) +#define y1 (planet_stuff->y1) +#define ystep (planet_stuff->ystep) +#define src_ws (planet_stuff->src_ws) + +#define planet_ccb (planet_stuff->planet_ccb) +#define surface_ccb (planet_stuff->surface_ccb) +#define tint_ccb (planet_stuff->tint_ccb) + +#define black_rect_ccb (planet_stuff->black_rect_ccb) + +#define black_circ_ccb (planet_stuff->black_circ_ccb) + +#define pshadow_ccb (planet_stuff->pshadow_ccb) + +#define pshield_ccb (planet_stuff->pshield_ccb) + +#define pblack_circ_ccb (planet_stuff->pblack_circ_ccb) + +#define black_circ_plut (planet_stuff->black_circ_plut) + +#define repair_ccb (planet_stuff->repair_ccb) + +#define rmap (planet_stuff->rmap) + +#define cur_ccb (planet_stuff->cur_ccb) + +#define old_sx (planet_stuff->old_sx) +#define old_sy (planet_stuff->old_sy) + +#define plCCB (planet_stuff->plCCB) + +#define last_zoom_ccb (planet_stuff->last_zoom_ccb) +#define zoom_batch (planet_stuff->zoom_batch) + +#define shield_pulse (zoom_batch) + +#ifdef SCALE_ROTATE +#define scale (planet_stuff->scale) + +#define SCALE_AMT_SHIFT 7 +#define SCALE_AMT_MASK ((1<<(SCALE_AMT_SHIFT+1))-1) +#define SCALE_X_SHIFT 9 +#define SCALE_X_MASK (3<> SCALE_X_SHIFT) - 1; \ + _dy = (Sint32)((scale & SCALE_Y_MASK) >> SCALE_Y_SHIFT) - 1; \ + (ccb)->ccb_XPos = (((ccb)->ccb_XPos - (cx)) * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_YPos = (((ccb)->ccb_YPos - (cy)) * s) >> SCALE_AMT_SHIFT; \ + if (_dx < 0) \ + (ccb)->ccb_XPos += ((cx) * s) >> SCALE_AMT_SHIFT; \ + else if (_dx > 0) \ + (ccb)->ccb_XPos += ((cx) << 1) - (((cx) * s) >> SCALE_AMT_SHIFT); \ + else \ + (ccb)->ccb_XPos += (cx); \ + if (_dy < 0) \ + (ccb)->ccb_YPos += ((cy) * s) >> SCALE_AMT_SHIFT; \ + else if (_dy > 0) \ + (ccb)->ccb_YPos += ((cy) << 1) - (((cy) * s) >> SCALE_AMT_SHIFT); \ + else \ + (ccb)->ccb_YPos += (cy); \ + (ccb)->ccb_HDX = ((ccb)->ccb_HDX * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_VDY = ((ccb)->ccb_VDY * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_VDX = ((ccb)->ccb_VDX * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_HDY = ((ccb)->ccb_HDY * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_HDDX = ((ccb)->ccb_HDDX * s) >> SCALE_AMT_SHIFT; \ + (ccb)->ccb_HDDY = ((ccb)->ccb_HDDY * s) >> SCALE_AMT_SHIFT; \ + } while (0) +#endif + +#define pcirc_ccb (planet_stuff->pcirc_ccb) +#define pblur_ccb (planet_stuff->pblur_ccb) + +#if 0 +static void +build_steps () +{ + Sint32 y, i, c, inc; + + c = 1; + inc = 1; + y = 0; + for (i = 0; y < (HEIGHT >> 1); ++i) + { + ystep[i] = c; + y += c; + if (y > (HEIGHT >> 2) && inc == 1) + { + y -= c; + ystep[i] = ((HEIGHT >> 1) - (y << 1)); + if (ystep[i] == 0) + --i; + else + y += ystep[i]; + + inc = -1; + } + c += inc; + } + + ystep[i] = 1; + +#if 0 +y = 0; +for (i = 0; y < (HEIGHT >> 1); i++) +{ + printf ("ystep[%ld] = %ld\n", i, ystep[i]); + y += ystep[i]; +} +#endif +} + +static void +build_tables (Sint32 da) +{ + Sint32 y, i; + + build_steps (); + + OpenMathFolio (); // calling this multiply is not a problem, right? + + for (y = 0, i = 0; y <= (HEIGHT >> 1); i++) + { + Sint32 dx, dy, a, h; + + h = ystep[i]; + + if (y + h > (HEIGHT >> 1) + && (h = (HEIGHT >> 1) - y + 1) == 0) + return; + + dy = (HEIGHT >> 1) - y; + dx = (int)SqrtF16 (((HEIGHT >> 1) * (HEIGHT >> 1) - dy * dy) << 16); + dy <<= 16; + + a = (int)Atan2F16 (-dx, -dy); + a += da << 16; + x0[i] = (int)(HEIGHT * CosF16 (a)); + y0[i] = (int)(HEIGHT * SinF16 (a)); + a = (int)Atan2F16 (dx, -dy); + a += da << 16; + x1[i] = (int)(HEIGHT * CosF16 (a)); + y1[i] = (int)(HEIGHT * SinF16 (a)); + + x0[i] >>= 1; + y0[i] >>= 1; + x1[i] >>= 1; + y1[i] >>= 1; + + y += h; +#if 0 +printf ("%ld: %ld ", i, y); +printf ("%ld,%ld -- ", x0[i] >> 16, y0[i] >> 16); +printf ("%ld,%ld\n", x1[i] >> 16, y1[i] >> 16); +#endif + } + + x0[i] = x0[i - 1]; + y0[i] = y0[i - 1]; + x1[i] = x1[i - 1]; + y1[i] = y1[i - 1]; +} + +static void +draw_band (Sint32 src_x, Sint32 src_y, Sint32 dst_cx, Sint32 dst_cy) +{ + //I_CANNOT_FIGURE_OUT_HOW_TO_FIX_THIS_FILE___STREAM???(); + + Sint32 *sp; + Sint32 i; + + sp = (Sint32 *)planet_ccb.ccb_SourcePtr + src_y * (LINE_PIXELS >> 1); + + for (i = 0; i < XBANDS; i++) + { +#define src_w src_ws[i] + cur_ccb->ccb_SourcePtr = (CelData *)(sp + (src_x >> 1)); + cur_ccb->ccb_XPos = dst_cx + cur_ccb->ccb_Width; + cur_ccb->ccb_YPos = dst_cy + cur_ccb->ccb_Height; +#ifdef SCALE_ROTATE + if (scale) + SCALE_CEL (cur_ccb, dst_cx, dst_cy); +#endif + cur_ccb++; + + src_x += src_w; + if (src_x >= WIDTH) + src_x -= WIDTH; + else if (src_x < 0) + src_x += WIDTH; + } +} + +static void +set_band_cels (Sint32 src_y, Sint32 src_h, Sint32 band) +{ + Sint32 i, dst_x0, dst_y0, dst_x1, dst_y1, dx0, dy0, dx1, dy1; + + if (src_y > (HEIGHT >> 1)) + { + if (src_y + src_h > HEIGHT + && (src_h = HEIGHT - src_y + 1) == 0) + return; + dx0 = x1[band + 1]; + dy0 = y1[band + 1]; + dx1 = x1[band]; + dy1 = y1[band]; + dst_x0 = -dx0; + dst_y0 = -dy0; + dst_x1 = -dx1; + dst_y1 = -dy1; + dx0 -= x0[band + 1]; + dy0 -= y0[band + 1]; + dx1 -= x0[band]; + dy1 -= y0[band]; + } + else + { + if (src_y + src_h > (HEIGHT >> 1) + && (src_h = (HEIGHT >> 1) - src_y + 1) == 0) + return; + dx0 = x0[band]; + dy0 = y0[band]; + dx1 = x0[band + 1]; + dy1 = y0[band + 1]; + dst_x0 = dx0; + dst_y0 = dy0; + dst_x1 = dx1; + dst_y1 = dy1; + dx0 = x1[band] - dx0; + dy0 = y1[band] - dy0; + dx1 = x1[band + 1] - dx1; + dy1 = y1[band + 1] - dy1; + } + + for (i = 0; i < XBANDS; i++) + { +#define dd d[i] +#define src_w src_ws[i] + POINT quadpts[4]; + Sint32 d[XBANDS] = { 17, 47, 64, 64, 47, 17 }; + + quadpts[0].x = dst_x0; + quadpts[0].y = dst_y0; + quadpts[3].x = dst_x1; + quadpts[3].y = dst_y1; + + dst_x0 += (dx0 * dd) >> 8; + dst_y0 += (dy0 * dd) >> 8; + dst_x1 += (dx1 * dd) >> 8; + dst_y1 += (dy1 * dd) >> 8; + + quadpts[1].x = dst_x0; + quadpts[1].y = dst_y0; + quadpts[2].x = dst_x1; + quadpts[2].y = dst_y1; + + cur_ccb->ccb_PRE0 &= ~PRE0_VCNT_MASK; + cur_ccb->ccb_PRE1 &= ~PRE1_TLHPCNT_MASK; + cur_ccb->ccb_PRE0 |= (src_h - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT; + cur_ccb->ccb_PRE1 |= (src_w - PRE1_TLHPCNT_PREFETCH) << PRE1_TLHPCNT_SHIFT; + + cur_ccb->ccb_Width = src_w; + cur_ccb->ccb_Height = src_h; + + MAP_CEL (cur_ccb, quadpts); + + cur_ccb->ccb_Width = cur_ccb->ccb_XPos; + cur_ccb->ccb_Height = cur_ccb->ccb_YPos; + + cur_ccb++; + } +} + +static void +init_rotate_cels () +{ + Sint32 i, incr, y; + + incr = 1; + cur_ccb = plCCB; + for (y = 0, i = 0; y < HEIGHT;) + { +#define src_h ystep[i] + set_band_cels (y, src_h, i); + y += src_h; + i += incr; + if (src_h == 0) + { + --i; + incr = -1; + if (HEIGHT & 1) + --i; + } + } +#if 0 +printf ("using %d cels for rotate\n", cur_ccb - plCCB); +#endif +} +#endif + +void +SetPlanetTilt (Sint32 da) +{ +#if 0 + Sint32 w, i; + + shield_pulse = MAX_PULSE_RED; + for (i = 0, cur_ccb = plCCB; i < NUM_ROTATE_CELS; i++, cur_ccb++) + { + *cur_ccb = planet_ccb; + cur_ccb->ccb_NextPtr = cur_ccb + 1; + } + + if (!src_ws[0]) + { + Sint32 err; + + w = (WIDTH / 2) / XBANDS; + err = XBANDS; + i = XBANDS - 1; + do + { + src_ws[i] = w; + if ((err -= ((WIDTH / 2) % XBANDS)) <= 0) + { + src_ws[i]++; + err += XBANDS; + } + } while (i--); + + build_tables (da); + } + + init_rotate_cels (); + + { + CCB *ccb; + + ccb = plCCB; + cur_ccb = plCCB + NUM_ROTATE_CELS; + for (i = 0; i < NUM_ROTATE_CELS; i++, cur_ccb++, ccb++) + { + *cur_ccb = *ccb; + cur_ccb->ccb_NextPtr = cur_ccb + 1; + } + } +#endif +} + +int +RotatePlanet (Sint32 x, Sint32 dx, Sint32 dy) +{ +#if 1 + return (0); +#else + Sint32 i, y; + Sint32 incr; + CCB *first; + + dx <<= 16; + dy <<= 16; + + if (pblack_circ_ccb && !pshield_ccb->ccb_HDY) + { + pblack_circ_ccb->ccb_XPos = dx - (pblack_circ_ccb->ccb_Width << 15); + pblack_circ_ccb->ccb_YPos = dy - (pblack_circ_ccb->ccb_Height << 15); + pblack_circ_ccb->ccb_HDX = 1 << 20; + pblack_circ_ccb->ccb_VDY = 1 << 16; +#ifdef SCALE_ROTATE + if ((scale & SCALE_AMT_MASK) > SCALE_STEP) + { + scale -= SCALE_STEP; + SCALE_CEL (pblack_circ_ccb, dx, dy); + scale += SCALE_STEP; + } + else if (!scale) +#endif + add_cel (pblack_circ_ccb); +#ifdef KDEBUG +printf ("CLEAR...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + } + + incr = 1; +#ifdef SCALE_ROTATE + if (scale) + { + CCB *ccb; + + ccb = plCCB; + cur_ccb = plCCB + NUM_ROTATE_CELS; + for (i = 0; i < NUM_ROTATE_CELS; i++, cur_ccb++, ccb++) + { + *cur_ccb = *ccb; + cur_ccb->ccb_NextPtr = cur_ccb + 1; + } + first = plCCB + NUM_ROTATE_CELS; + } + else +#endif + first = plCCB; + cur_ccb = first; + for (y = 0, i = 0; y < HEIGHT;) + { +#define src_h ystep[i] + draw_band (x, y, dx, dy); + y += src_h; + i += incr; + if (src_h == 0) + { + --i; + incr = -1; + if (HEIGHT & 1) + --i; + } + } + + add_cels (first, cur_ccb - 1); + +#ifdef KDEBUG +printf ("PLANET...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + if (pcirc_ccb) + { + pcirc_ccb->ccb_XPos = dx - (pcirc_ccb->ccb_Width << 15); + pcirc_ccb->ccb_YPos = dy - (pcirc_ccb->ccb_Height << 15); + pcirc_ccb->ccb_HDX = 1 << 20; + pcirc_ccb->ccb_VDY = 1 << 16; +#ifdef SCALE_ROTATE + if (scale) + SCALE_CEL (pcirc_ccb, dx, dy); +#endif + add_cel (pcirc_ccb); +#ifdef KDEBUG +printf ("CLIP...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + } + + if (pblur_ccb) + { + pblur_ccb->ccb_XPos = dx - (pblur_ccb->ccb_Width << 15); + pblur_ccb->ccb_YPos = dy - (pblur_ccb->ccb_Height << 15); + pblur_ccb->ccb_HDX = 1 << 20; + pblur_ccb->ccb_VDY = 1 << 16; +#ifdef SCALE_ROTATE + if (scale) + SCALE_CEL (pblur_ccb, dx, dy); +#endif + add_cel (pblur_ccb); +#ifdef KDEBUG +printf ("BLUR...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + } + + if (pshadow_ccb) + { + pshadow_ccb->ccb_XPos = dx - (pshadow_ccb->ccb_Width << 15); + pshadow_ccb->ccb_YPos = dy - (pshadow_ccb->ccb_Height << 15); + pshadow_ccb->ccb_HDX = 1 << 20; + pshadow_ccb->ccb_VDY = 1 << 16; +#ifdef SCALE_ROTATE + if (scale) + SCALE_CEL (pshadow_ccb, dx, dy); +#endif + add_cel (pshadow_ccb); +#ifdef KDEBUG +printf ("SHADOW...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + } + + if (!pshield_ccb->ccb_HDY) + { + pshield_ccb->ccb_XPos = dx - (pshield_ccb->ccb_Width << 15); + pshield_ccb->ccb_YPos = dy - (pshield_ccb->ccb_Height << 15); + pshield_ccb->ccb_HDX = 1 << 20; + pshield_ccb->ccb_VDY = 1 << 16; +#ifdef SCALE_ROTATE + if (scale) + SCALE_CEL (pshield_ccb, dx, dy); +#endif + + if (shield_pulse & PULSE_NEG_BIT) + { + if (((--shield_pulse) & ~PULSE_NEG_BIT) < MIN_PULSE_RED) + shield_pulse = (MIN_PULSE_RED + 1); + } + else if (((++shield_pulse) & ~PULSE_NEG_BIT) > MAX_PULSE_RED) + shield_pulse = (MAX_PULSE_RED - 1) | PULSE_NEG_BIT; + pshield_ccb->ccb_PIXC = + PIXC_DUP (PPMPC_1S_PDC | PPMPC_MS_CCB + | (((shield_pulse & ~PULSE_NEG_BIT) >> PULSE_SCALE) << PPMPC_MF_SHIFT) + | PPMPC_SF_8 | PPMPC_2S_CFBD | PPMPC_2D_1); + + add_cel (pshield_ccb); +#ifdef KDEBUG +printf ("SHIELD...\n"); +while (AnyButtonPress (FALSE)); +while (!AnyButtonPress (FALSE)); +while (AnyButtonPress (FALSE)); +#endif /* KDEBUG */ + } + +#ifdef SCALE_ROTATE + if (scale && ((scale += SCALE_STEP) & SCALE_AMT_MASK) > SCALE_MAX) + scale = 0; + + return (scale != 0); +#else + return (0); +#endif +#endif +} + +void +DrawPlanet (Sint32 x, Sint32 y, Sint32 dy, Uint32 rgb) +{ +#if 1 + STAMP s; + + s.origin.x = x; + s.origin.y = y; + s.frame = pSolarSysState->TopoFrame; + DrawStamp (&s); +#else + if (rgb || !pshield_ccb->ccb_HDY) + { + Sint32 i, nt, my; + + if (!pshield_ccb->ccb_HDY) + { + dy = HEIGHT + NUM_TINTS; + rgb = 0x1f << 10; + } + + my = dy - NUM_TINTS; + if (my < 0) + { + nt = NUM_TINTS + my + 1; + my = 0; + } + else if (my >= HEIGHT) + { + nt = NUM_TINTS; + my = HEIGHT - 1; + } + else + nt = NUM_TINTS; + + my += y; + + surface_ccb.ccb_XPos = x << 16; + surface_ccb.ccb_YPos = y << 16; + surface_ccb.ccb_SourcePtr = planet_ccb.ccb_SourcePtr; + surface_ccb.ccb_PRE0 = + PRE0_BGND + | (((dy + 1) - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT) + | PRE0_LINEAR + | PRE0_BPP_16; + surface_ccb.ccb_PIXC = + PIXC_DUP (PPMPC_1S_PDC | PPMPC_MS_CCB | PPMPC_MF_6 + | PPMPC_SF_8 | PPMPC_2S_0); + add_cel (&surface_ccb); + + nt = NUM_TINTS - nt; + for (i = nt; i < NUM_TINTS; i++, my++) + { + if (my >= y && my < y + HEIGHT) + { + if (i == 0) + { + tint_ccb[i].ccb_YPos = y << 16; + tint_ccb[i].ccb_VDY = (my - y + 1) << 16; + } + else + tint_ccb[i].ccb_YPos = my << 16; + tint_ccb[i].ccb_XPos = x << 16; + *((Uint32 *)tint_ccb[i].ccb_SourcePtr) = rgb | (rgb << 16) | 0x80008000; + add_cel (&tint_ccb[i]); + } + } + } + else + { + surface_ccb.ccb_XPos = x << 16; + surface_ccb.ccb_YPos = y << 16; + surface_ccb.ccb_SourcePtr = planet_ccb.ccb_SourcePtr; + surface_ccb.ccb_PRE0 = + PRE0_BGND + | ((HEIGHT - PRE0_VCNT_PREFETCH) << PRE0_VCNT_SHIFT) + | PRE0_LINEAR + | PRE0_BPP_16; + surface_ccb.ccb_PIXC = PIXC_UNCODED16; + add_cel (&surface_ccb); + } +#endif +} + +CCB * +GetCelArray () +{ + return (plCCB); +} diff --git a/sc2/src/sc2code/planets/plandata.h b/sc2/src/sc2code/planets/plandata.h new file mode 100644 index 000000000..74143b44c --- /dev/null +++ b/sc2/src/sc2code/planets/plandata.h @@ -0,0 +1,280 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _PLANDATA_H +#define _PLANDATA_H + +/*------------------------------ Type Defines ----------------------------- */ +#define NUMBER_OF_ORBITS 16 +#define VACANT 0xFF + +enum +{ + SMALL_ROCKY_WORLD = 0, + LARGE_ROCKY_WORLD, + GAS_GIANT, + + NUM_PLANET_TYPES +}; + +enum +{ + DWARF_STAR = 0, + GIANT_STAR, + SUPER_GIANT_STAR, + + NUM_STAR_TYPES +}; + +enum +{ + BLUE_BODY = 0, + GREEN_BODY, + ORANGE_BODY, + RED_BODY, + WHITE_BODY, + GRAY_BODY = WHITE_BODY, + YELLOW_BODY, + + NUM_STAR_COLORS, + + CYAN_BODY = NUM_STAR_COLORS, + PURPLE_BODY, + VIOLET_BODY +}; + +enum +{ + OWNER_NOBODY = 0, + OWNER_NEUTRAL, + OWNER_HIERARCHY, + + OWNER_PLAYER = (1 << 2) +}; + +#define STAR_OWNER_SHIFT 0 +#define STAR_TYPE_SHIFT 3 /* STAR_OWNER_SHIFT + 3 */ +#define STAR_COLOR_SHIFT 5 /* STAR_TYPE_SHIFT + 2 */ +#define STAR_COLOR_MASK (BYTE)(0xFF << STAR_COLOR_SHIFT) +#define STAR_TYPE_MASK (BYTE)((0xFF << STAR_TYPE_SHIFT) \ + & ~STAR_COLOR_MASK) +#define STAR_OWNER_MASK (BYTE)((0xFF << STAR_OWNER_SHIFT) \ + & ~(STAR_COLOR_MASK \ + | STAR_TYPE_MASK)) +#define STAR_UNKNOWN_MASK (STAR_OWNER_MASK & ~OWNER_PLAYER) + +#define MAKE_STAR(t,c,o) \ + (BYTE)((((BYTE)(t) << STAR_TYPE_SHIFT) & STAR_TYPE_MASK) \ + | (((BYTE)(c) << STAR_COLOR_SHIFT) & STAR_COLOR_MASK) \ + | (((BYTE)(o) << STAR_OWNER_SHIFT) & STAR_OWNER_MASK)) +#define STAR_TYPE(f) (BYTE)(((f) & STAR_TYPE_MASK) >> STAR_TYPE_SHIFT) +#define STAR_COLOR(f) (BYTE)(((f) & STAR_COLOR_MASK) >> STAR_COLOR_SHIFT) +#define STAR_OWNER(f) (BYTE)(((f) & STAR_OWNER_MASK) >> STAR_OWNER_SHIFT) +#define STAR_UNKNOWN(f) (BOOLEAN)((STAR_OWNER(f) \ + & STAR_UNKNOWN_MASK) == STAR_UNKNOWN_MASK) + +#define PLAN_SIZE_MASK 0x03 + +#define TOPO_ALGO (0 << 2) +#define CRATERED_ALGO (1 << 2) +#define GAS_GIANT_ALGO (2 << 2) +#define PLAN_ALGO_MASK 0x0C + +#define PLANSIZE(type) ((BYTE)((type) & PLAN_SIZE_MASK)) +#define PLANALGO(type) ((BYTE)((type) & PLAN_ALGO_MASK)) +#define PLANCOLOR(type) HINIBBLE (type) + +#define THIN_ATMOSPHERE 10 +#define NORMAL_ATMOSPHERE 75 +#define THICK_ATMOSPHERE 200 +#define SUPER_THICK_ATMOSPHERE 2500 +#define GAS_GIANT_ATMOSPHERE 0xFFFF + +enum +{ + FIRST_ROCKY_WORLD = 0, + FIRST_SMALL_ROCKY_WORLD = FIRST_ROCKY_WORLD, + + OOLITE_WORLD = FIRST_SMALL_ROCKY_WORLD, + YTTRIC_WORLD, + QUASI_DEGENERATE_WORLD, + LANTHANIDE_WORLD, + TREASURE_WORLD, + UREA_WORLD, + METAL_WORLD, + RADIOACTIVE_WORLD, + OPALESCENT_WORLD, + CYANIC_WORLD, + ACID_WORLD, + ALKALI_WORLD, + HALIDE_WORLD, + GREEN_WORLD, + COPPER_WORLD, + CARBIDE_WORLD, + ULTRAMARINE_WORLD, + NOBLE_WORLD, + AZURE_WORLD, + CHONDRITE_WORLD, + PURPLE_WORLD, + SUPER_DENSE_WORLD, + PELLUCID_WORLD, + DUST_WORLD, + CRIMSON_WORLD, + CIMMERIAN_WORLD, + INFRARED_WORLD, + SELENIC_WORLD, + AURIC_WORLD, + LAST_SMALL_ROCKY_WORLD = AURIC_WORLD, + + FIRST_LARGE_ROCKY_WORLD, + FLUORESCENT_WORLD = FIRST_LARGE_ROCKY_WORLD, + ULTRAVIOLET_WORLD, + PLUTONIC_WORLD, + RAINBOW_WORLD, + CRACKED_WORLD, + SAPPHIRE_WORLD, + ORGANIC_WORLD, + XENOLITHIC_WORLD, + REDUX_WORLD, + PRIMORDIAL_WORLD, + EMERALD_WORLD, + CHLORINE_WORLD, + MAGNETIC_WORLD, + WATER_WORLD, + TELLURIC_WORLD, + HYDROCARBON_WORLD, + IODINE_WORLD, + VINYLOGOUS_WORLD, + RUBY_WORLD, + MAGMA_WORLD, + MAROON_WORLD, + LAST_LARGE_ROCKY_WORLD = MAROON_WORLD, + + FIRST_GAS_GIANT, + BLU_GAS_GIANT = FIRST_GAS_GIANT, /* Gas Giants */ + CYA_GAS_GIANT, + GRN_GAS_GIANT, + GRY_GAS_GIANT, + ORA_GAS_GIANT, + PUR_GAS_GIANT, + RED_GAS_GIANT, + VIO_GAS_GIANT, + YEL_GAS_GIANT, + LAST_GAS_GIANT = YEL_GAS_GIANT, + + NUMBER_OF_PLANET_TYPES +}; + +#define NUMBER_OF_SMALL_ROCKY_WORLDS (LAST_SMALL_ROCKY_WORLD - FIRST_SMALL_ROCKY_WORLD + 1) +#define NUMBER_OF_LARGE_ROCKY_WORLDS (LAST_LARGE_ROCKY_WORLD - FIRST_LARGE_ROCKY_WORLD + 1) +#define NUMBER_OF_ROCKY_WORLDS (NUMBER_OF_SMALL_ROCKY_WORLDS + NUMBER_OF_LARGE_ROCKY_WORLDS) +#define NUMBER_OF_GAS_GIANTS (LAST_GAS_GIANT - FIRST_GAS_GIANT + 1) + +typedef struct +{ + const SIZE level_tab[3]; + const BYTE xlat_tab[256]; +} XLAT_DESC; +typedef const XLAT_DESC *PXLAT_DESC; + +typedef struct +{ + BYTE ElementType; + BYTE Density; +} ElementEntry; + +typedef struct +{ + BYTE Type; /* HiNybble is interplanetary color */ + /* \ */ + /* \ Planet size map algo */ + /* \ \ \ */ + /* \ \ \ */ + /* 0000 00 00 */ + BYTE BaseTectonics; /* Scaled with Earth at 100 */ + BYTE AtmoAndDensity; +#define NUM_USEFUL_ELEMENTS 8 + ElementEntry UsefulElements[NUM_USEFUL_ELEMENTS]; + + RESOURCE CMapInstance, XlatTabInstance; + COUNT num_faults; + SIZE fault_depth; + COUNT num_blemishes; + SIZE base_elevation; +} PlanetFrame; +typedef const PlanetFrame *PPLANDATA; + +typedef const ElementEntry *PELEMENT_ENTRY; + +#define XLAT_DESCPTR PXLAT_DESC +#define PLANDATAPTR PPLANDATA +#define ELEMENT_ENTRYPTR PELEMENT_ENTRY + +typedef struct +{ + SIZE AxialTilt; + UWORD Tectonics; + UWORD Weather; + UWORD PlanetDensity; + UWORD PlanetRadius; + UWORD SurfaceGravity; + SIZE SurfaceTemperature; + UWORD RotationPeriod; + UWORD AtmoDensity; + SIZE LifeChance; + UWORD PlanetToSunDist; + + PLANDATAPTR PlanDataPtr; + + DWORD ScanSeed[NUM_SCAN_TYPES]; + DWORD ScanRetrieveMask[NUM_SCAN_TYPES]; + POINT CurPt; + COUNT CurDensity; + COUNT CurType; + + STRING DiscoveryString; + FONT LanderFont; +} PLANET_INFO; +typedef PLANET_INFO *PPLANET_INFO; + +enum +{ + GAS_DENSITY, + LIGHT_DENSITY, + LOW_DENSITY, + NORMAL_DENSITY, + HIGH_DENSITY, + SUPER_DENSITY +}; + +#define CalcGravity(d,r) (UWORD)((DWORD)(d) * (r) / 100) +#define CalcFromBase(b,v) ((UWORD)(b) + ((UWORD)Random () % (v))) + +#define PLANET_INFOPTR PPLANET_INFO + +#define EARTH_ATMOSPHERE 50 + +#define COLD_THRESHOLD -40 +#define HOT_THRESHOLD 100 + +/*------------------------------ Global Data ------------------------------ */ + +extern const PlanetFrame *PlanData; + +#endif /* _PLANDATA_H */ + diff --git a/sc2/src/sc2code/planets/planets.c b/sc2/src/sc2code/planets/planets.c new file mode 100644 index 000000000..8c124349e --- /dev/null +++ b/sc2/src/sc2code/planets/planets.c @@ -0,0 +1,230 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "scan.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void +DrawPlanet(int x, int y, int dy, unsigned int rgb); + +//End Added by Chris + +extern int rotate_planet_task (PVOID Blah); + +void +DrawScannedObjects (BOOLEAN Reversed) +{ + HELEMENT hElement, hNextElement; + + for (hElement = Reversed ? GetTailElement () : GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = Reversed ? + GetPredElement (ElementPtr) : + GetSuccElement (ElementPtr); + + if (ElementPtr->state_flags & APPEARING) + { + STAMP s; + + s.origin = ElementPtr->current.location; + s.frame = ElementPtr->next.image.frame; + DrawStamp (&s); + } + + UnlockElement (hElement); + } +} + +void +LoadPlanet (BOOLEAN IsDefined) +{ + STAMP s; + + SetSemaphore (&GraphicsSem); + + BatchGraphics (); + if (!(LastActivity & CHECK_LOAD)) + DrawStarBackGround (TRUE); + + if (pSolarSysState->MenuState.flash_task == 0) + { + PPLANET_DESC pPlanetDesc; + extern void GeneratePlanetSide (void); + + StopMusic (); + + TaskContext = CaptureContext (CreateContext ()); + + pPlanetDesc = pSolarSysState->pOrbitalDesc; + + if (pPlanetDesc->data_index & PLANET_SHIELDED) + ; /* pSolarSysState->PlanetSideFrame[2] = CaptureDrawable ( + LoadGraphic (PLANET_SHIELDED_MASK_PMAP_ANIM) + ); */ +// else if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != GAS_GIANT_ATMOSPHERE) +// LoadLanderData (); + + { + extern void GeneratePlanetMask (PPLANET_DESC + pPlanetDesc, BOOLEAN IsEarth); + + GeneratePlanetMask (pPlanetDesc, IsDefined); + } + + if (pPlanetDesc->pPrevDesc != &pSolarSysState->SunDesc[0]) + pPlanetDesc = pPlanetDesc->pPrevDesc; + + GeneratePlanetSide (); + } + + if (LastActivity & CHECK_LOAD) + { + if (LOBYTE (LastActivity) == 0) + { + ClearSemaphore (&GraphicsSem); + DrawSISFrame (); + SetSemaphore (&GraphicsSem); + } + else + { + ClearSISRect (DRAW_SIS_DISPLAY); + RepairSISBorder (); + } + DrawSISMessage (NULL_PTR); + DrawSISTitle (GLOBAL_SIS (PlanetName)); + + DrawStarBackGround (TRUE); + } + + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + BatchGraphics (); + DrawPlanet (SIS_SCREEN_WIDTH - MAP_WIDTH, SIS_SCREEN_HEIGHT - MAP_HEIGHT, 0, 0); + UnbatchGraphics (); + + s.frame = pSolarSysState->PlanetSideFrame[2]; + if (s.frame) + { + s.origin.x = SIS_SCREEN_WIDTH >> 1; + s.origin.y = ((116 - SIS_ORG_Y) >> 1) + 2; + DrawStamp (&s); + } + + if (!(LastActivity & CHECK_LOAD)) + { + RECT r; + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + UnbatchGraphics (); + LoadIntoExtraScreen (&r); + } + + ClearSemaphore (&GraphicsSem); + + if (!PLRPlaying ((MUSIC_REF)~0)) + { + extern MUSIC_REF LanderMusic; + + PlayMusic (LanderMusic, TRUE, 1); + if (pSolarSysState->MenuState.flash_task == 0) + { + pSolarSysState->MenuState.flash_task = + AddTask (rotate_planet_task, 4096); + + while (pSolarSysState->MenuState.Initialized == 2) + TaskSwitch (); + } + } + + if (LastActivity & CHECK_LOAD) + { + RECT r; + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + SetSemaphore (&GraphicsSem); + ScreenTransition (3, &r); + UnbatchGraphics (); + LoadIntoExtraScreen (&r); + ClearSemaphore (&GraphicsSem); + } +} + +void +FreePlanet (void) +{ + COUNT i; + + SetSemaphore (&GraphicsSem); + + if (pSolarSysState->MenuState.flash_task) + { + DeleteTask (pSolarSysState->MenuState.flash_task); + pSolarSysState->MenuState.flash_task = 0; + } + + StopMusic (); + + for (i = 0; i < sizeof (pSolarSysState->PlanetSideFrame) + / sizeof (pSolarSysState->PlanetSideFrame[0]); ++i) + { + DestroyDrawable (ReleaseDrawable (pSolarSysState->PlanetSideFrame[i])); + pSolarSysState->PlanetSideFrame[i] = 0; + } + +// FreeLanderData (); + + DestroyStringTable (ReleaseStringTable (pSolarSysState->XlatRef)); + pSolarSysState->XlatRef = 0; + UnlockResourceData (pSolarSysState->hTopoData); + FreeResourceData (pSolarSysState->hTopoData); + pSolarSysState->hTopoData = 0; + DestroyDrawable (ReleaseDrawable (pSolarSysState->TopoFrame)); + pSolarSysState->TopoFrame = 0; + DestroyColorMap (ReleaseColorMap (pSolarSysState->OrbitalCMap)); + pSolarSysState->OrbitalCMap = 0; + + DestroyContext (ReleaseContext (TaskContext)); + TaskContext = 0; + + DestroyStringTable (ReleaseStringTable ( + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString + )); + pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; + DestroyFont (ReleaseFont ( + pSolarSysState->SysInfo.PlanetInfo.LanderFont + )); + pSolarSysState->SysInfo.PlanetInfo.LanderFont = 0; + + ClearSemaphore (&GraphicsSem); +} + diff --git a/sc2/src/sc2code/planets/planets.h b/sc2/src/sc2code/planets/planets.h new file mode 100644 index 000000000..1f1d1d0e0 --- /dev/null +++ b/sc2/src/sc2code/planets/planets.h @@ -0,0 +1,194 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _PLANETS_H +#define _PLANETS_H + +#define END_INTERPLANETARY START_INTERPLANETARY + +enum +{ + SCAN = 0, + STARMAP, + EQUIP_DEVICE, + CARGO, + ROSTER +}; + +enum +{ + MINERAL_SCAN = 0, + ENERGY_SCAN, + BIOLOGICAL_SCAN, + + NUM_SCAN_TYPES, + EXIT_SCAN = NUM_SCAN_TYPES, + AUTO_SCAN, + DISPATCH_SHUTTLE +}; + +#define MAP_WIDTH SIS_SCREEN_WIDTH +#define MAP_HEIGHT (75 - SAFE_Y) + +enum +{ + GENERATE_PLANETS = 0, + GENERATE_MOONS, + GENERATE_ORBITAL, + + INIT_NPCS, + REINIT_NPCS, + UNINIT_NPCS, + + GENERATE_MINERAL, + GENERATE_ENERGY, + GENERATE_LIFE, + + GENERATE_NAME +}; + +enum +{ + BIOLOGICAL_DISASTER = 0, + EARTHQUAKE_DISASTER, + LIGHTNING_DISASTER, + LAVASPOT_DISASTER, + + /* additional lander sounds */ + LANDER_INJURED, + LANDER_SHOOTS, + LANDER_HITS, + LIFEFORM_CANNED, + LANDER_PICKUP, + LANDER_FULL, + LANDER_DEPARTS, + LANDER_RETURNS, + LANDER_DESTROYED +}; +#define MAX_SCROUNGED 50 /* max lander can hold */ + +#define SCALE_RADIUS(r) ((r) << 6) +#define UNSCALE_RADIUS(r) ((r) >> 6) +#define MAX_ZOOM_RADIUS SCALE_RADIUS(128) +#define MIN_ZOOM_RADIUS (MAX_ZOOM_RADIUS>>3) +#define EARTH_RADIUS SCALE_RADIUS(8) + +#define MIN_PLANET_RADIUS SCALE_RADIUS (4) +#define MAX_PLANET_RADIUS SCALE_RADIUS (124) + +#define DISPLAY_FACTOR ((SIS_SCREEN_WIDTH >> 1) - 8) + +#define NUM_SCANDOT_TRANSITIONS 4 + +#define MIN_MOON_RADIUS 35 +#define MOON_DELTA 20 + +#define PLANET_SHIELDED (1 << 7) + +typedef struct planet_desc +{ + DWORD rand_seed; + + BYTE data_index; + BYTE NumPlanets; + SIZE radius; + POINT location; + + COLOR temp_color; + COUNT NextIndex; + STAMP image; + + struct planet_desc *pPrevDesc; +} PLANET_DESC; +typedef PLANET_DESC *PPLANET_DESC; + +typedef struct +{ + POINT star_pt; + BYTE Type, Index; + BYTE Prefix, Postfix; +} STAR_DESC; +typedef STAR_DESC *PSTAR_DESC; +#define STAR_DESCPTR PSTAR_DESC + +#define MAX_SUNS 1 +#define MAX_PLANETS 16 +#define MAX_MOONS 4 + +#include "elemdata.h" +#include "plandata.h" +#include "sundata.h" + +typedef void (*PLAN_GEN_FUNC) (BYTE control); + +typedef struct solarsys_state +{ + MENU_STATE MenuState; + + COUNT WaitIntersect; + PLANET_DESC SunDesc[MAX_SUNS], + PlanetDesc[MAX_PLANETS], + MoonDesc[MAX_MOONS]; + PPLANET_DESC pBaseDesc, pOrbitalDesc; + SIZE FirstPlanetIndex, LastPlanetIndex; + + BYTE turn_counter, turn_wait; + BYTE thrust_counter, max_ship_speed; + + FRAME TopoFrame; + MEM_HANDLE hTopoData; + PBYTE lpTopoData; + STRING XlatRef; + STRINGPTR XlatPtr; + COLORMAP OrbitalCMap; + + SYSTEM_INFO SysInfo; + + COUNT CurNode; + PLAN_GEN_FUNC GenFunc; + + FRAME PlanetSideFrame[6]; +} SOLARSYS_STATE; +typedef SOLARSYS_STATE *PSOLARSYS_STATE; + +extern PSOLARSYS_STATE pSolarSysState; + +extern void LoadPlanet (BOOLEAN IsDefined); +extern void FreePlanet (void); + +extern void ExploreSolarSys (void); +extern void DrawStarBackGround (BOOLEAN ForPlanet); +extern void XFormIPLoc (PPOINT pIn, PPOINT pOut, BOOLEAN ToDisplay); +extern void GenerateRandomIP (BYTE control); +extern PLAN_GEN_FUNC GenerateIP (BYTE Index); +extern void DrawSystem (SIZE radius, BOOLEAN IsInnerSystem); +extern void DrawOval (PRECT pRect, BYTE num_off_pixels); +extern void DrawFilledOval (PRECT pRect); +extern void DoMissions (void); +extern void FillOrbits (BYTE NumPlanets, PPLANET_DESC pBaseDesc, BOOLEAN + TypesDefined); +extern void ScanSystem (void); +extern void ChangeSolarSys (void); +extern BOOLEAN DoFlagshipCommands (INPUT_STATE InputState, PMENU_STATE + pMS); +extern void ZoomSystem (void); +extern void LoadSolarSys (void); +extern void InitLander (BYTE LanderFlags); + +#endif /* _PLANETS_H */ + diff --git a/sc2/src/sc2code/planets/plangen.c b/sc2/src/sc2code/planets/plangen.c new file mode 100644 index 000000000..746870487 --- /dev/null +++ b/sc2/src/sc2code/planets/plangen.c @@ -0,0 +1,981 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +extern void DeltaTopography (COUNT num_iterations, PSBYTE DepthArray, + PRECT pRect, SIZE depth_delta); + +void SetPlanetMusic (BYTE planet_type); + +void SetPlanetTilt (Sint32 da); + +void RepairBackRect (PRECT pRect); + +int RotatePlanet (Sint32 x, Sint32 dx, Sint32 dy); + +#define NUM_BATCH_POINTS 64 + +void +RenderTopography (BOOLEAN Reconstruct) +{ + CONTEXT OldContext; + FRAME OldFrame; + + OldContext = SetContext (TaskContext); + OldFrame = SetContextFGFrame (pSolarSysState->TopoFrame); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + if (pSolarSysState->XlatRef == 0) + { + STAMP s; + + s.origin.x = s.origin.y = 0; +#if 0 + s.frame = SetAbsFrameIndex ( + pSolarSysState->PlanetFrameArray[2], 1 + ); +#endif + DrawStamp (&s); + } + else + { + COUNT i; + BYTE AlgoType; + SIZE base, d; + POINT pt; + PLANDATAPTR PlanDataPtr; + PRIMITIVE BatchArray[NUM_BATCH_POINTS]; + register PPRIMITIVE pBatch; + PBYTE lpDst, xlat_tab, cbase; + HOT_SPOT OldHot; + RECT ClipRect; + + OldHot = SetFrameHot (pSolarSysState->TopoFrame, MAKE_HOT_SPOT (0, 0)); + GetContextClipRect (&ClipRect); + SetContextClipRect (NULL_PTR); + SetContextClipping (FALSE); + + pBatch = &BatchArray[0]; + for (i = 0; i < NUM_BATCH_POINTS; ++i, ++pBatch) + { + SetPrimNextLink (pBatch, i + 1); + SetPrimType (pBatch, POINT_PRIM); + } + SetPrimNextLink (&pBatch[-1], END_OF_LIST); + + PlanDataPtr = &PlanData[ + pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED + ]; + AlgoType = PLANALGO (PlanDataPtr->Type); + if (Reconstruct && AlgoType != GAS_GIANT_ALGO) + base = 0; + else + base = PlanDataPtr->base_elevation; + xlat_tab = (PBYTE)((XLAT_DESCPTR)pSolarSysState->XlatPtr)->xlat_tab; + cbase = GetColorMapAddress (pSolarSysState->OrbitalCMap); + + pBatch = &BatchArray[i = NUM_BATCH_POINTS]; + lpDst = pSolarSysState->lpTopoData; + for (pt.y = 0; pt.y < MAP_HEIGHT; ++pt.y) + { + for (pt.x = 0; pt.x < MAP_WIDTH; ++pt.x) + { + d = (SBYTE)*lpDst; + if (Reconstruct) + { + d = (SIZE)((BYTE)((BYTE)d - (BYTE)base)); + ++lpDst; + } + else if (AlgoType == GAS_GIANT_ALGO) + { + *lpDst++ = (BYTE)((SBYTE)d + base); + d &= 255; + } + else + { + d += base; + if (d < 0) + d = 0; + else if (d > 255) + d = 255; + *lpDst++ = (BYTE)d; + } + + --pBatch; + pBatch->Object.Point.x = pt.x; + pBatch->Object.Point.y = pt.y; +{ + PBYTE ctab; + + d = xlat_tab[d] - cbase[0]; + ctab = (cbase + 2) + d * 3; + SetPrimColor (pBatch, BUILD_COLOR (MAKE_RGB15 (ctab[0] >> 3, ctab[1] >> 3, ctab[2] >> 3), d)); +} + if (--i) + continue; + + DrawBatch (BatchArray, 0, 0); + pBatch = &BatchArray[i = NUM_BATCH_POINTS]; + } + } + + if (i < NUM_BATCH_POINTS) + { + DrawBatch (BatchArray, i, 0); + } + + SetContextClipping (TRUE); + SetContextClipRect (&ClipRect); + SetFrameHot (pSolarSysState->TopoFrame, OldHot); + } + + SetContextFGFrame (OldFrame); + SetContext (OldContext); +} + +#if 0 +static void +RenderLevelMasks (void) +{ + COUNT i, num_frames; + BYTE AlgoType; + SIZE base, d; + POINT pt; + PLANDATAPTR PlanDataPtr; + PRIMITIVE BatchArray[NUM_BATCH_POINTS]; + register PPRIMITIVE pBatch; + PBYTE lpDst; + PSIZE level_tab; + FRAME DupFrame, MaskFrame; + + pBatch = &BatchArray[0]; + for (i = 0; i < NUM_BATCH_POINTS; ++i, ++pBatch) + { + SetPrimNextLink (pBatch, i + 1); + SetPrimType (pBatch, POINT_PRIM); + } + SetPrimNextLink (&pBatch[-1], END_OF_LIST); + + PlanDataPtr = &PlanData[ + pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED + ]; + base = PlanDataPtr->base_elevation; + AlgoType = PLANALGO (PlanDataPtr->Type); + + MaskFrame = pSolarSysState->PlanetFrameArray[1]; + DupFrame = CaptureDrawable ( + CreateDrawable (WANT_MASK, + (MAP_WIDTH >> 1) - 1, + MAP_HEIGHT, + 1) + ); + + level_tab = (PSIZE)((XLAT_DESCPTR)pSolarSysState->XlatPtr)->level_tab; + num_frames = GetFrameCount (MaskFrame); + while (num_frames--) + { + MaskFrame = DecFrameIndex (MaskFrame); + + SetContextDrawState (DEST_MASK | DRAW_SUBTRACTIVE); + SetContextFGFrame (DupFrame); + ClearDrawable (); + SetContextFGFrame (MaskFrame); + SetContextDrawState (DEST_MASK | DRAW_ADDITIVE); + + SetContextClipping (FALSE); + + pBatch = &BatchArray[i = NUM_BATCH_POINTS]; + lpDst = pSolarSysState->lpTopoData; + for (pt.y = 0; pt.y < MAP_HEIGHT; ++pt.y) + { + for (pt.x = 0; pt.x < MAP_WIDTH; ++pt.x) + { + d = *lpDst++; + if (d >= level_tab[num_frames] + && (num_frames == 2 + || d < level_tab[num_frames + 1])) + { + --pBatch; + pBatch->Object.Point.x = pt.x; + pBatch->Object.Point.y = pt.y; + if (--i) + continue; + + DrawBatch (BatchArray, 0, 0); + pBatch = &BatchArray[i = NUM_BATCH_POINTS]; + } + } + } + + if (i < NUM_BATCH_POINTS) + { + DrawBatch (BatchArray, i, 0); + } + + SetContextClipping (TRUE); + + { + STAMP s; + + SetContextFGFrame (DupFrame); + s.origin.x = 0; + s.origin.y = 0; + s.frame = MaskFrame; + DrawStamp (&s); + + SetContextFGFrame (MaskFrame); + s.origin.x = MAP_WIDTH; + s.origin.y = 0; + s.frame = DupFrame; + DrawStamp (&s); + } + } + + DestroyDrawable (ReleaseDrawable (DupFrame)); +} +#endif + +#ifdef NOTYET +static void +ExpandMap (PSBYTE DepthArray) +{ + BYTE i, j; + register PSBYTE lpSrc, lpDst; + + lpSrc = &DepthArray[(MAP_WIDTH >> 1) * ((MAP_HEIGHT >> 1) + 1) - 1]; + lpDst = &DepthArray[MAP_WIDTH * MAP_HEIGHT - 1]; + i = (MAP_HEIGHT >> 1) + 1; + do + { + register SBYTE lf, rt; + + rt = lpSrc[-(MAP_WIDTH >> 1) + 1]; + lf = *lpSrc--; + *lpDst-- = (SBYTE)((rt + lf) >> 1); + *lpDst-- = lf; + + j = (MAP_WIDTH >> 1) - 1; + do + { + rt = lf; + lf = *lpSrc--; + *lpDst-- = (SBYTE)((rt + lf) >> 1); + *lpDst-- = lf; + } while (--j); + + lpDst -= MAP_WIDTH; + } while (--i); + + lpDst = &DepthArray[MAP_WIDTH]; + i = MAP_HEIGHT >> 1; + do + { + register SBYTE top, bot; + + j = MAP_WIDTH; + do + { + top = lpDst[-MAP_WIDTH]; + bot = lpDst[MAP_WIDTH]; + *lpDst++ = (SBYTE)((top + bot) >> 1); + } while (--j); + + lpDst += MAP_WIDTH; + } while (--i); +} +#endif /* NOTYET */ + +#define RANGE_SHIFT 6 + +static void +DitherMap (PSBYTE DepthArray) +{ + COUNT i; + register PSBYTE lpDst; + + i = (MAP_WIDTH * MAP_HEIGHT) >> 2; + lpDst = DepthArray; + do + { + DWORD rand_val; + + rand_val = Random (); + *lpDst++ += (1 << (RANGE_SHIFT - 4)) + - (LOBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); + *lpDst++ += (1 << (RANGE_SHIFT - 4)) + - (HIBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); + *lpDst++ += (1 << (RANGE_SHIFT - 4)) + - (LOBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); + *lpDst++ += (1 << (RANGE_SHIFT - 4)) + - (HIBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); + } while (--i); +} + +static void +MakeCrater (PRECT pRect, PSBYTE DepthArray, SIZE rim_delta, SIZE + crater_delta, BOOLEAN SetDepth) +{ + COORD x, y, lf_x, rt_x; + SIZE A, B; + long Asquared, TwoAsquared, + Bsquared, TwoBsquared; + long d, dx, dy; + COUNT TopIndex, BotIndex, rim_pixels; + + A = pRect->extent.width >> 1; + B = pRect->extent.height >> 1; + + x = 0; + y = B; + + Asquared = (DWORD)A * A; + TwoAsquared = Asquared << 1; + Bsquared = (DWORD)B * B; + TwoBsquared = Bsquared << 1; + + dx = 0; + dy = TwoAsquared * B; + d = Bsquared - (dy >> 1) + (Asquared >> 2); + + A += pRect->corner.x; + B += pRect->corner.y; + TopIndex = (B - y) * MAP_WIDTH; + BotIndex = (B + y) * MAP_WIDTH; + rim_pixels = 1; + while (dx < dy) + { + if (d > 0) + { + lf_x = A - x; + rt_x = A + x; + if (SetDepth) + { + memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); + memset ((PSBYTE)&DepthArray[BotIndex + lf_x], 0, rt_x - lf_x + 1); + } + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += rim_delta; + DepthArray[BotIndex + lf_x] += rim_delta; + rim_pixels = 0; + } + else + { + do + { + DepthArray[TopIndex + lf_x] += rim_delta; + DepthArray[BotIndex + lf_x] += rim_delta; + if (lf_x != rt_x) + { + DepthArray[TopIndex + rt_x] += rim_delta; + DepthArray[BotIndex + rt_x] += rim_delta; + } + ++lf_x; + --rt_x; + } while (--rim_pixels); + + while (lf_x < rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + DepthArray[BotIndex + lf_x] += crater_delta; + DepthArray[TopIndex + rt_x] += crater_delta; + DepthArray[BotIndex + rt_x] += crater_delta; + ++lf_x; + --rt_x; + } + + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + DepthArray[BotIndex + lf_x] += crater_delta; + } + } + + --y; + TopIndex += MAP_WIDTH; + BotIndex -= MAP_WIDTH; + dy -= TwoAsquared; + d -= dy; + } + + ++rim_pixels; + ++x; + dx += TwoBsquared; + d += Bsquared + dx; + } + + d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; + + while (y > 0) + { + lf_x = A - x; + rt_x = A + x; + if (SetDepth) + { + memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); + memset ((PSBYTE)&DepthArray[BotIndex + lf_x], 0, rt_x - lf_x + 1); + } + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += rim_delta; + DepthArray[BotIndex + lf_x] += rim_delta; + } + else + { + do + { + DepthArray[TopIndex + lf_x] += rim_delta; + DepthArray[BotIndex + lf_x] += rim_delta; + if (lf_x != rt_x) + { + DepthArray[TopIndex + rt_x] += rim_delta; + DepthArray[BotIndex + rt_x] += rim_delta; + } + ++lf_x; + --rt_x; + } while (--rim_pixels); + + while (lf_x < rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + DepthArray[BotIndex + lf_x] += crater_delta; + DepthArray[TopIndex + rt_x] += crater_delta; + DepthArray[BotIndex + rt_x] += crater_delta; + ++lf_x; + --rt_x; + } + + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + DepthArray[BotIndex + lf_x] += crater_delta; + } + } + + if (d < 0) + { + ++x; + dx += TwoBsquared; + d += dx; + } + + rim_pixels = 1; + --y; + TopIndex += MAP_WIDTH; + BotIndex -= MAP_WIDTH; + dy -= TwoAsquared; + d += Asquared - dy; + } + + lf_x = A - x; + rt_x = A + x; + if (SetDepth) + memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += rim_delta; + } + else + { + do + { + DepthArray[TopIndex + lf_x] += rim_delta; + if (lf_x != rt_x) + DepthArray[TopIndex + rt_x] += rim_delta; + ++lf_x; + --rt_x; + } while (--rim_pixels); + + while (lf_x < rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + DepthArray[TopIndex + rt_x] += crater_delta; + ++lf_x; + --rt_x; + } + + if (lf_x == rt_x) + { + DepthArray[TopIndex + lf_x] += crater_delta; + } + } +} + +#define NUM_BAND_COLORS 4 + +static void +MakeStorms (COUNT storm_count, PSBYTE DepthArray) +{ +#define MAX_STORMS 8 + COUNT i; + RECT storm_r[MAX_STORMS]; + register PRECT pstorm_r; + + pstorm_r = &storm_r[i = storm_count]; + while (i--) + { + BOOLEAN intersect; + DWORD rand_val; + UWORD loword, hiword; + SIZE band_delta; + + --pstorm_r; + do + { + COUNT j; + + intersect = FALSE; + + rand_val = Random (); + loword = LOWORD (rand_val); + hiword = HIWORD (rand_val); + switch (HIBYTE (hiword) & 31) + { + case 0: + pstorm_r->extent.height = + (LOBYTE (hiword) % (MAP_HEIGHT >> 2)) + + (MAP_HEIGHT >> 2); + break; + case 1: + case 2: + case 3: + case 4: + pstorm_r->extent.height = + (LOBYTE (hiword) % (MAP_HEIGHT >> 3)) + + (MAP_HEIGHT >> 3); + break; + default: + pstorm_r->extent.height = + (LOBYTE (hiword) % (MAP_HEIGHT >> 4)) + + 4; + break; + } + + if (pstorm_r->extent.height <= 4) + pstorm_r->extent.height += 4; + + rand_val = Random (); + loword = LOWORD (rand_val); + hiword = HIWORD (rand_val); + + pstorm_r->extent.width = pstorm_r->extent.height + + (LOBYTE (loword) % pstorm_r->extent.height); + + pstorm_r->corner.x = HIBYTE (loword) + % (MAP_WIDTH - pstorm_r->extent.width); + pstorm_r->corner.y = LOBYTE (loword) + % (MAP_HEIGHT - pstorm_r->extent.height); + + for (j = i + 1; j < storm_count; ++j) + { + COORD x, y; + SIZE w, h; + + x = storm_r[j].corner.x - pstorm_r->corner.x; + y = storm_r[j].corner.y - pstorm_r->corner.y; + w = x + storm_r[j].extent.width + 4; + h = y + storm_r[j].extent.height + 4; + intersect = (BOOLEAN) (w > 0 && h > 0 + && x < pstorm_r->extent.width + 4 + && y < pstorm_r->extent.height + 4); + if (intersect) + break; + } + + } while (intersect); + + MakeCrater (pstorm_r, DepthArray, 6, 6, FALSE); + ++pstorm_r->corner.x; + ++pstorm_r->corner.y; + pstorm_r->extent.width -= 2; + pstorm_r->extent.height -= 2; + + band_delta = HIBYTE (loword) & ((3 << RANGE_SHIFT) + 20); + + MakeCrater (pstorm_r, DepthArray, + band_delta, band_delta, TRUE); + ++pstorm_r->corner.x; + ++pstorm_r->corner.y; + pstorm_r->extent.width -= 2; + pstorm_r->extent.height -= 2; + + band_delta += 2; + if (pstorm_r->extent.width > 2 && pstorm_r->extent.height > 2) + { + MakeCrater (pstorm_r, DepthArray, + band_delta, band_delta, TRUE); + ++pstorm_r->corner.x; + ++pstorm_r->corner.y; + pstorm_r->extent.width -= 2; + pstorm_r->extent.height -= 2; + } + + band_delta += 2; + if (pstorm_r->extent.width > 2 && pstorm_r->extent.height > 2) + { + MakeCrater (pstorm_r, DepthArray, + band_delta, band_delta, TRUE); + ++pstorm_r->corner.x; + ++pstorm_r->corner.y; + pstorm_r->extent.width -= 2; + pstorm_r->extent.height -= 2; + } + + band_delta += 4; + MakeCrater (pstorm_r, DepthArray, + band_delta, band_delta, TRUE); + } +} + +static void +MakeGasGiant (COUNT num_bands, PSBYTE DepthArray, PRECT pRect, SIZE + depth_delta) +{ + COORD last_y, next_y; + SIZE band_error, band_bump, band_delta; + COUNT i, j, band_height; + PSBYTE lpDst; + UWORD loword, hiword; + DWORD rand_val; + + band_height = pRect->extent.height / num_bands; + band_bump = pRect->extent.height % num_bands; + band_error = num_bands >> 1; + lpDst = DepthArray; + + band_delta = ((LOWORD (Random ()) + & (NUM_BAND_COLORS - 1)) << RANGE_SHIFT) + + (1 << (RANGE_SHIFT - 1)); + last_y = next_y = 0; + for (i = num_bands; i > 0; --i) + { + COORD cur_y; + + rand_val = Random (); + loword = LOWORD (rand_val); + hiword = HIWORD (rand_val); + + next_y += band_height; + if ((band_error -= band_bump) < 0) + { + ++next_y; + band_error += num_bands; + } + if (i == 1) + cur_y = pRect->extent.height; + else + { + RECT r; + + cur_y = next_y + + ((band_height - 2) >> 1) + - ((LOBYTE (hiword) % (band_height - 2)) + 1); + r.corner.x = r.corner.y = 0; + r.extent.width = pRect->extent.width; + r.extent.height = 5; + DeltaTopography (50, + &DepthArray[(cur_y - 2) * r.extent.width], + &r, depth_delta); + } + + for (j = cur_y - last_y; j > 0; --j) + { + COUNT k; + + for (k = pRect->extent.width; k > 0; --k) + *lpDst++ += band_delta; + } + + last_y = cur_y; + band_delta = (band_delta + + ((((LOBYTE (loword) & 1) << 1) - 1) << RANGE_SHIFT)) + & (((1 << RANGE_SHIFT) * NUM_BAND_COLORS) - 1); + } + + MakeStorms (4 + ((COUNT)Random () & 3) + 1, DepthArray); + + DitherMap (DepthArray); +} + +static void +ValidateMap (PSBYTE DepthArray) +{ + BYTE state; + BYTE pixel_count[2], lb[2]; + SBYTE last_byte; + COUNT i; + register PSBYTE lpDst; + + i = MAP_WIDTH - 1; + lpDst = DepthArray; + last_byte = *lpDst++; + state = pixel_count[0] = pixel_count[1] = 0; + do + { + if (pixel_count[state]++ == 0) + lb[state] = last_byte; + + if (last_byte > *lpDst) + { + if (last_byte - *lpDst > 128) + state ^= 1; + } + else + { + if (*lpDst - last_byte > 128) + state ^= 1; + } + last_byte = *lpDst++; + } while (--i); + + i = MAP_WIDTH * MAP_HEIGHT; + lpDst = DepthArray; + if (pixel_count[0] > pixel_count[1]) + last_byte = lb[0]; + else + last_byte = lb[1]; + do + { + if (last_byte > *lpDst) + { + if (last_byte - *lpDst > 128) + *lpDst = last_byte; + } + else + { + if (*lpDst - last_byte > 128) + *lpDst = last_byte; + } + last_byte = *lpDst++; + } while (--i); +} + +void +GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth) +{ + RECT r; + DWORD old_seed; + PLANDATAPTR PlanDataPtr; + + if (IsEarth) + { + pSolarSysState->TopoFrame = CaptureDrawable ( + LoadGraphic (EARTH_MASK_ANIM) + ); + return; + } + + old_seed = SeedRandom (pPlanetDesc->rand_seed); + + PlanDataPtr = &PlanData[ + pPlanetDesc->data_index & ~PLANET_SHIELDED + ]; + r.corner.x = r.corner.y = 0; + r.extent.width = MAP_WIDTH; + r.extent.height = MAP_HEIGHT; + if (pSolarSysState->hTopoData == 0) + { + pSolarSysState->hTopoData = AllocResourceData (MAP_WIDTH * MAP_HEIGHT, 0); + LockResourceData (pSolarSysState->hTopoData, &pSolarSysState->lpTopoData); + } + if (pSolarSysState->lpTopoData) + { + COUNT i; + + memset (pSolarSysState->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT); + switch (PLANALGO (PlanDataPtr->Type)) + { + case GAS_GIANT_ALGO: + MakeGasGiant (PlanDataPtr->num_faults, + pSolarSysState->lpTopoData, &r, PlanDataPtr->fault_depth); + break; + case TOPO_ALGO: + case CRATERED_ALGO: + if (PlanDataPtr->num_faults) + DeltaTopography (PlanDataPtr->num_faults, + pSolarSysState->lpTopoData, &r, PlanDataPtr->fault_depth); + + for (i = 0; i < PlanDataPtr->num_blemishes; ++i) + { + RECT crater_r; + UWORD loword; + + loword = LOWORD (Random ()); + switch (HIBYTE (loword) & 31) + { + case 0: + crater_r.extent.width = + (LOBYTE (loword) % (MAP_HEIGHT >> 2)) + + (MAP_HEIGHT >> 2); + break; + case 1: + case 2: + case 3: + case 4: + crater_r.extent.width = + (LOBYTE (loword) % (MAP_HEIGHT >> 3)) + + (MAP_HEIGHT >> 3); + break; + default: + crater_r.extent.width = + (LOBYTE (loword) % (MAP_HEIGHT >> 4)) + + 4; + break; + } + + loword = LOWORD (Random ()); + crater_r.extent.height = crater_r.extent.width; + crater_r.corner.x = HIBYTE (loword) + % (MAP_WIDTH - crater_r.extent.width); + crater_r.corner.y = LOBYTE (loword) + % (MAP_HEIGHT - crater_r.extent.height); + MakeCrater (&crater_r, pSolarSysState->lpTopoData, + PlanDataPtr->fault_depth << 2, + -(PlanDataPtr->fault_depth << 2), + FALSE); + } + + if (PLANALGO (PlanDataPtr->Type) == CRATERED_ALGO) + DitherMap (pSolarSysState->lpTopoData); + ValidateMap (pSolarSysState->lpTopoData); + break; + } + + { + CONTEXT OldContext; + + OldContext = SetContext (TaskContext); + +#if 0 + pSolarSysState->PlanetFrameArray[1] = CaptureDrawable ( + CreateDrawable (WANT_MASK, + MAP_WIDTH + ((MAP_WIDTH >> 1) - 1), + MAP_HEIGHT, + 3) + ); +#endif + pSolarSysState->TopoFrame = CaptureDrawable ( + CreateDrawable (WANT_PIXMAP, MAP_WIDTH, MAP_HEIGHT, 1) + ); + pSolarSysState->OrbitalCMap = CaptureColorMap ( + LoadColorMap (PlanDataPtr->CMapInstance) + ); + pSolarSysState->XlatRef = CaptureStringTable ( + LoadStringTable (PlanDataPtr->XlatTabInstance) + ); + + if (pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature > HOT_THRESHOLD) + { + pSolarSysState->OrbitalCMap = SetAbsColorMapIndex ( + pSolarSysState->OrbitalCMap, 2 + ); + pSolarSysState->XlatRef = SetAbsStringTableIndex (pSolarSysState->XlatRef, 2); + } + else if (pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature > COLD_THRESHOLD) + { + pSolarSysState->OrbitalCMap = SetAbsColorMapIndex ( + pSolarSysState->OrbitalCMap, 1 + ); + pSolarSysState->XlatRef = SetAbsStringTableIndex (pSolarSysState->XlatRef, 1); + } + pSolarSysState->XlatPtr = GetStringAddress (pSolarSysState->XlatRef); + + RenderTopography (FALSE); +#if 0 + RenderLevelMasks (); +#endif + + SetContext (OldContext); + } + } + + SeedRandom (old_seed); + + SetPlanetMusic (pPlanetDesc->data_index & ~PLANET_SHIELDED); +} + +int +rotate_planet_task(void *blah) +{ + SIZE i; + DWORD TimeIn; + PSOLARSYS_STATE pSS; + BOOLEAN repair, zooming; + + repair = FALSE; + zooming = TRUE; + + pSS = pSolarSysState; + while (((PSOLARSYS_STATE volatile)pSS)->MenuState.Initialized < 2) + TaskSwitch (); + + SetPlanetTilt ((pSS->SysInfo.PlanetInfo.AxialTilt << 8) / 360); + + i = 1 - ((pSS->SysInfo.PlanetInfo.AxialTilt & 1) << 1); + TimeIn = GetTimeCounter (); + for (;;) + { + BYTE view_index; + COORD x; + + if (i > 0) + x = 0; + else + x = MAP_WIDTH - 1; + view_index = MAP_WIDTH; + do + { + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + if (((PSOLARSYS_STATE volatile)pSS)->MenuState.Initialized <= 3 + && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + OldContext = SetContext (SpaceContext); + BatchGraphics (); + if (repair) + { + RECT r; + + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT - MAP_HEIGHT; + RepairBackRect (&r); + } + repair = RotatePlanet (x, SIS_SCREEN_WIDTH >> 1, (148 - SIS_ORG_Y) >> 1); + + UnbatchGraphics (); + SetContext (OldContext); + if (!repair && zooming) + { + zooming = FALSE; + ++pSS->MenuState.Initialized; + } + x += i; + } + ClearSemaphore (&GraphicsSem); + + TimeIn = SleepTask (TimeIn + (ONE_SECOND * 5 / MAP_WIDTH)); + } while (--view_index); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} diff --git a/sc2/src/sc2code/planets/planmap.c b/sc2/src/sc2code/planets/planmap.c new file mode 100644 index 000000000..317ae780d --- /dev/null +++ b/sc2/src/sc2code/planets/planmap.c @@ -0,0 +1,248 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "gfxlib.h" +#include "scan.h" +#include "libs/compiler.h" +#include "libs/graphics/drawable.h" + +typedef struct +{ + BYTE bit0, bit1, bit2, bit3; + COUNT index0, index1, index2, index3; +} MAP_BLOCK; + +BOOLEAN +MapMask (FRAMEPTR SrcFramePtr, FRAMEPTR DstFramePtr, PRECT pSrcRect, + PSCAN_BLOCK pscan_block) +{ + COUNT num_scans; + COORD loc_x, x; + PBYTE lpSrcMask, lpDstMask; + SIZE width, height, src_error, src_delta, src_bump; + COUNT src_mask_incr, src_byte_count, dst_byte_count; + MAP_BLOCK SrcBlock; + PPOINT point_array; + PSCAN_DESC scan_array; + + loc_x = pSrcRect->corner.x; + width = pSrcRect->extent.width; + height = pSrcRect->extent.height; + + src_mask_incr = SCAN_WIDTH (GetFrameWidth (SrcFramePtr)); + lpSrcMask = (BYTE *)SrcFramePtr + SrcFramePtr->DataOffs; + if (0) + lpSrcMask += GetFrameWidth (SrcFramePtr) + * GetFrameHeight (SrcFramePtr); + src_byte_count = src_mask_incr + * GetFrameHeight (SrcFramePtr); + + lpDstMask = (BYTE *)DstFramePtr + DstFramePtr->DataOffs; + if (0) + lpDstMask += GetFrameWidth (DstFramePtr) + * GetFrameHeight (DstFramePtr); + dst_byte_count = SCAN_WIDTH (GetFrameWidth (DstFramePtr)) + * GetFrameHeight (DstFramePtr); + memset (lpDstMask, 0, dst_byte_count * 3); + + x = loc_x + (width >> 1); + SrcBlock.bit0 = SrcBlock.bit1 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (x)); + SrcBlock.index0 = SrcBlock.index1 = BYTE_POS (x); + SrcBlock.bit2 = (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (loc_x)); + SrcBlock.index2 = BYTE_POS (loc_x); + x = loc_x + width - 1; + SrcBlock.bit3 = (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (x)); + SrcBlock.index3 = BYTE_POS (x); + + num_scans = pscan_block->num_scans; + + src_delta = (height - 1) << 1; + src_bump = (num_scans - pscan_block->num_same_scans - 1) << 1; + src_error = src_bump; + + point_array = pscan_block->line_base; + scan_array = pscan_block->scan_base; + do + { + COORD y; + + y = scan_array->num_dots >> 1; + if (y) + { + COORD offs_x, offs_y; + SIZE error_term, bump, incr; + PPOINT pdot0, pdot1, pdot2, pdot3; + SIZE ig, idgr, idgd; + MAP_BLOCK SBlock, DBlock; + + offs_x = scan_array->start.x; + offs_y = scan_array->start.y; + pdot0 = pdot1 = &point_array[scan_array->start_dot + y]; + pdot2 = &point_array[scan_array->start_dot]; + pdot3 = &point_array[scan_array->start_dot + scan_array->num_dots - 1]; + + x = pdot0->x + offs_x; + DBlock.bit0 = DBlock.bit1 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (x)); + DBlock.index0 = DBlock.index1 = BYTE_POS (x) + pdot0->y + offs_y; + x = pdot2->x + offs_x; + DBlock.bit2 = (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (x)); + DBlock.index2 = BYTE_POS (x) + pdot2->y + offs_y; + x = pdot3->x + offs_x; + DBlock.bit3 = (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (x)); + DBlock.index3 = BYTE_POS (x) + pdot3->y + offs_y; + + SBlock = SrcBlock; + + incr = scan_array->dots_per_semi << 1; + bump = width << 1; + error_term = width; + + x = 0; + ig = (y << 1) - 3; + idgr = -6; + idgd = (y << 2) - 10; + do + { + if (lpSrcMask[SBlock.index0] & SBlock.bit0) + lpDstMask[DBlock.index0] |= DBlock.bit0; + SBlock.index0 += src_byte_count; + DBlock.index0 += dst_byte_count; + if (lpSrcMask[SBlock.index0] & SBlock.bit0) + lpDstMask[DBlock.index0] |= DBlock.bit0; + SBlock.index0 += src_byte_count; + DBlock.index0 += dst_byte_count; + if (lpSrcMask[SBlock.index0] & SBlock.bit0) + lpDstMask[DBlock.index0] |= DBlock.bit0; + if ((SBlock.bit0 >>= 1) == 0) + { + SBlock.bit0 = (BYTE)0x80; + ++SBlock.index0; + } + SBlock.index0 -= src_byte_count << 1; + DBlock.index0 -= dst_byte_count << 1; + + if (lpSrcMask[SBlock.index1] & SBlock.bit1) + lpDstMask[DBlock.index1] |= DBlock.bit1; + SBlock.index1 += src_byte_count; + DBlock.index1 += dst_byte_count; + if (lpSrcMask[SBlock.index1] & SBlock.bit1) + lpDstMask[DBlock.index1] |= DBlock.bit1; + SBlock.index1 += src_byte_count; + DBlock.index1 += dst_byte_count; + if (lpSrcMask[SBlock.index1] & SBlock.bit1) + lpDstMask[DBlock.index1] |= DBlock.bit1; + if ((SBlock.bit1 <<= 1) == 0) + { + SBlock.bit1 = (BYTE)0x01; + --SBlock.index1; + } + SBlock.index1 -= src_byte_count << 1; + DBlock.index1 -= dst_byte_count << 1; + + if (lpSrcMask[SBlock.index2] & SBlock.bit2) + lpDstMask[DBlock.index2] |= DBlock.bit2; + SBlock.index2 += src_byte_count; + DBlock.index2 += dst_byte_count; + if (lpSrcMask[SBlock.index2] & SBlock.bit2) + lpDstMask[DBlock.index2] |= DBlock.bit2; + SBlock.index2 += src_byte_count; + DBlock.index2 += dst_byte_count; + if (lpSrcMask[SBlock.index2] & SBlock.bit2) + lpDstMask[DBlock.index2] |= DBlock.bit2; + if ((SBlock.bit2 >>= 1) == 0) + { + SBlock.bit2 = (BYTE)0x80; + ++SBlock.index2; + } + SBlock.index2 -= src_byte_count << 1; + DBlock.index2 -= dst_byte_count << 1; + + if (lpSrcMask[SBlock.index3] & SBlock.bit3) + lpDstMask[DBlock.index3] |= DBlock.bit3; + SBlock.index3 += src_byte_count; + DBlock.index3 += dst_byte_count; + if (lpSrcMask[SBlock.index3] & SBlock.bit3) + lpDstMask[DBlock.index3] |= DBlock.bit3; + SBlock.index3 += src_byte_count; + DBlock.index3 += dst_byte_count; + if (lpSrcMask[SBlock.index3] & SBlock.bit3) + lpDstMask[DBlock.index3] |= DBlock.bit3; + if ((SBlock.bit3 <<= 1) == 0) + { + SBlock.bit3 = (BYTE)0x01; + --SBlock.index3; + } + SBlock.index3 -= src_byte_count << 1; + DBlock.index3 -= dst_byte_count << 1; + + if ((error_term -= incr) <= 0) + { + error_term += bump; + if (ig >= 0) + { + ig += idgr; + idgd -= 4; + } + else + { + ig += idgd; + idgd -= 8; + --y; + ++pdot2; + loc_x = pdot2->x + offs_x; + DBlock.bit2 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (loc_x)); + DBlock.index2 = BYTE_POS (loc_x) + pdot2->y + offs_y; + --pdot3; + loc_x = pdot3->x + offs_x; + DBlock.bit3 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (loc_x)); + DBlock.index3 = BYTE_POS (loc_x) + pdot3->y + offs_y; + } + idgr -= 4; + ++x; + ++pdot0; + loc_x = pdot0->x + offs_x; + DBlock.bit0 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (loc_x)); + DBlock.index0 = BYTE_POS (loc_x) + pdot0->y + offs_y; + --pdot1; + loc_x = pdot1->x + offs_x; + DBlock.bit1 = + (BYTE)((BYTE)0x80 >> (BYTE)BYTE_OFFS (loc_x)); + DBlock.index1 = BYTE_POS (loc_x) + pdot1->y + offs_y; + } + } while (y >= x); + } + + if ((src_error -= src_delta) <= 0) + { + if (--height > 0) + { + src_error += src_bump; + lpSrcMask += src_mask_incr; + } + } + ++scan_array; + } while (--num_scans); + + return (TRUE); +} + diff --git a/sc2/src/sc2code/planets/planscan.c b/sc2/src/sc2code/planets/planscan.c new file mode 100644 index 000000000..e2d65cf16 --- /dev/null +++ b/sc2/src/sc2code/planets/planscan.c @@ -0,0 +1,309 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "graphics/gfxintrn.h" +#include "scan.h" +#include "units.h" + +void +GenerateRotatedScans (FRAMEPTR FramePtr, PSCAN_BLOCK pscan_block, COUNT + angle) +{ + SIZE width, height, dst_mask_incr; + PBYTE lpBase; + SIZE cosA1xcosA2, sinA1xcosA2, + sinA1xsinA2, cosA1xsinA2; + POINT center; + LINE left_edge, right_edge; + SIZE delta_x0, delta_y0, delta_x1, delta_y1; + SIZE xincr0, yincr0, xincr1, yincr1; + SIZE error0; + SIZE xerror1, yerror1; + SIZE bump0, bump1, nd, num_dots0, num_dots1; + PPOINT point_array; + PSCAN_DESC scan_array; + + width = GetFrameWidth (FramePtr); + height = GetFrameHeight (FramePtr); + dst_mask_incr = SCAN_WIDTH (width); + lpBase = (PBYTE)FramePtr + FramePtr->DataOffs; + if (0) + lpBase += width * height; + + center.x = width >> 1; + center.y = height >> 1; + + if (width > height) + bump0 = (width >> 1); + else + bump0 = (height >> 1); + bump0 += 4; /* allow for a little extra room */ + + cosA1xcosA2 = sinA1xcosA2 = COSINE (angle, bump0); + sinA1xsinA2 = cosA1xsinA2 = SINE (angle, bump0); + left_edge.first.x = (-cosA1xcosA2 - -sinA1xsinA2) + center.x; + left_edge.first.y = (-cosA1xsinA2 + -sinA1xcosA2) + center.y; + left_edge.second.x = (-cosA1xcosA2 - sinA1xsinA2) + center.x; + left_edge.second.y = (-cosA1xsinA2 + sinA1xcosA2) + center.y; + right_edge.first.x = (cosA1xcosA2 - -sinA1xsinA2) + center.x; + right_edge.first.y = (cosA1xsinA2 + -sinA1xcosA2) + center.y; + right_edge.second.x = (cosA1xcosA2 - sinA1xsinA2) + center.x; + right_edge.second.y = (cosA1xsinA2 + sinA1xcosA2) + center.y; + + delta_x0 = left_edge.second.x - left_edge.first.x; + if (delta_x0 >= 0) + xincr0 = 1; + else + { + xincr0 = -1; + delta_x0 = -delta_x0; + } + delta_y0 = left_edge.second.y - left_edge.first.y; + if (delta_y0 >= 0) + yincr0 = 1; + else + { + yincr0 = -1; + delta_y0 = -delta_y0; + } + + num_dots0 = delta_x0 + delta_y0; /* four connect */ + delta_x0 <<= 1; + error0 = bump0 = num_dots0 << 1; + + delta_x1 = right_edge.first.x - left_edge.first.x; + if (delta_x1 >= 0) + xincr1 = 1; + else + { + xincr1 = -1; + delta_x1 = -delta_x1; + } + delta_y1 = right_edge.first.y - left_edge.first.y; + if (delta_y1 >= 0) + yincr1 = 1; + else + { + yincr1 = -1; + delta_y1 = -delta_y1; + } + + if (delta_x1 >= delta_y1) + { + num_dots1 = delta_x1; + delta_x1 <<= 1; + delta_y1 <<= 1; + bump1 = delta_x1; + } + else + { + num_dots1 = delta_y1; + delta_x1 <<= 1; + delta_y1 <<= 1; + bump1 = delta_y1; + } + +#ifdef DEBUG +{ +LINE loc_line, loc_left_edge, loc_right_edge; + +loc_left_edge = left_edge; +loc_left_edge.first.x += 160 - center.x; +loc_left_edge.first.y += 100 - center.y; +loc_left_edge.second.x += 160 - center.x; +loc_left_edge.second.y += 100 - center.y; +loc_right_edge = right_edge; +loc_right_edge.first.x += 160 - center.x; +loc_right_edge.first.y += 100 - center.y; +loc_right_edge.second.x += 160 - center.x; +loc_right_edge.second.y += 100 - center.y; + +loc_line = loc_left_edge; +DrawLine (&loc_line); +loc_line.second = loc_right_edge.first; +DrawLine (&loc_line); +loc_line.first = loc_right_edge.second; +DrawLine (&loc_line); +loc_line.second = loc_left_edge.second; +DrawLine (&loc_line); +} +#endif /* DEBUG */ + + pscan_block->num_same_scans = 0; + + point_array = pscan_block->line_base; + left_edge.second.x = left_edge.second.y = 0; + xerror1 = yerror1 = nd = num_dots1; + do + { + *point_array++ = left_edge.second; + if ((xerror1 -= delta_x1) <= 0) + { + left_edge.second.x += xincr1; + xerror1 += bump1; + } + if ((yerror1 -= delta_y1) <= 0) + { + left_edge.second.y += yincr1 * dst_mask_incr; + yerror1 += bump1; + } + + } while (nd--); + + scan_array = pscan_block->scan_base; + do + { + BYTE on; + PBYTE lpScan; + + on = 0; + left_edge.second = left_edge.first; + lpScan = lpBase + (left_edge.second.y * dst_mask_incr); + + xerror1 = yerror1 = nd = num_dots1; +#ifdef DEBUG +SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C)); +#endif /* DEBUG */ + do + { +#ifdef DEBUG +POINT pt; +pt.x = left_edge.second.x + 160 - center.x; +pt.y = left_edge.second.y + 100 - center.y; +#endif /* DEBUG */ + if (!(on & 1)) + { + if (left_edge.second.x >= 0 && left_edge.second.y >= 0 + && left_edge.second.x < width + && left_edge.second.y < height + && (lpScan[BYTE_POS (left_edge.second.x)] + & (BYTE)((BYTE)0x80 >> BYTE_OFFS (left_edge.second.x)))) + { +#ifdef DEBUG +SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); +DrawPoint (&pt); +#endif /* DEBUG */ + scan_array->start = left_edge.first; + scan_array->start.y *= dst_mask_incr; + + scan_array->start_dot = num_dots1 - nd; + scan_array->num_dots = nd; + + ++on; + } +#ifdef DEBUG +else +DrawPoint (&pt); +#endif /* DEBUG */ + } + else + { + if (left_edge.second.x < 0 || left_edge.second.y < 0 + || left_edge.second.x >= width + || left_edge.second.y >= height + || !(lpScan[BYTE_POS (left_edge.second.x)] + & (BYTE)((BYTE)0x80 >> BYTE_OFFS (left_edge.second.x)))) + { +#ifdef DEBUG +SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C)); +#endif /* DEBUG */ + scan_array->num_dots -= nd; + /* calculate number of dots in semi-circle */ + scan_array->dots_per_semi = (SIZE)((DWORD)(scan_array->num_dots + * SCALED_ROOT_TWO) >> SCALE_FACTOR); + if (on > 1) + { + scan_array->num_dots |= SAME_SCAN; + ++pscan_block->num_same_scans; + } +#ifdef DEBUG +printf ("<%d, %d>-<%d, %d>, %d, %d, %u%s\n", +scan_array->start.x, scan_array->start.y, +scan_array->end.x, scan_array->end.y, +scan_array->xerror, scan_array->yerror, +scan_array->num_dots & ~SAME_SCAN, +(scan_array->num_dots & SAME_SCAN) ? ", SAME SCAN" : ""); +#endif /* DEBUG */ + ++scan_array; + + ++on; + } +#ifdef DEBUG +DrawPoint (&pt); +#endif /* DEBUG */ + } + + if ((xerror1 -= delta_x1) <= 0) + { + left_edge.second.x += xincr1; + xerror1 += bump1; + } + if ((yerror1 -= delta_y1) <= 0) + { + left_edge.second.y += yincr1; + yerror1 += bump1; + + lpScan = lpBase + (left_edge.second.y * dst_mask_incr); + } + + } while (nd--); + if (on & 1) + { + scan_array->num_dots -= nd; + /* calculate number of dots in semi-circle */ + scan_array->dots_per_semi = (SIZE)((DWORD)(scan_array->num_dots + * SCALED_ROOT_TWO) >> SCALE_FACTOR); + if (on > 1) + { + scan_array->num_dots |= SAME_SCAN; + ++pscan_block->num_same_scans; + } +#ifdef DEBUG +printf ("<%d, %d>-<%d, %d>, %d, %d, %u\n", +scan_array->start.x, scan_array->start.y, +scan_array->end.x, scan_array->end.y, +scan_array->xerror, scan_array->yerror, +scan_array->num_dots & ~SAME_SCAN, +(scan_array->num_dots & SAME_SCAN) ? ", SAME SCAN" : ""); +#endif /* DEBUG */ + ++scan_array; + } + + if ((error0 -= delta_x0) > 0) + left_edge.first.y += yincr0; + else + { + left_edge.first.x += xincr0; + error0 += bump0; + } + + } while (num_dots0--); + + pscan_block->num_scans = (COUNT)(scan_array - pscan_block->scan_base); +#ifdef DEBUG +{ +extern DWORD AnyButtonPress (BOOLEAN CheckSpecial); +printf ("num_scans = %u\n", pscan_block->num_scans); +while (!AnyButtonPress (TRUE)) + ; +} +#endif /* DEBUG */ +} + + + diff --git a/sc2/src/sc2code/planets/pstarmap.c b/sc2/src/sc2code/planets/pstarmap.c new file mode 100644 index 000000000..1a2d982c7 --- /dev/null +++ b/sc2/src/sc2code/planets/pstarmap.c @@ -0,0 +1,1334 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void RepairBackRect (PRECT pRect); + +//End Added by Chris + +#define UNIVERSE_TO_DISPX(ux) \ + (COORD)(((((long)(ux) - pMenuState->flash_rect1.corner.x) \ + << LOBYTE (pMenuState->delta_item)) \ + * SIS_SCREEN_WIDTH / (MAX_X_UNIVERSE + 1)) + ((SIS_SCREEN_WIDTH - 1) >> 1)) +#define UNIVERSE_TO_DISPY(uy) \ + (COORD)(((((long)pMenuState->flash_rect1.corner.y - (uy)) \ + << LOBYTE (pMenuState->delta_item)) \ + * SIS_SCREEN_HEIGHT / (MAX_Y_UNIVERSE + 1)) + ((SIS_SCREEN_HEIGHT - 1) >> 1)) +#define DISP_TO_UNIVERSEX(dx) \ + ((COORD)((((long)((dx) - ((SIS_SCREEN_WIDTH - 1) >> 1)) \ + * (MAX_X_UNIVERSE + 1)) >> LOBYTE (pMenuState->delta_item)) \ + / SIS_SCREEN_WIDTH) + pMenuState->flash_rect1.corner.x) +#define DISP_TO_UNIVERSEY(dy) \ + ((COORD)((((long)(((SIS_SCREEN_HEIGHT - 1) >> 1) - (dy)) \ + * (MAX_Y_UNIVERSE + 1)) >> LOBYTE (pMenuState->delta_item)) \ + / SIS_SCREEN_HEIGHT) + pMenuState->flash_rect1.corner.y) + +static BOOLEAN transition_pending; + +int +flash_cursor_func(void *blah) +{ + BYTE c, val; + POINT universe; + STAMP s; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + universe = CurStarDescPtr->star_pt; + else + { + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + } + s.frame = IncFrameIndex (pMenuState->CurFrame); + + c = 0x00; + val = -0x02; + for (;;) + { + DWORD TimeIn; + COLOR OldColor; + CONTEXT OldContext; + + TimeIn = GetTimeCounter (); + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + + if (c == 0x00 || c == 0x1A) + val = -val; + c += val; + OldColor = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (c, c, c), c)); + s.origin.x = UNIVERSE_TO_DISPX (universe.x); + s.origin.y = UNIVERSE_TO_DISPY (universe.y); + DrawFilledStamp (&s); + SetContextForeGroundColor (OldColor); + + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + SleepTask (TimeIn + (ONE_SECOND >> 4)); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return (0); +} + +static void +DrawCursor (COORD curs_x, COORD curs_y) +{ + STAMP s; + + s.origin.x = curs_x; + s.origin.y = curs_y; + s.frame = pMenuState->CurFrame; + + DrawStamp (&s); +} + +static void +DrawAutoPilot (PPOINT pDstPt) +{ + SIZE dx, dy, + xincr, yincr, + xerror, yerror, + cycle, delta; + POINT pt; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + pt = CurStarDescPtr->star_pt; + else + { + pt.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + pt.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + } + pt.x = UNIVERSE_TO_DISPX (pt.x); + pt.y = UNIVERSE_TO_DISPY (pt.y); + + dx = UNIVERSE_TO_DISPX (pDstPt->x) - pt.x; + if (dx >= 0) + xincr = 1; + else + { + xincr = -1; + dx = -dx; + } + dx <<= 1; + + dy = UNIVERSE_TO_DISPY (pDstPt->y) - pt.y; + if (dy >= 0) + yincr = 1; + else + { + yincr = -1; + dy = -dy; + } + dy <<= 1; + + if (dx >= dy) + cycle = dx; + else + cycle = dy; + delta = xerror = yerror = cycle >> 1; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x04, 0x04, 0x1F), 0x01)); + + delta &= ~1; + while (delta--) + { + if (!(delta & 1)) + DrawPoint (&pt); + + if ((xerror -= dx) <= 0) + { + pt.x += xincr; + xerror += cycle; + } + if ((yerror -= dy) <= 0) + { + pt.y += yincr; + yerror += cycle; + } + } +} + +static void +GetSphereRect (EXTENDED_SHIP_FRAGMENTPTR StarShipPtr, PRECT pRect, PRECT + pRepairRect) +{ + long diameter; + + diameter = (long)( + StarShipPtr->ShipInfo.known_strength + * SPHERE_RADIUS_INCREMENT + ); + pRect->extent.width = UNIVERSE_TO_DISPX (diameter) + - UNIVERSE_TO_DISPX (0); + if (pRect->extent.width < 0) + pRect->extent.width = -pRect->extent.width; + else if (pRect->extent.width == 0) + pRect->extent.width = 1; + pRect->extent.height = UNIVERSE_TO_DISPY (diameter) + - UNIVERSE_TO_DISPY (0); + if (pRect->extent.height < 0) + pRect->extent.height = -pRect->extent.height; + else if (pRect->extent.height == 0) + pRect->extent.height = 1; + + pRect->corner.x = UNIVERSE_TO_DISPX ( + StarShipPtr->ShipInfo.known_loc.x + ); + pRect->corner.y = UNIVERSE_TO_DISPY ( + StarShipPtr->ShipInfo.known_loc.y + ); + pRect->corner.x -= pRect->extent.width >> 1; + pRect->corner.y -= pRect->extent.height >> 1; + + { + TEXT t; + STRING locString; + + SetContextFont (TinyFont); + + t.baseline.x = pRect->corner.x + (pRect->extent.width >> 1); + t.baseline.y = pRect->corner.y + (pRect->extent.height >> 1) - 1; + t.align = ALIGN_CENTER; + locString = SetAbsStringTableIndex ( + StarShipPtr->ShipInfo.race_strings, 1 + ); + t.CharCount = GetStringLength (locString); + t.pStr = (UNICODE *)GetStringAddress (locString); + TextRect (&t, pRepairRect, NULL_PTR); + + if (pRepairRect->corner.x <= 0) + pRepairRect->corner.x = 1; + else if (pRepairRect->corner.x + pRepairRect->extent.width >= SIS_SCREEN_WIDTH) + pRepairRect->corner.x = SIS_SCREEN_WIDTH - pRepairRect->extent.width - 1; + if (pRepairRect->corner.y <= 0) + pRepairRect->corner.y = 1; + else if (pRepairRect->corner.y + pRepairRect->extent.height >= SIS_SCREEN_HEIGHT) + pRepairRect->corner.y = SIS_SCREEN_HEIGHT - pRepairRect->extent.height - 1; + + BoxUnion (pRepairRect, pRect, pRepairRect); + } +} + +static void +DrawStarMap (COUNT race_update, PRECT pClipRect) +{ +#define GRID_DELTA 500 + SIZE i; + COUNT which_space; + long diameter; + RECT r, old_r; + STAMP s; + FRAME star_frame; + STAR_DESCPTR SDPtr; + FRAME OldFrame; + BOOLEAN draw_cursor; + + if (pClipRect == (PRECT)-1) + { + pClipRect = 0; + draw_cursor = FALSE; + } + else + { + SetSemaphore (&GraphicsSem); + draw_cursor = TRUE; + } + + SetContext (SpaceContext); + if (pClipRect) + { + GetContextClipRect (&old_r); + pClipRect->corner.x += old_r.corner.x; + pClipRect->corner.y += old_r.corner.y; + SetContextClipRect (pClipRect); + pClipRect->corner.x -= old_r.corner.x; + pClipRect->corner.y -= old_r.corner.y; + SetFrameHot (Screen, + MAKE_HOT_SPOT (pClipRect->corner.x, pClipRect->corner.y)); + } + OldFrame = SetContextBGFrame ((FRAME)0); + BatchGraphics (); + + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + which_space = GET_GAME_STATE (ARILOU_SPACE_SIDE); + + if (which_space <= 1) + { + SDPtr = &star_array[0]; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x7), 0x57)); + SetContextBackGroundColor (BLACK_COLOR); + } + else + { + SDPtr = &star_array[NUM_SOLAR_SYSTEMS + 1]; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0xB, 0x00), 0x6D)); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x8, 0x00), 0x6E)); + } + ClearDrawable (); + + if (race_update == 0 + && which_space < 2 + && (diameter = (long)GLOBAL_SIS (FuelOnBoard) << 1)) + { + COLOR OldColor; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + r.corner = CurStarDescPtr->star_pt; + else + { + r.corner.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + r.corner.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + } + + r.extent.width = UNIVERSE_TO_DISPX (diameter) + - UNIVERSE_TO_DISPX (0); + if (r.extent.width < 0) + r.extent.width = -r.extent.width; + r.extent.height = UNIVERSE_TO_DISPY (diameter) + - UNIVERSE_TO_DISPY (0); + if (r.extent.height < 0) + r.extent.height = -r.extent.height; + + r.corner.x = UNIVERSE_TO_DISPX (r.corner.x) + - (r.extent.width >> 1); + r.corner.y = UNIVERSE_TO_DISPY (r.corner.y) + - (r.extent.height >> 1); + + OldColor = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x3, 0x3, 0x3), 0x22)); + DrawFilledOval (&r); + SetContextForeGroundColor (OldColor); + } + + for (i = MAX_Y_UNIVERSE + 1; i >= 0; i -= GRID_DELTA) + { + SIZE j; + + r.corner.x = UNIVERSE_TO_DISPX (0); + r.corner.y = UNIVERSE_TO_DISPY (i); + r.extent.width = SIS_SCREEN_WIDTH << LOBYTE (pMenuState->delta_item); + r.extent.height = 1; + DrawFilledRectangle (&r); + + r.corner.y = UNIVERSE_TO_DISPY (MAX_Y_UNIVERSE + 1); + r.extent.width = 1; + r.extent.height = SIS_SCREEN_HEIGHT << LOBYTE (pMenuState->delta_item); + for (j = MAX_X_UNIVERSE + 1; j >= 0; j -= GRID_DELTA) + { + r.corner.x = UNIVERSE_TO_DISPX (j); + DrawFilledRectangle (&r); + } + } + + star_frame = SetRelFrameIndex (pMenuState->CurFrame, 2); + if (which_space <= 1) + { + COUNT index; + HSTARSHIP hStarShip, hNextShip; + COLOR race_colors[] = + { + RACE_COLORS + }; + + for (index = 0, + hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip != 0; ++index, hStarShip = hNextShip) + { + EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + if (StarShipPtr->ShipInfo.known_strength) + { + RECT repair_r; + + GetSphereRect (StarShipPtr, &r, &repair_r); + if (r.corner.x < SIS_SCREEN_WIDTH + && r.corner.y < SIS_SCREEN_HEIGHT + && r.corner.x + r.extent.width > 0 + && r.corner.y + r.extent.height > 0 + && (pClipRect == 0 + || (repair_r.corner.x < pClipRect->corner.x + pClipRect->extent.width + && repair_r.corner.y < pClipRect->corner.y + pClipRect->extent.height + && repair_r.corner.x + repair_r.extent.width > pClipRect->corner.x + && repair_r.corner.y + repair_r.extent.height > pClipRect->corner.y))) + { + COLOR c; + TEXT t; + STRING locString; + + c = race_colors[index]; + if (index + 1 == race_update) + SetContextForeGroundColor (WHITE_COLOR); + else + SetContextForeGroundColor (c); + DrawOval (&r, 0); + + SetContextFont (TinyFont); + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + (r.extent.height >> 1) - 1; + t.align = ALIGN_CENTER; + locString = SetAbsStringTableIndex ( + StarShipPtr->ShipInfo.race_strings, 1 + ); + t.CharCount = GetStringLength (locString); + t.pStr = (UNICODE *)GetStringAddress (locString); + TextRect (&t, &r, NULL_PTR); + + if (r.corner.x <= 0) + t.baseline.x -= r.corner.x - 1; + else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) + t.baseline.x -= (r.corner.x + r.extent.width) + - SIS_SCREEN_WIDTH + 1; + if (r.corner.y <= 0) + t.baseline.y -= r.corner.y - 1; + else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) + t.baseline.y -= (r.corner.y + r.extent.height) + - SIS_SCREEN_HEIGHT + 1; + + { + BYTE r, g, b; + COLOR c32k; + + c32k = COLOR_32k (c); + r = (c32k >> (5 * 2)) & 0x1F; + if ((r += 0x03) > 0x1F) r = 0x1F; + g = (c32k >> (5 * 1)) & 0x1F; + if ((g += 0x03) > 0x1F) g = 0x1F; + b = (c32k >> (5 * 0)) & 0x1F; + if ((b += 0x03) > 0x1F) b = 0x1F; + + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (r, g, b), COLOR_256 (c) - 1) + ); + } + DrawText (&t); + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + } + + do + { + BYTE star_type; + + star_type = SDPtr->Type; + +#ifdef NOTYET +{ +UNICODE buf[40]; + +GetClusterName (SDPtr, buf); +wprintf ("%s\n", buf); +} +#endif /* NOTYET */ + s.origin.x = UNIVERSE_TO_DISPX (SDPtr->star_pt.x); + s.origin.y = UNIVERSE_TO_DISPY (SDPtr->star_pt.y); + if (which_space <= 1) + s.frame = SetRelFrameIndex (star_frame, + STAR_TYPE (star_type) + * NUM_STAR_COLORS + + STAR_COLOR (star_type)); + else if (SDPtr->star_pt.x == ARILOU_HOME_X + && SDPtr->star_pt.y == ARILOU_HOME_Y) + s.frame = SetRelFrameIndex (star_frame, + SUPER_GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); + else + s.frame = SetRelFrameIndex (star_frame, + GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); + DrawStamp (&s); + + ++SDPtr; + } while (SDPtr->star_pt.x <= MAX_X_UNIVERSE + && SDPtr->star_pt.y <= MAX_Y_UNIVERSE); + + if (GET_GAME_STATE (ARILOU_SPACE)) + { + if (which_space <= 1) + { + s.origin.x = UNIVERSE_TO_DISPX (ARILOU_SPACE_X); + s.origin.y = UNIVERSE_TO_DISPY (ARILOU_SPACE_Y); + } + else + { + s.origin.x = UNIVERSE_TO_DISPX (QUASI_SPACE_X); + s.origin.y = UNIVERSE_TO_DISPY (QUASI_SPACE_Y); + } + s.frame = SetRelFrameIndex (star_frame, + GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); + DrawStamp (&s); + } + + if (race_update == 0 + && GLOBAL (autopilot.x) != ~0 + && GLOBAL (autopilot.y) != ~0) + DrawAutoPilot (&GLOBAL (autopilot)); + + if (transition_pending) + { + GetContextClipRect (&r); + ScreenTransition (3, &r); + transition_pending = FALSE; + } + + UnbatchGraphics (); + + if (pClipRect) + { + SetContextClipRect (&old_r); + SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); + } + + SetContextBGFrame (OldFrame); + + if (race_update == 0) + { + if (draw_cursor) + { + GetContextClipRect (&r); + LoadIntoExtraScreen (&r); + DrawCursor ( + UNIVERSE_TO_DISPX (pMenuState->first_item.x), + UNIVERSE_TO_DISPY (pMenuState->first_item.y) + ); + } + } + + if (draw_cursor) + ClearSemaphore (&GraphicsSem); +} + +static void +EraseCursor (COORD curs_x, COORD curs_y) +{ + RECT r; + + GetFrameRect (pMenuState->CurFrame, &r); + + if ((r.corner.x += curs_x) < 0) + { + r.extent.width += r.corner.x; + r.corner.x = 0; + } + else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) + r.extent.width = SIS_SCREEN_WIDTH - r.corner.x; + if ((r.corner.y += curs_y) < 0) + { + r.extent.height += r.corner.y; + r.corner.y = 0; + } + else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) + r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; + +#ifndef OLD + RepairBackRect (&r); +#else /* NEW */ + r.extent.height += r.corner.y & 1; + r.corner.y &= ~1; + ClearSemaphore (&GraphicsSem); + DrawStarMap (0, &r); + SetSemaphore (&GraphicsSem); +#endif /* OLD */ +} + +static void +ZoomStarMap (SIZE dir) +{ +#define MAX_ZOOM_SHIFT 4 + if (dir > 0) + { + if (LOBYTE (pMenuState->delta_item) < MAX_ZOOM_SHIFT) + { + ++pMenuState->delta_item; + pMenuState->flash_rect1.corner = pMenuState->first_item; + + DrawStarMap (0, NULL_PTR); + SleepTask (GetTimeCounter () + (ONE_SECOND >> 3)); + } + } + else if (dir < 0) + { + if (LOBYTE (pMenuState->delta_item)) + { + if (LOBYTE (pMenuState->delta_item) > 1) + pMenuState->flash_rect1.corner = pMenuState->first_item; + else + { + pMenuState->flash_rect1.corner.x = MAX_X_UNIVERSE >> 1; + pMenuState->flash_rect1.corner.y = MAX_Y_UNIVERSE >> 1; + } + --pMenuState->delta_item; + + DrawStarMap (0, NULL_PTR); + SleepTask (GetTimeCounter () + (ONE_SECOND >> 3)); + } + } +} + +static BOOLEAN +DoMoveCursor (INPUT_STATE InputState, PMENU_STATE pMS) +{ +#define MIN_ACCEL_DELAY (ONE_SECOND / 60) +#define MAX_ACCEL_DELAY (ONE_SECOND / 8) + STAMP s; + UNICODE buf[30]; + static UNICODE last_buf; + + pMS->MenuRepeatDelay = (COUNT)pMS->CurState; + if (!pMS->Initialized) + { + pMS->Initialized = MAKE_WORD ( + KBDToUNICODE (SK_INSERT), + KBDToUNICODE (SK_DELETE) + ); + pMS->InputFunc = DoMoveCursor; + + pMS->flash_task = AddTask (flash_cursor_func, 2048); + s.origin.x = UNIVERSE_TO_DISPX (pMS->first_item.x); + s.origin.y = UNIVERSE_TO_DISPY (pMS->first_item.y); + last_buf = ~0; + buf[0] = '\0'; + goto UpdateCursorInfo; + } + else if (InputState & DEVICE_BUTTON2) + { + SetSemaphore (&GraphicsSem); + if (pMS->flash_task) + { + DeleteTask (pMS->flash_task); + pMS->flash_task = 0; + } + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + GLOBAL (autopilot) = pMS->first_item; + + DrawStarMap (0, NULL_PTR); + } + else + { + SBYTE sx, sy; + POINT pt; + SIZE ZoomIn, ZoomOut; + + ZoomIn = ZoomOut = 0; + if (InputState & DEVICE_LEFTSHIFT) + ZoomIn = 1; + else if (InputState & DEVICE_RIGHTSHIFT) + ZoomOut = 1; + + ZoomStarMap (ZoomOut - ZoomIn); + + sx = GetInputXComponent (InputState); + sy = GetInputYComponent (InputState); + if (sx == 0 && sy == 0) + { + extern INPUT_STATE OldInputState; + + if (OldInputState == 0) + pMS->CurState = MAX_ACCEL_DELAY; + } + else + { + if (pMS->CurState > MIN_ACCEL_DELAY) + --pMS->CurState; + + pt.x = UNIVERSE_TO_DISPX (pMS->first_item.x); + pt.y = UNIVERSE_TO_DISPY (pMS->first_item.y); + + s.origin.x = pt.x + sx; + s.origin.y = pt.y + sy; + + buf[0] = '\0'; + if (sx) + { + pMS->first_item.x = + DISP_TO_UNIVERSEX (s.origin.x) - sx; + while (UNIVERSE_TO_DISPX (pMS->first_item.x) == pt.x) + { + pMS->first_item.x += sx; + if (pMS->first_item.x < 0) + { + pMS->first_item.x = 0; + break; + } + else if (pMS->first_item.x > MAX_X_UNIVERSE) + { + pMS->first_item.x = MAX_X_UNIVERSE; + break; + } + } + s.origin.x = UNIVERSE_TO_DISPX (pMS->first_item.x); + } + + if (sy) + { + pMS->first_item.y = + DISP_TO_UNIVERSEY (s.origin.y) + sy; + while (UNIVERSE_TO_DISPY (pMS->first_item.y) == pt.y) + { + pMS->first_item.y -= sy; + if (pMS->first_item.y < 0) + { + pMS->first_item.y = 0; + break; + } + else if (pMS->first_item.y > MAX_Y_UNIVERSE) + { + pMS->first_item.y = MAX_Y_UNIVERSE; + break; + } + } + s.origin.y = UNIVERSE_TO_DISPY (pMS->first_item.y); + } + + if (s.origin.x < 0 || s.origin.y < 0 + || s.origin.x >= SIS_SCREEN_WIDTH + || s.origin.y >= SIS_SCREEN_HEIGHT) + { + pMS->flash_rect1.corner = pMS->first_item; + DrawStarMap (0, NULL_PTR); + + s.origin.x = UNIVERSE_TO_DISPX (pMS->first_item.x); + s.origin.y = UNIVERSE_TO_DISPY (pMS->first_item.y); + } + else + { + SetSemaphore (&GraphicsSem); + EraseCursor (pt.x, pt.y); + // ClearDrawable (); + DrawCursor (s.origin.x, s.origin.y); + ClearSemaphore (&GraphicsSem); + } + +UpdateCursorInfo: + { + STAR_DESCPTR SDPtr, BestSDPtr; + + SDPtr = BestSDPtr = 0; + while ((SDPtr = FindStar (SDPtr, &pMS->first_item, 75, 75))) + { + if (UNIVERSE_TO_DISPX (SDPtr->star_pt.x) == s.origin.x + && UNIVERSE_TO_DISPY (SDPtr->star_pt.y) == s.origin.y + && (BestSDPtr == 0 + || STAR_TYPE (SDPtr->Type) >= STAR_TYPE (BestSDPtr->Type))) + BestSDPtr = SDPtr; + } + + if (BestSDPtr) + { + pMS->first_item = BestSDPtr->star_pt; + GetClusterName (BestSDPtr, buf); + } + } + + if (GET_GAME_STATE (ARILOU_SPACE)) + { + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + pt.x = ARILOU_SPACE_X; + pt.y = ARILOU_SPACE_Y; + } + else + { + pt.x = QUASI_SPACE_X; + pt.y = QUASI_SPACE_Y; + } + + if (UNIVERSE_TO_DISPX (pt.x) == s.origin.x + && UNIVERSE_TO_DISPY (pt.y) == s.origin.y) + { + pMS->first_item = pt; + wstrcpy (buf, GAME_STRING (STAR_STRING_BASE + 132)); + } + } + + { + COUNT fuel_required; + DWORD f; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + pt = CurStarDescPtr->star_pt; + else + { + pt.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + pt.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + } + pt.x -= pMS->first_item.x; + pt.y -= pMS->first_item.y; + + f = (DWORD)((long)pt.x * pt.x + (long)pt.y * pt.y); + if (f == 0 || GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) + fuel_required = 0; + else + fuel_required = square_root (f) + (FUEL_TANK_SCALE >> 1); + SetSemaphore (&GraphicsSem); + DrawHyperCoords (pMenuState->first_item); + if (last_buf == (UNICODE) ~0 + || (buf[0] && !last_buf) || (!buf[0] && last_buf)) + { + last_buf = buf[0]; + DrawSISMessage (buf); + } + wsprintf (buf, "%s %u.%u", + GAME_STRING (NAVIGATION_STRING_BASE + 4), + fuel_required / FUEL_TANK_SCALE, + (fuel_required % FUEL_TANK_SCALE) / 10); + DrawStatusMessage (buf); + ClearSemaphore (&GraphicsSem); + } + } + } + + return (TRUE); +} + +static void +RepairMap (COUNT update_race, PRECT pLastRect, PRECT pNextRect) +{ + RECT r; + + /* make a rect big enough for text */ + r.extent.width = 50; + r.corner.x = (pNextRect->corner.x + (pNextRect->extent.width >> 1)) + - (r.extent.width >> 1); + if (r.corner.x < 0) + r.corner.x = 0; + else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) + r.corner.x = SIS_SCREEN_WIDTH - r.extent.width; + r.extent.height = 9; + r.corner.y = (pNextRect->corner.y + (pNextRect->extent.height >> 1)) + - r.extent.height; + if (r.corner.y < 0) + r.corner.y = 0; + else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) + r.corner.y = SIS_SCREEN_HEIGHT - r.extent.height; + BoxUnion (pLastRect, &r, &r); + BoxUnion (pNextRect, &r, &r); + *pLastRect = *pNextRect; + + if (r.corner.x < 0) + { + r.extent.width += r.corner.x; + r.corner.x = 0; + } + if (r.corner.x + r.extent.width > SIS_SCREEN_WIDTH) + r.extent.width = SIS_SCREEN_WIDTH - r.corner.x; + if (r.corner.y < 0) + { + r.extent.height += r.corner.y; + r.corner.y = 0; + } + if (r.corner.y + r.extent.height > SIS_SCREEN_HEIGHT) + r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; + + r.extent.height += r.corner.y & 1; + r.corner.y &= ~1; + + DrawStarMap (update_race, &r); +} + +static void +UpdateMap (void) +{ + BYTE ButtonState, VisibleChange; + BOOLEAN MapDrawn, Interrupted; + COUNT index; + HSTARSHIP hStarShip, hNextShip; + + FlushInput (); + ButtonState = 1; /* assume a button down */ + + MapDrawn = Interrupted = FALSE; + for (index = 1, + hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip; ++index, hStarShip = hNextShip) + { + EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + if (ButtonState) + { + if (!AnyButtonPress (TRUE)) + ButtonState = 0; + } + else if ((Interrupted = (BOOLEAN)( + Interrupted || AnyButtonPress (TRUE) + ))) + MapDrawn = TRUE; + + if (StarShipPtr->ShipInfo.known_strength) + { + SIZE dx, dy, delta; + RECT r, last_r, temp_r0, temp_r1; + + dx = StarShipPtr->ShipInfo.loc.x + - StarShipPtr->ShipInfo.known_loc.x; + dy = StarShipPtr->ShipInfo.loc.y + - StarShipPtr->ShipInfo.known_loc.y; + if (dx || dy) + { + SIZE xincr, yincr, + xerror, yerror, + cycle; + + if (dx >= 0) + xincr = 1; + else + { + xincr = -1; + dx = -dx; + } + dx <<= 1; + + if (dy >= 0) + yincr = 1; + else + { + yincr = -1; + dy = -dy; + } + dy <<= 1; + + if (dx >= dy) + cycle = dx; + else + cycle = dy; + delta = xerror = yerror = cycle >> 1; + + if (!MapDrawn) + { + DrawStarMap ((COUNT)~0, NULL_PTR); + MapDrawn = TRUE; + } + + GetSphereRect (StarShipPtr, &temp_r0, &last_r); + ++last_r.extent.width; + ++last_r.extent.height; + VisibleChange = FALSE; + do + { + do + { + if ((xerror -= dx) <= 0) + { + StarShipPtr->ShipInfo.known_loc.x += xincr; + xerror += cycle; + } + if ((yerror -= dy) <= 0) + { + StarShipPtr->ShipInfo.known_loc.y += yincr; + yerror += cycle; + } + GetSphereRect (StarShipPtr, &temp_r1, &r); + } while (delta-- + && ((delta & 0x1F) + || (temp_r0.corner.x == temp_r1.corner.x + && temp_r0.corner.y == temp_r1.corner.y))); + + if (ButtonState) + { + if (!AnyButtonPress (TRUE)) + ButtonState = 0; + } + else if ((Interrupted = (BOOLEAN)( + Interrupted || AnyButtonPress (TRUE) + ))) + { + MapDrawn = TRUE; + goto DoneSphereMove; + } + + ++r.extent.width; + ++r.extent.height; + if (temp_r0.corner.x != temp_r1.corner.x + || temp_r0.corner.y != temp_r1.corner.y) + { + VisibleChange = TRUE; + RepairMap (index, &last_r, &r); + } + } while (delta >= 0); + if (VisibleChange) + RepairMap ((COUNT)~0, &last_r, &r); + +DoneSphereMove: + StarShipPtr->ShipInfo.known_loc = StarShipPtr->ShipInfo.loc; + } + + delta = StarShipPtr->ShipInfo.actual_strength + - StarShipPtr->ShipInfo.known_strength; + if (delta) + { + if (!MapDrawn) + { + DrawStarMap ((COUNT)~0, NULL_PTR); + MapDrawn = TRUE; + } + + if (delta > 0) + dx = 1; + else + { + delta = -delta; + dx = -1; + } + --delta; + + GetSphereRect (StarShipPtr, &temp_r0, &last_r); + ++last_r.extent.width; + ++last_r.extent.height; + VisibleChange = FALSE; + do + { + do + { + StarShipPtr->ShipInfo.known_strength += dx; + GetSphereRect (StarShipPtr, &temp_r1, &r); + } while (delta-- + && ((delta & 0xF) + || temp_r0.extent.height == temp_r1.extent.height)); + + if (ButtonState) + { + if (!AnyButtonPress (TRUE)) + ButtonState = 0; + } + else if ((Interrupted = (BOOLEAN)( + Interrupted || AnyButtonPress (TRUE) + ))) + { + MapDrawn = TRUE; + goto DoneSphereGrowth; + } + ++r.extent.width; + ++r.extent.height; + if (temp_r0.extent.height != temp_r1.extent.height) + { + VisibleChange = TRUE; + RepairMap (index, &last_r, &r); + } + } while (delta >= 0); + if (VisibleChange || temp_r0.extent.width != temp_r1.extent.width) + RepairMap ((COUNT)~0, &last_r, &r); + +DoneSphereGrowth: + StarShipPtr->ShipInfo.known_strength = + StarShipPtr->ShipInfo.actual_strength; + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } +} + +static BOOLEAN +DoStarMap (void) +{ + SOUND OldMenuSounds; + MENU_STATE MenuState; + POINT universe; + //FRAME OldFrame; + RECT clip_r; + CONTEXT OldContext; + extern FRAME misc_data; + + pMenuState = &MenuState; + memset (pMenuState, 0, sizeof (*pMenuState)); + + MenuState.flash_rect1.corner.x = MAX_X_UNIVERSE >> 1; + MenuState.flash_rect1.corner.y = MAX_Y_UNIVERSE >> 1; + MenuState.CurFrame = SetAbsFrameIndex (misc_data, 48); + MenuState.delta_item = 0; + + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) + universe = CurStarDescPtr->star_pt; + else + { + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + } + + MenuState.first_item = GLOBAL (autopilot); + if (MenuState.first_item.x == ~0 && MenuState.first_item.y == ~0) + MenuState.first_item = universe; + + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + + MenuState.InputFunc = DoMoveCursor; + MenuState.Initialized = FALSE; + MenuState.CurState = MAX_ACCEL_DELAY; + + transition_pending = TRUE; + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + UpdateMap (); + + SetSemaphore (&GraphicsSem); + + DrawStarMap (0, (PRECT)-1); + transition_pending = FALSE; + + BatchGraphics (); + OldContext = SetContext (SpaceContext); + GetContextClipRect (&clip_r); + SetContext (OldContext); + LoadIntoExtraScreen (&clip_r); + DrawCursor ( + UNIVERSE_TO_DISPX (pMenuState->first_item.x), + UNIVERSE_TO_DISPY (pMenuState->first_item.y) + ); + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + + OldMenuSounds = MenuSounds; + MenuSounds = 0; + DoInput ((PVOID)&MenuState); + MenuSounds = OldMenuSounds; + + pMenuState = 0; + + SetSemaphore (&GraphicsSem); + + DrawHyperCoords (universe); + DrawSISMessage (NULL_PTR); + DrawStatusMessage (NULL_PTR); + + if (GLOBAL (autopilot.x) == universe.x + && GLOBAL (autopilot.y) == universe.y) + GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; + + return (GLOBAL (autopilot.x) != ~0 + && GLOBAL (autopilot.y) != ~0); +} + +BOOLEAN +DoFlagshipCommands (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (!(pMS->Initialized & 1)) + { + ChangeSolarSys (); + } + else + { + SetSemaphore (&GraphicsSem); + while (((PMENU_STATE volatile)pMS)->CurState == 0 + && (((PMENU_STATE volatile)pMS)->Initialized & 1) + && !(GLOBAL (CurrentActivity) + & (START_ENCOUNTER | END_INTERPLANETARY + | CHECK_ABORT | CHECK_LOAD)) + && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) + { + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + SetSemaphore (&GraphicsSem); + } + ClearSemaphore (&GraphicsSem); + + if (pMS->CurState) + { + BYTE NewState; + + NewState = pMS->CurState; + if ((InputState & DEVICE_BUTTON1) || LastActivity == CHECK_LOAD) + { + if (NewState != SCAN + 1 && NewState != (ROSTER + 1) + 1) + { + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + + switch (NewState - 1) + { + case SCAN: + ScanSystem (); + break; + case EQUIP_DEVICE: + { + extern BOOLEAN Devices (PMENU_STATE pMS); + + pMenuState = pMS; + if (!Devices (pMS)) + InputState &= ~DEVICE_BUTTON1; + pMenuState = 0; + if (GET_GAME_STATE (PORTAL_COUNTER)) + return (FALSE); + break; + } + case CARGO: + { + extern void Cargo + (PMENU_STATE + pMS); + + Cargo (pMS); + break; + } + case ROSTER: + { + + extern + BOOLEAN + Roster + (void); + + if (!Roster ()) + InputState &= ~DEVICE_BUTTON1; + break; + } + case ROSTER + 1: + if (GameOptions () == 0) + return (FALSE); +// else +// DrawMenuStateStrings (PM_SCAN, ROSTER + 1); + break; + case STARMAP: + { + BOOLEAN AutoPilotSet; + + SetSemaphore (&GraphicsSem); + if (++pMS->Initialized > 3) + RepairSISBorder (); + + AutoPilotSet = DoStarMap (); + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE + || (GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + ClearSemaphore (&GraphicsSem); + return (FALSE); + } + else if (pMS->Initialized <= 3) + { + ZoomSystem (); + --pMS->Initialized; + } + ClearSemaphore (&GraphicsSem); + + if (!AutoPilotSet && pMS->Initialized >= 3) + { + LoadPlanet (FALSE); + --pMS->Initialized; + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + break; + } + } + case ROSTER + 2: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + return (FALSE); + + if (pMS->Initialized <= 1) + { + pMS->Initialized = 1; + ResumeGameClock (); + } + else if (pMS->flash_task) + { + FreePlanet (); + SetSemaphore (&GraphicsSem); + LoadSolarSys (); + ZoomSystem (); + ClearSemaphore (&GraphicsSem); + } + + SetSemaphore (&GraphicsSem); + pMS->CurState = 0; + ClearSemaphore (&GraphicsSem); + break; + } + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + ; + else if (pMS->CurState) + { + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + if (InputState & DEVICE_BUTTON1) + { + pMS->CurState = (ROSTER + 2) + 1; + DrawMenuStateStrings (PM_SCAN, ROSTER + 2); + } + } + else + { + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings (PM_SCAN, ROSTER + 2); + } + } + else + { + BYTE FirstState; + + FirstState = (BYTE)(pMS->Initialized <= 1 ? STARMAP : SCAN); + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == (BYTE)(FirstState + 1)) + NewState = (ROSTER + 2) + 1; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == (ROSTER + 2) + 1) + NewState = (BYTE)(FirstState + 1); + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_SCAN, (BYTE)(NewState - 1)); + + pMS->CurState = NewState; + } + } + } + } + + return (!(GLOBAL (CurrentActivity) + & (START_ENCOUNTER | END_INTERPLANETARY + | CHECK_ABORT | CHECK_LOAD)) + && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0); +} + diff --git a/sc2/src/sc2code/planets/report.c b/sc2/src/sc2code/planets/report.c new file mode 100644 index 000000000..0eb75761a --- /dev/null +++ b/sc2/src/sc2code/planets/report.c @@ -0,0 +1,256 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "starcon.h" +#include "lander.h" + +#define NUM_CELL_COLS 34 +#define NUM_CELL_ROWS 11 + +extern FRAME SpaceJunkFrame; + +static void +ClearReportArea (COUNT page_cells) +{ + COUNT i; + RECT r; + STAMP s; + PRIMITIVE prim_row[NUM_CELL_COLS]; + + s.frame = SetAbsFrameIndex (SpaceJunkFrame, 18); + GetFrameRect (s.frame, &r); + s.origin.x = 1 + (r.extent.width >> 1); + s.origin.y = 1; + for (i = 0; i < NUM_CELL_COLS; ++i) + { + prim_row[i].Object.Stamp = s; + s.origin.x += r.extent.width + 1; + + SetPrimNextLink (&prim_row[i], i + 1); + SetPrimType (&prim_row[i], STAMPFILL_PRIM); + SetPrimColor (&prim_row[i], BUILD_COLOR (MAKE_RGB15 (0x00, 0x07, 0x00), 0x57)); + } + SetPrimNextLink (&prim_row[i - 1], END_OF_LIST); + + if (page_cells == 0) + { + SetContextBackGroundColor (BLACK_COLOR); + ClearDrawable (); + } + SetContextClipping (FALSE); + for (i = 0; i < NUM_CELL_ROWS; ++i) + { + DrawBatch (prim_row, 0, 0); + r.corner.y -= r.extent.height + 1; + SetFrameHot (s.frame, MAKE_HOT_SPOT (r.corner.x, r.corner.y)); + } + SetContextClipping (TRUE); + r.corner.y = 0; + SetFrameHot (s.frame, MAKE_HOT_SPOT (r.corner.x, r.corner.y)); +} + +static void +MakeReport (SOUND ReadOutSounds, UNICODE *pStr, COUNT StrLen) +{ + BYTE ButtonState; + int end_page_len; + UNICODE last_c, end_page_buf[80]; + COUNT row_cells, page_cells; + BOOLEAN Sleepy; + RECT r; + TEXT t; + + wsprintf (end_page_buf, "%s\n", GAME_STRING (SCAN_STRING_BASE + NUM_SCAN_TYPES)); + end_page_len = wstrlen (end_page_buf); + + GetFrameRect (SetAbsFrameIndex (SpaceJunkFrame, 18), &r); + + t.align = ALIGN_LEFT; + t.CharCount = 1; + t.pStr = pStr; + last_c = *pStr; + + Sleepy = TRUE; + page_cells = 0; + ClearSemaphore (&GraphicsSem); + + FlushInput (); + goto InitPageCell; + while (StrLen) + { + COUNT col_cells; + UNICODE *pLastStr; + + pLastStr = t.pStr; + + col_cells = 0; + if (row_cells == NUM_CELL_ROWS - 1 && StrLen > NUM_CELL_COLS) + { + col_cells = (NUM_CELL_COLS >> 1) - (end_page_len >> 1); + t.pStr = end_page_buf; + StrLen += end_page_len; + } + t.baseline.x = 1 + (r.extent.width >> 1) + + (col_cells * (r.extent.width + 1)); + do + { + COUNT word_chars; + UNICODE *pStr; + + pStr = t.pStr; + while (isgraph (*pStr)) + ++pStr; + + word_chars = (COUNT)(pStr - t.pStr); + if ((col_cells += word_chars) <= NUM_CELL_COLS) + { + DWORD TimeOut; + + if (StrLen -= word_chars) + --StrLen; + TimeOut = GetTimeCounter (); + while (word_chars--) + { + if (!Sleepy) + DrawText (&t); + else + { + SetSemaphore (&GraphicsSem); + DrawText (&t); + ClearSemaphore (&GraphicsSem); + + PlaySound (ReadOutSounds, GAME_SOUND_PRIORITY); + + if (t.pStr[0] == ',') + TimeOut += ONE_SECOND / 4; + if (t.pStr[0] == '.') + TimeOut += ONE_SECOND / 2; + else + TimeOut += ONE_SECOND / 20; + if (word_chars == 0) + TimeOut += ONE_SECOND / 20; + + while (TaskSwitch () < TimeOut) + { + if (ButtonState) + { + if (!AnyButtonPress (TRUE)) + ButtonState = 0; + } + else if (AnyButtonPress (TRUE)) + { + Sleepy = FALSE; + SetSemaphore (&GraphicsSem); + BatchGraphics (); + break; + } + } + } + ++t.pStr; + t.baseline.x += r.extent.width + 1; + } + + ++col_cells; + last_c = *t.pStr++; + t.baseline.x += r.extent.width + 1; + } + } while (col_cells <= NUM_CELL_COLS && last_c != '\n' && StrLen); + + t.baseline.y += r.extent.height + 1; + if (++row_cells == NUM_CELL_ROWS || StrLen == 0) + { + t.pStr = pLastStr; + if (!Sleepy) + { + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + } + + while (AnyButtonPress (TRUE)) + TaskSwitch (); + + while (!AnyButtonPress (TRUE)) + TaskSwitch (); +InitPageCell: + ButtonState = 1; + t.baseline.y = r.extent.height + 1; + row_cells = 0; + if (StrLen) + { + SetSemaphore (&GraphicsSem); + if (!Sleepy) + BatchGraphics (); + ClearReportArea (page_cells++); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0, 0x1F, 0), 0xFF)); + if (Sleepy) + ClearSemaphore (&GraphicsSem); + } + } + } + SetSemaphore (&GraphicsSem); +} + +void +DoDiscoveryReport (SOUND ReadOutSounds) +{ + POINT old_curs; + CONTEXT OldContext; + FRAME OldFrame; + extern void DrawScannedObjects (BOOLEAN Reversed); + + if (pMenuState) + { + old_curs = pMenuState->flash_rect0.corner; + pMenuState->flash_rect0.corner.x = /* disable cursor */ + pMenuState->flash_rect0.corner.x = -1000; + } + + OldContext = SetContext (ScanContext); + OldFrame = SetContextBGFrame ((FRAME)0); + { + FONT OldFont; + + OldFont = SetContextFont (pSolarSysState->SysInfo.PlanetInfo.LanderFont); + MakeReport (ReadOutSounds, + (UNICODE *)GetStringAddress (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString), + GetStringLength (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString)); + SetContextFont (OldFont); + } + SetContextBGFrame (OldFrame); +#ifdef OLD + ClearDrawable (); + if (pSolarSysState->MenuState.Initialized >= 3) + DrawScannedObjects (FALSE); +#else /* !OLD */ + if (pSolarSysState->MenuState.Initialized < 3) + ClearDrawable (); +#endif /* OLD */ + SetContext (OldContext); + + ClearSemaphore (&GraphicsSem); + FlushInput (); + while (AnyButtonPress (TRUE)) + TaskSwitch (); + SetSemaphore (&GraphicsSem); + + if (pMenuState) + pMenuState->flash_rect0.corner = old_curs; +} + + diff --git a/sc2/src/sc2code/planets/roster.c b/sc2/src/sc2code/planets/roster.c new file mode 100644 index 000000000..2de35f327 --- /dev/null +++ b/sc2/src/sc2code/planets/roster.c @@ -0,0 +1,434 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +int +flash_ship_task(void *blah) +{ + DWORD TimeIn; + COLOR c; + + c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24); + TimeIn = GetTimeCounter (); + for (;;) + { + STAMP s; + SHIP_FRAGMENTPTR StarShipPtr; + COLOR OldColor; + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + s.origin = pMenuState->first_item; + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMenuState->CurFrame + ); + s.frame = StarShipPtr->ShipInfo.icons; + UnlockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMenuState->CurFrame + ); + OldContext = SetContext (StatusContext); + if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24)) + c = BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2E); + else + c -= BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01); + OldColor = SetContextForeGroundColor (c); + DrawFilledStamp (&s); + SetContextForeGroundColor (OldColor); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + TimeIn = SleepTask (TimeIn + 8); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static HSTARSHIP +MatchSupportShip (PMENU_STATE pMS) +{ + PPOINT pship_pos; + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), + pship_pos = (PPOINT)pMS->flash_frame0; + hStarShip; hStarShip = hNextShip, ++pship_pos) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + + if (pship_pos->x == pMS->first_item.x + && pship_pos->y == pMS->first_item.y) + { + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + + return (hStarShip); + } + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + } + + return (0); +} + +static void +DeltaSupportCrew (SIZE crew_delta) +{ + UNICODE buf[10]; + HSTARSHIP hTemplate; + SHIP_FRAGMENTPTR StarShipPtr, TemplatePtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMenuState->CurFrame + ); + hTemplate = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), + GET_RACE_ID (StarShipPtr) + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + + StarShipPtr->ShipInfo.crew_level += crew_delta; + + if (StarShipPtr->ShipInfo.crew_level == 0) + StarShipPtr->ShipInfo.crew_level = 1; + else if (StarShipPtr->ShipInfo.crew_level > + TemplatePtr->RaceDescPtr->ship_info.crew_level) + StarShipPtr->ShipInfo.crew_level = + TemplatePtr->RaceDescPtr->ship_info.crew_level; + else + { + if (StarShipPtr->ShipInfo.crew_level == + TemplatePtr->RaceDescPtr->ship_info.crew_level) + wsprintf (buf, "%u", StarShipPtr->ShipInfo.crew_level); + else + wsprintf (buf, "%u/%u", + StarShipPtr->ShipInfo.crew_level, + TemplatePtr->RaceDescPtr->ship_info.crew_level); + + DrawStatusMessage (buf); + DeltaSISGauges (-crew_delta, 0, 0); + if (crew_delta) + { + RECT r; + + r.corner.x = 2; + r.corner.y = 130; + r.extent.width = STATUS_MESSAGE_WIDTH; + r.extent.height = STATUS_MESSAGE_HEIGHT; + SetContext (StatusContext); + SetFlashRect (&r, (FRAME)0); + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + UnlockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMenuState->CurFrame + ); +} + +#define SHIP_TOGGLE ((BYTE)(1 << 7)) + +static void +RosterCleanup (PMENU_STATE pMS) +{ + if (pMS->flash_task) + { + DeleteTask (pMS->flash_task); + pMS->flash_task = 0; + } + + if (pMS->CurFrame) + { + STAMP s; + SHIP_FRAGMENTPTR StarShipPtr; + + SetContext (StatusContext); + s.origin = pMS->first_item; + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMS->CurFrame + ); + s.frame = StarShipPtr->ShipInfo.icons; + UnlockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMS->CurFrame + ); + if (!(pMS->CurState & SHIP_TOGGLE)) + DrawStamp (&s); + else + { + SetContextForeGroundColor (WHITE_COLOR); + DrawFilledStamp (&s); + } + } +} + +static BOOLEAN +DoModifyRoster (INPUT_STATE InputState, PMENU_STATE pMS) +{ + BYTE NewState; + SBYTE sx, sy; + RECT r; + STAMP s; + SHIP_FRAGMENTPTR StarShipPtr; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->CurFrame = 0; + SetSemaphore (&GraphicsSem); + RosterCleanup (pMS); + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + + if (!pMS->Initialized) + { + pMS->InputFunc = DoModifyRoster; + pMS->Initialized = TRUE; + + pMS->CurState = NewState = 0; + SetSemaphore (&GraphicsSem); + SetContext (StatusContext); + goto SelectSupport; + } + else if ((InputState & DEVICE_BUTTON2) + && !(pMS->CurState & SHIP_TOGGLE)) + { + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + RosterCleanup (pMS); + pMS->CurFrame = 0; + DrawStatusMessage (NULL_PTR); + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + SetSemaphore (&GraphicsSem); + pMS->CurState ^= SHIP_TOGGLE; + if (!(pMS->CurState & SHIP_TOGGLE)) + SetFlashRect (NULL_PTR, (FRAME)0); + else + { + RosterCleanup (pMS); + + r.corner.x = 2; + r.corner.y = 130; + r.extent.width = STATUS_MESSAGE_WIDTH; + r.extent.height = STATUS_MESSAGE_HEIGHT; + SetContext (StatusContext); + SetFlashRect (&r, (FRAME)0); + } + ClearSemaphore (&GraphicsSem); + } + else if (pMS->CurState & SHIP_TOGGLE) + { + if ((sy = GetInputYComponent (InputState)) < 0) + { + if (GLOBAL_SIS (CrewEnlisted)) + { + SetSemaphore (&GraphicsSem); + DeltaSupportCrew (1); + ClearSemaphore (&GraphicsSem); + } + } + else if (sy > 0) + { + if (GLOBAL_SIS (CrewEnlisted) + < GetCPodCapacity (NULL_PTR)) + { + SetSemaphore (&GraphicsSem); + DeltaSupportCrew (-1); + ClearSemaphore (&GraphicsSem); + } + } + } + else + { + PPOINT pship_pos; + + NewState = pMS->CurState; + sx = (SBYTE)((pMS->delta_item + 1) >> 1); + if (GetInputXComponent (InputState)) + { + pship_pos = (PPOINT)pMS->flash_frame1; + if (NewState == (BYTE)(sx - 1)) + NewState = (BYTE)(pMS->delta_item - 1); + else if (NewState >= (BYTE)sx) + { + NewState -= sx; + if (pship_pos[NewState].y < pship_pos[pMS->CurState].y) + ++NewState; + } + else + { + NewState += sx; + if (NewState != (BYTE)sx + && pship_pos[NewState].y > pship_pos[pMS->CurState].y) + --NewState; + } + } + else if ((sy = GetInputYComponent (InputState)) > 0) + { + if (++NewState == (BYTE)pMS->delta_item) + NewState = (BYTE)(sx - 1); + else if (NewState == (BYTE)sx) + NewState = 0; + } + else if (sy < 0) + { + if (NewState == 0) + NewState += sx - 1; + else if (NewState == (BYTE)sx) + NewState = (BYTE)(pMS->delta_item - 1); + else + --NewState; + } + + if (NewState != pMS->CurState) + { + SetSemaphore (&GraphicsSem); + SetContext (StatusContext); + s.origin = pMS->first_item; + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMS->CurFrame + ); + s.frame = StarShipPtr->ShipInfo.icons; + UnlockStarShip ( + &GLOBAL (built_ship_q), + (HSTARSHIP)pMS->CurFrame + ); + DrawStamp (&s); +SelectSupport: + pship_pos = (PPOINT)pMS->flash_frame1; + pMS->first_item = pship_pos[NewState]; + pMS->CurFrame = (FRAME)MatchSupportShip (pMS); + + DeltaSupportCrew (0); + ClearSemaphore (&GraphicsSem); + + pMS->CurState = NewState; + } + + if (pMS->flash_task == 0) + pMS->flash_task = AddTask (flash_ship_task, 2048); + } + + return (TRUE); +} + +BOOLEAN +Roster (void) +{ + COUNT num_support_ships; + + num_support_ships = CountLinks (&GLOBAL (built_ship_q)); + if (num_support_ships) + { + SIZE i, j, k, l; + POINT modified_ship_pos[MAX_COMBAT_SHIPS]; + POINT ship_pos[MAX_COMBAT_SHIPS] = + { + SUPPORT_SHIP_PTS + }; + MENU_STATE MenuState; + PMENU_STATE pOldMenuState; + + pOldMenuState = pMenuState; + pMenuState = &MenuState; + + j = 0; + k = (num_support_ships + 1) >> 1; + for (i = 0; (int)i < (int)num_support_ships; i += 2) + { + modified_ship_pos[j++] = ship_pos[i]; + modified_ship_pos[k++] = ship_pos[i + 1]; + } + + k = (num_support_ships + 1) >> 1; + for (i = 0; i < k; ++i) + { + for (j = k - 1; j > i; --j) + { + if (modified_ship_pos[i].y > modified_ship_pos[j].y) + { + POINT temp; + + temp = modified_ship_pos[i]; + modified_ship_pos[i] = modified_ship_pos[j]; + modified_ship_pos[j] = temp; + } + } + } + + l = k; + k = num_support_ships >> 1; + for (i = 0; i < k; ++i) + { + for (j = k - 1; j > i; --j) + { + if (modified_ship_pos[i + l].y > modified_ship_pos[j + l].y) + { + POINT temp; + + temp = modified_ship_pos[i + l]; + modified_ship_pos[i + l] = modified_ship_pos[j + l]; + modified_ship_pos[j + l] = temp; + } + } + } + + MenuState.InputFunc = DoModifyRoster; + MenuState.Initialized = FALSE; + MenuState.CurState = 0; + MenuState.flash_task = 0; + MenuState.delta_item = (SIZE)num_support_ships; + + MenuState.flash_frame0 = (FRAME)ship_pos; + MenuState.flash_frame1 = (FRAME)modified_ship_pos; + DoInput ((PVOID)&MenuState); + + pMenuState = pOldMenuState; + + return (TRUE); + } + + return (FALSE); +} + diff --git a/sc2/src/sc2code/planets/scan.c b/sc2/src/sc2code/planets/scan.c new file mode 100644 index 000000000..a793cba00 --- /dev/null +++ b/sc2/src/sc2code/planets/scan.c @@ -0,0 +1,1163 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lifeform.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void +DrawPlanet(int x, int y, int dy, unsigned int rgb); + +void WaitForNoInput (SIZE Duration); + +//End Added by Chris + +#define FLASH_INDEX 105 +#define FLASH_WIDTH 9 +#define FLASH_HEIGHT 9 +extern FRAME misc_data; + +extern void DrawScannedObjects (BOOLEAN Reversed); + +CONTEXT ScanContext; + +void +RepairBackRect (PRECT pRect) +{ + RECT new_r, old_r; + + GetContextClipRect (&old_r); + new_r.corner.x = pRect->corner.x + old_r.corner.x; + new_r.corner.y = pRect->corner.y + old_r.corner.y; + new_r.extent = pRect->extent; + + new_r.extent.height += new_r.corner.y & 1; + new_r.corner.y &= ~1; + DrawFromExtraScreen (&new_r); +} + +static void +EraseCoarseScan (void) +{ + RECT r, tr; + extern FRAME SpaceJunkFrame; + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + + r.corner.x = (SIS_SCREEN_WIDTH >> 1) - (160 >> 1); + r.corner.y = 13 - 7; + r.extent.width = 160; + r.extent.height = 10; + RepairBackRect (&r); + + GetFrameRect (SetAbsFrameIndex (SpaceJunkFrame, 20), &tr); + r = tr; + r.extent.width = 70; + RepairBackRect (&r); + + r = tr; + r.corner.x += (r.extent.width - 70); + r.extent.width = 70; + RepairBackRect (&r); + + ClearSemaphore (&GraphicsSem); +} + +static void +PrintCoarseScan (void) +{ +#define SCAN_LEADING 19 + SIZE temp; + TEXT t; + STAMP s; + UNICODE buf[40]; + extern FRAME SpaceJunkFrame; + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + + if (CurStarDescPtr->Index == SOL_DEFINED) + { + if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) + wstrcpy (buf, GLOBAL_SIS (PlanetName)); + else + { + switch (pSolarSysState->pOrbitalDesc->pPrevDesc + - pSolarSysState->PlanetDesc) + { + case 2: /* EARTH */ + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 9)); + break; + case 4: /* JUPITER */ + switch (pSolarSysState->pOrbitalDesc + - pSolarSysState->MoonDesc) + { + case 0: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 10)); + break; + case 1: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 11)); + break; + case 2: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 12)); + break; + case 3: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 13)); + break; + } + break; + case 5: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 14)); + break; + case 7: + wstrcpy (buf, GAME_STRING (PLANET_NUMBER_BASE + 15)); + break; + } + } + } + else + { + temp = pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED; + if (temp >= FIRST_GAS_GIANT) + wsprintf (buf, "%s", GAME_STRING (SCAN_STRING_BASE + 4 + 51)); + else + wsprintf (buf, "%s %s", + GAME_STRING (SCAN_STRING_BASE + 4 + temp), + GAME_STRING (SCAN_STRING_BASE + 4 + 50)); + } + + t.align = ALIGN_CENTER; + t.baseline.x = SIS_SCREEN_WIDTH >> 1; + t.baseline.y = 13; + t.pStr = buf; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x19), 0x3B)); + SetContextFont (MicroFont); + DrawText (&t); + + s.origin.x = s.origin.y = 0; + s.frame = SetAbsFrameIndex (SpaceJunkFrame, 20); + DrawStamp (&s); + + ClearSemaphore (&GraphicsSem); + +#define LEFT_SIDE_BASELINE_X 27 +#define RIGHT_SIDE_BASELINE_X (SIS_SCREEN_WIDTH - LEFT_SIDE_BASELINE_X) +#define SCAN_BASELINE_Y 25 + + t.baseline.x = LEFT_SIDE_BASELINE_X; + t.baseline.y = SCAN_BASELINE_Y; + t.align = ALIGN_LEFT; + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + temp = (SIZE)((pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist * 100L + + (EARTH_RADIUS >> 1)) / EARTH_RADIUS); + if (temp >= 10 * 100) + wsprintf (buf, "%u.%u&", temp / 100, (temp / 10) % 10); + else + wsprintf (buf, "%u.%02u&", temp / 100, temp % 100); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == GAS_GIANT_ATMOSPHERE) + wsprintf (buf, "|"); + else + { + temp = (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity * 100 + + (EARTH_ATMOSPHERE >> 1)) / EARTH_ATMOSPHERE; + if (temp >= 10 * 100) + wsprintf (buf, "%u.%u&", temp / 100, (temp / 10) % 10); + else + wsprintf (buf, "%u.%02u&", temp / 100, temp % 100); + } + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + wsprintf (buf, "%d^", pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + wsprintf (buf, "<%u>", pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == 0 + ? 0 : (pSolarSysState->SysInfo.PlanetInfo.Weather + 1)); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + wsprintf (buf, "<%u>", + PLANSIZE ( + pSolarSysState->SysInfo.PlanetInfo.PlanDataPtr->Type + ) == GAS_GIANT + ? 0 : (pSolarSysState->SysInfo.PlanetInfo.Tectonics + 1)); + t.CharCount = (COUNT)~0; + DrawText (&t); + ClearSemaphore (&GraphicsSem); + + t.baseline.x = RIGHT_SIDE_BASELINE_X; + t.baseline.y = SCAN_BASELINE_Y; + t.align = ALIGN_RIGHT; + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + { + DWORD tr; + + tr = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius; + if ((tr = (tr * tr * tr / 100L + * (DWORD)pSolarSysState->SysInfo.PlanetInfo.PlanetDensity + + (DWORD)((100L * 100L) >> 1)) + / (DWORD)(100L * 100L)) == 0) + tr = 1; + if (tr >= 10 * 100) + wsprintf (buf, "%lu.%lu&", tr / 100, (tr / 10) % 10); + else + wsprintf (buf, "%lu.%02lu&", tr / 100, tr % 100); + } + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + if ((temp = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius) >= 10 * 100) + wsprintf (buf, "%u.%u&", temp / 100, (temp / 10) % 10); + else + wsprintf (buf, "%u.%02u&", temp / 100, temp % 100); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + if ((temp = pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity) >= 10 * 100) + wsprintf (buf, "%u.%u&", temp / 100, (temp / 10) % 10); + else + { + if (temp == 0) + temp = 1; + wsprintf (buf, "%u.%02u&", temp / 100, temp % 100); + } + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + if ((temp = pSolarSysState->SysInfo.PlanetInfo.AxialTilt) < 0) + temp = -temp; + wsprintf (buf, "%u^", temp); + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += SCAN_LEADING; + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + t.pStr = buf; + if (pSolarSysState->SysInfo.PlanetInfo.RotationPeriod < 240 * 10) + { + temp = (SIZE)(pSolarSysState->SysInfo.PlanetInfo.RotationPeriod * 10 / 24); + wsprintf (buf, "%u.%02u&", temp / 100, temp % 100); + } + else + { + temp = (SIZE)((pSolarSysState->SysInfo.PlanetInfo.RotationPeriod + + (24 >> 1)) / 24); + wsprintf (buf, "%u.%u&", temp / 10, temp % 10); + } + t.CharCount = (COUNT)~0; + DrawText (&t); + ClearSemaphore (&GraphicsSem); +} + +static void +SetPlanetLoc (POINT new_pt) +{ + RECT r; + STAMP s; + + pSolarSysState->MenuState.first_item = new_pt; + new_pt.x >>= MAG_SHIFT; + new_pt.y >>= MAG_SHIFT; + + SetSemaphore (&GraphicsSem); + SetContext (ScanContext); + s.origin.x = pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); + s.origin.y = pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); + s.frame = pMenuState->flash_frame0; + DrawStamp (&s); + + pMenuState->flash_rect0.corner = new_pt; + GetContextClipRect (&r); + r.corner.x += pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); + r.corner.y += pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); + r.extent.width = FLASH_WIDTH; + r.extent.height = FLASH_HEIGHT; + LoadDisplayPixmap (&r, pMenuState->flash_frame0); + ClearSemaphore (&GraphicsSem); + + TaskSwitch (); +} + +int +flash_planet_loc_func(void *blah) +{ + DWORD TimeIn; + BYTE c, val; + PRIMITIVE p; + + SetPrimType (&p, STAMPFILL_PRIM); + SetPrimNextLink (&p, END_OF_LIST); + + p.Object.Stamp.origin.x = p.Object.Stamp.origin.y = -1; + p.Object.Stamp.frame = SetAbsFrameIndex (misc_data, FLASH_INDEX); + c = 0x00; + val = -0x02; + TimeIn = 0; + for (;;) + { + DWORD T; + CONTEXT OldContext; + + T = SetSemaphore (&GraphicsSem); + if (p.Object.Stamp.origin.x != pMenuState->flash_rect0.corner.x + || p.Object.Stamp.origin.y != pMenuState->flash_rect0.corner.y) + { + c = 0x00; + val = -0x02; + } + else + { + if (T < TimeIn) + { + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + + continue; + } + + if (c == 0x00 || c == 0x1A) + val = -val; + c += val; + } + p.Object.Stamp.origin = pMenuState->flash_rect0.corner; + SetPrimColor (&p, BUILD_COLOR (MAKE_RGB15 (c, c, c), c)); + + OldContext = SetContext (ScanContext); + DrawBatch (&p, 0, 0); + SetContext (OldContext); + + TimeIn = T + (ONE_SECOND >> 4); + ClearSemaphore (&GraphicsSem); + + TaskSwitch (); + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static BOOLEAN DoScan (INPUT_STATE InputState, PMENU_STATE pMS); + +static BOOLEAN +PickPlanetSide (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + if (pMenuState->flash_task) + { + SetSemaphore (&GraphicsSem); + DeleteTask (pMenuState->flash_task); + ClearSemaphore (&GraphicsSem); + pMenuState->flash_task = 0; + } + goto ExitPlanetSide; + } + + pMS->MenuRepeatDelay = 0; + if (!pMS->Initialized) + { + pMS->InputFunc = PickPlanetSide; + if (pMS->CurFrame == 0) + { + pMS->CurFrame = (FRAME)MenuSounds; + MenuSounds = 0; + } + if (!(InputState & DEVICE_BUTTON1)) + { + RECT r; + + pMS->Initialized = TRUE; + + SetSemaphore (&GraphicsSem); + SetContext (ScanContext); + pMenuState->flash_rect0.corner.x = + pSolarSysState->MenuState.first_item.x >> MAG_SHIFT; + pMenuState->flash_rect0.corner.y = + pSolarSysState->MenuState.first_item.y >> MAG_SHIFT; + GetContextClipRect (&r); + r.corner.x += pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); + r.corner.y += pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); + r.extent.width = FLASH_WIDTH; + r.extent.height = FLASH_HEIGHT; + LoadDisplayPixmap (&r, pMenuState->flash_frame0); + + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + InitLander (0); + + pMenuState->flash_task = AddTask (flash_planet_loc_func, 2048); + } + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + STAMP s; + + MenuSounds = (SOUND)pMS->CurFrame; + pMS->CurFrame = 0; + + SetSemaphore (&GraphicsSem); + DrawStatusMessage (NULL_PTR); + if (pMenuState->flash_task) + { + DeleteTask (pMenuState->flash_task); + pMenuState->flash_task = 0; + } + ClearSemaphore (&GraphicsSem); + + if (!(InputState & DEVICE_BUTTON1)) + SetPlanetLoc (pSolarSysState->MenuState.first_item); + else + { + COUNT fuel_required; + extern void PlanetSide (PMENU_STATE pMS); + + fuel_required = (COUNT)( + pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity << 1 + ); + if (fuel_required > 3 * FUEL_TANK_SCALE) + fuel_required = 3 * FUEL_TANK_SCALE; + + EraseCoarseScan (); + + SetSemaphore (&GraphicsSem); + DeltaSISGauges (0, -(SIZE)fuel_required, 0); + SetContext (ScanContext); + s.origin = pMenuState->flash_rect0.corner; + s.frame = SetAbsFrameIndex (misc_data, FLASH_INDEX); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + PlanetSide (pMS); + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + goto ExitPlanetSide; + + if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) + { + HSTARSHIP hStarShip; + extern ACTIVITY NextActivity; + extern void SaveFlagshipState (void); + + SetSemaphore (&GraphicsSem); + if (pMenuState->flash_task) + { + DeleteTask (pMenuState->flash_task); + pMenuState->flash_task = 0; + } + ClearSemaphore (&GraphicsSem); + + NextActivity |= CHECK_LOAD; /* fake a load game */ + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + + battle_counter = 0; + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + + hStarShip = CloneShipFragment (SPATHI_SHIP, + &GLOBAL (npc_built_ship_q), 1); + if (hStarShip) + { + BYTE captains_name_index; + COUNT which_player; + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + which_player = StarShipPlayer (StarShipPtr); + captains_name_index = NAME_OFFSET + NUM_CAPTAINS_NAMES; + OwnStarShip (StarShipPtr, which_player, captains_name_index); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + } + + SaveFlagshipState (); + return (FALSE); + } + + PrintCoarseScan (); + } + + DrawMenuStateStrings (PM_MIN_SCAN, DISPATCH_SHUTTLE); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + +ExitPlanetSide: + if (pMS->CurFrame) + { + MenuSounds = (SOUND)pMS->CurFrame; + pMS->CurFrame = 0; + } + + pMS->InputFunc = DoScan; + pMS->CurState = DISPATCH_SHUTTLE; + pMS->MenuRepeatDelay = MENU_REPEAT_DELAY; + } + else + { + SIZE dx, dy; + POINT new_pt; + + new_pt = pSolarSysState->MenuState.first_item; + + dx = GetInputXComponent (InputState) << MAG_SHIFT; + if (dx) + { + new_pt.x += dx; + if (new_pt.x < 0) + new_pt.x += (MAP_WIDTH << MAG_SHIFT); + else if (new_pt.x >= (MAP_WIDTH << MAG_SHIFT)) + new_pt.x -= (MAP_WIDTH << MAG_SHIFT); + } + dy = GetInputYComponent (InputState) << MAG_SHIFT; + if (dy) + { + new_pt.y += dy; + if (new_pt.y < 0 || new_pt.y >= (MAP_HEIGHT << MAG_SHIFT)) + new_pt.y = pSolarSysState->MenuState.first_item.y; + } + + if (new_pt.x != pSolarSysState->MenuState.first_item.x + || new_pt.y != pSolarSysState->MenuState.first_item.y) + { + DWORD TimeIn; + + TimeIn = GetTimeCounter (); + SetPlanetLoc (new_pt); + SleepTask (TimeIn + 3); + } + } + + return (TRUE); +} + +#define NUM_FLASH_COLORS 8 + +static void +DrawScannedStuff (COUNT y, BYTE CurState) +{ + HELEMENT hElement, hNextElement; + COLOR OldColor; + + OldColor = SetContextForeGroundColor (0); + + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + //COLOR OldColor; + SIZE dy; + + LockElement (hElement, &ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + + dy = y - ElementPtr->current.location.y; + if (LOBYTE (ElementPtr->life_span) == CurState + && dy >= 0)// && dy <= 3) + { + COUNT i; + //DWORD Time; + STAMP s; + + ElementPtr->state_flags |= APPEARING; + + s.origin = ElementPtr->current.location; + s.frame = ElementPtr->current.image.frame; + + if (dy >= NUM_FLASH_COLORS) + { + i = (COUNT)(GetFrameIndex (ElementPtr->next.image.frame) + - GetFrameIndex (ElementPtr->current.image.frame) + + 1); + do + { + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + } while (--i); + } + else + { + BYTE r, g, b; + COLOR c; + + // mineral -- white --> turquoise?? (contrasts with red) + // energy -- white --> red (contrasts with white) + // bio -- white --> violet (contrasts with green) + b = (BYTE)(0x1f - 0x1f * dy / (NUM_FLASH_COLORS - 1)); + switch (CurState) + { + case (MINERAL_SCAN): + r = b; + g = 0x1f; + b = 0x1f; + break; + case (ENERGY_SCAN): + r = 0x1f; + g = b; + break; + case (BIOLOGICAL_SCAN): + r = 0x1f; + g = b; + b = 0x1f; + break; + } + + c = BUILD_COLOR (MAKE_RGB15 (r, g, b), 0); + + SetContextForeGroundColor (c); + i = (COUNT)(GetFrameIndex (ElementPtr->next.image.frame) + - GetFrameIndex (ElementPtr->current.image.frame) + + 1); + do + { + DrawFilledStamp (&s); + s.frame = IncFrameIndex (s.frame); + } while (--i); + } + } + + UnlockElement (hElement); + } + + SetContextForeGroundColor (OldColor); +} + +static BOOLEAN +DoScan (INPUT_STATE InputState, PMENU_STATE + pMS) +{ + //STAMP s; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (!pMS->Initialized) + { + pMS->Initialized = TRUE; + pMS->InputFunc = DoScan; + } + else if ((InputState & DEVICE_BUTTON2) + || ((InputState & DEVICE_BUTTON1) + && pMS->CurState == EXIT_SCAN)) + { + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + BatchGraphics (); + DrawPlanet (SIS_SCREEN_WIDTH - MAP_WIDTH, SIS_SCREEN_HEIGHT - MAP_HEIGHT, 0, 0); + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + + EraseCoarseScan (); +// DrawMenuStateStrings (PM_SCAN, SCAN); + + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + BYTE min_scan, max_scan; + RECT r; + INPUT_STATE PressState, ButtonState; + + if (pMS->CurState == DISPATCH_SHUTTLE) + { + COUNT fuel_required; + UNICODE buf[20]; + + fuel_required = (COUNT)( + pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity << 1 + ); + if (fuel_required > 3 * FUEL_TANK_SCALE) + fuel_required = 3 * FUEL_TANK_SCALE; + + if (GLOBAL_SIS (FuelOnBoard) < (DWORD)fuel_required + || GLOBAL_SIS (NumLanders) == 0 + || GLOBAL_SIS (CrewEnlisted) == 0) + { + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 2), + 0, GAME_SOUND_PRIORITY); + return (TRUE); + } + + wsprintf (buf, "%s%u.%u", + GAME_STRING (NAVIGATION_STRING_BASE + 5), + fuel_required / FUEL_TANK_SCALE, + ((fuel_required % FUEL_TANK_SCALE) + 5) / 10); + SetSemaphore (&GraphicsSem); + DrawStatusMessage (buf); + ClearSemaphore (&GraphicsSem); + + SetSemaphore (&GraphicsSem); + SetContext (ScanContext); + BatchGraphics (); + DrawPlanet (0, 0, 0, 0); + DrawScannedObjects (FALSE); + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + + pMS->Initialized = FALSE; + pMS->CurFrame = 0; + return (PickPlanetSide (InputState, pMS)); + } + +pSolarSysState->MenuState.Initialized += 4; + + if ((min_scan = pMS->CurState) != AUTO_SCAN) + max_scan = min_scan; + else + min_scan = MINERAL_SCAN, max_scan = BIOLOGICAL_SCAN; + + do + { + TEXT t; + COUNT i; + + t.baseline.x = SIS_SCREEN_WIDTH >> 1; + t.baseline.y = SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7; + t.align = ALIGN_CENTER; + t.CharCount = (COUNT)~0; + + pSolarSysState->CurNode = (COUNT)~0; + (*pSolarSysState->GenFunc) ( + (BYTE)(min_scan + GENERATE_MINERAL) + ); + pMS->delta_item = (SIZE)pSolarSysState->CurNode; + t.pStr = GAME_STRING (SCAN_STRING_BASE + min_scan); + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + r.corner.x = 0; + r.corner.y = t.baseline.y - 10; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = t.baseline.y - r.corner.y + 1; + RepairBackRect (&r); + + SetContextFont (MicroFont); + switch (min_scan) + { + case MINERAL_SCAN: + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C) + ); + break; + case ENERGY_SCAN: + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0xC, 0xC, 0xC), 0x1C) + ); + break; + case BIOLOGICAL_SCAN: + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x00, 0xE, 0x00), 0x6C) + ); + break; + } + DrawText (&t); + + SetContext (ScanContext); + ClearSemaphore (&GraphicsSem); + + { + DWORD rgb; + + switch (min_scan) + { + case MINERAL_SCAN: + rgb = 0x1f << 10; + break; + case ENERGY_SCAN: + rgb = (0x1f << 10) | (0x1f << 5) | 0x1f; + break; + case BIOLOGICAL_SCAN: + rgb = 0x1f << 5; + break; + } + + SetSemaphore (&GraphicsSem); + BatchGraphics (); + DrawPlanet (0, 0, 0, 0); + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + + PressState = AnyButtonPress (TRUE); + for (i = 0; i < MAP_HEIGHT + NUM_FLASH_COLORS + 1; i++) + { + ButtonState = AnyButtonPress (TRUE); + if (PressState) + { + PressState = ButtonState; + ButtonState = 0; + } + if (ButtonState) + i = MAP_HEIGHT + NUM_FLASH_COLORS; + SetSemaphore (&GraphicsSem); + BatchGraphics (); + DrawPlanet (0, 0, i, rgb); + if (pMS->delta_item) + DrawScannedStuff (i, min_scan); + UnbatchGraphics (); + ClearSemaphore (&GraphicsSem); + + SleepTask (GetTimeCounter () + 2); + } + } + + } while (++min_scan <= max_scan); + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + r.corner.x = 0; + r.corner.y = (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7) - 10; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7) - r.corner.y + 1; + RepairBackRect (&r); + + SetContext (ScanContext); + if (pMS->CurState == AUTO_SCAN) + { + DrawPlanet (0, 0, 0, 0); + DrawScannedObjects (FALSE); + ClearSemaphore (&GraphicsSem); + + DrawMenuStateStrings (PM_MIN_SCAN, pMS->CurState = DISPATCH_SHUTTLE); + } + else + ClearSemaphore (&GraphicsSem); + +pSolarSysState->MenuState.Initialized -= 4; + WaitForNoInput (ONE_SECOND / 2); + } + else if (!(pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) + && pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != + GAS_GIANT_ATMOSPHERE) + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == MINERAL_SCAN) + NewState = DISPATCH_SHUTTLE; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == DISPATCH_SHUTTLE) + NewState = MINERAL_SCAN; + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_MIN_SCAN, NewState); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +void +ScanSystem (void) +{ + RECT r; + MENU_STATE MenuState; + + MenuState.InputFunc = DoScan; + MenuState.Initialized = FALSE; + MenuState.flash_task = 0; + +{ +#define REPAIR_SCAN (1 << 6) + extern BYTE draw_sys_flags; + + if (draw_sys_flags & REPAIR_SCAN) + { + RECT r; + + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + LoadIntoExtraScreen (&r); + draw_sys_flags &= ~REPAIR_SCAN; + } +} + + if ((pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) + || pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == + GAS_GIANT_ATMOSPHERE) + { + MenuState.CurState = EXIT_SCAN; + ScanContext = 0; + } + else + { + MenuState.CurState = AUTO_SCAN; + pSolarSysState->MenuState.first_item.x = (MAP_WIDTH >> 1) << MAG_SHIFT; + pSolarSysState->MenuState.first_item.y = (MAP_HEIGHT >> 1) << MAG_SHIFT; + + SetSemaphore (&GraphicsSem); + ScanContext = CaptureContext (CreateContext ()); + SetContext (ScanContext); + MenuState.flash_rect0.extent.width = FLASH_WIDTH; + MenuState.flash_rect0.extent.height = FLASH_HEIGHT; + MenuState.flash_frame0 = CaptureDrawable ( + CreateDrawable (WANT_PIXMAP | MAPPED_TO_DISPLAY, + FLASH_WIDTH, FLASH_HEIGHT, 1) + ); + SetContextFGFrame (Screen); + r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; + r.extent.width = MAP_WIDTH; + r.extent.height = MAP_HEIGHT; + SetContextClipRect (&r); + DrawScannedObjects (FALSE); + ClearSemaphore (&GraphicsSem); + } + + DrawMenuStateStrings (PM_MIN_SCAN, MenuState.CurState); + + PrintCoarseScan (); + + pMenuState = &MenuState; + DoInput ((PVOID)&MenuState); + pMenuState = 0; + + if (ScanContext) + { + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + DestroyDrawable (ReleaseDrawable (MenuState.flash_frame0)); + DestroyContext (ReleaseContext (ScanContext)); + ScanContext = 0; + ClearSemaphore (&GraphicsSem); + } +} + +void +GeneratePlanetSide (void) +{ + SIZE scan; + BYTE life_init_tab[MAX_LIFE_VARIATION]; + + InitDisplayList (); + if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) + return; + + memset (life_init_tab, 0, sizeof (life_init_tab)); + for (scan = BIOLOGICAL_SCAN; scan >= MINERAL_SCAN; --scan) + { + COUNT num_nodes; + FRAME f; + + f = SetAbsFrameIndex ( + misc_data, + NUM_SCANDOT_TRANSITIONS * (scan - ENERGY_SCAN) + ); + + pSolarSysState->CurNode = (COUNT)~0; + (*pSolarSysState->GenFunc) ( + (BYTE)(scan + GENERATE_MINERAL) + ); + num_nodes = pSolarSysState->CurNode; + if (num_nodes) + { + while (num_nodes--) + { + HELEMENT hNodeElement; + + if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] + & (1L << num_nodes)) + && (hNodeElement = AllocElement ())) + { + ELEMENTPTR NodeElementPtr; + + LockElement (hNodeElement, &NodeElementPtr); + + pSolarSysState->CurNode = num_nodes; + (*pSolarSysState->GenFunc) ( + (BYTE)(scan + GENERATE_MINERAL) + ); + + NodeElementPtr->life_span = MAKE_WORD (scan, num_nodes + 1); + NodeElementPtr->state_flags = BAD_GUY; + NodeElementPtr->current.location.x = + pSolarSysState->SysInfo.PlanetInfo.CurPt.x; + NodeElementPtr->current.location.y = + pSolarSysState->SysInfo.PlanetInfo.CurPt.y; + + SetPrimType (&DisplayArray[NodeElementPtr->PrimIndex], STAMP_PRIM); + if (scan == MINERAL_SCAN) + { + COUNT EType; + + EType = pSolarSysState->SysInfo.PlanetInfo.CurType; + NodeElementPtr->turn_wait = (BYTE)EType; + NodeElementPtr->mass_points = + HIBYTE ( + pSolarSysState->SysInfo.PlanetInfo.CurDensity + ); + NodeElementPtr->current.image.frame = + SetAbsFrameIndex ( + misc_data, + (NUM_SCANDOT_TRANSITIONS << 1) + + ElementCategory (EType) * 5 + ); + NodeElementPtr->next.image.frame = + SetRelFrameIndex ( + NodeElementPtr->current.image.frame, + LOBYTE ( + pSolarSysState->SysInfo.PlanetInfo.CurDensity + ) + 1 + ); + DisplayArray[NodeElementPtr->PrimIndex].Object.Stamp.frame = + IncFrameIndex ( + NodeElementPtr->next.image.frame + ); + } + else + { + extern void + object_animation + (PELEMENT + ElementPtr); + + NodeElementPtr->current.image.frame = f; + NodeElementPtr->next.image.frame = + SetRelFrameIndex ( + f, NUM_SCANDOT_TRANSITIONS - 1 + ); + NodeElementPtr->turn_wait = MAKE_BYTE (4, 4); + NodeElementPtr->preprocess_func = object_animation; + if (scan == ENERGY_SCAN) + { + if (pSolarSysState->SysInfo.PlanetInfo.CurType == 1) + NodeElementPtr->mass_points = 0; + else if (pSolarSysState->SysInfo.PlanetInfo.CurType == 2) + NodeElementPtr->mass_points = 1; + else + NodeElementPtr->mass_points = MAX_SCROUNGED; + DisplayArray[NodeElementPtr->PrimIndex].Object.Stamp.frame = + pSolarSysState->PlanetSideFrame[1]; + } + else + { + COUNT i, which_node; + + which_node = pSolarSysState->SysInfo.PlanetInfo.CurType; + + if (CreatureData[which_node].Attributes & SPEED_MASK) + { + i = (COUNT)Random (); + NodeElementPtr->current.location.x = + (LOBYTE (i) % (MAP_WIDTH - (8 << 1))) + 8; + NodeElementPtr->current.location.y = + (HIBYTE (i) % (MAP_HEIGHT - (8 << 1))) + 8; + } + + if (pSolarSysState->PlanetSideFrame[0] == 0) + pSolarSysState->PlanetSideFrame[0] = + CaptureDrawable (LoadGraphic ( + CANNISTER_MASK_PMAP_ANIM + )); + for (i = 0; i < MAX_LIFE_VARIATION + && life_init_tab[i] != (BYTE)(which_node + 1); + ++i) + { + if (life_init_tab[i] == 0) + { + life_init_tab[i] = (BYTE)which_node + 1; + + pSolarSysState->PlanetSideFrame[i + 3] = + CaptureDrawable (LoadGraphic ( + MAKE_RESOURCE ( + GET_PACKAGE (LIFE00_MASK_PMAP_ANIM) + + which_node, GFXRES, + GET_INSTANCE (LIFE00_MASK_PMAP_ANIM) + + which_node))); + + break; + } + } + + NodeElementPtr->mass_points = (BYTE)which_node; + NodeElementPtr->hit_points = HINIBBLE ( + CreatureData[which_node].ValueAndHitPoints + ); + DisplayArray[NodeElementPtr->PrimIndex].Object.Stamp.frame = + SetAbsFrameIndex ( + pSolarSysState->PlanetSideFrame[i + 3], + (COUNT)Random () + ); + } + } + + NodeElementPtr->next.location.x = + NodeElementPtr->current.location.x << MAG_SHIFT; + NodeElementPtr->next.location.y = + NodeElementPtr->current.location.y << MAG_SHIFT; + UnlockElement (hNodeElement); + + PutElement (hNodeElement); + } + } + } + } +} + diff --git a/sc2/src/sc2code/planets/scan.h b/sc2/src/sc2code/planets/scan.h new file mode 100644 index 000000000..7a4f7e4be --- /dev/null +++ b/sc2/src/sc2code/planets/scan.h @@ -0,0 +1,44 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCAN_H +#define _SCAN_H + +typedef struct +{ + POINT start; + COUNT start_dot, + num_dots, + dots_per_semi; +} SCAN_DESC; +typedef SCAN_DESC *PSCAN_DESC; + +typedef struct +{ + PPOINT line_base; + COUNT num_scans, num_same_scans; + PSCAN_DESC scan_base; +} SCAN_BLOCK; +typedef SCAN_BLOCK *PSCAN_BLOCK; + +#define SAME_SCAN (1 << 16) +#define SCALED_ROOT_TWO 92682L /* root 2 * (1 << 16) */ +#define SCALE_FACTOR 16 + +#endif /* _SCAN_H */ + diff --git a/sc2/src/sc2code/planets/solarsys.c b/sc2/src/sc2code/planets/solarsys.c new file mode 100644 index 000000000..6e6a1fc11 --- /dev/null +++ b/sc2/src/sc2code/planets/solarsys.c @@ -0,0 +1,1876 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void LoadLanderData (void); + +void RenderTopography (BOOLEAN Reconstruct); + +//End Added by Chris + +PSOLARSYS_STATE pSolarSysState; +FRAME SISIPFrame, SunFrame, OrbitalFrame, SpaceJunkFrame; +COLORMAP OrbitalCMap; +MUSIC_REF SpaceMusic; + +#define DRAW_STARS (1 << 0) +#define DRAW_PLANETS (1 << 1) +#define DRAW_ORBITS (1 << 2) +#define DRAW_HYPER_COORDS (1 << 3) +#define UNBATCH_SYS (1 << 4) +#define DRAW_REFRESH (1 << 5) +#define REPAIR_SCAN (1 << 6) +#define GRAB_BKGND (1 << 7) + +static SIZE old_radius; +BYTE draw_sys_flags = DRAW_STARS + | DRAW_PLANETS + | DRAW_ORBITS + | DRAW_HYPER_COORDS + | GRAB_BKGND; + +static void +GenerateMoons (void) +{ + COUNT i, facing; + PPLANET_DESC pMoonDesc; + PPLANET_DESC pCurDesc; + DWORD old_seed; + + GLOBAL (ip_location.x) = + (SIZE)((long)(GLOBAL (ShipStamp.origin.x) + - (SIS_SCREEN_WIDTH >> 1)) + * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); + GLOBAL (ip_location.y) = + (SIZE)((long)(GLOBAL (ShipStamp.origin.y) + - (SIS_SCREEN_HEIGHT >> 1)) + * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); + pCurDesc = pSolarSysState->pBaseDesc; + old_seed = SeedRandom (pCurDesc->rand_seed); + + (*pSolarSysState->GenFunc) (GENERATE_NAME); + (*pSolarSysState->GenFunc) (GENERATE_MOONS); + + facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + ARCTAN (pCurDesc->location.x, pCurDesc->location.y) + )); + for (i = 0, pMoonDesc = &pSolarSysState->MoonDesc[0]; + i < MAX_MOONS; ++i, ++pMoonDesc) + { + pMoonDesc->pPrevDesc = pCurDesc; + if (pSolarSysState->MenuState.Initialized > 1 + || i >= pCurDesc->NumPlanets) + ; + else + { + BYTE data_index; + + pMoonDesc->temp_color = pCurDesc->temp_color; + + data_index = pMoonDesc->data_index; + /* Starbase */ + if (data_index == (BYTE)~0) + { + pMoonDesc->image.frame = SetAbsFrameIndex ( + SpaceJunkFrame, 16 + ); + } + /* Samatra */ + else if (data_index == (BYTE)(~0 - 1)) + { + pMoonDesc->image.frame = SetAbsFrameIndex ( + SpaceJunkFrame, 19 + ); + } + } + } + + pSolarSysState->pBaseDesc = pSolarSysState->MoonDesc; + SeedRandom (old_seed); +} + +void +FreeIPData (void) +{ + DestroyDrawable (ReleaseDrawable (SISIPFrame)); + SISIPFrame = 0; + DestroyDrawable (ReleaseDrawable (SunFrame)); + SunFrame = 0; + DestroyColorMap (ReleaseColorMap (OrbitalCMap)); + OrbitalCMap = 0; + DestroyDrawable (ReleaseDrawable (OrbitalFrame)); + OrbitalFrame = 0; + DestroyDrawable (ReleaseDrawable (SpaceJunkFrame)); + SpaceJunkFrame = 0; + DestroyMusic (SpaceMusic); + SpaceMusic = 0; +} + +void +LoadIPData (void) +{ + if (SpaceJunkFrame == 0) + { + SpaceJunkFrame = CaptureDrawable ( + LoadGraphic (IPBKGND_MASK_PMAP_ANIM) + ); + SISIPFrame = + CaptureDrawable ( + LoadGraphic (SISIP_MASK_PMAP_ANIM) + ); + + OrbitalCMap = CaptureColorMap (LoadColorMap (ORBPLAN_COLOR_MAP)); + OrbitalFrame = CaptureDrawable ( + LoadGraphic (ORBPLAN_MASK_PMAP_ANIM) + ); + SunFrame = SetAbsFrameIndex ( + CaptureDrawable (LoadGraphic (SUN_MASK_PMAP_ANIM)), + STAR_TYPE (CurStarDescPtr->Type) + ); + + SpaceMusic = LoadMusicInstance (IP_MUSIC); + } +} + +void +LoadSolarSys (void) +{ + COUNT i; + PPLANET_DESC pCurDesc; + DWORD old_seed; +#define NUM_TEMP_RANGES 5 + COLOR temp_color_array[NUM_TEMP_RANGES] = + { + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xE), 0x54), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x6, 0x8), 0x62), + BUILD_COLOR (MAKE_RGB15 (0x00, 0xB, 0x00), 0x6D), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x8, 0x00), 0x75), + }; + + pSolarSysState->MenuState.CurState = 0; + pSolarSysState->MenuState.Initialized = + HIBYTE (HIWORD (GLOBAL (ShipStamp.frame))); + if (pSolarSysState->MenuState.Initialized) + { + GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( + LOWORD (GLOBAL (ShipStamp.frame)), + LOBYTE (HIWORD (GLOBAL (ShipStamp.frame))) + ); + ++pSolarSysState->MenuState.Initialized; + } + else + { +// LoadIPData (); + } + + old_seed = SeedRandom ( + MAKE_DWORD (CurStarDescPtr->star_pt.x, + CurStarDescPtr->star_pt.y) + ); + + pCurDesc = &pSolarSysState->SunDesc[0]; + pCurDesc->pPrevDesc = 0; + pCurDesc->rand_seed = Random (); + + pCurDesc->data_index = STAR_TYPE (CurStarDescPtr->Type); + pCurDesc->location.x = pCurDesc->location.y = 0; + pCurDesc->image.origin = pCurDesc->location; + pCurDesc->image.frame = SunFrame; + + (*pSolarSysState->GenFunc) (GENERATE_PLANETS); + if (GET_GAME_STATE (PLANETARY_CHANGE)) + { + PutPlanetInfo (); + SET_GAME_STATE (PLANETARY_CHANGE, 0); + } + + for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; + i < MAX_PLANETS; ++i, ++pCurDesc) + { + pCurDesc->pPrevDesc = &pSolarSysState->SunDesc[0]; + pCurDesc->image.origin = pCurDesc->location; + if (pSolarSysState->MenuState.Initialized != 0 + || i >= pSolarSysState->SunDesc[0].NumPlanets) + pCurDesc->image.frame = 0; + else + { + COUNT index; + SYSTEM_INFO SysInfo; + + DoPlanetaryAnalysis (&SysInfo, pCurDesc); + index = (SysInfo.PlanetInfo.SurfaceTemperature + 250) / 100; + if (index >= NUM_TEMP_RANGES) + index = NUM_TEMP_RANGES - 1; + pCurDesc->temp_color = temp_color_array[index]; + } + } + + { + SIZE sort_array[MAX_PLANETS + 1]; + + for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) + sort_array[i] = i - 1; + + for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) + { + COUNT j; + + for (j = pSolarSysState->SunDesc[0].NumPlanets; j > i; --j) + { + SIZE real_i, real_j; + + real_i = sort_array[i]; + real_j = sort_array[j]; + if (pSolarSysState->PlanetDesc[real_i].image.origin.y > + pSolarSysState->PlanetDesc[real_j].image.origin.y) + { + SIZE temp; + + temp = sort_array[i]; + sort_array[i] = sort_array[j]; + sort_array[j] = temp; + } + } + } + + pSolarSysState->FirstPlanetIndex = sort_array[0]; + pSolarSysState->LastPlanetIndex = sort_array[ + pSolarSysState->SunDesc[0].NumPlanets + ]; + for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) + pSolarSysState->PlanetDesc[sort_array[i]].NextIndex = + sort_array[i + 1]; + } + + if ((i = LOBYTE (HIWORD (GLOBAL (ShipStamp.frame)))) == 0) + pSolarSysState->pBaseDesc = + pSolarSysState->pOrbitalDesc = pSolarSysState->PlanetDesc; + else + { + pSolarSysState->pOrbitalDesc = 0; + pSolarSysState->pBaseDesc = &pSolarSysState->PlanetDesc[i - 1]; + pSolarSysState->SunDesc[0].location = + GLOBAL (ip_location); + GenerateMoons (); + + SET_GAME_STATE (PLANETARY_LANDING, 0); + } + + { + BYTE i, num_thrusters; + + num_thrusters = 0; + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + if (GLOBAL_SIS (DriveSlots[i]) == FUSION_THRUSTER) + ++num_thrusters; + } + pSolarSysState->max_ship_speed = (BYTE)( + (num_thrusters + 5) * IP_SHIP_THRUST_INCREMENT + ); + + pSolarSysState->turn_wait = IP_SHIP_TURN_WAIT; + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + if (GLOBAL_SIS (JetSlots[i]) == TURNING_JETS) + pSolarSysState->turn_wait -= IP_SHIP_TURN_DECREMENT; + } + } + + i = pSolarSysState->MenuState.Initialized; + if (i) + { + if ((i -= 2) == 0) + pSolarSysState->pOrbitalDesc = pSolarSysState->pBaseDesc->pPrevDesc; + else + pSolarSysState->pOrbitalDesc = &pSolarSysState->MoonDesc[i - 1]; + pSolarSysState->MenuState.Initialized = 2; + GLOBAL (ip_location) = + pSolarSysState->SunDesc[0].location; + } + else + { + if ((i = LOWORD (GLOBAL (ShipStamp.frame))) == 0) + ++i; + + GLOBAL (ShipStamp.frame) = + SetAbsFrameIndex (SISIPFrame, i - 1); + } + + SeedRandom (old_seed); +} + +static void +FreeSolarSys (void) +{ + if (pSolarSysState->MenuState.flash_task) + { + if (pSolarSysState->MenuState.Initialized >= 3) + FreePlanet (); + else + { + SetSemaphore (&GraphicsSem); + DeleteTask (pSolarSysState->MenuState.flash_task); + pSolarSysState->MenuState.flash_task = 0; + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + extern void SaveFlagshipState (void); + + SaveFlagshipState (); + } + ClearSemaphore (&GraphicsSem); + } + } + + SetSemaphore (&GraphicsSem); + + SetContext (SpaceContext); + SetContextBGFrame ((FRAME)0); + + StopMusic (); + +// FreeIPData (); + + ClearSemaphore (&GraphicsSem); +} + +static void +CheckIntersect (BOOLEAN just_checking) +{ + COUNT i; + PPLANET_DESC pCurDesc; + INTERSECT_CONTROL ShipIntersect, PlanetIntersect; + COUNT NewWaitPlanet; + BYTE PlanetOffset, MoonOffset; + + pCurDesc = pSolarSysState->pBaseDesc->pPrevDesc; + + ShipIntersect.IntersectStamp.origin = GLOBAL (ShipStamp.origin); + ShipIntersect.EndPoint = ShipIntersect.IntersectStamp.origin; + ShipIntersect.IntersectStamp.frame = GLOBAL (ShipStamp.frame); + + PlanetIntersect.IntersectStamp.origin.x = SIS_SCREEN_WIDTH >> 1; + PlanetIntersect.IntersectStamp.origin.y = SIS_SCREEN_HEIGHT >> 1; + PlanetIntersect.EndPoint = PlanetIntersect.IntersectStamp.origin; + if (pSolarSysState->WaitIntersect != (COUNT)~0 + && pSolarSysState->WaitIntersect != MAKE_WORD ( + pCurDesc - pSolarSysState->PlanetDesc + 1, 1 + )) + PlanetIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); + else + PlanetIntersect.IntersectStamp.frame = pCurDesc->image.frame; + + NewWaitPlanet = 0; + + if (pCurDesc != pSolarSysState->SunDesc /* can't intersect with sun */ + && DrawablesIntersect (&ShipIntersect, + &PlanetIntersect, MAX_TIME_VALUE)) + { + PlanetOffset = pCurDesc - pSolarSysState->PlanetDesc + 1; + MoonOffset = 1; +//printf ("0: Planet %d, Moon %d\n", PlanetOffset, MoonOffset); + NewWaitPlanet = MAKE_WORD (PlanetOffset, MoonOffset); + if (pSolarSysState->WaitIntersect != (COUNT)~0 + && pSolarSysState->WaitIntersect != NewWaitPlanet) + { +ShowPlanet: + pSolarSysState->WaitIntersect = NewWaitPlanet; + + if (!just_checking) + { + ZeroVelocityComponents (&GLOBAL (velocity)); + ++pSolarSysState->MenuState.Initialized; + pSolarSysState->pOrbitalDesc = pCurDesc; + } + +#ifdef DEBUG +printf ("Star index = %d, Planet index = %d, <%d, %d>\n", +CurStarDescPtr - star_array, +pCurDesc - pSolarSysState->PlanetDesc, +pSolarSysState->SunDesc[0].location.x, +pSolarSysState->SunDesc[0].location.y); +#endif /* DEBUG */ + return; + } + } + + { + for (i = pCurDesc->NumPlanets, + pCurDesc = pSolarSysState->pBaseDesc; i; --i, ++pCurDesc) + { + PlanetIntersect.IntersectStamp.origin = pCurDesc->image.origin; + PlanetIntersect.EndPoint = PlanetIntersect.IntersectStamp.origin; + if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) + { + PlanetOffset = pCurDesc->pPrevDesc - pSolarSysState->PlanetDesc; + MoonOffset = pCurDesc - pSolarSysState->MoonDesc + 2; + } + else + { + PlanetOffset = pCurDesc - pSolarSysState->PlanetDesc; + MoonOffset = 0; + } + ++PlanetOffset; + if (pSolarSysState->WaitIntersect != (COUNT)~0 + && pSolarSysState->WaitIntersect != MAKE_WORD (PlanetOffset, MoonOffset)) + PlanetIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); + else + PlanetIntersect.IntersectStamp.frame = pCurDesc->image.frame; + + if (DrawablesIntersect (&ShipIntersect, + &PlanetIntersect, MAX_TIME_VALUE)) + { +//printf ("1: Planet %d, Moon %d\n", PlanetOffset, MoonOffset); + NewWaitPlanet = MAKE_WORD (PlanetOffset, MoonOffset); + + if (pSolarSysState->WaitIntersect == (COUNT)~0) + return; + else if (pSolarSysState->WaitIntersect == NewWaitPlanet) + continue; + else if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) + goto ShowPlanet; + else if (!just_checking) /* pBaseDesc == PlanetDesc */ + { + COUNT angle; + RECT r; + + angle = FACING_TO_ANGLE ( + GetFrameIndex (GLOBAL (ShipStamp.frame)) + ) + HALF_CIRCLE; + GLOBAL (ShipStamp.origin.x) = + (SIS_SCREEN_WIDTH >> 1) + COSINE ( + angle, MIN_MOON_RADIUS + + ((MAX_MOONS - 1) * MOON_DELTA) + + (MOON_DELTA >> 2) + ); + GLOBAL (ShipStamp.origin.y) = + (SIS_SCREEN_HEIGHT >> 1) + SINE ( + angle, MIN_MOON_RADIUS + + ((MAX_MOONS - 1) * MOON_DELTA) + + (MOON_DELTA >> 2) + ); + if (GLOBAL (ShipStamp.origin.y) < 0) + GLOBAL (ShipStamp.origin.y) = 1; + else if (GLOBAL (ShipStamp.origin.y) >= SIS_SCREEN_HEIGHT) + GLOBAL (ShipStamp.origin.y) = + (SIS_SCREEN_HEIGHT - 1) - 1; + pSolarSysState->pBaseDesc = pCurDesc; + XFormIPLoc ( + &pCurDesc->image.origin, + &pSolarSysState->SunDesc[0].location, + FALSE + ); + ZeroVelocityComponents (&GLOBAL (velocity)); + GenerateMoons (); + + NewWaitPlanet = 0; + BatchGraphics (); + SetGraphicGrabOther (1); + DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); + SetGraphicGrabOther (0); + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + UnbatchGraphics (); + LoadIntoExtraScreen (&r); + } + break; + } + } + } + + if (pSolarSysState->WaitIntersect != (COUNT)~0 || NewWaitPlanet == 0) + pSolarSysState->WaitIntersect = NewWaitPlanet; +} + +static void +GetOrbitRect (PRECT pRect, COORD cx, COORD cy, SIZE + radius, COUNT xnumer, COUNT ynumer, COUNT denom) +{ +#ifdef BVT_NOT + pRect->corner.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)-cx * xnumer / denom); + pRect->corner.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)-cy * ynumer / denom); + pRect->extent.width = (SIZE)(radius * (DWORD)(xnumer << 1) / denom); +#endif + pRect->corner.x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)-cx * (long)xnumer / (long)denom); + pRect->corner.y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)-cy * (long)ynumer / (long)denom); + pRect->extent.width = (SIZE)((long)radius * (long)(xnumer << 1) / (long)denom); + pRect->extent.height = pRect->extent.width >> 1; +} + +static void +DrawOrbit (PPLANET_DESC pPlanetDesc, COUNT xnumer, COUNT + ynumer0, COUNT ynumer1, COUNT denom) +{ + COUNT index; + COORD cx, cy; + RECT r; + +if (!(draw_sys_flags & (DRAW_ORBITS | DRAW_PLANETS))) + return; + + cx = cy = pPlanetDesc->radius; + if (xnumer > (COUNT)DISPLAY_FACTOR) + { + cx = cx + pPlanetDesc->location.x; + cy = (cy + pPlanetDesc->location.y) << 1; + } + GetOrbitRect (&r, cx, cy, + pPlanetDesc->radius, xnumer, ynumer0, denom); + +if (draw_sys_flags & DRAW_ORBITS) +{ + if (pSolarSysState->pBaseDesc) + { + SetContextForeGroundColor (pPlanetDesc->temp_color); + DrawOval (&r, 1); + } +} + +if (!(draw_sys_flags & DRAW_PLANETS)) + return; + + r.corner.x += (r.extent.width >> 1); + r.corner.y += (r.extent.height >> 1); + r.corner.x = r.corner.x + + (SIZE)((long)pPlanetDesc->location.x + * (long)xnumer / (long)denom); + r.corner.y = r.corner.y + + (SIZE)((long)pPlanetDesc->location.y + * (long)ynumer1 / (long)denom); + + index = pPlanetDesc->data_index & ~PLANET_SHIELDED; + if (index < NUMBER_OF_PLANET_TYPES) + { + BYTE Type; + COUNT Size; + + Type = PlanData[index].Type; + SetColorMap (GetColorMapAddress ( + SetAbsColorMapIndex (OrbitalCMap, + PLANCOLOR (Type)) + )); + + Size = PLANSIZE (Type); + if (denom == 2 || xnumer > (COUNT)DISPLAY_FACTOR) + Size += 3; + else if (denom <= (COUNT)(MAX_ZOOM_RADIUS >> 2)) + { + ++Size; + if (denom == MIN_ZOOM_RADIUS) + ++Size; + } + if (pPlanetDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) + pPlanetDesc->image.frame = + SetAbsFrameIndex (OrbitalFrame, + (Size << FACING_SHIFT) + + NORMALIZE_FACING (ANGLE_TO_FACING ( + ARCTAN (pPlanetDesc->location.x, pPlanetDesc->location.y) + ))); + else + { + --Size; + pPlanetDesc->image.frame = + SetAbsFrameIndex (OrbitalFrame, + (Size << FACING_SHIFT) + + NORMALIZE_FACING (ANGLE_TO_FACING ( + ARCTAN ( + pPlanetDesc->pPrevDesc->location.x, + pPlanetDesc->pPrevDesc->location.y + ) + ))); + } + } + + if (!(denom == 2 || xnumer > (COUNT)DISPLAY_FACTOR)) + { + pPlanetDesc->image.origin = r.corner; + } + else + { + STAMP s; + + if (denom == 2) + pPlanetDesc->image.origin = r.corner; + + s.origin = r.corner; + s.frame = pPlanetDesc->image.frame; + DrawStamp (&s); + if (index < NUMBER_OF_PLANET_TYPES + && (pPlanetDesc->data_index & PLANET_SHIELDED)) + { + s.frame = SetAbsFrameIndex (SpaceJunkFrame, 17); + DrawStamp (&s); + } + } +} + +static void +FindRadius (void) +{ + SIZE delta_x, delta_y; + SIZE radius; + + do + { + if ((pSolarSysState->SunDesc[0].radius >>= 1) > MIN_ZOOM_RADIUS) + radius = pSolarSysState->SunDesc[0].radius >> 1; + else + radius = 0; + + GetOrbitRect (&pSolarSysState->MenuState.flash_rect0, + radius, radius, radius, + DISPLAY_FACTOR, + DISPLAY_FACTOR >> 2, + pSolarSysState->SunDesc[0].radius); + + XFormIPLoc (&GLOBAL (ip_location), + &GLOBAL (ShipStamp.origin), + TRUE); + + } while (radius + && (delta_x = GLOBAL (ShipStamp.origin.x) + - pSolarSysState->MenuState.flash_rect0.corner.x) >= 0 + && (delta_y = GLOBAL (ShipStamp.origin.y) + - pSolarSysState->MenuState.flash_rect0.corner.y) >= 0 + && delta_x < pSolarSysState->MenuState.flash_rect0.extent.width + && delta_y < pSolarSysState->MenuState.flash_rect0.extent.height); +} + +void +ZoomSystem (void) +{ + RECT r; + + BatchGraphics (); + if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) + DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); + else + { + if (pSolarSysState->MenuState.CurState == 0) + FindRadius (); + + DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); + } + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + UnbatchGraphics (); + LoadIntoExtraScreen (&r); +} + +static UWORD +flagship_inertial_thrust (register COUNT CurrentAngle) +{ + BYTE max_speed; + SIZE cur_delta_x, cur_delta_y; + register COUNT TravelAngle; + register VELOCITYPTR VelocityPtr; + + max_speed = pSolarSysState->max_ship_speed; + VelocityPtr = &GLOBAL (velocity); + GetCurrentVelocityComponents (VelocityPtr, &cur_delta_x, &cur_delta_y); + if ((TravelAngle = + GetVelocityTravelAngle (VelocityPtr)) == CurrentAngle + && cur_delta_x == COSINE (CurrentAngle, max_speed) + && cur_delta_y == SINE (CurrentAngle, max_speed)) + return (SHIP_AT_MAX_SPEED); + else + { + register SIZE delta_x, delta_y; + DWORD desired_speed; + + delta_x = cur_delta_x + + COSINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT); + delta_y = cur_delta_y + + SINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT); + desired_speed = (DWORD) ((long) delta_x * delta_x) + + (DWORD) ((long) delta_y * delta_y); + if (desired_speed <= (DWORD) ((UWORD) max_speed * max_speed)) + SetVelocityComponents (VelocityPtr, delta_x, delta_y); + else if (TravelAngle == CurrentAngle) + { + SetVelocityComponents (VelocityPtr, + COSINE (CurrentAngle, max_speed), + SINE (CurrentAngle, max_speed)); + return (SHIP_AT_MAX_SPEED); + } + else + { + VELOCITY_DESC v; + + v = *VelocityPtr; + + DeltaVelocityComponents (&v, + COSINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT >> 1) + - COSINE (TravelAngle, IP_SHIP_THRUST_INCREMENT), + SINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT >> 1) + - SINE (TravelAngle, IP_SHIP_THRUST_INCREMENT)); + GetCurrentVelocityComponents (&v, &cur_delta_x, &cur_delta_y); + desired_speed = + (DWORD) ((long) cur_delta_x * cur_delta_x) + + (DWORD) ((long) cur_delta_y * cur_delta_y); + if (desired_speed > (DWORD) ((UWORD) max_speed * max_speed)) + { + SetVelocityComponents (VelocityPtr, + COSINE (CurrentAngle, max_speed), + SINE (CurrentAngle, max_speed)); + return (SHIP_AT_MAX_SPEED); + } + + *VelocityPtr = v; + } + + return (0); + } +} + +extern void DrawIPRadar (BOOLEAN FirstTime); + +static void +UndrawShip (INPUT_STATE InputState) +{ + COUNT index; + SIZE radius, delta_x, delta_y; + BOOLEAN LeavingInnerSystem; + + ClockTick (); + +#ifdef SHOW_RADAR + DrawIPRadar (FALSE); +#endif /* SHOW_RADAR */ + + delta_x = GetInputXComponent (InputState); +// delta_y = GetInputYComponent (InputState); + if (InputState & DEVICE_BUTTON1) + delta_y = -1; + else + delta_y = GetInputYComponent (InputState); + + if (delta_x || delta_y < 0) + { + GLOBAL (autopilot.x) = + GLOBAL (autopilot.y) = ~0; + } + else if (GLOBAL (autopilot.x) != ~0 + && GLOBAL (autopilot.y) != ~0) + delta_y = -1; + else + delta_y = 0; + + index = GetFrameIndex (GLOBAL (ShipStamp.frame)); + if (pSolarSysState->turn_counter) + --pSolarSysState->turn_counter; + else if (delta_x) + { + if (delta_x < 0) + index = NORMALIZE_FACING (index - 1); + else + index = NORMALIZE_FACING (index + 1); + + GLOBAL (ShipStamp.frame) = + SetAbsFrameIndex (GLOBAL (ShipStamp.frame), + index); + + pSolarSysState->turn_counter = pSolarSysState->turn_wait; + } + if (pSolarSysState->thrust_counter) + --pSolarSysState->thrust_counter; + else if (delta_y < 0) + { +#define THRUST_WAIT 1 + flagship_inertial_thrust (FACING_TO_ANGLE (index)); + + pSolarSysState->thrust_counter = THRUST_WAIT; + } + + LeavingInnerSystem = FALSE; + radius = pSolarSysState->SunDesc[0].radius; + if (GLOBAL (ShipStamp.origin.x) < 0 + || GLOBAL (ShipStamp.origin.x) >= SIS_SCREEN_WIDTH + || GLOBAL (ShipStamp.origin.y) < 0 + || GLOBAL (ShipStamp.origin.y) >= SIS_SCREEN_HEIGHT) + { + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + { + if (radius == MAX_ZOOM_RADIUS) + { + GLOBAL (CurrentActivity) |= END_INTERPLANETARY; + return; + } + } + else + { + PPLANET_DESC pPlanetDesc; + + LeavingInnerSystem = TRUE; + pPlanetDesc = pSolarSysState->pBaseDesc->pPrevDesc; + pSolarSysState->pBaseDesc = pSolarSysState->PlanetDesc; + + pSolarSysState->WaitIntersect = MAKE_WORD ( + pPlanetDesc - pSolarSysState->PlanetDesc + 1, 0 + ); + GLOBAL (ip_location) = + pSolarSysState->SunDesc[0].location; + ZeroVelocityComponents (&GLOBAL (velocity)); + } + + radius = MAX_ZOOM_RADIUS << 1; + } + + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc + && (radius > MAX_ZOOM_RADIUS + || ((delta_x = GLOBAL (ShipStamp.origin.x) + - pSolarSysState->MenuState.flash_rect0.corner.x) >= 0 + && (delta_y = GLOBAL (ShipStamp.origin.y) + - pSolarSysState->MenuState.flash_rect0.corner.y) >= 0 + && delta_x < pSolarSysState->MenuState.flash_rect0.extent.width + && delta_y < pSolarSysState->MenuState.flash_rect0.extent.height))) + { + old_radius = pSolarSysState->SunDesc[0].radius; + pSolarSysState->SunDesc[0].radius = radius; + FindRadius (); + if (old_radius == (MAX_ZOOM_RADIUS << 1) + || old_radius == pSolarSysState->SunDesc[0].radius + || LeavingInnerSystem) + { + old_radius = 0; + if (LeavingInnerSystem) + SetGraphicGrabOther (1); + DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); + if (LeavingInnerSystem) + { + COUNT OldWI; + + SetGraphicGrabOther (0); + OldWI = pSolarSysState->WaitIntersect; + CheckIntersect (TRUE); + if (pSolarSysState->WaitIntersect != OldWI) + { + pSolarSysState->WaitIntersect = (COUNT)~0; + return; + } + } + } + else + return; + } + + if (GLOBAL (autopilot.x) == ~0 + && GLOBAL (autopilot.y) == ~0) + CheckIntersect (FALSE); +} + +#if 0 +static void +DrawSimpleSystem (SIZE radius, BYTE flags) +{ + draw_sys_flags &= ~flags; + DrawSystem (radius, FALSE); + draw_sys_flags |= flags; +} +#endif + +static void +ScaleSystem (void) +{ +#if 0 +#define NUM_STEPS 8 + COUNT num_steps; + SIZE err, d, new_radius, step; + RECT r; + BOOLEAN first_time; + CONTEXT OldContext; + + first_time = TRUE; + new_radius = pSolarSysState->SunDesc[0].radius; + + BatchGraphics (); + DrawSimpleSystem (new_radius, DRAW_PLANETS | DRAW_ORBITS | GRAB_BKGND); + + pSolarSysState->SunDesc[0].radius = old_radius; + + d = new_radius - old_radius; + step = d / NUM_STEPS; + if (d < 0) + d = -d; + + num_steps = err = NUM_STEPS; + + OldContext = SetContext (SpaceContext); + GetContextClipRect (&r); + SetGraphicGrabOther (1); // to grab from hidden screen (since we haven't flipped yet) + LoadIntoExtraScreen (&r); + SetContextBGFrame ((FRAME)0); + SetGraphicGrabOther (0); + SetContextFGFrame (Screen); + + do + { + if ((err -= d) <= 0) + { + pSolarSysState->SunDesc[0].radius += step; + + BatchGraphics (); + + DrawFromExtraScreen (r.corner.x, r.corner.y); + + DrawSimpleSystem (pSolarSysState->SunDesc[0].radius, + DRAW_ORBITS | DRAW_STARS | GRAB_BKGND | DRAW_HYPER_COORDS); + + RedrawQueue (FALSE); + + if (first_time) + { + first_time = FALSE; + UnbatchGraphics (); // to balance out Batch before DrawSimpleSystem above + } + + UnbatchGraphics (); + + err += d; + } + } while (--num_steps); + + SetContext (OldContext); + pSolarSysState->SunDesc[0].radius = new_radius; + DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); + old_radius = 0; +#else + RECT r; + CONTEXT OldContext; + + OldContext = SetContext (SpaceContext); + BatchGraphics (); + DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); + GetContextClipRect (&r); + ScreenTransition (3, &r); + UnbatchGraphics (); + LoadIntoExtraScreen (&r); + SetContext (OldContext); + + old_radius = 0; +#endif +} + +int IPtask_func(void* blah) +{ +#define IP_FRAME_RATE 4 +#define DEBOUNCE_DELAY ((ONE_SECOND >> 1) / IP_FRAME_RATE) + BYTE MenuTransition; + DWORD NextTime; + INPUT_STATE InputState; + + TaskSwitch (); + + if (LastActivity != CHECK_LOAD) + InputState = 0; + else + InputState = DEVICE_BUTTON2; + + MenuTransition = 0; + NextTime = GetTimeCounter (); + for (;;) + { + CONTEXT OldContext; + BOOLEAN InnerSystem; + RECT r; + + InnerSystem = FALSE; + SetSemaphore (&GraphicsSem); + while (pSolarSysState->MenuState.Initialized > 1 + || (GLOBAL (CurrentActivity) + & (START_ENCOUNTER | END_INTERPLANETARY + | CHECK_ABORT | CHECK_LOAD)) + || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0) + { + InputState = 0; + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + NextTime = SetSemaphore (&GraphicsSem); + } + + OldContext = SetContext (StatusContext); + if (pSolarSysState->MenuState.CurState + || pSolarSysState->MenuState.Initialized == 0) + { + InputState = 0; + if (draw_sys_flags & DRAW_REFRESH) + goto TheMess; + } + else + { + if (MenuTransition) + { + if (MenuTransition < DEBOUNCE_DELAY + && !(InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2))) + MenuTransition = 0; + else + { + --MenuTransition; + InputState &= ~(DEVICE_BUTTON1 | DEVICE_BUTTON2); + } + } + +TheMess: + // this is a mess: + // we have to treat things slightly differently depending on the + // situation (note that DRAW_REFRESH means we had gone to the + // menu) + InnerSystem = (BOOLEAN) (pSolarSysState->pBaseDesc != + pSolarSysState->PlanetDesc); + if (InnerSystem) + { + BatchGraphics (); + if (draw_sys_flags & DRAW_REFRESH) + { + InnerSystem = FALSE; + DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); + } + } + else if (draw_sys_flags & DRAW_REFRESH) + { + BatchGraphics (); + DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); + } + + if (MenuTransition < DEBOUNCE_DELAY) + UndrawShip (InputState); + if (pSolarSysState->MenuState.Initialized != 1) + InputState = 0; + } + + if (old_radius) + ScaleSystem (); + + BatchGraphics (); + + if (!(draw_sys_flags & DRAW_REFRESH)) // don't repair from Extra or draw ship if forcing repair + { + CONTEXT OldContext; + + OldContext = SetContext (SpaceContext); + GetContextClipRect (&r); + DrawFromExtraScreen (&r); + SetContext (OldContext); + + // Don't redraw if entering/exiting inner system + // this screws up ScreenTransition by leaving an image of the + // ship in the ExtraScreen (which we use for repair) + if (pSolarSysState->MenuState.CurState == 0 + && (InnerSystem ^ (BOOLEAN)(pSolarSysState->pBaseDesc != pSolarSysState->PlanetDesc))) + ; + else + RedrawQueue (FALSE); + } + + if (InnerSystem) + { + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + { + // transition screen if we left inner system (if going + // from outer to inner, ScreenTransition happens elsewhere) + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + } + UnbatchGraphics (); + } + else if (draw_sys_flags & DRAW_REFRESH) + { + // must set rect for LoadInto... below + r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SIS_SCREEN_HEIGHT; + ScreenTransition (3, &r); + UnbatchGraphics (); + } + + UnbatchGraphics (); + + if (draw_sys_flags & UNBATCH_SYS) + { + // means we're forcing a redraw/transition from Init- & ChangeSolarSys + draw_sys_flags &= ~UNBATCH_SYS; + UnbatchGraphics (); + } + + // LoadInto Extra if we left inner system, or we forced a redraw + if ((InnerSystem && pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + || (draw_sys_flags & DRAW_REFRESH)) + { + LoadIntoExtraScreen (&r); + draw_sys_flags &= ~DRAW_REFRESH; + } + + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + + if (!(InputState & DEVICE_BUTTON2)) + { + NextTime = SleepTask (NextTime + IP_FRAME_RATE); + if (pSolarSysState->MenuState.CurState + || pSolarSysState->MenuState.Initialized != 1) + InputState = 0; + else + InputState = GetInputState (NormalInput); + JournalInput (InputState); + + if (InputState & DEVICE_EXIT) + InputState = ConfirmExit (); + } + else + { + MenuTransition = DEBOUNCE_DELAY; + SuspendGameClock (); + + SetSemaphore (&GraphicsSem); + DrawStatusMessage (NULL_PTR); + if (LastActivity == CHECK_LOAD) + pSolarSysState->MenuState.CurState = (ROSTER + 1) + 1; + else + { + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings (PM_SCAN, STARMAP); + SetSemaphore (&GraphicsSem); + pSolarSysState->MenuState.CurState = STARMAP + 1; + } + SetFlashRect ((PRECT)~0L, (FRAME)0); + FlushInput (); + ClearSemaphore (&GraphicsSem); + } + } + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static void +DrawInnerSystem (void) +{ + SetSemaphore (&GraphicsSem); + DrawSISTitle (GLOBAL_SIS (PlanetName)); + DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); + ClearSemaphore (&GraphicsSem); +} + +static BOOLEAN +ValidateOrbits (void) +{ + BYTE i; + BOOLEAN InnerSystem; + POINT old_pts[2]; + PPLANET_DESC pCurDesc; + + InnerSystem = (BOOLEAN)( + pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc + ); + if (InnerSystem) + { + old_pts[0] = GLOBAL (ShipStamp.origin); + old_pts[1] = GLOBAL (ip_location); + GLOBAL (ip_location) = + pSolarSysState->SunDesc[0].location; + } + + pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS << 1; + FindRadius (); + + pSolarSysState->pBaseDesc = 0; + for (i = pSolarSysState->SunDesc[0].NumPlanets, + pCurDesc = &pSolarSysState->PlanetDesc[0]; + i; --i, ++pCurDesc) + { + DrawOrbit (pCurDesc, + DISPLAY_FACTOR, + DISPLAY_FACTOR >> 2, + DISPLAY_FACTOR >> 1, + pSolarSysState->SunDesc[0].radius); + } + + if (!InnerSystem) + pSolarSysState->pBaseDesc = pSolarSysState->PlanetDesc; + else + { + pSolarSysState->pBaseDesc = pSolarSysState->MoonDesc; + GLOBAL (ShipStamp.origin) = old_pts[0]; + GLOBAL (ip_location) = old_pts[1]; + } + + return (InnerSystem); +} + +void +ChangeSolarSys (void) +{ + if (pSolarSysState->MenuState.Initialized == 0) + { +StartGroups: + ++pSolarSysState->MenuState.Initialized; + if (pSolarSysState->MenuState.flash_task == 0) + { + DrawMenuStateStrings (PM_SCAN, PM_NAVIGATE - PM_SCAN); + + SetSemaphore (&GraphicsSem); + RepairSISBorder (); + + InitDisplayList (); + DoMissions (); + + // if entering new system (NOT from load), + // force redraw and transition in IPtask_func + if ((draw_sys_flags & UNBATCH_SYS) + && LastActivity != (CHECK_LOAD | CHECK_RESTART)) + draw_sys_flags |= DRAW_REFRESH; + + CheckIntersect (TRUE); + + pSolarSysState->MenuState.flash_task = + AddTask (IPtask_func, 6144); + ClearSemaphore (&GraphicsSem); + + if (!PLRPlaying ((MUSIC_REF)~0) && LastActivity != CHECK_LOAD) + { + PlayMusic (SpaceMusic, TRUE, 1); + if (LastActivity == (CHECK_LOAD | CHECK_RESTART)) + { + BYTE clut_buf[] = {FadeAllToColor}; + + LastActivity = 0; + if (draw_sys_flags & UNBATCH_SYS) + { + draw_sys_flags &= ~UNBATCH_SYS; + UnbatchGraphics (); + } + SetSemaphore (&GraphicsSem); + while (pSolarSysState->SunDesc[0].radius == (MAX_ZOOM_RADIUS << 1)) + { + ClearSemaphore (&GraphicsSem); + TaskSwitch (); + SetSemaphore (&GraphicsSem); + } + ClearSemaphore (&GraphicsSem); + XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); + } + } + + ResumeGameClock (); + SetGameClockRate (INTERPLANETARY_CLOCK_RATE); + } + } + else + { + if (pSolarSysState->MenuState.flash_task) + { + SuspendGameClock (); + FreeSolarSys (); + + if (pSolarSysState->pOrbitalDesc->pPrevDesc != + &pSolarSysState->SunDesc[0]) + GLOBAL (ShipStamp.origin) = + pSolarSysState->pOrbitalDesc->image.origin; + else + { + GLOBAL (ShipStamp.origin.x) = + SIS_SCREEN_WIDTH >> 1; + GLOBAL (ShipStamp.origin.y) = + SIS_SCREEN_HEIGHT >> 1; + } + + } + + GetPlanetInfo (); + (*pSolarSysState->GenFunc) (GENERATE_ORBITAL); + LastActivity &= ~(CHECK_LOAD | CHECK_RESTART); + if ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD | START_ENCOUNTER)) + || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + return; + + if (pSolarSysState->MenuState.flash_task == 0) + { + LoadSolarSys (); + ValidateOrbits (); + DrawInnerSystem (); + + goto StartGroups; + } + else + { + DrawMenuStateStrings (PM_SCAN, SCAN); + SetSemaphore (&GraphicsSem); + pSolarSysState->MenuState.CurState = SCAN + 1; + SetFlashRect ((PRECT)~0L, (FRAME)0); + FlushInput (); + ClearSemaphore (&GraphicsSem); + } + } +} + +static void +InitSolarSys (void) +{ + BOOLEAN InnerSystem; + BOOLEAN Reentry; + + SetSemaphore (&GraphicsSem); + +LoadIPData (); +LoadLanderData (); + ClearSemaphore (&GraphicsSem); + + pSolarSysState->MenuState.InputFunc = DoFlagshipCommands; + + Reentry = (BOOLEAN)(GLOBAL (ShipStamp.frame) != 0); + if (!Reentry) + { + GLOBAL (autopilot.x) = + GLOBAL (autopilot.y) = ~0; + + GLOBAL (ShipStamp.origin.x) = SIS_SCREEN_WIDTH >> 1; + GLOBAL (ShipStamp.origin.y) = SIS_SCREEN_HEIGHT >> 1; + GLOBAL (ShipStamp.origin.y) += (SIS_SCREEN_HEIGHT >> 1) - 1; + + pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS; + XFormIPLoc (&GLOBAL (ShipStamp.origin), + &GLOBAL (ip_location), + FALSE); + } + + LoadSolarSys (); + InnerSystem = ValidateOrbits (); + + if (Reentry) + { + (*pSolarSysState->GenFunc) (REINIT_NPCS); + } + else + { + battle_counter = 0; + GLOBAL (BattleGroupRef) = 0; + ReinitQueue (&GLOBAL (npc_built_ship_q)); + (*pSolarSysState->GenFunc) (INIT_NPCS); + } + + if (pSolarSysState->MenuState.Initialized == 0) + { + BatchGraphics (); + draw_sys_flags |= UNBATCH_SYS; + + if (LastActivity & (CHECK_LOAD | CHECK_RESTART)) + { + if ((LastActivity & (CHECK_LOAD | CHECK_RESTART)) == LastActivity) + { + extern ACTIVITY NextActivity; + + DrawSISFrame (); + if (NextActivity) + LastActivity &= ~(CHECK_LOAD | CHECK_RESTART); + } + else + { + SetSemaphore (&GraphicsSem); + ClearSISRect (DRAW_SIS_DISPLAY); + ClearSemaphore (&GraphicsSem); + + LastActivity &= ~CHECK_LOAD; + } + } + +// SetSemaphore (&GraphicsSem); + DrawSISMessage (NULL_PTR); + SetContext (SpaceContext); + SetContextFGFrame (Screen); + SetContextBGFrame ((FRAME)0); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContextBackGroundColor (BLACK_COLOR); +// ClearSemaphore (&GraphicsSem); + + if (InnerSystem) + { + SetGraphicGrabOther (1); // since Unbatch won't have flipped yet + DrawInnerSystem (); + SetGraphicGrabOther (0); + if (draw_sys_flags & UNBATCH_SYS) + { + draw_sys_flags &= ~UNBATCH_SYS; + ScreenTransition (3, 0); + UnbatchGraphics (); + LoadIntoExtraScreen (0); + } + } + else + { + SetSemaphore (&GraphicsSem); + DrawHyperCoords (CurStarDescPtr->star_pt); /* Adjust position */ + ClearSemaphore (&GraphicsSem); + + /* force a redraw */ + pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS << 1; + } + } +} + +static void +UninitSolarSys (void) +{ + FreeSolarSys (); + +//FreeLanderData (); +//FreeIPData (); + + if (GLOBAL (CurrentActivity) & END_INTERPLANETARY) + { + GLOBAL (CurrentActivity) &= ~END_INTERPLANETARY; + (*pSolarSysState->GenFunc) (UNINIT_NPCS); + + SET_GAME_STATE (USED_BROADCASTER, 0); + } + else if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) && battle_counter) + { + GetGroupInfo (GLOBAL (BattleGroupRef), (BYTE)battle_counter); + if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) + { + BYTE i; + DWORD best_dist; + PPLANET_DESC pCurDesc; + + best_dist = ~0L; + for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; + i < pSolarSysState->SunDesc[0].NumPlanets; ++i, ++pCurDesc) + { + SIZE dx, dy; + DWORD dist; + + dx = GLOBAL (ShipStamp.origin.x) + - pCurDesc->image.origin.x; + dy = GLOBAL (ShipStamp.origin.y) + - pCurDesc->image.origin.y; + if ((dist = (DWORD)((long)dx * dx + (long)dy * dy)) < best_dist) + { + best_dist = dist; + pSolarSysState->pBaseDesc = pCurDesc; + } + } + + (*pSolarSysState->GenFunc) (GENERATE_NAME); + } + } +} + +void +GenerateRandomIP (BYTE control) +{ + COUNT i; + DWORD rand_val; + PPLANET_DESC pCurDesc; + + switch (control) + { + case INIT_NPCS: + if (!GetGroupInfo (GLOBAL (BattleGroupRef), (BYTE)~0)) + { + GLOBAL (BattleGroupRef) = 0; + BuildGroups (); + } + break; + case REINIT_NPCS: + GetGroupInfo (0L, 0); + break; + case UNINIT_NPCS: + PutGroupInfo (0L, (BYTE)~0); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + break; + case GENERATE_MINERAL: + GenerateMineralDeposits (&pSolarSysState->SysInfo, &pSolarSysState->CurNode); + break; + case GENERATE_ENERGY: + pSolarSysState->CurNode = 0; + break; + case GENERATE_LIFE: + GenerateLifeForms (&pSolarSysState->SysInfo, &pSolarSysState->CurNode); + break; + case GENERATE_ORBITAL: + { +#ifdef DEBUG +if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) + printf ("Planet index = %d\n", pSolarSysState->pOrbitalDesc - pSolarSysState->PlanetDesc); +else + printf ("Planet index = %d, Moon index = %d\n", + pSolarSysState->pOrbitalDesc->pPrevDesc - pSolarSysState->PlanetDesc, + pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc); +#endif /* DEBUG */ + rand_val = DoPlanetaryAnalysis ( + &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc + ); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + i = (COUNT)~0; + rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; + i = (COUNT)~0; + GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); + + pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; + LoadPlanet (FALSE); + break; + } + case GENERATE_NAME: + { + i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; + wsprintf (GLOBAL_SIS (PlanetName), "%s", GAME_STRING (PLANET_NUMBER_BASE + (9 + 7) + i)); + SET_GAME_STATE (BATTLE_PLANET, pSolarSysState->PlanetDesc[i].data_index); + break; + } + case GENERATE_MOONS: + FillOrbits ( + pSolarSysState->pBaseDesc->NumPlanets, + &pSolarSysState->MoonDesc[0], FALSE + ); + break; + case GENERATE_PLANETS: + { + FillOrbits ((BYTE)~0, &pSolarSysState->PlanetDesc[0], FALSE); + for (i = pSolarSysState->SunDesc[0].NumPlanets, + pCurDesc = &pSolarSysState->PlanetDesc[0]; i; --i, ++pCurDesc) + { + BYTE byte_val; + BYTE num_moons; + + rand_val = Random (); + byte_val = LOBYTE (rand_val); + + num_moons = 0; + switch (PLANSIZE (PlanData[ + pCurDesc->data_index & ~PLANET_SHIELDED + ].Type)) + { + case LARGE_ROCKY_WORLD: + if (byte_val < 0x00FF * 25 / 100) + { + if (byte_val < 0x00FF * 5 / 100) + ++num_moons; + ++num_moons; + } + break; + case GAS_GIANT: + if (byte_val < 0x00FF * 90 / 100) + { + if (byte_val < 0x00FF * 75 / 100) + { + if (byte_val < 0x00FF * 50 / 100) + { + if (byte_val < 0x00FF * 25 / 100) + ++num_moons; + ++num_moons; + } + ++num_moons; + } + ++num_moons; + } + break; + } + pCurDesc->NumPlanets = num_moons; + } + break; + } + } +} + +void +DrawSystem (SIZE radius, BOOLEAN IsInnerSystem) +{ + BYTE i; + PPLANET_DESC pCurDesc, pBaseDesc; + + BatchGraphics (); + if (draw_sys_flags & DRAW_STARS) + DrawStarBackGround (FALSE); + + if (!IsInnerSystem) + { + pBaseDesc = pSolarSysState->PlanetDesc; + pSolarSysState->pOrbitalDesc = 0; + } + else + { + pBaseDesc = pSolarSysState->pBaseDesc; + + pCurDesc = pBaseDesc->pPrevDesc; + pSolarSysState->pOrbitalDesc = pCurDesc; + DrawOrbit (pCurDesc, + DISPLAY_FACTOR << 2, + DISPLAY_FACTOR, + DISPLAY_FACTOR << 1, + radius); + } + + for (i = pBaseDesc->pPrevDesc->NumPlanets, + pCurDesc = pBaseDesc; i; --i, ++pCurDesc) + { + if (IsInnerSystem) + DrawOrbit (pCurDesc, 2, 1, 1, 2); + else + DrawOrbit (pCurDesc, + DISPLAY_FACTOR, + DISPLAY_FACTOR >> 2, + DISPLAY_FACTOR >> 1, + radius); + } + + if (IsInnerSystem) + DrawSISTitle (GLOBAL_SIS (PlanetName)); + else + { + SIZE index; + + index = 0; + if (radius <= (MAX_ZOOM_RADIUS >> 1)) + { + ++index; + if (radius <= (MAX_ZOOM_RADIUS >> 2)) + ++index; + } + + pCurDesc = &pSolarSysState->SunDesc[0]; + pCurDesc->image.origin.x = SIS_SCREEN_WIDTH >> 1; + pCurDesc->image.origin.y = SIS_SCREEN_HEIGHT >> 1; + pCurDesc->image.frame = + SetRelFrameIndex (SunFrame, index); + + index = pSolarSysState->FirstPlanetIndex; + if (draw_sys_flags & DRAW_PLANETS) + { + for (;;) + { + pCurDesc = &pSolarSysState->PlanetDesc[index]; + SetColorMap (GetColorMapAddress ( + SetAbsColorMapIndex (OrbitalCMap, + PLANCOLOR (PlanData[pCurDesc->data_index].Type)) + )); + DrawStamp (&pCurDesc->image); + if (index == pSolarSysState->LastPlanetIndex) + break; + index = pCurDesc->NextIndex; + } + } + + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + XFormIPLoc (&GLOBAL (ip_location), + &GLOBAL (ShipStamp.origin), + TRUE); + else + XFormIPLoc (&pSolarSysState->SunDesc[0].location, + &GLOBAL (ShipStamp.origin), + TRUE); + + if (draw_sys_flags & DRAW_HYPER_COORDS) + DrawHyperCoords (CurStarDescPtr->star_pt); + } + + UnbatchGraphics (); + + SetContext (SpaceContext); + + if (draw_sys_flags & GRAB_BKGND) + { + RECT r; + + GetContextClipRect (&r); + LoadIntoExtraScreen (&r); + } + +// pSolarSysState->WaitIntersect = TRUE; +} + +void +DrawStarBackGround (BOOLEAN ForPlanet) +{ + COUNT i, j; + DWORD rand_val; + STAMP s; + DWORD old_seed; + + SetContext (SpaceContext); + SetContextBGFrame ((FRAME)0); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + SetContextBackGroundColor (BLACK_COLOR); + + ClearDrawable (); + + old_seed = SeedRandom ( + MAKE_DWORD (CurStarDescPtr->star_pt.x, + CurStarDescPtr->star_pt.y) + ); + +#define NUM_DIM_PIECES 8 + s.frame = SpaceJunkFrame; + for (i = 0; i < NUM_DIM_PIECES; ++i) + { +#define NUM_DIM_DRAWN 5 + for (j = 0; j < NUM_DIM_DRAWN; ++j) + { + rand_val = Random (); + s.origin.x = LOWORD (rand_val) % SIS_SCREEN_WIDTH; + s.origin.y = HIWORD (rand_val) % SIS_SCREEN_HEIGHT; + + DrawStamp (&s); + } + s.frame = IncFrameIndex (s.frame); + } +#define NUM_BRT_PIECES 8 + for (i = 0; i < NUM_BRT_PIECES; ++i) + { +#define NUM_BRT_DRAWN 30 + for (j = 0; j < NUM_BRT_DRAWN; ++j) + { + rand_val = Random (); + s.origin.x = LOWORD (rand_val) % SIS_SCREEN_WIDTH; + s.origin.y = HIWORD (rand_val) % SIS_SCREEN_HEIGHT; + + DrawStamp (&s); + } + s.frame = IncFrameIndex (s.frame); + } + + if (ForPlanet) + { + RECT r; + + if (pSolarSysState->MenuState.flash_task + || (LastActivity & CHECK_LOAD)) + RenderTopography (TRUE); + + BatchGraphics (); + + SetContext (ScreenContext); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + r.corner.x = SIS_ORG_X - 1; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 4; + r.extent.width = SIS_SCREEN_WIDTH + 2; + r.extent.height = 3; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.extent.width = 1; + r.extent.height = MAP_HEIGHT + 1; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; + r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; + DrawFilledRectangle (&r); + r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH; + DrawFilledRectangle (&r); + r.extent.width = SIS_SCREEN_WIDTH + 1; + r.extent.height = 1; + r.corner.x = SIS_ORG_X; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 5; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 1; + r.extent.width = MAP_WIDTH + 2; + r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; + DrawFilledRectangle (&r); + r.extent.width = 1; + r.extent.height = MAP_HEIGHT + 1; + r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; + r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; + DrawFilledRectangle (&r); + + UnbatchGraphics (); + } + + SeedRandom (old_seed); +} + +void +XFormIPLoc (PPOINT pIn, PPOINT pOut, BOOLEAN ToDisplay) +{ + if (ToDisplay) + { + pOut->x = (SIS_SCREEN_WIDTH >> 1) + + (SIZE)((long)pIn->x + * (DISPLAY_FACTOR >> 1) +// / (long)pSolarSysState->SunDesc[0].radius); + / pSolarSysState->SunDesc[0].radius); + pOut->y = (SIS_SCREEN_HEIGHT >> 1) + + (SIZE)((long)pIn->y + * (DISPLAY_FACTOR >> 1) +// / (long)pSolarSysState->SunDesc[0].radius); + / pSolarSysState->SunDesc[0].radius); + } + else + { + pOut->x = (SIZE)((long)(pIn->x + - (SIS_SCREEN_WIDTH >> 1)) +// * (long)pSolarSysState->SunDesc[0].radius + * pSolarSysState->SunDesc[0].radius + / (DISPLAY_FACTOR >> 1)); + pOut->y = (SIZE)((long)(pIn->y + - (SIS_SCREEN_HEIGHT >> 1)) +// * (long)pSolarSysState->SunDesc[0].radius + * pSolarSysState->SunDesc[0].radius + / (DISPLAY_FACTOR >> 1)); + } +} + +void +ExploreSolarSys (void) +{ + SOLARSYS_STATE SolarSysState; + + if (CurStarDescPtr == 0) + { + POINT universe; + + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + if ((CurStarDescPtr = FindStar (0, &universe, 1, 1)) == 0) + ; + } + GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (CurStarDescPtr->star_pt.x); + GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (CurStarDescPtr->star_pt.y); + + pSolarSysState = &SolarSysState; + + memset (pSolarSysState, 0, sizeof (*pSolarSysState)); + + SolarSysState.GenFunc = GenerateIP (CurStarDescPtr->Index); + + InitSolarSys (); + DoInput ((PVOID)&SolarSysState.MenuState); + UninitSolarSys (); + pSolarSysState = 0; +} + diff --git a/sc2/src/sc2code/planets/sundata.h b/sc2/src/sc2code/planets/sundata.h new file mode 100644 index 000000000..b09c5a4a4 --- /dev/null +++ b/sc2/src/sc2code/planets/sundata.h @@ -0,0 +1,59 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SUNDATA_H +#define _SUNDATA_H + +/*------------------------------ Global Data ------------------------------ */ + +#define NUMBER_OF_SUN_SIZES (SUPER_GIANT_STAR - DWARF_STAR + 1) + +#define DWARF_ENERGY 1 +#define GIANT_ENERGY 5 +#define SUPERGIANT_ENERGY 20 + +typedef struct +{ + BYTE StarSize; + BYTE StarIntensity; + UWORD StarEnergy; + + PLANET_INFO PlanetInfo; +} SYSTEM_INFO; +typedef SYSTEM_INFO *PSYSTEM_INFO; + +#define SYSTEM_INFOPTR PSYSTEM_INFO + +extern DWORD GenerateMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, PCOUNT + pwhich_deposit); +extern DWORD GenerateLifeForms (SYSTEM_INFOPTR SysInfoPtr, PCOUNT + pwhich_life); + +#define DWARF_ELEMENT_DENSITY 1 +#define GIANT_ELEMENT_DENSITY 3 +#define SUPERGIANT_ELEMENT_DENSITY 8 + +#define MAX_ELEMENT_DENSITY ((MAX_ELEMENT_UNITS * SUPERGIANT_ELEMENT_DENSITY) << 1) + +extern DWORD DoPlanetaryAnalysis (SYSTEM_INFOPTR SysInfoPtr, PPLANET_DESC + pPlanetDesc); + +extern SYSTEM_INFO CurSysInfo; + +#endif /* _SUNDATA_H */ + diff --git a/sc2/src/sc2code/planets/surface.c b/sc2/src/sc2code/planets/surface.c new file mode 100644 index 000000000..3ab2cf253 --- /dev/null +++ b/sc2/src/sc2code/planets/surface.c @@ -0,0 +1,258 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "lifeform.h" + +const BYTE *Elements; +const PlanetFrame *PlanData; + +static COUNT +CalcMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, COUNT which_deposit) +{ + BYTE j; + COUNT num_deposits; + ELEMENT_ENTRYPTR eptr; + + eptr = &SysInfoPtr->PlanetInfo.PlanDataPtr->UsefulElements[0]; + num_deposits = 0; + j = NUM_USEFUL_ELEMENTS; + do + { + BYTE num_possible; + + num_possible = (BYTE)((BYTE)Random () + % (DEPOSIT_QUANTITY (eptr->Density) + 1)); + while (num_possible--) + { +#define MEDIUM_DEPOSIT_THRESHOLD 150 +#define LARGE_DEPOSIT_THRESHOLD 225 + DWORD rand_val; + UWORD loword, hiword; + COUNT deposit_quality_fine, + deposit_quality_gross; + + deposit_quality_fine = ((COUNT)Random () % 100) + + ( + DEPOSIT_QUALITY (eptr->Density) + + SysInfoPtr->StarSize + ) * 50; + if (deposit_quality_fine < MEDIUM_DEPOSIT_THRESHOLD) + deposit_quality_gross = 0; + else if (deposit_quality_fine < LARGE_DEPOSIT_THRESHOLD) + deposit_quality_gross = 1; + else + deposit_quality_gross = 2; + + rand_val = Random (); + loword = LOWORD (rand_val); + hiword = HIWORD (rand_val); + SysInfoPtr->PlanetInfo.CurPt.x = + (LOBYTE (loword) % (MAP_WIDTH - (8 << 1))) + 8; + SysInfoPtr->PlanetInfo.CurPt.y = + (HIBYTE (loword) % (MAP_HEIGHT - (8 << 1))) + 8; + + SysInfoPtr->PlanetInfo.CurDensity = + MAKE_WORD ( + deposit_quality_gross, deposit_quality_fine / 10 + 1 + ); + SysInfoPtr->PlanetInfo.CurType = eptr->ElementType; +#ifdef DEBUG + //printf ("\t\t%d units of %Fs\n", + // SysInfoPtr->PlanetInfo.CurDensity, + // Elements[eptr->ElementType].name); +#endif /* DEBUG */ + if ((num_deposits >= which_deposit + && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] + & (1L << num_deposits))) + || ++num_deposits == sizeof (DWORD) * 8) + goto ExitCalcMinerals; + } + ++eptr; + } while (--j); + +ExitCalcMinerals: + return (num_deposits); +} + +DWORD +GenerateMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, PCOUNT + pwhich_deposit) +{ + DWORD old_rand; + + old_rand = SeedRandom (SysInfoPtr->PlanetInfo.ScanSeed[MINERAL_SCAN]); + *pwhich_deposit = CalcMineralDeposits (SysInfoPtr, *pwhich_deposit); + return (SeedRandom (old_rand)); +} + +static COUNT +CalcLifeForms (SYSTEM_INFOPTR SysInfoPtr, COUNT which_life) +{ + COUNT num_life_forms; + + num_life_forms = 0; + if (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type) == GAS_GIANT) + SysInfoPtr->PlanetInfo.LifeChance = -1; + else + { +#define MIN_LIFE_CHANCE 10 + SIZE life_var; + + life_var = 0; + + if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -151) + life_var -= 300; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -51) + life_var -= 100; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 0) + life_var += 100; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 50) + life_var += 300; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 150) + life_var += 50; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 250) + life_var -= 100; + else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 500) + life_var -= 400; + else + life_var -= 800; + + if (SysInfoPtr->PlanetInfo.AtmoDensity == 0) + life_var -= 1000; + else if (SysInfoPtr->PlanetInfo.AtmoDensity < 15) + life_var += 100; + else if (SysInfoPtr->PlanetInfo.AtmoDensity < 30) + life_var += 200; + else if (SysInfoPtr->PlanetInfo.AtmoDensity < 100) + life_var += 300; + else if (SysInfoPtr->PlanetInfo.AtmoDensity < 1000) + life_var += 150; + else if (SysInfoPtr->PlanetInfo.AtmoDensity < 2500) + ; + else + life_var -= 100; + +#ifndef NOTYET + life_var += 200 + 80 + 80; +#else /* NOTYET */ + if (SysInfoPtr->PlanetInfo.SurfaceGravity < 10) + ; + else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 35) + life_var += 50; + else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 75) + life_var += 100; + else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 150) + life_var += 200; + else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 400) + life_var += 50; + else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 800) + ; + else + life_var -= 100; + + if (SysInfoPtr->PlanetInfo.Tectonics < 1) + life_var += 80; + else if (SysInfoPtr->PlanetInfo.Tectonics < 2) + life_var += 70; + else if (SysInfoPtr->PlanetInfo.Tectonics < 3) + life_var += 60; + else if (SysInfoPtr->PlanetInfo.Tectonics < 4) + life_var += 50; + else if (SysInfoPtr->PlanetInfo.Tectonics < 5) + life_var += 25; + else if (SysInfoPtr->PlanetInfo.Tectonics < 6) + ; + else + life_var -= 100; + + if (SysInfoPtr->PlanetInfo.Weather < 1) + life_var += 80; + else if (SysInfoPtr->PlanetInfo.Weather < 2) + life_var += 70; + else if (SysInfoPtr->PlanetInfo.Weather < 3) + life_var += 60; + else if (SysInfoPtr->PlanetInfo.Weather < 4) + life_var += 50; + else if (SysInfoPtr->PlanetInfo.Weather < 5) + life_var += 25; + else if (SysInfoPtr->PlanetInfo.Weather < 6) + ; + else + life_var -= 100; +#endif /* NOTYET */ + + SysInfoPtr->PlanetInfo.LifeChance = life_var; + + life_var = (COUNT)Random () & 1023; + if (life_var < SysInfoPtr->PlanetInfo.LifeChance + || (SysInfoPtr->PlanetInfo.LifeChance < MIN_LIFE_CHANCE + && life_var < MIN_LIFE_CHANCE)) + { + BYTE num_types; + + num_types = (BYTE)(((BYTE)Random () % MAX_LIFE_VARIATION) + 1); + do + { + BYTE index, num_creatures; + UWORD rand_val; + + rand_val = (UWORD)Random (); + index = LOBYTE (rand_val) % NUM_CREATURE_TYPES; + num_creatures = (BYTE)((HIBYTE (rand_val) % 10) + 1); + do + { + rand_val = (UWORD)Random (); + SysInfoPtr->PlanetInfo.CurPt.x = + (LOBYTE (rand_val) % (MAP_WIDTH - (8 << 1))) + 8; + SysInfoPtr->PlanetInfo.CurPt.y = + (HIBYTE (rand_val) % (MAP_HEIGHT - (8 << 1))) + 8; + SysInfoPtr->PlanetInfo.CurType = index; + + if ((num_life_forms >= which_life + && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] + & (1L << num_life_forms))) + || ++num_life_forms == sizeof (DWORD) * 8) + { + num_types = 1; + break; + } + } while (--num_creatures); + } while (--num_types); + } +#ifdef DEBUG +else + printf ("It's dead, Jim! (%d >= %d)\n", life_var, SysInfoPtr->PlanetInfo.LifeChance); +#endif /* DEBUG */ + } + + return (num_life_forms); +} + +DWORD +GenerateLifeForms (SYSTEM_INFOPTR SysInfoPtr, PCOUNT pwhich_life) +{ + DWORD old_rand; + + old_rand = SeedRandom (SysInfoPtr->PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); + *pwhich_life = CalcLifeForms (SysInfoPtr, *pwhich_life); + return (SeedRandom (old_rand)); +} + + + diff --git a/sc2/src/sc2code/process.c b/sc2/src/sc2code/process.c new file mode 100644 index 000000000..9d0b19161 --- /dev/null +++ b/sc2/src/sc2code/process.c @@ -0,0 +1,1162 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +COUNT DisplayFreeList; +PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS]; +extern POINT SpaceOrg; + +#ifndef OLD_ZOOM +SIZE zoom_out = 1 << ZOOM_SHIFT; +#endif + +#if 0 +#define CALC_ZOOM_STUFF(idx,sc) \ + do \ + { \ + int i, z; \ + \ + z = 1 << ZOOM_SHIFT; \ + for (i = 0; (z <<= 1) <= zoom_out; i++) \ + ; \ + *(idx) = i; \ + *(sc) = ((1 << i) << (ZOOM_SHIFT + 8)) / zoom_out; \ + } while (0) +#else +#define CALC_ZOOM_STUFF(idx,sc) \ + do \ + { \ + int i; \ + \ + if (zoom_out < 2 << ZOOM_SHIFT) \ + i = 0; \ + else if (zoom_out < 4 << ZOOM_SHIFT) \ + i = 1; \ + else \ + i = 2; \ + *(idx) = i; \ + *(sc) = (1 << (i + ZOOM_SHIFT + 8)) / zoom_out; \ + } while (0) +#endif + +HELEMENT +AllocElement (void) +{ + HELEMENT hElement; + + hElement = AllocLink (&disp_q); + if (hElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + memset (ElementPtr, 0, sizeof (*ElementPtr)); + ElementPtr->PrimIndex = AllocDisplayPrim (); + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + UnlockElement (hElement); + } + + return (hElement); +} + +void +FreeElement (HELEMENT hElement) +{ + if (hElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + FreeDisplayPrim (ElementPtr->PrimIndex); + UnlockElement (hElement); + + FreeLink (&disp_q, hElement); + } +} + +void +SetUpElement (register ELEMENTPTR ElementPtr) +{ + ElementPtr->next = ElementPtr->current; + if (CollidingElement (ElementPtr)) + { + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + } +} + +static void +PreProcess (register ELEMENTPTR ElementPtr) +{ + register ELEMENT_FLAGS state_flags; + + if (ElementPtr->life_span == 0) + { + if (ElementPtr->pParent) /* untarget this dead element */ + Untarget (ElementPtr); + + ElementPtr->state_flags |= DISAPPEARING; + if (ElementPtr->death_func) + (*ElementPtr->death_func) (ElementPtr); + } + + state_flags = ElementPtr->state_flags; + if (!(state_flags & DISAPPEARING)) + { + if (state_flags & APPEARING) + { + SetUpElement (ElementPtr); + + if (state_flags & PLAYER_SHIP) + state_flags &= ~APPEARING; /* want to preprocess ship */ + } + + if (ElementPtr->preprocess_func && !(state_flags & APPEARING)) + { + (*ElementPtr->preprocess_func) (ElementPtr); + + if (((state_flags = ElementPtr->state_flags) & CHANGING) + && CollidingElement (ElementPtr)) + InitIntersectFrame (ElementPtr); + } + + if (!(state_flags & IGNORE_VELOCITY)) + { + SIZE delta_x, delta_y; + + GetNextVelocityComponents (&ElementPtr->velocity, + &delta_x, &delta_y, 1); + if (delta_x != 0 || delta_y != 0) + { + state_flags |= CHANGING; + ElementPtr->next.location.x += delta_x; + ElementPtr->next.location.y += delta_y; + } + } + + if (CollidingElement (ElementPtr)) + InitIntersectEndPoint (ElementPtr); + + if (state_flags & FINITE_LIFE) + --ElementPtr->life_span; + } + + ElementPtr->state_flags = (state_flags + & ~(POST_PROCESS | COLLISION)) + | PRE_PROCESS; +} + +static void +PostProcess (register ELEMENTPTR ElementPtr) +{ + if (ElementPtr->postprocess_func) + (*ElementPtr->postprocess_func) (ElementPtr); + ElementPtr->current = ElementPtr->next; + + if (CollidingElement (ElementPtr)) + { + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + } + + ElementPtr->state_flags = (ElementPtr->state_flags + & ~(PRE_PROCESS | CHANGING | APPEARING)) + | POST_PROCESS; +} + +#ifdef OLD_ZOOM +static BYTE +CalcReduction (SIZE dx, SIZE dy) +#else +static COUNT +CalcReduction (SIZE dx, SIZE dy) +#endif +{ +#ifdef OLD_ZOOM + BYTE next_reduction; + SIZE sdx, sdy; + + if (LOBYTE (GLOBAL (CurrentActivity)) > IN_ENCOUNTER) + return (0); + + sdx = dx; + sdy = dy; + for (next_reduction = MAX_VIS_REDUCTION; + (dx <<= REDUCTION_SHIFT) <= TRANSITION_WIDTH + && (dy <<= REDUCTION_SHIFT) <= TRANSITION_HEIGHT + && next_reduction > 0; + next_reduction -= REDUCTION_SHIFT) + ; + + /* check for "real" zoom in */ + if (next_reduction < GLOBAL (cur_state) + && GLOBAL (cur_state) <= MAX_VIS_REDUCTION) + { +#define HYSTERESIS_X DISPLAY_TO_WORLD(24) +#define HYSTERESIS_Y DISPLAY_TO_WORLD(20) + if (((sdx + HYSTERESIS_X) + << (MAX_VIS_REDUCTION - next_reduction)) > TRANSITION_WIDTH + || ((sdy + HYSTERESIS_Y) + << (MAX_VIS_REDUCTION - next_reduction)) > TRANSITION_HEIGHT) + /* if we don't zoom in, we want to stay at next+1 */ + next_reduction += REDUCTION_SHIFT; + } + + if (next_reduction == 0 + && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + next_reduction += REDUCTION_SHIFT; +#else + COUNT next_reduction; +#ifdef KDEBUG +printf ("CalcReduction:\n"); +#endif + if (LOBYTE (GLOBAL (CurrentActivity)) > IN_ENCOUNTER) + return (1 << ZOOM_SHIFT); + + dx = (dx * MAX_ZOOM_OUT) / (LOG_SPACE_WIDTH >> 2); + if (dx < (1 << ZOOM_SHIFT)) + dx = 1 << ZOOM_SHIFT; + else if (dx > MAX_ZOOM_OUT) + dx = MAX_ZOOM_OUT; + + dy = (dy * MAX_ZOOM_OUT) / (LOG_SPACE_HEIGHT >> 2); + if (dy < (1 << ZOOM_SHIFT)) + dy = 1 << ZOOM_SHIFT; + else if (dy > MAX_ZOOM_OUT) + dy = MAX_ZOOM_OUT; + + if (dy > dx) + next_reduction = dy; + else + next_reduction = dx; + + if (next_reduction < (2 << ZOOM_SHIFT) + && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + next_reduction = (2 << ZOOM_SHIFT); +#ifdef KDEBUG +printf ("CalcReduction: exit\n"); +#endif +#endif + + return (next_reduction); +} + +#ifdef OLD_ZOOM +static VIEW_STATE +CalcView (PPOINT pNewScrollPt, register BYTE next_reduction, + PSIZE pdx, PSIZE pdy) +#else +static VIEW_STATE +CalcView (PPOINT pNewScrollPt, register SIZE next_reduction, + PSIZE pdx, PSIZE pdy, COUNT ships_alive) +#endif +{ + SIZE dx, dy; + VIEW_STATE view_state; + +#ifdef KDEBUG +printf ("CalcView:\n"); +#endif + dx = ((COORD)(LOG_SPACE_WIDTH >> 1) - pNewScrollPt->x); + dy = ((COORD)(LOG_SPACE_HEIGHT >> 1) - pNewScrollPt->y); + dx = WRAP_DELTA_X (dx); + dy = WRAP_DELTA_Y (dy); + if (ships_alive == 1) + { +#define ORG_JUMP_X (LOG_SPACE_WIDTH / 75) +#define ORG_JUMP_Y (LOG_SPACE_HEIGHT / 75) + if (dx > ORG_JUMP_X) + dx = ORG_JUMP_X; + else if (dx < -ORG_JUMP_X) + dx = -ORG_JUMP_X; + if (dy > ORG_JUMP_Y) + dy = ORG_JUMP_Y; + else if (dy < -ORG_JUMP_Y) + dy = -ORG_JUMP_Y; + } + + if ((dx || dy) && LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + MoveSIS (&dx, &dy); + +#ifdef OLD_ZOOM + if (GLOBAL (cur_state) == next_reduction) +#else + if (zoom_out == next_reduction) +#endif + view_state = dx == 0 && dy == 0 + && LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE + ? VIEW_STABLE : VIEW_SCROLL; + else + { +#ifdef OLD_ZOOM + GLOBAL (cur_state) = next_reduction; + + SpaceOrg.x = (COORD)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH >> ((MAX_REDUCTION + 1) - next_reduction)); + SpaceOrg.y = (COORD)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT >> ((MAX_REDUCTION + 1) - next_reduction)); +#else +#define ZOOM_JUMP ((1 << ZOOM_SHIFT) >> 3) + if (ships_alive == 1 + && zoom_out > next_reduction + && zoom_out <= MAX_ZOOM_OUT + && zoom_out - next_reduction > ZOOM_JUMP) + next_reduction = zoom_out - ZOOM_JUMP; + + zoom_out = next_reduction; + + SpaceOrg.x = (int)(LOG_SPACE_WIDTH >> 1) + - (LOG_SPACE_WIDTH * next_reduction / (MAX_ZOOM_OUT << 2)); + SpaceOrg.y = (int)(LOG_SPACE_HEIGHT >> 1) + - (LOG_SPACE_HEIGHT * next_reduction / (MAX_ZOOM_OUT << 2)); +#endif + + view_state = VIEW_CHANGE; + } + + if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_HYPERSPACE) + MoveGalaxy (view_state, dx, dy); + + *pdx = dx; + *pdy = dy; + +#ifdef KDEBUG +printf ("CalcView: exit\n"); +#endif + return (view_state); +} + + +static ELEMENT_FLAGS +ProcessCollisions (HELEMENT hSuccElement, register ELEMENTPTR ElementPtr, + TIME_VALUE min_time, ELEMENT_FLAGS process_flags) +{ + HELEMENT hTestElement; + + while ((hTestElement = hSuccElement) != 0) + { + ELEMENTPTR TestElementPtr; + + LockElement (hTestElement, &TestElementPtr); + if (!(TestElementPtr->state_flags & process_flags)) + PreProcess (TestElementPtr); + hSuccElement = GetSuccElement (TestElementPtr); + + if (TestElementPtr == ElementPtr) + { + UnlockElement (hTestElement); + + continue; + } + + if (CollisionPossible (TestElementPtr, ElementPtr)) + { + register ELEMENT_FLAGS state_flags, test_state_flags; + TIME_VALUE time_val; + + state_flags = ElementPtr->state_flags; + test_state_flags = TestElementPtr->state_flags; + if (((state_flags | test_state_flags) & FINITE_LIFE) + && (((state_flags & APPEARING) + && ElementPtr->life_span > 1) + || ((test_state_flags & APPEARING) + && TestElementPtr->life_span > 1))) + time_val = 0; + else + { + while ((time_val = DrawablesIntersect (&ElementPtr->IntersectControl, + &TestElementPtr->IntersectControl, min_time)) == 1 + && !((state_flags | test_state_flags) & FINITE_LIFE)) + { +#ifdef DEBUG +printf ("BAD NEWS 0x%x <--> 0x%x\n", ElementPtr, TestElementPtr); +#endif /* DEBUG */ + if (state_flags & COLLISION) + { + InitIntersectEndPoint (TestElementPtr); + TestElementPtr->IntersectControl.IntersectStamp.origin = + TestElementPtr->IntersectControl.EndPoint; + time_val = DrawablesIntersect (&ElementPtr->IntersectControl, + &TestElementPtr->IntersectControl, 1); + InitIntersectStartPoint (TestElementPtr); + } + + if (time_val == 1) + { + FRAME CurFrame, NextFrame, + TestCurFrame, TestNextFrame; + + CurFrame = ElementPtr->current.image.frame; + NextFrame = ElementPtr->next.image.frame; + TestCurFrame = TestElementPtr->current.image.frame; + TestNextFrame = TestElementPtr->next.image.frame; + if (NextFrame == CurFrame + && TestNextFrame == TestCurFrame) + { + if (test_state_flags & APPEARING) + { + do_damage (TestElementPtr, TestElementPtr->hit_points); + if (TestElementPtr->pParent) /* untarget this dead element */ + Untarget (TestElementPtr); + + TestElementPtr->state_flags |= (COLLISION | DISAPPEARING); + if (TestElementPtr->death_func) + (*TestElementPtr->death_func) (TestElementPtr); + } + if (state_flags & APPEARING) + { + do_damage (ElementPtr, ElementPtr->hit_points); + if (ElementPtr->pParent) /* untarget this dead element */ + Untarget (ElementPtr); + + ElementPtr->state_flags |= (COLLISION | DISAPPEARING); + if (ElementPtr->death_func) + (*ElementPtr->death_func) (ElementPtr); + + UnlockElement (hTestElement); + return (COLLISION); + } + + time_val = 0; + } + else + { + if (GetFrameIndex (CurFrame) != + GetFrameIndex (NextFrame)) + ElementPtr->next.image.frame = + SetEquFrameIndex (NextFrame, + CurFrame); + else if (NextFrame != CurFrame) + { + ElementPtr->next.image = + ElementPtr->current.image; + if (ElementPtr->life_span > NORMAL_LIFE) + ElementPtr->life_span = NORMAL_LIFE; + } + + if (GetFrameIndex (TestCurFrame) != + GetFrameIndex (TestNextFrame)) + TestElementPtr->next.image.frame = + SetEquFrameIndex (TestNextFrame, + TestCurFrame); + else if (TestNextFrame != TestCurFrame) + { + TestElementPtr->next.image = + TestElementPtr->current.image; + if (TestElementPtr->life_span > NORMAL_LIFE) + TestElementPtr->life_span = NORMAL_LIFE; + } + + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + if (state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->ShipFacing = + GetFrameIndex ( + ElementPtr->next.image.frame); + } + + InitIntersectStartPoint (TestElementPtr); + InitIntersectEndPoint (TestElementPtr); + InitIntersectFrame (TestElementPtr); + if (test_state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (TestElementPtr, &StarShipPtr); + StarShipPtr->ShipFacing = + GetFrameIndex ( + TestElementPtr->next.image.frame); + } + } + } + + if (time_val == 0) + { + InitIntersectEndPoint (ElementPtr); + InitIntersectEndPoint (TestElementPtr); + + break; + } + } + } + + if (time_val > 0) + { + POINT SavePt, TestSavePt; + +#ifdef DEBUG +printf ("0x%x <--> 0x%x at %u\n", ElementPtr, TestElementPtr, time_val); +#endif /* DEBUG */ + SavePt = ElementPtr->IntersectControl.EndPoint; + TestSavePt = TestElementPtr->IntersectControl.EndPoint; + InitIntersectEndPoint (ElementPtr); + InitIntersectEndPoint (TestElementPtr); + if (time_val == 1 + || (((state_flags & COLLISION) + || !ProcessCollisions (hSuccElement, ElementPtr, + time_val - 1, process_flags)) + && ((test_state_flags & COLLISION) + || !ProcessCollisions ( + !(TestElementPtr->state_flags & APPEARING) ? + GetSuccElement (ElementPtr) : + GetHeadElement (), TestElementPtr, + time_val - 1, process_flags)))) + { + state_flags = ElementPtr->state_flags; + test_state_flags = TestElementPtr->state_flags; + +#ifdef DEBUG +printf ("PROCESSING 0x%x <--> 0x%x at %u\n", ElementPtr, TestElementPtr, time_val); +#endif /* DEBUG */ + if (test_state_flags & PLAYER_SHIP) + { + (*TestElementPtr->collision_func) ( + TestElementPtr, &TestSavePt, + ElementPtr, &SavePt + ); + (*ElementPtr->collision_func) ( + ElementPtr, &SavePt, + TestElementPtr, &TestSavePt + ); + } + else + { + (*ElementPtr->collision_func) ( + ElementPtr, &SavePt, + TestElementPtr, &TestSavePt + ); + (*TestElementPtr->collision_func) ( + TestElementPtr, &TestSavePt, + ElementPtr, &SavePt + ); + } + + if (TestElementPtr->state_flags & COLLISION) + { + if (!(test_state_flags & COLLISION)) + { + TestElementPtr->IntersectControl.IntersectStamp.origin = + TestSavePt; + TestElementPtr->next.location.x = + DISPLAY_TO_WORLD (TestSavePt.x); + TestElementPtr->next.location.y = + DISPLAY_TO_WORLD (TestSavePt.y); + InitIntersectEndPoint (TestElementPtr); + } + } + + if (ElementPtr->state_flags & COLLISION) + { + if (!(state_flags & COLLISION)) + { + ElementPtr->IntersectControl.IntersectStamp.origin = + SavePt; + ElementPtr->next.location.x = + DISPLAY_TO_WORLD (SavePt.x); + ElementPtr->next.location.y = + DISPLAY_TO_WORLD (SavePt.y); + InitIntersectEndPoint (ElementPtr); + + if (!(state_flags & FINITE_LIFE) && + !(test_state_flags & FINITE_LIFE)) + { + collide (ElementPtr, TestElementPtr); + + ProcessCollisions (GetHeadElement (), ElementPtr, + MAX_TIME_VALUE, process_flags); + ProcessCollisions (GetHeadElement (), TestElementPtr, + MAX_TIME_VALUE, process_flags); + } + } + UnlockElement (hTestElement); + return (COLLISION); + } + + if (!CollidingElement (ElementPtr)) + { + ElementPtr->state_flags |= COLLISION; + UnlockElement (hTestElement); + return (COLLISION); + } + } + } + } + + UnlockElement (hTestElement); + } + + return (ElementPtr->state_flags & COLLISION); +} + +#define MAX_SOUNDS 8 +static BYTE num_sounds; +static SOUND sound_buf[MAX_SOUNDS]; + +static VIEW_STATE +PreProcessQueue (PSIZE pscroll_x, PSIZE pscroll_y) +{ +#ifdef OLD_ZOOM + BYTE min_reduction, max_reduction; +#else + SIZE min_reduction, max_reduction; +#endif + COUNT num_ships; + POINT Origin; + register HELEMENT hElement; + COUNT ships_alive; + +#ifdef KDEBUG +printf ("PreProcess:\n"); +#endif + num_ships = (LOBYTE (battle_counter) ? 1 : 0) + + (HIBYTE (battle_counter) ? 1 : 0); + +#ifdef OLD_ZOOM + min_reduction = max_reduction = MAX_VIS_REDUCTION + 1; +#else + min_reduction = max_reduction = MAX_ZOOM_OUT + (1 << ZOOM_SHIFT); +#endif + Origin.x = (COORD)(LOG_SPACE_WIDTH >> 1); + Origin.y = (COORD)(LOG_SPACE_HEIGHT >> 1); + + hElement = GetHeadElement (); + ships_alive = 0; + while (hElement != 0) + { + ELEMENTPTR ElementPtr; + HELEMENT hNextElement; + + LockElement (hElement, &ElementPtr); + + if (!(ElementPtr->state_flags & PRE_PROCESS)) + PreProcess (ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + + if (CollidingElement (ElementPtr) + && !(ElementPtr->state_flags & COLLISION)) + ProcessCollisions (hNextElement, ElementPtr, + MAX_TIME_VALUE, PRE_PROCESS); + + if (ElementPtr->state_flags & PLAYER_SHIP) + { + SIZE dx, dy; + + ships_alive++; +#ifdef OLD_ZOOM + if (max_reduction > MAX_VIS_REDUCTION + && min_reduction > MAX_VIS_REDUCTION) +#else + if (max_reduction > MAX_ZOOM_OUT + && min_reduction > MAX_ZOOM_OUT) +#endif + { + Origin.x = DISPLAY_ALIGN (ElementPtr->next.location.x); + Origin.y = DISPLAY_ALIGN (ElementPtr->next.location.y); + } + + dx = DISPLAY_ALIGN (ElementPtr->next.location.x) - Origin.x; + dx = WRAP_DELTA_X (dx); + dy = DISPLAY_ALIGN (ElementPtr->next.location.y) - Origin.y; + dy = WRAP_DELTA_Y (dy); + + if (num_ships <= 2 || !(ElementPtr->state_flags & BAD_GUY)) + { + Origin.x = DISPLAY_ALIGN (Origin.x + (dx >> 1)); + Origin.y = DISPLAY_ALIGN (Origin.y + (dy >> 1)); + + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + max_reduction = CalcReduction (dx, dy); + } +#ifdef OLD_ZOOM + else if (max_reduction > MAX_VIS_REDUCTION + && min_reduction <= MAX_VIS_REDUCTION) +#else + else if (max_reduction > MAX_ZOOM_OUT + && min_reduction <= MAX_ZOOM_OUT) +#endif + { + Origin.x = DISPLAY_ALIGN (Origin.x + (dx >> 1)); + Origin.y = DISPLAY_ALIGN (Origin.y + (dy >> 1)); + + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + min_reduction = CalcReduction (dx, dy); + } + else + { +#ifdef OLD_ZOOM + BYTE reduction; +#else + SIZE reduction; +#endif + + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + reduction = CalcReduction (dx << 1, dy << 1); + +#ifdef OLD_ZOOM + if (min_reduction > MAX_VIS_REDUCTION + || reduction < min_reduction) +#else + if (min_reduction > MAX_ZOOM_OUT + || reduction < min_reduction) +#endif + min_reduction = reduction; + } +//printf ("dx = %d dy = %d min_red = %d max_red = %d\n", dx, dy, min_reduction, max_reduction); + } + + UnlockElement (hElement); + hElement = hNextElement; + } + +#ifdef OLD_ZOOM + if ((min_reduction > MAX_VIS_REDUCTION || min_reduction <= max_reduction) + && (min_reduction = max_reduction) > MAX_VIS_REDUCTION + && (min_reduction = GLOBAL (cur_state)) > MAX_VIS_REDUCTION) + min_reduction = 0; +#else + if ((min_reduction > MAX_ZOOM_OUT || min_reduction <= max_reduction) + && (min_reduction = max_reduction) > MAX_ZOOM_OUT + && (min_reduction = zoom_out) > MAX_ZOOM_OUT) + min_reduction = 1 << ZOOM_SHIFT; +#endif + +#ifdef KDEBUG +printf ("PreProcess: exit\n"); +#endif + return (CalcView (&Origin, min_reduction, pscroll_x, pscroll_y, ships_alive)); +} + +void +InsertPrim (PRIM_LINKS *pLinks, COUNT PI, COUNT iPI) +{ + COUNT Link; + PRIM_LINKS PL; + + if (iPI == END_OF_LIST) + { + Link = GetSuccLink (*pLinks); /* get tail */ + if (Link == END_OF_LIST) + *pLinks = MakeLinks (PI, PI); + else + *pLinks = MakeLinks (GetPredLink (*pLinks), PI); + } + else + { + PL = GetPrimLinks (&DisplayArray[iPI]); + if (iPI != GetPredLink (*pLinks)) /* if not the head */ + Link = GetPredLink (PL); + else + { + Link = END_OF_LIST; + *pLinks = MakeLinks (PI, GetSuccLink (*pLinks)); + } + SetPrimLinks (&DisplayArray[iPI], PI, GetSuccLink (PL)); + } + + if (Link != END_OF_LIST) + { + PL = GetPrimLinks (&DisplayArray[Link]); + SetPrimLinks (&DisplayArray[Link], GetPredLink (PL), PI); + } + SetPrimLinks (&DisplayArray[PI], Link, iPI); +} + +PRIM_LINKS DisplayLinks; + +static void +PostProcessQueue (register VIEW_STATE view_state, register SIZE scroll_x, + register SIZE scroll_y) +{ + POINT delta; +#ifdef OLD_ZOOM + register BYTE reduction; +#else + register SIZE reduction; +#endif + register HELEMENT hElement; + +#ifdef KDEBUG +printf ("PostProcess:\n"); +#endif +#ifdef OLD_ZOOM + reduction = (BYTE)(GLOBAL (cur_state) + ONE_SHIFT); +#else + reduction = zoom_out << ONE_SHIFT; +#endif + + hElement = GetHeadElement (); + while (hElement != 0) + { + register ELEMENT_FLAGS state_flags; + ELEMENTPTR ElementPtr; + HELEMENT hNextElement; + + LockElement (hElement, &ElementPtr); + + state_flags = ElementPtr->state_flags; + if (state_flags & PRE_PROCESS) + { + if (!(state_flags & COLLISION)) + ElementPtr->state_flags &= ~DEFY_PHYSICS; + else + ElementPtr->state_flags &= ~COLLISION; + + if (state_flags & POST_PROCESS) + delta.x = delta.y = 0; + else + { + delta.x = scroll_x; + delta.y = scroll_y; + } + } + else + { + HELEMENT hPostElement; + + hPostElement = hElement; + do + { + ELEMENTPTR PostElementPtr; + + LockElement (hPostElement, &PostElementPtr); + if (!(PostElementPtr->state_flags & PRE_PROCESS)) + PreProcess (PostElementPtr); + hNextElement = GetSuccElement (PostElementPtr); + + if (CollidingElement (PostElementPtr) + && !(PostElementPtr->state_flags & COLLISION)) + ProcessCollisions (GetHeadElement (), PostElementPtr, + MAX_TIME_VALUE, PRE_PROCESS | POST_PROCESS); + UnlockElement (hPostElement); + } while ((hPostElement = hNextElement) != 0); + + scroll_x = scroll_y = 0; + delta.x = delta.y = 0; /* because these are + * newly added elements + * that are already in + * adjusted coordinates + */ + state_flags = ElementPtr->state_flags; + } + + if (state_flags & DISAPPEARING) + { + hNextElement = GetSuccElement (ElementPtr); + UnlockElement (hElement); + + RemoveElement (hElement); + FreeElement (hElement); + } + else + { + GRAPHICS_PRIM ObjType; + + ObjType = GetPrimType (&DisplayArray[ElementPtr->PrimIndex]); + if (view_state != VIEW_STABLE + || (state_flags & (APPEARING | CHANGING))) + { + POINT next; + + if (ObjType == LINE_PRIM) + { + SIZE dx, dy; + + dx = ElementPtr->next.location.x + - ElementPtr->current.location.x; + dy = ElementPtr->next.location.y + - ElementPtr->current.location.y; + + next.x = WRAP_X (ElementPtr->current.location.x + delta.x); + next.y = WRAP_Y (ElementPtr->current.location.y + delta.y); +#ifdef OLD_ZOOM + DisplayArray[ElementPtr->PrimIndex].Object.Line.first.x = + (next.x - SpaceOrg.x) >> reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Line.first.y = + (next.y - SpaceOrg.y) >> reduction; +#else + DisplayArray[ElementPtr->PrimIndex].Object.Line.first.x = + ((next.x - SpaceOrg.x) << ZOOM_SHIFT) / reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Line.first.y = + ((next.y - SpaceOrg.y) << ZOOM_SHIFT) / reduction; +#endif + next.x += dx; + next.y += dy; +#ifdef OLD_ZOOM + DisplayArray[ElementPtr->PrimIndex].Object.Line.second.x = + (next.x - SpaceOrg.x) >> reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Line.second.y = + (next.y - SpaceOrg.y) >> reduction; +#else + DisplayArray[ElementPtr->PrimIndex].Object.Line.second.x = + ((next.x - SpaceOrg.x) << ZOOM_SHIFT) / reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Line.second.y = + ((next.y - SpaceOrg.y) << ZOOM_SHIFT) / reduction; +#endif + } + else + { + next.x = WRAP_X (ElementPtr->next.location.x + delta.x); + next.y = WRAP_Y (ElementPtr->next.location.y + delta.y); +#ifdef OLD_ZOOM + DisplayArray[ElementPtr->PrimIndex].Object.Point.x = + (next.x - SpaceOrg.x) >> reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Point.y = + (next.y - SpaceOrg.y) >> reduction; +#else + DisplayArray[ElementPtr->PrimIndex].Object.Point.x = + ((next.x - SpaceOrg.x) << ZOOM_SHIFT) / reduction; + DisplayArray[ElementPtr->PrimIndex].Object.Point.y = + ((next.y - SpaceOrg.y) << ZOOM_SHIFT) / reduction; +#endif + + if (ObjType == STAMP_PRIM + || ObjType == STAMPFILL_PRIM) + { + if (view_state == VIEW_CHANGE + || (state_flags & (APPEARING | CHANGING))) + { +#ifdef OLD_ZOOM + ElementPtr->next.image.frame = +#ifdef SAFE + SetAbsFrameIndex ( + ElementPtr->next.image.farray + [GLOBAL (cur_state)], + GetFrameIndex (ElementPtr->next.image.frame)); +#else /* SAFE */ + SetEquFrameIndex ( + ElementPtr->next.image.farray + [GLOBAL (cur_state)], + ElementPtr->next.image.frame); +#endif /* SAFE */ +#else + COUNT index, scale; + + CALC_ZOOM_STUFF (&index, &scale); + ElementPtr->next.image.frame = +#ifdef SAFE + SetAbsFrameIndex ( + ElementPtr->next.image.farray + [index], + GetFrameIndex (ElementPtr->next.image.frame)); +#else /* SAFE */ + SetEquFrameIndex ( + ElementPtr->next.image.farray + [index], + ElementPtr->next.image.frame); +#endif /* SAFE */ +#endif + } + DisplayArray[ElementPtr->PrimIndex].Object.Stamp.frame = + ElementPtr->next.image.frame; + } + } + + ElementPtr->next.location = next; + } + + PostProcess (ElementPtr); + + if (ObjType < NUM_PRIMS) + InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, END_OF_LIST); + + hNextElement = GetSuccElement (ElementPtr); + UnlockElement (hElement); + } + + hElement = hNextElement; + } +#ifdef KDEBUG +printf ("PostProcess: exit\n"); +#endif +} + +void +InitDisplayList (void) +{ + COUNT i; + +#ifdef OLD_ZOOM + GLOBAL (cur_state) = MAX_VIS_REDUCTION + 1; +#else + zoom_out = MAX_ZOOM_OUT + (1 << ZOOM_SHIFT); +#endif + + ReinitQueue (&disp_q); + + for (i = 0; i < MAX_DISPLAY_PRIMS; ++i) + SetPrimLinks (&DisplayArray[i], END_OF_LIST, i + 1); + SetPrimLinks (&DisplayArray[i - 1], END_OF_LIST, END_OF_LIST); + DisplayFreeList = 0; + DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); +} + +void +PlaySound (SOUND S, BYTE Priority) +{ +#define MIN_FX_CHANNEL 1 +#define NUM_FX_CHANNELS 4 /* obviously number of channels + is assumed to be at least 5 */ + BYTE chan, c; + static BYTE lru_channel[NUM_FX_CHANNELS] = {0, 1, 2, 3}; + static SOUND channel[NUM_FX_CHANNELS]; + + if (S == 0) return; + + for (chan = 0; chan < NUM_FX_CHANNELS; ++chan) + { + if (S == channel[chan]) + break; + } + + if (chan == NUM_FX_CHANNELS) + { + for (chan = 0; chan < NUM_FX_CHANNELS; ++chan) + { + if (!ChannelPlaying (chan + MIN_FX_CHANNEL)) + break; + } + + if (chan == NUM_FX_CHANNELS) + chan = lru_channel[0]; + } + + channel[chan] = S; + + for (c = 0; c < NUM_FX_CHANNELS - 1; ++c) + { + if (lru_channel[c] == chan) + { + memmove ( + (PBYTE)&lru_channel[c], + (PBYTE)&lru_channel[c + 1], + (NUM_FX_CHANNELS - 1) - c + ); + break; + } + } + lru_channel[NUM_FX_CHANNELS - 1] = chan; + + PlaySoundEffect (S, chan + MIN_FX_CHANNEL, Priority); +} + +UWORD nth_frame; + +void +RedrawQueue (BOOLEAN clear) +{ + SIZE scroll_x, scroll_y; + VIEW_STATE view_state; + + SetContext (StatusContext); + + view_state = PreProcessQueue (&scroll_x, &scroll_y); + PostProcessQueue (view_state, scroll_x, scroll_y); + + SetContext (SpaceContext); + if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE + || !(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + BYTE skip_frames; + + if ((skip_frames = HIBYTE (nth_frame)) != (BYTE)~0 + && (skip_frames == 0 || (--nth_frame & 0x00FF) == 0)) + { + nth_frame += skip_frames; +if (clear) + ClearDrawable (); // this is for BATCH_BUILD_PAGE effect, but not scaled by SetGraphicScale +{ + COUNT index, scale; + + CALC_ZOOM_STUFF (&index, &scale); + SetGraphicScale (scale); +} + DrawBatch (DisplayArray, DisplayLinks, 0);//BATCH_BUILD_PAGE); +SetGraphicScale (0); + } + + if (num_sounds > 0) + { + SOUND *pSound; + + pSound = sound_buf; + do + { + PlaySound (*pSound++, GAME_SOUND_PRIORITY); + } while (--num_sounds); + } + } + DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); +} + +void +ProcessSound (SOUND Sound) +{ + if (Sound == (SOUND)~0) + { + memset (sound_buf, 0, sizeof (sound_buf)); + num_sounds = MAX_SOUNDS; + } + else if (num_sounds < MAX_SOUNDS) + sound_buf[num_sounds++] = Sound; +} + +void +Untarget (ELEMENTPTR ElementPtr) +{ + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); hElement; hElement = hNextElement) + { + HELEMENT hTarget; + ELEMENTPTR ListPtr; + + LockElement (hElement, &ListPtr); + hNextElement = GetSuccElement (ListPtr); + + hTarget = ListPtr->hTarget; + if (hTarget) + { + ELEMENTPTR TargetElementPtr; + + LockElement (hTarget, &TargetElementPtr); + if (TargetElementPtr == ElementPtr) + ListPtr->hTarget = 0; + UnlockElement (hTarget); + } + + UnlockElement (hElement); + } +} + diff --git a/sc2/src/sc2code/races.h b/sc2/src/sc2code/races.h new file mode 100644 index 000000000..2c24094fb --- /dev/null +++ b/sc2/src/sc2code/races.h @@ -0,0 +1,509 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _RACES_H +#define _RACES_H + +#define RACES_PER_PLAYER 7 +#define MAX_SHIPS_PER_SIDE 14 + +/* heat of battle specific flags */ +#define LEFT (1 << 0) +#define RIGHT (1 << 1) +#define THRUST (1 << 2) +#define WEAPON (1 << 3) +#define SPECIAL (1 << 4) +#define LOW_ON_ENERGY (1 << 5) +#define SHIP_BEYOND_MAX_SPEED (1 << 6) +#define SHIP_AT_MAX_SPEED (1 << 7) +#define SHIP_IN_GRAVITY_WELL (1 << 8) +#define PLAY_VICTORY_DITTY (1 << 9) + +/* ship specific flags */ +/* +#define GOOD_GUY (1 << 0) +#define BAD_GUY (1 << 1) +*/ +#define SEEKING_WEAPON (1 << 2) +#define SEEKING_SPECIAL (1 << 3) +#define POINT_DEFENSE (1 << 4) +#define IMMEDIATE_WEAPON (1 << 5) +#define CREW_IMMUNE (1 << 6) +#define FIRES_FORE (1 << 7) +#define FIRES_RIGHT (1 << 8) +#define FIRES_AFT (1 << 9) +#define FIRES_LEFT (1 << 10) +#define SHIELD_DEFENSE (1 << 11) +#define DONT_CHASE (1 << 12) + +#define MAX_SHAPES_ACTIVE 2 + /* SHIP_SHAPE_ACTIVE && SPECIAL_SHAPE_ACTIVE */ + +typedef struct captain_stuff +{ + FRAME background, turn, thrust, weapon, special; +} CAPTAIN_STUFF; +typedef CAPTAIN_STUFF *PCAPTAIN_STUFF; +#define CAPTAIN_STUFFPTR PCAPTAIN_STUFF + +typedef struct +{ + COUNT ManeuverabilityIndex; + COUNT WeaponRange; + void (*intelligence_func) (PVOID ShipPtr, PVOID ObjectsOfConcern, + COUNT ConcernCounter); +} INTEL_STUFF; + +typedef struct +{ + COUNT max_thrust, + thrust_increment; + BYTE energy_regeneration, + weapon_energy_cost, + special_energy_cost, + energy_wait, + turn_wait, + thrust_wait, + weapon_wait, + special_wait, + ship_mass; +} CHARACTERISTIC_STUFF; +typedef CHARACTERISTIC_STUFF *PCHARACTERISTIC_STUFF; + +typedef struct +{ + UWORD ship_flags; + BYTE var1, var2; + BYTE crew_level, max_crew; + BYTE energy_level, max_energy; + POINT loc; + + STRING race_strings; + FRAME icons, melee_icon; +} SHIP_INFO; +typedef SHIP_INFO *PSHIP_INFO; +#define SHIP_INFOPTR PSHIP_INFO + +#define ship_cost var1 +#define group_counter ship_flags + +enum +{ + IN_ORBIT = 0, + EXPLORE, + FLEE, + ON_STATION, + + IGNORE_FLAGSHIP = 1 << 2, + REFORM_GROUP = 1 << 3 +}; +#define MAX_REVOLUTIONS 5 + +#define GET_RACE_ID(s) ((s)->ShipInfo.var1) +#define SET_RACE_ID(s,v) ((s)->ShipInfo.var1 = (v)) +#define GET_GROUP_LOC(s) LONIBBLE ((s)->ShipInfo.var2) +#define SET_GROUP_LOC(s,v) ((s)->ShipInfo.var2 = \ + MAKE_BYTE ((v), HINIBBLE ((s)->ShipInfo.var2))) +#define GET_GROUP_MISSION(s) HINIBBLE ((s)->ShipInfo.var2) +#define SET_GROUP_MISSION(s,v) ((s)->ShipInfo.var2 = \ + MAKE_BYTE (LONIBBLE ((s)->ShipInfo.var2), (v))) +#define GET_GROUP_DEST(s) LONIBBLE ((s)->ShipInfo.energy_level) +#define SET_GROUP_DEST(s,v) ((s)->ShipInfo.energy_level = \ + MAKE_BYTE ((v), HINIBBLE ((s)->ShipInfo.energy_level))) +#define GET_ORBIT_LOC(s) HINIBBLE ((s)->ShipInfo.energy_level) +#define SET_ORBIT_LOC(s,v) ((s)->ShipInfo.energy_level = \ + MAKE_BYTE (LONIBBLE ((s)->ShipInfo.energy_level), (v))) +#define GET_GROUP_ID(s) ((s)->ShipInfo.max_energy) +#define SET_GROUP_ID(s,v) ((s)->ShipInfo.max_energy = (v)) + +#define STATION_RADIUS 1600 +#define ORBIT_RADIUS 2400 + +typedef struct +{ + UWORD ship_flags; + BYTE days_left, growth_fract; + BYTE crew_level, max_crew; + BYTE energy_level, max_energy; + POINT loc; + + STRING race_strings; + FRAME icons, melee_icon; + + COUNT actual_strength, known_strength; + POINT known_loc; + + BYTE growth_err_term, func_index; + POINT dest_loc; +} EXTENDED_SHIP_INFO; +typedef EXTENDED_SHIP_INFO *PEXTENDED_SHIP_INFO; + +typedef struct +{ + FRAME ship[NUM_VIEWS]; + FRAME weapon[NUM_VIEWS]; + FRAME special[NUM_VIEWS]; + CAPTAIN_STUFF captain_control; + DWORD victory_ditty; + SOUND ship_sounds; +} DATA_STUFF; +typedef DATA_STUFF *PDATA_STUFF; +#define DATA_STUFFPTR PDATA_STUFF + +typedef struct race_desc +{ + SHIP_INFO ship_info; + CHARACTERISTIC_STUFF characteristics; + DATA_STUFF ship_data; + INTEL_STUFF cyborg_control; + + void (*preprocess_func) (PELEMENT ElementPtr); + void (*postprocess_func) (PELEMENT ElementPtr); + COUNT (*init_weapon_func) (PELEMENT ElementPtr, HELEMENT + Weapon[]); + + PVOID CodeRef; +} RACE_DESC; +typedef RACE_DESC *PRACE_DESC; +#define RACE_DESCPTR PRACE_DESC + +typedef QUEUE_HANDLE HSTARSHIP; + +typedef struct +{ + HSTARSHIP pred, succ; + + DWORD RaceResIndex; + RACE_DESCPTR RaceDescPtr; + BYTE captains_name_index; + + BYTE weapon_counter, + special_counter, + energy_counter; + + BYTE ship_input_state; + UWORD cur_status_flags, old_status_flags; + + HELEMENT hShip; + COUNT ShipFacing; + FRAME silhouette; +} STARSHIP; +typedef STARSHIP *PSTARSHIP; +#define STARSHIPPTR PSTARSHIP + +typedef struct +{ + HSTARSHIP pred, succ; + + DWORD RaceResIndex; + RACE_DESCPTR RaceDescPtr; + SHIP_INFO ShipInfo; +} SHIP_FRAGMENT; +typedef SHIP_FRAGMENT *PSHIP_FRAGMENT; +#define SHIP_FRAGMENTPTR PSHIP_FRAGMENT + +typedef struct +{ + HSTARSHIP pred, succ; + + DWORD RaceResIndex; + RACE_DESCPTR RaceDescPtr; + EXTENDED_SHIP_INFO ShipInfo; +} EXTENDED_SHIP_FRAGMENT; +typedef EXTENDED_SHIP_FRAGMENT *PEXTENDED_SHIP_FRAGMENT; +#define EXTENDED_SHIP_FRAGMENTPTR PEXTENDED_SHIP_FRAGMENT + +#define AllocStarShip(pq) AllocLink (pq) +#define LockStarShip(pq,h) (STARSHIPPTR)LockLink (pq, h) +#define UnlockStarShip(pq,h) UnlockLink (pq, h) +#define FreeStarShip(pq,h) FreeLink (pq, h) + +enum +{ + ARILOU_SHIP, + CHMMR_SHIP, + HUMAN_SHIP, + ORZ_SHIP, + PKUNK_SHIP, + SHOFIXTI_SHIP, + SPATHI_SHIP, + SUPOX_SHIP, + THRADDASH_SHIP, + UTWIG_SHIP, + VUX_SHIP, + YEHAT_SHIP, + MELNORME_SHIP, + DRUUGE_SHIP, + ILWRATH_SHIP, + MYCON_SHIP, + SLYLANDRO_SHIP, + UMGAH_SHIP, + URQUAN_SHIP, + ZOQFOTPIK_SHIP, + + SYREEN_SHIP, + BLACK_URQUAN_SHIP, + YEHAT_REBEL_SHIP, + URQUAN_PROBE_SHIP, + SAMATRA_SHIP = URQUAN_PROBE_SHIP, + + NUM_AVAILABLE_RACES +}; + +#define YEHAT_REBEL_CONVERSATION (~0L) + +#define RACE_COMMUNICATION \ + ARILOU_CONVERSATION, /* ARILOU_SHIP */ \ + CHMMR_CONVERSATION, /* CHMMR_SHIP */ \ + 0L, /* HUMAN_SHIP */ \ + ORZ_CONVERSATION, /* ORZ_SHIP */ \ + PKUNK_CONVERSATION, /* PKUNK_SHIP */ \ + SHOFIXTI_CONVERSATION, /* SHOFIXTI_SHIP */ \ + SPATHI_CONVERSATION, /* SPATHI_SHIP */ \ + SUPOX_CONVERSATION, /* SUPOX_SHIP */ \ + THRADD_CONVERSATION, /* THRADDASH_SHIP */ \ + UTWIG_CONVERSATION, /* UTWIG_SHIP */ \ + VUX_CONVERSATION, /* VUX_SHIP */ \ + YEHAT_CONVERSATION, /* YEHAT_SHIP */ \ + MELNORME_CONVERSATION, /* MELNORME_SHIP */ \ + DRUUGE_CONVERSATION, /* DRUUGE_SHIP */ \ + ILWRATH_CONVERSATION, /* ILWRATH_SHIP */ \ + MYCON_CONVERSATION, /* MYCON_SHIP */ \ + SLYLANDRO_CONVERSATION, /* SLYLANDRO_SHIP */ \ + UMGAH_CONVERSATION, /* UMGAH_SHIP */ \ + URQUAN_CONVERSATION, /* URQUAN_SHIP */ \ + ZOQFOTPIK_CONVERSATION, /* ZOQFOTPIK_SHIP */ \ + 0L, /* SYREEN_SHIP */ \ + BLACKURQ_CONVERSATION, /* BLACK_URQUAN_SHIP */ \ + YEHAT_REBEL_CONVERSATION, /* YEHAT_REBEL_SHIP */ \ + 0L, /* URQUAN_PROBE_SHIP */ + +#define RACE_SHIP_COST \ + 1600, /* ARILOU_SHIP */ \ + 3000, /* CHMMR_SHIP */ \ + 1100, /* HUMAN_SHIP */ \ + 2300, /* ORZ_SHIP */ \ + 2000, /* PKUNK_SHIP */ \ + 500, /* SHOFIXTI_SHIP */ \ + 1800, /* SPATHI_SHIP */ \ + 1600, /* SUPOX_SHIP */ \ + 1000, /* THRADDASH_SHIP */ \ + 2200, /* UTWIG_SHIP */ \ + 1200, /* VUX_SHIP */ \ + 2300, /* YEHAT_SHIP */ \ + 3600, /* MELNORME_SHIP */ \ + 1700, /* DRUUGE_SHIP */ \ + 1000, /* ILWRATH_SHIP */ \ + 2100, /* MYCON_SHIP */ \ + 4400, /* SLYLANDRO_SHIP */ \ + 700, /* UMGAH_SHIP */ \ + 3000, /* URQUAN_SHIP */ \ + 600, /* ZOQFOTPIK_SHIP */ \ + 1300, /* SYREEN_SHIP */ \ + 3000, /* BLACK_URQUAN_SHIP */ \ + 2300, /* YEHAT_REBEL_SHIP */ + +#define LOG_TO_IP(s) ((s) << 1) +#define RACE_IP_SPEED \ + LOG_TO_IP (40), /* ARILOU_SHIP */ \ + LOG_TO_IP (27), /* CHMMR_SHIP */ \ + LOG_TO_IP (24), /* HUMAN_SHIP */ \ + LOG_TO_IP (40), /* ORZ_SHIP */ \ + LOG_TO_IP (40), /* PKUNK_SHIP */ \ + LOG_TO_IP (35), /* SHOFIXTI_SHIP */ \ + LOG_TO_IP (48), /* SPATHI_SHIP */ \ + LOG_TO_IP (40), /* SUPOX_SHIP */ \ + LOG_TO_IP (28), /* THRADDASH_SHIP */ \ + LOG_TO_IP (30), /* UTWIG_SHIP */ \ + LOG_TO_IP (21), /* VUX_SHIP */ \ + LOG_TO_IP (30), /* YEHAT_SHIP */ \ + LOG_TO_IP (40), /* MELNORME_SHIP */ \ + LOG_TO_IP (20), /* DRUUGE_SHIP */ \ + LOG_TO_IP (25), /* ILWRATH_SHIP */ \ + LOG_TO_IP (27), /* MYCON_SHIP */ \ + LOG_TO_IP (60), /* SLYLANDRO_SHIP */ \ + LOG_TO_IP (18), /* UMGAH_SHIP */ \ + LOG_TO_IP (30), /* URQUAN_SHIP */ \ + LOG_TO_IP (40), /* ZOQFOTPIK_SHIP */ \ + LOG_TO_IP (36), /* SYREEN_SHIP */ \ + LOG_TO_IP (30), /* BLACK_URQUAN_SHIP */ \ + LOG_TO_IP (30), /* YEHAT_REBEL_SHIP */ \ + LOG_TO_IP (90), /* URQUAN_PROBE_SHIP */ + +#define LOG_TO_HYPER(s) (WORLD_TO_VELOCITY (s) >> 1) +#define RACE_HYPER_SPEED \ + LOG_TO_HYPER (40), /* ARILOU_SHIP */ \ + LOG_TO_HYPER (27), /* CHMMR_SHIP */ \ + LOG_TO_HYPER (24), /* HUMAN_SHIP */ \ + LOG_TO_HYPER (40), /* ORZ_SHIP */ \ + LOG_TO_HYPER (40), /* PKUNK_SHIP */ \ + LOG_TO_HYPER (35), /* SHOFIXTI_SHIP */ \ + LOG_TO_HYPER (48), /* SPATHI_SHIP */ \ + LOG_TO_HYPER (40), /* SUPOX_SHIP */ \ + LOG_TO_HYPER (50), /* THRADDASH_SHIP */ \ + LOG_TO_HYPER (30), /* UTWIG_SHIP */ \ + LOG_TO_HYPER (21), /* VUX_SHIP */ \ + LOG_TO_HYPER (30), /* YEHAT_SHIP */ \ + LOG_TO_HYPER (40), /* MELNORME_SHIP */ \ + LOG_TO_HYPER (20), /* DRUUGE_SHIP */ \ + LOG_TO_HYPER (25), /* ILWRATH_SHIP */ \ + LOG_TO_HYPER (27), /* MYCON_SHIP */ \ + LOG_TO_HYPER (60), /* SLYLANDRO_SHIP */ \ + LOG_TO_HYPER (18), /* UMGAH_SHIP */ \ + LOG_TO_HYPER (30), /* URQUAN_SHIP */ \ + LOG_TO_HYPER (40), /* ZOQFOTPIK_SHIP */ \ + LOG_TO_HYPER (36), /* SYREEN_SHIP */ \ + LOG_TO_HYPER (30), /* BLACK_URQUAN_SHIP */ \ + LOG_TO_HYPER (30), /* YEHAT_REBEL_SHIP */ + +#define RACE_HYPERSPACE_PERCENT \ + 20, /* ARILOU_SHIP */ \ + 0, /* CHMMR_SHIP */ \ + 0, /* HUMAN_SHIP */ \ + 20, /* ORZ_SHIP */ \ + 40, /* PKUNK_SHIP */ \ + 0, /* SHOFIXTI_SHIP */ \ + 20, /* SPATHI_SHIP */ \ + 40, /* SUPOX_SHIP */ \ + 60, /* THRADDASH_SHIP */ \ + 40, /* UTWIG_SHIP */ \ + 40, /* VUX_SHIP */ \ + 60, /* YEHAT_SHIP */ \ + 0, /* MELNORME_SHIP */ \ + 30, /* DRUUGE_SHIP */ \ + 60, /* ILWRATH_SHIP */ \ + 40, /* MYCON_SHIP */ \ + 2, /* SLYLANDRO_SHIP */ \ + 30, /* UMGAH_SHIP */ \ + 70, /* URQUAN_SHIP */ \ + 0, /* ZOQFOTPIK_SHIP */ \ + 0, /* SYREEN_SHIP */ \ + 70, /* BLACK_URQUAN_SHIP */ \ + 60, /* YEHAT_REBEL_SHIP */ \ + 0, /* URQUAN_PROBE_SHIP */ + +#define RACE_INTERPLANETARY_PERCENT \ + 0, /* ARILOU_SHIP */ \ + 0, /* CHMMR_SHIP */ \ + 0, /* HUMAN_SHIP */ \ + 20, /* ORZ_SHIP */ \ + 20, /* PKUNK_SHIP */ \ + 0, /* SHOFIXTI_SHIP */ \ + 10, /* SPATHI_SHIP */ \ + 20, /* SUPOX_SHIP */ \ + 20, /* THRADDASH_SHIP */ \ + 20, /* UTWIG_SHIP */ \ + 20, /* VUX_SHIP */ \ + 40, /* YEHAT_SHIP */ \ + 0, /* MELNORME_SHIP */ \ + 20, /* DRUUGE_SHIP */ \ + 60, /* ILWRATH_SHIP */ \ + 20, /* MYCON_SHIP */ \ + 5, /* SLYLANDRO_SHIP */ \ + 20, /* UMGAH_SHIP */ \ + 40, /* URQUAN_SHIP */ \ + 0, /* ZOQFOTPIK_SHIP */ \ + 0, /* SYREEN_SHIP */ \ + 40, /* BLACK_URQUAN_SHIP */ \ + 40, /* YEHAT_REBEL_SHIP */ \ + 0, /* URQUAN_PROBE_SHIP */ + +#define RACE_ENCOUNTER_MAKEUP \ + MAKE_BYTE (1, 5), /* ARILOU_SHIP */ \ + 0, /* CHMMR_SHIP */ \ + 0, /* HUMAN_SHIP */ \ + MAKE_BYTE (1, 5), /* ORZ_SHIP */ \ + MAKE_BYTE (1, 5), /* PKUNK_SHIP */ \ + 0, /* SHOFIXTI_SHIP */ \ + MAKE_BYTE (1, 5), /* SPATHI_SHIP */ \ + MAKE_BYTE (1, 5), /* SUPOX_SHIP */ \ + MAKE_BYTE (1, 5), /* THRADDASH_SHIP */ \ + MAKE_BYTE (1, 5), /* UTWIG_SHIP */ \ + MAKE_BYTE (1, 5), /* VUX_SHIP */ \ + MAKE_BYTE (1, 5), /* YEHAT_SHIP */ \ + MAKE_BYTE (1, 1), /* MELNORME_SHIP */ \ + MAKE_BYTE (1, 5), /* DRUUGE_SHIP */ \ + MAKE_BYTE (1, 5), /* ILWRATH_SHIP */ \ + MAKE_BYTE (1, 5), /* MYCON_SHIP */ \ + MAKE_BYTE (1, 1), /* SLYLANDRO_SHIP */ \ + MAKE_BYTE (1, 5), /* UMGAH_SHIP */ \ + MAKE_BYTE (1, 5), /* URQUAN_SHIP */ \ + MAKE_BYTE (1, 5), /* ZOQFOTPIK_SHIP */ \ + 0, /* SYREEN_SHIP */ \ + MAKE_BYTE (1, 5), /* BLACK_URQUAN_SHIP */ \ + MAKE_BYTE (1, 5), /* YEHAT_REBEL_SHIP */ + +#define RACE_COLORS \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), /* ARILOU_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* CHMMR_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x1f), 0x4D), /* HUMAN_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* ORZ_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* PKUNK_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* SHOFIXTI_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SPATHI_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SUPOX_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* THRADDASH_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* UTWIG_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), /* VUX_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x11), 0x3D), /* YEHAT_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* MELNORME_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), /* DRUUGE_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* ILWRATH_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* MYCON_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SLYLANDRO_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x11), 0x3D), /* UMGAH_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x08, 0x00), 0x6E), /* URQUAN_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), /* ZOQFOTPIK_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* SYREEN_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x20), /* BLACK_URQUAN_SHIP */ \ + BUILD_COLOR (MAKE_RGB15 (0x14, 0x07, 0x1F), 0x39), /* YEHAT_REBEL_SHIP */ + +#define RADAR_SCAN_WIDTH (UNIT_SCREEN_WIDTH * NUM_RADAR_SCREENS) +#define RADAR_SCAN_HEIGHT (UNIT_SCREEN_HEIGHT * NUM_RADAR_SCREENS) + +#define ARILOU_SPACE_X 438 +#define ARILOU_SPACE_Y 6372 + +#define QUASI_SPACE_X 5000 +#define QUASI_SPACE_Y 5000 +#define ARILOU_HOME_X (QUASI_SPACE_X + ((RADAR_SCAN_WIDTH >> 1) * 3)) +#define ARILOU_HOME_Y (QUASI_SPACE_Y + ((RADAR_SCAN_HEIGHT >> 1) * 3)) + +#define SOL_X 1752 +#define SOL_Y 1450 + +extern BOOLEAN InitKernel (void); +extern void UninitKernel (BOOLEAN ships); + +extern void DrawCaptainsWindow (STARSHIPPTR + StarShipPtr); +extern BOOLEAN GetNextStarShip (STARSHIPPTR + LastStarShipPtr, COUNT which_side); +extern HSTARSHIP GetEncounterStarShip (STARSHIPPTR + LastStarShipPtr, COUNT which_player); +extern void DrawArmadaPickShip (BOOLEAN + draw_salvage_frame, PRECT pPickRect); + +extern BOOLEAN load_animation (PFRAME pixarray, DWORD + big_res, DWORD med_res, DWORD sml_res); +extern BOOLEAN free_image (PFRAME pixarray); +extern void NotifyOthers (COUNT which_race, BYTE + target_loc); + +#endif /* _RACES_H */ + diff --git a/sc2/src/sc2code/resinst.h b/sc2/src/sc2code/resinst.h new file mode 100644 index 000000000..b37fc95b6 --- /dev/null +++ b/sc2/src/sc2code/resinst.h @@ -0,0 +1,25 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "ikey_con.h" +#include "igfxres.h" +#include "ifontres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "ires_ind.h" diff --git a/sc2/src/sc2code/respkg.h b/sc2/src/sc2code/respkg.h new file mode 100644 index 000000000..db02bb560 --- /dev/null +++ b/sc2/src/sc2code/respkg.h @@ -0,0 +1,304 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +enum +{ + INIT_PACKAGE = 1, + TITLE_PACKAGE, + ARILOU_SHIP_PACKAGE, + CHMMR_SHIP_PACKAGE, + EARTHLING_SHIP_PACKAGE, + ORZ_SHIP_PACKAGE, + PKUNK_SHIP_PACKAGE, + SHOFIXTI_SHIP_PACKAGE, + SPATHI_SHIP_PACKAGE, + SUPOX_SHIP_PACKAGE, + THRADD_SHIP_PACKAGE, + UTWIG_SHIP_PACKAGE, + VUX_SHIP_PACKAGE, + YEHAT_SHIP_PACKAGE, + MELNORME_SHIP_PACKAGE, + DRUUGE_SHIP_PACKAGE, + ILWRATH_SHIP_PACKAGE, + MYCON_SHIP_PACKAGE, + SLYLANDRO_SHIP_PACKAGE, + UMGAH_SHIP_PACKAGE, + URQUAN_SHIP_PACKAGE, + ZOQFOTPIK_SHIP_PACKAGE, + SYREEN_SHIP_PACKAGE, + BLACKURQ_SHIP_PACKAGE, + ANDROSYN_SHIP_PACKAGE, + CHENJESU_SHIP_PACKAGE, + MMRNMHRM_SHIP_PACKAGE, + KERNEL_PACKAGE, + SC2KERNEL_PACKAGE, + MICROFONT_PACKAGE, + SC2DATA_PACKAGE, + MENU_SOUND_PACKAGE, + SOUND_PACKAGE, + SPACE_PACKAGE, + AMBIENT_HYPER_PACKAGE, + HYPER_PACKAGE, + ARISPACE_PACKAGE, + HYPERSPACE_MUSIC_PACKAGE, + QUASISPACE_MUSIC_PACKAGE, + INIT_PACKAGE, + IP_PACKAGE, + LANDER_PACKAGE, + ORBIT_VIEW_PACKAGE, + EARTH_PACKAGE, + CANNISTER_PACKAGE, + LIFE00_PACKAGE, + LIFE01_PACKAGE, + LIFE02_PACKAGE, + LIFE03_PACKAGE, + LIFE04_PACKAGE, + LIFE05_PACKAGE, + LIFE06_PACKAGE, + LIFE07_PACKAGE, + LIFE08_PACKAGE, + LIFE09_PACKAGE, + LIFE10_PACKAGE, + LIFE11_PACKAGE, + LIFE12_PACKAGE, + LIFE13_PACKAGE, + LIFE14_PACKAGE, + LIFE15_PACKAGE, + LIFE16_PACKAGE, + LIFE17_PACKAGE, + LIFE18_PACKAGE, + LIFE19_PACKAGE, + LIFE20_PACKAGE, + LIFE21_PACKAGE, + LIFE22_PACKAGE, + LIFE23_PACKAGE, + LIFE24_PACKAGE, + LIFE25_PACKAGE, + OOLITE_PACKAGE, + YTTRIC_COLOR_PACKAGE, + YTTRIC_XLAT_PACKAGE, + QD_COLOR_PACKAGE, + QD_XLAT_PACKAGE, + LANTHANIDE_COLOR_PACKAGE, + TREASURE_COLOR_PACKAGE, + UREA_COLOR_PACKAGE, + UREA_XLAT_PACKAGE, + METAL_PACKAGE, + RADIOACTIVE_COLOR_PACKAGE, + OPALESCENT_COLOR_PACKAGE, + OPALESCENT_XLAT_PACKAGE, + CYANIC_COLOR_PACKAGE, + ACID_COLOR_PACKAGE, + ALKALI_COLOR_PACKAGE, + HALIDE_COLOR_PACKAGE, + GREEN_COLOR_PACKAGE, + COPPER_COLOR_PACKAGE, + CARBIDE_COLOR_PACKAGE, + ULTRAMARINE_COLOR_PACKAGE, + NOBLE_COLOR_PACKAGE, + AZURE_COLOR_PACKAGE, + CHONDRITE_PACKAGE, + PURPLE_COLOR_PACKAGE, + SUPER_DENSE_COLOR_PACKAGE, + PELLUCID_COLOR_PACKAGE, + DUST_COLOR_PACKAGE, + MAROON_COLOR_PACKAGE, + CIMMERIAN_COLOR_PACKAGE, + INFRARED_COLOR_PACKAGE, + SELENIC_COLOR_PACKAGE, + AURIC_COLOR_PACKAGE, + FLUORESCENT_COLOR_PACKAGE, + ULTRAVIOLET_COLOR_PACKAGE, + PLUTONIC_COLOR_PACKAGE, + RAINBOW_COLOR_PACKAGE, + CRACKED_PACKAGE, + SAPPHIRE_COLOR_PACKAGE, + SAPPHIRE_XLAT_PACKAGE, + ORGANIC_COLOR_PACKAGE, + XENOLITHIC_COLOR_PACKAGE, + REDUX_PACKAGE, + PRIMORDIAL_COLOR_PACKAGE, + EMERALD_COLOR_PACKAGE, + CHLORINE_COLOR_PACKAGE, + CHLORINE_XLAT_PACKAGE, + MAGNETIC_COLOR_PACKAGE, + WATER_COLOR_PACKAGE, + TELLURIC_COLOR_PACKAGE, + HYDROCARBON_COLOR_PACKAGE, + IODINE_COLOR_PACKAGE, + VINYLOGOUS_COLOR_PACKAGE, + RUBY_COLOR_PACKAGE, + MAGMA_COLOR_PACKAGE, + CRIMSON_COLOR_PACKAGE, + GAS_XLAT_PACKAGE, + BLU_GAS_CT_PACKAGE, + CYA_GAS_CT_PACKAGE, + GRN_GAS_CT_PACKAGE, + GRY_GAS_CT_PACKAGE, + ORA_GAS_CT_PACKAGE, + PUR_GAS_CT_PACKAGE, + RED_GAS_CT_PACKAGE, + VIO_GAS_CT_PACKAGE, + YEL_GAS_CT_PACKAGE, + REPORT_PACKAGE, + MOONBASE_PACKAGE, + MAIDENS_PACKAGE, + CHMMR_BASE_PACKAGE, + AQUA_PACKAGE, + BURV_BCS_PACKAGE, + TAALO_DEVICE_PACKAGE, + SUN_DEVICE_PACKAGE, + VAULT_PACKAGE, + WRECK_PACKAGE, + BOMB_PACKAGE, + BEAST_PACKAGE, + EGG_CASE_PACKAGE, + SPAPLUTO_PACKAGE, + BURV_RUINS_PACKAGE, + ANDROSYNTH_RUINS_PACKAGE, + DRUUGE_RUINS_PACKAGE, + PKUNK_RUINS_PACKAGE, + RACE_RUINS_PACKAGE, + RACE_RUINS_TEXT_PACKAGE, + UMGAH_BCS_PACKAGE, + IP_MUSIC_PACKAGE, + ORBIT_MUSIC_PACKAGE, + MELEE_BGROUND_PACKAGE, + MELEE_PICK_PACKAGE, + SC2_SEGUE_PACKAGE, + SC2_PICK_PACKAGE, + ARILOU_CONVERSATION_PACKAGE, + CHMMR_CONVERSATION_PACKAGE, + COMMANDER_CONVERSATION_PACKAGE, + ORZ_CONVERSATION_PACKAGE, + PKUNK_CONVERSATION_PACKAGE, + SHOFIXTI_CONVERSATION_PACKAGE, + SPATHI_CONVERSATION_PACKAGE, + SUPOX_CONVERSATION_PACKAGE, + THRADD_CONVERSATION_PACKAGE, + UTWIG_CONVERSATION_PACKAGE, + VUX_CONVERSATION_PACKAGE, + YEHAT_CONVERSATION_PACKAGE, + MELNORME_CONVERSATION_PACKAGE, + DRUUGE_CONVERSATION_PACKAGE, + ILWRATH_CONVERSATION_PACKAGE, + MYCON_CONVERSATION_PACKAGE, + SLYLANDRO_CONVERSATION_PACKAGE, + UMGAH_CONVERSATION_PACKAGE, + URQUAN_CONVERSATION_PACKAGE, + ZOQFOTPIK_CONVERSATION_PACKAGE, + SYREEN_CONVERSATION_PACKAGE, + BLACKURQ_CONVERSATION_PACKAGE, + TALKING_PET_CONVERSATION_PACKAGE, + SLYLANDRO_HOME_CONVERSATION_PACKAGE, + PLAYER_CONVERSATION_PACKAGE, + SIS_PACKAGE, + SAMATRA_PACKAGE, + URQUAN_PROBE_PACKAGE, + RESTART_PACKAGE, + MODULE_PACKAGE, + OUTFIT_PACKAGE, + OUTFIT_MUSIC_PACKAGE, + BLUEPRINT_PACKAGE, + SHIPYARD_MUSIC_PACKAGE, + STARBASE_PACKAGE, + SAMATRA_BATTLE_PACKAGE, + SHIELDED_BATTLE_PACKAGE, + PLANET00_PACKAGE, + PLANET01_PACKAGE, + PLANET02_PACKAGE, + PLANET03_PACKAGE, + PLANET04_PACKAGE, + PLANET05_PACKAGE, + PLANET06_PACKAGE, + PLANET07_PACKAGE, + PLANET08_PACKAGE, + PLANET09_PACKAGE, + PLANET10_PACKAGE, + PLANET11_PACKAGE, + PLANET12_PACKAGE, + PLANET13_PACKAGE, + PLANET14_PACKAGE, + PLANET15_PACKAGE, + PLANET16_PACKAGE, + PLANET17_PACKAGE, + PLANET18_PACKAGE, + PLANET19_PACKAGE, + PLANET20_PACKAGE, + PLANET21_PACKAGE, + PLANET22_PACKAGE, + PLANET23_PACKAGE, + PLANET24_PACKAGE, + PLANET25_PACKAGE, + PLANET26_PACKAGE, + PLANET27_PACKAGE, + PLANET28_PACKAGE, + PLANET29_PACKAGE, + PLANET30_PACKAGE, + PLANET31_PACKAGE, + PLANET32_PACKAGE, + PLANET33_PACKAGE, + PLANET34_PACKAGE, + PLANET35_PACKAGE, + PLANET36_PACKAGE, + PLANET37_PACKAGE, + PLANET38_PACKAGE, + PLANET39_PACKAGE, + PLANET40_PACKAGE, + PLANET41_PACKAGE, + PLANET42_PACKAGE, + PLANET43_PACKAGE, + PLANET44_PACKAGE, + PLANET45_PACKAGE, + PLANET46_PACKAGE, + PLANET47_PACKAGE, + PLANET48_PACKAGE, + PLANET49_PACKAGE, + PLANET50_PACKAGE, + PLANET51_PACKAGE, + PLANET52_PACKAGE, + PLANET53_PACKAGE, + PLANET54_PACKAGE, + PLANET55_PACKAGE, + PLANET56_PACKAGE, + PLANET57_PACKAGE, + PLANET58_PACKAGE, + BATTLE_MUSIC_PACKAGE, + CREDIT00_PACKAGE, + CREDIT01_PACKAGE, + CREDIT02_PACKAGE, + CREDIT03_PACKAGE, + CREDIT04_PACKAGE, + CREDIT05_PACKAGE, + CREDIT06_PACKAGE, + CREDIT07_PACKAGE, + CREDIT08_PACKAGE, + CREDIT09_PACKAGE, + CREDIT10_PACKAGE, + CREDIT11_PACKAGE, + CREDIT12_PACKAGE, + CREDIT13_PACKAGE, + CREDIT14_PACKAGE, + CREDIT15_PACKAGE, + CREDIT16_PACKAGE, + CREDIT17_PACKAGE, + CREDIT18_PACKAGE, + CREDIT19_PACKAGE, + CREDIT_MUSIC_PACKAGE +}; + diff --git a/sc2/src/sc2code/restart.c b/sc2/src/sc2code/restart.c new file mode 100644 index 000000000..404f21b9f --- /dev/null +++ b/sc2/src/sc2code/restart.c @@ -0,0 +1,288 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +//Added by Chris + +void Melee (void); + +void Victory (void); + +void Credits (void); + +void FreeHyperData (void); + +void FreeIPData (void); + +void FreeSC2Data (void); + +void FreeLanderData (void); + +//End Added by Chris + +enum +{ + START_NEW_GAME = 0, + LOAD_SAVED_GAME, + PLAY_SUPER_MELEE +}; + +static void +DrawRestartMenu (BYTE OldState, BYTE NewState, FRAME f) +{ + RECT r; + + SetSemaphore (&GraphicsSem); + SetContext (ScreenContext); + r.corner.x = r.corner.y = r.extent.width = r.extent.height = 0; + SetContextClipRect (&r); + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + SetFlashRect (&r, SetAbsFrameIndex (f, NewState + 1)); + ClearSemaphore (&GraphicsSem); + (void) OldState; /* Satisfying compiler (unused parameter) */ +} + +DWORD InTime; + +static BOOLEAN +DoRestart (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (!pMS->Initialized) + { + DrawRestartMenu ((BYTE)~0, pMS->CurState, pMS->CurFrame); + pMS->Initialized = TRUE; + + { + BYTE clut_buf[] = {FadeAllToColor}; + + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2)); + } + } +#ifdef TESTING +else if (InputState & DEVICE_EXIT) return (FALSE); +#endif /* TESTING */ + else if (InputState == 0) + { + if (GetTimeCounter () - InTime < ONE_SECOND * 15) + return (TRUE); + + GLOBAL (CurrentActivity) = (ACTIVITY)~0; + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + switch (pMS->CurState) + { + case LOAD_SAVED_GAME: + LastActivity = CHECK_LOAD; + GLOBAL (CurrentActivity) = IN_INTERPLANETARY; + break; + case START_NEW_GAME: + LastActivity = CHECK_LOAD | CHECK_RESTART; + GLOBAL (CurrentActivity) = IN_INTERPLANETARY; + break; + case PLAY_SUPER_MELEE: + GLOBAL (CurrentActivity) = SUPER_MELEE; + break; + } + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + else + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == START_NEW_GAME) + NewState = PLAY_SUPER_MELEE; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == PLAY_SUPER_MELEE) + NewState = START_NEW_GAME; + } + + if (NewState != pMS->CurState) + { + DrawRestartMenu (pMS->CurState, NewState, pMS->CurFrame); + pMS->CurState = NewState; + } + } + + InTime = GetTimeCounter (); + return (TRUE); +} + +BOOLEAN +StartGame (void) +{ + MENU_STATE MenuState; + +TimedOut: + LastActivity = GLOBAL (CurrentActivity); + GLOBAL (CurrentActivity) = 0; + if (LastActivity == (ACTIVITY)~0) + Introduction (); + + memset ((PMENU_STATE)&MenuState, 0, sizeof (MenuState)); + MenuState.InputFunc = DoRestart; + + { + DWORD TimeOut; + BYTE black_buf[1]; + extern ACTIVITY NextActivity; + +TryAgain: + ReinitQueue (&race_q[0]); + ReinitQueue (&race_q[1]); + + black_buf[0] = FadeAllToBlack; + + SetContext (ScreenContext); + SetContextBGFrame ((FRAME)0); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + GLOBAL (CurrentActivity) |= CHECK_ABORT; + if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 + && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP) + && !GET_GAME_STATE (UTWIG_BOMB)) + { + BYTE white_buf[] = {FadeAllToWhite}; + + SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); + + SleepTask (XFormColorMap ((COLORMAPPTR)white_buf, ONE_SECOND / 8) + 2); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + ClearDrawable (); + FlushColorXForms (); + + TimeOut = ONE_SECOND / 8; + } + else + { + TimeOut = ONE_SECOND / 2; +#ifdef NOTYET +LastActivity = WON_LAST_BATTLE; +#endif /* NOTYET */ + if (LOBYTE (LastActivity) == WON_LAST_BATTLE) + { + Victory (); + Credits (); + TimeOut = ONE_SECOND / 2; + } + } + + LastActivity = NextActivity = 0; + + { + RECT r; + STAMP s; + + s.frame = CaptureDrawable ( + LoadGraphic (RESTART_PMAP_ANIM) + ); + MenuState.CurFrame = s.frame; + GetFrameRect (s.frame, &r); + s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; + s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; + SleepTask (XFormColorMap ((COLORMAPPTR)black_buf, TimeOut)); + if (TimeOut == ONE_SECOND / 8) + SleepTask (GetTimeCounter () + ONE_SECOND * 3); + + SetContextBackGroundColor (BLACK_COLOR); + BatchGraphics (); + ClearDrawable (); + FlushColorXForms (); + DrawStamp (&s); + UnbatchGraphics (); + + FlushInput (); + DoInput ((PVOID)&MenuState); + + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)0, (FRAME)0); + ClearSemaphore (&GraphicsSem); + DestroyDrawable (ReleaseDrawable (s.frame)); + + if (GLOBAL (CurrentActivity) == (ACTIVITY)~0) + goto TimedOut; +#ifdef TESTING +if (GLOBAL (CurrentActivity) & CHECK_ABORT) +{ + while (SoundPlaying ()); + StopSound (); + + FreeSC2Data (); + FreeLanderData (); + FreeIPData (); + FreeHyperData (); + FlushColorXForms (); + return (FALSE); +} +#endif /* TESTING */ + + TimeOut = XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND / 2); + } + + SleepTask (TimeOut); + FlushColorXForms (); + + SeedRandomNumbers (); + + if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) + { +FreeSC2Data (); +FreeLanderData (); +FreeIPData (); +FreeHyperData (); + Melee (); + MenuState.Initialized = FALSE; + goto TryAgain; + } + +{ +extern STAR_DESC starmap_array[]; +extern const BYTE element_array[]; +extern const PlanetFrame planet_array[]; + +star_array = starmap_array; +Elements = element_array; +PlanData = planet_array; +} + + PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; + PlayerControl[1] = COMPUTER_CONTROL | AWESOME_RATING; + SetPlayerInput (); + return (TRUE); + } + + return (FALSE); +} + diff --git a/sc2/src/sc2code/restypes.h b/sc2/src/sc2code/restypes.h new file mode 100644 index 000000000..9b758894f --- /dev/null +++ b/sc2/src/sc2code/restypes.h @@ -0,0 +1,35 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/save.c b/sc2/src/sc2code/save.c new file mode 100644 index 000000000..a1fa3ef01 --- /dev/null +++ b/sc2/src/sc2code/save.c @@ -0,0 +1,471 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "declib.h" + +void FreeSC2Data (void); + +BOOLEAN LoadSC2Data (void); + +static void +SaveShipQueue (DECODE_REF fh, PQUEUE pQueue) +{ + COUNT num_links; + HSTARSHIP hStarShip; + + num_links = CountLinks (pQueue); + cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); + + hStarShip = GetHeadLink (pQueue); + while (num_links--) + { + HSTARSHIP hNextShip; + SHIP_FRAGMENTPTR FragPtr; + COUNT Index, Offset; + PBYTE Ptr; + + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); + hNextShip = _GetSuccLink (FragPtr); + + if (pQueue == &GLOBAL (avail_race_q)) + { + Index = GetIndexFromStarShip (pQueue, hStarShip); + Offset = 0; + } + else + { + Index = GET_RACE_ID (FragPtr); + Offset = (PBYTE)&FragPtr->ShipInfo + - (PBYTE)&FragPtr->RaceDescPtr; + } + + cwrite ((PBYTE)&Index, sizeof (Index), 1, fh); + + Ptr = ((PBYTE)&FragPtr->ShipInfo) - Offset; + cwrite ((PBYTE)Ptr, + ((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, + 1, fh); + if (Offset == 0) + { + EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr; + + ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr; + Ptr = (PBYTE)&ExtFragPtr->ShipInfo.actual_strength; + cwrite ((PBYTE)Ptr, ((PBYTE)&ExtFragPtr[1]) - Ptr, 1, fh); + } + + UnlockStarShip (pQueue, hStarShip); + hStarShip = hNextShip; + } +} + +static void +PrepareSummary (SUMMARY_DESC *summary_desc) +{ + extern SIZE InventoryDevices (BYTE *pDeviceMap); + + summary_desc->SS = GlobData.SIS_state; + + switch (summary_desc->Activity = LOBYTE (GLOBAL (CurrentActivity))) + { + case IN_HYPERSPACE: + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) + summary_desc->Activity = IN_QUASISPACE; + break; + case IN_INTERPLANETARY: + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0) + summary_desc->Activity = IN_STARBASE; + else if (pSolarSysState && pSolarSysState->MenuState.Initialized >= 3) + summary_desc->Activity = IN_PLANET_ORBIT; + break; + } + + summary_desc->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0); + summary_desc->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1); + + { + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), summary_desc->NumShips = 0; + hStarShip; hStarShip = hNextShip, ++summary_desc->NumShips) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + summary_desc->ShipList[summary_desc->NumShips] = GET_RACE_ID (StarShipPtr); + UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); + } + } + + summary_desc->NumDevices = InventoryDevices (summary_desc->DeviceList); + + summary_desc->Flags = GET_GAME_STATE (LANDER_SHIELDS) + | (GET_GAME_STATE (IMPROVED_LANDER_SPEED) << (4 + 0)) + | (GET_GAME_STATE (IMPROVED_LANDER_CARGO) << (4 + 1)) + | (GET_GAME_STATE (IMPROVED_LANDER_SHOT) << (4 + 2)) + | ((GET_GAME_STATE (CHMMR_BOMB_STATE) < 2 ? 0 : 1) << (4 + 3)); + + summary_desc->day_index = GLOBAL (GameClock.day_index); + summary_desc->month_index = GLOBAL (GameClock.month_index); + summary_desc->year_index = GLOBAL (GameClock.year_index); +} + +static void +SaveProblemMessage (STAMP *MsgStamp) +{ +#define MAX_MSG_LINES 1 + RECT r; + COUNT i; + TEXT t; + UNICODE *ppStr[MAX_MSG_LINES]; + + ppStr[0] = GAME_STRING (SAVEGAME_STRING_BASE + 2); + + SetContextFont (StarConFont); + + t.baseline.x = t.baseline.y = 0; + t.align = ALIGN_CENTER; + for (i = 0; i < MAX_MSG_LINES; ++i) + { + RECT tr; + + t.pStr = ppStr[i]; + if (*t.pStr == '\0') + break; + t.CharCount = (COUNT)~0; + TextRect (&t, &tr, NULL_PTR); + if (i == 0) + r = tr; + else + BoxUnion (&tr, &r, &r); + t.baseline.y += 11; + } + t.baseline.x = ((SIS_SCREEN_WIDTH >> 1) - (r.extent.width >> 1)) + - r.corner.x; + t.baseline.y = ((SIS_SCREEN_HEIGHT >> 1) - (r.extent.height >> 1)) + - r.corner.y; + r.corner.x += t.baseline.x - 4; + r.corner.y += t.baseline.y - 4; + r.extent.width += 8; + r.extent.height += 8; + + { + RECT clip_r; + + GetContextClipRect (&clip_r); + MsgStamp->origin = r.corner; + r.corner.x += clip_r.corner.x; + r.corner.y += clip_r.corner.y; + MsgStamp->frame = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); + r.corner.x -= clip_r.corner.x; + r.corner.y -= clip_r.corner.y; + } + + BatchGraphics (); + DrawStarConBox (&r, 2, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x0F)); + + for (i = 0; i < MAX_MSG_LINES; ++i) + { + t.pStr = ppStr[i]; + if (*t.pStr == '\0') + break; + t.CharCount = (COUNT)~0; + DrawText (&t); + t.baseline.y += 11; + } + UnbatchGraphics (); +} + +BOOLEAN +SaveProblem (void) +{ + BOOLEAN manage; + STAMP s; + INPUT_STATE InputState; + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (SpaceContext); + + SaveProblemMessage (&s); + + GLOBAL (CurrentActivity) |= CHECK_ABORT; + + while (AnyButtonPress (FALSE)); + do + { + InputState = GetInputState (NormalInput); + if (InputState & DEVICE_BUTTON1) + manage = TRUE; + else if (InputState & DEVICE_BUTTON3) + manage = FALSE; + else + InputState = 0; + } while (!InputState); + + GLOBAL (CurrentActivity) &= ~CHECK_ABORT; + + BatchGraphics (); + DrawStamp (&s); + UnbatchGraphics (); + SetContext (OldContext); + DestroyDrawable (ReleaseDrawable (s.frame)); + + ClearSemaphore (&GraphicsSem); + + if (manage) + { + BYTE clut_buf[1]; + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + clut_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2)); + FlushColorXForms (); + +#if 0 + SuspendTasking (); // just in case + ManageNVRAM (); + ResumeTasking (); +#endif + + clut_buf[0] = FadeAllToColor; + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2)); + FlushColorXForms (); + } + else + { +#if 0 + CleanNVRAM (); +#endif + SleepTask (GetTimeCounter () + (ONE_SECOND / 4)); + } + + return (manage); +} + +BOOLEAN +SaveGame (COUNT which_game, SUMMARY_DESC *summary_desc) +{ + BOOLEAN success, made_room; + PVOID out_fp; + MEM_HANDLE h; + DECODE_REF fh; + + success = TRUE; + made_room = FALSE; +RetrySave: + h = mem_request (10 * 1024); + if ((out_fp = mem_lock (h)) == 0 + || (fh = copen (out_fp, MEMORY_STREAM, STREAM_WRITE)) == 0) + { + if (success) + { + success = FALSE; + made_room = TRUE; + mem_unlock (h); + mem_release (h); + + FreeSC2Data (); +//printf ("Insufficient room for save buffers -- RETRYING\n"); + goto RetrySave; + } +//else +//printf ("Insufficient room for save buffers -- GIVING UP!\n"); + } + else + { + FILE *fp; + DWORD flen; + COUNT num_links; + FRAME frame; + POINT pt; + STAR_DESC SD; + char buf[256]; + extern void SaveFlagshipState (void); + + success = TRUE; + if (CurStarDescPtr) + SD = *CurStarDescPtr; + else + { + SD.star_pt.x = SD.star_pt.y = 0; + SD.Type = SD.Index = SD.Prefix = SD.Postfix = 0; + } + + frame = GLOBAL (ShipStamp.frame); + pt = GLOBAL (ip_location); + SaveFlagshipState (); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && !(GLOBAL (CurrentActivity) + & (START_ENCOUNTER | START_INTERPLANETARY))) + PutGroupInfo (0L, (BYTE)~0); + + cwrite ((PBYTE)&GlobData.Game_state, sizeof (GlobData.Game_state), 1, fh); + + GLOBAL (ip_location) = pt; + GLOBAL (ShipStamp.frame) = frame; + + SaveShipQueue (fh, &GLOBAL (avail_race_q)); + if (!(GLOBAL (CurrentActivity) & START_INTERPLANETARY)) + SaveShipQueue (fh, &GLOBAL (npc_built_ship_q)); + SaveShipQueue (fh, &GLOBAL (built_ship_q)); + + num_links = CountLinks (&GLOBAL (GameClock.event_q)); + cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); + { + HEVENT hEvent; + + hEvent = GetHeadLink (&GLOBAL (GameClock.event_q)); + while (num_links--) + { + HEVENT hNextEvent; + EVENTPTR EventPtr; + + LockEvent (hEvent, &EventPtr); + hNextEvent = GetSuccEvent (EventPtr); + + cwrite ((PBYTE)EventPtr, sizeof (*EventPtr), 1, fh); + + UnlockEvent (hEvent); + hEvent = hNextEvent; + } + } + + num_links = CountLinks (&GLOBAL (encounter_q)); + cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); + { + HENCOUNTER hEncounter; + + hEncounter = GetHeadLink (&GLOBAL (encounter_q)); + while (num_links--) + { + HENCOUNTER hNextEncounter; + ENCOUNTERPTR EncounterPtr; + + LockEncounter (hEncounter, &EncounterPtr); + hNextEncounter = GetSuccEncounter (EncounterPtr); + + cwrite ((PBYTE)EncounterPtr, sizeof (*EncounterPtr), 1, fh); + + UnlockEncounter (hEncounter); + hEncounter = hNextEncounter; + } + } + + fp = OpenResFile (STARINFO_FILE, "rb"); + if (fp) + { + flen = LengthResFile (fp); + cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + ReadResFile (buf, num_bytes, 1, fp); + cwrite ((PBYTE)buf, num_bytes, 1, fh); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + fp = OpenResFile (DEFGRPINFO_FILE, "rb"); + if (fp) + { + flen = LengthResFile (fp); + cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + ReadResFile (buf, num_bytes, 1, fp); + cwrite ((PBYTE)buf, num_bytes, 1, fh); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + fp = OpenResFile (RANDGRPINFO_FILE, "rb"); + if (fp) + { + flen = LengthResFile (fp); + cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); + while (flen) + { + COUNT num_bytes; + + num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; + ReadResFile (buf, num_bytes, 1, fp); + cwrite ((PBYTE)buf, num_bytes, 1, fh); + + flen -= num_bytes; + } + CloseResFile (fp); + } + + cwrite ((PBYTE)&SD, sizeof (SD), 1, fh); + + flen = cclose (fh); + + sprintf (buf, "starcon2.%02u", which_game); +//printf ("'%s' is %lu bytes long\n", buf, flen + sizeof (*summary_desc)); + if (flen && (out_fp = (PVOID)OpenResFile (buf, "wb"))) + { + PrepareSummary (summary_desc); + + success = (BOOLEAN)(WriteResFile ( + summary_desc, sizeof (*summary_desc), 1, out_fp + ) != 0); + if (success && WriteResFile (mem_lock (h), (COUNT)flen, 1, out_fp) == 0) + success = FALSE; + + mem_unlock (h); + if (CloseResFile ((FILE *)out_fp) == 0) + success = FALSE; + + } + else + success = FALSE; + + if (!success) + DeleteResFile (buf); + } + + mem_unlock (h); + mem_release (h); + + if (made_room) + LoadSC2Data (); + + return (success); +} + diff --git a/sc2/src/sc2code/settings.c b/sc2/src/sc2code/settings.c new file mode 100644 index 000000000..ede8ebb3d --- /dev/null +++ b/sc2/src/sc2code/settings.c @@ -0,0 +1,95 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +static MUSIC_REF LastMusicRef; +static BOOLEAN LastContinuous; +static BYTE LastPriority; + +void +ToggleMusic (void) +{ + GLOBAL (glob_flags) ^= MUSIC_DISABLED; + if (LastPriority <= 1) + { + if (GLOBAL (glob_flags) & MUSIC_DISABLED) + PLRStop (LastMusicRef); + else if (LastMusicRef) + PLRPlaySong (LastMusicRef, LastContinuous, LastPriority); + } +} + +void +PlayMusic (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) +{ + LastMusicRef = MusicRef; + LastContinuous = Continuous; + LastPriority = Priority; + + if ( +#ifdef NEVER + Priority > 1 + || +#endif /* NEVER */ + !(GLOBAL (glob_flags) & MUSIC_DISABLED) + ) + { + PLRPlaySong (MusicRef, Continuous, Priority); + } +} + +void +StopMusic (void) +{ + PLRStop (LastMusicRef); + LastMusicRef = 0; +} + +void +ResumeMusic (void) +{ + PLRResume (LastMusicRef); +} + +void +PauseMusic (void) +{ + PLRPause (LastMusicRef); +} + +void +ToggleSoundEffect (void) +{ + GLOBAL (glob_flags) ^= SOUND_DISABLED; +} + +void +PlaySoundEffect (SOUND S, COUNT Channel, BYTE Priority) +{ + if (!(GLOBAL (glob_flags) & SOUND_DISABLED)) + { + SetChannelVolume (Channel, MAX_VOLUME >> 1, Priority); + SetChannelRate (Channel, GetSampleRate (S), Priority); + PlayChannel (Channel, + GetSampleAddress (S), + GetSampleLength (S), + 0, 0, Priority); + } +} + diff --git a/sc2/src/sc2code/setup.c b/sc2/src/sc2code/setup.c new file mode 100644 index 000000000..257b0bc52 --- /dev/null +++ b/sc2/src/sc2code/setup.c @@ -0,0 +1,284 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "coderes.h" + +//Added by Chris + +BOOLEAN InitSpace (void); + +extern BOOLEAN InitVideo (BOOLEAN UseCDROM); + +//End Added by Chris + +ACTIVITY LastActivity; +BYTE PlayerControl[NUM_PLAYERS]; + +MEM_HANDLE hResIndex; +CONTEXT ScreenContext, SpaceContext, StatusContext, OffScreenContext, + TaskContext; +SIZE screen_width, screen_height; +FRAME Screen; +FONT StarConFont, MicroFont, TinyFont; +INPUT_REF ArrowInput, ComputerInput, NormalInput, SerialInput, + JoystickInput[NUM_PLAYERS], KeyboardInput[NUM_PLAYERS], + CombinedInput[NUM_PLAYERS], PlayerInput[NUM_PLAYERS]; +QUEUE race_q[NUM_PLAYERS]; +SOUND MenuSounds, GameSounds; +FRAME ActivityFrame, status, flagship_status, misc_data; +SEMAPHORE GraphicsSem; +STRING GameStrings; + +static MEM_HANDLE +LoadKeyConfig (FILE *fp, DWORD length) +{ + COUNT i; + BYTE buf[38], *pbuf; + + ReadResFile (buf, 1, sizeof (buf), fp); + + for (i = 0, pbuf = buf; i < NUM_PLAYERS; ++i, pbuf += 10) + { + KeyboardInput[i] = CaptureInputDevice ( + CreateJoystickKeyboardDevice ( + pbuf[2], pbuf[4], pbuf[6], 0, + 0, pbuf[8], pbuf[0], + 0, 0x1b + ) + ); + + } + + (void) length; /* Satisfying compiler (unused parameter) */ + return (NULL_HANDLE); +} + +static void +InitPlayerInput (void) +{ + INPUT_DEVICE InputDevice; + extern BOOLEAN PauseGame (void); + + InitInput (SK_F1, SK_F10, PauseGame); + + JoystickInput[0] = CaptureInputDevice (CreateJoystickDevice (0)); + JoystickInput[1] = CaptureInputDevice (CreateJoystickDevice (1)); + + SerialInput = CaptureInputDevice (CreateSerialKeyboardDevice ()); + ArrowInput = CaptureInputDevice (CreateJoystickKeyboardDevice ( + SK_LF_ARROW, SK_RT_ARROW, SK_UP_ARROW, SK_DN_ARROW, + '\n', ' ', 0x1b, SK_KEYPAD_MINUS, SK_KEYPAD_PLUS + )); + + InputDevice = CreateInternalDevice (game_input); + NormalInput = CaptureInputDevice (InputDevice); + InputDevice = CreateInternalDevice (computer_intelligence); + ComputerInput = CaptureInputDevice (InputDevice); + InputDevice = CreateInternalDevice (combined_input0); + CombinedInput[0] = CaptureInputDevice (InputDevice); + InputDevice = CreateInternalDevice (combined_input1); + CombinedInput[1] = CaptureInputDevice (InputDevice); + +#if DEMO_MODE + InputDevice = CreateInternalDevice (demo_input); + DemoInput = CaptureInputDevice (InputDevice); +#endif /* DEMO_MODE */ +} + +void +UninitPlayerInput (void) +{ + COUNT which_player; + +#if DEMO_MODE + DestroyInputDevice (ReleaseInputDevice (DemoInput)); +#endif /* DEMO_MODE */ + DestroyInputDevice (ReleaseInputDevice (ComputerInput)); + DestroyInputDevice (ReleaseInputDevice (NormalInput)); + + DestroyInputDevice (ReleaseInputDevice (ArrowInput)); + DestroyInputDevice (ReleaseInputDevice (SerialInput)); + for (which_player = 0; which_player < NUM_PLAYERS; ++which_player) + { + DestroyInputDevice (ReleaseInputDevice (JoystickInput[which_player])); + DestroyInputDevice (ReleaseInputDevice (KeyboardInput[which_player])); + DestroyInputDevice (ReleaseInputDevice (CombinedInput[which_player])); + } + + UninitInput (); +} + +BOOLEAN +LoadKernel (int argc, char *argv[]) +{ +#define MIN_K_REQUIRED (580000L / 1024) + if (!InitGraphics (argc, argv, MIN_K_REQUIRED)) + return (FALSE); + InitSound (argc, argv); + InitVideo (TRUE); + if ((ScreenContext = CaptureContext (CreateContext ())) == 0) + return(FALSE); + + if ((Screen = CaptureDrawable ( + CreateDisplay (WANT_MASK | WANT_PIXMAP, &screen_width, &screen_height) + )) == 0) + return(FALSE); + + SetContext (ScreenContext); + SetContextFGFrame (Screen); + SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); + + if ((hResIndex = InitResourceSystem ("starcon", RES_INDEX, NULL)) == 0) + return (FALSE); + INIT_INSTANCES (); + + InstallResTypeVectors (KEY_CONFIG, LoadKeyConfig, NULL_PTR); + GetResource (JOYSTICK_KEYS); + + { + COLORMAP ColorMapTab; + + ColorMapTab = CaptureColorMap (LoadColorMap (STARCON_COLOR_MAP)); + SetColorMap (GetColorMapAddress (ColorMapTab)); + DestroyColorMap (ReleaseColorMap (ColorMapTab)); + } + + InitPlayerInput (); + + GLOBAL (CurrentActivity) = (ACTIVITY)~0; + return (TRUE); +} + +BOOLEAN +InitContexts (void) +{ + RECT r; + if ((StatusContext = CaptureContext ( + CreateContext () + )) == 0) + return (FALSE); + + SetContext (StatusContext); + SetContextFGFrame (Screen); + r.corner.x = SPACE_WIDTH + SAFE_X; + r.corner.y = SAFE_Y; + r.extent.width = STATUS_WIDTH; + r.extent.height = STATUS_HEIGHT; + SetContextClipRect (&r); + + if ((SpaceContext = CaptureContext ( + CreateContext () + )) == 0) + return (FALSE); + + if ((OffScreenContext = CaptureContext ( + CreateContext () + )) == 0) + return (FALSE); + + if (!InitQueue (&disp_q, 100, sizeof (ELEMENT))) + return (FALSE); + + return (TRUE); +} + +BOOLEAN +InitKernel (void) +{ + COUNT counter; + + for (counter = 0; counter < NUM_PLAYERS; ++counter) + { + InitQueue (&race_q[counter], MAX_SHIPS_PER_SIDE, sizeof (STARSHIP)); + } + + if ((StarConFont = CaptureFont ( + LoadGraphic (STARCON_FONT) + )) == 0) + return (FALSE); + + if ((TinyFont = CaptureFont ( + LoadGraphic (TINY_FONT) + )) == 0) + return (FALSE); + if ((ActivityFrame = CaptureDrawable ( + LoadGraphic (ACTIVITY_ANIM) + )) == 0) + return (FALSE); + + if ((status = CaptureDrawable ( + LoadGraphic (STATUS_MASK_PMAP_ANIM) + )) == 0) + return (FALSE); + + if ((GameStrings = CaptureStringTable ( + LoadStringTableInstance (STARCON_GAME_STRINGS) + )) == 0) + return (FALSE); + + if ((MicroFont = CaptureFont ( + LoadGraphic (MICRO_FONT) + )) == 0) + return (FALSE); + + if ((MenuSounds = CaptureSound ( + LoadSound (MENU_SOUNDS) + )) == 0) + return (FALSE); + + InitSpace (); + + return (TRUE); +} + +BOOLEAN +InitGameKernel (void) +{ + if (ActivityFrame == 0) + { + InitKernel (); + InitContexts (); + } + return(TRUE); +} + +void +SetPlayerInput (void) +{ + COUNT which_player; + + for (which_player = 0; which_player < NUM_PLAYERS; ++which_player) + { + if (!(PlayerControl[which_player] & HUMAN_CONTROL)) + PlayerInput[which_player] = ComputerInput; + else if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) + { + if (which_player == 0) + PlayerInput[which_player] = NormalInput; + else + { + PlayerInput[which_player] = ComputerInput; + PlayerControl[which_player] = COMPUTER_CONTROL | AWESOME_RATING; + } + } + else + PlayerInput[which_player] = CombinedInput[which_player]; + } +} + diff --git a/sc2/src/sc2code/ship.c b/sc2/src/sc2code/ship.c new file mode 100644 index 000000000..dda4871bd --- /dev/null +++ b/sc2/src/sc2code/ship.c @@ -0,0 +1,504 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +animation_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +UWORD +inertial_thrust (ELEMENTPTR ElementPtr) +{ + register COUNT CurrentAngle, TravelAngle; + COUNT max_thrust, thrust_increment; + register VELOCITYPTR VelocityPtr; + STARSHIPPTR StarShipPtr; + + VelocityPtr = &ElementPtr->velocity; + + GetElementStarShip (ElementPtr, &StarShipPtr); + CurrentAngle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + thrust_increment = StarShipPtr->RaceDescPtr->characteristics.thrust_increment; + max_thrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; + if (thrust_increment == max_thrust) + { + SetVelocityVector (VelocityPtr, + max_thrust, StarShipPtr->ShipFacing); + return (SHIP_AT_MAX_SPEED); + } + else if ((TravelAngle = + GetVelocityTravelAngle (VelocityPtr)) == CurrentAngle + && (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + && !(StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL)) + return (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)); + else + { + register SIZE delta_x, delta_y; + SIZE cur_delta_x, cur_delta_y; + DWORD desired_speed, max_speed; + + thrust_increment = WORLD_TO_VELOCITY (thrust_increment); + GetCurrentVelocityComponents (VelocityPtr, &cur_delta_x, &cur_delta_y); + delta_x = cur_delta_x + + COSINE (CurrentAngle, thrust_increment); + delta_y = cur_delta_y + + SINE (CurrentAngle, thrust_increment); + desired_speed = (DWORD)((long)delta_x * delta_x) + + (DWORD)((long)delta_y * delta_y); + max_speed = (DWORD)WORLD_TO_VELOCITY (max_thrust) + * WORLD_TO_VELOCITY (max_thrust); + if (desired_speed <= max_speed) + SetVelocityComponents (VelocityPtr, delta_x, delta_y); + else + { +#define MAX_ALLOWED_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (18)) + DWORD current_speed; + + if (((StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL) + && desired_speed <= + (DWORD)MAX_ALLOWED_SPEED * (DWORD)MAX_ALLOWED_SPEED) + || (current_speed = + (DWORD)((long)cur_delta_x * (long)cur_delta_x) + + (DWORD)((long)cur_delta_y * (long)cur_delta_y)) > desired_speed) + { + SetVelocityComponents (VelocityPtr, delta_x, delta_y); + return (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + } + else if (TravelAngle == CurrentAngle) + { + if (current_speed <= max_speed) + SetVelocityVector (VelocityPtr, + max_thrust, StarShipPtr->ShipFacing); + return (SHIP_AT_MAX_SPEED); + } + else + { + VELOCITY_DESC v; + + v = *VelocityPtr; + + DeltaVelocityComponents (&v, + COSINE (CurrentAngle, thrust_increment >> 1) + - COSINE (TravelAngle, thrust_increment), + SINE (CurrentAngle, thrust_increment >> 1) + - SINE (TravelAngle, thrust_increment)); + GetCurrentVelocityComponents (&v, &cur_delta_x, &cur_delta_y); + desired_speed = (long)cur_delta_x * (long)cur_delta_x + + (long)cur_delta_y * (long)cur_delta_y; + if (desired_speed > max_speed) + { + if (desired_speed < current_speed) + *VelocityPtr = v; + return (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + } + + *VelocityPtr = v; + } + } + + return (0); + } +} + +void +ship_preprocess (register PELEMENT ElementPtr) +{ + register ELEMENT_FLAGS cur_status_flags; + STARSHIPPTR StarShipPtr; + RACE_DESCPTR RDPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + RDPtr = StarShipPtr->RaceDescPtr; + + cur_status_flags = + StarShipPtr->cur_status_flags + & ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + if (!(ElementPtr->state_flags & APPEARING)) + cur_status_flags |= StarShipPtr->ship_input_state + & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + else + { + ElementPtr->crew_level = + (BYTE)RDPtr->ship_info.crew_level; + + if ((ElementPtr->state_flags & BAD_GUY) + && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + STAMP s; + CONTEXT OldContext; + + OldContext = SetContext (StatusContext); + s.origin.x = s.origin.y = 0; + s.frame = RDPtr->ship_data.captain_control.background; + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + RDPtr->ship_data.captain_control.background = 0; + SetContext (OldContext); + } + else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) + { + InitShipStatus (StarShipPtr, NULL_PTR); + DrawCaptainsWindow (StarShipPtr); + if (RDPtr->preprocess_func) + (*RDPtr->preprocess_func) (ElementPtr); + + if (ElementPtr->hTarget == 0) + { + extern void ship_transition (PELEMENT ElementPtr); + + ship_transition (ElementPtr); + } + else + { + extern BOOLEAN OpponentAlive (STARSHIPPTR + TestStarShipPtr); + + ElementPtr->hTarget = 0; + if (!PLRPlaying ((MUSIC_REF)~0) && OpponentAlive (StarShipPtr)) + BattleSong (TRUE); + } + return; + } + else + { + ElementPtr->current.location.x = LOG_SPACE_WIDTH >> 1; + ElementPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; + ElementPtr->next.location = ElementPtr->current.location; + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + + ClearSemaphore (&GraphicsSem); + ResumeGameClock (); + SetGameClockRate (HYPERSPACE_CLOCK_RATE); + SetSemaphore (&GraphicsSem); + + if (hyper_transition (ElementPtr)) + return; + } + } + StarShipPtr->cur_status_flags = cur_status_flags; + + if (StarShipPtr->energy_counter) + --StarShipPtr->energy_counter; + else if (RDPtr->ship_info.energy_level < (BYTE)RDPtr->ship_info.max_energy + || (SBYTE)RDPtr->characteristics.energy_regeneration < 0) + DeltaEnergy ((ELEMENTPTR)ElementPtr, + (SBYTE)RDPtr->characteristics.energy_regeneration); + + if (RDPtr->preprocess_func) + { + (*RDPtr->preprocess_func) (ElementPtr); + cur_status_flags = StarShipPtr->cur_status_flags; + } + + if (ElementPtr->turn_wait) + --ElementPtr->turn_wait; + else if (cur_status_flags & (LEFT | RIGHT)) + { + if (cur_status_flags & LEFT) + StarShipPtr->ShipFacing = + NORMALIZE_FACING (StarShipPtr->ShipFacing - 1); + else + StarShipPtr->ShipFacing = + NORMALIZE_FACING (StarShipPtr->ShipFacing + 1); + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + StarShipPtr->ShipFacing); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = RDPtr->characteristics.turn_wait; + } + + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + else if (cur_status_flags & THRUST) + { + UWORD thrust_status; + + thrust_status = inertial_thrust ((ELEMENTPTR)ElementPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED + | SHIP_BEYOND_MAX_SPEED + | SHIP_IN_GRAVITY_WELL); + StarShipPtr->cur_status_flags |= thrust_status; + + ElementPtr->thrust_wait = RDPtr->characteristics.thrust_wait; + + if (!OBJECT_CLOAKED (ElementPtr) + && LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) + { + extern void spawn_ion_trail + (PELEMENT + ElementPtr); + + spawn_ion_trail (ElementPtr); + } + } + + if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) + PreProcessStatus (ElementPtr); +} + +void +ship_postprocess (register + PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + RACE_DESCPTR RDPtr; + + if (ElementPtr->crew_level == 0) + return; + + GetElementStarShip (ElementPtr, &StarShipPtr); + RDPtr = StarShipPtr->RaceDescPtr; + + if (StarShipPtr->weapon_counter) + --StarShipPtr->weapon_counter; + else if ((StarShipPtr->cur_status_flags + & WEAPON) && DeltaEnergy ((ELEMENTPTR)ElementPtr, + -RDPtr->characteristics.weapon_energy_cost)) + { + COUNT num_weapons; + HELEMENT Weapon[6]; + + num_weapons = (*RDPtr->init_weapon_func) (ElementPtr, Weapon); + + if (num_weapons) + { + HELEMENT *WeaponPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + WeaponPtr = &Weapon[0]; + do + { + HELEMENT w; + + w = *WeaponPtr++; + if (w) + { + ELEMENTPTR EPtr; + + EPtr = LockElement (w, &EPtr); + SetElementStarShip (EPtr, StarShipPtr); + UnlockElement (w); + + PutElement (w); + } + } while (--num_weapons); + ProcessSound (RDPtr->ship_data.ship_sounds); + } + + StarShipPtr->weapon_counter = + RDPtr->characteristics.weapon_wait; + } + + if (StarShipPtr->special_counter) + --StarShipPtr->special_counter; + + if (RDPtr->postprocess_func) + (*RDPtr->postprocess_func) (ElementPtr); + + if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) + PostProcessStatus (ElementPtr); +} + +void +collision (PELEMENT + ElementPtr0, PPOINT + pPt0, PELEMENT + ElementPtr1, PPOINT + pPt1) +{ + if (!(ElementPtr1->state_flags & FINITE_LIFE)) + { + ElementPtr0->state_flags |= COLLISION; + if (GRAVITY_MASS (ElementPtr1->mass_points)) + { + SIZE damage; + + if ((damage = ElementPtr0->hit_points >> 2) == 0) + damage = 1; + do_damage ((ELEMENTPTR)ElementPtr0, damage); + + damage = TARGET_DAMAGED_FOR_1_PT + (damage >> 1); + if (damage > TARGET_DAMAGED_FOR_6_PLUS_PT) + damage = TARGET_DAMAGED_FOR_6_PLUS_PT; + ProcessSound (SetAbsSoundIndex (GameSounds, damage)); + } + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static BOOLEAN +spawn_ship (STARSHIPPTR + StarShipPtr) +{ + HELEMENT hShip; + RACE_DESCPTR RDPtr; + + if (!load_ship (StarShipPtr, TRUE)) + return (FALSE); + + RDPtr = StarShipPtr->RaceDescPtr; + RDPtr->ship_info.var2 = (BYTE)StarShipPtr->ShipFacing; + + StarShipPtr->ship_input_state = 0; + StarShipPtr->cur_status_flags = + StarShipPtr->old_status_flags = 0; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER + || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + if ((RDPtr->ship_info.crew_level = StarShipPtr->special_counter) > + RDPtr->ship_info.max_crew) + RDPtr->ship_info.crew_level = RDPtr->ship_info.max_crew; + } + + StarShipPtr->energy_counter = + StarShipPtr->weapon_counter = + StarShipPtr->special_counter = 0; + + if ((hShip = StarShipPtr->hShip) == 0 + && (hShip = AllocElement ()) != 0) + InsertElement (hShip, GetHeadElement ()); + + if ((StarShipPtr->hShip = hShip) != 0) + { + ELEMENTPTR ShipElementPtr; + + LockElement (hShip, &ShipElementPtr); + + ShipElementPtr->crew_level = 0; + ShipElementPtr->mass_points = RDPtr->characteristics.ship_mass; + ShipElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR + | (RDPtr->ship_info.ship_flags & (GOOD_GUY | BAD_GUY)); + ShipElementPtr->turn_wait = ShipElementPtr->thrust_wait = 0; + ShipElementPtr->life_span = NORMAL_LIFE; + + SetPrimType (&DisplayArray[ShipElementPtr->PrimIndex], STAMP_PRIM); + ShipElementPtr->current.image.farray = RDPtr->ship_data.ship; + + if ((ShipElementPtr->state_flags & BAD_GUY) + && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) + { + StarShipPtr->ShipFacing = 0; + ShipElementPtr->current.image.frame = + SetAbsFrameIndex (RDPtr->ship_data.ship[0], + StarShipPtr->ShipFacing); + ShipElementPtr->current.location.x = LOG_SPACE_WIDTH >> 1; + ShipElementPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; + ++ShipElementPtr->life_span; + } + else + { + StarShipPtr->ShipFacing = NORMALIZE_FACING (Random ()); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + COUNT facing; + + if ((facing = LOWORD (GLOBAL (ShipStamp.frame))) > 0) + --facing; + + GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( + StarShipPtr->ShipFacing + 1, 0 + ); + StarShipPtr->ShipFacing = facing; + } + ShipElementPtr->current.image.frame = + SetAbsFrameIndex (RDPtr->ship_data.ship[0], + StarShipPtr->ShipFacing); + do + { + ShipElementPtr->current.location.x = + WRAP_X (DISPLAY_ALIGN_X (Random ())); + ShipElementPtr->current.location.y = + WRAP_Y (DISPLAY_ALIGN_Y (Random ())); + } while (CalculateGravity (ShipElementPtr) + || TimeSpaceMatterConflict (ShipElementPtr)); + } + + ShipElementPtr->preprocess_func = ship_preprocess; + ShipElementPtr->postprocess_func = ship_postprocess; + ShipElementPtr->death_func = ship_death; + ShipElementPtr->collision_func = collision; + ZeroVelocityComponents (&ShipElementPtr->velocity); + + SetElementStarShip (ShipElementPtr, StarShipPtr); + ShipElementPtr->hTarget = 0; + + UnlockElement (hShip); + } + + return (hShip != 0); +} + +BOOLEAN +GetNextStarShip (STARSHIPPTR + LastStarShipPtr, + COUNT which_side) +{ + HSTARSHIP hBattleShip; + + cur_player = which_side; + CyborgDescPtr = 0; + + + hBattleShip = GetEncounterStarShip (LastStarShipPtr, which_side); + if (hBattleShip) + { + STARSHIPPTR StarShipPtr; + + StarShipPtr = LockStarShip (&race_q[which_side], hBattleShip); + if (LastStarShipPtr) + { + if (StarShipPtr == LastStarShipPtr) + LastStarShipPtr = 0; + else + StarShipPtr->hShip = LastStarShipPtr->hShip; + } + + if (!spawn_ship (StarShipPtr)) + { + UnlockStarShip (&race_q[which_side], hBattleShip); + return (FALSE); + } + UnlockStarShip (&race_q[which_side], hBattleShip); + } + + if (LastStarShipPtr) + LastStarShipPtr->hShip = 0; + + return (hBattleShip != 0); +} + diff --git a/sc2/src/sc2code/ships/Makefile.am b/sc2/src/sc2code/ships/Makefile.am new file mode 100644 index 000000000..961405012 --- /dev/null +++ b/sc2/src/sc2code/ships/Makefile.am @@ -0,0 +1,31 @@ + +# Automake template file. +# Written by Mudry , protected by GNU GPL. +# CVS $ Id: $ + +RACES = androsyn arilou blackurq chenjesu chmmr druuge human ilwrath \ + lastbat melnorme mmrnmhrm mycon orz pkunk probe shofixti \ + sis_ship slylandr spathi supox syreen thradd umgah urquan utwig \ + vux yehat zoqfot + +EXTRA_DIRS = $(RACES) + +INCLUDES = @SDL_CFLAGS@ @SMPEG_CFLAGS@ \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/sc2code \ + -I$(top_srcdir)/src/sc2code/libs + +noinst_LTLIBRARIES = libships.la +libships_la_LIBADD = $(patsubst %.c, %.lo, $(wildcard */*.c)) +libships_la_SOURCES = dummy.c + +%.lo: %.c + $(COMPILE) -c $< -o $@ + +clean: clean-am + rm -f */*.{o,lo} + +distclean: distclean-am + rm -f */*.{o,lo} + + diff --git a/sc2/src/sc2code/ships/androsyn/androsyn.c b/sc2/src/sc2code/ships/androsyn/androsyn.c new file mode 100644 index 000000000..614475643 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/androsyn.c @@ -0,0 +1,474 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/androsyn/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 24 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 3 +#define SPECIAL_ENERGY_COST 2 +#define ENERGY_WAIT 8 +#define MAX_THRUST 24 +#define THRUST_INCREMENT 3 +#define TURN_WAIT 4 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 6 + +static RACE_DESC androsynth_desc = +{ + { + FIRES_FORE | SEEKING_WEAPON, + 15, /* Super Melee cost */ + ~0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, + }, + (STRING)ANDROSYNTH_RACE_STRINGS, + (FRAME)ANDROSYNTH_ICON_MASK_PMAP_ANIM, + (FRAME)ANDROSYNTH_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)ANDROSYNTH_BIG_MASK_PMAP_ANIM, + (FRAME)ANDROSYNTH_MED_MASK_PMAP_ANIM, + (FRAME)ANDROSYNTH_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)BUBBLE_BIG_MASK_PMAP_ANIM, + (FRAME)BUBBLE_MED_MASK_PMAP_ANIM, + (FRAME)BUBBLE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)BLAZER_BIG_MASK_PMAP_ANIM, + (FRAME)BLAZER_MED_MASK_PMAP_ANIM, + (FRAME)BLAZER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)ANDROSYNTH_CAPT_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)ANDROSYNTH_VICTORY_SONG, + (SOUND)ANDROSYNTH_SHIP_SOUNDS, + }, + { + 0, + LONG_RANGE_WEAPON >> 2, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define BLAZER_DAMAGE 3 +#define BLAZER_MASS 1 + +static void +blazer_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ +#define BLAZER_OFFSET 10 + BYTE old_offs; + SIZE old_crew_level; + COUNT old_life; + + old_crew_level = ElementPtr0->crew_level; + old_life = ElementPtr0->life_span; + old_offs = ElementPtr0->blast_offset; + ElementPtr0->blast_offset = BLAZER_OFFSET; + ElementPtr0->mass_points = BLAZER_DAMAGE; + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->mass_points = BLAZER_MASS; + ElementPtr0->blast_offset = old_offs; + ElementPtr0->life_span = old_life; + ElementPtr0->crew_level = old_crew_level; + + ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID); + collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +#define MISSILE_SPEED DISPLAY_TO_WORLD (8) + +static void +bubble_preprocess (PELEMENT ElementPtr) +{ + BYTE thrust_wait, turn_wait; + + thrust_wait = HINIBBLE (ElementPtr->turn_wait); + turn_wait = LONIBBLE (ElementPtr->turn_wait); + if (thrust_wait > 0) + --thrust_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + thrust_wait = (BYTE)((COUNT)Random () & 3); + } + + if (turn_wait > 0) + --turn_wait; + else + { + COUNT facing; + SIZE delta_facing; + + facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + )); + if ((delta_facing = TrackShip (ElementPtr, &facing)) == -1) + facing = (COUNT)Random (); + else if (delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE)) + facing += (COUNT)Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); + else + facing -= (COUNT)Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); + SetVelocityVector (&ElementPtr->velocity, + MISSILE_SPEED, facing); + +#define TRACK_WAIT 2 + turn_wait = TRACK_WAIT; + } + + ElementPtr->turn_wait = MAKE_BYTE (turn_wait, thrust_wait); +} + +#define MISSILE_DAMAGE 2 +#define MISSILE_LIFE 200 + +static COUNT +initialize_bubble (PELEMENT ShipPtr, HELEMENT BubbleArray[]) +{ +#define ANDROSYNTH_OFFSET 14 +#define MISSILE_OFFSET 3 +#define MISSILE_HITS 3 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = ANDROSYNTH_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = bubble_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + BubbleArray[0] = initialize_missile (&MissileBlock); + + if (BubbleArray[0]) + { + ELEMENTPTR BubblePtr; + + LockElement (BubbleArray[0], &BubblePtr); + BubblePtr->turn_wait = 0; + UnlockElement (BubbleArray[0]); + } + + return (1); +} + +static void +androsynth_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + /* in blazer form */ + if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) + { + ObjectsOfConcern[CREW_OBJECT_INDEX].ObjectPtr = 0; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) + { + if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) + && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + lpEvalDesc->MoveState = AVOID; + else + lpEvalDesc->ObjectPtr = 0; + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + } + else + { + STARSHIPPTR pEnemyStarShip; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { + GetElementStarShip (lpEvalDesc->ObjectPtr, &pEnemyStarShip); + if (lpEvalDesc->which_turn <= 16 + && (StarShipPtr->special_counter > 0 + || StarShipPtr->RaceDescPtr->ship_info.energy_level < MAX_ENERGY / 3 + || ((WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= CLOSE_RANGE_WEAPON + && lpEvalDesc->ObjectPtr->crew_level > BLAZER_DAMAGE) + || (lpEvalDesc->ObjectPtr->crew_level > (BYTE)(BLAZER_DAMAGE * 3) + && MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) > SLOW_SHIP)))) + lpEvalDesc->MoveState = ENTICE; + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->special_counter == 0) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 4) + || (lpEvalDesc->ObjectPtr + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= MAX_ENERGY / 3 + && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) >= + WEAPON_RANGE (&StarShipPtr->RaceDescPtr->cyborg_control) << 1 + || (lpEvalDesc->which_turn < 16 + && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) > CLOSE_RANGE_WEAPON + || lpEvalDesc->ObjectPtr->crew_level <= BLAZER_DAMAGE) + && (lpEvalDesc->ObjectPtr->crew_level <= (BYTE)(BLAZER_DAMAGE * 3) + || MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= + SLOW_SHIP))))) + StarShipPtr->ship_input_state |= SPECIAL; + } + + if (!(StarShipPtr->ship_input_state & SPECIAL) + && StarShipPtr->weapon_counter == 0 + && lpEvalDesc->ObjectPtr) + { + if (lpEvalDesc->which_turn <= 4) + StarShipPtr->ship_input_state |= WEAPON; + else if (lpEvalDesc->MoveState != PURSUE + && lpEvalDesc->which_turn <= 12) + { + COUNT travel_facing, direction_facing; + SIZE delta_x, delta_y, + ship_delta_x, ship_delta_y, + other_delta_x, other_delta_y; + + GetCurrentVelocityComponents (&ShipPtr->velocity, + &ship_delta_x, &ship_delta_y); + GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, + &other_delta_x, &other_delta_y); + delta_x = ship_delta_x - other_delta_x; + delta_y = ship_delta_y - other_delta_y; + travel_facing = ARCTAN (delta_x, delta_y); + + delta_x = + lpEvalDesc->ObjectPtr->next.location.x - + ShipPtr->next.location.x; + delta_y = + lpEvalDesc->ObjectPtr->next.location.y - + ShipPtr->next.location.y; + direction_facing = ARCTAN (delta_x, delta_y); + + if (NORMALIZE_ANGLE (travel_facing + - direction_facing + OCTANT) <= QUADRANT) + StarShipPtr->ship_input_state |= WEAPON; + } + } + } +} + +static void (*ship_collision_func[2]) (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1); + +#define BLAZER_TURN_WAIT 1 + +static void +androsynth_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + /* take care of blazer effect */ + if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) + { +#define BLAZER_DEGENERATION (-1) + if ((StarShipPtr->cur_status_flags & SPECIAL) + || StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) + { + StarShipPtr->RaceDescPtr->characteristics.special_wait = + StarShipPtr->RaceDescPtr->characteristics.turn_wait; + StarShipPtr->RaceDescPtr->characteristics.turn_wait = BLAZER_TURN_WAIT; + StarShipPtr->RaceDescPtr->characteristics.energy_regeneration = + (BYTE)BLAZER_DEGENERATION; + StarShipPtr->energy_counter = ENERGY_WAIT; + ElementPtr->mass_points = BLAZER_MASS; + ship_collision_func[WHICH_SIDE(ElementPtr->state_flags)] = ElementPtr->collision_func; + { + ElementPtr->collision_func = blazer_collision; + } + + if (StarShipPtr->cur_status_flags & SPECIAL) + { + ProcessSound (SetAbsSoundIndex ( + /* COMET_ON */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + ElementPtr->turn_wait = 0; + ElementPtr->thrust_wait = 0; + } + } + + if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) + /* if blazer wasn't able to change back into ship + * give it a little more juice to try to get out + * of its predicament. + */ + { + DeltaEnergy (ElementPtr, -BLAZER_DEGENERATION); + StarShipPtr->energy_counter = 1; + } + } +} + +static void +androsynth_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + ELEMENT_FLAGS cur_status_flags; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + cur_status_flags = StarShipPtr->cur_status_flags; + if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) + { + if (cur_status_flags & SPECIAL) + { + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST) + DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); /* so text will flash */ + else + { + cur_status_flags &= ~WEAPON; + + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + ElementPtr->next.image.frame = + SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], + ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + } + } + } + else + { + cur_status_flags &= ~(THRUST | WEAPON | SPECIAL); + + /* protection against vux */ + if (StarShipPtr->RaceDescPtr->characteristics.turn_wait > BLAZER_TURN_WAIT) + { + StarShipPtr->RaceDescPtr->characteristics.special_wait += + StarShipPtr->RaceDescPtr->characteristics.turn_wait + - BLAZER_TURN_WAIT; + StarShipPtr->RaceDescPtr->characteristics.turn_wait = BLAZER_TURN_WAIT; + } + + if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) + { + ZeroVelocityComponents (&ElementPtr->velocity); + cur_status_flags &= ~(LEFT | RIGHT + | SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + + StarShipPtr->RaceDescPtr->characteristics.turn_wait = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + StarShipPtr->RaceDescPtr->characteristics.energy_regeneration = ENERGY_REGENERATION; + ElementPtr->mass_points = SHIP_MASS; + ElementPtr->collision_func = ship_collision_func[WHICH_SIDE(ElementPtr->state_flags)]; + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.ship; + ElementPtr->next.image.frame = + SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], + ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + } + else + { + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + else + { +#define BLAZER_THRUST 60 + COUNT facing; + + facing = StarShipPtr->ShipFacing; + if (ElementPtr->turn_wait == 0 + && (cur_status_flags & (LEFT | RIGHT))) + { + if (cur_status_flags & LEFT) + --facing; + else + ++facing; + } + + SetVelocityVector (&ElementPtr->velocity, + BLAZER_THRUST, NORMALIZE_FACING (facing)); + cur_status_flags |= SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED; + } + } + } + StarShipPtr->cur_status_flags = cur_status_flags; +} + +RACE_DESCPTR +init_androsynth () +{ + RACE_DESCPTR RaceDescPtr; + + androsynth_desc.preprocess_func = androsynth_preprocess; + androsynth_desc.postprocess_func = androsynth_postprocess; + androsynth_desc.init_weapon_func = initialize_bubble; + androsynth_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) androsynth_intelligence; + + RaceDescPtr = &androsynth_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/androsyn/androsyn.res b/sc2/src/sc2code/ships/androsyn/androsyn.res new file mode 100644 index 000000000..fe1edcd6f --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/androsyn.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH androsyn + +PACKAGE ANDROSYNTH_CODE_PACKAGE androsyn.shp + CODE ANDROSYNTH_CODE androsyn.cod + GFXRES ANDROSYNTH_ICON_MASK_PMAP_ANIM andicons.ani + GFXRES ANDROSYNTH_MICON_MASK_PMAP_ANIM andmicon.ani + STRTAB ANDROSYNTH_RACE_STRINGS andtext.txt + +PACKAGE ANDROSYNTH_PACKAGE androsyn.shp + GFXRES ANDROSYNTH_BIG_MASK_PMAP_ANIM androsyn.big + GFXRES ANDROSYNTH_MED_MASK_PMAP_ANIM androsyn.med + GFXRES ANDROSYNTH_SML_MASK_PMAP_ANIM androsyn.sml + GFXRES BUBBLE_BIG_MASK_PMAP_ANIM bubble.big + GFXRES BUBBLE_MED_MASK_PMAP_ANIM bubble.med + GFXRES BUBBLE_SML_MASK_PMAP_ANIM bubble.sml + GFXRES BLAZER_BIG_MASK_PMAP_ANIM blazer.big + GFXRES BLAZER_MED_MASK_PMAP_ANIM blazer.med + GFXRES BLAZER_SML_MASK_PMAP_ANIM blazer.sml + + GFXRES ANDROSYNTH_CAPT_MASK_PMAP_ANIM andcap.ani + SNDRES ANDROSYNTH_SHIP_SOUNDS andsound.snd + + MUSICRES ANDROSYNTH_VICTORY_SONG andditty.mod + diff --git a/sc2/src/sc2code/ships/androsyn/icode.h b/sc2/src/sc2code/ships/androsyn/icode.h new file mode 100644 index 000000000..14bbe838f --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/icode.h @@ -0,0 +1,3 @@ +#define ANDROSYNTH_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/androsyn/igfxres.h b/sc2/src/sc2code/ships/androsyn/igfxres.h new file mode 100644 index 000000000..2cc57c826 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/igfxres.h @@ -0,0 +1,14 @@ +#define ANDROSYNTH_ICON_MASK_PMAP_ANIM 0x00200002L +#define ANDROSYNTH_MICON_MASK_PMAP_ANIM 0x00200102L +#define ANDROSYNTH_BIG_MASK_PMAP_ANIM 0x00400202L +#define ANDROSYNTH_MED_MASK_PMAP_ANIM 0x00400302L +#define ANDROSYNTH_SML_MASK_PMAP_ANIM 0x00400402L +#define BUBBLE_BIG_MASK_PMAP_ANIM 0x00400502L +#define BUBBLE_MED_MASK_PMAP_ANIM 0x00400602L +#define BUBBLE_SML_MASK_PMAP_ANIM 0x00400702L +#define BLAZER_BIG_MASK_PMAP_ANIM 0x00400802L +#define BLAZER_MED_MASK_PMAP_ANIM 0x00400902L +#define BLAZER_SML_MASK_PMAP_ANIM 0x00400a02L +#define ANDROSYNTH_CAPT_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/androsyn/imusicre.h b/sc2/src/sc2code/ships/androsyn/imusicre.h new file mode 100644 index 000000000..c3f523730 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/imusicre.h @@ -0,0 +1,3 @@ +#define ANDROSYNTH_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/androsyn/isndres.h b/sc2/src/sc2code/ships/androsyn/isndres.h new file mode 100644 index 000000000..adac3c906 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/isndres.h @@ -0,0 +1,3 @@ +#define ANDROSYNTH_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/androsyn/istrtab.h b/sc2/src/sc2code/ships/androsyn/istrtab.h new file mode 100644 index 000000000..616548000 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/istrtab.h @@ -0,0 +1,3 @@ +#define ANDROSYNTH_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/androsyn/resinst.h b/sc2/src/sc2code/ships/androsyn/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/androsyn/respkg.h b/sc2/src/sc2code/ships/androsyn/respkg.h new file mode 100644 index 000000000..5461dd039 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/respkg.h @@ -0,0 +1,6 @@ +enum +{ + ANDROSYNTH_CODE_PACKAGE = 1, + ANDROSYNTH_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/androsyn/restypes.h b/sc2/src/sc2code/ships/androsyn/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/androsyn/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/arilou/arilou.c b/sc2/src/sc2code/ships/arilou/arilou.c new file mode 100644 index 000000000..578bc6f08 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/arilou.c @@ -0,0 +1,290 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/arilou/resinst.h" +#include "starcon.h" + +#define MAX_CREW 6 +#define MAX_ENERGY 20 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 3 +#define ENERGY_WAIT 6 +#define MAX_THRUST /* DISPLAY_TO_WORLD (10) */ 40 +#define THRUST_INCREMENT MAX_THRUST +#define TURN_WAIT 0 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 1 +#define SPECIAL_WAIT 2 + +#define SHIP_MASS 1 +#define ARILOU_OFFSET 9 +#define LASER_RANGE DISPLAY_TO_WORLD (100 + ARILOU_OFFSET) + +static RACE_DESC arilou_desc = +{ + { + /* FIRES_FORE | */ IMMEDIATE_WEAPON, + 16, /* Super Melee cost */ + 250 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 438, 6372, + }, + (STRING)ARILOU_RACE_STRINGS, + (FRAME)ARILOU_ICON_MASK_PMAP_ANIM, + (FRAME)ARILOU_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)ARILOU_BIG_MASK_PMAP_ANIM, + (FRAME)ARILOU_MED_MASK_PMAP_ANIM, + (FRAME)ARILOU_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)WARP_BIG_MASK_PMAP_ANIM, + (FRAME)WARP_MED_MASK_PMAP_ANIM, + (FRAME)WARP_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)ARILOU_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)ARILOU_VICTORY_SONG, + (SOUND)ARILOU_SHIP_SOUNDS, + }, + { + 0, + LASER_RANGE >> 1, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_autoaim_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) +{ + COUNT orig_facing; + SIZE delta_facing; + STARSHIPPTR StarShipPtr; + LASER_BLOCK LaserBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + LaserBlock.face = orig_facing = StarShipPtr->ShipFacing; + if ((delta_facing = TrackShip (ShipPtr, &LaserBlock.face)) > 0) + LaserBlock.face = NORMALIZE_FACING (orig_facing + delta_facing); + ShipPtr->hTarget = 0; + + LaserBlock.cx = ShipPtr->next.location.x; + LaserBlock.cy = ShipPtr->next.location.y; + LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = ARILOU_OFFSET; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E); + LaserArray[0] = initialize_laser (&LaserBlock); + + return (1); +} + +static void +arilou_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, + COUNT ConcernCounter) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->ship_input_state |= THRUST; + + ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->special_counter == 0) + { + PEVALUATE_DESC lpEvalDesc; + + StarShipPtr->ship_input_state &= ~SPECIAL; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 6) + { + BOOLEAN IsTrackingWeapon; + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & SEEKING_WEAPON) && + lpEvalDesc->ObjectPtr->next.image.farray == + EnemyStarShipPtr->RaceDescPtr->ship_data.weapon) || + ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & SEEKING_SPECIAL) && + lpEvalDesc->ObjectPtr->next.image.farray == + EnemyStarShipPtr->RaceDescPtr->ship_data.special)) + IsTrackingWeapon = TRUE; + else + IsTrackingWeapon = FALSE; + + if (((lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ + || (IsTrackingWeapon && (lpEvalDesc->which_turn == 1 + || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT))) /* FIGHTERS!!! */ + || PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 3, 0)) + && !(Random () & 3)) + { + StarShipPtr->ship_input_state &= ~(LEFT | RIGHT | THRUST | WEAPON); + StarShipPtr->ship_input_state |= SPECIAL; + } + } + } + if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST << 1) + StarShipPtr->ship_input_state &= ~WEAPON; +} + +static void +arilou_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (!(ElementPtr->state_flags & NONSOLID)) + { + if (ElementPtr->thrust_wait == 0) + { + ZeroVelocityComponents (&ElementPtr->velocity); + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + } + + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { +#define HYPER_LIFE 5 + ZeroVelocityComponents (&ElementPtr->velocity); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | LEFT | RIGHT | THRUST | WEAPON); + + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; + ElementPtr->life_span = HYPER_LIFE; + + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + ElementPtr->next.image.frame = + StarShipPtr->RaceDescPtr->ship_data.special[0]; + + ProcessSound (SetAbsSoundIndex ( + /* HYPERJUMP */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + } + else if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) + { + COUNT life_span; + + StarShipPtr->cur_status_flags = + (StarShipPtr->cur_status_flags + & ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL)) + | (StarShipPtr->old_status_flags + & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL)); + ++StarShipPtr->weapon_counter; + ++StarShipPtr->special_counter; + ++StarShipPtr->energy_counter; + ++ElementPtr->turn_wait; + ++ElementPtr->thrust_wait; + + if ((life_span = ElementPtr->life_span) == NORMAL_LIFE) + { + ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); + ElementPtr->state_flags |= APPEARING; + ElementPtr->current.image.farray = + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.ship; + ElementPtr->current.image.frame = + ElementPtr->next.image.frame = + SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], + StarShipPtr->ShipFacing); + InitIntersectStartPoint (ElementPtr); + } + else + { + --life_span; + if (life_span != 2) + { + if (life_span < 2) + ElementPtr->next.image.frame = + DecFrameIndex (ElementPtr->next.image.frame); + else + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->next.image.frame); + } + else + { + ElementPtr->next.location.x = + WRAP_X (DISPLAY_ALIGN_X (Random ())); + ElementPtr->next.location.y = + WRAP_Y (DISPLAY_ALIGN_Y (Random ())); + } + } + + ElementPtr->state_flags |= CHANGING; + } +} + +RACE_DESCPTR +init_arilou (void) +{ + RACE_DESCPTR RaceDescPtr; + + arilou_desc.preprocess_func = arilou_preprocess; + arilou_desc.init_weapon_func = initialize_autoaim_laser; + arilou_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) arilou_intelligence; + + RaceDescPtr = &arilou_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/arilou/arilou.res b/sc2/src/sc2code/ships/arilou/arilou.res new file mode 100644 index 000000000..b1227718a --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/arilou.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH arilou + +PACKAGE ARILOU_CODE_PACKAGE arilou.shp + CODE ARILOU_CODE arilou.cod + GFXRES ARILOU_ICON_MASK_PMAP_ANIM ariicons.ani + GFXRES ARILOU_MICON_MASK_PMAP_ANIM arimicon.ani + STRTAB ARILOU_RACE_STRINGS aritext.txt + +PACKAGE ARILOU_PACKAGE arilou.shp + GFXRES ARILOU_BIG_MASK_PMAP_ANIM arilou.big + GFXRES ARILOU_MED_MASK_PMAP_ANIM arilou.med + GFXRES ARILOU_SML_MASK_PMAP_ANIM arilou.sml + GFXRES WARP_BIG_MASK_PMAP_ANIM warp.big + GFXRES WARP_MED_MASK_PMAP_ANIM warp.med + GFXRES WARP_SML_MASK_PMAP_ANIM warp.sml + + GFXRES ARILOU_CAPTAIN_MASK_PMAP_ANIM aricap.ani + SNDRES ARILOU_SHIP_SOUNDS arisound.snd + + MUSICRES ARILOU_VICTORY_SONG ariditty.mod + diff --git a/sc2/src/sc2code/ships/arilou/icode.h b/sc2/src/sc2code/ships/arilou/icode.h new file mode 100644 index 000000000..a2fccecf6 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/icode.h @@ -0,0 +1,3 @@ +#define ARILOU_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/arilou/igfxres.h b/sc2/src/sc2code/ships/arilou/igfxres.h new file mode 100644 index 000000000..32f1a3d7d --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/igfxres.h @@ -0,0 +1,11 @@ +#define ARILOU_ICON_MASK_PMAP_ANIM 0x00200002L +#define ARILOU_MICON_MASK_PMAP_ANIM 0x00200102L +#define ARILOU_BIG_MASK_PMAP_ANIM 0x00400202L +#define ARILOU_MED_MASK_PMAP_ANIM 0x00400302L +#define ARILOU_SML_MASK_PMAP_ANIM 0x00400402L +#define WARP_BIG_MASK_PMAP_ANIM 0x00400502L +#define WARP_MED_MASK_PMAP_ANIM 0x00400602L +#define WARP_SML_MASK_PMAP_ANIM 0x00400702L +#define ARILOU_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/arilou/imusicre.h b/sc2/src/sc2code/ships/arilou/imusicre.h new file mode 100644 index 000000000..a31696e2f --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/imusicre.h @@ -0,0 +1,3 @@ +#define ARILOU_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/arilou/isndres.h b/sc2/src/sc2code/ships/arilou/isndres.h new file mode 100644 index 000000000..1c6605287 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/isndres.h @@ -0,0 +1,3 @@ +#define ARILOU_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/arilou/istrtab.h b/sc2/src/sc2code/ships/arilou/istrtab.h new file mode 100644 index 000000000..95b92caf2 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/istrtab.h @@ -0,0 +1,3 @@ +#define ARILOU_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/arilou/resinst.h b/sc2/src/sc2code/ships/arilou/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/arilou/respkg.h b/sc2/src/sc2code/ships/arilou/respkg.h new file mode 100644 index 000000000..0015d086a --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/respkg.h @@ -0,0 +1,6 @@ +enum +{ + ARILOU_CODE_PACKAGE = 1, + ARILOU_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/arilou/restypes.h b/sc2/src/sc2code/ships/arilou/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/arilou/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/blackurq/blackurq.c b/sc2/src/sc2code/ships/blackurq/blackurq.c new file mode 100644 index 000000000..7df229319 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/blackurq.c @@ -0,0 +1,563 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/blackurq/resinst.h" +#include "starcon.h" + +#define MAX_CREW MAX_CREW_SIZE +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 6 +#define SPECIAL_ENERGY_COST (MAX_ENERGY_SIZE / 2) +#define ENERGY_WAIT 4 +#define MAX_THRUST 30 +#define THRUST_INCREMENT 6 +#define TURN_WAIT 4 +#define THRUST_WAIT 6 +#define WEAPON_WAIT 6 +#define SPECIAL_WAIT 9 + +#define SHIP_MASS 10 +#define MISSILE_SPEED 64 +#define MISSILE_LIFE 64 /* actually, it's as long as you + * hold the button down. + */ + +static RACE_DESC black_urquan_desc = +{ + { + FIRES_FORE, + 30, /* Super Melee cost */ + 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 6000, 6250, + }, + (STRING)KOHR_AH_RACE_STRINGS, + (FRAME)KOHR_AH_ICON_MASK_PMAP_ANIM, + (FRAME)KOHR_AH_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)KOHR_AH_BIG_MASK_PMAP_ANIM, + (FRAME)KOHR_AH_MED_MASK_PMAP_ANIM, + (FRAME)KOHR_AH_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)BUZZSAW_BIG_MASK_PMAP_ANIM, + (FRAME)BUZZSAW_MED_MASK_PMAP_ANIM, + (FRAME)BUZZSAW_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)GAS_BIG_MASK_PMAP_ANIM, + (FRAME)GAS_MED_MASK_PMAP_ANIM, + (FRAME)GAS_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)KOHR_AH_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)KOHR_AH_VICTORY_SONG, + (SOUND)KOHR_AH_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define SAW_RATE 0 +#define MAX_SAWS 8 + +static void +spin_preprocess (ElementPtr) +PELEMENT ElementPtr; +{ + ELEMENTPTR ShipPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipPtr); + if (ShipPtr->crew_level + && ++StarShipPtr->RaceDescPtr->characteristics.special_wait > MAX_SAWS) + { + ElementPtr->life_span = 1; + ElementPtr->state_flags |= DISAPPEARING; + } + else + { + ++ElementPtr->life_span; + if (ElementPtr->turn_wait) + --ElementPtr->turn_wait; + else + { +#define LAST_SPIN_INDEX 1 + if (GetFrameIndex ( + ElementPtr->current.image.frame + ) < LAST_SPIN_INDEX) + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + else + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, 0); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = SAW_RATE; + } + } + UnlockElement (StarShipPtr->hShip); +} + +#define TRACK_WAIT 4 + +static void +buzztrack_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + else + { + COUNT facing; + + if (ElementPtr->hTarget == 0 + && TrackShip (ElementPtr, &facing) < 0) + { + ZeroVelocityComponents (&ElementPtr->velocity); + } + else + { +#define ACTIVATE_RANGE SPACE_WIDTH + SIZE delta_x, delta_y; + ELEMENTPTR eptr; + + LockElement (ElementPtr->hTarget, &eptr); + delta_x = eptr->current.location.x + - ElementPtr->current.location.x; + delta_y = eptr->current.location.y + - ElementPtr->current.location.y; + UnlockElement (ElementPtr->hTarget); + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + delta_x = WORLD_TO_DISPLAY (delta_x); + delta_y = WORLD_TO_DISPLAY (delta_y); + if (delta_x >= ACTIVATE_RANGE + || delta_y >= ACTIVATE_RANGE + || (DWORD)((UWORD)delta_x * delta_x) + + (DWORD)((UWORD)delta_y * delta_y) >= + (DWORD)ACTIVATE_RANGE * ACTIVATE_RANGE) + { + ZeroVelocityComponents (&ElementPtr->velocity); + } + else + { + ElementPtr->thrust_wait = TRACK_WAIT; + SetVelocityVector (&ElementPtr->velocity, + DISPLAY_TO_WORLD (2), facing); + } + } + } + + spin_preprocess (ElementPtr); +} + +static void +decelerate_preprocess (PELEMENT ElementPtr) +{ + SIZE dx, dy; + + GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); + dx /= 2; + dy /= 2; + SetVelocityComponents (&ElementPtr->velocity, dx, dy); + if (dx == 0 && dy == 0) + { + ElementPtr->preprocess_func = buzztrack_preprocess; + } + + spin_preprocess (ElementPtr); +} + +static void +splinter_preprocess (PELEMENT ElementPtr) +{ + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; +} + +static void +buzzsaw_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + + if (ElementPtr0->state_flags & DISAPPEARING) + { + ElementPtr0->state_flags &= ~DISAPPEARING; + ElementPtr0->state_flags |= NONSOLID | CHANGING; + ElementPtr0->life_span = 5; + ElementPtr0->next.image.frame = + SetAbsFrameIndex (ElementPtr0->current.image.frame, 2); + + ElementPtr0->preprocess_func = splinter_preprocess; + } +} + +static void +buzzsaw_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (!(StarShipPtr->cur_status_flags & WEAPON)) + { + ElementPtr->life_span >>= 1; + ElementPtr->preprocess_func = decelerate_preprocess; + } + + spin_preprocess (ElementPtr); +} + +static void +buzzsaw_postprocess (PELEMENT ElementPtr) +{ + HELEMENT hElement; + + ElementPtr->postprocess_func = 0; + hElement = AllocElement (); + if (hElement) + { + COUNT PI; + ELEMENTPTR ListElementPtr; + STARSHIPPTR StarShipPtr; + + LockElement (hElement, &ListElementPtr); + PI = ListElementPtr->PrimIndex; + *ListElementPtr = *ElementPtr; + ListElementPtr->PrimIndex = PI; + (GLOBAL (DisplayArray))[PI] = + (GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; + ListElementPtr->current = ListElementPtr->next; + InitIntersectStartPoint (ListElementPtr); + InitIntersectEndPoint (ListElementPtr); + ListElementPtr->state_flags = (ListElementPtr->state_flags + & ~(PRE_PROCESS | CHANGING | APPEARING)) + | POST_PROCESS; + UnlockElement (hElement); + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ListElementPtr); + InsertElement (hElement, GetSuccElement (ListElementPtr)); + UnlockElement (StarShipPtr->hShip); + + ElementPtr->life_span = 0; + } +} + +static COUNT +initialize_buzzsaw (PELEMENT ShipPtr, HELEMENT SawArray[]) +{ +#define MISSILE_HITS 10 +#define MISSILE_DAMAGE 4 +#define MISSILE_OFFSET 9 +#define KOHR_AH_OFFSET 28 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = KOHR_AH_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = buzzsaw_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + SawArray[0] = initialize_missile (&MissileBlock); + + if (SawArray[0]) + { + ELEMENTPTR SawPtr; + + LockElement (SawArray[0], &SawPtr); + SawPtr->turn_wait = SAW_RATE; + SawPtr->thrust_wait = 0; + SawPtr->postprocess_func = buzzsaw_postprocess; + SawPtr->collision_func = buzzsaw_collision; + UnlockElement (SawArray[0]); + } + + return (1); +} + +static void +black_urquan_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr + && lpEvalDesc->MoveState == ENTICE + && (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) + && lpEvalDesc->which_turn <= 8) + lpEvalDesc->MoveState = PURSUE; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->ship_input_state &= ~SPECIAL; + + if (StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST + && lpEvalDesc->ObjectPtr + && lpEvalDesc->which_turn <= 8) + StarShipPtr->ship_input_state |= SPECIAL; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { +#define FRAGMENT_LIFE 10 +#define FRAGMENT_SPEED MISSILE_SPEED +#define FRAGMENT_RANGE (FRAGMENT_LIFE * FRAGMENT_SPEED) + HELEMENT h, hNext; + ELEMENTPTR BuzzSawPtr; + + h = (StarShipPtr->old_status_flags & WEAPON) ? + GetSuccElement (ShipPtr) : (HELEMENT)0; + for (; h; h = hNext) + { + LockElement (h, &BuzzSawPtr); + hNext = GetSuccElement (BuzzSawPtr); + if (!(BuzzSawPtr->state_flags & NONSOLID) + && BuzzSawPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.weapon + && BuzzSawPtr->life_span > MISSILE_LIFE * 3 / 4 + && (BuzzSawPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) + { + { + //COUNT which_turn; + + if (!PlotIntercept (BuzzSawPtr, + lpEvalDesc->ObjectPtr, BuzzSawPtr->life_span, + FRAGMENT_RANGE / 2)) + StarShipPtr->ship_input_state &= ~WEAPON; + else if (StarShipPtr->weapon_counter == 0) + StarShipPtr->ship_input_state |= WEAPON; + + UnlockElement (h); + break; + } + hNext = 0; + } + UnlockElement (h); + } + + if (h == 0) + { + if (StarShipPtr->old_status_flags & WEAPON) + StarShipPtr->ship_input_state &= ~WEAPON; + else if (StarShipPtr->weapon_counter == 0 + && ship_weapons (ShipPtr, lpEvalDesc->ObjectPtr, FRAGMENT_RANGE / 2)) + StarShipPtr->ship_input_state |= WEAPON; + + if (StarShipPtr->special_counter == 0 + && !(StarShipPtr->ship_input_state & WEAPON) + && lpEvalDesc->which_turn <= 8 + && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= + SPECIAL_ENERGY_COST) + StarShipPtr->ship_input_state |= SPECIAL; + } + } +} + +#define GAS_RATE 2 + +static void +gas_cloud_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = GAS_RATE; + } +} + +#define GAS_DAMAGE 3 + +static void +gas_cloud_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr1->state_flags & PLAYER_SHIP) + ElementPtr0->mass_points = GAS_DAMAGE; + else + ElementPtr0->mass_points = 50; + + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +static void +spawn_gas_cloud (ElementPtr) +PELEMENT ElementPtr; +{ +#define GAS_SPEED 16 +#define GAS_HITS 100 +#define GAS_OFFSET 2 +#define NUM_GAS_CLOUDS 16 + SIZE dx, dy; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ElementPtr, &StarShipPtr); + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + MissileBlock.index = 0; + MissileBlock.sender = + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = 20; + MissileBlock.speed = GAS_SPEED; + MissileBlock.hit_points = GAS_HITS; + MissileBlock.damage = GAS_DAMAGE; + MissileBlock.life = + GetFrameCount (MissileBlock.farray[0]) * (GAS_RATE + 1) - 1; + MissileBlock.preprocess_func = gas_cloud_preprocess; + MissileBlock.blast_offs = GAS_OFFSET; + + GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); + for (MissileBlock.face = 0; + MissileBlock.face < ANGLE_TO_FACING (FULL_CIRCLE); + MissileBlock.face += + (ANGLE_TO_FACING (FULL_CIRCLE) / NUM_GAS_CLOUDS)) + { + HELEMENT hGasCloud; + + hGasCloud = initialize_missile (&MissileBlock); + if (hGasCloud) + { + ELEMENTPTR GasCloudPtr; + + LockElement (hGasCloud, &GasCloudPtr); + SetElementStarShip (GasCloudPtr, StarShipPtr); + GasCloudPtr->hTarget = 0; + GasCloudPtr->turn_wait = GAS_RATE - 1; + GasCloudPtr->collision_func = gas_cloud_collision; + DeltaVelocityComponents (&GasCloudPtr->velocity, dx, dy); + UnlockElement (hGasCloud); + PutElement (hGasCloud); + } + } +} + +static void +black_urquan_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + spawn_gas_cloud (ElementPtr); + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + + StarShipPtr->special_counter = SPECIAL_WAIT; + } +} + +static void +black_urquan_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + /* no spinning disks */ + StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; + if (StarShipPtr->weapon_counter == 0 + && (StarShipPtr->cur_status_flags + & StarShipPtr->old_status_flags & WEAPON)) + ++StarShipPtr->weapon_counter; +} + +RACE_DESCPTR +init_black_urquan () +{ + RACE_DESCPTR RaceDescPtr; + + black_urquan_desc.preprocess_func = black_urquan_preprocess; + black_urquan_desc.postprocess_func = black_urquan_postprocess; + black_urquan_desc.init_weapon_func = initialize_buzzsaw; + black_urquan_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) black_urquan_intelligence; + + RaceDescPtr = &black_urquan_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/blackurq/blackurq.res b/sc2/src/sc2code/ships/blackurq/blackurq.res new file mode 100644 index 000000000..339e690b6 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/blackurq.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH blackurq + +PACKAGE KOHR_AH_CODE_PACKAGE blackurq.shp + CODE KOHR_AH_CODE blackurq.cod + GFXRES KOHR_AH_ICON_MASK_PMAP_ANIM blaicons.ani + GFXRES KOHR_AH_MICON_MASK_PMAP_ANIM blamicon.ani + STRTAB KOHR_AH_RACE_STRINGS blatext.txt + +PACKAGE KOHR_AH_PACKAGE blackurq.shp + GFXRES KOHR_AH_BIG_MASK_PMAP_ANIM blackurq.big + GFXRES KOHR_AH_MED_MASK_PMAP_ANIM blackurq.med + GFXRES KOHR_AH_SML_MASK_PMAP_ANIM blackurq.sml + GFXRES BUZZSAW_BIG_MASK_PMAP_ANIM buzbig.ani + GFXRES BUZZSAW_MED_MASK_PMAP_ANIM buzmed.ani + GFXRES BUZZSAW_SML_MASK_PMAP_ANIM buzsml.ani + GFXRES GAS_BIG_MASK_PMAP_ANIM gasbig.ani + GFXRES GAS_MED_MASK_PMAP_ANIM gasmed.ani + GFXRES GAS_SML_MASK_PMAP_ANIM gassml.ani + + GFXRES KOHR_AH_CAPTAIN_MASK_PMAP_ANIM blacap.ani + SNDRES KOHR_AH_SHIP_SOUNDS blasound.snd + + MUSICRES KOHR_AH_VICTORY_SONG bladitty.mod + diff --git a/sc2/src/sc2code/ships/blackurq/icode.h b/sc2/src/sc2code/ships/blackurq/icode.h new file mode 100644 index 000000000..1eb7bb93e --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/icode.h @@ -0,0 +1,3 @@ +#define KOHR_AH_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/blackurq/igfxres.h b/sc2/src/sc2code/ships/blackurq/igfxres.h new file mode 100644 index 000000000..fc8349ef8 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/igfxres.h @@ -0,0 +1,14 @@ +#define KOHR_AH_ICON_MASK_PMAP_ANIM 0x00200002L +#define KOHR_AH_MICON_MASK_PMAP_ANIM 0x00200102L +#define KOHR_AH_BIG_MASK_PMAP_ANIM 0x00400202L +#define KOHR_AH_MED_MASK_PMAP_ANIM 0x00400302L +#define KOHR_AH_SML_MASK_PMAP_ANIM 0x00400402L +#define BUZZSAW_BIG_MASK_PMAP_ANIM 0x00400502L +#define BUZZSAW_MED_MASK_PMAP_ANIM 0x00400602L +#define BUZZSAW_SML_MASK_PMAP_ANIM 0x00400702L +#define GAS_BIG_MASK_PMAP_ANIM 0x00400802L +#define GAS_MED_MASK_PMAP_ANIM 0x00400902L +#define GAS_SML_MASK_PMAP_ANIM 0x00400a02L +#define KOHR_AH_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/blackurq/imusicre.h b/sc2/src/sc2code/ships/blackurq/imusicre.h new file mode 100644 index 000000000..bc07a8e3e --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/imusicre.h @@ -0,0 +1,3 @@ +#define KOHR_AH_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/blackurq/isndres.h b/sc2/src/sc2code/ships/blackurq/isndres.h new file mode 100644 index 000000000..35bc02454 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/isndres.h @@ -0,0 +1,3 @@ +#define KOHR_AH_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/blackurq/istrtab.h b/sc2/src/sc2code/ships/blackurq/istrtab.h new file mode 100644 index 000000000..720f658df --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/istrtab.h @@ -0,0 +1,3 @@ +#define KOHR_AH_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/blackurq/resinst.h b/sc2/src/sc2code/ships/blackurq/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/blackurq/respkg.h b/sc2/src/sc2code/ships/blackurq/respkg.h new file mode 100644 index 000000000..d5ceb8ab7 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/respkg.h @@ -0,0 +1,6 @@ +enum +{ + KOHR_AH_CODE_PACKAGE = 1, + KOHR_AH_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/blackurq/restypes.h b/sc2/src/sc2code/ships/blackurq/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/blackurq/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/chenjesu/chenjesu.c b/sc2/src/sc2code/ships/chenjesu/chenjesu.c new file mode 100644 index 000000000..3ba76ec5f --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/chenjesu.c @@ -0,0 +1,583 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/chenjesu/resinst.h" +#include "starcon.h" + +#define MAX_CREW 36 +#define MAX_ENERGY 30 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 5 +#define SPECIAL_ENERGY_COST MAX_ENERGY +#define ENERGY_WAIT 4 +#define MAX_THRUST /* DISPLAY_TO_WORLD (7) */ 27 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 3 +#define TURN_WAIT 6 +#define THRUST_WAIT 4 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 0 + +#define MAX_DOGGIES 4 + +#define SHIP_MASS 10 +#define MISSILE_SPEED DISPLAY_TO_WORLD (16) +#define MISSILE_LIFE 90 /* actually, it's as long as you + * hold the button down. + */ + +static RACE_DESC chenjesu_desc = +{ + { + FIRES_FORE | SEEKING_SPECIAL | SEEKING_WEAPON, + 28, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)CHENJESU_RACE_STRINGS, + (FRAME)CHENJESU_ICON_MASK_PMAP_ANIM, + (FRAME)CHENJESU_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)CHENJESU_BIG_MASK_PMAP_ANIM, + (FRAME)CHENJESU_MED_MASK_PMAP_ANIM, + (FRAME)CHENJESU_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SPARK_BIG_MASK_PMAP_ANIM, + (FRAME)SPARK_MED_MASK_PMAP_ANIM, + (FRAME)SPARK_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)DOGGY_BIG_MASK_PMAP_ANIM, + (FRAME)DOGGY_MED_MASK_PMAP_ANIM, + (FRAME)DOGGY_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)CHENJESU_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)CHENJESU_VICTORY_SONG, + (SOUND)CHENJESU_SHIP_SOUNDS, + }, + { + 0, + LONG_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define FRAGMENT_LIFE 10 +#define FRAGMENT_SPEED MISSILE_SPEED +#define FRAGMENT_RANGE (FRAGMENT_LIFE * FRAGMENT_SPEED) + +static void +crystal_postprocess (PELEMENT ElementPtr) +{ +#define FRAGMENT_HITS 1 +#define FRAGMENT_DAMAGE 2 +#define FRAGMENT_OFFSET 2 +#define NUM_FRAGMENTS 8 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ElementPtr, &StarShipPtr); + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.index = 1; + MissileBlock.sender = + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = 0; + MissileBlock.speed = FRAGMENT_SPEED; + MissileBlock.hit_points = FRAGMENT_HITS; + MissileBlock.damage = FRAGMENT_DAMAGE; + MissileBlock.life = FRAGMENT_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = FRAGMENT_OFFSET; + + for (MissileBlock.face = 0; + MissileBlock.face < ANGLE_TO_FACING (FULL_CIRCLE); + MissileBlock.face += + (ANGLE_TO_FACING (FULL_CIRCLE) / NUM_FRAGMENTS)) + { + HELEMENT hFragment; + + hFragment = initialize_missile (&MissileBlock); + if (hFragment) + { + ELEMENTPTR FragPtr; + + LockElement (hFragment, &FragPtr); + SetElementStarShip (FragPtr, StarShipPtr); + UnlockElement (hFragment); + PutElement (hFragment); + } + } + + ProcessSound (SetAbsSoundIndex ( + /* CRYSTAL_FRAGMENTS */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); +} + +static void +crystal_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->cur_status_flags & WEAPON) + ++ElementPtr->life_span; /* keep it going while key pressed */ + else + { + ElementPtr->life_span = 1; + + ElementPtr->postprocess_func = crystal_postprocess; + } +} + +static void +animate (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +crystal_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + HELEMENT hBlastElement; + + hBlastElement = + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + if (hBlastElement) + { + ELEMENTPTR BlastElementPtr; + +#define NUM_SPARKLES 8 + LockElement (hBlastElement, &BlastElementPtr); + BlastElementPtr->current.location = ElementPtr1->current.location; + + BlastElementPtr->life_span = NUM_SPARKLES; + BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; + { + BlastElementPtr->preprocess_func = animate; + } + + BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], + 2); /* skip stones */ + + UnlockElement (hBlastElement); + } +} + +#define DOGGY_OFFSET 18 +#define DOGGY_SPEED DISPLAY_TO_WORLD (8) + +static void +doggy_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ++StarShipPtr->special_counter; + if (ElementPtr->thrust_wait > 0) /* could be non-zero after a collision */ + --ElementPtr->thrust_wait; + else + { + COUNT facing, orig_facing; + SIZE delta_facing; + + facing = orig_facing = + NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + )); + if ((delta_facing = TrackShip (ElementPtr, &facing)) < 0) + facing = NORMALIZE_FACING (Random ()); + else + { + ELEMENTPTR ShipPtr; + + LockElement (ElementPtr->hTarget, &ShipPtr); + facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + ARCTAN (ShipPtr->current.location.x - + ElementPtr->current.location.x, + ShipPtr->current.location.y - + ElementPtr->current.location.y) + )); + delta_facing = NORMALIZE_FACING (facing - + GetFrameIndex (ShipPtr->current.image.frame)); + UnlockElement (ElementPtr->hTarget); + + if (delta_facing > ANGLE_TO_FACING (HALF_CIRCLE - OCTANT) && + delta_facing < ANGLE_TO_FACING (HALF_CIRCLE + OCTANT)) + { + if (delta_facing >= ANGLE_TO_FACING (HALF_CIRCLE)) + facing -= ANGLE_TO_FACING (QUADRANT); + else + facing += ANGLE_TO_FACING (QUADRANT); + } + + facing = NORMALIZE_FACING (facing); + } + + if (facing != orig_facing) + SetVelocityVector (&ElementPtr->velocity, + DOGGY_SPEED, facing); + } +} + +static void +doggy_death (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ProcessSound (SetAbsSoundIndex ( + /* DOGGY_DIES */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3)); + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE; + ElementPtr->life_span = 6; + { + ElementPtr->preprocess_func = animate; + } + ElementPtr->death_func = NULL_PTR; + ElementPtr->collision_func = NULL_PTR; + ZeroVelocityComponents (&ElementPtr->velocity); + + ElementPtr->turn_wait = ElementPtr->next_turn = 0; +} + +static void +doggy_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ +#define ENERGY_DRAIN 10 + collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && (ElementPtr0->state_flags + & (GOOD_GUY | BAD_GUY)) != + (ElementPtr1->state_flags + & (GOOD_GUY | BAD_GUY))) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + ProcessSound (SetAbsSoundIndex ( + /* DOGGY_STEALS_ENERGY */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + GetElementStarShip (ElementPtr1, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < ENERGY_DRAIN) + DeltaEnergy (ElementPtr1, -StarShipPtr->RaceDescPtr->ship_info.energy_level); + else + DeltaEnergy (ElementPtr1, -ENERGY_DRAIN); + } + if (ElementPtr0->thrust_wait <= COLLISION_THRUST_WAIT) + ElementPtr0->thrust_wait += COLLISION_THRUST_WAIT << 1; +} + +#define CHENJESU_OFFSET 16 + +static void +spawn_doggy (ElementPtr) +PELEMENT ElementPtr; +{ + HELEMENT hDoggyElement; + + if ((hDoggyElement = AllocElement ()) != 0) + { + COUNT angle; + ELEMENTPTR DoggyElementPtr; + STARSHIPPTR StarShipPtr; + + ElementPtr->state_flags |= DEFY_PHYSICS; + + PutElement (hDoggyElement); + LockElement (hDoggyElement, &DoggyElementPtr); + DoggyElementPtr->hit_points = 3; + DoggyElementPtr->mass_points = 4; + DoggyElementPtr->thrust_wait = 0; + DoggyElementPtr->state_flags = APPEARING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + DoggyElementPtr->life_span = NORMAL_LIFE; + SetPrimType (&(GLOBAL (DisplayArray))[DoggyElementPtr->PrimIndex], + STAMP_PRIM); + { + DoggyElementPtr->preprocess_func = doggy_preprocess; + DoggyElementPtr->postprocess_func = NULL_PTR; + DoggyElementPtr->collision_func = doggy_collision; + DoggyElementPtr->death_func = doggy_death; + } + + GetElementStarShip (ElementPtr, &StarShipPtr); + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; + DoggyElementPtr->current.location.x = ElementPtr->next.location.x + + COSINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); + DoggyElementPtr->current.location.y = ElementPtr->next.location.y + + SINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); + DoggyElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; + DoggyElementPtr->current.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; + + SetVelocityVector (&DoggyElementPtr->velocity, + DOGGY_SPEED, NORMALIZE_FACING (ANGLE_TO_FACING (angle))); + + SetElementStarShip (DoggyElementPtr, StarShipPtr); + + UnlockElement (hDoggyElement); + } +} + +static void +chenjesu_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->ship_input_state &= ~SPECIAL; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if ((lpEvalDesc->which_turn <= 16 + && MANEUVERABILITY ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) >= MEDIUM_SHIP) + || (MANEUVERABILITY ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) <= SLOW_SHIP + && WEAPON_RANGE ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) >= LONG_RANGE_WEAPON * 3 / 4 + && (EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON))) + lpEvalDesc->MoveState = PURSUE; + } + + if (StarShipPtr->special_counter == 1 + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 8) + { + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (lpEvalDesc->ObjectPtr) + { + HELEMENT h, hNext; + ELEMENTPTR CrystalPtr; + + h = (StarShipPtr->old_status_flags & WEAPON) ? + GetTailElement () : (HELEMENT)0; + for (; h; h = hNext) + { + LockElement (h, &CrystalPtr); + hNext = GetPredElement (CrystalPtr); + if (!(CrystalPtr->state_flags & NONSOLID) + && CrystalPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.weapon + && CrystalPtr->preprocess_func + && CrystalPtr->life_span > 0 + && (CrystalPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) + { + if (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr) + { + COUNT which_turn; + + if ((which_turn = PlotIntercept (CrystalPtr, + ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr, + CrystalPtr->life_span, + FRAGMENT_RANGE / 2)) == 0 + || (which_turn == 1 + && PlotIntercept (CrystalPtr, + ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr, + CrystalPtr->life_span, 0) == 0)) + StarShipPtr->ship_input_state &= ~WEAPON; + else if (StarShipPtr->weapon_counter == 0) + { + StarShipPtr->ship_input_state |= WEAPON; + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + } + + UnlockElement (h); + break; + } + hNext = 0; + } + UnlockElement (h); + } + + if (h == 0) + { + if (StarShipPtr->old_status_flags & WEAPON) + { + StarShipPtr->ship_input_state &= ~WEAPON; + if (lpEvalDesc == &ObjectsOfConcern[ENEMY_WEAPON_INDEX]) + StarShipPtr->weapon_counter = 3; + } + else if (StarShipPtr->weapon_counter == 0 + && ship_weapons (ShipPtr, lpEvalDesc->ObjectPtr, FRAGMENT_RANGE / 2)) + StarShipPtr->ship_input_state |= WEAPON; + } + } + + if (StarShipPtr->special_counter < MAX_DOGGIES) + { + if (lpEvalDesc->ObjectPtr + && StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST + && !(StarShipPtr->ship_input_state & WEAPON)) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static COUNT +initialize_crystal (PELEMENT ShipPtr, HELEMENT CrystalArray[]) +{ +#define MISSILE_HITS 10 +#define MISSILE_DAMAGE 6 +#define MISSILE_OFFSET 0 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = CHENJESU_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = crystal_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + CrystalArray[0] = initialize_missile (&MissileBlock); + + if (CrystalArray[0]) + { + ELEMENTPTR CrystalPtr; + + LockElement (CrystalArray[0], &CrystalPtr); + CrystalPtr->collision_func = crystal_collision; + UnlockElement (CrystalArray[0]); + } + + return (1); +} + +static void +chenjesu_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter < MAX_DOGGIES + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + spawn_doggy (ElementPtr); + + ProcessSound (SetAbsSoundIndex ( + /* RELEASE_DOGGY */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 4)); + } + + StarShipPtr->special_counter = 1; + /* say there is one doggy, because ship_postprocess will + * decrement special_counter */ +} + +static void +chenjesu_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->special_counter > 1) /* only when STANDARD + * computer opponent + */ + StarShipPtr->special_counter += MAX_DOGGIES; + if (StarShipPtr->cur_status_flags + & StarShipPtr->old_status_flags + & WEAPON) + ++StarShipPtr->weapon_counter; +} + +RACE_DESCPTR +init_chenjesu () +{ + RACE_DESCPTR RaceDescPtr; + + chenjesu_desc.preprocess_func = chenjesu_preprocess; + chenjesu_desc.postprocess_func = chenjesu_postprocess; + chenjesu_desc.init_weapon_func = initialize_crystal; + chenjesu_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) chenjesu_intelligence; + + RaceDescPtr = &chenjesu_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/chenjesu/chenjesu.res b/sc2/src/sc2code/ships/chenjesu/chenjesu.res new file mode 100644 index 000000000..30b932604 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/chenjesu.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH chenjesu + +PACKAGE CHENJESU_CODE_PACKAGE chenjesu.shp + CODE CHENJESU_CODE chenjesu.cod + GFXRES CHENJESU_ICON_MASK_PMAP_ANIM cheicons.ani + GFXRES CHENJESU_MICON_MASK_PMAP_ANIM chemicon.ani + STRTAB CHENJESU_RACE_STRINGS chetext.txt + +PACKAGE CHENJESU_PACKAGE chenjesu.shp + GFXRES CHENJESU_BIG_MASK_PMAP_ANIM chenjesu.big + GFXRES CHENJESU_MED_MASK_PMAP_ANIM chenjesu.med + GFXRES CHENJESU_SML_MASK_PMAP_ANIM chenjesu.sml + GFXRES SPARK_BIG_MASK_PMAP_ANIM spark.big + GFXRES SPARK_MED_MASK_PMAP_ANIM spark.med + GFXRES SPARK_SML_MASK_PMAP_ANIM spark.sml + GFXRES DOGGY_BIG_MASK_PMAP_ANIM doggy.big + GFXRES DOGGY_MED_MASK_PMAP_ANIM doggy.med + GFXRES DOGGY_SML_MASK_PMAP_ANIM doggy.sml + + GFXRES CHENJESU_CAPTAIN_MASK_PMAP_ANIM checap.ani + SNDRES CHENJESU_SHIP_SOUNDS chesound.snd + + MUSICRES CHENJESU_VICTORY_SONG cheditty.mod + diff --git a/sc2/src/sc2code/ships/chenjesu/icode.h b/sc2/src/sc2code/ships/chenjesu/icode.h new file mode 100644 index 000000000..8b93a9a5d --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/icode.h @@ -0,0 +1,3 @@ +#define CHENJESU_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/chenjesu/igfxres.h b/sc2/src/sc2code/ships/chenjesu/igfxres.h new file mode 100644 index 000000000..d3ff837ee --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/igfxres.h @@ -0,0 +1,14 @@ +#define CHENJESU_ICON_MASK_PMAP_ANIM 0x00200002L +#define CHENJESU_MICON_MASK_PMAP_ANIM 0x00200102L +#define CHENJESU_BIG_MASK_PMAP_ANIM 0x00400202L +#define CHENJESU_MED_MASK_PMAP_ANIM 0x00400302L +#define CHENJESU_SML_MASK_PMAP_ANIM 0x00400402L +#define SPARK_BIG_MASK_PMAP_ANIM 0x00400502L +#define SPARK_MED_MASK_PMAP_ANIM 0x00400602L +#define SPARK_SML_MASK_PMAP_ANIM 0x00400702L +#define DOGGY_BIG_MASK_PMAP_ANIM 0x00400802L +#define DOGGY_MED_MASK_PMAP_ANIM 0x00400902L +#define DOGGY_SML_MASK_PMAP_ANIM 0x00400a02L +#define CHENJESU_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/chenjesu/imusicre.h b/sc2/src/sc2code/ships/chenjesu/imusicre.h new file mode 100644 index 000000000..b23f8a9e2 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/imusicre.h @@ -0,0 +1,3 @@ +#define CHENJESU_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/chenjesu/isndres.h b/sc2/src/sc2code/ships/chenjesu/isndres.h new file mode 100644 index 000000000..0e136a575 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/isndres.h @@ -0,0 +1,3 @@ +#define CHENJESU_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/chenjesu/istrtab.h b/sc2/src/sc2code/ships/chenjesu/istrtab.h new file mode 100644 index 000000000..e45a705ad --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/istrtab.h @@ -0,0 +1,3 @@ +#define CHENJESU_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/chenjesu/resinst.h b/sc2/src/sc2code/ships/chenjesu/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/chenjesu/respkg.h b/sc2/src/sc2code/ships/chenjesu/respkg.h new file mode 100644 index 000000000..d3c7fbcc4 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/respkg.h @@ -0,0 +1,6 @@ +enum +{ + CHENJESU_CODE_PACKAGE = 1, + CHENJESU_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/chenjesu/restypes.h b/sc2/src/sc2code/ships/chenjesu/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/chenjesu/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/chmmr/chmmr.c b/sc2/src/sc2code/ships/chmmr/chmmr.c new file mode 100644 index 000000000..5d44524c1 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/chmmr.c @@ -0,0 +1,760 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/chmmr/resinst.h" +#include "starcon.h" + +#define MAX_CREW MAX_CREW_SIZE +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 1 +#define ENERGY_WAIT 1 +#define MAX_THRUST 35 +#define THRUST_INCREMENT 7 +#define TURN_WAIT 3 +#define THRUST_WAIT 5 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 10 +#define CHMMR_OFFSET 18 +#define LASER_RANGE DISPLAY_TO_WORLD (150) + +static RACE_DESC chmmr_desc = +{ + { + FIRES_FORE | IMMEDIATE_WEAPON | SEEKING_SPECIAL | POINT_DEFENSE, + 30, /* Super Melee cost */ + 0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)CHMMR_RACE_STRINGS, + (FRAME)CHMMR_ICON_MASK_PMAP_ANIM, + (FRAME)CHMMR_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)CHMMR_BIG_MASK_PMAP_ANIM, + (FRAME)CHMMR_MED_MASK_PMAP_ANIM, + (FRAME)CHMMR_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)MUZZLE_BIG_MASK_PMAP_ANIM, + (FRAME)MUZZLE_MED_MASK_PMAP_ANIM, + (FRAME)MUZZLE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SATELLITE_BIG_MASK_PMAP_ANIM, + (FRAME)SATELLITE_MED_MASK_PMAP_ANIM, + (FRAME)SATELLITE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)CHMMR_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)CHMMR_VICTORY_SONG, + (SOUND)CHMMR_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +animate (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +laser_death (ELEMENTPTR ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->special_counter = ElementPtr->turn_wait; + + if (StarShipPtr->hShip) + { + SIZE dx, dy; + long dist; + HELEMENT hIonSpots; + ELEMENTPTR ShipPtr; + + LockElement (StarShipPtr->hShip, &ShipPtr); + + dx = ElementPtr->current.location.x + - ShipPtr->current.location.x; + dy = ElementPtr->current.location.y + - ShipPtr->current.location.y; + if (((BYTE)Random () & 0x07) + && (dist = (long)dx * dx + (long)dy * dy) >= + (long)DISPLAY_TO_WORLD (CHMMR_OFFSET + 10) + * DISPLAY_TO_WORLD (CHMMR_OFFSET + 10) + && (hIonSpots = AllocElement ())) + { + COUNT angle, magnitude; + ELEMENTPTR IonSpotsPtr; + + LockElement (hIonSpots, &IonSpotsPtr); + IonSpotsPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + IonSpotsPtr->turn_wait = IonSpotsPtr->next_turn = 0; + IonSpotsPtr->life_span = 9; + + angle = ARCTAN (dx, dy); + magnitude = ((COUNT)Random () + % ((square_root (dist) + 1) + - DISPLAY_TO_WORLD (CHMMR_OFFSET + 10))) + + DISPLAY_TO_WORLD (CHMMR_OFFSET + 10); + IonSpotsPtr->current.location.x = + ShipPtr->current.location.x + + COSINE (angle, magnitude); + IonSpotsPtr->current.location.y = + ShipPtr->current.location.y + + SINE (angle, magnitude); + IonSpotsPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.weapon; + IonSpotsPtr->current.image.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.weapon[0], + ANGLE_TO_FACING (FULL_CIRCLE) << 1 + ); + + IonSpotsPtr->preprocess_func = animate; + + SetElementStarShip (IonSpotsPtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + IonSpotsPtr->PrimIndex + ], STAMP_PRIM); + + UnlockElement (hIonSpots); + PutElement (hIonSpots); + } + + UnlockElement (StarShipPtr->hShip); + } +} + +static COUNT +initialize_megawatt_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) +{ +#define NUM_CYCLES 4 + RECT r; + STARSHIPPTR StarShipPtr; + LASER_BLOCK LaserBlock; + COLOR cycle_array[] = + { + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F), + }; + + GetElementStarShip (ShipPtr, &StarShipPtr); + LaserBlock.face = StarShipPtr->ShipFacing; + GetFrameRect (SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.weapon[0], LaserBlock.face + ), &r); + LaserBlock.cx = DISPLAY_ALIGN (ShipPtr->next.location.x) + + DISPLAY_TO_WORLD (r.corner.x); + LaserBlock.cy = DISPLAY_ALIGN (ShipPtr->next.location.y) + + DISPLAY_TO_WORLD (r.corner.y); + LaserBlock.ex = COSINE ( + FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE + ); + LaserBlock.ey = SINE ( + FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE + ); + LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = 0; + LaserBlock.color = cycle_array[StarShipPtr->special_counter]; + LaserArray[0] = initialize_laser (&LaserBlock); + + if (LaserArray[0]) + { + ELEMENTPTR LaserPtr; + + LockElement (LaserArray[0], &LaserPtr); + + LaserPtr->mass_points = 2; + LaserPtr->death_func = laser_death; + LaserPtr->turn_wait = (BYTE)((StarShipPtr->special_counter + 1) + % NUM_CYCLES); + + UnlockElement (LaserArray[0]); + } + + return (1); +} + +static void +chmmr_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->ship_input_state &= ~SPECIAL; + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr + && !(StarShipPtr->ship_input_state & WEAPON) + && lpEvalDesc->which_turn > 12 + && NORMALIZE_ANGLE ( + GetVelocityTravelAngle (&ShipPtr->velocity) + - (GetVelocityTravelAngle (&lpEvalDesc->ObjectPtr->velocity) + + HALF_CIRCLE) + QUADRANT + ) > HALF_CIRCLE) + StarShipPtr->ship_input_state |= SPECIAL; +} + +static void +chmmr_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + if (StarShipPtr->cur_status_flags & WEAPON) + { + HELEMENT hMuzzleFlash; + ELEMENTPTR MuzzleFlashPtr; + + LockElement (GetTailElement (), &MuzzleFlashPtr); + if ((PELEMENT)MuzzleFlashPtr != ElementPtr + && (MuzzleFlashPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + && (MuzzleFlashPtr->state_flags & APPEARING) + && GetPrimType (&(GLOBAL (DisplayArray))[ + MuzzleFlashPtr->PrimIndex + ]) == LINE_PRIM + && !(StarShipPtr->special_counter & 1) + && (hMuzzleFlash = AllocElement ())) + { + LockElement (hMuzzleFlash, &MuzzleFlashPtr); + MuzzleFlashPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + MuzzleFlashPtr->life_span = 1; + + MuzzleFlashPtr->current = ElementPtr->next; + MuzzleFlashPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.weapon; + MuzzleFlashPtr->current.image.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.weapon[0], + StarShipPtr->ShipFacing + ANGLE_TO_FACING (FULL_CIRCLE) + ); + + SetElementStarShip (MuzzleFlashPtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + MuzzleFlashPtr->PrimIndex + ], STAMP_PRIM); + + UnlockElement (hMuzzleFlash); + PutElement (hMuzzleFlash); + } + UnlockElement (GetTailElement ()); + } + + if ((StarShipPtr->cur_status_flags & SPECIAL) + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + COUNT facing; + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + + facing = 0; + if (TrackShip (ElementPtr, &facing) >= 0) + { +#define NUM_SHADOWS 5 + + ELEMENTPTR ShipElementPtr; + + LockElement (ElementPtr->hTarget, &ShipElementPtr); + if (!GRAVITY_MASS (ShipElementPtr->mass_points + 1)) + { + SIZE i, dx, dy; + COUNT angle, magnitude; + STARSHIPPTR EnemyStarShipPtr; + SIZE shadow_offs[] = + { + DISPLAY_TO_WORLD (8), + DISPLAY_TO_WORLD (8 + 9), + DISPLAY_TO_WORLD (8 + 9 + 11), + DISPLAY_TO_WORLD (8 + 9 + 11 + 14), + DISPLAY_TO_WORLD (8 + 9 + 11 + 14 + 18), + }; + COLOR color_tab[] = + { + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xE), 0x54), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0xC), 0x55), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x9), 0x56), + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x7), 0x57), + }; + + + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + dx = (ElementPtr->next.location.x + + COSINE (angle, (LASER_RANGE / 3) + + DISPLAY_TO_WORLD (CHMMR_OFFSET))) + - ShipElementPtr->next.location.x; + dy = (ElementPtr->next.location.y + + SINE (angle, (LASER_RANGE / 3) + + DISPLAY_TO_WORLD (CHMMR_OFFSET))) + - ShipElementPtr->next.location.y; + angle = ARCTAN (dx, dy); + magnitude = WORLD_TO_VELOCITY (12) / ShipElementPtr->mass_points; + DeltaVelocityComponents (&ShipElementPtr->velocity, + COSINE (angle, magnitude), SINE (angle, magnitude)); + + GetCurrentVelocityComponents (&ShipElementPtr->velocity, + &dx, &dy); + GetElementStarShip (ShipElementPtr, &EnemyStarShipPtr); + for (i = 0; i < NUM_SHADOWS; ++i) + { + HELEMENT hShadow; + + hShadow = AllocElement (); + if (hShadow) + { + ELEMENTPTR ShadowElementPtr; + + LockElement (hShadow, &ShadowElementPtr); + + ShadowElementPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | POST_PROCESS + | (ShipElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + ShadowElementPtr->life_span = 1; + + ShadowElementPtr->current = ShipElementPtr->next; + ShadowElementPtr->current.location.x += + COSINE (angle, shadow_offs[i]); + ShadowElementPtr->current.location.y += + SINE (angle, shadow_offs[i]); + ShadowElementPtr->next = ShadowElementPtr->current; + + SetElementStarShip (ShadowElementPtr, EnemyStarShipPtr); + SetVelocityComponents (&ShadowElementPtr->velocity, + dx, dy); + + SetPrimType (&(GLOBAL (DisplayArray))[ + ShadowElementPtr->PrimIndex + ], STAMPFILL_PRIM); + SetPrimColor (&(GLOBAL (DisplayArray))[ + ShadowElementPtr->PrimIndex + ], color_tab[i]); + + UnlockElement (hShadow); + InsertElement (hShadow, GetHeadElement ()); + } + } + } + UnlockElement (ElementPtr->hTarget); + } + } + + StarShipPtr->special_counter = 0; +} + +#define SATELLITE_OFFSET DISPLAY_TO_WORLD (64) + +static void +satellite_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + ++ElementPtr->life_span; + + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + (GetFrameIndex (ElementPtr->current.image.frame) + 1) & 7); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = (BYTE)NORMALIZE_ANGLE ( + ElementPtr->turn_wait + 1 + ); + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->hShip) + { + SIZE dx, dy; + ELEMENTPTR ShipPtr; + + StarShipPtr->RaceDescPtr->ship_info.ship_flags |= POINT_DEFENSE; + + LockElement (StarShipPtr->hShip, &ShipPtr); + + dx = (ShipPtr->next.location.x + + COSINE (ElementPtr->turn_wait, SATELLITE_OFFSET)) + - ElementPtr->current.location.x; + dy = (ShipPtr->next.location.y + + SINE (ElementPtr->turn_wait, SATELLITE_OFFSET)) + - ElementPtr->current.location.y; + dx = WRAP_DELTA_X (dx); + dy = WRAP_DELTA_Y (dy); + if ((long)dx * dx + (long)dy * dy + <= DISPLAY_TO_WORLD (20L) * DISPLAY_TO_WORLD (20L)) + SetVelocityComponents (&ElementPtr->velocity, + WORLD_TO_VELOCITY (dx), + WORLD_TO_VELOCITY (dy)); + else + { + COUNT angle; + + angle = ARCTAN (dx, dy); + SetVelocityComponents (&ElementPtr->velocity, + COSINE (angle, WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (20))), + SINE (angle, WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (20)))); + } + + UnlockElement (StarShipPtr->hShip); + } +} + +static void +spawn_point_defense (PELEMENT ElementPtr) +{ +#define DEFENSE_RANGE (UWORD)64 +#define DEFENSE_WAIT 2 + BYTE weakest; + UWORD best_dist; + STARSHIPPTR StarShipPtr; + HELEMENT hObject, hNextObject, hBestObject; + ELEMENTPTR ShipPtr, SattPtr, ObjectPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + hBestObject = 0; + best_dist = DEFENSE_RANGE + 1; + weakest = 255; + LockElement (StarShipPtr->hShip, &ShipPtr); + LockElement (ElementPtr->hTarget, &SattPtr); + for (hObject = GetPredElement (ElementPtr); + hObject; hObject = hNextObject) + { + LockElement (hObject, &ObjectPtr); + hNextObject = GetPredElement (ObjectPtr); + if (((ObjectPtr->state_flags | ShipPtr->state_flags) + & (GOOD_GUY | BAD_GUY)) == (GOOD_GUY | BAD_GUY) + && CollisionPossible (ObjectPtr, ShipPtr) + && !OBJECT_CLOAKED (ObjectPtr)) + { + SIZE delta_x, delta_y; + UWORD dist; + + delta_x = ObjectPtr->next.location.x + - SattPtr->next.location.x; + delta_y = ObjectPtr->next.location.y + - SattPtr->next.location.y; + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + delta_x = WORLD_TO_DISPLAY (delta_x); + delta_y = WORLD_TO_DISPLAY (delta_y); + if ((UWORD)delta_x <= DEFENSE_RANGE && + (UWORD)delta_y <= DEFENSE_RANGE && + (dist = + (UWORD)delta_x * (UWORD)delta_x + + (UWORD)delta_y * (UWORD)delta_y) <= + DEFENSE_RANGE * DEFENSE_RANGE + && (ObjectPtr->hit_points < weakest + || (ObjectPtr->hit_points == weakest + && dist < best_dist))) + { + hBestObject = hObject; + best_dist = dist; + weakest = ObjectPtr->hit_points; + } + } + UnlockElement (hObject); + } + + if (hBestObject) + { + LASER_BLOCK LaserBlock; + HELEMENT hPointDefense; + + LockElement (hBestObject, &ObjectPtr); + + LaserBlock.cx = SattPtr->next.location.x; + LaserBlock.cy = SattPtr->next.location.y; + LaserBlock.face = 0; + LaserBlock.ex = ObjectPtr->next.location.x + - SattPtr->next.location.x; + LaserBlock.ey = ObjectPtr->next.location.y + - SattPtr->next.location.y; + LaserBlock.sender = + (SattPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = 0; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x00, 0x1, 0x1F), 0x4D); + hPointDefense = initialize_laser (&LaserBlock); + if (hPointDefense) + { + ELEMENTPTR PDPtr; + + LockElement (hPointDefense, &PDPtr); + SetElementStarShip (PDPtr, StarShipPtr); + PDPtr->hTarget = 0; + UnlockElement (hPointDefense); + + PutElement (hPointDefense); + + SattPtr->thrust_wait = DEFENSE_WAIT; + } + + UnlockElement (hBestObject); + } + + UnlockElement (ElementPtr->hTarget); + UnlockElement (StarShipPtr->hShip); +} + +static void +satellite_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + if (ElementPtr->thrust_wait || ElementPtr->life_span == 0) + --ElementPtr->thrust_wait; + else + { + HELEMENT hDefense; + + hDefense = AllocElement (); + if (hDefense) + { + ELEMENTPTR DefensePtr; + + PutElement (hDefense); + + LockElement (hDefense, &DefensePtr); + DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + + { + ELEMENTPTR SuccPtr; + + LockElement (GetSuccElement (ElementPtr), &SuccPtr); + DefensePtr->hTarget = GetPredElement (SuccPtr); + UnlockElement (GetSuccElement (ElementPtr)); + + DefensePtr->death_func = spawn_point_defense; + } + + GetElementStarShip (ElementPtr, &StarShipPtr); + SetElementStarShip (DefensePtr, StarShipPtr); + + UnlockElement (hDefense); + } + } +} + +static void +satellite_collision (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1) +{ + (void) ElementPtr0; /* Satisfying compiler (unused parameter) */ + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) ElementPtr1; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +satellite_death (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~POINT_DEFENSE; + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; + ElementPtr->life_span = 4; + ElementPtr->turn_wait = 1; + ElementPtr->next_turn = 0; + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, 8); + + ElementPtr->preprocess_func = animate; + ElementPtr->death_func = NULL_PTR; + ElementPtr->postprocess_func = NULL_PTR; + ElementPtr->collision_func = NULL_PTR; +} + +static void +spawn_satellites (PELEMENT ElementPtr) +{ +#define NUM_SATELLITES 3 + COUNT i; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->hShip) + { + LockElement (StarShipPtr->hShip, &ElementPtr); + for (i = 0; i < NUM_SATELLITES; ++i) + { + HELEMENT hSatellite; + + hSatellite = AllocElement (); + if (hSatellite) + { + COUNT angle; + ELEMENTPTR SattPtr; + + LockElement (hSatellite, &SattPtr); + SattPtr->state_flags = + IGNORE_SIMILAR | APPEARING | FINITE_LIFE + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + SattPtr->life_span = NORMAL_LIFE + 1; + SattPtr->hit_points = 10; + SattPtr->mass_points = 10; + + angle = (i * FULL_CIRCLE + (NUM_SATELLITES >> 1)) + / NUM_SATELLITES; + SattPtr->turn_wait = (BYTE)angle; + SattPtr->current.location.x = ElementPtr->next.location.x + + COSINE (angle, SATELLITE_OFFSET); + SattPtr->current.location.y = ElementPtr->next.location.y + + SINE (angle, SATELLITE_OFFSET); + SattPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + SattPtr->current.image.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], + (COUNT)Random () & 0x07 + ); + + SattPtr->preprocess_func = satellite_preprocess; + SattPtr->postprocess_func = satellite_postprocess; + SattPtr->death_func = satellite_death; + SattPtr->collision_func = satellite_collision; + + SetElementStarShip (SattPtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + SattPtr->PrimIndex + ], STAMP_PRIM); + + UnlockElement (hSatellite); + PutElement (hSatellite); + } + } + UnlockElement (StarShipPtr->hShip); + } +} + +static void +chmmr_preprocess (PELEMENT ElementPtr) +{ + HELEMENT hSatellite; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + hSatellite = AllocElement (); + if (hSatellite) + { + ELEMENTPTR SattPtr; + STARSHIPPTR StarShipPtr; + + LockElement (hSatellite, &SattPtr); + SattPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + SattPtr->life_span = HYPERJUMP_LIFE + 1; + + SattPtr->death_func = spawn_satellites; + + GetElementStarShip (ElementPtr, &StarShipPtr); + SetElementStarShip (SattPtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + SattPtr->PrimIndex + ], NO_PRIM); + + UnlockElement (hSatellite); + PutElement (hSatellite); + } + + StarShipPtr->RaceDescPtr->preprocess_func = 0; +} + +RACE_DESCPTR +init_chmmr () +{ + RACE_DESCPTR RaceDescPtr; + + chmmr_desc.preprocess_func = chmmr_preprocess; + chmmr_desc.postprocess_func = chmmr_postprocess; + chmmr_desc.init_weapon_func = initialize_megawatt_laser; + chmmr_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) chmmr_intelligence; + + RaceDescPtr = &chmmr_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/chmmr/chmmr.res b/sc2/src/sc2code/ships/chmmr/chmmr.res new file mode 100644 index 000000000..315e4a29c --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/chmmr.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH chmmr + +PACKAGE CHMMR_CODE_PACKAGE chmmr.shp + CODE CHMMR_CODE chmmr.cod + GFXRES CHMMR_ICON_MASK_PMAP_ANIM chmicons.ani + GFXRES CHMMR_MICON_MASK_PMAP_ANIM chmmicon.ani + STRTAB CHMMR_RACE_STRINGS chmtext.txt + +PACKAGE CHMMR_PACKAGE chmmr.shp + GFXRES CHMMR_BIG_MASK_PMAP_ANIM chmmr.big + GFXRES CHMMR_MED_MASK_PMAP_ANIM chmmr.med + GFXRES CHMMR_SML_MASK_PMAP_ANIM chmmr.sml + GFXRES MUZZLE_BIG_MASK_PMAP_ANIM muzbig.ani + GFXRES MUZZLE_MED_MASK_PMAP_ANIM muzmed.ani + GFXRES MUZZLE_SML_MASK_PMAP_ANIM muzsml.ani + GFXRES SATELLITE_BIG_MASK_PMAP_ANIM satbig.ani + GFXRES SATELLITE_MED_MASK_PMAP_ANIM satmed.ani + GFXRES SATELLITE_SML_MASK_PMAP_ANIM satsml.ani + + GFXRES CHMMR_CAPTAIN_MASK_PMAP_ANIM chmcap.ani + SNDRES CHMMR_SHIP_SOUNDS chmsound.snd + + MUSICRES CHMMR_VICTORY_SONG chmditty.mod + diff --git a/sc2/src/sc2code/ships/chmmr/icode.h b/sc2/src/sc2code/ships/chmmr/icode.h new file mode 100644 index 000000000..051f8a5c1 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/icode.h @@ -0,0 +1,3 @@ +#define CHMMR_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/chmmr/igfxres.h b/sc2/src/sc2code/ships/chmmr/igfxres.h new file mode 100644 index 000000000..f6fc0d481 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/igfxres.h @@ -0,0 +1,14 @@ +#define CHMMR_ICON_MASK_PMAP_ANIM 0x00200002L +#define CHMMR_MICON_MASK_PMAP_ANIM 0x00200102L +#define CHMMR_BIG_MASK_PMAP_ANIM 0x00400202L +#define CHMMR_MED_MASK_PMAP_ANIM 0x00400302L +#define CHMMR_SML_MASK_PMAP_ANIM 0x00400402L +#define MUZZLE_BIG_MASK_PMAP_ANIM 0x00400502L +#define MUZZLE_MED_MASK_PMAP_ANIM 0x00400602L +#define MUZZLE_SML_MASK_PMAP_ANIM 0x00400702L +#define SATELLITE_BIG_MASK_PMAP_ANIM 0x00400802L +#define SATELLITE_MED_MASK_PMAP_ANIM 0x00400902L +#define SATELLITE_SML_MASK_PMAP_ANIM 0x00400a02L +#define CHMMR_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/chmmr/imusicre.h b/sc2/src/sc2code/ships/chmmr/imusicre.h new file mode 100644 index 000000000..e08ae7248 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/imusicre.h @@ -0,0 +1,3 @@ +#define CHMMR_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/chmmr/isndres.h b/sc2/src/sc2code/ships/chmmr/isndres.h new file mode 100644 index 000000000..41387dad5 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/isndres.h @@ -0,0 +1,3 @@ +#define CHMMR_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/chmmr/istrtab.h b/sc2/src/sc2code/ships/chmmr/istrtab.h new file mode 100644 index 000000000..35a9f63dc --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/istrtab.h @@ -0,0 +1,3 @@ +#define CHMMR_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/chmmr/resinst.h b/sc2/src/sc2code/ships/chmmr/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/chmmr/respkg.h b/sc2/src/sc2code/ships/chmmr/respkg.h new file mode 100644 index 000000000..929aca9c3 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/respkg.h @@ -0,0 +1,6 @@ +enum +{ + CHMMR_CODE_PACKAGE = 1, + CHMMR_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/chmmr/restypes.h b/sc2/src/sc2code/ships/chmmr/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/chmmr/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/druuge/druuge.c b/sc2/src/sc2code/ships/druuge/druuge.c new file mode 100644 index 000000000..b589b6b73 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/druuge.c @@ -0,0 +1,318 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/druuge/resinst.h" +#include "starcon.h" + +#define MAX_CREW 14 +#define MAX_ENERGY 32 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 4 +#define SPECIAL_ENERGY_COST 16 +#define ENERGY_WAIT 50 +#define MAX_THRUST 20 +#define THRUST_INCREMENT 2 +#define TURN_WAIT 4 +#define THRUST_WAIT 1 +#define WEAPON_WAIT 10 +#define SPECIAL_WAIT 30 + +#define SHIP_MASS 5 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 20 +#define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) + +static RACE_DESC druuge_desc = +{ + { + FIRES_FORE, + 17, /* Super Melee cost */ + 1400 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 9500, 2792, + }, + (STRING)DRUUGE_RACE_STRINGS, + (FRAME)DRUUGE_ICON_MASK_PMAP_ANIM, + (FRAME)DRUUGE_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)DRUUGE_BIG_MASK_PMAP_ANIM, + (FRAME)DRUUGE_MED_MASK_PMAP_ANIM, + (FRAME)DRUUGE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)CANNON_BIG_MASK_PMAP_ANIM, + (FRAME)CANNON_MED_MASK_PMAP_ANIM, + (FRAME)CANNON_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)DRUUGE_CAPT_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)DRUUGE_VICTORY_SONG, + (SOUND)DRUUGE_SHIP_SOUNDS, + }, + { + 0, + MISSILE_RANGE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define RECOIL_VELOCITY WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (6)) +#define MAX_RECOIL_VELOCITY (RECOIL_VELOCITY * 4) + +static void +cannon_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && ElementPtr1->crew_level + && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) + { + COUNT angle; + SIZE cur_delta_x, cur_delta_y; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + + angle = FACING_TO_ANGLE ( + GetFrameIndex (ElementPtr0->next.image.frame) + ); + DeltaVelocityComponents (&ElementPtr1->velocity, + COSINE (angle, RECOIL_VELOCITY), + SINE (angle, RECOIL_VELOCITY)); + GetCurrentVelocityComponents (&ElementPtr1->velocity, + &cur_delta_x, &cur_delta_y); + if ((long)cur_delta_x * (long)cur_delta_x + + (long)cur_delta_y * (long)cur_delta_y + > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) + { + angle = ARCTAN (cur_delta_x, cur_delta_y); + SetVelocityComponents (&ElementPtr1->velocity, + COSINE (angle, MAX_RECOIL_VELOCITY), + SINE (angle, MAX_RECOIL_VELOCITY)); + } + } +} + +static COUNT +initialize_cannon (PELEMENT ShipPtr, HELEMENT CannonArray[]) +{ +#define DRUUGE_OFFSET 24 +#define MISSILE_OFFSET 6 +#define MISSILE_HITS 4 +#define MISSILE_DAMAGE 6 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = MissileBlock.face; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = DRUUGE_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + CannonArray[0] = initialize_missile (&MissileBlock); + + if (CannonArray[0]) + { + ELEMENTPTR CannonPtr; + + LockElement (CannonArray[0], &CannonPtr); + CannonPtr->collision_func = cannon_collision; + UnlockElement (CannonArray[0]); + } + + return (1); +} + +static void +druuge_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + UWORD ship_flags; + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + ship_flags = 0; + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) + lpEvalDesc->MoveState = ENTICE; + else if (lpEvalDesc->ObjectPtr + && lpEvalDesc->which_turn <= WORLD_TO_TURN (MISSILE_RANGE * 3 / 4)) + { + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; + EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags &= + ~(FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT); + + lpEvalDesc->MoveState = PURSUE; + if (ShipPtr->thrust_wait == 0) + ++ShipPtr->thrust_wait; + } + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + if (ship_flags) + { + EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags = ship_flags; + } + + if (!(StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) + && (lpEvalDesc->which_turn <= 12 + || ( + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 6 + ))) + { + StarShipPtr->ship_input_state |= WEAPON; + if (ShipPtr->thrust_wait < WEAPON_WAIT + 1) + ShipPtr->thrust_wait = WEAPON_WAIT + 1; + } + + + if ((StarShipPtr->ship_input_state & WEAPON) + && StarShipPtr->RaceDescPtr->ship_info.energy_level < WEAPON_ENERGY_COST + && ShipPtr->crew_level > 1) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; +} + +static void +druuge_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + /* if just fired cannon */ + if ((StarShipPtr->cur_status_flags & WEAPON) + && StarShipPtr->weapon_counter == + StarShipPtr->RaceDescPtr->characteristics.weapon_wait) + { + COUNT angle; + SIZE cur_delta_x, cur_delta_y; + + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; + DeltaVelocityComponents (&ElementPtr->velocity, + COSINE (angle, RECOIL_VELOCITY), + SINE (angle, RECOIL_VELOCITY)); + GetCurrentVelocityComponents (&ElementPtr->velocity, + &cur_delta_x, &cur_delta_y); + if ((long)cur_delta_x * (long)cur_delta_x + + (long)cur_delta_y * (long)cur_delta_y + > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) + { + angle = ARCTAN (cur_delta_x, cur_delta_y); + SetVelocityComponents (&ElementPtr->velocity, + COSINE (angle, MAX_RECOIL_VELOCITY), + SINE (angle, MAX_RECOIL_VELOCITY)); + } + } +} + +static void +druuge_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->cur_status_flags & SPECIAL) + { + if (StarShipPtr->special_counter + || ElementPtr->crew_level == 1 + || StarShipPtr->RaceDescPtr->ship_info.energy_level + == StarShipPtr->RaceDescPtr->ship_info.max_energy) + StarShipPtr->cur_status_flags &= ~SPECIAL; + else + { + ProcessSound (SetAbsSoundIndex ( + /* BURN UP CREW */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + + DeltaCrew (ElementPtr, -1); + DeltaEnergy (ElementPtr, SPECIAL_ENERGY_COST); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + } +} + +RACE_DESCPTR +init_druuge () +{ + RACE_DESCPTR RaceDescPtr; + + druuge_desc.preprocess_func = druuge_preprocess; + druuge_desc.postprocess_func = druuge_postprocess; + druuge_desc.init_weapon_func = initialize_cannon; + druuge_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) druuge_intelligence; + + RaceDescPtr = &druuge_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/druuge/druuge.res b/sc2/src/sc2code/ships/druuge/druuge.res new file mode 100644 index 000000000..c5022eef4 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/druuge.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH druuge + +PACKAGE DRUUGE_CODE_PACKAGE druuge.shp + CODE DRUUGE_CODE druuge.cod + GFXRES DRUUGE_ICON_MASK_PMAP_ANIM druicons.ani + GFXRES DRUUGE_MICON_MASK_PMAP_ANIM drumicon.ani + STRTAB DRUUGE_RACE_STRINGS drutext.txt + +PACKAGE DRUUGE_PACKAGE druuge.shp + GFXRES DRUUGE_BIG_MASK_PMAP_ANIM druuge.big + GFXRES DRUUGE_MED_MASK_PMAP_ANIM druuge.med + GFXRES DRUUGE_SML_MASK_PMAP_ANIM druuge.sml + GFXRES CANNON_BIG_MASK_PMAP_ANIM canbig.ani + GFXRES CANNON_MED_MASK_PMAP_ANIM canmed.ani + GFXRES CANNON_SML_MASK_PMAP_ANIM cansml.ani + + GFXRES DRUUGE_CAPT_MASK_PMAP_ANIM drucap.ani + SNDRES DRUUGE_SHIP_SOUNDS drusound.snd + + MUSICRES DRUUGE_VICTORY_SONG druditty.mod + diff --git a/sc2/src/sc2code/ships/druuge/icode.h b/sc2/src/sc2code/ships/druuge/icode.h new file mode 100644 index 000000000..e0e322a4f --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/icode.h @@ -0,0 +1,3 @@ +#define DRUUGE_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/druuge/igfxres.h b/sc2/src/sc2code/ships/druuge/igfxres.h new file mode 100644 index 000000000..efb3c435f --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/igfxres.h @@ -0,0 +1,11 @@ +#define DRUUGE_ICON_MASK_PMAP_ANIM 0x00200002L +#define DRUUGE_MICON_MASK_PMAP_ANIM 0x00200102L +#define DRUUGE_BIG_MASK_PMAP_ANIM 0x00400202L +#define DRUUGE_MED_MASK_PMAP_ANIM 0x00400302L +#define DRUUGE_SML_MASK_PMAP_ANIM 0x00400402L +#define CANNON_BIG_MASK_PMAP_ANIM 0x00400502L +#define CANNON_MED_MASK_PMAP_ANIM 0x00400602L +#define CANNON_SML_MASK_PMAP_ANIM 0x00400702L +#define DRUUGE_CAPT_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/druuge/imusicre.h b/sc2/src/sc2code/ships/druuge/imusicre.h new file mode 100644 index 000000000..591b0c7e9 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/imusicre.h @@ -0,0 +1,3 @@ +#define DRUUGE_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/druuge/isndres.h b/sc2/src/sc2code/ships/druuge/isndres.h new file mode 100644 index 000000000..bd7ad73de --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/isndres.h @@ -0,0 +1,3 @@ +#define DRUUGE_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/druuge/istrtab.h b/sc2/src/sc2code/ships/druuge/istrtab.h new file mode 100644 index 000000000..093f8eb44 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/istrtab.h @@ -0,0 +1,3 @@ +#define DRUUGE_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/druuge/resinst.h b/sc2/src/sc2code/ships/druuge/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/druuge/respkg.h b/sc2/src/sc2code/ships/druuge/respkg.h new file mode 100644 index 000000000..c9e383c58 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/respkg.h @@ -0,0 +1,6 @@ +enum +{ + DRUUGE_CODE_PACKAGE = 1, + DRUUGE_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/druuge/restypes.h b/sc2/src/sc2code/ships/druuge/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/druuge/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/dummy.c b/sc2/src/sc2code/ships/dummy.c new file mode 100644 index 000000000..e69de29bb diff --git a/sc2/src/sc2code/ships/human/human.c b/sc2/src/sc2code/ships/human/human.c new file mode 100644 index 000000000..db56f6f73 --- /dev/null +++ b/sc2/src/sc2code/ships/human/human.c @@ -0,0 +1,352 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/human/resinst.h" +#include "starcon.h" + +#define MAX_CREW 18 +#define MAX_ENERGY 18 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 9 +#define SPECIAL_ENERGY_COST 4 +#define ENERGY_WAIT 8 +#define MAX_THRUST /* DISPLAY_TO_WORLD (6) */ 24 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 3 +#define TURN_WAIT 1 +#define THRUST_WAIT 4 +#define WEAPON_WAIT 10 +#define SPECIAL_WAIT 9 + +#define SHIP_MASS 6 +#define MISSILE_LIFE 60 +#define MIN_MISSILE_SPEED DISPLAY_TO_WORLD (10) +#define MAX_MISSILE_SPEED DISPLAY_TO_WORLD (20) + +static RACE_DESC human_desc = +{ + { + FIRES_FORE | SEEKING_WEAPON | POINT_DEFENSE, + 11, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 1752, 1450, + }, + (STRING)HUMAN_RACE_STRINGS, + (FRAME)HUMAN_ICON_MASK_PMAP_ANIM, + (FRAME)HUMAN_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)HUMAN_BIG_MASK_PMAP_ANIM, + (FRAME)HUMAN_MED_MASK_PMAP_ANIM, + (FRAME)HUMAN_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SATURN_BIG_MASK_PMAP_ANIM, + (FRAME)SATURN_MED_MASK_PMAP_ANIM, + (FRAME)SATURN_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)HUMAN_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)HUMAN_VICTORY_SONG, + (SOUND)HUMAN_SHIP_SOUNDS, + }, + { + 0, + LONG_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define MISSILE_SPEED (MAX_THRUST >= MIN_MISSILE_SPEED ? \ + MAX_THRUST : MIN_MISSILE_SPEED) +#define TRACK_WAIT 3 + +static void +nuke_preprocess (PELEMENT ElementPtr) +{ + COUNT facing; + + facing = GetFrameIndex (ElementPtr->next.image.frame); + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + if (TrackShip (ElementPtr, &facing) > 0) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + facing); + ElementPtr->state_flags |= CHANGING; + } + + ElementPtr->turn_wait = TRACK_WAIT; + } + + { + SIZE speed; + +#define THRUST_SCALE DISPLAY_TO_WORLD (1) + if ((speed = MISSILE_SPEED + + ((MISSILE_LIFE - ElementPtr->life_span) * + THRUST_SCALE)) > MAX_MISSILE_SPEED) + speed = MAX_MISSILE_SPEED; + SetVelocityVector (&ElementPtr->velocity, + speed, facing); + } +} + +static void +spawn_point_defense (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hDefense; + + hDefense = AllocElement (); + if (hDefense) + { + ELEMENTPTR DefensePtr; + + LockElement (hDefense, &DefensePtr); + DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + { + DefensePtr->death_func = spawn_point_defense; + } + GetElementStarShip (ElementPtr, &StarShipPtr); + SetElementStarShip (DefensePtr, StarShipPtr); + UnlockElement (hDefense); + + PutElement (hDefense); + } + } + else + { + BOOLEAN PaidFor; + HELEMENT hObject, hNextObject; + ELEMENTPTR ShipPtr; + + PaidFor = FALSE; + + LockElement (StarShipPtr->hShip, &ShipPtr); + for (hObject = GetTailElement (); hObject; hObject = hNextObject) + { + ELEMENTPTR ObjectPtr; + + LockElement (hObject, &ObjectPtr); + hNextObject = GetPredElement (ObjectPtr); + if (ObjectPtr != ShipPtr && CollidingElement (ObjectPtr) && + !OBJECT_CLOAKED (ObjectPtr)) + { +#define LASER_RANGE (UWORD)100 + SIZE delta_x, delta_y; + + delta_x = ObjectPtr->next.location.x - + ShipPtr->next.location.x; + delta_y = ObjectPtr->next.location.y - + ShipPtr->next.location.y; + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + delta_x = WORLD_TO_DISPLAY (delta_x); + delta_y = WORLD_TO_DISPLAY (delta_y); + if ((UWORD)delta_x <= LASER_RANGE && + (UWORD)delta_y <= LASER_RANGE && + (UWORD)delta_x * (UWORD)delta_x + + (UWORD)delta_y * (UWORD)delta_y <= + LASER_RANGE * LASER_RANGE) + { + HELEMENT hPointDefense; + LASER_BLOCK LaserBlock; + + if (!PaidFor) + { + if (!DeltaEnergy (ShipPtr, -SPECIAL_ENERGY_COST)) + break; + + ProcessSound (SetAbsSoundIndex ( + /* POINT_DEFENSE_LASER */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + PaidFor = TRUE; + } + + LaserBlock.cx = ShipPtr->next.location.x; + LaserBlock.cy = ShipPtr->next.location.y; + LaserBlock.face = 0; + LaserBlock.ex = ObjectPtr->next.location.x + - ShipPtr->next.location.x; + LaserBlock.ey = ObjectPtr->next.location.y + - ShipPtr->next.location.y; + LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = 0; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); + hPointDefense = initialize_laser (&LaserBlock); + if (hPointDefense) + { + ELEMENTPTR PDPtr; + + LockElement (hPointDefense, &PDPtr); + SetElementStarShip (PDPtr, StarShipPtr); + PDPtr->hTarget = 0; + UnlockElement (hPointDefense); + + PutElement (hPointDefense); + } + } + } + UnlockElement (hObject); + } + UnlockElement (StarShipPtr->hShip); + } +} + +static COUNT +initialize_nuke (PELEMENT ShipPtr, HELEMENT NukeArray[]) +{ +#define HUMAN_OFFSET 42 +#define MISSILE_DAMAGE 4 +#define MISSILE_HITS 1 +#define NUKE_OFFSET 8 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); + MissileBlock.pixoffs = HUMAN_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = nuke_preprocess; + MissileBlock.blast_offs = NUKE_OFFSET; + NukeArray[0] = initialize_missile (&MissileBlock); + + if (NukeArray[0]) + { + ELEMENTPTR NukePtr; + + LockElement (NukeArray[0], &NukePtr); + NukePtr->turn_wait = TRACK_WAIT; + UnlockElement (NukeArray[0]); + } + + return (1); +} + +static void +human_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0 + && ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr != NULL_PTR + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 2) + || (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr != NULL_PTR + && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 4))) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = NULL_PTR; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->weapon_counter == 0) + { + if (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr + && (!(StarShipPtr->ship_input_state & (LEFT | RIGHT /* | THRUST */)) + || ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 12)) + StarShipPtr->ship_input_state |= WEAPON; + } +} + +static void +human_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0) + { + spawn_point_defense (ElementPtr); + } +} + +RACE_DESCPTR +init_human () +{ + RACE_DESCPTR RaceDescPtr; + + human_desc.postprocess_func = human_postprocess; + human_desc.init_weapon_func = initialize_nuke; + human_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) human_intelligence; + + RaceDescPtr = &human_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/human/human.res b/sc2/src/sc2code/ships/human/human.res new file mode 100644 index 000000000..cd2e51574 --- /dev/null +++ b/sc2/src/sc2code/ships/human/human.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH human + +PACKAGE HUMAN_CODE_PACKAGE human.shp + CODE HUMAN_CODE human.cod + GFXRES HUMAN_ICON_MASK_PMAP_ANIM humicons.ani + GFXRES HUMAN_MICON_MASK_PMAP_ANIM hummicon.ani + STRTAB HUMAN_RACE_STRINGS humtext.txt + +PACKAGE HUMAN_PACKAGE human.shp + GFXRES HUMAN_BIG_MASK_PMAP_ANIM human.big + GFXRES HUMAN_MED_MASK_PMAP_ANIM human.med + GFXRES HUMAN_SML_MASK_PMAP_ANIM human.sml + GFXRES SATURN_BIG_MASK_PMAP_ANIM saturn.big + GFXRES SATURN_MED_MASK_PMAP_ANIM saturn.med + GFXRES SATURN_SML_MASK_PMAP_ANIM saturn.sml + + GFXRES HUMAN_CAPTAIN_MASK_PMAP_ANIM humcap.ani + SNDRES HUMAN_SHIP_SOUNDS humsound.snd + + MUSICRES HUMAN_VICTORY_SONG humditty.mod + diff --git a/sc2/src/sc2code/ships/human/icode.h b/sc2/src/sc2code/ships/human/icode.h new file mode 100644 index 000000000..c0f1eedff --- /dev/null +++ b/sc2/src/sc2code/ships/human/icode.h @@ -0,0 +1,3 @@ +#define HUMAN_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/human/igfxres.h b/sc2/src/sc2code/ships/human/igfxres.h new file mode 100644 index 000000000..f08f52f1b --- /dev/null +++ b/sc2/src/sc2code/ships/human/igfxres.h @@ -0,0 +1,11 @@ +#define HUMAN_ICON_MASK_PMAP_ANIM 0x00200002L +#define HUMAN_MICON_MASK_PMAP_ANIM 0x00200102L +#define HUMAN_BIG_MASK_PMAP_ANIM 0x00400202L +#define HUMAN_MED_MASK_PMAP_ANIM 0x00400302L +#define HUMAN_SML_MASK_PMAP_ANIM 0x00400402L +#define SATURN_BIG_MASK_PMAP_ANIM 0x00400502L +#define SATURN_MED_MASK_PMAP_ANIM 0x00400602L +#define SATURN_SML_MASK_PMAP_ANIM 0x00400702L +#define HUMAN_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/human/imusicre.h b/sc2/src/sc2code/ships/human/imusicre.h new file mode 100644 index 000000000..e9f27f665 --- /dev/null +++ b/sc2/src/sc2code/ships/human/imusicre.h @@ -0,0 +1,3 @@ +#define HUMAN_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/human/isndres.h b/sc2/src/sc2code/ships/human/isndres.h new file mode 100644 index 000000000..f2d17fe94 --- /dev/null +++ b/sc2/src/sc2code/ships/human/isndres.h @@ -0,0 +1,3 @@ +#define HUMAN_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/human/istrtab.h b/sc2/src/sc2code/ships/human/istrtab.h new file mode 100644 index 000000000..27bdaf1d8 --- /dev/null +++ b/sc2/src/sc2code/ships/human/istrtab.h @@ -0,0 +1,3 @@ +#define HUMAN_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/human/resinst.h b/sc2/src/sc2code/ships/human/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/human/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/human/respkg.h b/sc2/src/sc2code/ships/human/respkg.h new file mode 100644 index 000000000..0b21b0017 --- /dev/null +++ b/sc2/src/sc2code/ships/human/respkg.h @@ -0,0 +1,6 @@ +enum +{ + HUMAN_CODE_PACKAGE = 1, + HUMAN_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/human/restypes.h b/sc2/src/sc2code/ships/human/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/human/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/ilwrath/icode.h b/sc2/src/sc2code/ships/ilwrath/icode.h new file mode 100644 index 000000000..27bd109e7 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/icode.h @@ -0,0 +1,3 @@ +#define ILWRATH_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/ilwrath/igfxres.h b/sc2/src/sc2code/ships/ilwrath/igfxres.h new file mode 100644 index 000000000..264ffc91b --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/igfxres.h @@ -0,0 +1,11 @@ +#define ILWRATH_ICON_MASK_PMAP_ANIM 0x00200002L +#define ILWRATH_MICON_MASK_PMAP_ANIM 0x00200102L +#define ILWRATH_BIG_MASK_PMAP_ANIM 0x00400202L +#define ILWRATH_MED_MASK_PMAP_ANIM 0x00400302L +#define ILWRATH_SML_MASK_PMAP_ANIM 0x00400402L +#define FIRE_BIG_MASK_PMAP_ANIM 0x00400502L +#define FIRE_MED_MASK_PMAP_ANIM 0x00400602L +#define FIRE_SML_MASK_PMAP_ANIM 0x00400702L +#define ILWRATH_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/ilwrath/ilwrath.c b/sc2/src/sc2code/ships/ilwrath/ilwrath.c new file mode 100644 index 000000000..979ef4094 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/ilwrath.c @@ -0,0 +1,376 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/ilwrath/resinst.h" +#include "starcon.h" + +#define MAX_CREW 22 +#define MAX_ENERGY 16 +#define ENERGY_REGENERATION 4 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 3 +#define ENERGY_WAIT 4 +#define MAX_THRUST 25 +#define THRUST_INCREMENT 5 +#define TURN_WAIT 2 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 13 + +#define SHIP_MASS 7 +#define MISSILE_LIFE 8 + +static RACE_DESC ilwrath_desc = +{ + { + FIRES_FORE, + 10, /* Super Melee cost */ + 1410 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 48, 1700, + }, + (STRING)ILWRATH_RACE_STRINGS, + (FRAME)ILWRATH_ICON_MASK_PMAP_ANIM, + (FRAME)ILWRATH_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)ILWRATH_BIG_MASK_PMAP_ANIM, + (FRAME)ILWRATH_MED_MASK_PMAP_ANIM, + (FRAME)ILWRATH_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)FIRE_BIG_MASK_PMAP_ANIM, + (FRAME)FIRE_MED_MASK_PMAP_ANIM, + (FRAME)FIRE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)ILWRATH_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)ILWRATH_VICTORY_SONG, + (SOUND)ILWRATH_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +flame_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +flame_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->state_flags &= ~DISAPPEARING; + ElementPtr0->state_flags |= NONSOLID; +} + +static void +ilwrath_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + lpEvalDesc->MoveState = PURSUE; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 10) + /* don't want to dodge when you could be flaming */ + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (lpEvalDesc->ObjectPtr + && (lpEvalDesc->which_turn <= 6 + || (lpEvalDesc->which_turn <= 10 + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 10))) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (OBJECT_CLOAKED (ShipPtr)) + { + StarShipPtr->ship_input_state &= ~LEFT | RIGHT; + StarShipPtr->ship_input_state |= THRUST; + } + StarShipPtr->ship_input_state |= WEAPON; + } + else if (StarShipPtr->special_counter == 0 + && (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER + || !GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER))) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (!OBJECT_CLOAKED (ShipPtr) + && !(StarShipPtr->ship_input_state & WEAPON)) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static COUNT +initialize_flame (PELEMENT ShipPtr, HELEMENT FlameArray[]) +{ +#define ILWRATH_OFFSET 29 +#define MISSILE_SPEED MAX_THRUST +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 0 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = ILWRATH_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = flame_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + FlameArray[0] = initialize_missile (&MissileBlock); + + if (FlameArray[0]) + { + SIZE dx, dy; + ELEMENTPTR FlamePtr; + + LockElement (FlameArray[0], &FlamePtr); + GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); + DeltaVelocityComponents (&FlamePtr->velocity, dx, dy); + FlamePtr->current.location.x -= VELOCITY_TO_WORLD (dx); + FlamePtr->current.location.y -= VELOCITY_TO_WORLD (dy); + + FlamePtr->collision_func = flame_collision; + FlamePtr->turn_wait = 0; + UnlockElement (FlameArray[0]); + } + + return (1); +} + +static void +ilwrath_preprocess (PELEMENT ElementPtr) +{ + ELEMENT_FLAGS status_flags; + STARSHIPPTR StarShipPtr; + PPRIMITIVE lpPrim; + + GetElementStarShip (ElementPtr, &StarShipPtr); + status_flags = StarShipPtr->cur_status_flags; + lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; + if (GetPrimType (lpPrim) == STAMPFILL_PRIM) + { + COLOR Color; + BOOLEAN weapon_discharge; + + Color = GetPrimColor (lpPrim); + weapon_discharge = ((status_flags & WEAPON) + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST); + if (weapon_discharge + || (StarShipPtr->special_counter == 0 + && ((status_flags & SPECIAL) || Color != BLACK_COLOR))) + { + if (Color == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)) + SetPrimType (lpPrim, STAMP_PRIM); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + else + { + ProcessSound (SetAbsSoundIndex ( + /* CLOAKING_OFF */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + if (weapon_discharge) + { + COUNT facing; + + facing = StarShipPtr->ShipFacing; + if (TrackShip (ElementPtr, &facing) >= 0) + { +#define LOOK_AHEAD 4 + ELEMENTPTR eptr; + SIZE dx0, dy0, dx1, dy1; + VELOCITY_DESC v; + + LockElement (ElementPtr->hTarget, &eptr); + v = eptr->velocity; + GetNextVelocityComponents (&v, &dx0, &dy0, LOOK_AHEAD); + v = ElementPtr->velocity; + GetNextVelocityComponents (&v, &dx1, &dy1, LOOK_AHEAD); + dx0 = (eptr->current.location.x + dx0) + - (ElementPtr->current.location.x + dx1); + dy0 = (eptr->current.location.y + dy0) + - (ElementPtr->current.location.y + dy1); + UnlockElement (ElementPtr->hTarget); + + StarShipPtr->ShipFacing = + NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (dx0, dy0)) + ); +#ifdef NOTYET + if (ElementPtr->thrust_wait == 0 + && (StarShipPtr->cur_status_flags & THRUST)) + { + COUNT last_facing; + + do + { + VELOCITY_DESC temp_v; + + last_facing = StarShipPtr->ShipFacing; + inertial_thrust (ElementPtr); + temp_v = ElementPtr->velocity; + ElementPtr->velocity = v; + + dx0 += dx1; + dy0 += dy1; + GetNextVelocityComponents (&temp_v, + &dx1, &dy1, LOOK_AHEAD); + dx0 -= dx1; + dy0 -= dy1; + StarShipPtr->ShipFacing = + NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (dx0, dy0)) + ); + } while (StarShipPtr->ShipFacing != last_facing); + } +#endif /* NOTYET */ + if (ElementPtr->turn_wait == 0) + ++ElementPtr->turn_wait; + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + StarShipPtr->ShipFacing); + } + ElementPtr->hTarget = 0; + } + } + + ElementPtr->state_flags |= CHANGING; + status_flags &= ~SPECIAL; + StarShipPtr->special_counter = 0; + } + else if (Color != BLACK_COLOR) + { + if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) + { + SetPrimColor (lpPrim, BLACK_COLOR); + Untarget (ElementPtr); + } + else if (Color == BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + else if (Color == BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + else + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B)); + + ElementPtr->state_flags |= CHANGING; + } + } + + if ((status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + SetPrimType (lpPrim, STAMPFILL_PRIM); + + ProcessSound (SetAbsSoundIndex ( + /* CLOAKING_ON */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + + ElementPtr->state_flags |= CHANGING; + } +} + +RACE_DESCPTR +init_ilwrath () +{ + RACE_DESCPTR RaceDescPtr; + + ilwrath_desc.preprocess_func = ilwrath_preprocess; + ilwrath_desc.init_weapon_func = initialize_flame; + ilwrath_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) ilwrath_intelligence; + + RaceDescPtr = &ilwrath_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/ilwrath/ilwrath.res b/sc2/src/sc2code/ships/ilwrath/ilwrath.res new file mode 100644 index 000000000..aa9e1c88a --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/ilwrath.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH ilwrath + +PACKAGE ILWRATH_CODE_PACKAGE ilwrath.shp + CODE ILWRATH_CODE ilwrath.cod + GFXRES ILWRATH_ICON_MASK_PMAP_ANIM ilwicons.ani + GFXRES ILWRATH_MICON_MASK_PMAP_ANIM ilwmicon.ani + STRTAB ILWRATH_RACE_STRINGS ilwtext.txt + +PACKAGE ILWRATH_PACKAGE ilwrath.shp + GFXRES ILWRATH_BIG_MASK_PMAP_ANIM ilwrath.big + GFXRES ILWRATH_MED_MASK_PMAP_ANIM ilwrath.med + GFXRES ILWRATH_SML_MASK_PMAP_ANIM ilwrath.sml + GFXRES FIRE_BIG_MASK_PMAP_ANIM fire.big + GFXRES FIRE_MED_MASK_PMAP_ANIM fire.med + GFXRES FIRE_SML_MASK_PMAP_ANIM fire.sml + + GFXRES ILWRATH_CAPTAIN_MASK_PMAP_ANIM ilwcap.ani + SNDRES ILWRATH_SHIP_SOUNDS ilwsound.snd + + MUSICRES ILWRATH_VICTORY_SONG ilwditty.mod + diff --git a/sc2/src/sc2code/ships/ilwrath/imusicre.h b/sc2/src/sc2code/ships/ilwrath/imusicre.h new file mode 100644 index 000000000..93585893d --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/imusicre.h @@ -0,0 +1,3 @@ +#define ILWRATH_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/ilwrath/isndres.h b/sc2/src/sc2code/ships/ilwrath/isndres.h new file mode 100644 index 000000000..ec9e8698a --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/isndres.h @@ -0,0 +1,3 @@ +#define ILWRATH_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/ilwrath/istrtab.h b/sc2/src/sc2code/ships/ilwrath/istrtab.h new file mode 100644 index 000000000..89947af20 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/istrtab.h @@ -0,0 +1,3 @@ +#define ILWRATH_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/ilwrath/resinst.h b/sc2/src/sc2code/ships/ilwrath/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/ilwrath/respkg.h b/sc2/src/sc2code/ships/ilwrath/respkg.h new file mode 100644 index 000000000..1c88ac649 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/respkg.h @@ -0,0 +1,6 @@ +enum +{ + ILWRATH_CODE_PACKAGE = 1, + ILWRATH_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/ilwrath/restypes.h b/sc2/src/sc2code/ships/ilwrath/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/ilwrath/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/lastbat/icode.h b/sc2/src/sc2code/ships/lastbat/icode.h new file mode 100644 index 000000000..bbfbce654 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/icode.h @@ -0,0 +1,3 @@ +#define SAMATRA_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/lastbat/igfxres.h b/sc2/src/sc2code/ships/lastbat/igfxres.h new file mode 100644 index 000000000..5251b16b2 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/igfxres.h @@ -0,0 +1,12 @@ +#define SAMATRA_BIG_MASK_ANIM 0x00400002L +#define SAMATRA_MED_MASK_PMAP_ANIM 0x00400102L +#define SAMATRA_SML_MASK_PMAP_ANIM 0x00400202L +#define SENTINEL_BIG_MASK_ANIM 0x00400302L +#define SENTINEL_MED_MASK_PMAP_ANIM 0x00400402L +#define SENTINEL_SML_MASK_PMAP_ANIM 0x00400502L +#define GENERATOR_BIG_MASK_ANIM 0x00400602L +#define GENERATOR_MED_MASK_PMAP_ANIM 0x00400702L +#define GENERATOR_SML_MASK_PMAP_ANIM 0x00400802L +#define SAMATRA_CAPTAIN_MASK_PMAP_ANIM 0x00600902L + + diff --git a/sc2/src/sc2code/ships/lastbat/imusicre.h b/sc2/src/sc2code/ships/lastbat/imusicre.h new file mode 100644 index 000000000..fed097185 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/imusicre.h @@ -0,0 +1,3 @@ +#define SAMATRA_VICTORY_SONG 0x00400005L + +typedef RESOURCE MUSICRES_INSTANCE; diff --git a/sc2/src/sc2code/ships/lastbat/isndres.h b/sc2/src/sc2code/ships/lastbat/isndres.h new file mode 100644 index 000000000..2e567d8cd --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/isndres.h @@ -0,0 +1,3 @@ +#define SAMATRA_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/lastbat/istrtab.h b/sc2/src/sc2code/ships/lastbat/istrtab.h new file mode 100644 index 000000000..593946557 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/istrtab.h @@ -0,0 +1,3 @@ +#define SAMATRA_SHIP_SOUNDS 0x00400004L + + diff --git a/sc2/src/sc2code/ships/lastbat/lastbat.c b/sc2/src/sc2code/ships/lastbat/lastbat.c new file mode 100644 index 000000000..5ce4bdf44 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/lastbat.c @@ -0,0 +1,903 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/lastbat/resinst.h" +#include "starcon.h" + +#define num_generators characteristics.max_thrust + +#define MAX_CREW 1 +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 3 +#define ENERGY_WAIT 6 +#define MAX_THRUST 0 +#define THRUST_INCREMENT 0 +#define TURN_WAIT 0 +#define THRUST_WAIT 0 +#define WEAPON_WAIT ((ONE_SECOND / BATTLE_FRAME_RATE) * 10) +#define SPECIAL_WAIT ((ONE_SECOND / BATTLE_FRAME_RATE) * 3) + +#define SHIP_MASS (MAX_SHIP_MASS * 10) +#define SAMATRA_OFFSET 9 +#define MISSILE_SPEED DISPLAY_TO_WORLD (8) + +static RACE_DESC samatra_desc = +{ + { + /* FIRES_FORE | */ IMMEDIATE_WEAPON | CREW_IMMUNE, + 16, /* Super Melee cost */ + 0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)0, + (FRAME)0, + (FRAME)0, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SAMATRA_BIG_MASK_ANIM, + (FRAME)SAMATRA_MED_MASK_PMAP_ANIM, + (FRAME)SAMATRA_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SENTINEL_BIG_MASK_ANIM, + (FRAME)SENTINEL_MED_MASK_PMAP_ANIM, + (FRAME)SENTINEL_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)GENERATOR_BIG_MASK_ANIM, + (FRAME)GENERATOR_MED_MASK_PMAP_ANIM, + (FRAME)GENERATOR_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SAMATRA_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + 0, + (SOUND)SAMATRA_SHIP_SOUNDS, + }, + { + 0, + 0, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static HELEMENT spawn_comet (PELEMENT ElementPtr); + +static void +comet_preprocess (PELEMENT ElementPtr) +{ + COUNT frame_index; + + frame_index = GetFrameIndex (ElementPtr->current.image.frame) + 1; + if (frame_index < 29) + { + if (frame_index == 25) + { + SIZE cur_delta_x, cur_delta_y; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ++StarShipPtr->RaceDescPtr->characteristics.weapon_wait; + spawn_comet (ElementPtr); + ElementPtr->state_flags |= NONSOLID; + + GetCurrentVelocityComponents (&ElementPtr->velocity, + &cur_delta_x, &cur_delta_y); + SetVelocityComponents (&ElementPtr->velocity, + cur_delta_x / 2, cur_delta_y / 2); + } + ++ElementPtr->life_span; + } + + ElementPtr->next.image.frame = + SetAbsFrameIndex ( + ElementPtr->current.image.frame, frame_index + ); + ElementPtr->state_flags |= CHANGING; +} + +#define COMET_DAMAGE 2 + +static void +comet_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr1->state_flags & GOOD_GUY) + { + BYTE old_hits; + COUNT old_life; + HELEMENT hBlastElement; + + if (ElementPtr1->state_flags & PLAYER_SHIP) + ElementPtr0->mass_points = COMET_DAMAGE; + else + ElementPtr0->mass_points = 50; + + old_hits = ElementPtr0->hit_points; + old_life = ElementPtr0->life_span; + hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + if (ElementPtr1->state_flags & PLAYER_SHIP) + { + ElementPtr0->hit_points = old_hits; + ElementPtr0->life_span = old_life; + ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID | COLLISION); + + if (hBlastElement) + { + RemoveElement (hBlastElement); + FreeElement (hBlastElement); + } + } + + if (ElementPtr0->state_flags & DISAPPEARING) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + --StarShipPtr->RaceDescPtr->characteristics.weapon_wait; + } + } +} + +static HELEMENT +spawn_comet (PELEMENT ElementPtr) +{ +#define COMET_OFFSET 0 +#define COMET_HITS 12 +#define COMET_SPEED DISPLAY_TO_WORLD (12) +#define COMET_LIFE 2 + MISSILE_BLOCK MissileBlock; + HELEMENT hComet; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = 0; + MissileBlock.index = 24; + MissileBlock.sender = BAD_GUY | IGNORE_SIMILAR; + MissileBlock.pixoffs = 0; + MissileBlock.speed = 0; + MissileBlock.hit_points = COMET_HITS; + MissileBlock.damage = COMET_DAMAGE; + MissileBlock.life = COMET_LIFE; + MissileBlock.preprocess_func = comet_preprocess; + MissileBlock.blast_offs = COMET_OFFSET; + hComet = initialize_missile (&MissileBlock); + + if (hComet) + { + ELEMENTPTR CometPtr; + + PutElement (hComet); + + LockElement (hComet, &CometPtr); + CometPtr->collision_func = comet_collision; + SetElementStarShip (CometPtr, StarShipPtr); + { + COUNT facing; + + CometPtr->turn_wait = ElementPtr->turn_wait; + CometPtr->hTarget = ElementPtr->hTarget; + if (ElementPtr->state_flags & PLAYER_SHIP) + { + CometPtr->turn_wait = 0; + facing = (COUNT)Random (); + SetVelocityVector (&CometPtr->velocity, + COMET_SPEED, facing); + } + else + { + CometPtr->velocity = ElementPtr->velocity; + CometPtr->hit_points = ElementPtr->hit_points; + facing = ANGLE_TO_FACING ( + GetVelocityTravelAngle (&CometPtr->velocity) + ); + } + + if (CometPtr->turn_wait) + --CometPtr->turn_wait; + else + { +#define COMET_WAIT 3 + facing = NORMALIZE_FACING (facing); + if (TrackShip (CometPtr, &facing) > 0) + SetVelocityVector (&CometPtr->velocity, + COMET_SPEED, facing); + CometPtr->turn_wait = COMET_WAIT; + } + } + UnlockElement (hComet); + } + + return (hComet); +} + +static void +turret_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { +#define TURRET_WAIT 0 + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + (GetFrameIndex (ElementPtr->current.image.frame) % 10) + 1); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = TURRET_WAIT; + } +} + +#define GATE_DAMAGE 1 +#define GATE_HITS 100 + +static void +gate_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr1->state_flags & GOOD_GUY) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->num_generators == 0) + { + if (!(ElementPtr1->state_flags & FINITE_LIFE)) + ElementPtr0->state_flags |= COLLISION; + + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && GetPrimType ( + &GLOBAL (DisplayArray[ElementPtr0->PrimIndex]) + ) == STAMPFILL_PRIM + && GET_GAME_STATE (BOMB_CARRIER)) + { + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + } + } + else + { + HELEMENT hBlastElement; + + if (ElementPtr1->state_flags & PLAYER_SHIP) + ElementPtr0->mass_points = GATE_DAMAGE; + else + ElementPtr0->mass_points = 50; + + ElementPtr0->hit_points = GATE_HITS; + hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID | COLLISION); + ElementPtr0->life_span = NORMAL_LIFE; + + if (hBlastElement) + { + RemoveElement (hBlastElement); + FreeElement (hBlastElement); + } + } + } +} + +static void +gate_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->num_generators == 0) + { + ElementPtr->mass_points = SHIP_MASS; + ElementPtr->state_flags &= ~FINITE_LIFE; + ElementPtr->life_span = NORMAL_LIFE + 1; + ElementPtr->preprocess_func = 0; + SetPrimColor ( + &GLOBAL (DisplayArray[ElementPtr->PrimIndex]), + BLACK_COLOR + ); + SetPrimType ( + &GLOBAL (DisplayArray[ElementPtr->PrimIndex]), + STAMPFILL_PRIM + ); + } + else + { + ++ElementPtr->life_span; + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + if (GetFrameIndex (ElementPtr->next.image.frame) == 0) + ElementPtr->next.image.frame = + SetAbsFrameIndex ( + ElementPtr->next.image.frame, 11 + ); + + ElementPtr->state_flags |= CHANGING; + } +} + +static void +generator_death (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & FINITE_LIFE)) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + --StarShipPtr->RaceDescPtr->num_generators; + ElementPtr->state_flags |= FINITE_LIFE | NONSOLID; + ElementPtr->preprocess_func = 0; + ElementPtr->turn_wait = 12; + ElementPtr->thrust_wait = 0; + + ElementPtr->current.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, 10 - 1); + } + + if (ElementPtr->thrust_wait) + { + --ElementPtr->thrust_wait; + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= CHANGING; + ++ElementPtr->life_span; + } + else if (ElementPtr->turn_wait--) + { + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= CHANGING; + ++ElementPtr->life_span; + + ElementPtr->next.image.frame = IncFrameIndex ( + ElementPtr->current.image.frame + ); + + ElementPtr->thrust_wait = 1; + } +} + +#define GENERATOR_HITS 15 + +static void +generator_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else if ((ElementPtr->turn_wait = + (BYTE)((GENERATOR_HITS + - ElementPtr->hit_points) / 5)) < 3) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + (GetFrameIndex (ElementPtr->current.image.frame) + 1) % 10); + ElementPtr->state_flags |= CHANGING; + } +} + +static void +generator_collision (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (!(ElementPtr1->state_flags & FINITE_LIFE)) + { + ElementPtr0->state_flags |= COLLISION; + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +#define TRACK_WAIT 1 + +static void +sentinel_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ++StarShipPtr->RaceDescPtr->characteristics.special_wait; + ++ElementPtr->life_span; + + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + else + { +#define ANIMATION_WAIT 1 + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + (GetFrameIndex (ElementPtr->current.image.frame) + 1) % 6); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->thrust_wait = ANIMATION_WAIT; + } + + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT facing; + HELEMENT hTarget; + + if (!(ElementPtr->state_flags & NONSOLID)) + facing = ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + ); + else + { + ElementPtr->state_flags &= ~NONSOLID; + facing = (COUNT)Random (); + SetVelocityVector (&ElementPtr->velocity, + MISSILE_SPEED, facing); + } + facing = NORMALIZE_FACING (facing); + if (ElementPtr->hTarget == 0) + { + COUNT f; + + f = facing; + TrackShip (ElementPtr, &f); + } + + if (ElementPtr->hTarget == 0) + hTarget = StarShipPtr->hShip; + else if (StarShipPtr->hShip == 0) + hTarget = ElementPtr->hTarget; + else + { + SIZE delta_x0, delta_y0, delta_x1, delta_y1; + ELEMENTPTR ShipPtr, EnemyShipPtr; + + LockElement (ElementPtr->hTarget, &EnemyShipPtr); + + LockElement (StarShipPtr->hShip, &ShipPtr); + delta_x0 = ShipPtr->current.location.x + - ElementPtr->current.location.x; + delta_y0 = ShipPtr->current.location.y + - ElementPtr->current.location.y; + + delta_x1 = ShipPtr->current.location.x + - EnemyShipPtr->current.location.x; + delta_y1 = ShipPtr->current.location.y + - EnemyShipPtr->current.location.y; + UnlockElement (StarShipPtr->hShip); + + if ((long)delta_x0 * delta_x0 + + (long)delta_y0 * delta_y0 > + (long)delta_x1 * delta_x1 + + (long)delta_y1 * delta_y1) + hTarget = StarShipPtr->hShip; + else + hTarget = ElementPtr->hTarget; + + UnlockElement (ElementPtr->hTarget); + } + + if (hTarget) + { + COUNT num_frames; + SIZE delta_x, delta_y; + ELEMENTPTR TargetPtr; + VELOCITY_DESC TargetVelocity; + + LockElement (hTarget, &TargetPtr); + + delta_x = TargetPtr->current.location.x + - ElementPtr->current.location.x; + delta_x = WRAP_DELTA_X (delta_x); + delta_y = TargetPtr->current.location.y + - ElementPtr->current.location.y; + delta_y = WRAP_DELTA_Y (delta_y); + + if ((num_frames = WORLD_TO_TURN ( + square_root ((long)delta_x * delta_x + + (long)delta_y * delta_y) + )) == 0) + num_frames = 1; + + TargetVelocity = TargetPtr->velocity; + GetNextVelocityComponents (&TargetVelocity, + &delta_x, &delta_y, num_frames); + + delta_x = (TargetPtr->current.location.x + delta_x) + - ElementPtr->current.location.x; + delta_x = WRAP_DELTA_X (delta_x); + delta_y = (TargetPtr->current.location.y + delta_y) + - ElementPtr->current.location.y; + delta_y = WRAP_DELTA_Y (delta_y); + + UnlockElement (hTarget); + + delta_x = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing + ); + + if (delta_x > 0) + { + if (delta_x <= ANGLE_TO_FACING (HALF_CIRCLE)) + ++facing; + else + --facing; + } + + SetVelocityVector (&ElementPtr->velocity, + MISSILE_SPEED, facing); + } + + ElementPtr->turn_wait = TRACK_WAIT; + } +} + +#define RECOIL_VELOCITY WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (10)) +#define MAX_RECOIL_VELOCITY (RECOIL_VELOCITY * 4) + +static void +sentinel_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + COUNT angle; + STARSHIPPTR StarShipPtr; + + if (ElementPtr1->state_flags & BAD_GUY) + { + if (ElementPtr0->preprocess_func == ElementPtr1->preprocess_func + && !(ElementPtr0->state_flags & DEFY_PHYSICS) + && (pPt0->x != ElementPtr0->IntersectControl.IntersectStamp.origin.x + || pPt0->y != ElementPtr0->IntersectControl.IntersectStamp.origin.y)) + { + angle = ARCTAN (pPt0->x - pPt1->x, pPt0->y - pPt1->y); + + SetVelocityComponents (&ElementPtr0->velocity, + COSINE (angle, WORLD_TO_VELOCITY (MISSILE_SPEED)), + SINE (angle, WORLD_TO_VELOCITY (MISSILE_SPEED))); + ElementPtr0->turn_wait = TRACK_WAIT; + ElementPtr0->state_flags |= COLLISION | DEFY_PHYSICS; + } + } + else + { + BYTE old_hits; + COUNT old_life; + HELEMENT hBlastElement; + + old_hits = ElementPtr0->hit_points; + old_life = ElementPtr0->life_span; + ElementPtr0->blast_offset = 0; + hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->thrust_wait = 0; + + if ((ElementPtr1->state_flags & PLAYER_SHIP) + && ElementPtr1->crew_level + && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) + { + SIZE cur_delta_x, cur_delta_y; + + ElementPtr0->life_span = old_life; + ElementPtr0->hit_points = old_hits; + ElementPtr0->state_flags &= ~DISAPPEARING; + ElementPtr0->state_flags |= DEFY_PHYSICS; + ElementPtr0->turn_wait = (ONE_SECOND / BATTLE_FRAME_RATE) >> 1; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + if (ElementPtr1->turn_wait < COLLISION_TURN_WAIT) + ElementPtr1->turn_wait += COLLISION_TURN_WAIT; + if (ElementPtr1->thrust_wait < COLLISION_THRUST_WAIT) + ElementPtr1->thrust_wait += COLLISION_THRUST_WAIT; + + angle = GetVelocityTravelAngle (&ElementPtr0->velocity); + DeltaVelocityComponents (&ElementPtr1->velocity, + COSINE (angle, RECOIL_VELOCITY), + SINE (angle, RECOIL_VELOCITY)); + GetCurrentVelocityComponents (&ElementPtr1->velocity, + &cur_delta_x, &cur_delta_y); + if ((long)cur_delta_x * (long)cur_delta_x + + (long)cur_delta_y * (long)cur_delta_y + > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) + { + angle = ARCTAN (cur_delta_x, cur_delta_y); + SetVelocityComponents (&ElementPtr1->velocity, + COSINE (angle, MAX_RECOIL_VELOCITY), + SINE (angle, MAX_RECOIL_VELOCITY)); + } + + ZeroVelocityComponents (&ElementPtr0->velocity); + } + + if (ElementPtr0->state_flags & DISAPPEARING) + { + GetElementStarShip (ElementPtr0, &StarShipPtr); + --StarShipPtr->RaceDescPtr->characteristics.special_wait; + if (hBlastElement) + { + ELEMENTPTR BlastElementPtr; + + LockElement (hBlastElement, &BlastElementPtr); + BlastElementPtr->life_span = 6; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex ( + BlastElementPtr->current.image.farray[0], 6 + ); + UnlockElement (hBlastElement); + } + } + } +} + +static void +samatra_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); +} + +#define MAX_COMETS 3 +#define MAX_SENTINELS 4 + +static void +samatra_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->num_generators) + { + if (StarShipPtr->weapon_counter == 0 + && StarShipPtr->RaceDescPtr->characteristics.weapon_wait < MAX_COMETS + && spawn_comet (ElementPtr)) + { + StarShipPtr->weapon_counter = WEAPON_WAIT; + } + + if (StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->characteristics.special_wait < MAX_SENTINELS) + { +#define MISSILE_LIFE 2 +#define MISSILE_OFFSET 0 +#define MISSILE_HITS 10 +#define MISSILE_DAMAGE 1 + MISSILE_BLOCK MissileBlock; + HELEMENT hSentinel; + + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = 0; + MissileBlock.index = 0; + MissileBlock.sender = BAD_GUY; + MissileBlock.pixoffs = 0; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = sentinel_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + hSentinel = initialize_missile (&MissileBlock); + + if (hSentinel) + { + ELEMENTPTR SentinelPtr; + + LockElement (hSentinel, &SentinelPtr); + SentinelPtr->collision_func = sentinel_collision; + SentinelPtr->turn_wait = TRACK_WAIT + 2; + SetElementStarShip (SentinelPtr, StarShipPtr); + UnlockElement (hSentinel); + + StarShipPtr->special_counter = SPECIAL_WAIT; + + PutElement (hSentinel); + } + } + } +} + +static void +samatra_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->RaceDescPtr->characteristics.weapon_wait = 0; + StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; + if (!(ElementPtr->state_flags & APPEARING)) + { + ++ElementPtr->turn_wait; + ++ElementPtr->thrust_wait; + } + else + { +#define MAX_GENERATORS 8 + POINT offs[] = + { + {-127-9, -53+18}, + { -38-9, -88+18}, + { 44-9, -85+18}, + { 127-9, -60+18}, + { 124-9, 28+18}, + { 73-9, 61+18}, + { -87-9, 58+18}, + {-136-9, 29+18}, + }; + + for (StarShipPtr->RaceDescPtr->num_generators = 0; + StarShipPtr->RaceDescPtr->num_generators < MAX_GENERATORS; + ++StarShipPtr->RaceDescPtr->num_generators) + { + HELEMENT hGenerator; + + hGenerator = AllocElement (); + if (hGenerator) + { + ELEMENTPTR GeneratorPtr; + + LockElement (hGenerator, &GeneratorPtr); + GeneratorPtr->hit_points = GENERATOR_HITS; + GeneratorPtr->mass_points = MAX_SHIP_MASS * 10; + GeneratorPtr->life_span = NORMAL_LIFE; + GeneratorPtr->state_flags = + APPEARING | BAD_GUY | IGNORE_SIMILAR; + SetPrimType ( + &GLOBAL (DisplayArray[GeneratorPtr->PrimIndex]), + STAMP_PRIM + ); + GeneratorPtr->current.location.x = + ((LOG_SPACE_WIDTH >> 1) + + DISPLAY_TO_WORLD (offs[StarShipPtr->RaceDescPtr->num_generators].x)) + & ~((SCALED_ONE << MAX_VIS_REDUCTION) - 1); + GeneratorPtr->current.location.y = + ((LOG_SPACE_HEIGHT >> 1) + + DISPLAY_TO_WORLD (offs[StarShipPtr->RaceDescPtr->num_generators].y)) + & ~((SCALED_ONE << MAX_VIS_REDUCTION) - 1); + GeneratorPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + GeneratorPtr->current.image.frame = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], + (BYTE)Random () % 10 + ); + + GeneratorPtr->preprocess_func = generator_preprocess; + GeneratorPtr->collision_func = generator_collision; + GeneratorPtr->death_func = generator_death; + + SetElementStarShip (GeneratorPtr, StarShipPtr); + UnlockElement (hGenerator); + + InsertElement (hGenerator, GetHeadElement ()); + } + } + + { + HELEMENT hTurret; + + hTurret = AllocElement (); + if (hTurret) + { + ELEMENTPTR TurretPtr; + + LockElement (hTurret, &TurretPtr); + TurretPtr->hit_points = 1; + TurretPtr->life_span = NORMAL_LIFE; + TurretPtr->state_flags = + APPEARING | BAD_GUY | IGNORE_SIMILAR | NONSOLID; + SetPrimType ( + &GLOBAL (DisplayArray[TurretPtr->PrimIndex]), + STAMP_PRIM + ); + TurretPtr->current.location.x = LOG_SPACE_WIDTH >> 1; + TurretPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; + TurretPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.ship; + TurretPtr->current.image.frame = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship[0], 1 + ); + + TurretPtr->preprocess_func = turret_preprocess; + + SetElementStarShip (TurretPtr, StarShipPtr); + UnlockElement (hTurret); + + InsertElement (hTurret, GetSuccElement (ElementPtr)); + } + } + + { + HELEMENT hGate; + + hGate = AllocElement (); + if (hGate) + { + ELEMENTPTR GatePtr; + + LockElement (hGate, &GatePtr); + GatePtr->hit_points = GATE_HITS; + GatePtr->mass_points = GATE_DAMAGE; + GatePtr->life_span = 2; + GatePtr->state_flags = + APPEARING | FINITE_LIFE | BAD_GUY | IGNORE_SIMILAR; + SetPrimType ( + &GLOBAL (DisplayArray[GatePtr->PrimIndex]), + STAMP_PRIM + ); + GatePtr->current.location.x = LOG_SPACE_WIDTH >> 1; + GatePtr->current.location.y = LOG_SPACE_HEIGHT >> 1; + GatePtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.ship; + GatePtr->current.image.frame = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship[0], 11 + ); + + GatePtr->preprocess_func = gate_preprocess; + GatePtr->collision_func = gate_collision; + + SetElementStarShip (GatePtr, StarShipPtr); + UnlockElement (hGate); + + InsertElement (hGate, GetSuccElement (ElementPtr)); + } + } + + StarShipPtr->weapon_counter = WEAPON_WAIT >> 1; + StarShipPtr->special_counter = SPECIAL_WAIT >> 1; + } +} + +RACE_DESCPTR +init_samatra () +{ + RACE_DESCPTR RaceDescPtr; + + samatra_desc.preprocess_func = samatra_preprocess; + samatra_desc.postprocess_func = samatra_postprocess; + samatra_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) samatra_intelligence; + + RaceDescPtr = &samatra_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/lastbat/lastbat.res b/sc2/src/sc2code/ships/lastbat/lastbat.res new file mode 100644 index 000000000..25c2845a6 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/lastbat.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH lastbat + +PACKAGE SAMATRA_CODE_PACKAGE lastbat.sc2 + CODE SAMATRA_CODE lastbat.cod + +PACKAGE SAMATRA_PACKAGE lastbat.sc2 + GFXRES SAMATRA_BIG_MASK_ANIM lastbat.big + GFXRES SAMATRA_MED_MASK_PMAP_ANIM lastbat.med + GFXRES SAMATRA_SML_MASK_PMAP_ANIM lastbat.sml + GFXRES SENTINEL_BIG_MASK_ANIM senbig.ani + GFXRES SENTINEL_MED_MASK_PMAP_ANIM senmed.ani + GFXRES SENTINEL_SML_MASK_PMAP_ANIM sensml.ani + GFXRES GENERATOR_BIG_MASK_ANIM genbig.ani + GFXRES GENERATOR_MED_MASK_PMAP_ANIM genmed.ani + GFXRES GENERATOR_SML_MASK_PMAP_ANIM gensml.ani + + SNDRES SAMATRA_SHIP_SOUNDS lassound.snd + +PACKAGE SAMATRA_STATUS_PACKAGE lastbat.sc2 + GFXRES SAMATRA_CAPTAIN_MASK_PMAP_ANIM lascap.ani + diff --git a/sc2/src/sc2code/ships/lastbat/resinst.h b/sc2/src/sc2code/ships/lastbat/resinst.h new file mode 100644 index 000000000..17ee6ae6e --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/resinst.h @@ -0,0 +1,3 @@ +#include "igfxres.h" +#include "isndres.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/lastbat/respkg.h b/sc2/src/sc2code/ships/lastbat/respkg.h new file mode 100644 index 000000000..e60b0bf2f --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/respkg.h @@ -0,0 +1,7 @@ +enum +{ + SAMATRA_CODE_PACKAGE = 1, + SAMATRA_PACKAGE, + SAMATRA_STATUS_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/lastbat/restypes.h b/sc2/src/sc2code/ships/lastbat/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/lastbat/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/melnorme/icode.h b/sc2/src/sc2code/ships/melnorme/icode.h new file mode 100644 index 000000000..5871ddfc8 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/icode.h @@ -0,0 +1,3 @@ +#define MELNORME_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/melnorme/igfxres.h b/sc2/src/sc2code/ships/melnorme/igfxres.h new file mode 100644 index 000000000..5fbeb77e8 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/igfxres.h @@ -0,0 +1,14 @@ +#define MELNORME_ICON_MASK_PMAP_ANIM 0x00200002L +#define MELNORME_MICON_MASK_PMAP_ANIM 0x00200102L +#define MELNORME_BIG_MASK_PMAP_ANIM 0x00400202L +#define MELNORME_MED_MASK_PMAP_ANIM 0x00400302L +#define MELNORME_SML_MASK_PMAP_ANIM 0x00400402L +#define PUMPUP_BIG_MASK_PMAP_ANIM 0x00400502L +#define PUMPUP_MED_MASK_PMAP_ANIM 0x00400602L +#define PUMPUP_SML_MASK_PMAP_ANIM 0x00400702L +#define CONFUSE_BIG_MASK_PMAP_ANIM 0x00400802L +#define CONFUSE_MED_MASK_PMAP_ANIM 0x00400902L +#define CONFUSE_SML_MASK_PMAP_ANIM 0x00400a02L +#define MELNORME_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/melnorme/imusicre.h b/sc2/src/sc2code/ships/melnorme/imusicre.h new file mode 100644 index 000000000..0d151f299 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/imusicre.h @@ -0,0 +1,3 @@ +#define MELNORME_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/melnorme/isndres.h b/sc2/src/sc2code/ships/melnorme/isndres.h new file mode 100644 index 000000000..96fbb872b --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/isndres.h @@ -0,0 +1,3 @@ +#define MELNORME_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/melnorme/istrtab.h b/sc2/src/sc2code/ships/melnorme/istrtab.h new file mode 100644 index 000000000..7efd6a8e0 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/istrtab.h @@ -0,0 +1,3 @@ +#define MELNORME_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/melnorme/melnorme.c b/sc2/src/sc2code/ships/melnorme/melnorme.c new file mode 100644 index 000000000..aabcbeaf3 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/melnorme.c @@ -0,0 +1,655 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/melnorme/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 5 +#define SPECIAL_ENERGY_COST 20 +#define ENERGY_WAIT 4 +#define MAX_THRUST 36 +#define THRUST_INCREMENT 6 +#define TURN_WAIT 4 +#define THRUST_WAIT 4 +#define WEAPON_WAIT 1 +#define SPECIAL_WAIT 20 + +#define SHIP_MASS 7 +#define PUMPUP_SPEED DISPLAY_TO_WORLD (45) +#define PUMPUP_LIFE 10 + +static RACE_DESC melnorme_desc = +{ + { + FIRES_FORE, + 18, /* Super Melee cost */ + ~0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, + }, + (STRING)MELNORME_RACE_STRINGS, + (FRAME)MELNORME_ICON_MASK_PMAP_ANIM, + (FRAME)MELNORME_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)MELNORME_BIG_MASK_PMAP_ANIM, + (FRAME)MELNORME_MED_MASK_PMAP_ANIM, + (FRAME)MELNORME_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)PUMPUP_BIG_MASK_PMAP_ANIM, + (FRAME)PUMPUP_MED_MASK_PMAP_ANIM, + (FRAME)PUMPUP_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)CONFUSE_BIG_MASK_PMAP_ANIM, + (FRAME)CONFUSE_MED_MASK_PMAP_ANIM, + (FRAME)CONFUSE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)MELNORME_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)MELNORME_VICTORY_SONG, + (SOUND)MELNORME_SHIP_SOUNDS, + }, + { + 0, + PUMPUP_SPEED * PUMPUP_LIFE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define NUM_PUMP_ANIMS 5 +#define REVERSE_DIR (BYTE)(1 << 7) + +static void +pump_up_preprocess (PELEMENT ElementPtr) +{ + if (--ElementPtr->thrust_wait & 1) + { + COUNT frame_index; + + frame_index = GetFrameIndex (ElementPtr->current.image.frame); + if (((ElementPtr->turn_wait & REVERSE_DIR) + && (frame_index % NUM_PUMP_ANIMS) != 0) + || (!(ElementPtr->turn_wait & REVERSE_DIR) + && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) + { + --frame_index; + ElementPtr->turn_wait |= REVERSE_DIR; + } + else + { + ++frame_index; + ElementPtr->turn_wait &= ~REVERSE_DIR; + } + + ElementPtr->next.image.frame = SetAbsFrameIndex ( + ElementPtr->current.image.frame, frame_index + ); + + ElementPtr->state_flags |= CHANGING; + } +} + +static COUNT initialize_pump_up (PELEMENT ShipPtr, HELEMENT + PumpUpArray[]); + +#define MELNORME_OFFSET 24 +#define LEVEL_COUNTER 72 +#define MAX_PUMP 4 +#define PUMPUP_DAMAGE 2 + +static void +pump_up_postprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & APPEARING) + { + ZeroVelocityComponents (&ElementPtr->velocity); + } + else + { + HELEMENT hPumpUp; + ELEMENTPTR EPtr, ShipPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipPtr); + initialize_pump_up (ShipPtr, &hPumpUp); + DeltaEnergy (ShipPtr, 0); + UnlockElement (StarShipPtr->hShip); + + LockElement (hPumpUp, &EPtr); + + EPtr->current.image.frame = ElementPtr->current.image.frame; + EPtr->turn_wait = ElementPtr->turn_wait; + EPtr->thrust_wait = ElementPtr->thrust_wait; + if (--EPtr->thrust_wait == 0) + { + if ((EPtr->turn_wait & ~REVERSE_DIR) < MAX_PUMP - 1) + { + ++EPtr->turn_wait; + EPtr->current.image.frame = SetRelFrameIndex ( + EPtr->current.image.frame, NUM_PUMP_ANIMS + ); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + } + EPtr->thrust_wait = LEVEL_COUNTER; + } + + EPtr->mass_points = EPtr->hit_points = + (PUMPUP_DAMAGE << (ElementPtr->turn_wait & ~REVERSE_DIR)); + SetElementStarShip (EPtr, StarShipPtr); + + if (EPtr->thrust_wait & 1) + { + COUNT frame_index; + + frame_index = GetFrameIndex (EPtr->current.image.frame); + if (((EPtr->turn_wait & REVERSE_DIR) + && (frame_index % NUM_PUMP_ANIMS) != 0) + || (!(EPtr->turn_wait & REVERSE_DIR) + && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) + { + --frame_index; + EPtr->turn_wait |= REVERSE_DIR; + } + else + { + ++frame_index; + EPtr->turn_wait &= ~REVERSE_DIR; + } + + EPtr->current.image.frame = SetAbsFrameIndex ( + EPtr->current.image.frame, frame_index + ); + } + + if (StarShipPtr->cur_status_flags + & StarShipPtr->old_status_flags + & WEAPON) + { + StarShipPtr->weapon_counter = WEAPON_WAIT; + } + else + { + COUNT angle; + + EPtr->life_span = PUMPUP_LIFE; + EPtr->preprocess_func = pump_up_preprocess; + EPtr->postprocess_func = 0; + + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + SetVelocityComponents (&EPtr->velocity, + COSINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED)), + SINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED))); + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3)); + } + + UnlockElement (hPumpUp); + PutElement (hPumpUp); + + SetPrimType ( + &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + NO_PRIM + ); + ElementPtr->state_flags |= NONSOLID; + } +} + +static void +animate (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +pump_up_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + RECT r; + BYTE old_thrust_wait; + HELEMENT hBlastElement; + + GetFrameRect (ElementPtr0->next.image.frame, &r); + + old_thrust_wait = ElementPtr0->thrust_wait; + ElementPtr0->blast_offset = r.extent.width >> 1; + hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->thrust_wait = old_thrust_wait; + + if (hBlastElement) + { + ELEMENTPTR BlastElementPtr; + +#define MIN_PUMPITUDE_ANIMS 3 + LockElement (hBlastElement, &BlastElementPtr); + + BlastElementPtr->life_span = + MIN_PUMPITUDE_ANIMS + + (ElementPtr0->turn_wait & ~REVERSE_DIR); + BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; + { + BlastElementPtr->preprocess_func = animate; + } + + BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], + MAX_PUMP * NUM_PUMP_ANIMS); + + UnlockElement (hBlastElement); + } +} + +static COUNT +initialize_pump_up (PELEMENT ShipPtr, HELEMENT PumpUpArray[]) +{ + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = MELNORME_OFFSET; + MissileBlock.speed = DISPLAY_TO_WORLD (MELNORME_OFFSET); + MissileBlock.hit_points = PUMPUP_DAMAGE; + MissileBlock.damage = PUMPUP_DAMAGE; + MissileBlock.life = 2; + MissileBlock.preprocess_func = 0; + MissileBlock.blast_offs = 0; + PumpUpArray[0] = initialize_missile (&MissileBlock); + + if (PumpUpArray[0]) + { + ELEMENTPTR PumpUpPtr; + + LockElement (PumpUpArray[0], &PumpUpPtr); + PumpUpPtr->postprocess_func = pump_up_postprocess; + PumpUpPtr->collision_func = pump_up_collision; + PumpUpPtr->thrust_wait = LEVEL_COUNTER; + UnlockElement (PumpUpArray[0]); + } + + return (1); +} + +static void +confuse_preprocess (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & NONSOLID)) + { + ElementPtr->next.image.frame = SetAbsFrameIndex ( + ElementPtr->current.image.frame, + (GetFrameIndex (ElementPtr->current.image.frame) + 1) & 7 + ); + ElementPtr->state_flags |= CHANGING; + } + else if (ElementPtr->hTarget == 0) + { + ElementPtr->life_span = 0; + ElementPtr->state_flags |= DISAPPEARING; + } + else + { + ELEMENTPTR eptr; + + LockElement (ElementPtr->hTarget, &eptr); + + ElementPtr->next.location = eptr->next.location; + + if (ElementPtr->turn_wait) + { + HELEMENT hEffect; + STARSHIPPTR StarShipPtr; + + if (GetFrameIndex (ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame)) == 0) + ElementPtr->next.image.frame = + SetRelFrameIndex (ElementPtr->next.image.frame, -8); + + GetElementStarShip (eptr, &StarShipPtr); + StarShipPtr->ship_input_state = + (StarShipPtr->ship_input_state + & ~(LEFT | RIGHT | SPECIAL)) + | ElementPtr->turn_wait; + + hEffect = AllocElement (); + if (hEffect) + { + LockElement (hEffect, &eptr); + + eptr->state_flags = FINITE_LIFE | NONSOLID | CHANGING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + eptr->life_span = 1; + eptr->current = eptr->next = ElementPtr->next; + eptr->preprocess_func = confuse_preprocess; + SetPrimType ( + &(GLOBAL (DisplayArray))[eptr->PrimIndex], + STAMP_PRIM + ); + + GetElementStarShip (ElementPtr, &StarShipPtr); + SetElementStarShip (eptr, StarShipPtr); + eptr->hTarget = ElementPtr->hTarget; + + UnlockElement (hEffect); + PutElement (hEffect); + } + } + + UnlockElement (ElementPtr->hTarget); + } +} + +static void +confusion_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr1->state_flags & PLAYER_SHIP) + { + HELEMENT hConfusionElement, hNextElement; + ELEMENTPTR ConfusionPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + for (hConfusionElement = GetHeadElement (); + hConfusionElement; hConfusionElement = hNextElement) + { + LockElement (hConfusionElement, &ConfusionPtr); + if ((ConfusionPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) + && ConfusionPtr->current.image.farray == + StarShipPtr->RaceDescPtr->ship_data.special + && (ConfusionPtr->state_flags & NONSOLID)) + { + UnlockElement (hConfusionElement); + break; + } + hNextElement = GetSuccElement (ConfusionPtr); + UnlockElement (hConfusionElement); + } + + if (hConfusionElement || (hConfusionElement = AllocElement ())) + { + LockElement (hConfusionElement, &ConfusionPtr); + + if (ConfusionPtr->state_flags == 0) /* not allocated before */ + { + InsertElement (hConfusionElement, GetHeadElement ()); + + ConfusionPtr->current = ElementPtr0->next; + ConfusionPtr->current.image.frame = SetAbsFrameIndex ( + ConfusionPtr->current.image.frame, 8 + ); + ConfusionPtr->next = ConfusionPtr->current; + ConfusionPtr->state_flags = FINITE_LIFE | NONSOLID | CHANGING + | (ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)); + ConfusionPtr->preprocess_func = confuse_preprocess; + SetPrimType ( + &(GLOBAL (DisplayArray))[ConfusionPtr->PrimIndex], + NO_PRIM + ); + + SetElementStarShip (ConfusionPtr, StarShipPtr); + GetElementStarShip (ElementPtr1, &StarShipPtr); + ConfusionPtr->hTarget = StarShipPtr->hShip; + } + + ConfusionPtr->life_span = 400; + ConfusionPtr->turn_wait = + (BYTE)(1 << ((BYTE)Random () & 1)); /* LEFT or RIGHT */ + + UnlockElement (hConfusionElement); + } + + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + ElementPtr0->state_flags |= DISAPPEARING | COLLISION | NONSOLID; + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static COUNT +initialize_confusion (PELEMENT ShipPtr, HELEMENT ConfusionArray[]) +{ +#define CMISSILE_SPEED DISPLAY_TO_WORLD (30) +#define CMISSILE_HITS 200 +#define CMISSILE_DAMAGE 0 +#define CMISSILE_LIFE 20 +#define CMISSILE_OFFSET 4 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK ConfusionBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + ConfusionBlock.cx = ShipPtr->next.location.x; + ConfusionBlock.cy = ShipPtr->next.location.y; + ConfusionBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + ConfusionBlock.index = 0; + ConfusionBlock.face = StarShipPtr->ShipFacing; + ConfusionBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + ConfusionBlock.pixoffs = MELNORME_OFFSET; + ConfusionBlock.speed = CMISSILE_SPEED; + ConfusionBlock.hit_points = CMISSILE_HITS; + ConfusionBlock.damage = CMISSILE_DAMAGE; + ConfusionBlock.life = CMISSILE_LIFE; + ConfusionBlock.preprocess_func = confuse_preprocess; + ConfusionBlock.blast_offs = CMISSILE_OFFSET; + ConfusionArray[0] = initialize_missile (&ConfusionBlock); + + if (ConfusionArray[0]) + { + ELEMENTPTR CMissilePtr; + + LockElement (ConfusionArray[0], &CMissilePtr); + CMissilePtr->collision_func = confusion_collision; + SetElementStarShip (CMissilePtr, StarShipPtr); + UnlockElement (ConfusionArray[0]); + } + return (1); +} + +static COUNT +initialize_test_pump_up (PELEMENT ShipPtr, HELEMENT PumpUpArray[]) +{ + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + //ELEMENTPTR PumpUpPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = MELNORME_OFFSET; + MissileBlock.speed = PUMPUP_SPEED; + MissileBlock.hit_points = PUMPUP_DAMAGE; + MissileBlock.damage = PUMPUP_DAMAGE; + MissileBlock.life = PUMPUP_LIFE; + MissileBlock.preprocess_func = 0; + MissileBlock.blast_offs = 0; + PumpUpArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +melnorme_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + COUNT old_count; + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + StarShipPtr->RaceDescPtr->init_weapon_func = initialize_test_pump_up; + old_count = StarShipPtr->weapon_counter; + + if (StarShipPtr->weapon_counter == WEAPON_WAIT) + StarShipPtr->weapon_counter = 0; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST + + WEAPON_ENERGY_COST + && !(StarShipPtr->old_status_flags & WEAPON)) + lpEvalDesc->MoveState = ENTICE; + else + { + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & IMMEDIATE_WEAPON)) + lpEvalDesc->MoveState = PURSUE; + } + } + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->weapon_counter == 0 + && (old_count != 0 + || ((StarShipPtr->special_counter + || StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST + + WEAPON_ENERGY_COST) + && !(StarShipPtr->ship_input_state & WEAPON)))) + StarShipPtr->ship_input_state ^= WEAPON; + + StarShipPtr->ship_input_state &= ~SPECIAL; + if (StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) + { + BYTE old_input_state; + + old_input_state = StarShipPtr->ship_input_state; + + StarShipPtr->RaceDescPtr->init_weapon_func = initialize_confusion; + + ++ShipPtr->turn_wait; + ++ShipPtr->thrust_wait; + ship_intelligence (ShipPtr, ObjectsOfConcern, ENEMY_SHIP_INDEX + 1); + --ShipPtr->thrust_wait; + --ShipPtr->turn_wait; + + if (StarShipPtr->ship_input_state & WEAPON) + { + StarShipPtr->ship_input_state &= ~WEAPON; + StarShipPtr->ship_input_state |= SPECIAL; + } + + StarShipPtr->ship_input_state = (unsigned char)(old_input_state + | (StarShipPtr->ship_input_state & SPECIAL)); + } + + StarShipPtr->weapon_counter = old_count; + + StarShipPtr->RaceDescPtr->init_weapon_func = initialize_pump_up; +} + +static void +melnorme_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + HELEMENT Confusion; + + initialize_confusion (ElementPtr, &Confusion); + if (Confusion) + { + PutElement (Confusion); + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + } +} + +RACE_DESCPTR +init_melnorme () +{ + RACE_DESCPTR RaceDescPtr; + + melnorme_desc.postprocess_func = melnorme_postprocess; + melnorme_desc.init_weapon_func = initialize_pump_up; + melnorme_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) melnorme_intelligence; + + RaceDescPtr = &melnorme_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/melnorme/melnorme.res b/sc2/src/sc2code/ships/melnorme/melnorme.res new file mode 100644 index 000000000..dc7629033 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/melnorme.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH melnorme + +PACKAGE MELNORME_CODE_PACKAGE melnorme.shp + CODE MELNORME_CODE melnorme.cod + GFXRES MELNORME_ICON_MASK_PMAP_ANIM melicons.ani + GFXRES MELNORME_MICON_MASK_PMAP_ANIM melmicon.ani + STRTAB MELNORME_RACE_STRINGS meltext.txt + +PACKAGE MELNORME_PACKAGE melnorme.shp + GFXRES MELNORME_BIG_MASK_PMAP_ANIM melnorme.big + GFXRES MELNORME_MED_MASK_PMAP_ANIM melnorme.med + GFXRES MELNORME_SML_MASK_PMAP_ANIM melnorme.sml + GFXRES PUMPUP_BIG_MASK_PMAP_ANIM pumpbig.ani + GFXRES PUMPUP_MED_MASK_PMAP_ANIM pumpmed.ani + GFXRES PUMPUP_SML_MASK_PMAP_ANIM pumpsml.ani + GFXRES CONFUSE_BIG_MASK_PMAP_ANIM confubig.ani + GFXRES CONFUSE_MED_MASK_PMAP_ANIM confumed.ani + GFXRES CONFUSE_SML_MASK_PMAP_ANIM confusml.ani + + GFXRES MELNORME_CAPTAIN_MASK_PMAP_ANIM melcap.ani + SNDRES MELNORME_SHIP_SOUNDS melsound.snd + + MUSICRES MELNORME_VICTORY_SONG melditty.mod + diff --git a/sc2/src/sc2code/ships/melnorme/resinst.h b/sc2/src/sc2code/ships/melnorme/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/melnorme/respkg.h b/sc2/src/sc2code/ships/melnorme/respkg.h new file mode 100644 index 000000000..a2bf4c206 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/respkg.h @@ -0,0 +1,6 @@ +enum +{ + MELNORME_CODE_PACKAGE = 1, + MELNORME_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/melnorme/restypes.h b/sc2/src/sc2code/ships/melnorme/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/melnorme/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/icode.h b/sc2/src/sc2code/ships/mmrnmhrm/icode.h new file mode 100644 index 000000000..80f8e7128 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/icode.h @@ -0,0 +1,3 @@ +#define MMRNMHRM_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/igfxres.h b/sc2/src/sc2code/ships/mmrnmhrm/igfxres.h new file mode 100644 index 000000000..4d728f51d --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/igfxres.h @@ -0,0 +1,14 @@ +#define MMRNMHRM_ICON_MASK_PMAP_ANIM 0x00200002L +#define MMRNMHRM_MICON_MASK_PMAP_ANIM 0x00200102L +#define MMRNMHRM_BIG_MASK_PMAP_ANIM 0x00400202L +#define MMRNMHRM_MED_MASK_PMAP_ANIM 0x00400302L +#define MMRNMHRM_SML_MASK_PMAP_ANIM 0x00400402L +#define TORP_BIG_MASK_PMAP_ANIM 0x00400502L +#define TORP_MED_MASK_PMAP_ANIM 0x00400602L +#define TORP_SML_MASK_PMAP_ANIM 0x00400702L +#define YWING_BIG_MASK_PMAP_ANIM 0x00400802L +#define YWING_MED_MASK_PMAP_ANIM 0x00400902L +#define YWING_SML_MASK_PMAP_ANIM 0x00400a02L +#define MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/imusicre.h b/sc2/src/sc2code/ships/mmrnmhrm/imusicre.h new file mode 100644 index 000000000..9302899ba --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/imusicre.h @@ -0,0 +1,3 @@ +#define MMRNMHRM_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/isndres.h b/sc2/src/sc2code/ships/mmrnmhrm/isndres.h new file mode 100644 index 000000000..4d9a27a45 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/isndres.h @@ -0,0 +1,3 @@ +#define MMRNMHRM_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/istrtab.h b/sc2/src/sc2code/ships/mmrnmhrm/istrtab.h new file mode 100644 index 000000000..f6f0720c6 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/istrtab.h @@ -0,0 +1,3 @@ +#define MMRNMHRM_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.c b/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.c new file mode 100644 index 000000000..72114be26 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.c @@ -0,0 +1,470 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/mmrnmhrm/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 10 +#define ENERGY_REGENERATION 2 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST MAX_ENERGY +#define ENERGY_WAIT 6 +#define MAX_THRUST 20 +#define THRUST_INCREMENT 5 +#define TURN_WAIT 2 +#define THRUST_WAIT 1 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 0 + +#define YWING_ENERGY_REGENERATION 1 +#define YWING_WEAPON_ENERGY_COST 1 +#define YWING_SPECIAL_ENERGY_COST MAX_ENERGY +#define YWING_ENERGY_WAIT 6 +#define YWING_MAX_THRUST 50 +#define YWING_THRUST_INCREMENT 10 +#define YWING_TURN_WAIT 14 +#define YWING_THRUST_WAIT 0 +#define YWING_WEAPON_WAIT 20 +#define YWING_SPECIAL_WAIT 0 + +#define SHIP_MASS 3 +#define MMRNMHRM_OFFSET 16 +#define LASER_RANGE DISPLAY_TO_WORLD (125 + MMRNMHRM_OFFSET) + +static CHARACTERISTIC_STUFF otherwing_desc[NUM_SIDES]; + +static RACE_DESC mmrnmhrm_desc = +{ + { + FIRES_FORE | IMMEDIATE_WEAPON, + 19, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)MMRNMHRM_RACE_STRINGS, + (FRAME)MMRNMHRM_ICON_MASK_PMAP_ANIM, + (FRAME)MMRNMHRM_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)MMRNMHRM_BIG_MASK_PMAP_ANIM, + (FRAME)MMRNMHRM_MED_MASK_PMAP_ANIM, + (FRAME)MMRNMHRM_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)TORP_BIG_MASK_PMAP_ANIM, + (FRAME)TORP_MED_MASK_PMAP_ANIM, + (FRAME)TORP_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)YWING_BIG_MASK_PMAP_ANIM, + (FRAME)YWING_MED_MASK_PMAP_ANIM, + (FRAME)YWING_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)MMRNMHRM_VICTORY_SONG, + (SOUND)MMRNMHRM_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define MISSILE_SPEED DISPLAY_TO_WORLD (20) +#define TRACK_WAIT 5 + +static void +missile_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT facing; + + facing = GetFrameIndex (ElementPtr->next.image.frame); + if (TrackShip (ElementPtr, &facing) > 0) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + facing); + ElementPtr->state_flags |= CHANGING; + + SetVelocityVector (&ElementPtr->velocity, + MISSILE_SPEED, facing); + } + + ElementPtr->turn_wait = TRACK_WAIT; + } +} + +static void +mmrnmhrm_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + BOOLEAN CanTransform; + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + CanTransform = (BOOLEAN)(StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= + StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + StarShipPtr->ship_input_state &= ~SPECIAL; + if (CanTransform + && lpEvalDesc->ObjectPtr + && !(StarShipPtr->ship_input_state & WEAPON)) + { + SIZE delta_x, delta_y; + COUNT travel_angle, direction_angle; + + GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, + &delta_x, &delta_y); + if (delta_x == 0 && delta_y == 0) + direction_angle = travel_angle = 0; + else + { + delta_x = lpEvalDesc->ObjectPtr->current.location.x + - ShipPtr->current.location.x; + delta_y = lpEvalDesc->ObjectPtr->current.location.y + - ShipPtr->current.location.y; + direction_angle = ARCTAN (-delta_x, -delta_y); + travel_angle = GetVelocityTravelAngle ( + &lpEvalDesc->ObjectPtr->velocity + ); + } + + if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) + { + if (lpEvalDesc->which_turn > 8) + { + if (MANEUVERABILITY (&EnemyStarShipPtr->RaceDescPtr->cyborg_control) <= SLOW_SHIP + || NORMALIZE_ANGLE ( + direction_angle - travel_angle + QUADRANT + ) > HALF_CIRCLE) + StarShipPtr->ship_input_state |= SPECIAL; + } + } + else + { + SIZE ship_delta_x, ship_delta_y; + + GetCurrentVelocityComponents (&ShipPtr->velocity, + &ship_delta_x, &ship_delta_y); + delta_x -= ship_delta_x; + delta_y -= ship_delta_y; + travel_angle = ARCTAN (delta_x, delta_y); + if (lpEvalDesc->which_turn < 16) + { + if (lpEvalDesc->which_turn <= 8 + || NORMALIZE_ANGLE ( + direction_angle - travel_angle + OCTANT + ) <= QUADRANT) + StarShipPtr->ship_input_state |= SPECIAL; + } + else if (lpEvalDesc->which_turn > 32 + && NORMALIZE_ANGLE ( + direction_angle - travel_angle + QUADRANT + ) > HALF_CIRCLE) + StarShipPtr->ship_input_state |= SPECIAL; + } + } + + if (ShipPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) + { + if (!(StarShipPtr->ship_input_state & SPECIAL) + && lpEvalDesc->ObjectPtr) + StarShipPtr->ship_input_state |= WEAPON; + else + StarShipPtr->ship_input_state &= ~WEAPON; + } +} + +static void +twin_laser_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (!(ElementPtr1->state_flags & PLAYER_SHIP) + || !(ElementPtr0->state_flags & ElementPtr1->state_flags + & (GOOD_GUY | BAD_GUY))) + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +static COUNT +initialize_dual_weapons (PELEMENT ShipPtr, HELEMENT WeaponArray[]) +{ +#define CENTER_OFFS DISPLAY_TO_WORLD (4) + COORD cx, cy; + COUNT facing, angle; + SIZE offs_x, offs_y; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + facing = StarShipPtr->ShipFacing; + angle = FACING_TO_ANGLE (facing); + cx = ShipPtr->next.location.x + COSINE (angle, CENTER_OFFS); + cy = ShipPtr->next.location.y + SINE (angle, CENTER_OFFS); + + if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) + { +#define WING_OFFS DISPLAY_TO_WORLD (10) + COORD ex, ey; + LASER_BLOCK LaserBlock; + ELEMENTPTR LaserPtr; + + LaserBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); + LaserBlock.pixoffs = 0; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C); + LaserBlock.face = facing; + + ex = cx + COSINE (angle, LASER_RANGE); + ey = cy + SINE (angle, LASER_RANGE); + offs_x = -SINE (angle, WING_OFFS); + offs_y = COSINE (angle, WING_OFFS); + + LaserBlock.cx = cx + offs_x; + LaserBlock.cy = cy + offs_y; + LaserBlock.ex = ex - LaserBlock.cx; + LaserBlock.ey = ey - LaserBlock.cy; + if ((WeaponArray[0] = initialize_laser (&LaserBlock))) + { + LockElement (WeaponArray[0], &LaserPtr); + LaserPtr->collision_func = twin_laser_collision; + UnlockElement (WeaponArray[0]); + } + + LaserBlock.cx = cx - offs_x; + LaserBlock.cy = cy - offs_y; + LaserBlock.ex = ex - LaserBlock.cx; + LaserBlock.ey = ey - LaserBlock.cy; + if ((WeaponArray[1] = initialize_laser (&LaserBlock))) + { + LockElement (WeaponArray[1], &LaserPtr); + LaserPtr->collision_func = twin_laser_collision; + UnlockElement (WeaponArray[1]); + } + } + else + { +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 0 +#define MISSILE_LIFE 40 +#define LAUNCH_OFFS DISPLAY_TO_WORLD (4) + MISSILE_BLOCK TorpBlock; + ELEMENTPTR TorpPtr; + + TorpBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + TorpBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + TorpBlock.pixoffs = 0; + TorpBlock.speed = MISSILE_SPEED; + TorpBlock.hit_points = MISSILE_HITS; + TorpBlock.damage = MISSILE_DAMAGE; + TorpBlock.life = MISSILE_LIFE; + TorpBlock.preprocess_func = missile_preprocess; + TorpBlock.blast_offs = MISSILE_OFFSET; + + TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing - 1); + offs_x = -SINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); + offs_y = COSINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); + + TorpBlock.cx = cx + offs_x; + TorpBlock.cy = cy + offs_y; + if ((WeaponArray[0] = initialize_missile (&TorpBlock))) + { + LockElement (WeaponArray[0], &TorpPtr); + TorpPtr->turn_wait = TRACK_WAIT; + UnlockElement (WeaponArray[0]); + } + + TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing + 1); + + TorpBlock.cx = cx - offs_x; + TorpBlock.cy = cy - offs_y; + if ((WeaponArray[1] = initialize_missile (&TorpBlock))) + { + LockElement (WeaponArray[1], &TorpPtr); + TorpPtr->turn_wait = TRACK_WAIT; + UnlockElement (WeaponArray[1]); + } + } + + return (2); +} + +static void +mmrnmhrm_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + /* take care of transform effect */ + if (ElementPtr->next.image.farray != ElementPtr->current.image.farray) + { + CHARACTERISTIC_STUFF t; + + ProcessSound (SetAbsSoundIndex ( + /* TRANSFORM */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + DeltaEnergy (ElementPtr, + -StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); + + StarShipPtr->weapon_counter = 0; + + t = otherwing_desc[WHICH_SIDE(ElementPtr->state_flags)]; + otherwing_desc[WHICH_SIDE(ElementPtr->state_flags)] = StarShipPtr->RaceDescPtr->characteristics; + StarShipPtr->RaceDescPtr->characteristics = t; + StarShipPtr->RaceDescPtr->cyborg_control.ManeuverabilityIndex = 0; + + if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) + { + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = LONG_RANGE_WEAPON - 1; + StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~IMMEDIATE_WEAPON; + StarShipPtr->RaceDescPtr->ship_info.ship_flags |= SEEKING_WEAPON; + StarShipPtr->RaceDescPtr->ship_data.ship_sounds = + SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2); + + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + } + else + { + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; + StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~SEEKING_WEAPON; + StarShipPtr->RaceDescPtr->ship_info.ship_flags |= IMMEDIATE_WEAPON; + StarShipPtr->RaceDescPtr->ship_data.ship_sounds = + SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 0); + + if (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + StarShipPtr->cur_status_flags |= + SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED; + } + } +} + +static void +mmrnmhrm_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & APPEARING) + { + COUNT i; + + i = WHICH_SIDE (ElementPtr->state_flags); + otherwing_desc[i].max_thrust = YWING_MAX_THRUST; + otherwing_desc[i].thrust_increment = YWING_THRUST_INCREMENT; + otherwing_desc[i].energy_regeneration = YWING_ENERGY_REGENERATION; + otherwing_desc[i].weapon_energy_cost = YWING_WEAPON_ENERGY_COST; + otherwing_desc[i].special_energy_cost = YWING_SPECIAL_ENERGY_COST; + otherwing_desc[i].energy_wait = YWING_ENERGY_WAIT; + otherwing_desc[i].turn_wait = YWING_TURN_WAIT; + otherwing_desc[i].thrust_wait = YWING_THRUST_WAIT; + otherwing_desc[i].weapon_wait = YWING_WEAPON_WAIT; + otherwing_desc[i].special_wait = YWING_SPECIAL_WAIT; + otherwing_desc[i].ship_mass = SHIP_MASS; + } + else + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0) + { + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < + StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) + DeltaEnergy (ElementPtr, + -StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); /* so text will flash */ + else + { + if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + else + ElementPtr->next.image.farray = + StarShipPtr->RaceDescPtr->ship_data.ship; + ElementPtr->next.image.frame = + SetEquFrameIndex (ElementPtr->next.image.farray[0], + ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + } + } +} + +RACE_DESCPTR +init_mmrnmhrm () +{ + RACE_DESCPTR RaceDescPtr; + + mmrnmhrm_desc.preprocess_func = mmrnmhrm_preprocess; + mmrnmhrm_desc.postprocess_func = mmrnmhrm_postprocess; + mmrnmhrm_desc.init_weapon_func = initialize_dual_weapons; + mmrnmhrm_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) mmrnmhrm_intelligence; + + RaceDescPtr = &mmrnmhrm_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.res b/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.res new file mode 100644 index 000000000..2f48ffd3c --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH mmrnmhrm + +PACKAGE MMRNMHRM_CODE_PACKAGE mmrnmhrm.shp + CODE MMRNMHRM_CODE mmrnmhrm.cod + GFXRES MMRNMHRM_ICON_MASK_PMAP_ANIM mmricons.ani + GFXRES MMRNMHRM_MICON_MASK_PMAP_ANIM mmrmicon.ani + STRTAB MMRNMHRM_RACE_STRINGS mmrtext.txt + +PACKAGE MMRNMHRM_PACKAGE mmrnmhrm.shp + GFXRES MMRNMHRM_BIG_MASK_PMAP_ANIM mmrnmhrm.big + GFXRES MMRNMHRM_MED_MASK_PMAP_ANIM mmrnmhrm.med + GFXRES MMRNMHRM_SML_MASK_PMAP_ANIM mmrnmhrm.sml + GFXRES TORP_BIG_MASK_PMAP_ANIM torp.big + GFXRES TORP_MED_MASK_PMAP_ANIM torp.med + GFXRES TORP_SML_MASK_PMAP_ANIM torp.sml + GFXRES YWING_BIG_MASK_PMAP_ANIM ywing.big + GFXRES YWING_MED_MASK_PMAP_ANIM ywing.med + GFXRES YWING_SML_MASK_PMAP_ANIM ywing.sml + + GFXRES MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM mmrcap.ani + SNDRES MMRNMHRM_SHIP_SOUNDS mmrsound.snd + + MUSICRES MMRNMHRM_VICTORY_SONG mmrditty.mod + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/resinst.h b/sc2/src/sc2code/ships/mmrnmhrm/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/mmrnmhrm/respkg.h b/sc2/src/sc2code/ships/mmrnmhrm/respkg.h new file mode 100644 index 000000000..cfc776ebb --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/respkg.h @@ -0,0 +1,6 @@ +enum +{ + MMRNMHRM_CODE_PACKAGE = 1, + MMRNMHRM_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/mmrnmhrm/restypes.h b/sc2/src/sc2code/ships/mmrnmhrm/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/mmrnmhrm/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/mycon/icode.h b/sc2/src/sc2code/ships/mycon/icode.h new file mode 100644 index 000000000..2531dbbfc --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/icode.h @@ -0,0 +1,3 @@ +#define MYCON_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/mycon/igfxres.h b/sc2/src/sc2code/ships/mycon/igfxres.h new file mode 100644 index 000000000..50b1f9cf8 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/igfxres.h @@ -0,0 +1,11 @@ +#define MYCON_ICON_MASK_PMAP_ANIM 0x00200002L +#define MYCON_MICON_MASK_PMAP_ANIM 0x00200102L +#define MYCON_BIG_MASK_PMAP_ANIM 0x00400202L +#define MYCON_MED_MASK_PMAP_ANIM 0x00400302L +#define MYCON_SML_MASK_PMAP_ANIM 0x00400402L +#define PLASMA_BIG_MASK_PMAP_ANIM 0x00400502L +#define PLASMA_MED_MASK_PMAP_ANIM 0x00400602L +#define PLASMA_SML_MASK_PMAP_ANIM 0x00400702L +#define MYCON_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/mycon/imusicre.h b/sc2/src/sc2code/ships/mycon/imusicre.h new file mode 100644 index 000000000..df213924b --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/imusicre.h @@ -0,0 +1,3 @@ +#define MYCON_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/mycon/isndres.h b/sc2/src/sc2code/ships/mycon/isndres.h new file mode 100644 index 000000000..50e4881e9 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/isndres.h @@ -0,0 +1,3 @@ +#define MYCON_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/mycon/istrtab.h b/sc2/src/sc2code/ships/mycon/istrtab.h new file mode 100644 index 000000000..3cff4b2d1 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/istrtab.h @@ -0,0 +1,3 @@ +#define MYCON_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/mycon/mycon.c b/sc2/src/sc2code/ships/mycon/mycon.c new file mode 100644 index 000000000..df2b626ea --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/mycon.c @@ -0,0 +1,371 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/mycon/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 40 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 20 +#define SPECIAL_ENERGY_COST MAX_ENERGY +#define ENERGY_WAIT 4 +#define MAX_THRUST /* DISPLAY_TO_WORLD (7) */ 27 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 9 +#define TURN_WAIT 6 +#define THRUST_WAIT 6 +#define WEAPON_WAIT 5 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 7 + +#define NUM_PLASMAS 11 +#define NUM_GLOBALLS 8 +#define PLASMA_DURATION 13 +#define MISSILE_LIFE (NUM_PLASMAS * PLASMA_DURATION) +#define MISSILE_SPEED DISPLAY_TO_WORLD (8) + +static RACE_DESC mycon_desc = +{ + { + FIRES_FORE | SEEKING_WEAPON, + 21, /* Super Melee cost */ + 1070 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 6392, 2200, + }, + (STRING)MYCON_RACE_STRINGS, + (FRAME)MYCON_ICON_MASK_PMAP_ANIM, + (FRAME)MYCON_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)MYCON_BIG_MASK_PMAP_ANIM, + (FRAME)MYCON_MED_MASK_PMAP_ANIM, + (FRAME)MYCON_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)PLASMA_BIG_MASK_PMAP_ANIM, + (FRAME)PLASMA_MED_MASK_PMAP_ANIM, + (FRAME)PLASMA_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)MYCON_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)MYCON_VICTORY_SONG, + (SOUND)MYCON_SHIP_SOUNDS, + }, + { + 0, + DISPLAY_TO_WORLD (800), + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define MISSILE_DAMAGE 10 + +#define TRACK_WAIT 1 + +static void +plasma_preprocess (PELEMENT ElementPtr) +{ + COUNT plasma_index; + + if (ElementPtr->mass_points > ElementPtr->hit_points) + ElementPtr->life_span = ElementPtr->hit_points * PLASMA_DURATION; + else + ElementPtr->hit_points = (BYTE)((ElementPtr->life_span * + MISSILE_DAMAGE + (MISSILE_LIFE - 1)) / MISSILE_LIFE); + ElementPtr->mass_points = ElementPtr->hit_points; + plasma_index = NUM_PLASMAS - ((ElementPtr->life_span + + (PLASMA_DURATION - 1)) / PLASMA_DURATION); + if (plasma_index != GetFrameIndex (ElementPtr->next.image.frame)) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + plasma_index); + ElementPtr->state_flags |= CHANGING; + } + + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT facing; + + facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + )); + if (TrackShip (ElementPtr, &facing) > 0) + SetVelocityVector (&ElementPtr->velocity, + MISSILE_SPEED, facing); + + ElementPtr->turn_wait = TRACK_WAIT; + } +} + +static void +plasma_blast_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->life_span >= ElementPtr->thrust_wait) + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->next.image.frame); + else + ElementPtr->next.image.frame = + DecFrameIndex (ElementPtr->next.image.frame); + if (ElementPtr->hTarget) + { + ELEMENTPTR ShipPtr; + + LockElement (ElementPtr->hTarget, &ShipPtr); + ElementPtr->next.location = ShipPtr->next.location; + UnlockElement (ElementPtr->hTarget); + } + + ElementPtr->state_flags |= CHANGING; +} + +static void +plasma_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + SIZE old_mass; + HELEMENT hBlastElement; + + old_mass = (SIZE)ElementPtr0->mass_points; + if ((ElementPtr0->pParent != ElementPtr1->pParent + || (ElementPtr1->state_flags & PLAYER_SHIP)) + && (hBlastElement = + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1))) + { + SIZE num_animations; + ELEMENTPTR BlastElementPtr; + + LockElement (hBlastElement, &BlastElementPtr); + BlastElementPtr->pParent = ElementPtr0->pParent; + if (!(ElementPtr1->state_flags & PLAYER_SHIP)) + BlastElementPtr->hTarget = 0; + else + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + BlastElementPtr->hTarget = StarShipPtr->hShip; + } + + BlastElementPtr->current.location = ElementPtr1->current.location; + + if ((num_animations = + (old_mass * NUM_GLOBALLS + + (MISSILE_DAMAGE - 1)) / MISSILE_DAMAGE) == 0) + num_animations = 1; + + BlastElementPtr->thrust_wait = (BYTE)num_animations; + BlastElementPtr->life_span = (num_animations << 1) - 1; + { + BlastElementPtr->preprocess_func = plasma_blast_preprocess; + } + BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], + NUM_PLASMAS); + + UnlockElement (hBlastElement); + } +} + +static void +mycon_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) + { + if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) + && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + lpEvalDesc->MoveState = AVOID; + else + lpEvalDesc->MoveState = PURSUE; + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == PURSUE) + StarShipPtr->ship_input_state &= ~THRUST; /* don't pursue seekers */ + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->weapon_counter == 0 + && lpEvalDesc->ObjectPtr + && (lpEvalDesc->which_turn <= 16 + || ShipPtr->crew_level == StarShipPtr->RaceDescPtr->ship_info.max_crew)) + { + COUNT travel_facing, direction_facing; + SIZE delta_x, delta_y; + + travel_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + + HALF_CIRCLE) + ); + delta_x = lpEvalDesc->ObjectPtr->current.location.x + - ShipPtr->current.location.x; + delta_y = lpEvalDesc->ObjectPtr->current.location.y + - ShipPtr->current.location.y; + direction_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + + if (NORMALIZE_FACING (direction_facing + - StarShipPtr->ShipFacing + + ANGLE_TO_FACING (QUADRANT)) + <= ANGLE_TO_FACING (HALF_CIRCLE) + && (!(StarShipPtr->cur_status_flags & + (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) + || NORMALIZE_FACING (direction_facing + - travel_facing + ANGLE_TO_FACING (OCTANT)) + <= ANGLE_TO_FACING (QUADRANT))) + StarShipPtr->ship_input_state |= WEAPON; + } + + if (StarShipPtr->special_counter == 0) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = DISPLAY_TO_WORLD (800); + if (ShipPtr->crew_level < StarShipPtr->RaceDescPtr->ship_info.max_crew) + { + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = MISSILE_SPEED * MISSILE_LIFE; + if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST + && !(StarShipPtr->ship_input_state & WEAPON)) + StarShipPtr->ship_input_state |= SPECIAL; + } + } +} + +static COUNT +initialize_plasma (PELEMENT ShipPtr, HELEMENT PlasmaArray[]) +{ +#define MYCON_OFFSET 24 +#define MISSILE_OFFSET 0 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); + MissileBlock.pixoffs = MYCON_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_DAMAGE; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = plasma_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + PlasmaArray[0] = initialize_missile (&MissileBlock); + + if (PlasmaArray[0]) + { + ELEMENTPTR PlasmaPtr; + + LockElement (PlasmaArray[0], &PlasmaPtr); + PlasmaPtr->collision_func = plasma_collision; + PlasmaPtr->turn_wait = TRACK_WAIT + 2; + UnlockElement (PlasmaArray[0]); + } + + return (1); +} + +static void +mycon_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && ElementPtr->crew_level != StarShipPtr->RaceDescPtr->ship_info.max_crew + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { +#define REGENERATION_AMOUNT 4 + SIZE add_crew; + + ProcessSound (SetAbsSoundIndex ( + /* GROW_NEW_CREW */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + if ((add_crew = REGENERATION_AMOUNT) > + StarShipPtr->RaceDescPtr->ship_info.max_crew - ElementPtr->crew_level) + add_crew = StarShipPtr->RaceDescPtr->ship_info.max_crew - ElementPtr->crew_level; + DeltaCrew (ElementPtr, add_crew); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +RACE_DESCPTR +init_mycon () +{ + RACE_DESCPTR RaceDescPtr; + + mycon_desc.postprocess_func = mycon_postprocess; + mycon_desc.init_weapon_func = initialize_plasma; + mycon_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) mycon_intelligence; + + RaceDescPtr = &mycon_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/mycon/mycon.res b/sc2/src/sc2code/ships/mycon/mycon.res new file mode 100644 index 000000000..1c5067396 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/mycon.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH mycon + +PACKAGE MYCON_CODE_PACKAGE mycon.shp + CODE MYCON_CODE mycon.cod + GFXRES MYCON_ICON_MASK_PMAP_ANIM mycicons.ani + GFXRES MYCON_MICON_MASK_PMAP_ANIM mycmicon.ani + STRTAB MYCON_RACE_STRINGS myctext.txt + +PACKAGE MYCON_PACKAGE mycon.shp + GFXRES MYCON_BIG_MASK_PMAP_ANIM mycon.big + GFXRES MYCON_MED_MASK_PMAP_ANIM mycon.med + GFXRES MYCON_SML_MASK_PMAP_ANIM mycon.sml + GFXRES PLASMA_BIG_MASK_PMAP_ANIM plasma.big + GFXRES PLASMA_MED_MASK_PMAP_ANIM plasma.med + GFXRES PLASMA_SML_MASK_PMAP_ANIM plasma.sml + + GFXRES MYCON_CAPTAIN_MASK_PMAP_ANIM myccap.ani + SNDRES MYCON_SHIP_SOUNDS mycsound.snd + + MUSICRES MYCON_VICTORY_SONG mycditty.mod + diff --git a/sc2/src/sc2code/ships/mycon/resinst.h b/sc2/src/sc2code/ships/mycon/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/mycon/respkg.h b/sc2/src/sc2code/ships/mycon/respkg.h new file mode 100644 index 000000000..12b0cd6e3 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/respkg.h @@ -0,0 +1,6 @@ +enum +{ + MYCON_CODE_PACKAGE = 1, + MYCON_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/mycon/restypes.h b/sc2/src/sc2code/ships/mycon/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/mycon/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/orz/icode.h b/sc2/src/sc2code/ships/orz/icode.h new file mode 100644 index 000000000..511ad3c85 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/icode.h @@ -0,0 +1,3 @@ +#define ORZ_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/orz/igfxres.h b/sc2/src/sc2code/ships/orz/igfxres.h new file mode 100644 index 000000000..9a02d02d7 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/igfxres.h @@ -0,0 +1,14 @@ +#define ORZ_ICON_MASK_PMAP_ANIM 0x00200002L +#define ORZ_MICON_MASK_PMAP_ANIM 0x00200102L +#define ORZ_BIG_MASK_PMAP_ANIM 0x00400202L +#define ORZ_MED_MASK_PMAP_ANIM 0x00400302L +#define ORZ_SML_MASK_PMAP_ANIM 0x00400402L +#define HOWITZER_BIG_MASK_PMAP_ANIM 0x00400502L +#define HOWITZER_MED_MASK_PMAP_ANIM 0x00400602L +#define HOWITZER_SML_MASK_PMAP_ANIM 0x00400702L +#define TURRET_BIG_MASK_PMAP_ANIM 0x00400802L +#define TURRET_MED_MASK_PMAP_ANIM 0x00400902L +#define TURRET_SML_MASK_PMAP_ANIM 0x00400a02L +#define ORZ_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/orz/imusicre.h b/sc2/src/sc2code/ships/orz/imusicre.h new file mode 100644 index 000000000..c42daed13 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/imusicre.h @@ -0,0 +1,3 @@ +#define ORZ_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/orz/isndres.h b/sc2/src/sc2code/ships/orz/isndres.h new file mode 100644 index 000000000..24762c8a4 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/isndres.h @@ -0,0 +1,3 @@ +#define ORZ_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/orz/istrtab.h b/sc2/src/sc2code/ships/orz/istrtab.h new file mode 100644 index 000000000..9c5abd468 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/istrtab.h @@ -0,0 +1,3 @@ +#define ORZ_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/orz/orz.c b/sc2/src/sc2code/ships/orz/orz.c new file mode 100644 index 000000000..ab70ba350 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/orz.c @@ -0,0 +1,1076 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/orz/resinst.h" +#include "starcon.h" + +#define MAX_CREW 16 +#define MAX_ENERGY 20 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST (MAX_ENERGY / 3) +#define SPECIAL_ENERGY_COST 0 +#define ENERGY_WAIT 6 +#define MAX_THRUST 35 +#define THRUST_INCREMENT 5 +#define TURN_WAIT 1 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 4 +#define SPECIAL_WAIT 12 + +#define SHIP_MASS 4 +#define ORZ_OFFSET 9 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 12 + +static RACE_DESC orz_desc = +{ + { + FIRES_FORE | SEEKING_SPECIAL, + 23, /* Super Melee cost */ + 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 3608, 2637, + }, + (STRING)ORZ_RACE_STRINGS, + (FRAME)ORZ_ICON_MASK_PMAP_ANIM, + (FRAME)ORZ_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)ORZ_BIG_MASK_PMAP_ANIM, + (FRAME)ORZ_MED_MASK_PMAP_ANIM, + (FRAME)ORZ_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)HOWITZER_BIG_MASK_PMAP_ANIM, + (FRAME)HOWITZER_MED_MASK_PMAP_ANIM, + (FRAME)HOWITZER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)TURRET_BIG_MASK_PMAP_ANIM, + (FRAME)TURRET_MED_MASK_PMAP_ANIM, + (FRAME)TURRET_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)ORZ_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)ORZ_VICTORY_SONG, + (SOUND)ORZ_SHIP_SOUNDS, + }, + { + 0, + MISSILE_SPEED * MISSILE_LIFE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +howitzer_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if ((ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) + != (ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +#define TURRET_OFFSET 14 +#define TURRET_WAIT 3 + +static COUNT +initialize_turret_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) +{ +#define MISSILE_HITS 2 +#define MISSILE_DAMAGE 3 +#define MISSILE_OFFSET 1 + ELEMENTPTR TurretPtr; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + + LockElement (GetSuccElement (ShipPtr), &TurretPtr); + if (TurretPtr->turn_wait == 0 + && (StarShipPtr->cur_status_flags & SPECIAL) + && (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) + { + if (StarShipPtr->cur_status_flags & RIGHT) + ++TurretPtr->thrust_wait; + else + --TurretPtr->thrust_wait; + + TurretPtr->turn_wait = TURRET_WAIT + 1; + } + MissileBlock.face = MissileBlock.index = + NORMALIZE_FACING (StarShipPtr->ShipFacing + + TurretPtr->thrust_wait); + UnlockElement (GetSuccElement (ShipPtr)); + + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = TURRET_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + MissileArray[0] = initialize_missile (&MissileBlock); + + if (MissileArray[0]) + { + ELEMENTPTR HowitzerPtr; + + LockElement (MissileArray[0], &HowitzerPtr); + HowitzerPtr->collision_func = howitzer_collision; + UnlockElement (MissileArray[0]); + } + + return (1); +} + +#define MAX_MARINES 8 + +static BYTE +count_marines (STARSHIPPTR StarShipPtr, BOOLEAN FindSpot) +{ + BYTE num_marines, id_use[MAX_MARINES]; + HELEMENT hElement, hNextElement; + + num_marines = MAX_MARINES; + while (num_marines--) + id_use[num_marines] = 0; + + num_marines = 0; + for (hElement = GetTailElement (); hElement; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = GetPredElement (ElementPtr); + if (ElementPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special + && ElementPtr->life_span + && !(ElementPtr->state_flags & (FINITE_LIFE | DISAPPEARING))) + { + if (ElementPtr->state_flags & NONSOLID) + { + id_use[ElementPtr->turn_wait] = 1; + } + + if (++num_marines == MAX_MARINES) + { + UnlockElement (hElement); + hNextElement = 0; + } + } + UnlockElement (hElement); + } + + if (FindSpot) + { + num_marines = 0; + while (id_use[num_marines]) + ++num_marines; + } + + return (num_marines); +} + +static void +orz_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + ELEMENTPTR TurretPtr; + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + LockElement (GetSuccElement (ShipPtr), &TurretPtr); + + ++TurretPtr->turn_wait; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + --TurretPtr->turn_wait; + + GetElementStarShip (ShipPtr, &StarShipPtr); + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr == 0) + StarShipPtr->ship_input_state &= ~SPECIAL; + else if (StarShipPtr->special_counter != 1) + { + STARSHIPPTR EnemyStarShipPtr; + + if (ShipPtr->turn_wait == 0 + && lpEvalDesc->MoveState == ENTICE + && lpEvalDesc->which_turn < 24 + && (StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) + && !(StarShipPtr->ship_input_state & THRUST) + && NORMALIZE_ANGLE ( + GetVelocityTravelAngle (&ShipPtr->velocity) + - ARCTAN ( + lpEvalDesc->ObjectPtr->next.location.x + - ShipPtr->next.location.x, + lpEvalDesc->ObjectPtr->next.location.y + - ShipPtr->next.location.y + ) + (QUADRANT - (OCTANT >> 1))) >= + ((QUADRANT - (OCTANT >> 1)) << 1)) + StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); + + StarShipPtr->ship_input_state &= ~SPECIAL; + if (ShipPtr->turn_wait == 0 + && !(StarShipPtr->ship_input_state & (LEFT | RIGHT | WEAPON)) + && TurretPtr->turn_wait == 0) + { + SIZE delta_facing; + COUNT facing;//, orig_facing; + + facing = NORMALIZE_FACING (StarShipPtr->ShipFacing + + TurretPtr->thrust_wait); + if ((delta_facing = TrackShip (TurretPtr, &facing)) > 0) + { + StarShipPtr->ship_input_state |= SPECIAL; + if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) + delta_facing += (((BYTE)Random () & 1) << 1) - 1; + + if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + StarShipPtr->ship_input_state |= RIGHT; + else + StarShipPtr->ship_input_state |= LEFT; + } + } + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (StarShipPtr->special_counter == 0 + && !(StarShipPtr->ship_input_state & WEAPON) + && StarShipPtr->RaceDescPtr->ship_info.crew_level > + (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_crew >> 2) + && !(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & POINT_DEFENSE) + && (MANEUVERABILITY ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) < SLOW_SHIP + || lpEvalDesc->which_turn <= 12 + || count_marines (StarShipPtr, FALSE) < 2)) + { + StarShipPtr->ship_input_state |= WEAPON | SPECIAL; + } + } + + UnlockElement (GetSuccElement (ShipPtr)); +} + +#define START_ION_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) + +void +ion_preprocess (PELEMENT ElementPtr) +{ + COLOR color_tab[] = + { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), + BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), + BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; +#define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) + + COUNT color_index = 0; + COLOR Color; + + Color = COLOR_256 (GetPrimColor (&(GLOBAL (DisplayArray))[ + ElementPtr->PrimIndex + ])); + if (Color != 0x2D) + { + ElementPtr->life_span = ElementPtr->thrust_wait; + + Color += 2; + if (Color > 0x7F) + Color = 0x2B; + else if (Color == 0x7E) + Color = 0x7F; + if (Color <= 0x2f && Color >= 0x2a) + color_index = Color - 0x2a; + else /* color is between 0x7a and 0x7f */ + color_index = (Color - 0x7a) + (NUM_TAB_COLORS >> 1); + SetPrimColor (&(GLOBAL (DisplayArray))[ + ElementPtr->PrimIndex + ], color_tab[color_index]); + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= CHANGING; + } +} + +static void marine_preprocess (PELEMENT ElementPtr); + +#define MARINE_WAIT 12 + +static void +intruder_preprocess (PELEMENT ElementPtr) +{ + HELEMENT hElement, hNextElement; + ELEMENTPTR ShipPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipPtr); + if (ShipPtr->crew_level == 0 + && ShipPtr->life_span == 1 + && (ShipPtr->state_flags & (FINITE_LIFE | NONSOLID)) == + (FINITE_LIFE | NONSOLID)) + { + ElementPtr->life_span = 0; + ElementPtr->state_flags |= DISAPPEARING; + } + UnlockElement (StarShipPtr->hShip); + + if (ElementPtr->thrust_wait) + --ElementPtr->thrust_wait; + + for (hElement = GetHeadElement (); hElement; hElement = hNextElement) + { + LockElement (hElement, &ShipPtr); + if ((ShipPtr->state_flags & PLAYER_SHIP) + && (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + != (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))) + { + STAMP s; + + if (ElementPtr->thrust_wait == MARINE_WAIT) + { + --ElementPtr->thrust_wait; + + s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; + s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; + s.frame = SetAbsFrameIndex (ElementPtr->next.image.farray[0], + GetFrameCount (ElementPtr->next.image.farray[0]) - 2); + ModifySilhouette (ShipPtr, &s, 0); + } + + ElementPtr->next.location = ShipPtr->next.location; + + if (ShipPtr->crew_level == 0 + || ElementPtr->life_span == 0) + { + UnlockElement (hElement); + hElement = 0; +LeftShip: + s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; + s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; + s.frame = ElementPtr->next.image.frame; + ModifySilhouette (ShipPtr, &s, MODIFY_SWAP); + } + else if (ElementPtr->thrust_wait == 0) + { + BYTE randval; + + ElementPtr->thrust_wait = MARINE_WAIT; + + randval = (BYTE)Random (); + if (randval < (0x0100 / 16)) + { + ElementPtr->life_span = 0; + ElementPtr->state_flags |= DISAPPEARING; + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 4)); + goto LeftShip; + } + else if (randval < (0x0100 / 2 + 0x0100 / 16)) + { + if (!DeltaCrew (ShipPtr, -1)) + ShipPtr->life_span = 0; + + ++ElementPtr->thrust_wait; + s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; + s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; + s.frame = SetAbsFrameIndex (ElementPtr->next.image.farray[0], + GetFrameCount (ElementPtr->next.image.farray[0]) - 1); + ModifySilhouette (ShipPtr, &s, 0); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3)); + } + } + + UnlockElement (hElement); + break; + } + hNextElement = GetSuccElement (ShipPtr); + UnlockElement (hElement); + } + + if (hElement == 0 && ElementPtr->life_span) + { + ElementPtr->state_flags &= ~NONSOLID; + ElementPtr->state_flags |= CHANGING | CREW_OBJECT; + SetPrimType (&(GLOBAL (DisplayArray))[ + ElementPtr->PrimIndex + ], STAMP_PRIM); + + ElementPtr->current.image.frame = + ElementPtr->next.image.frame = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], 21 + ); + ElementPtr->thrust_wait = 0; + ElementPtr->turn_wait = + MAKE_BYTE (0, NORMALIZE_FACING ((BYTE)Random ())); + ElementPtr->preprocess_func = marine_preprocess; + } +} + +static void +marine_preprocess (ElementPtr) +PELEMENT ElementPtr; +{ + ELEMENTPTR ShipPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipPtr); + if (ShipPtr->crew_level == 0 + && ShipPtr->life_span == 1 + && (ShipPtr->state_flags & (FINITE_LIFE | NONSOLID)) == + (FINITE_LIFE | NONSOLID)) + { + ElementPtr->life_span = 0; + ElementPtr->state_flags |= DISAPPEARING | NONSOLID; + ElementPtr->turn_wait = 1; + } + UnlockElement (StarShipPtr->hShip); + + if (LONIBBLE (ElementPtr->turn_wait)) + --ElementPtr->turn_wait; + else + { + COUNT facing, pfacing; + SIZE delta_x, delta_y, delta_facing; + HELEMENT hObject, hNextObject, hTarget; + ELEMENTPTR ObjectPtr; + + ElementPtr->thrust_wait &= ~(SHIP_IN_GRAVITY_WELL >> 6); + + hTarget = 0; + for (hObject = GetHeadElement (); + hObject; hObject = hNextObject) + { + LockElement (hObject, &ObjectPtr); + hNextObject = GetSuccElement (ObjectPtr); + if (GRAVITY_MASS (ObjectPtr->mass_points)) + { + delta_x = ObjectPtr->current.location.x + - ElementPtr->current.location.x; + delta_x = WRAP_DELTA_X (delta_x); + + delta_y = ObjectPtr->current.location.y + - ElementPtr->current.location.y; + delta_y = WRAP_DELTA_Y (delta_y); + if ((long)delta_x * delta_x + (long)delta_y * delta_y <= + (long)(DISPLAY_TO_WORLD (GRAVITY_THRESHOLD) + * DISPLAY_TO_WORLD (GRAVITY_THRESHOLD))) + { + pfacing = ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)); + delta_facing = NORMALIZE_FACING ( + pfacing - ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + ) + ANGLE_TO_FACING (OCTANT) + ); + if (delta_facing <= ANGLE_TO_FACING (QUADRANT)) + { + hTarget = hObject; + hNextObject = 0; + } + + ElementPtr->thrust_wait |= (SHIP_IN_GRAVITY_WELL >> 6); + } + } + else if ((ObjectPtr->state_flags & PLAYER_SHIP) + && ObjectPtr->crew_level + && !OBJECT_CLOAKED (ObjectPtr)) + { + if ((ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) != + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))) + { + if (ElementPtr->state_flags & IGNORE_SIMILAR) + hTarget = hObject; + } + else if (hTarget == 0) + hTarget = hObject; + } + UnlockElement (hObject); + } + + facing = HINIBBLE (ElementPtr->turn_wait); + if (hTarget == 0) + delta_facing = -1; + else + { + LockElement (hTarget, &ObjectPtr); + delta_x = ObjectPtr->current.location.x + - ElementPtr->current.location.x; + delta_x = WRAP_DELTA_X (delta_x); + delta_y = ObjectPtr->current.location.y + - ElementPtr->current.location.y; + delta_y = WRAP_DELTA_Y (delta_y); + if (GRAVITY_MASS (ObjectPtr->mass_points)) + { + delta_facing = NORMALIZE_FACING (pfacing - facing + + ANGLE_TO_FACING (OCTANT)); + + if (delta_facing > ANGLE_TO_FACING (QUADRANT)) + delta_facing = 0; + else + { + if (delta_facing == ANGLE_TO_FACING (OCTANT)) + facing += (((SIZE)Random () & 1) << 1) - 1; + else if (delta_facing < ANGLE_TO_FACING (OCTANT)) + ++facing; + else + --facing; + } + } + else + { + COUNT num_frames; + VELOCITY_DESC ShipVelocity; + + if ((ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + && (ElementPtr->state_flags & IGNORE_SIMILAR)) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], 21 + ); + ElementPtr->state_flags &= ~IGNORE_SIMILAR; + ElementPtr->state_flags |= CHANGING; + } + + if ((num_frames = WORLD_TO_TURN ( + square_root ((long)delta_x * delta_x + + (long)delta_y * delta_y) + )) == 0) + num_frames = 1; + + ShipVelocity = ObjectPtr->velocity; + GetNextVelocityComponents (&ShipVelocity, + &delta_x, &delta_y, num_frames); + + delta_x = (ObjectPtr->current.location.x + delta_x) + - ElementPtr->current.location.x; + delta_y = (ObjectPtr->current.location.y + delta_y) + - ElementPtr->current.location.y; + + delta_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing + ); + + if (delta_facing > 0) + { + if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) + facing += (((BYTE)Random () & 1) << 1) - 1; + else if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + ++facing; + else + --facing; + } + } + UnlockElement (hTarget); + } + + ElementPtr->turn_wait = MAKE_BYTE (0, NORMALIZE_FACING (facing)); + if (delta_facing == 0 + || ((ElementPtr->thrust_wait & (SHIP_BEYOND_MAX_SPEED >> 6)) + && !(ElementPtr->thrust_wait & (SHIP_IN_GRAVITY_WELL >> 6)))) + { + UWORD thrust_status; + COUNT OldFacing; + UWORD OldStatus; + COUNT OldIncrement, OldThrust; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + OldFacing = StarShipPtr->ShipFacing; + OldStatus = StarShipPtr->cur_status_flags; + OldIncrement = StarShipPtr->RaceDescPtr->characteristics.thrust_increment; + OldThrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; + + StarShipPtr->ShipFacing = facing; + StarShipPtr->cur_status_flags = ElementPtr->thrust_wait << 6; + StarShipPtr->RaceDescPtr->characteristics.thrust_increment = 8; + StarShipPtr->RaceDescPtr->characteristics.max_thrust = 32; + + thrust_status = inertial_thrust (ElementPtr); + + StarShipPtr->RaceDescPtr->characteristics.max_thrust = OldThrust; + StarShipPtr->RaceDescPtr->characteristics.thrust_increment = OldIncrement; + StarShipPtr->cur_status_flags = OldStatus; + StarShipPtr->ShipFacing = OldFacing; + + if ((ElementPtr->thrust_wait & (SHIP_IN_GRAVITY_WELL >> 6)) + || delta_facing + || !(thrust_status + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED))) + { + HELEMENT hIonElement; + + hIonElement = AllocElement (); + if (hIonElement) + { +#define ION_LIFE 1 + COUNT angle; + ELEMENTPTR IonElementPtr; + + angle = FACING_TO_ANGLE (facing) + HALF_CIRCLE; + + InsertElement (hIonElement, GetHeadElement ()); + LockElement (hIonElement, &IonElementPtr); + IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + IonElementPtr->life_span = IonElementPtr->thrust_wait = ION_LIFE; + SetPrimType (&(GLOBAL (DisplayArray))[ + IonElementPtr->PrimIndex + ], POINT_PRIM); + SetPrimColor (&(GLOBAL (DisplayArray))[ + IonElementPtr->PrimIndex + ], START_ION_COLOR); + IonElementPtr->current.location = ElementPtr->current.location; + IonElementPtr->current.location.x += + (COORD)COSINE (angle, DISPLAY_TO_WORLD (2)); + IonElementPtr->current.location.y += + (COORD)SINE (angle, DISPLAY_TO_WORLD (2)); + IonElementPtr->death_func = ion_preprocess; + + SetElementStarShip (IonElementPtr, StarShipPtr); + + { + /* normally done during preprocess, but because + * object is being inserted at head rather than + * appended after tail it may never get preprocessed. + */ + IonElementPtr->next = IonElementPtr->current; + --IonElementPtr->life_span; + IonElementPtr->state_flags |= PRE_PROCESS; + } + + UnlockElement (hIonElement); + } + } + + ElementPtr->thrust_wait = (BYTE)(thrust_status >> 6); + } + } +} + +static void +marine_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr0->life_span + && !(ElementPtr0->state_flags & (NONSOLID | COLLISION)) + && !(ElementPtr1->state_flags & FINITE_LIFE)) + { + if ((ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) + != (ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) + { + ElementPtr0->turn_wait = + MAKE_BYTE (5, HINIBBLE (ElementPtr0->turn_wait)); + ElementPtr0->thrust_wait &= + ~((SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED) >> 6); + ElementPtr0->state_flags |= COLLISION; + } + + if (GRAVITY_MASS (ElementPtr1->mass_points)) + { + ElementPtr0->state_flags |= NONSOLID | FINITE_LIFE; + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + } + else if ((ElementPtr1->state_flags & PLAYER_SHIP) + && ((ElementPtr1->state_flags & FINITE_LIFE) + || ElementPtr1->life_span == NORMAL_LIFE)) + { + ElementPtr1->state_flags &= ~COLLISION; + + if (!(ElementPtr0->state_flags & COLLISION)) + { + DeltaCrew (ElementPtr1, 1); + + ElementPtr0->state_flags |= + DISAPPEARING | NONSOLID | FINITE_LIFE; + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + } + else if ((ElementPtr0->state_flags & IGNORE_SIMILAR) + && ElementPtr1->crew_level +#ifdef NEVER + && (BYTE)Random () <= (0x0100 / 3) +#endif /* NEVER */ + ) + { + STAMP s; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (!DeltaCrew (ElementPtr1, -1)) + ElementPtr1->life_span = 0; + else + { + ElementPtr0->turn_wait = count_marines (StarShipPtr, TRUE); + ElementPtr0->thrust_wait = MARINE_WAIT; + ElementPtr0->next.image.frame = SetAbsFrameIndex ( + ElementPtr0->next.image.farray[0], + 22 + ElementPtr0->turn_wait + ); + ElementPtr0->state_flags |= NONSOLID; + ElementPtr0->state_flags &= ~CREW_OBJECT; + SetPrimType (&(GLOBAL (DisplayArray))[ + ElementPtr0->PrimIndex + ], NO_PRIM); + ElementPtr0->preprocess_func = intruder_preprocess; + + s.origin.x = 16 + (ElementPtr0->turn_wait & 3) * 9; + s.origin.y = 14 + (ElementPtr0->turn_wait >> 2) * 11; + s.frame = ElementPtr0->next.image.frame; + ModifySilhouette (ElementPtr1, &s, 0); + } + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + } + + ElementPtr0->state_flags &= ~COLLISION; + } + } + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +animate (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +turret_postprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->life_span == 0) + { + STARSHIPPTR StarShipPtr; + + SetPrimType (&(GLOBAL (DisplayArray))[ + ElementPtr->PrimIndex + ], NO_PRIM); + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->hShip) + { + COUNT facing; + HELEMENT hTurret, hSpaceMarine; + ELEMENTPTR ShipPtr; + + LockElement (StarShipPtr->hShip, &ShipPtr); + hTurret = AllocElement (); + if (hTurret) + { + ELEMENTPTR TurretPtr; + + LockElement (hTurret, &TurretPtr); + TurretPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR + | CHANGING | PRE_PROCESS | POST_PROCESS + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + TurretPtr->life_span = 1; + TurretPtr->current.image = ElementPtr->current.image; + TurretPtr->current.location = ShipPtr->next.location; + TurretPtr->turn_wait = ElementPtr->turn_wait; + TurretPtr->thrust_wait = ElementPtr->thrust_wait; + + if (TurretPtr->turn_wait) + --TurretPtr->turn_wait; + else if ((StarShipPtr->cur_status_flags & SPECIAL) + && (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) + { + if (StarShipPtr->cur_status_flags & RIGHT) + ++TurretPtr->thrust_wait; + else + --TurretPtr->thrust_wait; + + TurretPtr->turn_wait = TURRET_WAIT; + } + facing = NORMALIZE_FACING (StarShipPtr->ShipFacing + + TurretPtr->thrust_wait); + StarShipPtr->RaceDescPtr->ship_info.ship_flags &= + ~(FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT); + StarShipPtr->RaceDescPtr->ship_info.ship_flags |= FIRES_FORE + << (NORMALIZE_FACING (facing + ANGLE_TO_FACING (OCTANT)) + / ANGLE_TO_FACING (QUADRANT)); + TurretPtr->current.image.frame = SetAbsFrameIndex ( + TurretPtr->current.image.frame, facing + ); + facing = FACING_TO_ANGLE (facing); + if (StarShipPtr->cur_status_flags & WEAPON) + { + HELEMENT hTurretEffect; + ELEMENTPTR TurretEffectPtr; + + LockElement (GetTailElement (), &TurretEffectPtr); + if ((PELEMENT)TurretEffectPtr != ElementPtr + && (TurretEffectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + && (TurretEffectPtr->state_flags & APPEARING) + && GetPrimType (&(GLOBAL (DisplayArray))[ + TurretEffectPtr->PrimIndex + ]) == STAMP_PRIM + && (hTurretEffect = AllocElement ()) + ) + { + TurretPtr->current.location.x -= + COSINE (facing, DISPLAY_TO_WORLD (2)); + TurretPtr->current.location.y -= + SINE (facing, DISPLAY_TO_WORLD (2)); + + LockElement (hTurretEffect, &TurretEffectPtr); + TurretEffectPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + TurretEffectPtr->life_span = 4; + + TurretEffectPtr->current.location.x = + TurretPtr->current.location.x + + COSINE (facing, + DISPLAY_TO_WORLD (TURRET_OFFSET)); + TurretEffectPtr->current.location.y = + TurretPtr->current.location.y + + SINE (facing, + DISPLAY_TO_WORLD (TURRET_OFFSET)); + TurretEffectPtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + TurretEffectPtr->current.image.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], + ANGLE_TO_FACING (FULL_CIRCLE) + ); + + TurretEffectPtr->preprocess_func = animate; + + SetElementStarShip (TurretEffectPtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + TurretEffectPtr->PrimIndex + ], STAMP_PRIM); + + UnlockElement (hTurretEffect); + PutElement (hTurretEffect); + } + UnlockElement (GetTailElement ()); + } + TurretPtr->next = TurretPtr->current; + + SetPrimType (&(GLOBAL (DisplayArray))[ + TurretPtr->PrimIndex + ], + GetPrimType (&(GLOBAL (DisplayArray))[ + ShipPtr->PrimIndex + ])); + SetPrimColor (&(GLOBAL (DisplayArray))[ + TurretPtr->PrimIndex + ], + GetPrimColor (&(GLOBAL (DisplayArray))[ + ShipPtr->PrimIndex + ])); + + TurretPtr->postprocess_func = + ElementPtr->postprocess_func; + + SetElementStarShip (TurretPtr, StarShipPtr); + + UnlockElement (hTurret); + InsertElement (hTurret, GetSuccElement (ElementPtr)); + } + + if (StarShipPtr->special_counter == 0 + && (StarShipPtr->cur_status_flags & SPECIAL) + && (StarShipPtr->cur_status_flags & WEAPON) + && ShipPtr->crew_level > 1 + && count_marines (StarShipPtr, FALSE) < MAX_MARINES + && TrackShip (ShipPtr, &facing) >= 0 + && (hSpaceMarine = AllocElement ())) + { + ELEMENTPTR SpaceMarinePtr; + + LockElement (hSpaceMarine, &SpaceMarinePtr); + SpaceMarinePtr->state_flags = + IGNORE_SIMILAR | APPEARING | CREW_OBJECT + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + SpaceMarinePtr->life_span = NORMAL_LIFE; + SpaceMarinePtr->hit_points = 3; + SpaceMarinePtr->mass_points = 1; + + facing = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + SpaceMarinePtr->current.location.x = + ShipPtr->current.location.x + - COSINE (facing, + DISPLAY_TO_WORLD (TURRET_OFFSET)); + SpaceMarinePtr->current.location.y = + ShipPtr->current.location.y + - SINE (facing, + DISPLAY_TO_WORLD (TURRET_OFFSET)); + SpaceMarinePtr->current.image.farray = + StarShipPtr->RaceDescPtr->ship_data.special; + SpaceMarinePtr->current.image.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], 20 + ); + + SpaceMarinePtr->turn_wait = MAKE_BYTE (0, + NORMALIZE_FACING ( + ANGLE_TO_FACING (facing + HALF_CIRCLE) + )); + SpaceMarinePtr->preprocess_func = marine_preprocess; + SpaceMarinePtr->collision_func = marine_collision; + + SetElementStarShip (SpaceMarinePtr, StarShipPtr); + + SetPrimType (&(GLOBAL (DisplayArray))[ + SpaceMarinePtr->PrimIndex + ], STAMP_PRIM); + + UnlockElement (hSpaceMarine); + PutElement (hSpaceMarine); + + DeltaCrew (ShipPtr, -1); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + + UnlockElement (StarShipPtr->hShip); + } + } +} + +static void +orz_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (!(ElementPtr->state_flags & APPEARING)) + { + if (((StarShipPtr->cur_status_flags + | StarShipPtr->old_status_flags) & SPECIAL) + && (StarShipPtr->cur_status_flags & (LEFT | RIGHT)) + && ElementPtr->turn_wait == 0) + { + ++ElementPtr->turn_wait; + } + + if ((StarShipPtr->cur_status_flags & SPECIAL) + && (StarShipPtr->cur_status_flags & WEAPON) + && StarShipPtr->weapon_counter == 0) + { + ++StarShipPtr->weapon_counter; + } + } + else + { + HELEMENT hTurret; + + hTurret = AllocElement (); + if (hTurret) + { + ELEMENTPTR TurretPtr; + + LockElement (hTurret, &TurretPtr); + TurretPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + TurretPtr->life_span = 1; + TurretPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; + TurretPtr->current.image.frame = + SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], + StarShipPtr->ShipFacing); + + TurretPtr->postprocess_func = turret_postprocess; + + SetElementStarShip (TurretPtr, StarShipPtr); + + UnlockElement (hTurret); + InsertElement (hTurret, GetSuccElement (ElementPtr)); + } + } +} + +RACE_DESCPTR +init_orz () +{ + RACE_DESCPTR RaceDescPtr; + + orz_desc.preprocess_func = orz_preprocess; + orz_desc.init_weapon_func = initialize_turret_missile; + orz_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) orz_intelligence; + + RaceDescPtr = &orz_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/orz/orz.res b/sc2/src/sc2code/ships/orz/orz.res new file mode 100644 index 000000000..71139dd81 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/orz.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH orz + +PACKAGE ORZ_CODE_PACKAGE orz.shp + CODE ORZ_CODE orz.cod + GFXRES ORZ_ICON_MASK_PMAP_ANIM orzicons.ani + GFXRES ORZ_MICON_MASK_PMAP_ANIM orzmicon.ani + STRTAB ORZ_RACE_STRINGS orztext.txt + +PACKAGE ORZ_PACKAGE orz.shp + GFXRES ORZ_BIG_MASK_PMAP_ANIM orz.big + GFXRES ORZ_MED_MASK_PMAP_ANIM orz.med + GFXRES ORZ_SML_MASK_PMAP_ANIM orz.sml + GFXRES HOWITZER_BIG_MASK_PMAP_ANIM howbig.ani + GFXRES HOWITZER_MED_MASK_PMAP_ANIM howmed.ani + GFXRES HOWITZER_SML_MASK_PMAP_ANIM howsml.ani + GFXRES TURRET_BIG_MASK_PMAP_ANIM turbig.ani + GFXRES TURRET_MED_MASK_PMAP_ANIM turmed.ani + GFXRES TURRET_SML_MASK_PMAP_ANIM tursml.ani + + GFXRES ORZ_CAPTAIN_MASK_PMAP_ANIM orzcap.ani + SNDRES ORZ_SHIP_SOUNDS orzsound.snd + + MUSICRES ORZ_VICTORY_SONG orzditty.mod + diff --git a/sc2/src/sc2code/ships/orz/resinst.h b/sc2/src/sc2code/ships/orz/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/orz/respkg.h b/sc2/src/sc2code/ships/orz/respkg.h new file mode 100644 index 000000000..1eda34968 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/respkg.h @@ -0,0 +1,6 @@ +enum +{ + ORZ_CODE_PACKAGE = 1, + ORZ_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/orz/restypes.h b/sc2/src/sc2code/ships/orz/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/orz/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/pkunk/icode.h b/sc2/src/sc2code/ships/pkunk/icode.h new file mode 100644 index 000000000..1605259d8 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/icode.h @@ -0,0 +1,3 @@ +#define PKUNK_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/pkunk/igfxres.h b/sc2/src/sc2code/ships/pkunk/igfxres.h new file mode 100644 index 000000000..bd1619068 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/igfxres.h @@ -0,0 +1,11 @@ +#define PKUNK_ICON_MASK_PMAP_ANIM 0x00200002L +#define PKUNK_MICON_MASK_PMAP_ANIM 0x00200102L +#define PKUNK_BIG_MASK_PMAP_ANIM 0x00400202L +#define PKUNK_MED_MASK_PMAP_ANIM 0x00400302L +#define PKUNK_SML_MASK_PMAP_ANIM 0x00400402L +#define BUG_BIG_MASK_PMAP_ANIM 0x00400502L +#define BUG_MED_MASK_PMAP_ANIM 0x00400602L +#define BUG_SML_MASK_PMAP_ANIM 0x00400702L +#define PKUNK_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/pkunk/imusicre.h b/sc2/src/sc2code/ships/pkunk/imusicre.h new file mode 100644 index 000000000..cf7c4a082 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/imusicre.h @@ -0,0 +1,3 @@ +#define PKUNK_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/pkunk/isndres.h b/sc2/src/sc2code/ships/pkunk/isndres.h new file mode 100644 index 000000000..fd57c696b --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/isndres.h @@ -0,0 +1,3 @@ +#define PKUNK_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/pkunk/istrtab.h b/sc2/src/sc2code/ships/pkunk/istrtab.h new file mode 100644 index 000000000..4a057a520 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/istrtab.h @@ -0,0 +1,3 @@ +#define PKUNK_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/pkunk/pkunk.c b/sc2/src/sc2code/ships/pkunk/pkunk.c new file mode 100644 index 000000000..739004b2c --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/pkunk.c @@ -0,0 +1,567 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/pkunk/resinst.h" +#include "starcon.h" + +#define MAX_CREW 8 +#define MAX_ENERGY 12 +#define ENERGY_REGENERATION 0 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 2 +#define ENERGY_WAIT 0 +#define MAX_THRUST 64 +#define THRUST_INCREMENT 16 +#define TURN_WAIT 0 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 16 + +#define SHIP_MASS 1 +#define MISSILE_SPEED DISPLAY_TO_WORLD (24) +#define MISSILE_LIFE 5 + +static RACE_DESC pkunk_desc = +{ + { + FIRES_FORE | FIRES_LEFT | FIRES_RIGHT, + 20, /* Super Melee cost */ + 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 502, 401, + }, + (STRING)PKUNK_RACE_STRINGS, + (FRAME)PKUNK_ICON_MASK_PMAP_ANIM, + (FRAME)PKUNK_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + 0, /* SPECIAL_WAIT */ + SHIP_MASS, + }, + { + { + (FRAME)PKUNK_BIG_MASK_PMAP_ANIM, + (FRAME)PKUNK_MED_MASK_PMAP_ANIM, + (FRAME)PKUNK_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)BUG_BIG_MASK_PMAP_ANIM, + (FRAME)BUG_MED_MASK_PMAP_ANIM, + (FRAME)BUG_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)PKUNK_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)PKUNK_VICTORY_SONG, + (SOUND)PKUNK_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON + 1, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +animate (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static COUNT +initialize_bug_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) +{ +#define PKUNK_OFFSET 15 +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 1 + COUNT i; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = PKUNK_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + + for (i = 0; i < 3; ++i) + { + MissileBlock.face = + StarShipPtr->ShipFacing + + (ANGLE_TO_FACING (QUADRANT) * i); + if (i == 2) + MissileBlock.face += ANGLE_TO_FACING (QUADRANT); + MissileBlock.face = NORMALIZE_FACING (MissileBlock.face); + + if ((MissileArray[i] = initialize_missile (&MissileBlock))) + { + SIZE dx, dy; + ELEMENTPTR MissilePtr; + + LockElement (MissileArray[i], &MissilePtr); + GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); + DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); + MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); + MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); + + MissilePtr->preprocess_func = animate; + UnlockElement (MissileArray[i]); + } + } + + return (3); +} + +static HELEMENT hPhoenix = 0; + +static void +pkunk_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (hPhoenix && StarShipPtr->special_counter) + { + RemoveElement (hPhoenix); + FreeElement (hPhoenix); + hPhoenix = 0; + } + + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < + StarShipPtr->RaceDescPtr->ship_info.max_energy + && (StarShipPtr->special_counter == 0 + || (BYTE)Random () < 20)) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); +} + +static void pkunk_preprocess (PELEMENT ElementPtr); +static void pkunk_postprocess (PELEMENT ElementPtr); + +static void +new_pkunk (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + { + ELEMENTPTR ShipPtr; + + LockElement (StarShipPtr->hShip, &ShipPtr); + ShipPtr->death_func = new_pkunk; + UnlockElement (StarShipPtr->hShip); + } + else + { + ElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + + ElementPtr->mass_points = SHIP_MASS; + ElementPtr->preprocess_func = StarShipPtr->RaceDescPtr->preprocess_func; + ElementPtr->postprocess_func = StarShipPtr->RaceDescPtr->postprocess_func; + ElementPtr->death_func = + (void (*) (PELEMENT ElementPtr)) + StarShipPtr->RaceDescPtr->init_weapon_func; + StarShipPtr->RaceDescPtr->preprocess_func = pkunk_preprocess; + StarShipPtr->RaceDescPtr->postprocess_func = pkunk_postprocess; + StarShipPtr->RaceDescPtr->init_weapon_func = initialize_bug_missile; + StarShipPtr->RaceDescPtr->ship_info.crew_level = MAX_CREW; + StarShipPtr->RaceDescPtr->ship_info.energy_level = MAX_ENERGY; + /* fix vux impairment */ + StarShipPtr->RaceDescPtr->characteristics.max_thrust = MAX_THRUST; + StarShipPtr->RaceDescPtr->characteristics.thrust_increment = THRUST_INCREMENT; + StarShipPtr->RaceDescPtr->characteristics.turn_wait = TURN_WAIT; + StarShipPtr->RaceDescPtr->characteristics.thrust_wait = THRUST_WAIT; + StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; + + StarShipPtr->ship_input_state = 0; + StarShipPtr->cur_status_flags = + StarShipPtr->old_status_flags = 0; + StarShipPtr->energy_counter = + StarShipPtr->weapon_counter = + StarShipPtr->special_counter = 0; + ElementPtr->crew_level = + ElementPtr->turn_wait = ElementPtr->thrust_wait = 0; + ElementPtr->life_span = NORMAL_LIFE; + + StarShipPtr->ShipFacing = NORMALIZE_FACING (Random ()); + ElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; + ElementPtr->current.image.frame = + SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], + StarShipPtr->ShipFacing); + SetPrimType (&(GLOBAL (DisplayArray))[ + ElementPtr->PrimIndex + ], STAMP_PRIM); + + do + { + ElementPtr->current.location.x = + WRAP_X (DISPLAY_ALIGN_X (Random ())); + ElementPtr->current.location.y = + WRAP_Y (DISPLAY_ALIGN_Y (Random ())); + } while (CalculateGravity (ElementPtr) + || TimeSpaceMatterConflict (ElementPtr)); + + ElementPtr->hTarget = StarShipPtr->hShip; + } +} + +static void +intercept_pkunk_death (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->life_span = 1; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + { + ELEMENTPTR ShipPtr; + + LockElement (StarShipPtr->hShip, &ShipPtr); + if (GRAVITY_MASS (ShipPtr->mass_points + 1)) + { + ElementPtr->state_flags |= DISAPPEARING; + ElementPtr->life_span = 0; + } + else + { + ShipPtr->mass_points = MAX_SHIP_MASS + 1; + StarShipPtr->RaceDescPtr->preprocess_func = ShipPtr->preprocess_func; + StarShipPtr->RaceDescPtr->postprocess_func = ShipPtr->postprocess_func; + StarShipPtr->RaceDescPtr->init_weapon_func = + (COUNT (*) (PELEMENT ElementPtr, + HELEMENT Weapon[])) + ShipPtr->death_func; + + ElementPtr->death_func = new_pkunk; + } + UnlockElement (StarShipPtr->hShip); + } +} + +#define START_PHOENIX_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) +#define TRANSITION_LIFE 1 + +void +spawn_phoenix_trail (PELEMENT + ElementPtr) +{ + COLOR color_tab[] = + { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), + BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), + BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; + +#define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) + + COUNT color_index = 0; + COLOR Color; + + Color = COLOR_256 ( + GetPrimColor (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]) + ); + if (Color != 0x2F) + { + ElementPtr->life_span = TRANSITION_LIFE; + + ++Color; + if (Color > 0x7F) + Color = 0x2A; + if (Color <= 0x2f && Color >= 0x2a) + color_index = Color - 0x2a; + else /* color is between 0x7a and 0x7f */ + color_index = (Color - 0x7a) + (NUM_TAB_COLORS >> 1); + SetPrimColor ( + &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + color_tab[color_index] + ); + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= CHANGING; + } +} + +#define PHOENIX_LIFE 12 + +void +phoenix_transition (PELEMENT + ElementPtr) +{ + HELEMENT hShipImage; + ELEMENTPTR ShipImagePtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipImagePtr); + + if (!(ShipImagePtr->state_flags & NONSOLID)) + { + ElementPtr->preprocess_func = NULL_PTR; + } + else if ((hShipImage = AllocElement ())) + { +#define TRANSITION_SPEED DISPLAY_TO_WORLD (20) + COUNT angle; + + PutElement (hShipImage); + + LockElement (hShipImage, &ShipImagePtr); + ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + ShipImagePtr->life_span = TRANSITION_LIFE; + SetPrimType (&(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex], + STAMPFILL_PRIM); + SetPrimColor ( + &(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex], + START_PHOENIX_COLOR + ); + ShipImagePtr->current.image = ElementPtr->current.image; + ShipImagePtr->current.location = ElementPtr->current.location; + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + { + angle = ElementPtr->mass_points; + + ShipImagePtr->current.location.x += + COSINE (angle, TRANSITION_SPEED); + ShipImagePtr->current.location.y += + SINE (angle, TRANSITION_SPEED); + ElementPtr->preprocess_func = NULL_PTR; + } + else + { + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + + ShipImagePtr->current.location.x -= + COSINE (angle, TRANSITION_SPEED) + * (ElementPtr->life_span - 1); + ShipImagePtr->current.location.y -= + SINE (angle, TRANSITION_SPEED) + * (ElementPtr->life_span - 1); + + ShipImagePtr->current.location.x = + WRAP_X (ShipImagePtr->current.location.x); + ShipImagePtr->current.location.y = + WRAP_Y (ShipImagePtr->current.location.y); + } + + ShipImagePtr->mass_points = (BYTE)angle; + ShipImagePtr->preprocess_func = phoenix_transition; + ShipImagePtr->death_func = spawn_phoenix_trail; + SetElementStarShip (ShipImagePtr, StarShipPtr); + + UnlockElement (hShipImage); + } + + UnlockElement (StarShipPtr->hShip); +} + +static void +pkunk_preprocess (ElementPtr) +PELEMENT ElementPtr; +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->state_flags & APPEARING) + { + ELEMENTPTR PhoenixPtr; + + if (((BYTE)Random () & 1) + && (hPhoenix = AllocElement ())) + { + + LockElement (hPhoenix, &PhoenixPtr); + PhoenixPtr->state_flags = + FINITE_LIFE | NONSOLID | IGNORE_SIMILAR + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + PhoenixPtr->life_span = 1; + + PhoenixPtr->death_func = intercept_pkunk_death; + + SetElementStarShip (PhoenixPtr, StarShipPtr); + + UnlockElement (hPhoenix); + InsertElement (hPhoenix, GetHeadElement ()); + } + + if (ElementPtr->hTarget == 0) + StarShipPtr->RaceDescPtr->preprocess_func = 0; + else + { + COUNT angle, facing; + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1 + )); + + ElementPtr->life_span = PHOENIX_LIFE; + SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + NO_PRIM); + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; + + facing = StarShipPtr->ShipFacing; + for (angle = OCTANT; angle < FULL_CIRCLE; angle += QUADRANT) + { + StarShipPtr->ShipFacing = NORMALIZE_FACING ( + facing + ANGLE_TO_FACING (angle) + ); + phoenix_transition (ElementPtr); + } + StarShipPtr->ShipFacing = facing; + } + } + + if (StarShipPtr->RaceDescPtr->preprocess_func) + { + StarShipPtr->cur_status_flags &= + ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + + if (ElementPtr->life_span == NORMAL_LIFE) + { + ElementPtr->current.image.frame = + ElementPtr->next.image.frame = + SetEquFrameIndex ( + ElementPtr->current.image.farray[0], + ElementPtr->current.image.frame); + SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + STAMP_PRIM); + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + ZeroVelocityComponents (&((ELEMENTPTR)ElementPtr)->velocity); + ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); + ElementPtr->state_flags |= CHANGING; + + StarShipPtr->RaceDescPtr->preprocess_func = 0; + } + } +} + +static void +pkunk_postprocess (ElementPtr) +PELEMENT ElementPtr; +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->characteristics.special_wait) + --StarShipPtr->RaceDescPtr->characteristics.special_wait; + else if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->RaceDescPtr->ship_info.energy_level < + StarShipPtr->RaceDescPtr->ship_info.max_energy) + { + COUNT CurSound; + static COUNT LastSound = 0; + + do + { + CurSound = + 2 + ((COUNT)Random () + % (GetSoundCount (StarShipPtr->RaceDescPtr->ship_data.ship_sounds) - 2)); + } while (CurSound == LastSound); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, CurSound + )); + LastSound = CurSound; + + DeltaEnergy (ElementPtr, SPECIAL_ENERGY_COST); + + StarShipPtr->RaceDescPtr->characteristics.special_wait = SPECIAL_WAIT; + } +} + +RACE_DESCPTR +init_pkunk () +{ + RACE_DESCPTR RaceDescPtr; + + pkunk_desc.preprocess_func = pkunk_preprocess; + pkunk_desc.postprocess_func = pkunk_postprocess; + pkunk_desc.init_weapon_func = initialize_bug_missile; + pkunk_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, + PVOID + ObjectsOfConcern, + COUNT + ConcernCounter)) + pkunk_intelligence; + + RaceDescPtr = &pkunk_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/pkunk/pkunk.res b/sc2/src/sc2code/ships/pkunk/pkunk.res new file mode 100644 index 000000000..81c917570 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/pkunk.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH pkunk + +PACKAGE PKUNK_CODE_PACKAGE pkunk.shp + CODE PKUNK_CODE pkunk.cod + GFXRES PKUNK_ICON_MASK_PMAP_ANIM pkuicons.ani + GFXRES PKUNK_MICON_MASK_PMAP_ANIM pkumicon.ani + STRTAB PKUNK_RACE_STRINGS pkutext.txt + +PACKAGE PKUNK_PACKAGE pkunk.shp + GFXRES PKUNK_BIG_MASK_PMAP_ANIM pkunk.big + GFXRES PKUNK_MED_MASK_PMAP_ANIM pkunk.med + GFXRES PKUNK_SML_MASK_PMAP_ANIM pkunk.sml + GFXRES BUG_BIG_MASK_PMAP_ANIM bugbig.ani + GFXRES BUG_MED_MASK_PMAP_ANIM bugmed.ani + GFXRES BUG_SML_MASK_PMAP_ANIM bugsml.ani + + GFXRES PKUNK_CAPTAIN_MASK_PMAP_ANIM pkucap.ani + SNDRES PKUNK_SHIP_SOUNDS pkusound.snd + + MUSICRES PKUNK_VICTORY_SONG pkuditty.mod + diff --git a/sc2/src/sc2code/ships/pkunk/resinst.h b/sc2/src/sc2code/ships/pkunk/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/pkunk/respkg.h b/sc2/src/sc2code/ships/pkunk/respkg.h new file mode 100644 index 000000000..249d10312 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/respkg.h @@ -0,0 +1,6 @@ +enum +{ + PKUNK_CODE_PACKAGE = 1, + PKUNK_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/pkunk/restypes.h b/sc2/src/sc2code/ships/pkunk/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/pkunk/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/probe/icode.h b/sc2/src/sc2code/ships/probe/icode.h new file mode 100644 index 000000000..59938b971 --- /dev/null +++ b/sc2/src/sc2code/ships/probe/icode.h @@ -0,0 +1,3 @@ +#define PROBE_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/probe/igfxres.h b/sc2/src/sc2code/ships/probe/igfxres.h new file mode 100644 index 000000000..981fc3074 --- /dev/null +++ b/sc2/src/sc2code/ships/probe/igfxres.h @@ -0,0 +1,3 @@ +#define PROBE_MICON_MASK_PMAP_ANIM 0x00200002L + + diff --git a/sc2/src/sc2code/ships/probe/istrtab.h b/sc2/src/sc2code/ships/probe/istrtab.h new file mode 100644 index 000000000..2a01e92eb --- /dev/null +++ b/sc2/src/sc2code/ships/probe/istrtab.h @@ -0,0 +1,10 @@ +#ifndef _ISTRTAB_H +#define _ISTRTAB_H + +#define ARILOU_RACE_STRINGS 0x00200004L +#define ARILOU_SHIP_SOUNDS 0x00400104L +#define ARILOU_VICTORY_SONG 0x00600204L + +typedef RESOURCE STRTAB_INSTANCE; + +#endif /* _ISTRTAB_H */ diff --git a/sc2/src/sc2code/ships/probe/probe.c b/sc2/src/sc2code/ships/probe/probe.c new file mode 100644 index 000000000..5187aae0a --- /dev/null +++ b/sc2/src/sc2code/ships/probe/probe.c @@ -0,0 +1,112 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/probe/resinst.h" +#include "starcon.h" + +#define MAX_CREW 1 +#define MAX_ENERGY 1 +#define ENERGY_REGENERATION 0 +#define WEAPON_ENERGY_COST 0 +#define SPECIAL_ENERGY_COST 0 +#define ENERGY_WAIT 0 +#define MAX_THRUST 0 +#define THRUST_INCREMENT 0 +#define TURN_WAIT 0 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 0 + +static RACE_DESC probe_desc = +{ + { + 0, + 0, /* Super Melee cost */ + 0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + 0, + 0, + (FRAME)PROBE_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)0, + (SOUND)0, + }, + { + 0, + 0, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +RACE_DESCPTR +init_probe () +{ + RACE_DESCPTR RaceDescPtr; + + RaceDescPtr = &probe_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/probe/probe.res b/sc2/src/sc2code/ships/probe/probe.res new file mode 100644 index 000000000..7fd219992 --- /dev/null +++ b/sc2/src/sc2code/ships/probe/probe.res @@ -0,0 +1,8 @@ +INCLUDE ../star3do.typ + +PATH probe + +PACKAGE PROBE_CODE_PACKAGE probe.sc2 + CODE PROBE_CODE probe.cod + GFXRES PROBE_MICON_MASK_PMAP_ANIM promicon.ani + diff --git a/sc2/src/sc2code/ships/probe/resinst.h b/sc2/src/sc2code/ships/probe/resinst.h new file mode 100644 index 000000000..97bd4134b --- /dev/null +++ b/sc2/src/sc2code/ships/probe/resinst.h @@ -0,0 +1,2 @@ +#include "igfxres.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/probe/respkg.h b/sc2/src/sc2code/ships/probe/respkg.h new file mode 100644 index 000000000..e210c162c --- /dev/null +++ b/sc2/src/sc2code/ships/probe/respkg.h @@ -0,0 +1,5 @@ +enum +{ + PROBE_CODE_PACKAGE = 1 +}; + diff --git a/sc2/src/sc2code/ships/probe/restypes.h b/sc2/src/sc2code/ships/probe/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/probe/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/shofixti/icode.h b/sc2/src/sc2code/ships/shofixti/icode.h new file mode 100644 index 000000000..238efc3d0 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/icode.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/shofixti/igfxres.h b/sc2/src/sc2code/ships/shofixti/igfxres.h new file mode 100644 index 000000000..ea8f2873d --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/igfxres.h @@ -0,0 +1,18 @@ +#define SHOFIXTI_ICON_MASK_PMAP_ANIM 0x00200002L +#define SHOFIXTI_MICON_MASK_PMAP_ANIM 0x00200102L +#define SHOFIXTI_BIG_MASK_PMAP_ANIM 0x00400202L +#define SHOFIXTI_MED_MASK_PMAP_ANIM 0x00400302L +#define SHOFIXTI_SML_MASK_PMAP_ANIM 0x00400402L +#define DESTRUCT_BIG_MASK_ANIM 0x00400502L +#define DESTRUCT_MED_MASK_ANIM 0x00400602L +#define DESTRUCT_SML_MASK_ANIM 0x00400702L +#define SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM 0x00400802L +#define OLDSHOF_BIG_MASK_PMAP_ANIM 0x00600902L +#define OLDSHOF_MED_MASK_PMAP_ANIM 0x00600a02L +#define OLDSHOF_SML_MASK_PMAP_ANIM 0x00600b02L +#define OLDSHOF_CAPTAIN_MASK_PMAP_ANIM 0x00600c02L +#define DART_BIG_MASK_PMAP_ANIM 0x00800d02L +#define DART_MED_MASK_PMAP_ANIM 0x00800e02L +#define DART_SML_MASK_PMAP_ANIM 0x00800f02L + + diff --git a/sc2/src/sc2code/ships/shofixti/imusicre.h b/sc2/src/sc2code/ships/shofixti/imusicre.h new file mode 100644 index 000000000..b47fcc027 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/imusicre.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_VICTORY_SONG 0x00800006L + + diff --git a/sc2/src/sc2code/ships/shofixti/isndres.h b/sc2/src/sc2code/ships/shofixti/isndres.h new file mode 100644 index 000000000..9c82a3bdf --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/isndres.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_SHIP_SOUNDS 0x00800005L + + diff --git a/sc2/src/sc2code/ships/shofixti/istrtab.h b/sc2/src/sc2code/ships/shofixti/istrtab.h new file mode 100644 index 000000000..22893d741 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/istrtab.h @@ -0,0 +1,3 @@ +#define SHOFIXTI_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/shofixti/resinst.h b/sc2/src/sc2code/ships/shofixti/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/shofixti/respkg.h b/sc2/src/sc2code/ships/shofixti/respkg.h new file mode 100644 index 000000000..9f690d41f --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/respkg.h @@ -0,0 +1,8 @@ +enum +{ + SHOFIXTI_CODE_PACKAGE = 1, + SHOFIXTI_PACKAGE, + OLDSHOF_PACKAGE, + SHOFIXTI_SHARED_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/shofixti/restypes.h b/sc2/src/sc2code/ships/shofixti/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/shofixti/shofixti.c b/sc2/src/sc2code/ships/shofixti/shofixti.c new file mode 100644 index 000000000..255057593 --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/shofixti.c @@ -0,0 +1,419 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/shofixti/resinst.h" +#include "starcon.h" + +#define MAX_CREW 6 +#define MAX_ENERGY 4 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 0 +#define ENERGY_WAIT 9 +#define MAX_THRUST 35 +#define THRUST_INCREMENT 5 +#define TURN_WAIT 1 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 3 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 1 +#define MISSILE_SPEED DISPLAY_TO_WORLD (24) +#define MISSILE_LIFE 10 + +static RACE_DESC shofixti_desc = +{ + { + FIRES_FORE, + 5, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)SHOFIXTI_RACE_STRINGS, + (FRAME)SHOFIXTI_ICON_MASK_PMAP_ANIM, + (FRAME)SHOFIXTI_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SHOFIXTI_BIG_MASK_PMAP_ANIM, + (FRAME)SHOFIXTI_MED_MASK_PMAP_ANIM, + (FRAME)SHOFIXTI_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)DART_BIG_MASK_PMAP_ANIM, + (FRAME)DART_MED_MASK_PMAP_ANIM, + (FRAME)DART_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)DESTRUCT_BIG_MASK_ANIM, + (FRAME)DESTRUCT_MED_MASK_ANIM, + (FRAME)DESTRUCT_SML_MASK_ANIM, + }, + { + (FRAME)SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SHOFIXTI_VICTORY_SONG, + (SOUND)SHOFIXTI_SHIP_SOUNDS, + }, + { + 0, + MISSILE_SPEED * MISSILE_LIFE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_standard_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) +{ +#define SHOFIXTI_OFFSET 15 +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 1 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = SHOFIXTI_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + MissileArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +destruct_preprocess (PELEMENT ElementPtr) +{ +#define DESTRUCT_SWITCH ((NUM_EXPLOSION_FRAMES * 3) - 3) + PPRIMITIVE lpPrim; + + lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; + ElementPtr->state_flags |= CHANGING; + if (ElementPtr->life_span > DESTRUCT_SWITCH) + { + SetPrimType (lpPrim, STAMPFILL_PRIM); + if (ElementPtr->life_span == DESTRUCT_SWITCH + 2) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E)); + else + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + } + else if (ElementPtr->life_span < DESTRUCT_SWITCH) + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E)); + else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C)); + else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x14, 0xA, 0x00), 0x06)); + else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x14, 0xA, 0x00), 0x06)) + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04)); + } + else + { + HELEMENT hDestruct; + + SetPrimType (lpPrim, NO_PRIM); + ElementPtr->preprocess_func = NULL_PTR; + + hDestruct = AllocElement (); + if (hDestruct) + { + ELEMENTPTR DestructPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + PutElement (hDestruct); + LockElement (hDestruct, &DestructPtr); + SetElementStarShip (DestructPtr, StarShipPtr); + DestructPtr->hit_points = DestructPtr->mass_points = 0; + DestructPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + DestructPtr->life_span = (NUM_EXPLOSION_FRAMES - 3) - 1; + SetPrimType ( + &(GLOBAL (DisplayArray))[DestructPtr->PrimIndex], + STAMPFILL_PRIM + ); + SetPrimColor ( + &(GLOBAL (DisplayArray))[DestructPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + ); + DestructPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; + DestructPtr->current.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; + DestructPtr->current.location = ElementPtr->current.location; + { + DestructPtr->preprocess_func = destruct_preprocess; + } + DestructPtr->postprocess_func = + DestructPtr->death_func = NULL_PTR; + ZeroVelocityComponents (&DestructPtr->velocity); + UnlockElement (hDestruct); + } + } +} + +static void +self_destruct (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hDestruct; + + hDestruct = AllocElement (); + if (hDestruct) + { + ELEMENTPTR DestructPtr; + + LockElement (hDestruct, &DestructPtr); + DestructPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + DestructPtr->next.location = ElementPtr->next.location; + DestructPtr->life_span = 0; + DestructPtr->pParent = ElementPtr->pParent; + DestructPtr->hTarget = 0; + + DestructPtr->death_func = self_destruct; + + UnlockElement (hDestruct); + + PutElement (hDestruct); + } + + ElementPtr->state_flags |= NONSOLID; + ElementPtr->life_span = 0; + + ElementPtr->preprocess_func = destruct_preprocess; + } + else + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENTPTR ObjPtr; + + LockElement (hElement, &ObjPtr); + hNextElement = GetSuccElement (ObjPtr); + + if (CollidingElement (ObjPtr)) + { +#define DESTRUCT_RANGE 180 + SIZE delta_x, delta_y; + DWORD dist; + + if ((delta_x = ObjPtr->next.location.x + - ElementPtr->next.location.x) < 0) + delta_x = -delta_x; + if ((delta_y = ObjPtr->next.location.y + - ElementPtr->next.location.y) < 0) + delta_y = -delta_y; + delta_x = WORLD_TO_DISPLAY (delta_x); + delta_y = WORLD_TO_DISPLAY (delta_y); + if (delta_x <= DESTRUCT_RANGE && delta_y <= DESTRUCT_RANGE + && (dist = (DWORD)(delta_x * delta_x) + + (DWORD)(delta_y * delta_y)) <= + (DWORD)(DESTRUCT_RANGE * DESTRUCT_RANGE)) + { +#define MAX_DESTRUCTION (DESTRUCT_RANGE / 10) + SIZE destruction; + + destruction = ((MAX_DESTRUCTION + * (DESTRUCT_RANGE - square_root (dist))) + / DESTRUCT_RANGE) + 1; + + if (ObjPtr->state_flags & PLAYER_SHIP) + { + if (!DeltaCrew (ObjPtr, -destruction)) + ObjPtr->life_span = 0; + } + else if (!GRAVITY_MASS (ObjPtr->mass_points)) + { + if ((BYTE)destruction < ObjPtr->hit_points) + ObjPtr->hit_points -= (BYTE)destruction; + else + { + ObjPtr->hit_points = 0; + ObjPtr->life_span = 0; + } + } + } + } + + UnlockElement (hElement); + } + } +} + +static void +shofixti_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0) + { + if (StarShipPtr->ship_input_state & SPECIAL) + StarShipPtr->ship_input_state &= ~SPECIAL; + else + { + register PEVALUATE_DESC lpWeaponEvalDesc, lpShipEvalDesc; + + lpWeaponEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + lpShipEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->RaceDescPtr->ship_data.special[0] + && (GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) + - GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) > 5 + || (lpShipEvalDesc->ObjectPtr != NULL_PTR + && lpShipEvalDesc->which_turn <= 4) + || (lpWeaponEvalDesc->ObjectPtr != NULL_PTR + /* means IMMEDIATE WEAPON */ + && (((lpWeaponEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) + && ShipPtr->crew_level == 1) + || (PlotIntercept (lpWeaponEvalDesc->ObjectPtr, ShipPtr, 2, 0) + && lpWeaponEvalDesc->ObjectPtr->mass_points >= ShipPtr->crew_level + && (Random () & 1)))))) + StarShipPtr->ship_input_state |= SPECIAL; + } + } +} + +static void +shofixti_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags + ^ StarShipPtr->old_status_flags) & SPECIAL) + { + StarShipPtr->RaceDescPtr->ship_data.captain_control.special = + IncFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special); + if (GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) + - GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) == 3) + self_destruct (ElementPtr); + } +} + +RACE_DESCPTR +init_shofixti () +{ + RACE_DESCPTR RaceDescPtr; + + static RACE_DESC new_shofixti_desc; + + shofixti_desc.postprocess_func = shofixti_postprocess; + shofixti_desc.init_weapon_func = initialize_standard_missile; + shofixti_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) shofixti_intelligence; + + new_shofixti_desc = shofixti_desc; + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER + && !GET_GAME_STATE (SHOFIXTI_RECRUITED)) + { +#define NUM_LIMPETS 3 + COUNT i; + + new_shofixti_desc.ship_data.ship[0] = (FRAME)OLDSHOF_BIG_MASK_PMAP_ANIM; + new_shofixti_desc.ship_data.ship[1] = (FRAME)OLDSHOF_MED_MASK_PMAP_ANIM; + new_shofixti_desc.ship_data.ship[2] = (FRAME)OLDSHOF_SML_MASK_PMAP_ANIM; + new_shofixti_desc.ship_data.special[0] = + new_shofixti_desc.ship_data.special[1] = + new_shofixti_desc.ship_data.special[2] = (FRAME)0; + new_shofixti_desc.ship_data.captain_control.background = + (FRAME)OLDSHOF_CAPTAIN_MASK_PMAP_ANIM; + + /* weapon doesn't work as well */ + new_shofixti_desc.characteristics.weapon_wait = 10; + /* simulate VUX limpets */ + for (i = 0; i < NUM_LIMPETS; ++i) + { + if (++new_shofixti_desc.characteristics.turn_wait == 0) + --new_shofixti_desc.characteristics.turn_wait; + if (++new_shofixti_desc.characteristics.thrust_wait == 0) + --new_shofixti_desc.characteristics.thrust_wait; +#define MIN_THRUST_INCREMENT DISPLAY_TO_WORLD (1) + if (new_shofixti_desc.characteristics.thrust_increment <= MIN_THRUST_INCREMENT) + { + new_shofixti_desc.characteristics.max_thrust = + new_shofixti_desc.characteristics.thrust_increment << 1; + } + else + { + COUNT num_thrusts; + + num_thrusts = new_shofixti_desc.characteristics.max_thrust / + new_shofixti_desc.characteristics.thrust_increment; + --new_shofixti_desc.characteristics.thrust_increment; + new_shofixti_desc.characteristics.max_thrust = + new_shofixti_desc.characteristics.thrust_increment * num_thrusts; + } + } + } + + RaceDescPtr = &new_shofixti_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/shofixti/shofixti.res b/sc2/src/sc2code/ships/shofixti/shofixti.res new file mode 100644 index 000000000..e6b5c51fc --- /dev/null +++ b/sc2/src/sc2code/ships/shofixti/shofixti.res @@ -0,0 +1,34 @@ +INCLUDE ../star3do.typ + +PATH shofixti + +PACKAGE SHOFIXTI_CODE_PACKAGE shofixti.shp + CODE SHOFIXTI_CODE shofixti.cod + GFXRES SHOFIXTI_ICON_MASK_PMAP_ANIM shoicons.ani + GFXRES SHOFIXTI_MICON_MASK_PMAP_ANIM shomicon.ani + STRTAB SHOFIXTI_RACE_STRINGS shotext.txt + +PACKAGE SHOFIXTI_PACKAGE shofixti.shp + GFXRES SHOFIXTI_BIG_MASK_PMAP_ANIM shofixti.big + GFXRES SHOFIXTI_MED_MASK_PMAP_ANIM shofixti.med + GFXRES SHOFIXTI_SML_MASK_PMAP_ANIM shofixti.sml + GFXRES DESTRUCT_BIG_MASK_ANIM destruct.big + GFXRES DESTRUCT_MED_MASK_ANIM destruct.med + GFXRES DESTRUCT_SML_MASK_ANIM destruct.sml + + GFXRES SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM shocap.ani + +PACKAGE OLDSHOF_PACKAGE shofixti.shp + GFXRES OLDSHOF_BIG_MASK_PMAP_ANIM oldshof.big + GFXRES OLDSHOF_MED_MASK_PMAP_ANIM oldshof.med + GFXRES OLDSHOF_SML_MASK_PMAP_ANIM oldshof.sml + + GFXRES OLDSHOF_CAPTAIN_MASK_PMAP_ANIM oldcap.ani + +PACKAGE SHOFIXTI_SHARED_PACKAGE shofixti.shp + GFXRES DART_BIG_MASK_PMAP_ANIM missile.big + GFXRES DART_MED_MASK_PMAP_ANIM missile.med + GFXRES DART_SML_MASK_PMAP_ANIM missile.sml + SNDRES SHOFIXTI_SHIP_SOUNDS shosound.snd + MUSICRES SHOFIXTI_VICTORY_SONG shoditty.mod + diff --git a/sc2/src/sc2code/ships/sis_ship/icode.h b/sc2/src/sc2code/ships/sis_ship/icode.h new file mode 100644 index 000000000..c74cf64c5 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/icode.h @@ -0,0 +1,3 @@ +#define SIS_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/sis_ship/igfxres.h b/sc2/src/sc2code/ships/sis_ship/igfxres.h new file mode 100644 index 000000000..0b8ed792f --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/igfxres.h @@ -0,0 +1,11 @@ +#define SIS_ICON_MASK_PMAP_ANIM 0x00400002L +#define SIS_BIG_MASK_PMAP_ANIM 0x00400102L +#define SIS_MED_MASK_PMAP_ANIM 0x00400202L +#define SIS_SML_MASK_PMAP_ANIM 0x00400302L +#define BLASTER_BIG_MASK_PMAP_ANIM 0x00400402L +#define BLASTER_MED_MASK_PMAP_ANIM 0x00400502L +#define BLASTER_SML_MASK_PMAP_ANIM 0x00400602L +#define SIS_CAPTAIN_MASK_PMAP_ANIM 0x00400702L +#define SIS_HYPER_MASK_PMAP_ANIM 0x00600802L + + diff --git a/sc2/src/sc2code/ships/sis_ship/imusicre.h b/sc2/src/sc2code/ships/sis_ship/imusicre.h new file mode 100644 index 000000000..639437db4 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/imusicre.h @@ -0,0 +1,3 @@ +#define SIS_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/sis_ship/isndres.h b/sc2/src/sc2code/ships/sis_ship/isndres.h new file mode 100644 index 000000000..961c93956 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/isndres.h @@ -0,0 +1,3 @@ +#define SIS_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/sis_ship/istrtab.h b/sc2/src/sc2code/ships/sis_ship/istrtab.h new file mode 100644 index 000000000..15bdab79f --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/istrtab.h @@ -0,0 +1,3 @@ +#define SIS_SHIP_SOUNDS 0x00400004L + + diff --git a/sc2/src/sc2code/ships/sis_ship/resinst.h b/sc2/src/sc2code/ships/sis_ship/resinst.h new file mode 100644 index 000000000..55cb40937 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/resinst.h @@ -0,0 +1,4 @@ +#include "igfxres.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/sis_ship/respkg.h b/sc2/src/sc2code/ships/sis_ship/respkg.h new file mode 100644 index 000000000..e33687bf8 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/respkg.h @@ -0,0 +1,7 @@ +enum +{ + SIS_CODE_PACKAGE = 1, + SIS_BATTLE_PACKAGE, + SIS_HYPER_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/sis_ship/restypes.h b/sc2/src/sc2code/ships/sis_ship/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/sis_ship/sis.res b/sc2/src/sc2code/ships/sis_ship/sis.res new file mode 100644 index 000000000..e9a07d00c --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/sis.res @@ -0,0 +1,24 @@ +INCLUDE ../star3do.typ + +PATH sis_ship + +PACKAGE SIS_CODE_PACKAGE sis.dat + CODE SIS_CODE sis.cod + +PACKAGE SIS_BATTLE_PACKAGE sis.dat + GFXRES SIS_ICON_MASK_PMAP_ANIM sisicons.ani + + GFXRES SIS_BIG_MASK_PMAP_ANIM sis.big + GFXRES SIS_MED_MASK_PMAP_ANIM sis.med + GFXRES SIS_SML_MASK_PMAP_ANIM sis.sml + GFXRES BLASTER_BIG_MASK_PMAP_ANIM blasbig.ani + GFXRES BLASTER_MED_MASK_PMAP_ANIM blasmed.ani + GFXRES BLASTER_SML_MASK_PMAP_ANIM blassml.ani + + GFXRES SIS_CAPTAIN_MASK_PMAP_ANIM siscap.ani + SNDRES SIS_SHIP_SOUNDS sissound.snd + MUSICRES SIS_VICTORY_SONG sisditty.mod + +PACKAGE SIS_HYPER_PACKAGE sis.dat + GFXRES SIS_HYPER_MASK_PMAP_ANIM sishyper.ani + diff --git a/sc2/src/sc2code/ships/sis_ship/sis_ship.c b/sc2/src/sc2code/ships/sis_ship/sis_ship.c new file mode 100644 index 000000000..05039b172 --- /dev/null +++ b/sc2/src/sc2code/ships/sis_ship/sis_ship.c @@ -0,0 +1,868 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/sis_ship/resinst.h" +#include "starcon.h" + +#define MAX_TRACKING 3 +#define MAX_DEFENSE 8 + +#define MAX_CREW MAX_CREW_SIZE +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 0 +#define ENERGY_WAIT 10 +#define MAX_THRUST 10 +#define THRUST_INCREMENT 4 +#define TURN_WAIT 17 +#define THRUST_WAIT 6 +#define WEAPON_WAIT 6 +#define SPECIAL_WAIT 9 + +#define SHIP_MASS MAX_SHIP_MASS + +#define BLASTER_SPEED DISPLAY_TO_WORLD (24) +#define BLASTER_LIFE 12 + +static RACE_DESC sis_desc = +{ + { + 0, + 16, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + 0, + (FRAME)SIS_ICON_MASK_PMAP_ANIM, + 0, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SIS_BIG_MASK_PMAP_ANIM, + (FRAME)SIS_MED_MASK_PMAP_ANIM, + (FRAME)SIS_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)BLASTER_BIG_MASK_PMAP_ANIM, + (FRAME)BLASTER_MED_MASK_PMAP_ANIM, + (FRAME)BLASTER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)SIS_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SIS_VICTORY_SONG, + (SOUND)SIS_SHIP_SOUNDS, + }, + { + 0, + BLASTER_SPEED * BLASTER_LIFE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static BYTE num_trackers = 0; + +static void +sis_hyper_preprocess (PELEMENT ElementPtr) +{ + SIZE udx, udy, dx, dy; + SIZE AccelerateDirection; + STARSHIPPTR StarShipPtr; + + if (ElementPtr->state_flags & APPEARING) + { + ElementPtr->velocity = GLOBAL (velocity); + } + + AccelerateDirection = 0; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ++StarShipPtr->weapon_counter; /* no shooting in hyperspace! */ + if ((GLOBAL (autopilot)).x == ~0 + || (GLOBAL (autopilot)).y == ~0 + || (StarShipPtr->cur_status_flags & (LEFT | RIGHT | THRUST))) + { +LeaveAutoPilot: + (GLOBAL (autopilot)).x = + (GLOBAL (autopilot)).y = ~0; + if (!(StarShipPtr->cur_status_flags & THRUST) + || (GLOBAL_SIS (FuelOnBoard) == 0 + && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)) + { + AccelerateDirection = -1; + GetCurrentVelocityComponents (&ElementPtr->velocity, + &dx, &dy); + udx = dx << 4; + udy = dy << 4; + + StarShipPtr->cur_status_flags &= ~THRUST; + } + } + else + { + SIZE facing; + POINT universe; + + universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); + universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); + udx = (GLOBAL (autopilot)).x - universe.x; + udy = -((GLOBAL (autopilot)).y - universe.y); + if ((dx = udx) < 0) + dx = -dx; + if ((dy = udy) < 0) + dy = -dy; + if (dx <= 1 && dy <= 1) + goto LeaveAutoPilot; + + facing = NORMALIZE_FACING (ANGLE_TO_FACING (ARCTAN (udx, udy))); + + if ((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) + || (ElementPtr->state_flags & APPEARING)) + { + if (NORMALIZE_FACING (StarShipPtr->ShipFacing + + ANGLE_TO_FACING (QUADRANT) + - facing) > ANGLE_TO_FACING (HALF_CIRCLE)) + goto LeaveAutoPilot; + + facing = StarShipPtr->ShipFacing; + } + else if ((int)facing != (int)StarShipPtr->ShipFacing + && ElementPtr->turn_wait == 0) + { + if (NORMALIZE_FACING ( + StarShipPtr->ShipFacing - facing + ) >= ANGLE_TO_FACING (HALF_CIRCLE)) + { + facing = NORMALIZE_FACING (facing - 1); + StarShipPtr->cur_status_flags |= RIGHT; + } + else if ((int)StarShipPtr->ShipFacing != (int)facing) + { + facing = NORMALIZE_FACING (facing + 1); + StarShipPtr->cur_status_flags |= LEFT; + } + + if ((int)facing == (int)StarShipPtr->ShipFacing) + { + ZeroVelocityComponents (&ElementPtr->velocity); + } + } + + GetCurrentVelocityComponents ( + &ElementPtr->velocity, + &dx, &dy + ); + if (GLOBAL_SIS (FuelOnBoard) + && (int)facing == (int)StarShipPtr->ShipFacing) + { + StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; + AccelerateDirection = 1; + } + else + { + AccelerateDirection = -1; + udx = dx << 4; + udy = dy << 4; + } + } + + if (ElementPtr->thrust_wait == 0 && AccelerateDirection) + { + COUNT dist; + SIZE speed, velocity_increment; + + velocity_increment = WORLD_TO_VELOCITY ( + StarShipPtr->RaceDescPtr->characteristics.thrust_increment + ); + + if ((dist = square_root ((long)udx * udx + (long)udy * udy)) == 0) + dist = 1; /* prevent divide by zero */ + + speed = square_root ((long)dx * dx + (long)dy * dy); + if (AccelerateDirection < 0) + { + dy = (speed / velocity_increment - 1) + * velocity_increment; + if (dy < speed - velocity_increment) + dy = speed - velocity_increment; + if ((speed = dy) < 0) + speed = 0; + + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + } + else + { + SIZE max_velocity; + + AccelerateDirection = 0; + + max_velocity = WORLD_TO_VELOCITY ( + StarShipPtr->RaceDescPtr->characteristics.max_thrust + ); + + dy = (speed / velocity_increment + 1) + * velocity_increment; + if (dy < speed + velocity_increment) + dy = speed + velocity_increment; + if ((speed = dy) > max_velocity) + { + speed = max_velocity; + StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; + } + } + + dx = (SIZE)((long)udx * speed / (long)dist); + dy = (SIZE)((long)udy * speed / (long)dist); + SetVelocityComponents (&ElementPtr->velocity, dx, dy); + + ElementPtr->thrust_wait = + StarShipPtr->RaceDescPtr->characteristics.thrust_wait; + } +} + +static void +sis_hyper_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GLOBAL (velocity) = ElementPtr->velocity; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & WEAPON) + && StarShipPtr->special_counter == 0) + { +#define MENU_DELAY 10 + DoMenuOptions (); + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + StarShipPtr->special_counter = MENU_DELAY; + } +} + +static void +spawn_point_defense (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hDefense; + + hDefense = AllocElement (); + if (hDefense) + { + ELEMENTPTR DefensePtr; + + LockElement (hDefense, &DefensePtr); + DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + { + DefensePtr->death_func = spawn_point_defense; + } + GetElementStarShip (ElementPtr, &StarShipPtr); + SetElementStarShip (DefensePtr, StarShipPtr); + UnlockElement (hDefense); + + PutElement (hDefense); + } + } + else + { + BOOLEAN PaidFor; + HELEMENT hObject, hNextObject; + ELEMENTPTR ShipPtr; + COLOR LaserColor, + ColorRange[] = + { + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7E), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7D), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7C), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), + }; + + PaidFor = FALSE; + + LaserColor = ColorRange[ + StarShipPtr->RaceDescPtr->characteristics.special_energy_cost + ]; + LockElement (StarShipPtr->hShip, &ShipPtr); + for (hObject = GetTailElement (); hObject; hObject = hNextObject) + { + ELEMENTPTR ObjectPtr; + + LockElement (hObject, &ObjectPtr); + hNextObject = GetPredElement (ObjectPtr); + if (ObjectPtr != ShipPtr && CollidingElement (ObjectPtr) && + !OBJECT_CLOAKED (ObjectPtr)) + { +#define LASER_RANGE (UWORD)100 + SIZE delta_x, delta_y; + + delta_x = ObjectPtr->next.location.x - + ShipPtr->next.location.x; + delta_y = ObjectPtr->next.location.y - + ShipPtr->next.location.y; + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + delta_x = WORLD_TO_DISPLAY (delta_x); + delta_y = WORLD_TO_DISPLAY (delta_y); + if ((UWORD)delta_x <= LASER_RANGE && + (UWORD)delta_y <= LASER_RANGE && + (UWORD)delta_x * (UWORD)delta_x + + (UWORD)delta_y * (UWORD)delta_y <= + LASER_RANGE * LASER_RANGE) + { + HELEMENT hPointDefense; + LASER_BLOCK LaserBlock; + + if (!PaidFor) + { + if (!DeltaEnergy (ShipPtr, + -(StarShipPtr->RaceDescPtr->characteristics.special_energy_cost + << 2))) + break; + + ProcessSound (SetAbsSoundIndex ( + /* POINT_DEFENSE_LASER */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + PaidFor = TRUE; + } + + LaserBlock.cx = ShipPtr->next.location.x; + LaserBlock.cy = ShipPtr->next.location.y; + LaserBlock.face = 0; + LaserBlock.ex = ObjectPtr->next.location.x + - ShipPtr->next.location.x; + LaserBlock.ey = ObjectPtr->next.location.y + - ShipPtr->next.location.y; + LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = 0; + LaserBlock.color = LaserColor; + hPointDefense = initialize_laser (&LaserBlock); + if (hPointDefense) + { + ELEMENTPTR PDPtr; + + LockElement (hPointDefense, &PDPtr); + PDPtr->mass_points = + StarShipPtr->RaceDescPtr->characteristics.special_energy_cost; + SetElementStarShip (PDPtr, StarShipPtr); + PDPtr->hTarget = 0; + UnlockElement (hPointDefense); + + PutElement (hPointDefense); + } + } + } + UnlockElement (hObject); + } + UnlockElement (StarShipPtr->hShip); + } +} + +static void +sis_battle_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->RaceDescPtr->characteristics.special_energy_cost == 0) + { + StarShipPtr->cur_status_flags &= ~SPECIAL; + StarShipPtr->special_counter = 2; + } + if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags + & (FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT))) + { + StarShipPtr->cur_status_flags &= ~WEAPON; + StarShipPtr->weapon_counter = 2; + } +} + +static void +sis_battle_postprocess (PELEMENT ElementPtr) +{ + SIZE crew_delta; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) + { + spawn_point_defense (ElementPtr); + } + + if (ElementPtr->crew_level > 0 + && ElementPtr->crew_level < StarShipPtr->RaceDescPtr->ship_info.max_crew + && ElementPtr->crew_level != (crew_delta = + (SIZE)GLOBAL_SIS (CrewEnlisted) + 1)) + { + ElementPtr->crew_level = 0; + StarShipPtr->RaceDescPtr->ship_info.crew_level = 0; + if (crew_delta <= StarShipPtr->RaceDescPtr->ship_info.max_crew) + DeltaCrew (ElementPtr, crew_delta); + else + DeltaCrew (ElementPtr, StarShipPtr->RaceDescPtr->ship_info.max_crew); + } +} + +#define BLASTER_DAMAGE 2 + +static void +blaster_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + HELEMENT hBlastElement; + + hBlastElement = + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + if (hBlastElement) + { + ELEMENTPTR BlastElementPtr; + + LockElement (hBlastElement, &BlastElementPtr); + switch (ElementPtr0->mass_points) + { + case BLASTER_DAMAGE * 1: + BlastElementPtr->life_span = 2; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (ElementPtr0->current.image.frame, 0); + BlastElementPtr->preprocess_func = NULL_PTR; + break; + case BLASTER_DAMAGE * 2: + BlastElementPtr->life_span = 6; + BlastElementPtr->current.image.frame = + IncFrameIndex (ElementPtr0->current.image.frame); + break; + case BLASTER_DAMAGE * 3: + BlastElementPtr->life_span = 7; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (ElementPtr0->current.image.frame, 20); + break; + } + UnlockElement (hBlastElement); + } +} + +static void +blaster_preprocess (PELEMENT ElementPtr) +{ + BYTE wait; + + switch (ElementPtr->mass_points) + { + case BLASTER_DAMAGE * 1: + if (GetFrameIndex (ElementPtr->current.image.frame) < 8) + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + } + break; + case BLASTER_DAMAGE * 3: + if (GetFrameIndex (ElementPtr->current.image.frame) < 19) + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + else + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, 16); + ElementPtr->state_flags |= CHANGING; + break; + } + + if (LONIBBLE (ElementPtr->turn_wait)) + --ElementPtr->turn_wait; + else if ((wait = HINIBBLE (ElementPtr->turn_wait))) + { + COUNT facing; + + facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + )); + if (TrackShip (ElementPtr, &facing) > 0) + { + SetVelocityVector (&ElementPtr->velocity, + BLASTER_SPEED, facing); + } + + ElementPtr->turn_wait = MAKE_BYTE (wait, wait); + } +} + +static COUNT +initialize_blasters (PELEMENT ShipPtr, HELEMENT BlasterArray[]) +{ +#define SIS_VERT_OFFSET 28 +#define SIS_HORZ_OFFSET 20 +#define BLASTER_HITS 2 +#define BLASTER_OFFSET 8 + COUNT num_blasters; + + BYTE nt; + COUNT i; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock[6]; + PMISSILE_BLOCK lpMB; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + num_blasters = 0; + for (i = 0, lpMB = &MissileBlock[0]; i < NUM_MODULE_SLOTS; ++i) + { + BYTE which_gun; + + if (i == 3) + i = NUM_MODULE_SLOTS - 1; + which_gun = GLOBAL_SIS (ModuleSlots[ + (NUM_MODULE_SLOTS - 1) - i + ]); + if (which_gun >= GUN_WEAPON && which_gun <= CANNON_WEAPON) + { + which_gun -= GUN_WEAPON - 1; + lpMB->cx = ShipPtr->next.location.x; + lpMB->cy = ShipPtr->next.location.y; + lpMB->farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + lpMB->sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + lpMB->blast_offs = BLASTER_OFFSET; + lpMB->speed = BLASTER_SPEED; + lpMB->preprocess_func = blaster_preprocess; + lpMB->hit_points = BLASTER_HITS * which_gun; + lpMB->damage = BLASTER_DAMAGE * which_gun; + lpMB->life = BLASTER_LIFE + + ((BLASTER_LIFE >> 2) * (which_gun - 1)); + + if (which_gun == 1) + lpMB->index = 0; + else if (which_gun == 2) + lpMB->index = 9; + else + lpMB->index = 16; + + switch (i) + { + case 0: /* NOSE WEAPON */ + lpMB->pixoffs = SIS_VERT_OFFSET; + lpMB->face = StarShipPtr->ShipFacing; + break; + case 1: /* SPREAD WEAPON */ + lpMB->pixoffs = SIS_VERT_OFFSET; + lpMB->face = NORMALIZE_FACING ( + StarShipPtr->ShipFacing + 1 + ); + lpMB[1] = lpMB[0]; + ++lpMB; + lpMB->face = NORMALIZE_FACING ( + StarShipPtr->ShipFacing - 1 + ); + break; + case 2: /* SIDE WEAPON */ + lpMB->pixoffs = SIS_HORZ_OFFSET; + lpMB->face = NORMALIZE_FACING ( + StarShipPtr->ShipFacing + + ANGLE_TO_FACING (QUADRANT) + ); + lpMB[1] = lpMB[0]; + ++lpMB; + lpMB->face = NORMALIZE_FACING ( + StarShipPtr->ShipFacing + - ANGLE_TO_FACING (QUADRANT) + ); + break; + case NUM_MODULE_SLOTS - 1: /* TAIL WEAPON */ + lpMB->pixoffs = SIS_VERT_OFFSET; + lpMB->face = NORMALIZE_FACING ( + StarShipPtr->ShipFacing + + ANGLE_TO_FACING (HALF_CIRCLE) + ); + break; + } + + ++lpMB; + } + } + + + nt = (BYTE)((4 - num_trackers) & 3); + num_blasters = lpMB - &MissileBlock[0]; + for (i = 0, lpMB = &MissileBlock[0]; i < num_blasters; ++i, ++lpMB) + { + if ((BlasterArray[i] = initialize_missile (lpMB))) + { + ELEMENTPTR BlasterPtr; + + LockElement (BlasterArray[i], &BlasterPtr); + BlasterPtr->collision_func = blaster_collision; + BlasterPtr->turn_wait = MAKE_BYTE (nt, nt); + UnlockElement (BlasterArray[i]); + } + } + + return (num_blasters); +} + +static void +sis_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr) + { + if (StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) + { + if (StarShipPtr->special_counter == 0 + && ((lpEvalDesc->ObjectPtr + && lpEvalDesc->which_turn <= 2) + || (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr != NULL_PTR + && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 4))) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + lpEvalDesc->ObjectPtr = NULL_PTR; + } + else if (MANEUVERABILITY (&StarShipPtr->RaceDescPtr->cyborg_control) < MEDIUM_SHIP + && lpEvalDesc->MoveState == ENTICE + && (!(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) + || lpEvalDesc->which_turn <= 8) + && (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) + || (lpEvalDesc->ObjectPtr->mass_points >= 4 + && lpEvalDesc->which_turn == 2 + && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 16))) + lpEvalDesc->MoveState = PURSUE; + } + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (num_trackers + && StarShipPtr->weapon_counter == 0 + && !(StarShipPtr->ship_input_state & WEAPON) + && lpEvalDesc->ObjectPtr + && lpEvalDesc->which_turn <= 16) + { + COUNT direction_facing; + SIZE delta_x, delta_y; + UWORD fire_flags, ship_flags; + COUNT facing; + + delta_x = lpEvalDesc->ObjectPtr->current.location.x + - ShipPtr->current.location.x; + delta_y = lpEvalDesc->ObjectPtr->current.location.y + - ShipPtr->current.location.y; + direction_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + + ship_flags = StarShipPtr->RaceDescPtr->ship_info.ship_flags; + for (fire_flags = FIRES_FORE, facing = StarShipPtr->ShipFacing; + fire_flags <= FIRES_LEFT; + fire_flags <<= 1, facing += QUADRANT) + { + if ((ship_flags & fire_flags) && NORMALIZE_FACING ( + direction_facing - facing + ANGLE_TO_FACING (OCTANT) + ) <= ANGLE_TO_FACING (QUADRANT)) + { + StarShipPtr->ship_input_state |= WEAPON; + break; + } + } + } +} + +RACE_DESCPTR +init_sis () +{ + RACE_DESCPTR RaceDescPtr; + + COUNT i; + static RACE_DESC new_sis_desc; + + /* copy initial ship settings to new_sis_desc */ + new_sis_desc = sis_desc; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + for (i = 0; i < NUM_VIEWS; ++i) + { + new_sis_desc.ship_data.ship[i] = 0; + new_sis_desc.ship_data.weapon[i] = 0; + new_sis_desc.ship_data.special[i] = 0; + } + new_sis_desc.ship_info.icons = 0; + new_sis_desc.ship_data.captain_control.background = 0; + new_sis_desc.ship_data.victory_ditty = 0; + new_sis_desc.ship_data.ship_sounds = 0; + + new_sis_desc.ship_data.ship[0] = (FRAME)SIS_HYPER_MASK_PMAP_ANIM; + + new_sis_desc.preprocess_func = sis_hyper_preprocess; + new_sis_desc.postprocess_func = sis_hyper_postprocess; + + new_sis_desc.characteristics.max_thrust -= 4; + } + else + { + new_sis_desc.preprocess_func = sis_battle_preprocess; + new_sis_desc.postprocess_func = sis_battle_postprocess; + new_sis_desc.init_weapon_func = initialize_blasters; + new_sis_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) sis_intelligence; + + num_trackers = 0; + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + BYTE which_mod; + + which_mod = GLOBAL_SIS (ModuleSlots[ + (NUM_MODULE_SLOTS - 1) - i + ]); + switch (which_mod) + { + case GUN_WEAPON: + case BLASTER_WEAPON: + case CANNON_WEAPON: + new_sis_desc.characteristics.weapon_energy_cost += + (which_mod - GUN_WEAPON + 1) * 2; + if (i <= 1) + new_sis_desc.ship_info.ship_flags |= FIRES_FORE; + else if (i == 2) + new_sis_desc.ship_info.ship_flags |= FIRES_LEFT | FIRES_RIGHT; + else + new_sis_desc.ship_info.ship_flags |= FIRES_AFT; + break; + case TRACKING_SYSTEM: + ++num_trackers; + break; + case ANTIMISSILE_DEFENSE: + ++new_sis_desc.characteristics.special_energy_cost; + break; + case SHIVA_FURNACE: + ++new_sis_desc.characteristics.energy_regeneration; + break; + case DYNAMO_UNIT: + if ((new_sis_desc.characteristics.energy_wait -= 2) < 4) + new_sis_desc.characteristics.energy_wait = 4; + break; + } + } + + if (num_trackers > MAX_TRACKING) + num_trackers = MAX_TRACKING; + new_sis_desc.characteristics.weapon_energy_cost += num_trackers * 3; + if (new_sis_desc.characteristics.special_energy_cost) + { + new_sis_desc.ship_info.ship_flags |= POINT_DEFENSE; + if (new_sis_desc.characteristics.special_energy_cost > MAX_DEFENSE) + new_sis_desc.characteristics.special_energy_cost = MAX_DEFENSE; + } + + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) + { + SET_GAME_STATE (BOMB_CARRIER, 1); + } + } + + new_sis_desc.characteristics.thrust_wait = 0; + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + switch (GLOBAL_SIS (DriveSlots[i])) + { + case FUSION_THRUSTER: + new_sis_desc.characteristics.max_thrust += 2; + ++new_sis_desc.characteristics.thrust_wait; + break; + } + } + new_sis_desc.characteristics.thrust_wait = (BYTE)( + THRUST_WAIT + - (new_sis_desc.characteristics.thrust_wait >> 1) + ); + new_sis_desc.characteristics.max_thrust = + ((new_sis_desc.characteristics.max_thrust / + new_sis_desc.characteristics.thrust_increment) + 1) + * new_sis_desc.characteristics.thrust_increment; + + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + switch (GLOBAL_SIS (JetSlots[i])) + { + case TURNING_JETS: + new_sis_desc.characteristics.turn_wait -= 2; + break; + } + } + + if (GLOBAL_SIS (CrewEnlisted) < MAX_CREW - 1) + new_sis_desc.ship_info.crew_level = (BYTE)( + GLOBAL_SIS (CrewEnlisted) + 1 + ); + new_sis_desc.ship_info.energy_level = new_sis_desc.ship_info.max_energy; + + RaceDescPtr = &new_sis_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/slylandr/icode.h b/sc2/src/sc2code/ships/slylandr/icode.h new file mode 100644 index 000000000..418942a0c --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/icode.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/slylandr/igfxres.h b/sc2/src/sc2code/ships/slylandr/igfxres.h new file mode 100644 index 000000000..29503be91 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/igfxres.h @@ -0,0 +1,8 @@ +#define SLYLANDRO_ICON_MASK_PMAP_ANIM 0x00200002L +#define SLYLANDRO_MICON_MASK_PMAP_ANIM 0x00200102L +#define SLYLANDRO_BIG_MASK_PMAP_ANIM 0x00400202L +#define SLYLANDRO_MED_MASK_PMAP_ANIM 0x00400302L +#define SLYLANDRO_SML_MASK_PMAP_ANIM 0x00400402L +#define SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM 0x00400502L + + diff --git a/sc2/src/sc2code/ships/slylandr/imusicre.h b/sc2/src/sc2code/ships/slylandr/imusicre.h new file mode 100644 index 000000000..b811c2b09 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/imusicre.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/slylandr/isndres.h b/sc2/src/sc2code/ships/slylandr/isndres.h new file mode 100644 index 000000000..f4f1c626a --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/isndres.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/slylandr/istrtab.h b/sc2/src/sc2code/ships/slylandr/istrtab.h new file mode 100644 index 000000000..52f733e5f --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/istrtab.h @@ -0,0 +1,3 @@ +#define SLYLANDRO_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/slylandr/resinst.h b/sc2/src/sc2code/ships/slylandr/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/slylandr/respkg.h b/sc2/src/sc2code/ships/slylandr/respkg.h new file mode 100644 index 000000000..78a62391f --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/respkg.h @@ -0,0 +1,6 @@ +enum +{ + SLYLANDRO_CODE_PACKAGE = 1, + SLYLANDRO_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/slylandr/restypes.h b/sc2/src/sc2code/ships/slylandr/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/slylandr/slylandr.c b/sc2/src/sc2code/ships/slylandr/slylandr.c new file mode 100644 index 000000000..5fae1e472 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/slylandr.c @@ -0,0 +1,429 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/slylandr/resinst.h" +#include "starcon.h" +#include "element.h" + +#define MAX_CREW 12 +#define MAX_ENERGY 20 +#define ENERGY_REGENERATION 0 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 0 +#define ENERGY_WAIT 10 +#define MAX_THRUST 60 +#define THRUST_INCREMENT MAX_THRUST +#define TURN_WAIT 0 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 17 +#define SPECIAL_WAIT 20 + +#define SHIP_MASS 1 +#define SLYLANDRO_OFFSET 9 + +static RACE_DESC slylandro_desc = +{ + { + SEEKING_WEAPON | CREW_IMMUNE, + 17, /* Super Melee cost */ + ~0, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 333, 9812, + }, + (STRING)SLYLANDRO_RACE_STRINGS, + (FRAME)SLYLANDRO_ICON_MASK_PMAP_ANIM, + (FRAME)SLYLANDRO_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SLYLANDRO_BIG_MASK_PMAP_ANIM, + (FRAME)SLYLANDRO_MED_MASK_PMAP_ANIM, + (FRAME)SLYLANDRO_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SLYLANDRO_VICTORY_SONG, + (SOUND)SLYLANDRO_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON << 1, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT initialize_lightning (PELEMENT ElementPtr, HELEMENT + LaserArray[]); + +static void +lightning_postprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait + && !(ElementPtr->state_flags & COLLISION)) + { + HELEMENT Lightning; + + initialize_lightning (ElementPtr, &Lightning); + if (Lightning) + PutElement (Lightning); + } +} + +static void +lightning_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (StarShipPtr->weapon_counter > WEAPON_WAIT >> 1) + StarShipPtr->weapon_counter = + WEAPON_WAIT - StarShipPtr->weapon_counter; + StarShipPtr->weapon_counter -= ElementPtr0->turn_wait; + ElementPtr0->turn_wait = 0; + + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +static COUNT +initialize_lightning (PELEMENT ElementPtr, HELEMENT LaserArray[]) +{ + LASER_BLOCK LaserBlock; + + LaserBlock.cx = ElementPtr->next.location.x; + LaserBlock.cy = ElementPtr->next.location.y; + LaserBlock.ex = 0; + LaserBlock.ey = 0; + + LaserBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.face = 0; + LaserBlock.pixoffs = 0; + LaserArray[0] = initialize_laser (&LaserBlock); + + if (LaserArray[0]) + { + SIZE delta; + COUNT angle, facing; + DWORD rand_val; + ELEMENTPTR LaserPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + LockElement (LaserArray[0], &LaserPtr); + LaserPtr->postprocess_func = lightning_postprocess; + LaserPtr->collision_func = lightning_collision; + + rand_val = Random (); + + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + { + angle = GetVelocityTravelAngle (&ElementPtr->velocity); + facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle)); + delta = TrackShip (ElementPtr, &facing); + + LaserPtr->turn_wait = ElementPtr->turn_wait - 1; + + SetPrimColor (&(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + GetPrimColor (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex])); + } + else + { + facing = StarShipPtr->ShipFacing; + ElementPtr->hTarget = 0; + delta = TrackShip (ElementPtr, &facing); + ElementPtr->hTarget = 0; + angle = FACING_TO_ANGLE (facing); + + if ((LaserPtr->turn_wait = StarShipPtr->weapon_counter) == 0) + LaserPtr->turn_wait = WEAPON_WAIT; + + if (LaserPtr->turn_wait > WEAPON_WAIT >> 1) + LaserPtr->turn_wait = WEAPON_WAIT - LaserPtr->turn_wait; + + switch (HIBYTE (LOWORD (rand_val)) & 3) + { + case 0: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + ); + break; + case 1: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x16, 0x17, 0x1F), 0x42) + ); + break; + case 2: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x6, 0x7, 0x1F), 0x4A) + ); + break; + case 3: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50) + ); + break; + } + } + + if (delta == -1 || delta == ANGLE_TO_FACING (HALF_CIRCLE)) + angle += LOWORD (rand_val); + else if (delta == 0) + angle += LOWORD (rand_val) & 1 ? -1 : 1; + else if (delta < ANGLE_TO_FACING (HALF_CIRCLE)) + angle += LOWORD (rand_val) & (QUADRANT - 1); + else + angle -= LOWORD (rand_val) & (QUADRANT - 1); +#define LASER_RANGE 32 + delta = WORLD_TO_VELOCITY ( + DISPLAY_TO_WORLD ((HIWORD (rand_val) & (LASER_RANGE - 1)) + 4) + ); + SetVelocityComponents (&LaserPtr->velocity, + COSINE (angle, delta), SINE (angle, delta)); + + SetElementStarShip (LaserPtr, StarShipPtr); + UnlockElement (LaserArray[0]); + } + + return (1); +} + +static void +slylandro_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER) + /* no dodging in role playing game */ + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->ship_info.energy_level == 0 + && ObjectsOfConcern[GRAVITY_MASS_INDEX].ObjectPtr == 0) + ConcernCounter = FIRST_EMPTY_INDEX + 1; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == PURSUE + && lpEvalDesc->which_turn <= 6) + lpEvalDesc->MoveState = ENTICE; + + ++ShipPtr->thrust_wait; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + --ShipPtr->thrust_wait; + + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= WEAPON; + else + StarShipPtr->ship_input_state &= ~WEAPON; + + StarShipPtr->ship_input_state &= ~SPECIAL; + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < + StarShipPtr->RaceDescPtr->ship_info.max_energy) + { + lpEvalDesc = &ObjectsOfConcern[FIRST_EMPTY_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static BOOLEAN +harvest_space_junk (ElementPtr) +PELEMENT ElementPtr; +{ + BOOLEAN retval; + HELEMENT hElement, hNextElement; + + retval = FALSE; + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENTPTR ObjPtr; + + LockElement (hElement, &ObjPtr); + hNextElement = GetSuccElement (ObjPtr); + + if (!(ObjPtr->state_flags + & (APPEARING | GOOD_GUY | BAD_GUY + | PLAYER_SHIP | FINITE_LIFE)) + && !GRAVITY_MASS (ObjPtr->mass_points) + && CollisionPossible (ObjPtr, ElementPtr)) + { +#define HARVEST_RANGE (SPACE_HEIGHT * 3 / 8) + SIZE dx, dy; + + if ((dx = ObjPtr->next.location.x + - ElementPtr->next.location.x) < 0) + dx = -dx; + if ((dy = ObjPtr->next.location.y + - ElementPtr->next.location.y) < 0) + dy = -dy; + dx = WORLD_TO_DISPLAY (dx); + dy = WORLD_TO_DISPLAY (dy); + if (dx <= HARVEST_RANGE && dy <= HARVEST_RANGE + && dx * dx + dy * dy <= HARVEST_RANGE * HARVEST_RANGE) + { + ObjPtr->life_span = 0; + ObjPtr->state_flags |= NONSOLID; + + if (!retval) + { + STARSHIPPTR StarShipPtr; + + retval = TRUE; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + DeltaEnergy (ElementPtr, MAX_ENERGY); + } + } + } + + UnlockElement (hElement); + } + + return (retval); +} + +static void +slylandro_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->weapon_counter + && StarShipPtr->weapon_counter < WEAPON_WAIT) + { + HELEMENT Lightning; + + initialize_lightning (ElementPtr, &Lightning); + if (Lightning) + PutElement (Lightning); + } + + if (StarShipPtr->special_counter == 0 + && (StarShipPtr->cur_status_flags & SPECIAL) + && harvest_space_junk (ElementPtr)) + { + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +static void +slylandro_preprocess (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & (APPEARING | NONSOLID))) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & THRUST) + && !(StarShipPtr->old_status_flags & THRUST)) + StarShipPtr->ShipFacing += ANGLE_TO_FACING (HALF_CIRCLE); + + if (ElementPtr->turn_wait == 0) + { + ElementPtr->turn_wait += + StarShipPtr->RaceDescPtr->characteristics.turn_wait + 1; + if (StarShipPtr->cur_status_flags & LEFT) + --StarShipPtr->ShipFacing; + else if (StarShipPtr->cur_status_flags & RIGHT) + ++StarShipPtr->ShipFacing; + } + + StarShipPtr->ShipFacing = NORMALIZE_FACING (StarShipPtr->ShipFacing); + + if (ElementPtr->thrust_wait == 0) + { + ElementPtr->thrust_wait += + StarShipPtr->RaceDescPtr->characteristics.thrust_wait + 1; + + SetVelocityVector (&ElementPtr->velocity, + StarShipPtr->RaceDescPtr->characteristics.max_thrust, + StarShipPtr->ShipFacing); + StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; + StarShipPtr->cur_status_flags &= ~SHIP_IN_GRAVITY_WELL; + } + + ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + } +} + +RACE_DESCPTR +init_slylandro () +{ + RACE_DESCPTR RaceDescPtr; + + slylandro_desc.preprocess_func = slylandro_preprocess; + slylandro_desc.postprocess_func = slylandro_postprocess; + slylandro_desc.init_weapon_func = initialize_lightning; + slylandro_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) slylandro_intelligence; + + RaceDescPtr = &slylandro_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/slylandr/slylandr.res b/sc2/src/sc2code/ships/slylandr/slylandr.res new file mode 100644 index 000000000..e3a63e424 --- /dev/null +++ b/sc2/src/sc2code/ships/slylandr/slylandr.res @@ -0,0 +1,20 @@ +INCLUDE ../star3do.typ + +PATH slylandr + +PACKAGE SLYLANDRO_CODE_PACKAGE slylandr.shp + CODE SLYLANDRO_CODE slylandr.cod + GFXRES SLYLANDRO_ICON_MASK_PMAP_ANIM slyicons.ani + GFXRES SLYLANDRO_MICON_MASK_PMAP_ANIM slymicon.ani + STRTAB SLYLANDRO_RACE_STRINGS slytext.txt + +PACKAGE SLYLANDRO_PACKAGE slylandr.shp + GFXRES SLYLANDRO_BIG_MASK_PMAP_ANIM slylandr.big + GFXRES SLYLANDRO_MED_MASK_PMAP_ANIM slylandr.med + GFXRES SLYLANDRO_SML_MASK_PMAP_ANIM slylandr.sml + + GFXRES SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM slycap.ani + SNDRES SLYLANDRO_SHIP_SOUNDS slysound.snd + + MUSICRES SLYLANDRO_VICTORY_SONG slyditty.mod + diff --git a/sc2/src/sc2code/ships/spathi/icode.h b/sc2/src/sc2code/ships/spathi/icode.h new file mode 100644 index 000000000..3b36d810b --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/icode.h @@ -0,0 +1,3 @@ +#define SPATHI_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/spathi/igfxres.h b/sc2/src/sc2code/ships/spathi/igfxres.h new file mode 100644 index 000000000..33720b1f2 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/igfxres.h @@ -0,0 +1,14 @@ +#define SPATHI_ICON_MASK_PMAP_ANIM 0x00200002L +#define SPATHI_MICON_MASK_PMAP_ANIM 0x00200102L +#define SPATHI_BIG_MASK_PMAP_ANIM 0x00400202L +#define SPATHI_MED_MASK_PMAP_ANIM 0x00400302L +#define SPATHI_SML_MASK_PMAP_ANIM 0x00400402L +#define MISSILE_BIG_MASK_PMAP_ANIM 0x00400502L +#define MISSILE_MED_MASK_PMAP_ANIM 0x00400602L +#define MISSILE_SML_MASK_PMAP_ANIM 0x00400702L +#define DISCRIM_BIG_MASK_PMAP_ANIM 0x00400802L +#define DISCRIM_MED_MASK_PMAP_ANIM 0x00400902L +#define DISCRIM_SML_MASK_PMAP_ANIM 0x00400a02L +#define SPATHI_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/spathi/imusicre.h b/sc2/src/sc2code/ships/spathi/imusicre.h new file mode 100644 index 000000000..eb663fef3 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/imusicre.h @@ -0,0 +1,3 @@ +#define SPATHI_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/spathi/isndres.h b/sc2/src/sc2code/ships/spathi/isndres.h new file mode 100644 index 000000000..66c42cb91 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/isndres.h @@ -0,0 +1,3 @@ +#define SPATHI_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/spathi/istrtab.h b/sc2/src/sc2code/ships/spathi/istrtab.h new file mode 100644 index 000000000..f7e3e0264 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/istrtab.h @@ -0,0 +1,3 @@ +#define SPATHI_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/spathi/resinst.h b/sc2/src/sc2code/ships/spathi/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/spathi/respkg.h b/sc2/src/sc2code/ships/spathi/respkg.h new file mode 100644 index 000000000..4562a1fcb --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/respkg.h @@ -0,0 +1,6 @@ +enum +{ + SPATHI_CODE_PACKAGE = 1, + SPATHI_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/spathi/restypes.h b/sc2/src/sc2code/ships/spathi/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/spathi/spathi.c b/sc2/src/sc2code/ships/spathi/spathi.c new file mode 100644 index 000000000..d7be9c179 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/spathi.c @@ -0,0 +1,294 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/spathi/resinst.h" +#include "starcon.h" + +#define MAX_CREW 30 +#define MAX_ENERGY 10 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 3 +#define ENERGY_WAIT 10 +#define MAX_THRUST 48 +#define THRUST_INCREMENT 12 +#define TURN_WAIT 1 +#define THRUST_WAIT 1 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 7 + +#define SHIP_MASS 5 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 10 +#define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) + +static RACE_DESC spathi_desc = +{ + { + FIRES_FORE | FIRES_AFT | SEEKING_SPECIAL | DONT_CHASE, + 18, /* Super Melee cost */ + 1000 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 2549, 3600, + }, + (STRING)SPATHI_RACE_STRINGS, + (FRAME)SPATHI_ICON_MASK_PMAP_ANIM, + (FRAME)SPATHI_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SPATHI_BIG_MASK_PMAP_ANIM, + (FRAME)SPATHI_MED_MASK_PMAP_ANIM, + (FRAME)SPATHI_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)MISSILE_BIG_MASK_PMAP_ANIM, + (FRAME)MISSILE_MED_MASK_PMAP_ANIM, + (FRAME)MISSILE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)DISCRIM_BIG_MASK_PMAP_ANIM, + (FRAME)DISCRIM_MED_MASK_PMAP_ANIM, + (FRAME)DISCRIM_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SPATHI_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SPATHI_VICTORY_SONG, + (SOUND)SPATHI_SHIP_SOUNDS, + }, + { + 0, + MISSILE_RANGE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define DISCRIMINATOR_SPEED DISPLAY_TO_WORLD (8) +#define TRACK_WAIT 1 + +static void +butt_missile_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT facing; + + facing = GetFrameIndex (ElementPtr->next.image.frame); + if (TrackShip (ElementPtr, &facing) > 0) + { + ElementPtr->next.image.frame = + SetAbsFrameIndex (ElementPtr->next.image.frame, + facing); + ElementPtr->state_flags |= CHANGING; + + SetVelocityVector (&ElementPtr->velocity, + DISCRIMINATOR_SPEED, facing); + } + + ElementPtr->turn_wait = TRACK_WAIT; + } +} + +static void +spawn_butt_missile (ShipPtr) +PELEMENT ShipPtr; +{ +#define SPATHI_REAR_OFFSET 20 +#define DISCRIMINATOR_LIFE 30 +#define DISCRIMINATOR_HITS 1 +#define DISCRIMINATOR_DAMAGE 2 +#define DISCRIMINATOR_OFFSET 4 + HELEMENT ButtMissile; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK ButtMissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + ButtMissileBlock.cx = ShipPtr->next.location.x; + ButtMissileBlock.cy = ShipPtr->next.location.y; + ButtMissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + ButtMissileBlock.face = ButtMissileBlock.index = + NORMALIZE_FACING (StarShipPtr->ShipFacing + + ANGLE_TO_FACING (HALF_CIRCLE)); + ButtMissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); + ButtMissileBlock.pixoffs = SPATHI_REAR_OFFSET; + ButtMissileBlock.speed = DISCRIMINATOR_SPEED; + ButtMissileBlock.hit_points = DISCRIMINATOR_HITS; + ButtMissileBlock.damage = DISCRIMINATOR_DAMAGE; + ButtMissileBlock.life = DISCRIMINATOR_LIFE; + ButtMissileBlock.preprocess_func = butt_missile_preprocess; + ButtMissileBlock.blast_offs = DISCRIMINATOR_OFFSET; + ButtMissile = initialize_missile (&ButtMissileBlock); + if (ButtMissile) + { + ELEMENTPTR ButtPtr; + + LockElement (ButtMissile, &ButtPtr); + ButtPtr->turn_wait = TRACK_WAIT; + SetElementStarShip (ButtPtr, StarShipPtr); + UnlockElement (ButtMissile); + PutElement (ButtMissile); + } +} + +static void +spathi_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->ship_input_state &= ~SPECIAL; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr + && lpEvalDesc->which_turn <= 24) + { + COUNT travel_facing, direction_facing; + SIZE delta_x, delta_y; + + travel_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + + HALF_CIRCLE) + ); + delta_x = lpEvalDesc->ObjectPtr->current.location.x + - ShipPtr->current.location.x; + delta_y = lpEvalDesc->ObjectPtr->current.location.y + - ShipPtr->current.location.y; + direction_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + + if (NORMALIZE_FACING (direction_facing + - (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)) + + ANGLE_TO_FACING (QUADRANT)) + <= ANGLE_TO_FACING (HALF_CIRCLE) + && (lpEvalDesc->which_turn <= 8 + || NORMALIZE_FACING (direction_facing + + ANGLE_TO_FACING (HALF_CIRCLE) + - ANGLE_TO_FACING (GetVelocityTravelAngle ( + &lpEvalDesc->ObjectPtr->velocity + )) + + ANGLE_TO_FACING (QUADRANT)) + <= ANGLE_TO_FACING (HALF_CIRCLE)) + && (!(StarShipPtr->cur_status_flags & + (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) + || NORMALIZE_FACING (direction_facing + - travel_facing + ANGLE_TO_FACING (QUADRANT)) + <= ANGLE_TO_FACING (HALF_CIRCLE))) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static COUNT +initialize_standard_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) +{ +#define SPATHI_FORWARD_OFFSET 16 +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 1 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = SPATHI_FORWARD_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + MissileArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +spathi_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* LAUNCH_BUTT_MISSILE */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + spawn_butt_missile (ElementPtr); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +RACE_DESCPTR +init_spathi () +{ + RACE_DESCPTR RaceDescPtr; + + spathi_desc.postprocess_func = spathi_postprocess; + spathi_desc.init_weapon_func = initialize_standard_missile; + spathi_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) spathi_intelligence; + + RaceDescPtr = &spathi_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/spathi/spathi.res b/sc2/src/sc2code/ships/spathi/spathi.res new file mode 100644 index 000000000..a62fe26f2 --- /dev/null +++ b/sc2/src/sc2code/ships/spathi/spathi.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH spathi + +PACKAGE SPATHI_CODE_PACKAGE spathi.shp + CODE SPATHI_CODE spathi.cod + GFXRES SPATHI_ICON_MASK_PMAP_ANIM spaicons.ani + GFXRES SPATHI_MICON_MASK_PMAP_ANIM spamicon.ani + STRTAB SPATHI_RACE_STRINGS spatext.txt + +PACKAGE SPATHI_PACKAGE spathi.shp + GFXRES SPATHI_BIG_MASK_PMAP_ANIM spathi.big + GFXRES SPATHI_MED_MASK_PMAP_ANIM spathi.med + GFXRES SPATHI_SML_MASK_PMAP_ANIM spathi.sml + GFXRES MISSILE_BIG_MASK_PMAP_ANIM missile.big + GFXRES MISSILE_MED_MASK_PMAP_ANIM missile.med + GFXRES MISSILE_SML_MASK_PMAP_ANIM missile.sml + GFXRES DISCRIM_BIG_MASK_PMAP_ANIM discrim.big + GFXRES DISCRIM_MED_MASK_PMAP_ANIM discrim.med + GFXRES DISCRIM_SML_MASK_PMAP_ANIM discrim.sml + + GFXRES SPATHI_CAPTAIN_MASK_PMAP_ANIM spacap.ani + SNDRES SPATHI_SHIP_SOUNDS spasound.snd + + MUSICRES SPATHI_VICTORY_SONG spaditty.mod + diff --git a/sc2/src/sc2code/ships/supox/icode.h b/sc2/src/sc2code/ships/supox/icode.h new file mode 100644 index 000000000..17535df1b --- /dev/null +++ b/sc2/src/sc2code/ships/supox/icode.h @@ -0,0 +1,3 @@ +#define SUPOX_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/supox/igfxres.h b/sc2/src/sc2code/ships/supox/igfxres.h new file mode 100644 index 000000000..baa2888ae --- /dev/null +++ b/sc2/src/sc2code/ships/supox/igfxres.h @@ -0,0 +1,11 @@ +#define SUPOX_ICON_MASK_PMAP_ANIM 0x00200002L +#define SUPOX_MICON_MASK_PMAP_ANIM 0x00200102L +#define SUPOX_BIG_MASK_PMAP_ANIM 0x00400202L +#define SUPOX_MED_MASK_PMAP_ANIM 0x00400302L +#define SUPOX_SML_MASK_PMAP_ANIM 0x00400402L +#define GOB_BIG_MASK_PMAP_ANIM 0x00400502L +#define GOB_MED_MASK_PMAP_ANIM 0x00400602L +#define GOB_SML_MASK_PMAP_ANIM 0x00400702L +#define SUPOX_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/supox/imusicre.h b/sc2/src/sc2code/ships/supox/imusicre.h new file mode 100644 index 000000000..bdd5b063a --- /dev/null +++ b/sc2/src/sc2code/ships/supox/imusicre.h @@ -0,0 +1,3 @@ +#define SUPOX_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/supox/isndres.h b/sc2/src/sc2code/ships/supox/isndres.h new file mode 100644 index 000000000..9493fc9c7 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/isndres.h @@ -0,0 +1,3 @@ +#define SUPOX_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/supox/istrtab.h b/sc2/src/sc2code/ships/supox/istrtab.h new file mode 100644 index 000000000..63dc2eb55 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/istrtab.h @@ -0,0 +1,3 @@ +#define SUPOX_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/supox/resinst.h b/sc2/src/sc2code/ships/supox/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/supox/respkg.h b/sc2/src/sc2code/ships/supox/respkg.h new file mode 100644 index 000000000..4857baa12 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/respkg.h @@ -0,0 +1,6 @@ +enum +{ + SUPOX_CODE_PACKAGE = 1, + SUPOX_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/supox/restypes.h b/sc2/src/sc2code/ships/supox/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/supox/supox.c b/sc2/src/sc2code/ships/supox/supox.c new file mode 100644 index 000000000..cbe4963f5 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/supox.c @@ -0,0 +1,278 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/supox/resinst.h" +#include "starcon.h" + +#define MAX_CREW 12 +#define MAX_ENERGY 16 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 1 +#define ENERGY_WAIT 4 +#define MAX_THRUST 40 +#define THRUST_INCREMENT 8 +#define TURN_WAIT 1 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 2 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 4 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 10 + +static RACE_DESC supox_desc = +{ + { + FIRES_FORE, + 16, /* Super Melee cost */ + 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 7468, 9246, + }, + (STRING)SUPOX_RACE_STRINGS, + (FRAME)SUPOX_ICON_MASK_PMAP_ANIM, + (FRAME)SUPOX_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SUPOX_BIG_MASK_PMAP_ANIM, + (FRAME)SUPOX_MED_MASK_PMAP_ANIM, + (FRAME)SUPOX_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)GOB_BIG_MASK_PMAP_ANIM, + (FRAME)GOB_MED_MASK_PMAP_ANIM, + (FRAME)GOB_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)SUPOX_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SUPOX_VICTORY_SONG, + (SOUND)SUPOX_SHIP_SOUNDS, + }, + { + 0, + (MISSILE_SPEED * MISSILE_LIFE) >> 1, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +supox_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->special_counter || lpEvalDesc->ObjectPtr == 0) + StarShipPtr->ship_input_state &= ~SPECIAL; + else + { + BOOLEAN LinedUp; + COUNT direction_angle; + SIZE delta_x, delta_y; + + delta_x = lpEvalDesc->ObjectPtr->next.location.x + - ShipPtr->next.location.x; + delta_y = lpEvalDesc->ObjectPtr->next.location.y + - ShipPtr->next.location.y; + direction_angle = ARCTAN (delta_x, delta_y); + + LinedUp = (BOOLEAN)(NORMALIZE_ANGLE (NORMALIZE_ANGLE (direction_angle + - FACING_TO_ANGLE (StarShipPtr->ShipFacing)) + + QUADRANT) <= HALF_CIRCLE); + + if (!LinedUp + || lpEvalDesc->which_turn > 20 + || NORMALIZE_ANGLE ( + lpEvalDesc->facing + - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + + HALF_CIRCLE) + OCTANT + ) > QUADRANT) + StarShipPtr->ship_input_state &= ~SPECIAL; + else if (LinedUp && lpEvalDesc->which_turn <= 12) + StarShipPtr->ship_input_state |= SPECIAL; + + if (StarShipPtr->ship_input_state & SPECIAL) + lpEvalDesc->MoveState = PURSUE; + } + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->ship_input_state & SPECIAL) + StarShipPtr->ship_input_state |= THRUST | WEAPON; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr + && lpEvalDesc->MoveState == AVOID + && ShipPtr->turn_wait == 0) + { + StarShipPtr->ship_input_state &= ~THRUST; + StarShipPtr->ship_input_state |= SPECIAL; + if (!(StarShipPtr->cur_status_flags & (LEFT | RIGHT))) + StarShipPtr->ship_input_state |= 1 << ((BYTE)Random () & 1); + else + StarShipPtr->ship_input_state |= + StarShipPtr->cur_status_flags & (LEFT | RIGHT); + } +} + +static COUNT +initialize_horn (PELEMENT ShipPtr, HELEMENT HornArray[]) +{ +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 2 +#define SUPOX_OFFSET 23 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = SUPOX_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + HornArray[0] = initialize_missile (&MissileBlock); + return (1); +} + +static void +supox_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) +/* + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST) +*/ + ) + { + SIZE add_facing; + + add_facing = 0; + if (StarShipPtr->cur_status_flags & THRUST) + { + if (ElementPtr->thrust_wait == 0) + ++ElementPtr->thrust_wait; + + add_facing = ANGLE_TO_FACING (HALF_CIRCLE); + } + if (StarShipPtr->cur_status_flags & LEFT) + { + if (ElementPtr->turn_wait == 0) + ++ElementPtr->turn_wait; + + if (add_facing) + add_facing += ANGLE_TO_FACING (OCTANT); + else + add_facing = -ANGLE_TO_FACING (QUADRANT); + } + else if (StarShipPtr->cur_status_flags & RIGHT) + { + if (ElementPtr->turn_wait == 0) + ++ElementPtr->turn_wait; + + if (add_facing) + add_facing -= ANGLE_TO_FACING (OCTANT); + else + add_facing = ANGLE_TO_FACING (QUADRANT); + } + + if (add_facing) + { + COUNT facing; + UWORD thrust_status; + + facing = StarShipPtr->ShipFacing; + StarShipPtr->ShipFacing = NORMALIZE_FACING ( + facing + add_facing + ); + thrust_status = inertial_thrust (ElementPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED + | SHIP_BEYOND_MAX_SPEED + | SHIP_IN_GRAVITY_WELL); + StarShipPtr->cur_status_flags |= thrust_status; + StarShipPtr->ShipFacing = facing; + } + } +} + +RACE_DESCPTR +init_supox () +{ + RACE_DESCPTR RaceDescPtr; + + supox_desc.preprocess_func = supox_preprocess; + supox_desc.init_weapon_func = initialize_horn; + supox_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) supox_intelligence; + + RaceDescPtr = &supox_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/supox/supox.res b/sc2/src/sc2code/ships/supox/supox.res new file mode 100644 index 000000000..6b604b0e0 --- /dev/null +++ b/sc2/src/sc2code/ships/supox/supox.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH supox + +PACKAGE SUPOX_CODE_PACKAGE supox.shp + CODE SUPOX_CODE supox.cod + GFXRES SUPOX_ICON_MASK_PMAP_ANIM supicons.ani + GFXRES SUPOX_MICON_MASK_PMAP_ANIM supmicon.ani + STRTAB SUPOX_RACE_STRINGS suptext.txt + +PACKAGE SUPOX_PACKAGE supox.shp + GFXRES SUPOX_BIG_MASK_PMAP_ANIM supox.big + GFXRES SUPOX_MED_MASK_PMAP_ANIM supox.med + GFXRES SUPOX_SML_MASK_PMAP_ANIM supox.sml + GFXRES GOB_BIG_MASK_PMAP_ANIM gobbig.ani + GFXRES GOB_MED_MASK_PMAP_ANIM gobmed.ani + GFXRES GOB_SML_MASK_PMAP_ANIM gobsml.ani + + GFXRES SUPOX_CAPTAIN_MASK_PMAP_ANIM supcap.ani + SNDRES SUPOX_SHIP_SOUNDS supsound.snd + + MUSICRES SUPOX_VICTORY_SONG supditty.mod + diff --git a/sc2/src/sc2code/ships/syreen/icode.h b/sc2/src/sc2code/ships/syreen/icode.h new file mode 100644 index 000000000..3864d2892 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/icode.h @@ -0,0 +1,3 @@ +#define SYREEN_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/syreen/igfxres.h b/sc2/src/sc2code/ships/syreen/igfxres.h new file mode 100644 index 000000000..6c510bd43 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/igfxres.h @@ -0,0 +1,11 @@ +#define SYREEN_ICON_MASK_PMAP_ANIM 0x00200002L +#define SYREEN_MICON_MASK_PMAP_ANIM 0x00200102L +#define SYREEN_BIG_MASK_PMAP_ANIM 0x00400202L +#define SYREEN_MED_MASK_PMAP_ANIM 0x00400302L +#define SYREEN_SML_MASK_PMAP_ANIM 0x00400402L +#define DAGGER_BIG_MASK_PMAP_ANIM 0x00400502L +#define DAGGER_MED_MASK_PMAP_ANIM 0x00400602L +#define DAGGER_SML_MASK_PMAP_ANIM 0x00400702L +#define SYREEN_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/syreen/imusicre.h b/sc2/src/sc2code/ships/syreen/imusicre.h new file mode 100644 index 000000000..84025d94e --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/imusicre.h @@ -0,0 +1,3 @@ +#define SYREEN_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/syreen/isndres.h b/sc2/src/sc2code/ships/syreen/isndres.h new file mode 100644 index 000000000..d251870c6 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/isndres.h @@ -0,0 +1,3 @@ +#define SYREEN_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/syreen/istrtab.h b/sc2/src/sc2code/ships/syreen/istrtab.h new file mode 100644 index 000000000..457b0b7d0 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/istrtab.h @@ -0,0 +1,3 @@ +#define SYREEN_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/syreen/resinst.h b/sc2/src/sc2code/ships/syreen/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/syreen/respkg.h b/sc2/src/sc2code/ships/syreen/respkg.h new file mode 100644 index 000000000..fee31f463 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/respkg.h @@ -0,0 +1,6 @@ +enum +{ + SYREEN_CODE_PACKAGE = 1, + SYREEN_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/syreen/restypes.h b/sc2/src/sc2code/ships/syreen/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/syreen/syreen.c b/sc2/src/sc2code/ships/syreen/syreen.c new file mode 100644 index 000000000..208a7feb6 --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/syreen.c @@ -0,0 +1,275 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/syreen/resinst.h" +#include "starcon.h" + +#define SYREEN_MAX_CREW_SIZE MAX_CREW_SIZE +#define MAX_CREW 12 +#define MAX_ENERGY 16 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 5 +#define ENERGY_WAIT 6 +#define MAX_THRUST /* DISPLAY_TO_WORLD (8) */ 36 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 9 +#define TURN_WAIT 1 +#define THRUST_WAIT 1 +#define WEAPON_WAIT 8 +#define SPECIAL_WAIT 20 + +#define SHIP_MASS 2 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 10 + +static RACE_DESC syreen_desc = +{ + { + FIRES_FORE, + 13, /* Super Melee cost */ + 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, SYREEN_MAX_CREW_SIZE, + MAX_ENERGY, MAX_ENERGY, + { + 0, 0, + }, + (STRING)SYREEN_RACE_STRINGS, + (FRAME)SYREEN_ICON_MASK_PMAP_ANIM, + (FRAME)SYREEN_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)SYREEN_BIG_MASK_PMAP_ANIM, + (FRAME)SYREEN_MED_MASK_PMAP_ANIM, + (FRAME)SYREEN_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)DAGGER_BIG_MASK_PMAP_ANIM, + (FRAME)DAGGER_MED_MASK_PMAP_ANIM, + (FRAME)DAGGER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)SYREEN_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)SYREEN_VICTORY_SONG, + (SOUND)SYREEN_SHIP_SOUNDS, + }, + { + 0, + (MISSILE_SPEED * MISSILE_LIFE * 2 / 3), + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_dagger (PELEMENT ShipPtr, HELEMENT DaggerArray[]) +{ +#define SYREEN_OFFSET 30 +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 2 +#define MISSILE_OFFSET 3 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = SYREEN_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + DaggerArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +spawn_crew (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hCrew; + + if ((hCrew = AllocElement ()) != 0) + { + ELEMENTPTR CrewPtr; + + LockElement (hCrew, &CrewPtr); + CrewPtr->next.location = ElementPtr->next.location; + CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + CrewPtr->life_span = 0; + { + CrewPtr->death_func = spawn_crew; + } + CrewPtr->pParent = ElementPtr->pParent; + CrewPtr->hTarget = 0; + UnlockElement (hCrew); + + PutElement (hCrew); + } + } + else + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENTPTR ObjPtr; + + LockElement (hElement, &ObjPtr); + hNextElement = GetSuccElement (ObjPtr); + + if ((ObjPtr->state_flags & PLAYER_SHIP) + && (ObjPtr->state_flags & (GOOD_GUY | BAD_GUY)) != + (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + && ObjPtr->crew_level > 1) + { + SIZE dx, dy; + DWORD d_squared; + + if ((dx = ObjPtr->next.location.x + - ElementPtr->next.location.x) < 0) + dx = -dx; + if ((dy = ObjPtr->next.location.y + - ElementPtr->next.location.y) < 0) + dy = -dy; + dx = WORLD_TO_DISPLAY (dx); + dy = WORLD_TO_DISPLAY (dy); + if (dx <= SPACE_HEIGHT && dy <= SPACE_HEIGHT + && (d_squared = (DWORD)((UWORD)dx * (UWORD)dx) + + (DWORD)((UWORD)dy * (UWORD)dy)) <= + (DWORD)((UWORD)SPACE_HEIGHT * (UWORD)SPACE_HEIGHT)) + { +#define MAX_ABANDONERS 8 + COUNT crew_loss; + + crew_loss = ((MAX_ABANDONERS + * (SPACE_HEIGHT - square_root (d_squared))) + / SPACE_HEIGHT) + 1; + if (crew_loss >= ObjPtr->crew_level) + crew_loss = ObjPtr->crew_level - 1; + + AbandonShip (ObjPtr, ElementPtr, crew_loss); + } + } + + UnlockElement (hElement); + } + } +} + +static void +syreen_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr != NULL_PTR) + { + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) + && StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr->crew_level > 1 + && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + } +} + +static void +syreen_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* SYREEN_SONG */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + spawn_crew (ElementPtr); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +RACE_DESCPTR +init_syreen () +{ + RACE_DESCPTR RaceDescPtr; + + syreen_desc.postprocess_func = syreen_postprocess; + syreen_desc.init_weapon_func = initialize_dagger; + syreen_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) syreen_intelligence; + + RaceDescPtr = &syreen_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/syreen/syreen.res b/sc2/src/sc2code/ships/syreen/syreen.res new file mode 100644 index 000000000..7bec7f54b --- /dev/null +++ b/sc2/src/sc2code/ships/syreen/syreen.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH syreen + +PACKAGE SYREEN_CODE_PACKAGE syreen.shp + CODE SYREEN_CODE syreen.cod + GFXRES SYREEN_ICON_MASK_PMAP_ANIM syricons.ani + GFXRES SYREEN_MICON_MASK_PMAP_ANIM syrmicon.ani + STRTAB SYREEN_RACE_STRINGS syrtext.txt + +PACKAGE SYREEN_PACKAGE syreen.shp + GFXRES SYREEN_BIG_MASK_PMAP_ANIM syreen.big + GFXRES SYREEN_MED_MASK_PMAP_ANIM syreen.med + GFXRES SYREEN_SML_MASK_PMAP_ANIM syreen.sml + GFXRES DAGGER_BIG_MASK_PMAP_ANIM dagger.big + GFXRES DAGGER_MED_MASK_PMAP_ANIM dagger.med + GFXRES DAGGER_SML_MASK_PMAP_ANIM dagger.sml + + GFXRES SYREEN_CAPTAIN_MASK_PMAP_ANIM syrcap.ani + SNDRES SYREEN_SHIP_SOUNDS syrsound.snd + + MUSICRES SYREEN_VICTORY_SONG syrditty.mod + diff --git a/sc2/src/sc2code/ships/thradd/icode.h b/sc2/src/sc2code/ships/thradd/icode.h new file mode 100644 index 000000000..f30bb2a65 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/icode.h @@ -0,0 +1,3 @@ +#define THRADDASH_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/thradd/igfxres.h b/sc2/src/sc2code/ships/thradd/igfxres.h new file mode 100644 index 000000000..ec202f6fe --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/igfxres.h @@ -0,0 +1,14 @@ +#define THRADDASH_ICON_MASK_PMAP_ANIM 0x00200002L +#define THRADDASH_MICON_MASK_PMAP_ANIM 0x00200102L +#define THRADDASH_BIG_MASK_PMAP_ANIM 0x00400202L +#define THRADDASH_MED_MASK_PMAP_ANIM 0x00400302L +#define THRADDASH_SML_MASK_PMAP_ANIM 0x00400402L +#define HORN_BIG_MASK_PMAP_ANIM 0x00400502L +#define HORN_MED_MASK_PMAP_ANIM 0x00400602L +#define HORN_SML_MASK_PMAP_ANIM 0x00400702L +#define NAPALM_BIG_MASK_PMAP_ANIM 0x00400802L +#define NAPALM_MED_MASK_PMAP_ANIM 0x00400902L +#define NAPALM_SML_MASK_PMAP_ANIM 0x00400a02L +#define THRADDASH_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/thradd/imusicre.h b/sc2/src/sc2code/ships/thradd/imusicre.h new file mode 100644 index 000000000..ab8ee15ae --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/imusicre.h @@ -0,0 +1,3 @@ +#define THRADDASH_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/thradd/isndres.h b/sc2/src/sc2code/ships/thradd/isndres.h new file mode 100644 index 000000000..e50fa25d2 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/isndres.h @@ -0,0 +1,3 @@ +#define THRADDASH_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/thradd/istrtab.h b/sc2/src/sc2code/ships/thradd/istrtab.h new file mode 100644 index 000000000..4602837a4 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/istrtab.h @@ -0,0 +1,3 @@ +#define THRADDASH_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/thradd/resinst.h b/sc2/src/sc2code/ships/thradd/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/thradd/respkg.h b/sc2/src/sc2code/ships/thradd/respkg.h new file mode 100644 index 000000000..893695b12 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/respkg.h @@ -0,0 +1,6 @@ +enum +{ + THRADDASH_CODE_PACKAGE = 1, + THRADDASH_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/thradd/restypes.h b/sc2/src/sc2code/ships/thradd/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/thradd/thradd.c b/sc2/src/sc2code/ships/thradd/thradd.c new file mode 100644 index 000000000..c1e189b76 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/thradd.c @@ -0,0 +1,384 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/thradd/resinst.h" +#include "starcon.h" + +#define MAX_CREW 8 +#define MAX_ENERGY 24 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 2 +#define SPECIAL_ENERGY_COST 1 +#define ENERGY_WAIT 6 +#define MAX_THRUST 28 +#define THRUST_INCREMENT 7 +#define TURN_WAIT 1 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 12 +#define SPECIAL_WAIT 0 + +#define SHIP_MASS 7 +#define THRADDASH_OFFSET 9 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 15 + +static RACE_DESC thraddash_desc = +{ + { + FIRES_FORE, + 10, /* Super Melee cost */ + 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 2535, 8358, + }, + (STRING)THRADDASH_RACE_STRINGS, + (FRAME)THRADDASH_ICON_MASK_PMAP_ANIM, + (FRAME)THRADDASH_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)THRADDASH_BIG_MASK_PMAP_ANIM, + (FRAME)THRADDASH_MED_MASK_PMAP_ANIM, + (FRAME)THRADDASH_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)HORN_BIG_MASK_PMAP_ANIM, + (FRAME)HORN_MED_MASK_PMAP_ANIM, + (FRAME)HORN_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)NAPALM_BIG_MASK_PMAP_ANIM, + (FRAME)NAPALM_MED_MASK_PMAP_ANIM, + (FRAME)NAPALM_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)THRADDASH_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)THRADDASH_VICTORY_SONG, + (SOUND)THRADDASH_SHIP_SOUNDS, + }, + { + 0, + (MISSILE_SPEED * MISSILE_LIFE) >> 1, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +thraddash_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr) + { +#define STATIONARY_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (4)) + SIZE dx, dy; + + GetCurrentVelocityComponents ( + &lpEvalDesc->ObjectPtr->velocity, &dx, &dy + ); + if (lpEvalDesc->which_turn > 8 + || (long)dx * dx + (long)dy * dy <= + (long)STATIONARY_SPEED * STATIONARY_SPEED) + lpEvalDesc->MoveState = PURSUE; + else + lpEvalDesc->MoveState = ENTICE; + } + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) + { + if ((StarShipPtr->ship_input_state & THRUST) + || (ShipPtr->turn_wait == 0 + && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) + || NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle ( + &ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->velocity + ) + HALF_CIRCLE + OCTANT) + - StarShipPtr->ShipFacing) > ANGLE_TO_FACING (QUADRANT)) + StarShipPtr->ship_input_state |= SPECIAL; + } + else if (lpEvalDesc->ObjectPtr) + { + if (lpEvalDesc->MoveState == PURSUE) + { + if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST + + SPECIAL_ENERGY_COST + && ShipPtr->turn_wait == 0 + && !(StarShipPtr->ship_input_state & (LEFT | RIGHT)) + && (!(StarShipPtr->cur_status_flags & SPECIAL) + || !(StarShipPtr->cur_status_flags + & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)))) + StarShipPtr->ship_input_state |= SPECIAL; + } + else if (lpEvalDesc->MoveState == ENTICE) + { + COUNT direction_angle; + SIZE delta_x, delta_y; + + delta_x = lpEvalDesc->ObjectPtr->next.location.x + - ShipPtr->next.location.x; + delta_y = lpEvalDesc->ObjectPtr->next.location.y + - ShipPtr->next.location.y; + direction_angle = ARCTAN (delta_x, delta_y); + + if ((lpEvalDesc->which_turn > 24 + && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) + || (lpEvalDesc->which_turn <= 16 + && NORMALIZE_ANGLE (direction_angle + - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + + QUADRANT) <= HALF_CIRCLE + && (lpEvalDesc->which_turn < 12 + || NORMALIZE_ANGLE (direction_angle + - (GetVelocityTravelAngle ( + &lpEvalDesc->ObjectPtr->velocity + ) + HALF_CIRCLE) + + (OCTANT + 2)) <= ((OCTANT + 2) << 1)))) + StarShipPtr->ship_input_state |= SPECIAL; + } + } + + if ((StarShipPtr->ship_input_state & SPECIAL) + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= + SPECIAL_ENERGY_COST) + StarShipPtr->ship_input_state &= ~THRUST; + } +} + +#define NAPALM_WAIT 1 + +static void +flame_napalm_preprocess (PELEMENT ElementPtr) +{ + ZeroVelocityComponents (&ElementPtr->velocity); + + if (ElementPtr->state_flags & NONSOLID) + { + ElementPtr->state_flags &= ~NONSOLID; + ElementPtr->state_flags |= APPEARING; + SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + STAMP_PRIM); + + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + } + else if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { +#define NUM_NAPALM_FADES 6 + if (ElementPtr->life_span <= NUM_NAPALM_FADES * (NAPALM_WAIT + 1) + || GetFrameIndex ( + ElementPtr->current.image.frame + ) != NUM_NAPALM_FADES) + ElementPtr->next.image.frame = + DecFrameIndex (ElementPtr->current.image.frame); + else if (ElementPtr->life_span > NUM_NAPALM_FADES * (NAPALM_WAIT + 1)) + ElementPtr->next.image.frame = SetAbsFrameIndex ( + ElementPtr->current.image.frame, + GetFrameCount (ElementPtr->current.image.frame) - 1 + ); + + ElementPtr->turn_wait = NAPALM_WAIT; + ElementPtr->state_flags |= CHANGING; + } +} + +static COUNT +initialize_horn (PELEMENT ShipPtr, HELEMENT HornArray[]) +{ +#define MISSILE_HITS 2 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 3 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = THRADDASH_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + HornArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +thraddash_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (!(StarShipPtr->cur_status_flags & SPECIAL)) + { + if ((StarShipPtr->old_status_flags & SPECIAL) + && (StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED)) + StarShipPtr->cur_status_flags |= SHIP_BEYOND_MAX_SPEED; + } + else if (DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { +#define SPECIAL_THRUST_INCREMENT 12 +#define SPECIAL_MAX_THRUST 72 + COUNT max_thrust, thrust_increment; + UWORD thrust_status; + HELEMENT hTrailElement; + + if (!(StarShipPtr->old_status_flags & SPECIAL)) + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + + if (ElementPtr->thrust_wait == 0) + ++ElementPtr->thrust_wait; + + thrust_increment = + StarShipPtr->RaceDescPtr->characteristics.thrust_increment; + max_thrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; + StarShipPtr->RaceDescPtr->characteristics.thrust_increment = + SPECIAL_THRUST_INCREMENT; + StarShipPtr->RaceDescPtr->characteristics.max_thrust = + SPECIAL_MAX_THRUST; + + thrust_status = inertial_thrust (ElementPtr); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED + | SHIP_BEYOND_MAX_SPEED + | SHIP_IN_GRAVITY_WELL); + StarShipPtr->cur_status_flags |= thrust_status; + + StarShipPtr->RaceDescPtr->characteristics.thrust_increment = + thrust_increment; + StarShipPtr->RaceDescPtr->characteristics.max_thrust = max_thrust; + + { +#define NAPALM_HITS 1 +#define NAPALM_DAMAGE 2 +#define NAPALM_LIFE 48 +#define NAPALM_OFFSET 0 + MISSILE_BLOCK MissileBlock; + + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + MissileBlock.face = 0; + MissileBlock.index = GetFrameCount ( + StarShipPtr->RaceDescPtr->ship_data.special[0] + ) - 1; + MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = 0; + MissileBlock.speed = 0; + MissileBlock.hit_points = NAPALM_HITS; + MissileBlock.damage = NAPALM_DAMAGE; + MissileBlock.life = NAPALM_LIFE; + MissileBlock.preprocess_func = flame_napalm_preprocess; + MissileBlock.blast_offs = NAPALM_OFFSET; + + hTrailElement = initialize_missile (&MissileBlock); + if (hTrailElement) + { + ELEMENTPTR TrailElementPtr; + + LockElement (hTrailElement, &TrailElementPtr); + SetElementStarShip (TrailElementPtr, StarShipPtr); + TrailElementPtr->hTarget = 0; + TrailElementPtr->turn_wait = NAPALM_WAIT; + + TrailElementPtr->state_flags |= NONSOLID; + SetPrimType ( + &(GLOBAL (DisplayArray))[TrailElementPtr->PrimIndex], + NO_PRIM + ); + + /* normally done during preprocess, but because + * object is being inserted at head rather than + * appended after tail it may never get preprocessed. + */ + TrailElementPtr->next = TrailElementPtr->current; + TrailElementPtr->state_flags |= PRE_PROCESS; + + UnlockElement (hTrailElement); + InsertElement (hTrailElement, GetHeadElement ()); + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + } + } + } +} + +RACE_DESCPTR +init_thraddash () +{ + RACE_DESCPTR RaceDescPtr; + + thraddash_desc.preprocess_func = thraddash_preprocess; + thraddash_desc.init_weapon_func = initialize_horn; + thraddash_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) thraddash_intelligence; + + RaceDescPtr = &thraddash_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/thradd/thradd.res b/sc2/src/sc2code/ships/thradd/thradd.res new file mode 100644 index 000000000..e723ccf45 --- /dev/null +++ b/sc2/src/sc2code/ships/thradd/thradd.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH thradd + +PACKAGE THRADDASH_CODE_PACKAGE thradd.shp + CODE THRADDASH_CODE thradd.cod + GFXRES THRADDASH_ICON_MASK_PMAP_ANIM thricons.ani + GFXRES THRADDASH_MICON_MASK_PMAP_ANIM thrmicon.ani + STRTAB THRADDASH_RACE_STRINGS thrtext.txt + +PACKAGE THRADDASH_PACKAGE thradd.shp + GFXRES THRADDASH_BIG_MASK_PMAP_ANIM thradd.big + GFXRES THRADDASH_MED_MASK_PMAP_ANIM thradd.med + GFXRES THRADDASH_SML_MASK_PMAP_ANIM thradd.sml + GFXRES HORN_BIG_MASK_PMAP_ANIM horbig.ani + GFXRES HORN_MED_MASK_PMAP_ANIM hormed.ani + GFXRES HORN_SML_MASK_PMAP_ANIM horsml.ani + GFXRES NAPALM_BIG_MASK_PMAP_ANIM napbig.ani + GFXRES NAPALM_MED_MASK_PMAP_ANIM napmed.ani + GFXRES NAPALM_SML_MASK_PMAP_ANIM napsml.ani + + GFXRES THRADDASH_CAPTAIN_MASK_PMAP_ANIM thrcap.ani + SNDRES THRADDASH_SHIP_SOUNDS thrsound.snd + + MUSICRES THRADDASH_VICTORY_SONG thrditty.mod + diff --git a/sc2/src/sc2code/ships/umgah/icode.h b/sc2/src/sc2code/ships/umgah/icode.h new file mode 100644 index 000000000..6f9029b21 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/icode.h @@ -0,0 +1,3 @@ +#define UMGAH_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/umgah/igfxres.h b/sc2/src/sc2code/ships/umgah/igfxres.h new file mode 100644 index 000000000..e528e4bc0 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/igfxres.h @@ -0,0 +1,12 @@ +#define UMGAH_ICON_MASK_PMAP_ANIM 0x00200002L +#define UMGAH_MICON_MASK_PMAP_ANIM 0x00200102L +#define UMGAH_BIG_MASK_PMAP_ANIM 0x00400202L +#define UMGAH_MED_MASK_PMAP_ANIM 0x00400302L +#define UMGAH_SML_MASK_PMAP_ANIM 0x00400402L +#define SPRITZ_MASK_PMAP_ANIM 0x00400502L +#define CONE_BIG_MASK_ANIM 0x00400602L +#define CONE_MED_MASK_ANIM 0x00400702L +#define CONE_SML_MASK_ANIM 0x00400802L +#define UMGAH_CAPTAIN_MASK_PMAP_ANIM 0x00400902L + + diff --git a/sc2/src/sc2code/ships/umgah/imusicre.h b/sc2/src/sc2code/ships/umgah/imusicre.h new file mode 100644 index 000000000..f9a6c570e --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/imusicre.h @@ -0,0 +1,3 @@ +#define UMGAH_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/umgah/isndres.h b/sc2/src/sc2code/ships/umgah/isndres.h new file mode 100644 index 000000000..18a7345f2 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/isndres.h @@ -0,0 +1,3 @@ +#define UMGAH_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/umgah/istrtab.h b/sc2/src/sc2code/ships/umgah/istrtab.h new file mode 100644 index 000000000..b0144fc72 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/istrtab.h @@ -0,0 +1,3 @@ +#define UMGAH_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/umgah/resinst.h b/sc2/src/sc2code/ships/umgah/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/umgah/respkg.h b/sc2/src/sc2code/ships/umgah/respkg.h new file mode 100644 index 000000000..8fc5f3fac --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/respkg.h @@ -0,0 +1,6 @@ +enum +{ + UMGAH_CODE_PACKAGE = 1, + UMGAH_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/umgah/restypes.h b/sc2/src/sc2code/ships/umgah/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/umgah/umgah.c b/sc2/src/sc2code/ships/umgah/umgah.c new file mode 100644 index 000000000..c205695ab --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/umgah.c @@ -0,0 +1,370 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/umgah/resinst.h" +#include "starcon.h" + +#define MAX_CREW 10 +#define MAX_ENERGY 30 +#define ENERGY_REGENERATION MAX_ENERGY +#define WEAPON_ENERGY_COST 0 +#define SPECIAL_ENERGY_COST 1 +#define ENERGY_WAIT 150 +#define MAX_THRUST /* DISPLAY_TO_WORLD (5) */ 18 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 6 +#define TURN_WAIT 4 +#define THRUST_WAIT 3 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 2 + +#define SHIP_MASS 1 + +static FRAME LastShipFrame[2]; + +static RACE_DESC umgah_desc = +{ + { + FIRES_FORE | IMMEDIATE_WEAPON, + 7, /* Super Melee cost */ + 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 1798, 6000, + }, + (STRING)UMGAH_RACE_STRINGS, + (FRAME)UMGAH_ICON_MASK_PMAP_ANIM, + (FRAME)UMGAH_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)UMGAH_BIG_MASK_PMAP_ANIM, + (FRAME)UMGAH_MED_MASK_PMAP_ANIM, + (FRAME)UMGAH_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SPRITZ_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)CONE_BIG_MASK_ANIM, + (FRAME)CONE_MED_MASK_ANIM, + (FRAME)CONE_SML_MASK_ANIM, + }, + { + (FRAME)UMGAH_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)UMGAH_VICTORY_SONG, + (SOUND)UMGAH_SHIP_SOUNDS, + }, + { + 0, + (LONG_RANGE_WEAPON << 2), + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static void +cone_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->RaceDescPtr->ship_data.special[0] = + SetRelFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], + ANGLE_TO_FACING (FULL_CIRCLE)); + + ElementPtr->state_flags |= APPEARING; +} + +static void +cone_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + HELEMENT hBlastElement; + + hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + if (hBlastElement) + { + RemoveElement (hBlastElement); + FreeElement (hBlastElement); + + ElementPtr0->state_flags &= ~DISAPPEARING; + } +} + +#define JUMP_DIST DISPLAY_TO_WORLD (40) + +static void +umgah_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr, EnemyStarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) + { + if (lpEvalDesc->which_turn > 3 + || (StarShipPtr->old_status_flags & SPECIAL)) + lpEvalDesc->ObjectPtr = 0; + else if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) + && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + lpEvalDesc->MoveState = AVOID; + else + lpEvalDesc->MoveState = PURSUE; + } + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (StarShipPtr->special_counter + || ObjectsOfConcern[GRAVITY_MASS_INDEX].ObjectPtr + || lpEvalDesc->ObjectPtr == 0) + { + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (lpEvalDesc->which_turn < 16) + StarShipPtr->ship_input_state |= WEAPON; + StarShipPtr->ship_input_state &= ~SPECIAL; + } + else + { + BYTE this_turn; + SIZE delta_x, delta_y; + BOOLEAN EnemyBehind, EnoughJuice; + + if (lpEvalDesc->which_turn >= 0xFF + 1) + this_turn = 0xFF; + else + this_turn = (BYTE)lpEvalDesc->which_turn; + + EnoughJuice = (BOOLEAN)(WORLD_TO_TURN ( + JUMP_DIST * StarShipPtr->RaceDescPtr->ship_info.energy_level + / SPECIAL_ENERGY_COST + ) > this_turn); + delta_x = lpEvalDesc->ObjectPtr->next.location.x - + ShipPtr->next.location.x; + delta_y = lpEvalDesc->ObjectPtr->next.location.y - + ShipPtr->next.location.y; + EnemyBehind = (BOOLEAN)(NORMALIZE_ANGLE ( + ARCTAN (delta_x, delta_y) + - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + + HALF_CIRCLE) + (OCTANT + (OCTANT >> 2)) + ) <= ((OCTANT + (OCTANT >> 2)) << 1)); + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (EnoughJuice + && ((StarShipPtr->old_status_flags & SPECIAL) + || EnemyBehind + || (this_turn > 6 + && MANEUVERABILITY ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) <= SLOW_SHIP) + || (this_turn >= 16 && this_turn <= 24))) + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = (LONG_RANGE_WEAPON << 3); + else + StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + if (StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange == CLOSE_RANGE_WEAPON) + StarShipPtr->ship_input_state &= ~SPECIAL; + else + { + BOOLEAN LinedUp; + + StarShipPtr->ship_input_state &= ~THRUST; + LinedUp = (BOOLEAN)(ShipPtr->turn_wait == 0 + && !(StarShipPtr->old_status_flags & (LEFT | RIGHT))); + if (((StarShipPtr->old_status_flags & SPECIAL) + && this_turn <= StarShipPtr->RaceDescPtr->characteristics.special_wait) + || (!(StarShipPtr->old_status_flags & SPECIAL) + && EnemyBehind && (LinedUp || this_turn < 16))) + { + StarShipPtr->ship_input_state |= SPECIAL; + StarShipPtr->RaceDescPtr->characteristics.special_wait = this_turn; + + /* don't want him backing straight into ship */ + if (this_turn <= 8 && LinedUp) + { + if (Random () & 1) + StarShipPtr->ship_input_state |= LEFT; + else + StarShipPtr->ship_input_state |= RIGHT; + } + } + else if (StarShipPtr->old_status_flags & SPECIAL) + { + StarShipPtr->ship_input_state &= ~(SPECIAL | LEFT | RIGHT); + StarShipPtr->ship_input_state |= THRUST; + } + } + + if (this_turn < 16 && !EnemyBehind) + StarShipPtr->ship_input_state |= WEAPON; + } + + if (!(StarShipPtr->ship_input_state & SPECIAL)) + StarShipPtr->RaceDescPtr->characteristics.special_wait = 0xFF; +} +static COUNT +initialize_cone (PELEMENT ShipPtr, HELEMENT ConeArray[]) +{ +#define UMGAH_OFFSET 0 +#define MISSILE_SPEED 0 +#define MISSILE_HITS 100 +#define MISSILE_DAMAGE 1 +#define MISSILE_LIFE 1 +#define MISSILE_OFFSET 0 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = UMGAH_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = cone_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + + if (ShipPtr->next.image.frame != LastShipFrame[WHICH_SIDE(ShipPtr->state_flags)]) + { + LastShipFrame[WHICH_SIDE(ShipPtr->state_flags)] = ShipPtr->next.image.frame; + + StarShipPtr->RaceDescPtr->ship_data.special[0] = + SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.special[0], + StarShipPtr->ShipFacing + ); + } + + MissileBlock.index = GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0]); + ConeArray[0] = initialize_missile (&MissileBlock); + + if (ConeArray[0]) + { + ELEMENTPTR ConePtr; + + LockElement (ConeArray[0], &ConePtr); + ConePtr->collision_func = cone_collision; + ConePtr->state_flags &= ~APPEARING; + ConePtr->next = ConePtr->current; + InitIntersectStartPoint (ConePtr); + InitIntersectEndPoint (ConePtr); + ConePtr->IntersectControl.IntersectStamp.frame = + StarShipPtr->RaceDescPtr->ship_data.special[0]; + UnlockElement (ConeArray[0]); + } + + return (1); +} + +static void +umgah_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->special_counter > 0) + { + StarShipPtr->special_counter = 0; + + ZeroVelocityComponents (&ElementPtr->velocity); + } +} + +static void +umgah_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & APPEARING) + LastShipFrame[WHICH_SIDE(ElementPtr->state_flags)] = 0; + else + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->thrust_wait == 0 + && (StarShipPtr->cur_status_flags & SPECIAL) + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + COUNT facing; + + ProcessSound (SetAbsSoundIndex ( + /* ZIP_BACKWARDS */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + facing = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; + DeltaVelocityComponents (&ElementPtr->velocity, + COSINE (facing, WORLD_TO_VELOCITY (JUMP_DIST)), + SINE (facing, WORLD_TO_VELOCITY (JUMP_DIST))); + StarShipPtr->cur_status_flags &= + ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); + + StarShipPtr->special_counter = SPECIAL_WAIT; + } + } +} + +RACE_DESCPTR +init_umgah () +{ + RACE_DESCPTR RaceDescPtr; + + umgah_desc.preprocess_func = umgah_preprocess; + umgah_desc.postprocess_func = umgah_postprocess; + umgah_desc.init_weapon_func = initialize_cone; + umgah_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) umgah_intelligence; + + RaceDescPtr = &umgah_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/umgah/umgah.res b/sc2/src/sc2code/ships/umgah/umgah.res new file mode 100644 index 000000000..56570bad7 --- /dev/null +++ b/sc2/src/sc2code/ships/umgah/umgah.res @@ -0,0 +1,24 @@ +INCLUDE ../star3do.typ + +PATH umgah + +PACKAGE UMGAH_CODE_PACKAGE umgah.shp + CODE UMGAH_CODE umgah.cod + GFXRES UMGAH_ICON_MASK_PMAP_ANIM umgicons.ani + GFXRES UMGAH_MICON_MASK_PMAP_ANIM umgmicon.ani + STRTAB UMGAH_RACE_STRINGS umgtext.txt + +PACKAGE UMGAH_PACKAGE umgah.shp + GFXRES UMGAH_BIG_MASK_PMAP_ANIM umgah.big + GFXRES UMGAH_MED_MASK_PMAP_ANIM umgah.med + GFXRES UMGAH_SML_MASK_PMAP_ANIM umgah.sml + GFXRES SPRITZ_MASK_PMAP_ANIM spritz.ani + GFXRES CONE_BIG_MASK_ANIM cone.big + GFXRES CONE_MED_MASK_ANIM cone.med + GFXRES CONE_SML_MASK_ANIM cone.sml + + GFXRES UMGAH_CAPTAIN_MASK_PMAP_ANIM umgcap.ani + SNDRES UMGAH_SHIP_SOUNDS umgsound.snd + + MUSICRES UMGAH_VICTORY_SONG umgditty.mod + diff --git a/sc2/src/sc2code/ships/urquan/icode.h b/sc2/src/sc2code/ships/urquan/icode.h new file mode 100644 index 000000000..79bb1c987 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/icode.h @@ -0,0 +1,3 @@ +#define URQUAN_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/urquan/igfxres.h b/sc2/src/sc2code/ships/urquan/igfxres.h new file mode 100644 index 000000000..c313c5a17 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/igfxres.h @@ -0,0 +1,14 @@ +#define URQUAN_ICON_MASK_PMAP_ANIM 0x00200002L +#define URQUAN_MICON_MASK_PMAP_ANIM 0x00200102L +#define URQUAN_BIG_MASK_PMAP_ANIM 0x00400202L +#define URQUAN_MED_MASK_PMAP_ANIM 0x00400302L +#define URQUAN_SML_MASK_PMAP_ANIM 0x00400402L +#define FUSION_BIG_MASK_PMAP_ANIM 0x00400502L +#define FUSION_MED_MASK_PMAP_ANIM 0x00400602L +#define FUSION_SML_MASK_PMAP_ANIM 0x00400702L +#define FIGHTER_BIG_MASK_PMAP_ANIM 0x00400802L +#define FIGHTER_MED_MASK_PMAP_ANIM 0x00400902L +#define FIGHTER_SML_MASK_PMAP_ANIM 0x00400a02L +#define URQUAN_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/urquan/imusicre.h b/sc2/src/sc2code/ships/urquan/imusicre.h new file mode 100644 index 000000000..ebb527a27 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/imusicre.h @@ -0,0 +1,3 @@ +#define URQUAN_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/urquan/isndres.h b/sc2/src/sc2code/ships/urquan/isndres.h new file mode 100644 index 000000000..4900b4a7f --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/isndres.h @@ -0,0 +1,3 @@ +#define URQUAN_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/urquan/istrtab.h b/sc2/src/sc2code/ships/urquan/istrtab.h new file mode 100644 index 000000000..4db418f89 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/istrtab.h @@ -0,0 +1,3 @@ +#define URQUAN_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/urquan/resinst.h b/sc2/src/sc2code/ships/urquan/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/urquan/respkg.h b/sc2/src/sc2code/ships/urquan/respkg.h new file mode 100644 index 000000000..c4d407127 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/respkg.h @@ -0,0 +1,6 @@ +enum +{ + URQUAN_CODE_PACKAGE = 1, + URQUAN_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/urquan/restypes.h b/sc2/src/sc2code/ships/urquan/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/urquan/urquan.c b/sc2/src/sc2code/ships/urquan/urquan.c new file mode 100644 index 000000000..3f2676bae --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/urquan.c @@ -0,0 +1,542 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/urquan/resinst.h" +#include "starcon.h" + +#define MAX_CREW MAX_CREW_SIZE +#define MAX_ENERGY MAX_ENERGY_SIZE +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 6 +#define SPECIAL_ENERGY_COST 8 +#define ENERGY_WAIT 4 +#define MAX_THRUST 30 +#define THRUST_INCREMENT 6 +#define TURN_WAIT 4 +#define THRUST_WAIT 6 +#define WEAPON_WAIT 6 +#define SPECIAL_WAIT 9 + +#define SHIP_MASS 10 +#define MISSILE_SPEED DISPLAY_TO_WORLD (20) +#define MISSILE_LIFE 20 + +static RACE_DESC urquan_desc = +{ + { + FIRES_FORE | SEEKING_SPECIAL, + 30, /* Super Melee cost */ + 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 5750, 6000, + }, + (STRING)URQUAN_RACE_STRINGS, + (FRAME)URQUAN_ICON_MASK_PMAP_ANIM, + (FRAME)URQUAN_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)URQUAN_BIG_MASK_PMAP_ANIM, + (FRAME)URQUAN_MED_MASK_PMAP_ANIM, + (FRAME)URQUAN_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)FUSION_BIG_MASK_PMAP_ANIM, + (FRAME)FUSION_MED_MASK_PMAP_ANIM, + (FRAME)FUSION_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)FIGHTER_BIG_MASK_PMAP_ANIM, + (FRAME)FIGHTER_MED_MASK_PMAP_ANIM, + (FRAME)FIGHTER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)URQUAN_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)URQUAN_VICTORY_SONG, + (SOUND)URQUAN_SHIP_SOUNDS, + }, + { + 0, + MISSILE_SPEED * MISSILE_LIFE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_fusion (PELEMENT ShipPtr, HELEMENT FusionArray[]) +{ +#define MISSILE_HITS 10 +#define MISSILE_DAMAGE 6 +#define MISSILE_OFFSET 8 +#define URQUAN_OFFSET 32 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = URQUAN_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + FusionArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +#define TRACK_THRESHOLD 6 +#define FIGHTER_SPEED DISPLAY_TO_WORLD (8) +#define ONE_WAY_FLIGHT 125 +#define FIGHTER_LIFE (ONE_WAY_FLIGHT + ONE_WAY_FLIGHT + 150) + +#define FIGHTER_WEAPON_WAIT 8 +#define FIGHTER_OFFSET 4 +#define LASER_RANGE DISPLAY_TO_WORLD (40 + FIGHTER_OFFSET) + +static void +fighter_postprocess (PELEMENT ElementPtr) +{ + HELEMENT Laser; + STARSHIPPTR StarShipPtr; + LASER_BLOCK LaserBlock; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LaserBlock.cx = ElementPtr->next.location.x; + LaserBlock.cy = ElementPtr->next.location.y; + LaserBlock.face = ElementPtr->thrust_wait; + LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = FIGHTER_OFFSET; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E); + Laser = initialize_laser (&LaserBlock); + if (Laser) + { + ELEMENTPTR LaserPtr; + + LockElement (Laser, &LaserPtr); + SetElementStarShip (LaserPtr, StarShipPtr); + UnlockElement (Laser); + PutElement (Laser); + } + + ElementPtr->postprocess_func = 0; + ElementPtr->thrust_wait = FIGHTER_WEAPON_WAIT; + ProcessSound (SetAbsSoundIndex ( + /* FIGHTER_ZAP */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); +} + +static void +fighter_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + ++StarShipPtr->RaceDescPtr->characteristics.special_wait; + if (FIGHTER_LIFE - ElementPtr->life_span > TRACK_THRESHOLD + && !(ElementPtr->state_flags & CHANGING)) + { + BOOLEAN Enroute; + COUNT orig_facing, facing; + SIZE delta_x, delta_y; + ELEMENTPTR eptr; + + Enroute = TRUE; + + delta_x = StarShipPtr->RaceDescPtr->ship_info.crew_level; + delta_y = ElementPtr->life_span; + + orig_facing = facing = + GetFrameIndex (ElementPtr->current.image.frame); + if (((delta_y & 1) || ElementPtr->hTarget + || TrackShip (ElementPtr, &facing) >= 0) + && (delta_x == 0 || delta_y >= ONE_WAY_FLIGHT)) + ElementPtr->state_flags |= IGNORE_SIMILAR; + else if (delta_x) + { + LockElement (StarShipPtr->hShip, &eptr); + delta_x = eptr->current.location.x + - ElementPtr->current.location.x; + delta_y = eptr->current.location.y + - ElementPtr->current.location.y; + UnlockElement (StarShipPtr->hShip); + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + +#ifdef NEVER + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + if (delta_x <= LASER_RANGE && delta_y <= LASER_RANGE) +#endif /* NEVER */ + ElementPtr->state_flags &= ~IGNORE_SIMILAR; + + Enroute = FALSE; + } + + if (ElementPtr->thrust_wait > 0) + --ElementPtr->thrust_wait; + + if (ElementPtr->hTarget) + { + LockElement (ElementPtr->hTarget, &eptr); + delta_x = eptr->current.location.x + - ElementPtr->current.location.x; + delta_y = eptr->current.location.y + - ElementPtr->current.location.y; + UnlockElement (ElementPtr->hTarget); + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + + if (ElementPtr->thrust_wait == 0 + && abs (delta_x) < LASER_RANGE * 3 / 4 + && abs (delta_y) < LASER_RANGE * 3 / 4 + && delta_x * delta_x + delta_y * delta_y < + (LASER_RANGE * 3 / 4) * (LASER_RANGE * 3 / 4)) + { + ElementPtr->thrust_wait = + (BYTE)NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + ElementPtr->postprocess_func = fighter_postprocess; + } + + if (Enroute) + { + facing = GetFrameIndex (eptr->current.image.frame); + if (ElementPtr->turn_wait & LEFT) + { + delta_x += COSINE (FACING_TO_ANGLE (facing - 4), + DISPLAY_TO_WORLD (30)); + delta_y += SINE (FACING_TO_ANGLE (facing - 4), + DISPLAY_TO_WORLD (30)); + } + else + { + delta_x += COSINE (FACING_TO_ANGLE (facing + 4), + DISPLAY_TO_WORLD (30)); + delta_y += SINE (FACING_TO_ANGLE (facing + 4), + DISPLAY_TO_WORLD (30)); + } + facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + ); + } + } + ElementPtr->state_flags |= CHANGING; + + if (facing != orig_facing) + ElementPtr->next.image.frame = SetAbsFrameIndex ( + ElementPtr->next.image.frame, facing + ); + SetVelocityVector ( + &ElementPtr->velocity, FIGHTER_SPEED, facing + ); + } +} + +static void +fighter_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (GRAVITY_MASS (ElementPtr1->mass_points)) + { + HELEMENT hFighterElement; + + hFighterElement = AllocElement (); + if (hFighterElement) + { + COUNT PI, travel_facing; + SIZE delta_facing; + ELEMENTPTR FighterElementPtr; + + LockElement (hFighterElement, &FighterElementPtr); + PI = FighterElementPtr->PrimIndex; + *FighterElementPtr = *ElementPtr0; + FighterElementPtr->PrimIndex = PI; + (GLOBAL (DisplayArray))[PI] = + (GLOBAL (DisplayArray))[ElementPtr0->PrimIndex]; + FighterElementPtr->state_flags &= ~PRE_PROCESS; + FighterElementPtr->state_flags |= CHANGING; + FighterElementPtr->next = FighterElementPtr->current; + travel_facing = GetVelocityTravelAngle ( + &FighterElementPtr->velocity + ); + delta_facing = NORMALIZE_ANGLE ( + ARCTAN (pPt1->x - pPt0->x, pPt1->y - pPt0->y) + - travel_facing); + if (delta_facing == 0) + { + if (FighterElementPtr->turn_wait & LEFT) + travel_facing -= QUADRANT; + else + travel_facing += QUADRANT; + } + else if (delta_facing <= HALF_CIRCLE) + travel_facing -= QUADRANT; + else + travel_facing += QUADRANT; + + travel_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + NORMALIZE_ANGLE (travel_facing) + )); + FighterElementPtr->next.image.frame = + SetAbsFrameIndex (FighterElementPtr->next.image.frame, + travel_facing); + SetVelocityVector (&FighterElementPtr->velocity, + FIGHTER_SPEED, travel_facing); + UnlockElement (hFighterElement); + + PutElement (hFighterElement); + } + + ElementPtr0->state_flags |= DISAPPEARING | COLLISION; + } + else if (ElementPtr0->pParent != ElementPtr1->pParent) + { + ElementPtr0->blast_offset = 0; + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->state_flags |= DISAPPEARING | COLLISION; + } + else if (ElementPtr1->state_flags & PLAYER_SHIP) + { + ProcessSound (SetAbsSoundIndex ( + /* FIGHTERS_RETURN */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3)); + DeltaCrew (ElementPtr1, 1); + ElementPtr0->state_flags |= DISAPPEARING | COLLISION; + } + + if (ElementPtr0->state_flags & DISAPPEARING) + { + ElementPtr0->state_flags &= ~DISAPPEARING; + + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + ElementPtr0->state_flags |= NONSOLID; + + --StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +static void +spawn_fighters (ElementPtr) +PELEMENT ElementPtr; +{ + SIZE i; + COUNT facing; + SIZE delta_x, delta_y; + HELEMENT hFighterElement; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + facing = StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE); + delta_x = COSINE (FACING_TO_ANGLE (facing), DISPLAY_TO_WORLD (14)); + delta_y = SINE (FACING_TO_ANGLE (facing), DISPLAY_TO_WORLD (14)); + + i = ElementPtr->crew_level > 2 ? 2 : 1; + while (i-- && (hFighterElement = AllocElement ())) + { + SIZE sx, sy; + COUNT fighter_facing; + ELEMENTPTR FighterElementPtr; + + DeltaCrew (ElementPtr, -1); + + PutElement (hFighterElement); + LockElement (hFighterElement, &FighterElementPtr); + FighterElementPtr->hit_points = 1; + FighterElementPtr->mass_points = 0; + FighterElementPtr->thrust_wait = TRACK_THRESHOLD + 1; + FighterElementPtr->state_flags = APPEARING + | FINITE_LIFE | CREW_OBJECT | IGNORE_SIMILAR + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + FighterElementPtr->life_span = FIGHTER_LIFE; + SetPrimType (&(GLOBAL (DisplayArray))[FighterElementPtr->PrimIndex], + STAMP_PRIM); + { + FighterElementPtr->preprocess_func = fighter_preprocess; + FighterElementPtr->postprocess_func = 0; + FighterElementPtr->collision_func = fighter_collision; + FighterElementPtr->death_func = NULL_PTR; + } + + FighterElementPtr->current.location = ElementPtr->next.location; + if (i == 1) + { + FighterElementPtr->turn_wait = LEFT; + fighter_facing = NORMALIZE_FACING (facing + 2); + FighterElementPtr->current.location.x += delta_x - delta_y; + FighterElementPtr->current.location.y += delta_y + delta_x; + } + else + { + FighterElementPtr->turn_wait = RIGHT; + fighter_facing = NORMALIZE_FACING (facing - 2); + FighterElementPtr->current.location.x += delta_x + delta_y; + FighterElementPtr->current.location.y += delta_y - delta_x; + } + sx = COSINE (FACING_TO_ANGLE (fighter_facing), + WORLD_TO_VELOCITY (FIGHTER_SPEED)); + sy = SINE (FACING_TO_ANGLE (fighter_facing), + WORLD_TO_VELOCITY (FIGHTER_SPEED)); + SetVelocityComponents (&FighterElementPtr->velocity, sx, sy); + FighterElementPtr->current.location.x -= VELOCITY_TO_WORLD (sx); + FighterElementPtr->current.location.y -= VELOCITY_TO_WORLD (sy); + + FighterElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; + FighterElementPtr->current.image.frame = + SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], + fighter_facing); + SetElementStarShip (FighterElementPtr, StarShipPtr); + UnlockElement (hFighterElement); + } +} + +static void +urquan_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = PURSUE; + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr + && lpEvalDesc->MoveState == ENTICE + && (!(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) + || lpEvalDesc->which_turn <= 8) + && (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) + || (lpEvalDesc->ObjectPtr->mass_points >= 4 + && lpEvalDesc->which_turn == 2 + && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 16))) + lpEvalDesc->MoveState = PURSUE; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + { + STARSHIPPTR EnemyStarShipPtr; + + if (lpEvalDesc->ObjectPtr) + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr + && StarShipPtr->RaceDescPtr->ship_info.crew_level > + (StarShipPtr->RaceDescPtr->ship_info.max_crew >> 2) + && !(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & POINT_DEFENSE) + && (StarShipPtr->RaceDescPtr->characteristics.special_wait < 6 + || (MANEUVERABILITY ( + &EnemyStarShipPtr->RaceDescPtr->cyborg_control + ) <= SLOW_SHIP + && !(EnemyStarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)) + || (lpEvalDesc->which_turn <= 12 + && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= + (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_energy >> 1)))) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + } + + StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; +} + +static void +urquan_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && ElementPtr->crew_level > 1 + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* LAUNCH_FIGHTERS */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + spawn_fighters (ElementPtr); + + StarShipPtr->special_counter = SPECIAL_WAIT; + } +} + +RACE_DESCPTR +init_urquan () +{ + RACE_DESCPTR RaceDescPtr; + + urquan_desc.postprocess_func = urquan_postprocess; + urquan_desc.init_weapon_func = initialize_fusion; + urquan_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) urquan_intelligence; + + RaceDescPtr = &urquan_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/urquan/urquan.res b/sc2/src/sc2code/ships/urquan/urquan.res new file mode 100644 index 000000000..5fc65dc65 --- /dev/null +++ b/sc2/src/sc2code/ships/urquan/urquan.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH urquan + +PACKAGE URQUAN_CODE_PACKAGE urquan.shp + CODE URQUAN_CODE urquan.cod + GFXRES URQUAN_ICON_MASK_PMAP_ANIM urqicons.ani + GFXRES URQUAN_MICON_MASK_PMAP_ANIM urqmicon.ani + STRTAB URQUAN_RACE_STRINGS urqtext.txt + +PACKAGE URQUAN_PACKAGE urquan.shp + GFXRES URQUAN_BIG_MASK_PMAP_ANIM urquan.big + GFXRES URQUAN_MED_MASK_PMAP_ANIM urquan.med + GFXRES URQUAN_SML_MASK_PMAP_ANIM urquan.sml + GFXRES FUSION_BIG_MASK_PMAP_ANIM fusion.big + GFXRES FUSION_MED_MASK_PMAP_ANIM fusion.med + GFXRES FUSION_SML_MASK_PMAP_ANIM fusion.sml + GFXRES FIGHTER_BIG_MASK_PMAP_ANIM fight.big + GFXRES FIGHTER_MED_MASK_PMAP_ANIM fight.med + GFXRES FIGHTER_SML_MASK_PMAP_ANIM fight.sml + + GFXRES URQUAN_CAPTAIN_MASK_PMAP_ANIM urqcap.ani + SNDRES URQUAN_SHIP_SOUNDS urqsound.snd + + MUSICRES URQUAN_VICTORY_SONG urqditty.mod + diff --git a/sc2/src/sc2code/ships/utwig/icode.h b/sc2/src/sc2code/ships/utwig/icode.h new file mode 100644 index 000000000..0b07536be --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/icode.h @@ -0,0 +1,3 @@ +#define UTWIG_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/utwig/igfxres.h b/sc2/src/sc2code/ships/utwig/igfxres.h new file mode 100644 index 000000000..d6b0725bc --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/igfxres.h @@ -0,0 +1,11 @@ +#define UTWIG_ICON_MASK_PMAP_ANIM 0x00200002L +#define UTWIG_MICON_MASK_PMAP_ANIM 0x00200102L +#define UTWIG_BIG_MASK_PMAP_ANIM 0x00400202L +#define UTWIG_MED_MASK_PMAP_ANIM 0x00400302L +#define UTWIG_SML_MASK_PMAP_ANIM 0x00400402L +#define LANCE_BIG_MASK_PMAP_ANIM 0x00400502L +#define LANCE_MED_MASK_PMAP_ANIM 0x00400602L +#define LANCE_SML_MASK_PMAP_ANIM 0x00400702L +#define UTWIG_CAPTAIN_MASK_PMAP_ANIM 0x00400802L + + diff --git a/sc2/src/sc2code/ships/utwig/imusicre.h b/sc2/src/sc2code/ships/utwig/imusicre.h new file mode 100644 index 000000000..a59a3797e --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/imusicre.h @@ -0,0 +1,3 @@ +#define UTWIG_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/utwig/isndres.h b/sc2/src/sc2code/ships/utwig/isndres.h new file mode 100644 index 000000000..31569713c --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/isndres.h @@ -0,0 +1,3 @@ +#define UTWIG_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/utwig/istrtab.h b/sc2/src/sc2code/ships/utwig/istrtab.h new file mode 100644 index 000000000..d607df78c --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/istrtab.h @@ -0,0 +1,3 @@ +#define UTWIG_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/utwig/resinst.h b/sc2/src/sc2code/ships/utwig/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/utwig/respkg.h b/sc2/src/sc2code/ships/utwig/respkg.h new file mode 100644 index 000000000..aac57f2cf --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/respkg.h @@ -0,0 +1,6 @@ +enum +{ + UTWIG_CODE_PACKAGE = 1, + UTWIG_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/utwig/restypes.h b/sc2/src/sc2code/ships/utwig/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/utwig/utwig.c b/sc2/src/sc2code/ships/utwig/utwig.c new file mode 100644 index 000000000..e01d4b53c --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/utwig.c @@ -0,0 +1,369 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/utwig/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 20 +#define ENERGY_REGENERATION 0 +#define WEAPON_ENERGY_COST 0 +#define SPECIAL_ENERGY_COST 1 +#define ENERGY_WAIT 255 +#define MAX_THRUST 36 +#define THRUST_INCREMENT 6 +#define TURN_WAIT 1 +#define THRUST_WAIT 6 +#define WEAPON_WAIT 7 +#define SPECIAL_WAIT 12 + +#define SHIP_MASS 8 +#define UTWIG_OFFSET 9 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 10 + +static RACE_DESC utwig_desc = +{ + { + FIRES_FORE | POINT_DEFENSE | SHIELD_DEFENSE, + 22, /* Super Melee cost */ + 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY >> 1, MAX_ENERGY, + { + 8534, 8797, + }, + (STRING)UTWIG_RACE_STRINGS, + (FRAME)UTWIG_ICON_MASK_PMAP_ANIM, + (FRAME)UTWIG_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)UTWIG_BIG_MASK_PMAP_ANIM, + (FRAME)UTWIG_MED_MASK_PMAP_ANIM, + (FRAME)UTWIG_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)LANCE_BIG_MASK_PMAP_ANIM, + (FRAME)LANCE_MED_MASK_PMAP_ANIM, + (FRAME)LANCE_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)UTWIG_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)UTWIG_VICTORY_SONG, + (SOUND)UTWIG_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_lance (PELEMENT ShipPtr, HELEMENT WeaponArray[]) +{ +#define LAUNCH_XOFFS0 DISPLAY_TO_WORLD (5) +#define LAUNCH_YOFFS0 -DISPLAY_TO_WORLD (18) +#define LAUNCH_XOFFS1 DISPLAY_TO_WORLD (13) +#define LAUNCH_YOFFS1 -DISPLAY_TO_WORLD (9) +#define LAUNCH_XOFFS2 DISPLAY_TO_WORLD (17) +#define LAUNCH_YOFFS2 -DISPLAY_TO_WORLD (4) +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 1 + COUNT i; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + MissileBlock.pixoffs = 0; + + for (i = 0; i < 3; ++i) + { + COUNT angle; + SIZE sin0, cos0; + SIZE sin1sin0, cos1sin0, cos1cos0, sin1cos0; + + switch (i) + { + case 0: + cos0 = LAUNCH_XOFFS0; + sin0 = LAUNCH_YOFFS0; + break; + case 1: + cos0 = LAUNCH_XOFFS1; + sin0 = LAUNCH_YOFFS1; + break; + case 2: + cos0 = LAUNCH_XOFFS2; + sin0 = LAUNCH_YOFFS2; + break; + } + angle = FACING_TO_ANGLE (MissileBlock.face) + QUADRANT; + cos1cos0 = COSINE (angle, cos0); + sin1sin0 = SINE (angle, sin0); + sin1cos0 = SINE (angle, cos0); + cos1sin0 = COSINE (angle, sin0); + + cos0 = cos1cos0 - sin1sin0; + sin0 = sin1cos0 + cos1sin0; + MissileBlock.cx = ShipPtr->next.location.x + cos0; + MissileBlock.cy = ShipPtr->next.location.y + sin0; + WeaponArray[(i << 1)] = initialize_missile (&MissileBlock); + + cos0 = -cos1cos0 - sin1sin0; + sin0 = -sin1cos0 + cos1sin0; + MissileBlock.cx = ShipPtr->next.location.x + cos0; + MissileBlock.cy = ShipPtr->next.location.y + sin0; + WeaponArray[(i << 1) + 1] = initialize_missile (&MissileBlock); + } + + return (6); +} + +static void +utwig_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + SIZE ShieldStatus; + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) + ShieldStatus = 0; + else + { + ShieldStatus = -1; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) + { + ShieldStatus = 0; + if (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE)) + lpEvalDesc->MoveState = PURSUE; + else if (lpEvalDesc->ObjectPtr->mass_points + || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + { + if ((lpEvalDesc->which_turn >>= 1) == 0) + lpEvalDesc->which_turn = 1; + + if (lpEvalDesc->ObjectPtr->mass_points) + lpEvalDesc->ObjectPtr = 0; + else + lpEvalDesc->MoveState = PURSUE; + ShieldStatus = 1; + } + } + } + + if (StarShipPtr->special_counter == 0) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (ShieldStatus) + { + if ((ShieldStatus > 0 || lpEvalDesc->ObjectPtr) + && lpEvalDesc->which_turn <= 2 + && (ShieldStatus > 0 + || (lpEvalDesc->ObjectPtr->state_flags + & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ + || PlotIntercept (lpEvalDesc->ObjectPtr, + ShipPtr, 2, 0)) + && (Random () & 3)) + { + StarShipPtr->ship_input_state |= SPECIAL; + StarShipPtr->ship_input_state &= ~WEAPON; + } + + lpEvalDesc->ObjectPtr = 0; + } + } + + if (StarShipPtr->RaceDescPtr->ship_info.energy_level + && (lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX])->ObjectPtr) + { + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & IMMEDIATE_WEAPON)) + lpEvalDesc->MoveState = PURSUE; + } + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); +} + +static void +utwig_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr0->life_span > NORMAL_LIFE + && (ElementPtr1->state_flags & FINITE_LIFE) + && ElementPtr1->mass_points) + ElementPtr0->life_span += ElementPtr1->mass_points; + + collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +static void +utwig_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + PPRIMITIVE lpPrim; + + if (ElementPtr->state_flags & APPEARING) + { + ElementPtr->collision_func = utwig_collision; + } + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (ElementPtr->life_span > (NORMAL_LIFE + 1)) + { + DeltaEnergy (ElementPtr, + ElementPtr->life_span - (NORMAL_LIFE + 1)); + + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + } + + if (!(StarShipPtr->cur_status_flags & SPECIAL)) + StarShipPtr->special_counter = 0; + else if (StarShipPtr->special_counter % (SPECIAL_WAIT >> 1) == 0) + { + if (!DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + StarShipPtr->RaceDescPtr->ship_info.ship_flags &= + ~(POINT_DEFENSE | SHIELD_DEFENSE); + else if (StarShipPtr->special_counter == 0) + { + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + } + } + + lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; + if (StarShipPtr->special_counter == 0) + { + SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78)); + ElementPtr->life_span = NORMAL_LIFE; + SetPrimType (lpPrim, STAMP_PRIM); + } + else + { + COLOR color_tab[] = + { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2e), + BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2f), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7c), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7d), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7e), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7f), }; + +#define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) + + COUNT color_index = 0; + COLOR c; + + if (StarShipPtr->weapon_counter == 0) + ++StarShipPtr->weapon_counter; + + c = COLOR_256 (GetPrimColor (lpPrim)); + if (c >= 0x78) + { + if ((c += 2) > 0x7E) + c = 0x2A; + } + else if (c < 0x2E) + { + if (++c == 0x2B) + c = 0x2C; + } + else + c = 0x78; + if (c <= 0x2f && c >= 0x2a) + color_index = c - 0x2a; + else /* color is between 0x7a and 0x7f */ + color_index = (c - 0x7a) + (NUM_TAB_COLORS >> 1); + SetPrimColor (lpPrim, color_tab[color_index]); + + ElementPtr->life_span = NORMAL_LIFE + 1; + SetPrimType (lpPrim, STAMPFILL_PRIM); + } +} + +RACE_DESCPTR +init_utwig () +{ + RACE_DESCPTR RaceDescPtr; + + utwig_desc.preprocess_func = utwig_preprocess; + utwig_desc.init_weapon_func = initialize_lance; + utwig_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) utwig_intelligence; + + RaceDescPtr = &utwig_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/utwig/utwig.res b/sc2/src/sc2code/ships/utwig/utwig.res new file mode 100644 index 000000000..359b1ed15 --- /dev/null +++ b/sc2/src/sc2code/ships/utwig/utwig.res @@ -0,0 +1,23 @@ +INCLUDE ../star3do.typ + +PATH utwig + +PACKAGE UTWIG_CODE_PACKAGE utwig.shp + CODE UTWIG_CODE utwig.cod + GFXRES UTWIG_ICON_MASK_PMAP_ANIM utwicons.ani + GFXRES UTWIG_MICON_MASK_PMAP_ANIM utwmicon.ani + STRTAB UTWIG_RACE_STRINGS utwtext.txt + +PACKAGE UTWIG_PACKAGE utwig.shp + GFXRES UTWIG_BIG_MASK_PMAP_ANIM utwig.big + GFXRES UTWIG_MED_MASK_PMAP_ANIM utwig.med + GFXRES UTWIG_SML_MASK_PMAP_ANIM utwig.sml + GFXRES LANCE_BIG_MASK_PMAP_ANIM lanbig.ani + GFXRES LANCE_MED_MASK_PMAP_ANIM lanmed.ani + GFXRES LANCE_SML_MASK_PMAP_ANIM lansml.ani + + GFXRES UTWIG_CAPTAIN_MASK_PMAP_ANIM utwcap.ani + SNDRES UTWIG_SHIP_SOUNDS utwsound.snd + + MUSICRES UTWIG_VICTORY_SONG utwditty.mod + diff --git a/sc2/src/sc2code/ships/vux/icode.h b/sc2/src/sc2code/ships/vux/icode.h new file mode 100644 index 000000000..b36b1e31c --- /dev/null +++ b/sc2/src/sc2code/ships/vux/icode.h @@ -0,0 +1,3 @@ +#define VUX_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/vux/igfxres.h b/sc2/src/sc2code/ships/vux/igfxres.h new file mode 100644 index 000000000..df321c725 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/igfxres.h @@ -0,0 +1,12 @@ +#define VUX_ICON_MASK_PMAP_ANIM 0x00200002L +#define VUX_MICON_MASK_PMAP_ANIM 0x00200102L +#define VUX_BIG_MASK_PMAP_ANIM 0x00400202L +#define VUX_MED_MASK_PMAP_ANIM 0x00400302L +#define VUX_SML_MASK_PMAP_ANIM 0x00400402L +#define LIMPETS_BIG_MASK_PMAP_ANIM 0x00400502L +#define LIMPETS_MED_MASK_PMAP_ANIM 0x00400602L +#define LIMPETS_SML_MASK_PMAP_ANIM 0x00400702L +#define SLIME_MASK_PMAP_ANIM 0x00400802L +#define VUX_CAPTAIN_MASK_PMAP_ANIM 0x00400902L + + diff --git a/sc2/src/sc2code/ships/vux/imusicre.h b/sc2/src/sc2code/ships/vux/imusicre.h new file mode 100644 index 000000000..5a4453614 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/imusicre.h @@ -0,0 +1,3 @@ +#define VUX_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/vux/isndres.h b/sc2/src/sc2code/ships/vux/isndres.h new file mode 100644 index 000000000..b82604699 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/isndres.h @@ -0,0 +1,3 @@ +#define VUX_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/vux/istrtab.h b/sc2/src/sc2code/ships/vux/istrtab.h new file mode 100644 index 000000000..c82ced712 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/istrtab.h @@ -0,0 +1,3 @@ +#define VUX_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/vux/resinst.h b/sc2/src/sc2code/ships/vux/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/vux/respkg.h b/sc2/src/sc2code/ships/vux/respkg.h new file mode 100644 index 000000000..a89d118dd --- /dev/null +++ b/sc2/src/sc2code/ships/vux/respkg.h @@ -0,0 +1,6 @@ +enum +{ + VUX_CODE_PACKAGE = 1, + VUX_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/vux/restypes.h b/sc2/src/sc2code/ships/vux/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/vux/vux.c b/sc2/src/sc2code/ships/vux/vux.c new file mode 100644 index 000000000..06c3f0142 --- /dev/null +++ b/sc2/src/sc2code/ships/vux/vux.c @@ -0,0 +1,379 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/vux/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 40 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 2 +#define ENERGY_WAIT 8 +#define MAX_THRUST /* DISPLAY_TO_WORLD (5) */ 21 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 7 +#define TURN_WAIT 6 +#define THRUST_WAIT 4 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 7 + +#define SHIP_MASS 6 +#define VUX_OFFSET 12 +#define LASER_RANGE DISPLAY_TO_WORLD (150 + VUX_OFFSET) + +static RACE_DESC vux_desc = +{ + { + FIRES_FORE | SEEKING_SPECIAL | IMMEDIATE_WEAPON, + 12, /* Super Melee cost */ + 900 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 4412, 1558, + }, + (STRING)VUX_RACE_STRINGS, + (FRAME)VUX_ICON_MASK_PMAP_ANIM, + (FRAME)VUX_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)VUX_BIG_MASK_PMAP_ANIM, + (FRAME)VUX_MED_MASK_PMAP_ANIM, + (FRAME)VUX_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SLIME_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + }, + { + (FRAME)LIMPETS_BIG_MASK_PMAP_ANIM, + (FRAME)LIMPETS_MED_MASK_PMAP_ANIM, + (FRAME)LIMPETS_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)VUX_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)VUX_VICTORY_SONG, + (SOUND)VUX_SHIP_SOUNDS, + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define LIMPET_SPEED 25 + +static void +limpet_preprocess (PELEMENT ElementPtr) +{ + COUNT facing, orig_facing; + SIZE delta_facing; + + facing = orig_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( + GetVelocityTravelAngle (&ElementPtr->velocity) + )); + if ((delta_facing = TrackShip (ElementPtr, &facing)) > 0) + { + facing = orig_facing + delta_facing; + SetVelocityVector (&ElementPtr->velocity, + LIMPET_SPEED, facing); + } + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->next.image.frame); + + ElementPtr->state_flags |= CHANGING; +} + +static void +limpet_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT + ElementPtr1, PPOINT pPt1) +{ + if (ElementPtr1->state_flags & PLAYER_SHIP) + { + STAMP s; + STARSHIPPTR StarShipPtr; + RACE_DESCPTR RDPtr; + + GetElementStarShip (ElementPtr1, &StarShipPtr); + RDPtr = StarShipPtr->RaceDescPtr; + + if (++RDPtr->characteristics.turn_wait == 0) + --RDPtr->characteristics.turn_wait; + if (++RDPtr->characteristics.thrust_wait == 0) + --RDPtr->characteristics.thrust_wait; +#define MIN_THRUST_INCREMENT DISPLAY_TO_WORLD (1) + if (RDPtr->characteristics.thrust_increment <= MIN_THRUST_INCREMENT) + { + RDPtr->characteristics.max_thrust = + RDPtr->characteristics.thrust_increment << 1; + } + else + { + COUNT num_thrusts; + + num_thrusts = RDPtr->characteristics.max_thrust / + RDPtr->characteristics.thrust_increment; + --RDPtr->characteristics.thrust_increment; + RDPtr->characteristics.max_thrust = + RDPtr->characteristics.thrust_increment * num_thrusts; + } + RDPtr->cyborg_control.ManeuverabilityIndex = 0; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + ProcessSound (SetAbsSoundIndex ( + /* LIMPET_AFFIXES */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2)); + s.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_data.weapon[0], (COUNT)Random () + ); + ModifySilhouette (ElementPtr1, &s, MODIFY_IMAGE); + } + + ElementPtr0->hit_points = 0; + ElementPtr0->life_span = 0; + ElementPtr0->state_flags |= COLLISION | DISAPPEARING; + + (void) pPt0; /* Satisfying compiler (unused parameter) */ + (void) pPt1; /* Satisfying compiler (unused parameter) */ +} + +static void +spawn_limpets (PELEMENT ElementPtr) +{ +#define LIMPET_OFFSET 8 +#define LIMPET_LIFE 80 +#define LIMPET_HITS 1 +#define LIMPET_DAMAGE 0 + HELEMENT Limpet; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ElementPtr, &StarShipPtr); + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + MissileBlock.face = StarShipPtr->ShipFacing + HALF_CIRCLE; + MissileBlock.index = 0; + MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = LIMPET_OFFSET; + MissileBlock.speed = LIMPET_SPEED; + MissileBlock.hit_points = LIMPET_HITS; + MissileBlock.damage = LIMPET_DAMAGE; + MissileBlock.life = LIMPET_LIFE; + MissileBlock.preprocess_func = limpet_preprocess; + MissileBlock.blast_offs = 0; + + MissileBlock.cx = ElementPtr->next.location.x; + MissileBlock.cy = ElementPtr->next.location.y; + Limpet = initialize_missile (&MissileBlock); + if (Limpet) + { + ELEMENTPTR LimpetPtr; + + LockElement (Limpet, &LimpetPtr); + LimpetPtr->collision_func = limpet_collision; + SetElementStarShip (LimpetPtr, StarShipPtr); + UnlockElement (Limpet); + + PutElement (Limpet); + } +} + +static COUNT +initialize_horrific_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) +{ + STARSHIPPTR StarShipPtr; + LASER_BLOCK LaserBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + LaserBlock.face = StarShipPtr->ShipFacing; + LaserBlock.cx = ShipPtr->next.location.x; + LaserBlock.cy = ShipPtr->next.location.y; + LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); + LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + LaserBlock.pixoffs = VUX_OFFSET; + LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0xA), 0x0A); + LaserArray[0] = initialize_laser (&LaserBlock); + + return (1); +} + +static void +vux_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, + COUNT ConcernCounter) +{ + PEVALUATE_DESC lpEvalDesc; + STARSHIPPTR StarShipPtr; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + lpEvalDesc->MoveState = PURSUE; + if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr != 0 + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) + { + if ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->state_flags + & FINITE_LIFE) + && !(ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->state_flags + & CREW_OBJECT)) + ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState = AVOID; + else + ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState = PURSUE; + } + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr != 0 + && lpEvalDesc->which_turn <= 12 + && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= + (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_energy >> 1)) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; +} + +static void +vux_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* LAUNCH_LIMPET */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + spawn_limpets (ElementPtr); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +static void +vux_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & APPEARING) + { + COUNT facing; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + facing = StarShipPtr->ShipFacing; + if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER + && TrackShip (ElementPtr, &facing) >= 0) + { + ELEMENTPTR OtherShipPtr; + + LockElement (ElementPtr->hTarget, &OtherShipPtr); + + do + { +#define MAXX_ENTRY_DIST DISPLAY_TO_WORLD (SPACE_HEIGHT << 1) +#define MAXY_ENTRY_DIST DISPLAY_TO_WORLD (SPACE_HEIGHT << 1) + SIZE dx, dy; + + ElementPtr->current.location.x = + (OtherShipPtr->current.location.x - + (MAXX_ENTRY_DIST >> 1)) + + ((COUNT)Random () % MAXX_ENTRY_DIST); + ElementPtr->current.location.y = + (OtherShipPtr->current.location.y - + (MAXY_ENTRY_DIST >> 1)) + + ((COUNT)Random () % MAXY_ENTRY_DIST); + dx = OtherShipPtr->current.location.x - + ElementPtr->current.location.x; + dy = OtherShipPtr->current.location.y - + ElementPtr->current.location.y; + facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (dx, dy)) + ); + ElementPtr->current.image.frame = + SetAbsFrameIndex (ElementPtr->current.image.frame, + facing); + + ElementPtr->current.location.x = + WRAP_X (DISPLAY_ALIGN (ElementPtr->current.location.x)); + ElementPtr->current.location.y = + WRAP_Y (DISPLAY_ALIGN (ElementPtr->current.location.y)); + } while (CalculateGravity (ElementPtr) + || TimeSpaceMatterConflict (ElementPtr)); + + UnlockElement (ElementPtr->hTarget); + ElementPtr->hTarget = 0; + + ElementPtr->next = ElementPtr->current; + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + + StarShipPtr->ShipFacing = facing; + } + + StarShipPtr->RaceDescPtr->preprocess_func = 0; + } +} + +RACE_DESCPTR +init_vux (void) +{ + RACE_DESCPTR RaceDescPtr; + + vux_desc.preprocess_func = vux_preprocess; + vux_desc.postprocess_func = vux_postprocess; + vux_desc.init_weapon_func = initialize_horrific_laser; + vux_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) vux_intelligence; + + RaceDescPtr = &vux_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/vux/vux.res b/sc2/src/sc2code/ships/vux/vux.res new file mode 100644 index 000000000..9a8bd1a6b --- /dev/null +++ b/sc2/src/sc2code/ships/vux/vux.res @@ -0,0 +1,24 @@ +INCLUDE ../star3do.typ + +PATH vux + +PACKAGE VUX_CODE_PACKAGE vux.shp + CODE VUX_CODE vux.cod + GFXRES VUX_ICON_MASK_PMAP_ANIM vuxicons.ani + GFXRES VUX_MICON_MASK_PMAP_ANIM vuxmicon.ani + STRTAB VUX_RACE_STRINGS vuxtext.txt + +PACKAGE VUX_PACKAGE vux.shp + GFXRES VUX_BIG_MASK_PMAP_ANIM vux.big + GFXRES VUX_MED_MASK_PMAP_ANIM vux.med + GFXRES VUX_SML_MASK_PMAP_ANIM vux.sml + GFXRES LIMPETS_BIG_MASK_PMAP_ANIM limpets.big + GFXRES LIMPETS_MED_MASK_PMAP_ANIM limpets.med + GFXRES LIMPETS_SML_MASK_PMAP_ANIM limpets.sml + GFXRES SLIME_MASK_PMAP_ANIM slime.ani + + GFXRES VUX_CAPTAIN_MASK_PMAP_ANIM vuxcap.ani + SNDRES VUX_SHIP_SOUNDS vuxsound.snd + + MUSICRES VUX_VICTORY_SONG vuxditty.mod + diff --git a/sc2/src/sc2code/ships/yehat/icode.h b/sc2/src/sc2code/ships/yehat/icode.h new file mode 100644 index 000000000..0bc7c28f0 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/icode.h @@ -0,0 +1,3 @@ +#define YEHAT_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/yehat/igfxres.h b/sc2/src/sc2code/ships/yehat/igfxres.h new file mode 100644 index 000000000..42c7eed71 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/igfxres.h @@ -0,0 +1,14 @@ +#define YEHAT_ICON_MASK_PMAP_ANIM 0x00200002L +#define YEHAT_MICON_MASK_PMAP_ANIM 0x00200102L +#define YEHAT_BIG_MASK_PMAP_ANIM 0x00400202L +#define YEHAT_MED_MASK_PMAP_ANIM 0x00400302L +#define YEHAT_SML_MASK_PMAP_ANIM 0x00400402L +#define CANNON_BIG_MASK_PMAP_ANIM 0x00400502L +#define CANNON_MED_MASK_PMAP_ANIM 0x00400602L +#define CANNON_SML_MASK_PMAP_ANIM 0x00400702L +#define SHIELD_BIG_MASK_ANIM 0x00400802L +#define SHIELD_MED_MASK_ANIM 0x00400902L +#define SHIELD_SML_MASK_ANIM 0x00400a02L +#define YEHAT_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/yehat/imusicre.h b/sc2/src/sc2code/ships/yehat/imusicre.h new file mode 100644 index 000000000..d9b799f3a --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/imusicre.h @@ -0,0 +1,3 @@ +#define YEHAT_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/yehat/isndres.h b/sc2/src/sc2code/ships/yehat/isndres.h new file mode 100644 index 000000000..a2e4070d1 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/isndres.h @@ -0,0 +1,3 @@ +#define YEHAT_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/yehat/istrtab.h b/sc2/src/sc2code/ships/yehat/istrtab.h new file mode 100644 index 000000000..915ae77d6 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/istrtab.h @@ -0,0 +1,3 @@ +#define YEHAT_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/yehat/resinst.h b/sc2/src/sc2code/ships/yehat/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/yehat/respkg.h b/sc2/src/sc2code/ships/yehat/respkg.h new file mode 100644 index 000000000..699a0c4e8 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/respkg.h @@ -0,0 +1,6 @@ +enum +{ + YEHAT_CODE_PACKAGE = 1, + YEHAT_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/yehat/restypes.h b/sc2/src/sc2code/ships/yehat/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/yehat/yehat.c b/sc2/src/sc2code/ships/yehat/yehat.c new file mode 100644 index 000000000..d222bdb18 --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/yehat.c @@ -0,0 +1,363 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/yehat/resinst.h" +#include "starcon.h" + +#define MAX_CREW 20 +#define MAX_ENERGY 10 +#define ENERGY_REGENERATION 2 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST 3 +#define ENERGY_WAIT 6 +#define MAX_THRUST 30 +#define THRUST_INCREMENT 6 +#define TURN_WAIT 2 +#define THRUST_WAIT 2 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 2 + +#define SHIP_MASS 3 +#define MISSILE_SPEED DISPLAY_TO_WORLD (20) +#define MISSILE_LIFE 10 + +static RACE_DESC yehat_desc = +{ + { + FIRES_FORE | SHIELD_DEFENSE, + 23, /* Super Melee cost */ + 750 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 4970, 40, + }, + (STRING)YEHAT_RACE_STRINGS, + (FRAME)YEHAT_ICON_MASK_PMAP_ANIM, + (FRAME)YEHAT_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)YEHAT_BIG_MASK_PMAP_ANIM, + (FRAME)YEHAT_MED_MASK_PMAP_ANIM, + (FRAME)YEHAT_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)CANNON_BIG_MASK_PMAP_ANIM, + (FRAME)CANNON_MED_MASK_PMAP_ANIM, + (FRAME)CANNON_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SHIELD_BIG_MASK_ANIM, + (FRAME)SHIELD_MED_MASK_ANIM, + (FRAME)SHIELD_SML_MASK_ANIM, + }, + { + (FRAME)YEHAT_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)YEHAT_VICTORY_SONG, + (SOUND)YEHAT_SHIP_SOUNDS, + }, + { + 0, + MISSILE_SPEED * MISSILE_LIFE / 3, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +static COUNT +initialize_standard_missiles (PELEMENT ShipPtr, HELEMENT MissileArray[]) +{ +#define YEHAT_OFFSET 16 +#define LAUNCH_OFFS DISPLAY_TO_WORLD (8) +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 1 + SIZE offs_x, offs_y; + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = YEHAT_OFFSET; + MissileBlock.speed = MISSILE_SPEED; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = NULL_PTR; + MissileBlock.blast_offs = MISSILE_OFFSET; + + offs_x = -SINE (FACING_TO_ANGLE (MissileBlock.face), LAUNCH_OFFS); + offs_y = COSINE (FACING_TO_ANGLE (MissileBlock.face), LAUNCH_OFFS); + + MissileBlock.cx = ShipPtr->next.location.x + offs_x; + MissileBlock.cy = ShipPtr->next.location.y + offs_y; + MissileArray[0] = initialize_missile (&MissileBlock); + + MissileBlock.cx = ShipPtr->next.location.x - offs_x; + MissileBlock.cy = ShipPtr->next.location.y - offs_y; + MissileArray[1] = initialize_missile (&MissileBlock); + + return (2); +} + +static void +yehat_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + SIZE ShieldStatus; + STARSHIPPTR StarShipPtr; + PEVALUATE_DESC lpEvalDesc; + + ShieldStatus = -1; + lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) + { + ShieldStatus = 0; + if (!(lpEvalDesc->ObjectPtr->state_flags & (FINITE_LIFE | CREW_OBJECT))) + lpEvalDesc->MoveState = PURSUE; + else if (lpEvalDesc->ObjectPtr->mass_points + || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + { + if (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE)) + lpEvalDesc->which_turn <<= 1; + else + { + if ((lpEvalDesc->which_turn >>= 1) == 0) + lpEvalDesc->which_turn = 1; + + if (lpEvalDesc->ObjectPtr->mass_points) + lpEvalDesc->ObjectPtr = 0; + else + lpEvalDesc->MoveState = PURSUE; + } + ShieldStatus = 1; + } + } + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (ShieldStatus) + { + if (ShipPtr->life_span <= NORMAL_LIFE + 1 + && (ShieldStatus > 0 || lpEvalDesc->ObjectPtr) + && lpEvalDesc->which_turn <= 2 + && (ShieldStatus > 0 + || (lpEvalDesc->ObjectPtr->state_flags + & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ + || PlotIntercept (lpEvalDesc->ObjectPtr, + ShipPtr, 2, 0)) + && (Random () & 3)) + StarShipPtr->ship_input_state |= SPECIAL; + + if (lpEvalDesc->ObjectPtr + && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) + lpEvalDesc->ObjectPtr = 0; + } + } + + if ((lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX])->ObjectPtr) + { + STARSHIPPTR EnemyStarShipPtr; + + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags + & IMMEDIATE_WEAPON)) + lpEvalDesc->MoveState = PURSUE; + } + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); +/* + if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST) + StarShipPtr->ship_input_state &= ~WEAPON; +*/ +} + +static void +yehat_postprocess (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & NONSOLID)) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + /* take care of shield effect */ + if (StarShipPtr->special_counter > 0) + { + if (ElementPtr->life_span == NORMAL_LIFE) + StarShipPtr->special_counter = 0; + else + { +#ifdef OLD + SetPrimColor ( + &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + ); + SetPrimType ( + &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + STAMPFILL_PRIM + ); +#endif /* OLD */ + + ProcessSound (SetAbsSoundIndex ( + /* YEHAT_SHIELD_ON */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); + } + } + +#ifdef OLD + if (ElementPtr->life_span > NORMAL_LIFE) + { + HELEMENT hShipElement; + + if (hShipElement = AllocElement ()) + { + ELEMENTPTR ShipElementPtr; + + InsertElement (hShipElement, GetSuccElement (ElementPtr)); + LockElement (hShipElement, &ShipElementPtr); + + ShipElementPtr->state_flags = + /* in place of APPEARING */ + (CHANGING | PRE_PROCESS | POST_PROCESS) + | FINITE_LIFE | NONSOLID + | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + SetPrimType ( + &(GLOBAL (DisplayArray))[ShipElementPtr->PrimIndex], + STAMP_PRIM + ); + + ShipElementPtr->life_span = 0; /* because preprocessing + * will not be done + */ + ShipElementPtr->current.location = ElementPtr->next.location; + ShipElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; + ShipElementPtr->current.image.frame = + SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], + StarShipPtr->ShipFacing); + ShipElementPtr->next = ShipElementPtr->current; + ShipElementPtr->preprocess_func = + ShipElementPtr->postprocess_func = + ShipElementPtr->death_func = NULL_PTR; + ZeroVelocityComponents (&ShipElementPtr->velocity); + + UnlockElement (hShipElement); + } + } +#endif /* OLD */ + } +} + +static void +yehat_preprocess (PELEMENT ElementPtr) +{ + if (!(ElementPtr->state_flags & APPEARING)) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((ElementPtr->life_span > NORMAL_LIFE + /* take care of shield effect */ + && --ElementPtr->life_span == NORMAL_LIFE) + || (ElementPtr->life_span == NORMAL_LIFE + && ElementPtr->next.image.farray + == StarShipPtr->RaceDescPtr->ship_data.special)) + { +#ifdef NEVER + SetPrimType ( + &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], + STAMP_PRIM + ); +#endif /* NEVER */ + + ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; + ElementPtr->next.image.frame = + SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], + ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + } + + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0) + { + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST) + DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); /* so text will flash */ + else + { +#define SHIELD_LIFE 10 + ElementPtr->life_span = SHIELD_LIFE + NORMAL_LIFE; + + ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; + ElementPtr->next.image.frame = + SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], + ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + } + } +} + +RACE_DESCPTR +init_yehat () +{ + RACE_DESCPTR RaceDescPtr; + + yehat_desc.preprocess_func = yehat_preprocess; + yehat_desc.postprocess_func = yehat_postprocess; + yehat_desc.init_weapon_func = initialize_standard_missiles; + yehat_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) yehat_intelligence; + + RaceDescPtr = &yehat_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/yehat/yehat.res b/sc2/src/sc2code/ships/yehat/yehat.res new file mode 100644 index 000000000..728a70e0c --- /dev/null +++ b/sc2/src/sc2code/ships/yehat/yehat.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH yehat + +PACKAGE YEHAT_CODE_PACKAGE yehat.shp + CODE YEHAT_CODE yehat.cod + GFXRES YEHAT_ICON_MASK_PMAP_ANIM yehicons.ani + GFXRES YEHAT_MICON_MASK_PMAP_ANIM yehmicon.ani + STRTAB YEHAT_RACE_STRINGS yehtext.txt + +PACKAGE YEHAT_PACKAGE yehat.shp + GFXRES YEHAT_BIG_MASK_PMAP_ANIM yehat.big + GFXRES YEHAT_MED_MASK_PMAP_ANIM yehat.med + GFXRES YEHAT_SML_MASK_PMAP_ANIM yehat.sml + GFXRES CANNON_BIG_MASK_PMAP_ANIM missile.big + GFXRES CANNON_MED_MASK_PMAP_ANIM missile.med + GFXRES CANNON_SML_MASK_PMAP_ANIM missile.sml + GFXRES SHIELD_BIG_MASK_ANIM shield.big + GFXRES SHIELD_MED_MASK_ANIM shield.med + GFXRES SHIELD_SML_MASK_ANIM shield.sml + + GFXRES YEHAT_CAPTAIN_MASK_PMAP_ANIM yehcap.ani + SNDRES YEHAT_SHIP_SOUNDS yehsound.snd + + MUSICRES YEHAT_VICTORY_SONG yehditty.mod + diff --git a/sc2/src/sc2code/ships/zoqfot/icode.h b/sc2/src/sc2code/ships/zoqfot/icode.h new file mode 100644 index 000000000..6cb663e64 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/icode.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_CODE 0x00200008L + + diff --git a/sc2/src/sc2code/ships/zoqfot/igfxres.h b/sc2/src/sc2code/ships/zoqfot/igfxres.h new file mode 100644 index 000000000..b2821cee1 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/igfxres.h @@ -0,0 +1,14 @@ +#define ZOQFOTPIK_ICON_MASK_PMAP_ANIM 0x00200002L +#define ZOQFOTPIK_MICON_MASK_PMAP_ANIM 0x00200102L +#define ZOQFOTPIK_BIG_MASK_PMAP_ANIM 0x00400202L +#define ZOQFOTPIK_MED_MASK_PMAP_ANIM 0x00400302L +#define ZOQFOTPIK_SML_MASK_PMAP_ANIM 0x00400402L +#define SPIT_BIG_MASK_PMAP_ANIM 0x00400502L +#define SPIT_MED_MASK_PMAP_ANIM 0x00400602L +#define SPIT_SML_MASK_PMAP_ANIM 0x00400702L +#define STINGER_BIG_MASK_PMAP_ANIM 0x00400802L +#define STINGER_MED_MASK_PMAP_ANIM 0x00400902L +#define STINGER_SML_MASK_PMAP_ANIM 0x00400a02L +#define ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L + + diff --git a/sc2/src/sc2code/ships/zoqfot/imusicre.h b/sc2/src/sc2code/ships/zoqfot/imusicre.h new file mode 100644 index 000000000..52478e961 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/imusicre.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_VICTORY_SONG 0x00400006L + + diff --git a/sc2/src/sc2code/ships/zoqfot/isndres.h b/sc2/src/sc2code/ships/zoqfot/isndres.h new file mode 100644 index 000000000..bed244ba8 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/isndres.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_SHIP_SOUNDS 0x00400005L + + diff --git a/sc2/src/sc2code/ships/zoqfot/istrtab.h b/sc2/src/sc2code/ships/zoqfot/istrtab.h new file mode 100644 index 000000000..497b45408 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/istrtab.h @@ -0,0 +1,3 @@ +#define ZOQFOTPIK_RACE_STRINGS 0x00200004L + + diff --git a/sc2/src/sc2code/ships/zoqfot/resinst.h b/sc2/src/sc2code/ships/zoqfot/resinst.h new file mode 100644 index 000000000..d5310a924 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/resinst.h @@ -0,0 +1,5 @@ +#include "igfxres.h" +#include "istrtab.h" +#include "isndres.h" +#include "imusicre.h" +#include "icode.h" diff --git a/sc2/src/sc2code/ships/zoqfot/respkg.h b/sc2/src/sc2code/ships/zoqfot/respkg.h new file mode 100644 index 000000000..cb56c091a --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/respkg.h @@ -0,0 +1,6 @@ +enum +{ + ZOQFOTPIK_CODE_PACKAGE = 1, + ZOQFOTPIK_PACKAGE +}; + diff --git a/sc2/src/sc2code/ships/zoqfot/restypes.h b/sc2/src/sc2code/ships/zoqfot/restypes.h new file mode 100644 index 000000000..9fc3e4ca5 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/restypes.h @@ -0,0 +1,17 @@ +#ifndef _RESTYPES_H +#define _RESTYPES_H + +enum +{ + KEY_CONFIG = 1, + GFXRES, + FONTRES, + STRTAB, + SNDRES, + MUSICRES, + RES_INDEX, + CODE +}; + +#endif /* _RESTYPES_H */ + diff --git a/sc2/src/sc2code/ships/zoqfot/zoqfot.c b/sc2/src/sc2code/ships/zoqfot/zoqfot.c new file mode 100644 index 000000000..8c9ade23b --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/zoqfot.c @@ -0,0 +1,365 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "reslib.h" +#include "ships/zoqfot/resinst.h" +#include "starcon.h" + +#define MAX_CREW 10 +#define MAX_ENERGY 10 +#define ENERGY_REGENERATION 1 +#define WEAPON_ENERGY_COST 1 +#define SPECIAL_ENERGY_COST (MAX_ENERGY * 3 / 4) +#define ENERGY_WAIT 4 +#define MAX_THRUST 40 +#define THRUST_INCREMENT 10 +#define TURN_WAIT 1 +#define THRUST_WAIT 0 +#define WEAPON_WAIT 0 +#define SPECIAL_WAIT 6 + +#define SHIP_MASS 5 +#define MISSILE_SPEED DISPLAY_TO_WORLD (10) +#define MISSILE_LIFE 10 +#define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) + +static RACE_DESC zoqfotpik_desc = +{ + { + FIRES_FORE, + 6, /* Super Melee cost */ + 320 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + { + 3761, 5333, + }, + (STRING)ZOQFOTPIK_RACE_STRINGS, + (FRAME)ZOQFOTPIK_ICON_MASK_PMAP_ANIM, + (FRAME)ZOQFOTPIK_MICON_MASK_PMAP_ANIM, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + (FRAME)ZOQFOTPIK_BIG_MASK_PMAP_ANIM, + (FRAME)ZOQFOTPIK_MED_MASK_PMAP_ANIM, + (FRAME)ZOQFOTPIK_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)SPIT_BIG_MASK_PMAP_ANIM, + (FRAME)SPIT_MED_MASK_PMAP_ANIM, + (FRAME)SPIT_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)STINGER_BIG_MASK_PMAP_ANIM, + (FRAME)STINGER_MED_MASK_PMAP_ANIM, + (FRAME)STINGER_SML_MASK_PMAP_ANIM, + }, + { + (FRAME)ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM, + (FRAME)0, + (FRAME)0, + (FRAME)0, + (FRAME)0, + }, + (SOUND)ZOQFOTPIK_VICTORY_SONG, + (SOUND)ZOQFOTPIK_SHIP_SOUNDS, + }, + { + 0, + MISSILE_RANGE, + NULL_PTR, + }, + NULL_PTR, + NULL_PTR, + NULL_PTR, + 0, +}; + +#define ZOQFOTPIK_OFFSET 13 +#define SPIT_WAIT 2 + +static void +spit_preprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + COUNT index, angle, speed; + + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->next.image.frame); + angle = GetVelocityTravelAngle (&ElementPtr->velocity); + if ((index = GetFrameIndex (ElementPtr->next.image.frame)) == 1) + angle = angle + (((COUNT)Random () % 3) - 1); + + speed = WORLD_TO_VELOCITY (DISPLAY_TO_WORLD ( + GetFrameCount (ElementPtr->next.image.frame) - index) << 1); + SetVelocityComponents (&ElementPtr->velocity, + (SIZE)COSINE (angle, speed), + (SIZE)SINE (angle, speed)); + + ElementPtr->turn_wait = SPIT_WAIT; + ElementPtr->state_flags |= CHANGING; + } +} + +static COUNT +initialize_spit (PELEMENT ShipPtr, HELEMENT SpitArray[]) +{ +#define MISSILE_DAMAGE 1 +#define MISSILE_HITS 1 +#define MISSILE_OFFSET 0 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK MissileBlock; + + GetElementStarShip (ShipPtr, &StarShipPtr); + MissileBlock.cx = ShipPtr->next.location.x; + MissileBlock.cy = ShipPtr->next.location.y; + MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; + MissileBlock.face = StarShipPtr->ShipFacing; + MissileBlock.index = 0; + MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + MissileBlock.pixoffs = ZOQFOTPIK_OFFSET; + MissileBlock.speed = DISPLAY_TO_WORLD ( + GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.weapon[0])) << 1; + MissileBlock.hit_points = MISSILE_HITS; + MissileBlock.damage = MISSILE_DAMAGE; + MissileBlock.life = MISSILE_LIFE; + MissileBlock.preprocess_func = spit_preprocess; + MissileBlock.blast_offs = MISSILE_OFFSET; + SpitArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void spawn_tongue (PELEMENT ElementPtr); + +static void +tongue_postprocess (PELEMENT ElementPtr) +{ + if (ElementPtr->turn_wait) + spawn_tongue (ElementPtr); +} + +static void +tongue_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (StarShipPtr->special_counter == + StarShipPtr->RaceDescPtr->characteristics.special_wait) + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + + StarShipPtr->special_counter -= ElementPtr0->turn_wait; + ElementPtr0->turn_wait = 0; + ElementPtr0->state_flags |= NONSOLID; +} + +static void +spawn_tongue (ElementPtr) +PELEMENT ElementPtr; +{ +#define TONGUE_SPEED 0 +#define TONGUE_HITS 1 +#define TONGUE_DAMAGE 12 +#define TONGUE_OFFSET 4 + STARSHIPPTR StarShipPtr; + MISSILE_BLOCK TongueBlock; + HELEMENT Tongue; + + GetElementStarShip (ElementPtr, &StarShipPtr); + TongueBlock.cx = ElementPtr->next.location.x; + TongueBlock.cy = ElementPtr->next.location.y; + TongueBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; + TongueBlock.face = TongueBlock.index = StarShipPtr->ShipFacing; + TongueBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) + | IGNORE_SIMILAR; + TongueBlock.pixoffs = 0; + TongueBlock.speed = TONGUE_SPEED; + TongueBlock.hit_points = TONGUE_HITS; + TongueBlock.damage = TONGUE_DAMAGE; + TongueBlock.life = 1; + TongueBlock.preprocess_func = 0; + TongueBlock.blast_offs = TONGUE_OFFSET; + Tongue = initialize_missile (&TongueBlock); + if (Tongue) + { + ELEMENTPTR TonguePtr; + + LockElement (Tongue, &TonguePtr); + TonguePtr->postprocess_func = tongue_postprocess; + TonguePtr->collision_func = tongue_collision; + if (ElementPtr->state_flags & PLAYER_SHIP) + TonguePtr->turn_wait = StarShipPtr->special_counter; + else + { + COUNT angle; + RECT r; + SIZE x_offs, y_offs; + + TonguePtr->turn_wait = ElementPtr->turn_wait - 1; + + GetFrameRect (TonguePtr->current.image.frame, &r); + x_offs = DISPLAY_TO_WORLD (r.extent.width >> 1); + y_offs = DISPLAY_TO_WORLD (r.extent.height >> 1); + + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + if (angle > HALF_CIRCLE && angle < FULL_CIRCLE) + TonguePtr->current.location.x -= x_offs; + else if (angle > 0 && angle < HALF_CIRCLE) + TonguePtr->current.location.x += x_offs; + if (angle < QUADRANT || angle > FULL_CIRCLE - QUADRANT) + TonguePtr->current.location.y -= y_offs; + else if (angle > QUADRANT && angle < FULL_CIRCLE - QUADRANT) + TonguePtr->current.location.y += y_offs; + } + + SetElementStarShip (TonguePtr, StarShipPtr); + UnlockElement (Tongue); + PutElement (Tongue); + } +} + +static void +zoqfotpik_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter) +PELEMENT ShipPtr; +PEVALUATE_DESC ObjectsOfConcern; +COUNT ConcernCounter; +{ + BOOLEAN GiveTongueJob; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + + GiveTongueJob = FALSE; + if (StarShipPtr->special_counter == 0) + { + PEVALUATE_DESC lpEnemyEvalDesc; + + StarShipPtr->ship_input_state &= ~SPECIAL; + + lpEnemyEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEnemyEvalDesc->ObjectPtr + && lpEnemyEvalDesc->which_turn <= 4 +#ifdef NEVER + && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST +#endif /* NEVER */ + ) + { + SIZE delta_x, delta_y; + + GiveTongueJob = TRUE; + + lpEnemyEvalDesc->MoveState = PURSUE; + delta_x = lpEnemyEvalDesc->ObjectPtr->next.location.x + - ShipPtr->next.location.x; + delta_y = lpEnemyEvalDesc->ObjectPtr->next.location.y + - ShipPtr->next.location.y; + if (StarShipPtr->ShipFacing == NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) + )) + StarShipPtr->ship_input_state |= SPECIAL; + } + } + + ++StarShipPtr->weapon_counter; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + --StarShipPtr->weapon_counter; + + if (StarShipPtr->weapon_counter == 0) + { + StarShipPtr->ship_input_state &= ~WEAPON; + if (!GiveTongueJob) + { + ObjectsOfConcern += ConcernCounter; + while (ConcernCounter--) + { + --ObjectsOfConcern; + if (ObjectsOfConcern->ObjectPtr + && (ConcernCounter == ENEMY_SHIP_INDEX + || (ConcernCounter == ENEMY_WEAPON_INDEX + && ObjectsOfConcern->MoveState != AVOID +#ifdef NEVER + && !(PlayerControl[cur_player] & STANDARD_RATING) +#endif /* NEVER */ + )) + && ship_weapons (ShipPtr, + ObjectsOfConcern->ObjectPtr, DISPLAY_TO_WORLD (20))) + { + StarShipPtr->ship_input_state |= WEAPON; + break; + } + } + } + } +} + +static void +zoqfotpik_postprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* STICK_OUT_TONGUE */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1)); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } + + if (StarShipPtr->special_counter) + spawn_tongue (ElementPtr); +} + +RACE_DESCPTR +init_zoqfotpik () +{ + RACE_DESCPTR RaceDescPtr; + + zoqfotpik_desc.postprocess_func = zoqfotpik_postprocess; + zoqfotpik_desc.init_weapon_func = initialize_spit; + zoqfotpik_desc.cyborg_control.intelligence_func = + (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT + ConcernCounter)) zoqfotpik_intelligence; + + RaceDescPtr = &zoqfotpik_desc; + + return (RaceDescPtr); +} + diff --git a/sc2/src/sc2code/ships/zoqfot/zoqfot.res b/sc2/src/sc2code/ships/zoqfot/zoqfot.res new file mode 100644 index 000000000..7104a1431 --- /dev/null +++ b/sc2/src/sc2code/ships/zoqfot/zoqfot.res @@ -0,0 +1,26 @@ +INCLUDE ../star3do.typ + +PATH zoqfot + +PACKAGE ZOQFOTPIK_CODE_PACKAGE zoqfot.shp + CODE ZOQFOTPIK_CODE zoqfot.cod + GFXRES ZOQFOTPIK_ICON_MASK_PMAP_ANIM zoqicons.ani + GFXRES ZOQFOTPIK_MICON_MASK_PMAP_ANIM zoqmicon.ani + STRTAB ZOQFOTPIK_RACE_STRINGS zoqtext.txt + +PACKAGE ZOQFOTPIK_PACKAGE zoqfot.shp + GFXRES ZOQFOTPIK_BIG_MASK_PMAP_ANIM zoqfot.big + GFXRES ZOQFOTPIK_MED_MASK_PMAP_ANIM zoqfot.med + GFXRES ZOQFOTPIK_SML_MASK_PMAP_ANIM zoqfot.sml + GFXRES SPIT_BIG_MASK_PMAP_ANIM spitbig.ani + GFXRES SPIT_MED_MASK_PMAP_ANIM spitmed.ani + GFXRES SPIT_SML_MASK_PMAP_ANIM spitsml.ani + GFXRES STINGER_BIG_MASK_PMAP_ANIM stibig.ani + GFXRES STINGER_MED_MASK_PMAP_ANIM stimed.ani + GFXRES STINGER_SML_MASK_PMAP_ANIM stisml.ani + + GFXRES ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM zoqcap.ani + SNDRES ZOQFOTPIK_SHIP_SOUNDS zoqsound.snd + + MUSICRES ZOQFOTPIK_VICTORY_SONG zoqditty.mod + diff --git a/sc2/src/sc2code/shipstat.c b/sc2/src/sc2code/shipstat.c new file mode 100644 index 000000000..d334f7831 --- /dev/null +++ b/sc2/src/sc2code/shipstat.c @@ -0,0 +1,437 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +void +DrawCrewFuelString (COORD y, SIZE state) +{ + STAMP Stamp; + extern FRAME status; + + Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT; + if (state == 0) + { + Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + 6; + Stamp.frame = SetAbsFrameIndex (status, 0); + DrawStamp (&Stamp); + } + + Stamp.origin.x = ENERGY_XOFFS + (STAT_WIDTH >> 1) - 5; + Stamp.frame = SetAbsFrameIndex (status, 1); + if (state >= 0) + DrawStamp (&Stamp); + else + { +#define LOW_FUEL_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E) + SetContextForeGroundColor (LOW_FUEL_COLOR); + DrawFilledStamp (&Stamp); + } +} + +static void +DrawShipNameString (UNICODE *pStr, COUNT CharCount, COORD y) +{ + TEXT Text; + FONT OldFont; + + OldFont = SetContextFont (StarConFont); + + Text.pStr = pStr; + Text.CharCount = CharCount; + Text.align = ALIGN_CENTER; + + Text.baseline.y = STARCON_TEXT_HEIGHT + 3 + y; + Text.baseline.x = STATUS_WIDTH >> 1; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + DrawText (&Text); + --Text.baseline.y; + SetContextForeGroundColor (BLACK_COLOR); + DrawText (&Text); + + SetContextFont (OldFont); +} + +void +ClearShipStatus (COORD y) +{ + RECT r; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + r.corner.x = 2; + r.corner.y = 3 + y; + r.extent.width = STATUS_WIDTH - 4; + r.extent.height = SHIP_INFO_HEIGHT - 3; + DrawFilledRectangle (&r); +} + +void +OutlineShipStatus (COORD y) +{ + RECT r; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.x = 0; + r.corner.y = 1 + y; + r.extent.width = STATUS_WIDTH; + r.extent.height = 1; + DrawFilledRectangle (&r); + ++r.corner.y; + --r.extent.width; + DrawFilledRectangle (&r); + r.extent.width = 1; + r.extent.height = SHIP_INFO_HEIGHT - 2; + DrawFilledRectangle (&r); + ++r.corner.x; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = STATUS_WIDTH - 1; + DrawFilledRectangle (&r); + r.corner.x = STATUS_WIDTH - 2; + ++r.corner.y; + --r.extent.height; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.x = 0; + r.corner.y = y; + r.extent.width = STATUS_WIDTH; + r.extent.height = 1; + DrawFilledRectangle (&r); +} + +void +InitShipStatus (STARSHIPPTR StarShipPtr, PRECT pClipRect) +{ + RECT r; + COORD y, y_stat; + STAMP Stamp; + CONTEXT OldContext; + SHIP_INFOPTR SIPtr; + + SIPtr = &StarShipPtr->RaceDescPtr->ship_info; + y_stat = (SIPtr->ship_flags & GOOD_GUY) ? + GOOD_GUY_YOFFS : BAD_GUY_YOFFS; + + OldContext = SetContext (StatusContext); + y = y_stat; + if (pClipRect) + { + GetContextClipRect (&r); + r.corner.x += pClipRect->corner.x; + r.corner.y += (pClipRect->corner.y & ~1); + r.extent = pClipRect->extent; + r.extent.height += pClipRect->corner.y & 1; + SetContextClipRect (&r); + SetFrameHot (Screen, MAKE_HOT_SPOT ( + pClipRect->corner.x, + (pClipRect->corner.y & ~1) + )); + } + + BatchGraphics (); + + OutlineShipStatus (y); + ClearShipStatus (y); + + Stamp.origin.x = (STATUS_WIDTH >> 1); + Stamp.origin.y = 31 + y; + Stamp.frame = IncFrameIndex (SIPtr->icons); + DrawStamp (&Stamp); + + { + SIZE crew_height, energy_height; + + crew_height = (((SIPtr->max_crew + 1) >> 1) << 1) + 1; + energy_height = (((SIPtr->max_energy + 1) >> 1) << 1) + 1; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS + 1 + y; + r.extent.width = STAT_WIDTH + 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS - 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS + STAT_WIDTH; + r.corner.y -= energy_height; + r.extent.width = 1; + r.extent.height = energy_height; + DrawFilledRectangle (&r); + r.corner.x = CREW_XOFFS + STAT_WIDTH; + r.corner.y = (GAUGE_YOFFS + 1 + y) - crew_height; + r.extent.width = 1; + r.extent.height = crew_height; + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - crew_height + y; + r.extent.width = STAT_WIDTH + 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - energy_height + y; + DrawFilledRectangle (&r); + r.extent.width = 1; + r.extent.height = energy_height + 1; + DrawFilledRectangle (&r); + r.corner.x = CREW_XOFFS - 1; + r.corner.y = GAUGE_YOFFS - crew_height + y; + r.extent.height = crew_height + 1; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BLACK_COLOR); + + r.extent.width = STAT_WIDTH; + r.corner.x = CREW_XOFFS; + r.extent.height = crew_height; + r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; + DrawFilledRectangle (&r); + r.corner.x = ENERGY_XOFFS; + r.extent.height = energy_height; + r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; + DrawFilledRectangle (&r); + } + + if (StarShipPtr->captains_name_index + || LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) + { + STRING locString; + + DrawCrewFuelString (y, 0); + + locString = SetAbsStringTableIndex (SIPtr->race_strings, 1); + DrawShipNameString ( + (UNICODE *)GetStringAddress (locString), + GetStringLength (locString), + y + ); + + { + UNICODE buf[3]; + TEXT Text; + FONT OldFont; + + OldFont = SetContextFont (TinyFont); + + if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) + { + wsprintf (buf, "%d", SIPtr->ship_cost); + Text.pStr = buf; + Text.CharCount = (COUNT)~0; + } + else + { + locString = SetAbsStringTableIndex (SIPtr->race_strings, + StarShipPtr->captains_name_index); + Text.pStr = (UNICODE *)GetStringAddress (locString); + Text.CharCount = GetStringLength (locString); + } + Text.align = ALIGN_CENTER; + + Text.baseline.x = STATUS_WIDTH >> 1; + Text.baseline.y = y + GAUGE_YOFFS + 9; + + SetContextForeGroundColor (BLACK_COLOR); + DrawText (&Text); + + SetContextFont (OldFont); + } + } + else if (StarShipPtr->captains_name_index == 0) + { + if (SIPtr->ship_flags & GOOD_GUY) + { + DrawCrewFuelString (y, 0); + DrawShipNameString (GLOBAL_SIS (ShipName), (COUNT)~0, y); + } + } + + { + SIZE crew_delta, energy_delta; + + crew_delta = SIPtr->crew_level; + energy_delta = SIPtr->energy_level; + SIPtr->crew_level = SIPtr->energy_level = 0; + DeltaStatistics (StarShipPtr, crew_delta, energy_delta); + } + + UnbatchGraphics (); + + if (pClipRect) + { + SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); + r.corner.x = SPACE_WIDTH + SAFE_X; + r.corner.y = SAFE_Y; + r.extent.width = STATUS_WIDTH; + r.extent.height = STATUS_HEIGHT; + SetContextClipRect (&r); + } + + SetContext (OldContext); +} + +void +DeltaStatistics (STARSHIPPTR StarShipPtr, SIZE crew_delta, SIZE + energy_delta) +{ + COORD x, y; + RECT r; + SHIP_INFOPTR ShipInfoPtr; + + if (crew_delta == 0 && energy_delta == 0) + return; + + ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; + + x = 0; + y = GAUGE_YOFFS + + ((ShipInfoPtr->ship_flags & GOOD_GUY) ? + GOOD_GUY_YOFFS : BAD_GUY_YOFFS); + + r.extent.width = UNIT_WIDTH; + r.extent.height = UNIT_HEIGHT; + if (crew_delta != 0) + { + if (crew_delta > 0) + { + r.corner.y = (y + 1) - + (((ShipInfoPtr->crew_level + 1) >> 1) * (UNIT_HEIGHT + 1)); + if (StarShipPtr->captains_name_index == 0 + && (ShipInfoPtr->ship_flags & GOOD_GUY) + && LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) + { + if ((crew_delta = + GLOBAL_SIS (CrewEnlisted)) >= MAX_CREW_SIZE) + crew_delta = MAX_CREW_SIZE; + else /* if (crew_delta < MAX_CREW_SIZE) */ + { +#define PLAYER_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09) + SetContextForeGroundColor (PLAYER_UNIT_COLOR); + r.corner.x = x + (CREW_XOFFS + 1); + if (!(ShipInfoPtr->crew_level & 1)) + { + r.corner.x += UNIT_WIDTH + 1; + r.corner.y -= UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + ++ShipInfoPtr->crew_level; + } + } + +#define CREW_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02) +#define ROBOT_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08) + SetContextForeGroundColor ( + (ShipInfoPtr->ship_flags & CREW_IMMUNE) ? + ROBOT_UNIT_COLOR : CREW_UNIT_COLOR + ); + while (crew_delta--) + { + r.corner.x = x + (CREW_XOFFS + 1); + if (!(ShipInfoPtr->crew_level & 1)) + { + r.corner.x += UNIT_WIDTH + 1; + r.corner.y -= UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + ++ShipInfoPtr->crew_level; + } + } + else + { + if (StarShipPtr->captains_name_index == 0 + && (ShipInfoPtr->ship_flags & GOOD_GUY) + && LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) + { + COUNT death_count; + + death_count = (COUNT)-crew_delta; + if (GLOBAL_SIS (CrewEnlisted) >= death_count) + { + GLOBAL_SIS (CrewEnlisted) -= death_count; + death_count = 0; + } + else + { + death_count -= GLOBAL_SIS (CrewEnlisted); + GLOBAL_SIS (CrewEnlisted) = 0; + } + + DrawBattleCrewAmount ((BOOLEAN)(death_count == 0)); + } + + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = (y + 1) - + (((ShipInfoPtr->crew_level + 2) >> 1) * (UNIT_HEIGHT + 1)); + do + { + r.corner.x = x + (CREW_XOFFS + 1 + UNIT_WIDTH + 1); + if (!(ShipInfoPtr->crew_level & 1)) + { + r.corner.x -= UNIT_WIDTH + 1; + r.corner.y += UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + --ShipInfoPtr->crew_level; + } while (++crew_delta); + } + } + + if (energy_delta != 0) + { + if (energy_delta > 0) + { +#define FUEL_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) + SetContextForeGroundColor (FUEL_UNIT_COLOR); + r.corner.y = (y + 1) - + (((ShipInfoPtr->energy_level + 1) >> 1) * (UNIT_HEIGHT + 1)); + do + { + r.corner.x = x + (ENERGY_XOFFS + 1); + if (!(ShipInfoPtr->energy_level & 1)) + { + r.corner.x += UNIT_WIDTH + 1; + r.corner.y -= UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + ++ShipInfoPtr->energy_level; + } while (--energy_delta); + } + else + { + SetContextForeGroundColor (BLACK_COLOR); + r.corner.y = (y + 1) - + (((ShipInfoPtr->energy_level + 2) >> 1) * (UNIT_HEIGHT + 1)); + do + { + r.corner.x = x + (ENERGY_XOFFS + 1 + UNIT_WIDTH + 1); + if (!(ShipInfoPtr->energy_level & 1)) + { + r.corner.x -= UNIT_WIDTH + 1; + r.corner.y += UNIT_HEIGHT + 1; + } + DrawFilledRectangle (&r); + --ShipInfoPtr->energy_level; + } while (++energy_delta); + } + } +} + + diff --git a/sc2/src/sc2code/shipyard.c b/sc2/src/sc2code/shipyard.c new file mode 100644 index 000000000..f9338e893 --- /dev/null +++ b/sc2/src/sc2code/shipyard.c @@ -0,0 +1,1157 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "melee.h" +#include "SDL_wrapper.h" + +//Added by Chris + +void DoShipSpin (COUNT index, MUSIC_REF hMusic); + +void GetGaugeRect (PRECT pRect, BOOLEAN IsCrewRect); + +//End added by Chris + +enum +{ + SHIPYARD_CREW, + SHIPYARD_SAVELOAD, + SHIPYARD_EXIT +}; + +static void +SpinStarShip (HSTARSHIP hStarShip) +{ + COUNT Index; + HSTARSHIP hNextShip, hShip; + STARSHIPPTR StarShipPtr; + extern QUEUE master_q; + + StarShipPtr = LockStarShip (&GLOBAL (built_ship_q), hStarShip); + + for (Index = 0, hShip = GetHeadLink (&master_q); + hShip; hShip = hNextShip, ++Index) + { + STARSHIPPTR SSPtr; + + SSPtr = LockStarShip (&master_q, hShip); + if (StarShipPtr->RaceResIndex == SSPtr->RaceResIndex) + break; + hNextShip = _GetSuccLink (SSPtr); + UnlockStarShip (&master_q, hShip); + } + + UnlockStarShip (&master_q, hStarShip); + + if (Index < NUM_MELEE_SHIPS) + DoShipSpin (Index, pMenuState->hMusic); +} + +static COUNT +GetAvailableRaceCount (void) +{ + COUNT Index; + HSTARSHIP hStarShip, hNextShip; + + Index = 0; + for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip; hStarShip = hNextShip) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + if (StarShipPtr->ShipInfo.ship_flags & GOOD_GUY) + ++Index; + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + + return (Index); +} + +static HSTARSHIP +GetAvailableRaceFromIndex (BYTE Index) +{ + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip; hStarShip = hNextShip) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + if ((StarShipPtr->ShipInfo.ship_flags & GOOD_GUY) && Index-- == 0) + { + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + return (hStarShip); + } + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip ( + &GLOBAL (avail_race_q), hStarShip + ); + } + + return (0); +} + +static void +DrawRaceStrings (BYTE NewRaceItem) +{ + RECT r; + STAMP s; + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + + OldContext = SetContext (StatusContext); + GetContextClipRect (&r); + s.origin.x = RADAR_X - r.corner.x; + s.origin.y = RADAR_Y - r.corner.y; + r.corner.x = s.origin.x - 1; + r.corner.y = s.origin.y - 11; + r.extent.width = RADAR_WIDTH + 2; + r.extent.height = 11; + BatchGraphics (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawFilledRectangle (&r); + r.corner = s.origin; + r.extent.width = RADAR_WIDTH; + r.extent.height = RADAR_HEIGHT; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); + DrawFilledRectangle (&r); + if (NewRaceItem != (BYTE)~0) + { + TEXT t; + HSTARSHIP hStarShip; + STARSHIPPTR StarShipPtr; + UNICODE buf[10]; + COUNT ShipCost[] = + { + RACE_SHIP_COST + }; + + hStarShip = GetAvailableRaceFromIndex (NewRaceItem); + NewRaceItem = GetIndexFromStarShip (&GLOBAL (avail_race_q), hStarShip); + s.frame = SetAbsFrameIndex (pMenuState->ModuleFrame, 3 + NewRaceItem); + DrawStamp (&s); + StarShipPtr = LockStarShip (&GLOBAL (avail_race_q), hStarShip); + s.frame = StarShipPtr->RaceDescPtr->ship_info.melee_icon; + UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); + + t.baseline.x = s.origin.x + RADAR_WIDTH - 2; + t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; + s.origin.x += (RADAR_WIDTH >> 1); + s.origin.y += (RADAR_HEIGHT >> 1); + DrawStamp (&s); + t.align = ALIGN_RIGHT; + t.CharCount = (COUNT)~0; + t.pStr = buf; + wsprintf (buf, "%u", ShipCost[NewRaceItem]); + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); + DrawText (&t); + } + UnbatchGraphics (); + + SetFlashRect ((PRECT)~0L, (FRAME)0); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); +} + +#define SHIP_WIN_WIDTH 34 +#define SHIP_WIN_HEIGHT (SHIP_WIN_WIDTH + 6) + +static void +ShowShipCrew (SHIP_FRAGMENTPTR StarShipPtr, PRECT pRect) +{ + RECT r; + TEXT t; + UNICODE buf[20]; + HSTARSHIP hTemplate; + SHIP_FRAGMENTPTR TemplatePtr; + + hTemplate = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), + GET_RACE_ID (StarShipPtr) + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + if (StarShipPtr->ShipInfo.crew_level >= + TemplatePtr->RaceDescPtr->ship_info.crew_level) + wsprintf (buf, "%u", StarShipPtr->ShipInfo.crew_level); + else + wsprintf (buf, "%u/%u", + StarShipPtr->ShipInfo.crew_level, + TemplatePtr->RaceDescPtr->ship_info.crew_level); + UnlockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + + r = *pRect; + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + r.extent.height - 1; + t.align = ALIGN_CENTER; + t.pStr = buf; + t.CharCount = (COUNT)~0; + if (r.corner.y) + { + r.corner.y = t.baseline.y - 6; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = 6; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + } + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); + DrawText (&t); +} + +static void +ShowCombatShip (COUNT which_window, SHIP_FRAGMENTPTR YankedStarShipPtr) +{ + COUNT i, num_ships; + HSTARSHIP hStarShip, hNextShip; + SHIP_FRAGMENTPTR StarShipPtr; + struct + { + SHIP_FRAGMENTPTR StarShipPtr; + POINT finished_s; + STAMP ship_s, lfdoor_s, rtdoor_s; + } ship_win_info[MAX_COMBAT_SHIPS], *pship_win_info; + COORD x_coords[] = + { + 19, 60, 116, 157, + }; + + num_ships = 1; + pship_win_info = &ship_win_info[0]; + if (YankedStarShipPtr) + { + pship_win_info->StarShipPtr = YankedStarShipPtr; + + pship_win_info->lfdoor_s.origin.x = -(SHIP_WIN_WIDTH >> 1); + pship_win_info->rtdoor_s.origin.x = (SHIP_WIN_WIDTH >> 1); + pship_win_info->lfdoor_s.origin.y = + pship_win_info->rtdoor_s.origin.y = 0; + pship_win_info->lfdoor_s.frame = + IncFrameIndex (pMenuState->ModuleFrame); + pship_win_info->rtdoor_s.frame = + IncFrameIndex (pship_win_info->lfdoor_s.frame); + + pship_win_info->ship_s.origin.x = (SHIP_WIN_WIDTH >> 1) + 1; + pship_win_info->ship_s.origin.y = (SHIP_WIN_WIDTH >> 1); + pship_win_info->ship_s.frame = + YankedStarShipPtr->ShipInfo.melee_icon; + + pship_win_info->finished_s.x = x_coords[which_window & 3]; + pship_win_info->finished_s.y = 64 + (44 * (which_window >> 2)); + } + else + { + if (which_window == (COUNT)~0) + { + hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); + num_ships = CountLinks (&GLOBAL (built_ship_q)); + } + else + { + HSTARSHIP hTailShip; + + hTailShip = GetTailLink (&GLOBAL (built_ship_q)); + RemoveQueue (&GLOBAL (built_ship_q), hTailShip); + + hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); + while (hStarShip) + { + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + if (GET_GROUP_LOC (StarShipPtr) > which_window) + { + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + break; + } + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + + hStarShip = hNextShip; + } + InsertQueue (&GLOBAL (built_ship_q), + hTailShip, hStarShip); + + hStarShip = hTailShip; + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + SET_GROUP_LOC (StarShipPtr, which_window); + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + } + + for (i = 0; i < num_ships; ++i) + { + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + pship_win_info->StarShipPtr = StarShipPtr; + + pship_win_info->lfdoor_s.origin.x = -1; + pship_win_info->rtdoor_s.origin.x = 1; + pship_win_info->lfdoor_s.origin.y = + pship_win_info->rtdoor_s.origin.y = 0; + pship_win_info->lfdoor_s.frame = + IncFrameIndex (pMenuState->ModuleFrame); + pship_win_info->rtdoor_s.frame = + IncFrameIndex (pship_win_info->lfdoor_s.frame); + + pship_win_info->ship_s.origin.x = (SHIP_WIN_WIDTH >> 1) + 1; + pship_win_info->ship_s.origin.y = (SHIP_WIN_WIDTH >> 1); + pship_win_info->ship_s.frame = + StarShipPtr->ShipInfo.melee_icon; + + which_window = GET_GROUP_LOC (StarShipPtr); + pship_win_info->finished_s.x = x_coords[which_window & 3]; + pship_win_info->finished_s.y = 64 + (44 * (which_window >> 2)); + ++pship_win_info; + + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + hStarShip = hNextShip; + } + } + + if (num_ships) + { + BYTE ButtonState; + BOOLEAN AllDoorsFinished; + DWORD TimeIn; + RECT r; + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (OffScreenContext); + SetContextFGFrame (Screen); + SetContextBackGroundColor (BLACK_COLOR); + + AllDoorsFinished = FALSE; + r.corner.x = r.corner.y = 0; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = SHIP_WIN_HEIGHT; + ButtonState = AnyButtonPress (FALSE) ? 1 : 0; + TimeIn = GetTimeCounter (); + do + { + TimeIn = SleepTask (TimeIn + 5); + BatchGraphics (); +StartFinalPass: + pship_win_info = &ship_win_info[0]; + for (i = 0; i < num_ships; ++i) + { + if (ButtonState) + { + if (!AnyButtonPress (FALSE)) + ButtonState = 0; + } + else if (AnyButtonPress (FALSE)) + { + if (YankedStarShipPtr == 0) + AllDoorsFinished = TRUE; + else + pship_win_info->lfdoor_s.origin.x = + pship_win_info->rtdoor_s.origin.x = 0; + goto StartFinalPass; + } + + { + RECT ClipRect; + + ClipRect.corner.x = SIS_ORG_X + pship_win_info->finished_s.x; + ClipRect.corner.y = SIS_ORG_Y + pship_win_info->finished_s.y; + ClipRect.extent.width = SHIP_WIN_WIDTH; + ClipRect.extent.height = SHIP_WIN_HEIGHT; + SetContextClipRect (&ClipRect); + + ClearDrawable (); + DrawStamp (&pship_win_info->ship_s); + ShowShipCrew (pship_win_info->StarShipPtr, &r); + if (!AllDoorsFinished) + { + DrawStamp (&pship_win_info->lfdoor_s); + DrawStamp (&pship_win_info->rtdoor_s); + if (YankedStarShipPtr) + { + ++pship_win_info->lfdoor_s.origin.x; + --pship_win_info->rtdoor_s.origin.x; + } + else + { + --pship_win_info->lfdoor_s.origin.x; + ++pship_win_info->rtdoor_s.origin.x; + } + } + } + ++pship_win_info; + } + + UnbatchGraphics (); + } while (!AllDoorsFinished); + + SetContextClipRect (NULL_PTR); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + } +} + +static void +CrewTransaction (SIZE crew_delta) +{ + if (crew_delta) + { + SIZE crew_bought; + + crew_bought = (SIZE)MAKE_WORD ( + GET_GAME_STATE (CREW_PURCHASED0), + GET_GAME_STATE (CREW_PURCHASED1) + ) + crew_delta; + if (crew_bought < 0) + { + if (crew_delta < 0) + crew_bought = 0; + else + crew_bought = 0x7FFF; + } + else if (crew_delta > 0) + { + if (crew_bought >= CREW_EXPENSE_THRESHOLD + && crew_bought - crew_delta < CREW_EXPENSE_THRESHOLD) + { + GLOBAL (CrewCost) += 2; + + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); + SetSemaphore (&GraphicsSem); + } + } + else + { + if (crew_bought < CREW_EXPENSE_THRESHOLD + && crew_bought - crew_delta >= CREW_EXPENSE_THRESHOLD) + { + GLOBAL (CrewCost) -= 2; + + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); + SetSemaphore (&GraphicsSem); + } + } + if (!(ActivateStarShip ( + SHOFIXTI_SHIP, CHECK_ALLIANCE + ) & GOOD_GUY)) + { + SET_GAME_STATE (CREW_PURCHASED0, LOBYTE (crew_bought)); + SET_GAME_STATE (CREW_PURCHASED1, HIBYTE (crew_bought)); + } + } +} + +static BOOLEAN +DoModifyShips (INPUT_STATE InputState, PMENU_STATE pMS) +{ +#define MODIFY_CREW_FLAG (1 << 8) + RECT r; + HSTARSHIP hStarShip, hNextShip; + SHIP_FRAGMENTPTR StarShipPtr; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { + pMS->InputFunc = DoShipyard; + return (TRUE); + } + + if (!pMS->Initialized) + { + pMS->InputFunc = DoModifyShips; + pMS->Initialized = TRUE; + pMS->CurState = MAKE_BYTE (0, 0xF); + pMS->delta_item = 0; + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + goto ChangeFlashRect; + } + else + { + SBYTE dx, dy; + BYTE NewState; + + dx = GetInputXComponent (InputState); + dy = GetInputYComponent (InputState); + NewState = pMS->CurState; + if (pMS->delta_item & MODIFY_CREW_FLAG) + { + } + else if (dy) + { + if (HINIBBLE (NewState)) + NewState = pMS->CurState & 3; + else + NewState = (unsigned char)(pMS->CurState + (1 << 2)); + + NewState = (NewState + (dy << 2)) & 0xF; + if (NewState >> 2) + NewState -= (1 << 2); + else + NewState = MAKE_BYTE (pMS->CurState, 0xF); + } + else if (dx && !HINIBBLE (NewState)) + { + NewState = NewState & 3; + if ((dx += NewState) < 0) + NewState = (BYTE)(pMS->CurState + 3); + else if (dx > 3) + NewState = (BYTE)(pMS->CurState - 3); + else + NewState = (BYTE)(pMS->CurState - NewState + dx); + } + +#ifdef WANT_SHIP_SPINS + if ((InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2 | DEVICE_BUTTON3)) +#else + if ((InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) +#endif + || NewState != pMS->CurState + || ((pMS->delta_item & MODIFY_CREW_FLAG) && (dx || dy))) + { + for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); + hStarShip; hStarShip = hNextShip) + { + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + if (GET_GROUP_LOC (StarShipPtr) == pMS->CurState) + { + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + break; + } + + hNextShip = _GetSuccLink (StarShipPtr); + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + } + + SetSemaphore (&GraphicsSem); + +#ifdef WANT_SHIP_SPINS + if (InputState & DEVICE_BUTTON3) + { + HSTARSHIP hSpinShip; + + if ((hSpinShip = hStarShip) + || (HINIBBLE (pMS->CurState) == 0 + && (hSpinShip = GetAvailableRaceFromIndex ( + LOBYTE (pMS->delta_item) + )))) + { + SetFlashRect (NULL_PTR, (FRAME)0); + SpinStarShip (hSpinShip); + if (hStarShip) + goto ChangeFlashRect; + SetFlashRect ((PRECT)~0L, (FRAME)0); + } + } + else +#endif + if ((InputState & DEVICE_BUTTON1) + || ((pMS->delta_item & MODIFY_CREW_FLAG) + && (dx || dy || (InputState & DEVICE_BUTTON2)))) + { + COUNT ShipCost[] = + { + RACE_SHIP_COST + }; + + if (hStarShip == 0 && HINIBBLE (pMS->CurState) == 0) + { + COUNT Index; + +// SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + if (!(pMS->delta_item & MODIFY_CREW_FLAG)) + { + pMS->delta_item = MODIFY_CREW_FLAG; + DrawRaceStrings (0); + return (TRUE); + } + else if (InputState & DEVICE_BUTTON2) + { + pMS->delta_item ^= MODIFY_CREW_FLAG; + DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); + } + else if (InputState & DEVICE_BUTTON1) + { + Index = GetIndexFromStarShip ( + &GLOBAL (avail_race_q), + GetAvailableRaceFromIndex (LOBYTE (pMS->delta_item)) + ); + + if (GLOBAL_SIS (ResUnits) >= (DWORD)ShipCost[Index] + && CloneShipFragment (Index, + &GLOBAL (built_ship_q), 1)) + { + ShowCombatShip ((COUNT)pMS->CurState, (SHIP_FRAGMENTPTR)0); + DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); + + SetSemaphore (&GraphicsSem); + DeltaSISGauges ( + UNDEFINED_DELTA, UNDEFINED_DELTA, -((int)ShipCost[Index]) + ); + r.corner.x = pMS->flash_rect0.corner.x; + r.corner.y = pMS->flash_rect0.corner.y + + pMS->flash_rect0.extent.height - 6; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = 5; + SetContext (SpaceContext); + SetFlashRect (&r, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + + return (TRUE); + } + else + { + Index = GetAvailableRaceCount (); + NewState = LOBYTE (pMS->delta_item); + if (dx < 0 || dy < 0) + { + if (NewState-- == 0) + NewState = Index - 1; + } + else if (dx > 0 || dy > 0) + { + if (++NewState == Index) + NewState = 0; + } + + if (NewState != LOBYTE (pMS->delta_item)) + { + DrawRaceStrings (NewState); + pMS->delta_item = NewState | MODIFY_CREW_FLAG; + } + + return (TRUE); + } + SetSemaphore (&GraphicsSem); + goto ChangeFlashRect; + } + else if (InputState & (DEVICE_BUTTON1 | DEVICE_BUTTON2)) + { + if (!(pMS->delta_item ^= MODIFY_CREW_FLAG)) + goto ChangeFlashRect; + else if (hStarShip == 0) + { + SetContext (StatusContext); + GetGaugeRect (&r, TRUE); + SetFlashRect (&r, (FRAME)0); + SetContext (SpaceContext); + } + else + { + r.corner.x = pMS->flash_rect0.corner.x; + r.corner.y = pMS->flash_rect0.corner.y + + pMS->flash_rect0.extent.height - 6; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = 5; + SetContext (SpaceContext); + SetFlashRect (&r, (FRAME)0); + } + } + else if (pMS->delta_item & MODIFY_CREW_FLAG) + { + SIZE crew_delta, crew_bought; + + if (hStarShip) + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + crew_delta = 0; + if (dx < 0 || dy < 0) + { + if (hStarShip == 0) + { + if (GetCPodCapacity (&r.corner) > GetCrewCount () + && GLOBAL_SIS (ResUnits) >= + (DWORD)GLOBAL (CrewCost)) + { + DrawPoint (&r.corner); + DeltaSISGauges (1, 0, -GLOBAL (CrewCost)); + crew_delta = 1; + + SetContext (StatusContext); + GetGaugeRect (&r, TRUE); + SetFlashRect (&r, (FRAME)0); + SetContext (SpaceContext); + } + } + else + { + HSTARSHIP hTemplate; + SHIP_FRAGMENTPTR TemplatePtr; + + hTemplate = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), + GET_RACE_ID (StarShipPtr) + ); + TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + if (GLOBAL_SIS (ResUnits) >= + (DWORD)GLOBAL (CrewCost) + && StarShipPtr->ShipInfo.crew_level < + StarShipPtr->ShipInfo.max_crew + && StarShipPtr->ShipInfo.crew_level < + TemplatePtr->RaceDescPtr->ship_info.crew_level) + { + DeltaSISGauges (0, 0, -GLOBAL (CrewCost)); + ++StarShipPtr->ShipInfo.crew_level; + crew_delta = 1; + + ShowShipCrew (StarShipPtr, &pMS->flash_rect0); + r.corner.x = pMS->flash_rect0.corner.x; + r.corner.y = pMS->flash_rect0.corner.y + + pMS->flash_rect0.extent.height - 6; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = 5; + SetContext (SpaceContext); + SetFlashRect (&r, (FRAME)0); + } + UnlockStarShip ( + &GLOBAL (avail_race_q), hTemplate + ); + } + } + else if (dx > 0 || dy > 0) + { + crew_bought = (SIZE)MAKE_WORD ( + GET_GAME_STATE (CREW_PURCHASED0), + GET_GAME_STATE (CREW_PURCHASED1) + ); + if (hStarShip == 0) + { + if (GetCrewCount ()) + { + DeltaSISGauges (-1, 0, GLOBAL (CrewCost) + - (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); + crew_delta = -1; + + GetCPodCapacity (&r.corner); + SetContextForeGroundColor (BLACK_COLOR); + DrawPoint (&r.corner); + + SetContext (StatusContext); + GetGaugeRect (&r, TRUE); + SetFlashRect (&r, (FRAME)0); + SetContext (SpaceContext); + } + } + else if (StarShipPtr->ShipInfo.crew_level > 1) + { + DeltaSISGauges (0, 0, GLOBAL (CrewCost) + - (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); + crew_delta = -1; + --StarShipPtr->ShipInfo.crew_level; + + ShowShipCrew (StarShipPtr, &pMS->flash_rect0); + r.corner.x = pMS->flash_rect0.corner.x; + r.corner.y = pMS->flash_rect0.corner.y + + pMS->flash_rect0.extent.height - 6; + r.extent.width = SHIP_WIN_WIDTH; + r.extent.height = 5; + SetContext (SpaceContext); + SetFlashRect (&r, (FRAME)0); + } + else + { + COUNT ResUnits; + + ResUnits = (COUNT)ShipCost[ + GET_RACE_ID (StarShipPtr) + ]; + crew_delta = -(StarShipPtr->ShipInfo.crew_level - 1); + crew_bought = (SIZE)MAKE_WORD ( + GET_GAME_STATE (CREW_PURCHASED0), + GET_GAME_STATE (CREW_PURCHASED1) + ) - CREW_EXPENSE_THRESHOLD; + if (crew_bought <= 0 || (crew_bought += crew_delta) >= 0) + crew_bought = -crew_delta; + else + { + ResUnits += -crew_bought + * (GLOBAL (CrewCost) - 2); + crew_bought -= crew_delta; + } + ResUnits += crew_bought * GLOBAL (CrewCost); + + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + ShowCombatShip ((COUNT)pMS->CurState, StarShipPtr); + SetSemaphore (&GraphicsSem); + pMS->flash_rect0.extent.width = SHIP_WIN_WIDTH; + SetFlashRect (&pMS->flash_rect0, (FRAME)0); + + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + RemoveQueue ( + &GLOBAL (built_ship_q), hStarShip + ); + FreeStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + DeltaSISGauges ( + UNDEFINED_DELTA, UNDEFINED_DELTA, ResUnits + ); + hStarShip = 0; + + pMS->delta_item ^= MODIFY_CREW_FLAG; + } + } + + if (hStarShip) + UnlockStarShip ( + &GLOBAL (built_ship_q), hStarShip + ); + + CrewTransaction (crew_delta); + } + } + else if (InputState & DEVICE_BUTTON2) + { + ClearSemaphore (&GraphicsSem); + + pMS->InputFunc = DoShipyard; + DrawMenuStateStrings (PM_CREW, pMS->CurState = SHIPYARD_CREW); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + return (TRUE); + } + else + { + pMS->CurState = NewState; + +ChangeFlashRect: + if (HINIBBLE (pMS->CurState)) + { + pMS->flash_rect0.corner.x = + pMS->flash_rect0.corner.y = 0; + pMS->flash_rect0.extent.width = SIS_SCREEN_WIDTH; + pMS->flash_rect0.extent.height = 61; + } + else + { + COORD x_coords[] = + { + 19, 60, 116, 157, + }; + + pMS->flash_rect0.corner.x = x_coords[pMS->CurState & 3]; + pMS->flash_rect0.corner.y = 64 + (44 * (pMS->CurState >> 2)); + pMS->flash_rect0.extent.width = SHIP_WIN_WIDTH; + pMS->flash_rect0.extent.height = SHIP_WIN_HEIGHT; + } + SetFlashRect (&pMS->flash_rect0, (FRAME)0); + } + ClearSemaphore (&GraphicsSem); + } + } + + return (TRUE); +} + +static void +DrawBluePrint (PMENU_STATE pMS) +{ + COUNT num_frames; + STAMP s; + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + + pMS->ModuleFrame = CaptureDrawable ( + LoadGraphic (SISBLU_MASK_ANIM) + ); + + BatchGraphics (); + + s.origin.x = s.origin.y = 0; + s.frame = DecFrameIndex (pMS->ModuleFrame); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x16), 0x01)); + DrawFilledStamp (&s); + + for (num_frames = 0; num_frames < NUM_DRIVE_SLOTS; ++num_frames) + { + DrawShipPiece (pMS, GLOBAL_SIS (DriveSlots[num_frames]), + num_frames, TRUE); + } + for (num_frames = 0; num_frames < NUM_JET_SLOTS; ++num_frames) + { + DrawShipPiece (pMS, GLOBAL_SIS (JetSlots[num_frames]), + num_frames, TRUE); + } + for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) + { + BYTE which_piece; + + which_piece = GLOBAL_SIS (ModuleSlots[num_frames]); + + if (!(pMS->CurState == SHIPYARD && which_piece == CREW_POD)) + DrawShipPiece (pMS, which_piece, num_frames, TRUE); + } + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0x1F), 0x09)); + for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) + { + BYTE which_piece; + + which_piece = GLOBAL_SIS (ModuleSlots[num_frames]); + if (pMS->CurState == SHIPYARD && which_piece == CREW_POD) + DrawShipPiece (pMS, which_piece, num_frames, TRUE); + } + + { + num_frames = GLOBAL_SIS (CrewEnlisted); + GLOBAL_SIS (CrewEnlisted) = 0; + + while (num_frames--) + { + POINT pt; + + GetCPodCapacity (&pt); + DrawPoint (&pt); + + ++GLOBAL_SIS (CrewEnlisted); + } + } + { + RECT r; + + num_frames = GLOBAL_SIS (TotalElementMass); + GLOBAL_SIS (TotalElementMass) = 0; + + r.extent.width = 9; + r.extent.height = 1; + while (num_frames) + { + COUNT m; + + m = num_frames < SBAY_MASS_PER_ROW ? + num_frames : SBAY_MASS_PER_ROW; + GLOBAL_SIS (TotalElementMass) += m; + GetSBayCapacity (&r.corner); + DrawFilledRectangle (&r); + num_frames -= m; + } + } + if (GLOBAL_SIS (FuelOnBoard) > FUEL_RESERVE) + { + DWORD FuelVolume; + RECT r; + + FuelVolume = GLOBAL_SIS (FuelOnBoard) - FUEL_RESERVE; + GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; + + r.extent.width = 3; + r.extent.height = 1; + while (FuelVolume) + { + COUNT m; + + GetFTankCapacity (&r.corner); + DrawPoint (&r.corner); + r.corner.x += r.extent.width + 1; + DrawPoint (&r.corner); + r.corner.x -= r.extent.width; + SetContextForeGroundColor (SetContextBackGroundColor (BLACK_COLOR)); + DrawFilledRectangle (&r); + m = FuelVolume < FUEL_VOLUME_PER_ROW ? + (COUNT)FuelVolume : FUEL_VOLUME_PER_ROW; + GLOBAL_SIS (FuelOnBoard) += m; + FuelVolume -= m; + } + } + + UnbatchGraphics (); + + DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); + pMS->ModuleFrame = 0; + + ClearSemaphore (&GraphicsSem); +} + +BOOLEAN +DoShipyard (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + goto ExitShipyard; + + if (!pMS->Initialized) + { + pMS->InputFunc = DoShipyard; + + { + STAMP s; + + s.frame = CaptureDrawable ( + LoadGraphic (SHIPYARD_PMAP_ANIM) + ); + + pMS->hMusic = LoadMusicInstance (SHIPYARD_MUSIC); + + BatchGraphics (); + + DrawSISFrame (); + DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 3)); + DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE)); + + DrawBluePrint (pMS); + pMS->ModuleFrame = s.frame; + + DrawMenuStateStrings (PM_CREW, pMS->CurState = SHIPYARD_CREW); + + SetSemaphore (&GraphicsSem); + SetContext (SpaceContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + s.origin.x = s.origin.y = 0; + DrawStamp (&s); + + SetContextFont (TinyFont); + +{ + RECT r; + + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + ScreenTransition (3, &r); +} + PlayMusic (pMS->hMusic, TRUE, 1); + UnbatchGraphics (); + + ClearSemaphore (&GraphicsSem); + + ShowCombatShip ((COUNT)~0, (SHIP_FRAGMENTPTR)0); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + + pMS->Initialized = TRUE; + } + else if ((InputState & DEVICE_BUTTON2) + || ((InputState & DEVICE_BUTTON1) + && pMS->CurState == SHIPYARD_EXIT)) + { +ExitShipyard: + SetSemaphore (&GraphicsSem); + DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); + pMS->ModuleFrame = 0; + ClearSemaphore (&GraphicsSem); + + return (FALSE); + } + else if (InputState & DEVICE_BUTTON1) + { + if (pMS->CurState != SHIPYARD_SAVELOAD) + { + pMS->Initialized = FALSE; + DoModifyShips (InputState, pMS); + } + else + { + if (GameOptions () == 0) + goto ExitShipyard; + DrawMenuStateStrings (PM_CREW, pMS->CurState); + SetSemaphore (&GraphicsSem); + SetFlashRect ((PRECT)~0L, (FRAME)0); + ClearSemaphore (&GraphicsSem); + } + } + else + { + BYTE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == SHIPYARD_CREW) + NewState = SHIPYARD_EXIT; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == SHIPYARD_EXIT) + NewState = SHIPYARD_CREW; + } + + if (NewState != pMS->CurState) + { + DrawMenuStateStrings (PM_CREW, NewState); + + pMS->CurState = NewState; + } + } + + return (TRUE); +} + diff --git a/sc2/src/sc2code/sis.c b/sc2/src/sc2code/sis.c new file mode 100644 index 000000000..4216d66b8 --- /dev/null +++ b/sc2/src/sc2code/sis.c @@ -0,0 +1,1244 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "commglue.h" +#include "SDL_wrapper.h" + +void +RepairSISBorder (void) +{ + RECT r; + CONTEXT OldContext; + + OldContext = SetContext (ScreenContext); + + BatchGraphics (); + r.corner.x = SIS_ORG_X - 1; + r.corner.y = SIS_ORG_Y - 1; + r.extent.width = 1; + r.extent.height = SIS_SCREEN_HEIGHT + 2; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.x += (SIS_SCREEN_WIDTH + 2) - 1; + DrawFilledRectangle (&r); + + r.corner.x = SIS_ORG_X - 1; + r.corner.y += (SIS_SCREEN_HEIGHT + 2) - 1; + r.extent.width = SIS_SCREEN_WIDTH + 2; + r.extent.height = 1; + DrawFilledRectangle (&r); + UnbatchGraphics (); + + SetContext (OldContext); +} + +void +ClearSISRect (BYTE ClearFlags) +{ + RECT r; + COLOR OldColor; + CONTEXT OldContext; + + OldContext = SetContext (StatusContext); + OldColor = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + + r.corner.x = 2; + r.extent.width = STATUS_WIDTH - 4; + + BatchGraphics (); + if (ClearFlags & DRAW_SIS_DISPLAY) + { + DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); + } + + if (ClearFlags & CLEAR_SIS_RADAR) + { + ClearSemaphore (&GraphicsSem); + DrawMenuStateStrings ((BYTE)~0, (BYTE)~0); + SetSemaphore (&GraphicsSem); +#ifdef NEVER + r.corner.x = RADAR_X - 1; + r.corner.y = RADAR_Y - 1; + r.extent.width = RADAR_WIDTH + 2; + r.extent.height = RADAR_HEIGHT + 2; + + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0xE, 0x00), 0x6C)); +#endif /* NEVER */ + } + UnbatchGraphics (); + + SetContextForeGroundColor (OldColor); + SetContext (OldContext); +} + +void +DrawSISTitle (UNICODE *pStr) +{ + TEXT t; + CONTEXT OldContext; + + t.baseline.x = SIS_TITLE_WIDTH >> 1; + t.baseline.y = SIS_TITLE_HEIGHT - 2; + t.align = ALIGN_CENTER; + t.pStr = pStr; + t.CharCount = (COUNT)~0; + + OldContext = SetContext (OffScreenContext); +{ +RECT r; + +r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57 + 1; +r.corner.y = SIS_ORG_Y - SIS_TITLE_HEIGHT; +r.extent.width = SIS_TITLE_WIDTH; +r.extent.height = SIS_TITLE_HEIGHT - 1; +SetContextFGFrame (Screen); +SetContextClipRect (&r); +} + SetContextFont (TinyFont); + + BatchGraphics (); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + ClearDrawable (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); + DrawText (&t); + UnbatchGraphics (); + + SetContextClipRect (NULL_PTR); + + SetContext (OldContext); +} + +void +DrawHyperCoords (POINT universe) +{ + UNICODE buf[20]; + + wsprintf (buf, "%03u.%01u:%03u.%01u", + universe.x / 10, universe.x % 10, + universe.y / 10, universe.y % 10); + + DrawSISTitle (buf); +} + +void +DrawSISMessage (UNICODE *pStr) +{ + UNICODE buf[40]; + CONTEXT OldContext; + + OldContext = SetContext (OffScreenContext); +{ +RECT r; + +r.corner.x = SIS_ORG_X + 1; +r.corner.y = SIS_ORG_Y - SIS_MESSAGE_HEIGHT; +r.extent.width = SIS_MESSAGE_WIDTH; +r.extent.height = SIS_MESSAGE_HEIGHT - 1; +SetContextFGFrame (Screen); +SetContextClipRect (&r); +} + BatchGraphics (); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + ClearDrawable (); + + if (pStr == (UNICODE *)~0L) + { + if (GLOBAL_SIS (FuelOnBoard) == 0) + pStr = GAME_STRING (NAVIGATION_STRING_BASE + 2); + else + pStr = GAME_STRING (NAVIGATION_STRING_BASE + 3); + } + else + { + if (pStr == 0) + { + switch (LOBYTE (GLOBAL (CurrentActivity))) + { + default: + case IN_ENCOUNTER: + buf[0] = '\0'; + break; + case IN_LAST_BATTLE: + case IN_INTERPLANETARY: + GetClusterName (CurStarDescPtr, buf); + break; + case IN_HYPERSPACE: + wstrcpy (buf, GAME_STRING (NAVIGATION_STRING_BASE + + (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1 ? 0 : 1))); + break; + } + + pStr = buf; + } + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); + } + + { + TEXT t; + + t.baseline.x = SIS_MESSAGE_WIDTH >> 1; + t.baseline.y = SIS_MESSAGE_HEIGHT - 2; + t.align = ALIGN_CENTER; + t.pStr = pStr; + t.CharCount = (COUNT)~0; + + SetContextFont (TinyFont); + DrawText (&t); + } + UnbatchGraphics (); + +SetContextClipRect (NULL_PTR); + + SetContext (OldContext); +} + +void +DateToString (UNICODE *buf, BYTE month_index, BYTE day_index, COUNT + year_index) +{ + COUNT i; + + wstrcpy (buf, GAME_STRING (MONTHS_STRING_BASE + month_index - 1)); + buf[3] = ' '; + i = day_index; + buf[5] = (UNICODE)((i % 10) + '0'); + i /= 10; + buf[4] = (UNICODE)((i % 10) + '0'); + buf[6] = ' '; + + i = year_index; + buf[10] = (UNICODE)((i % 10) + '0'); + i /= 10; + buf[9] = (UNICODE)((i % 10) + '0'); + i /= 10; + buf[8] = (UNICODE)((i % 10) + '0'); + i /= 10; + buf[7] = (UNICODE)((i % 10) + '0'); + buf[11] = '\0'; +} + +void +DrawStatusMessage (UNICODE *pStr) +{ + RECT r; + TEXT t; + UNICODE buf[20]; + CONTEXT OldContext; + + OldContext = SetContext (StatusContext); + GetContextClipRect (&r); + SetContext (OffScreenContext); + SetContextFGFrame (Screen); + r.corner.x += 2; + r.corner.y += 130; + r.extent.width = STATUS_MESSAGE_WIDTH; + r.extent.height = STATUS_MESSAGE_HEIGHT; + SetContextClipRect (&r); + + BatchGraphics (); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x8, 0x00), 0x6E)); + ClearDrawable (); + + if (pStr == (UNICODE *)~0) + { + if (pMenuState == 0 + && CommData.ConversationPhrases /* Melnorme shenanigans */ + && cur_comm == MELNORME_CONVERSATION) + wsprintf (buf, "%u Cr", MAKE_WORD ( + GET_GAME_STATE (MELNORME_CREDIT0), + GET_GAME_STATE (MELNORME_CREDIT1) + )); + else if (GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) + wsprintf (buf, "%lu RU", GLOBAL_SIS (ResUnits)); + else + wstrcpy (buf, "@ RU"); + pStr = buf; + } + else if (pStr == 0) + { + DateToString (buf, + GLOBAL (GameClock.month_index), + GLOBAL (GameClock.day_index), + GLOBAL (GameClock.year_index)); + pStr = buf; + } + + t.baseline.x = STATUS_MESSAGE_WIDTH >> 1; + t.baseline.y = STATUS_MESSAGE_HEIGHT - 1; + t.align = ALIGN_CENTER; + t.pStr = pStr; + t.CharCount = (COUNT)~0; + + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B)); + DrawText (&t); + UnbatchGraphics (); + + SetContextClipRect (NULL_PTR); + + SetContext (OldContext); +} + +void +DrawCaptainsName (void) +{ + RECT r; + TEXT t; + CONTEXT OldContext; + FONT OldFont; + COLOR OldColor; + + OldContext = SetContext (StatusContext); + OldFont = SetContextFont (TinyFont); + OldColor = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + + r.corner.x = 2 + 1; + r.corner.y = 10; + r.extent.width = SHIP_NAME_WIDTH - 2; + r.extent.height = SHIP_NAME_HEIGHT; + DrawFilledRectangle (&r); + + t.baseline.x = (STATUS_WIDTH >> 1) - 1; + t.baseline.y = r.corner.y + 6; + t.align = ALIGN_CENTER; + t.pStr = GLOBAL_SIS (CommanderName); + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x16, 0xB, 0x1F), 0x38)); + DrawText (&t); + + SetContextForeGroundColor (OldColor); + SetContextFont (OldFont); + SetContext (OldContext); +} + +void +DrawFlagshipName (BOOLEAN InStatusArea) +{ + RECT r; + TEXT t; + FONT OldFont; + COLOR OldColor; + CONTEXT OldContext; + UNICODE buf[60]; + + if (InStatusArea) + { + OldContext = SetContext (StatusContext); + OldFont = SetContextFont (StarConFont); + + r.corner.x = 2; + r.corner.y = 20; + r.extent.width = SHIP_NAME_WIDTH; + r.extent.height = SHIP_NAME_HEIGHT; + + t.pStr = GLOBAL_SIS (ShipName); + } + else + { + OldContext = SetContext (SpaceContext); + OldFont = SetContextFont (MicroFont); + + r.corner.x = 0; + r.corner.y = 1; + r.extent.width = SIS_SCREEN_WIDTH; + r.extent.height = SHIP_NAME_HEIGHT; + + t.pStr = buf; + wsprintf (buf, "%s %s", GAME_STRING (NAMING_STRING_BASE + 1), GLOBAL_SIS (ShipName)); + wstrupr (buf); + } + OldColor = SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + (SHIP_NAME_HEIGHT - InStatusArea); + t.align = ALIGN_CENTER; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x0C)); + DrawText (&t); + + SetContextForeGroundColor (OldColor); + SetContextFont (OldFont); + SetContext (OldContext); +} + +void +DrawLanders (void) +{ + BYTE i; + SIZE width; + RECT r; + STAMP s; + CONTEXT OldContext; + extern FRAME flagship_status; + + OldContext = SetContext (StatusContext); + + s.frame = IncFrameIndex (flagship_status); + GetFrameRect (s.frame, &r); + + i = GLOBAL_SIS (NumLanders); + r.corner.x = (STATUS_WIDTH >> 1) - r.corner.x; + s.origin.x = r.corner.x + - (((r.extent.width * i) + + (2 * (i - 1))) >> 1); + s.origin.y = 29; + + width = r.extent.width + 2; + r.extent.width = (r.extent.width * MAX_LANDERS) + + (2 * (MAX_LANDERS - 1)) + 2; + r.corner.x -= r.extent.width >> 1; + r.corner.y += s.origin.y; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + while (i--) + { + DrawStamp (&s); + s.origin.x += width; + } + + SetContext (OldContext); +} + +void +DrawStorageBays (BOOLEAN Refresh) +{ + BYTE i; + RECT r; + CONTEXT OldContext; + + OldContext = SetContext (StatusContext); + + r.extent.width = 2; + r.extent.height = 4; + r.corner.y = 123; + if (Refresh) + { + r.extent.width = NUM_MODULE_SLOTS * (r.extent.width + 1); + r.corner.x = (STATUS_WIDTH >> 1) - (r.extent.width >> 1); + + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + r.extent.width = 2; + } + + i = CountSISPieces (STORAGE_BAY); + if (i) + { + COUNT j; + + r.corner.x = (STATUS_WIDTH >> 1) + - ((i * (r.extent.width + 1)) >> 1); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + for (j = GLOBAL_SIS (TotalElementMass); + j >= STORAGE_BAY_CAPACITY; j -= STORAGE_BAY_CAPACITY) + { + DrawFilledRectangle (&r); + r.corner.x += r.extent.width + 1; + + --i; + } + + r.extent.height = (4 * j + (STORAGE_BAY_CAPACITY - 1)) / STORAGE_BAY_CAPACITY; + if (r.extent.height) + { + r.corner.y += 4 - r.extent.height; + DrawFilledRectangle (&r); + r.extent.height = 4 - r.extent.height; + if (r.extent.height) + { + r.corner.y = 123; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x6, 0x6, 0x6), 0x20)); + DrawFilledRectangle (&r); + } + r.corner.x += r.extent.width + 1; + + --i; + } + r.extent.height = 4; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x6, 0x6, 0x6), 0x20)); + while (i--) + { + DrawFilledRectangle (&r); + r.corner.x += r.extent.width + 1; + } + } + + SetContext (OldContext); +} + +void +GetGaugeRect (PRECT pRect, BOOLEAN IsCrewRect) +{ + pRect->extent.width = 24; + pRect->corner.x = (STATUS_WIDTH >> 1) - (pRect->extent.width >> 1); + pRect->extent.height = 5; + pRect->corner.y = IsCrewRect ? 117 : 38; +} + +void +DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta) +{ + STAMP s; + RECT r; + TEXT t; + UNICODE buf[12]; + CONTEXT OldContext; + + if (crew_delta == 0 && fuel_delta == 0 && resunit_delta == 0) + return; + + OldContext = SetContext (StatusContext); + + BatchGraphics (); + if (crew_delta == UNDEFINED_DELTA) + { + COUNT i; + extern FRAME flagship_status; + + s.origin.x = s.origin.y = 0; + s.frame = flagship_status; + DrawStamp (&s); + + s.origin.x = s.origin.y = 0; + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (DriveSlots[i])) < EMPTY_SLOT) + { + s.frame = SetAbsFrameIndex ( + flagship_status, which_piece + 1 + 0 + ); + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + DrawStamp (&s); + } + + s.origin.y -= 3; + } + s.origin.y = 0; + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (JetSlots[i])) < EMPTY_SLOT) + { + s.frame = SetAbsFrameIndex ( + flagship_status, which_piece + 1 + 1 + ); + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + DrawStamp (&s); + } + + s.origin.y -= 3; + } + s.origin.y = 0; + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + BYTE which_piece; + + if ((which_piece = + GLOBAL_SIS (ModuleSlots[i])) < EMPTY_SLOT) + { + s.frame = SetAbsFrameIndex ( + flagship_status, which_piece + 1 + 2 + ); + DrawStamp (&s); + } + + s.origin.y -= 3; + } + + { + HSTARSHIP hStarShip, hNextShip; + PPOINT pship_pos; + POINT ship_pos[MAX_COMBAT_SHIPS] = + { + SUPPORT_SHIP_PTS + }; + + ClearSemaphore (&GraphicsSem); + for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), + pship_pos = ship_pos; + hStarShip; hStarShip = hNextShip, ++pship_pos) + { + SHIP_FRAGMENTPTR StarShipPtr; + + StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + hNextShip = _GetSuccLink (StarShipPtr); + + s.origin.x = pship_pos->x; + s.origin.y = pship_pos->y; + s.frame = StarShipPtr->ShipInfo.icons; + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + ClearSemaphore (&GraphicsSem); + + UnlockStarShip ( + &GLOBAL (built_ship_q), + hStarShip + ); + } + SetSemaphore (&GraphicsSem); + } + } + + t.baseline.x = STATUS_WIDTH >> 1; + t.align = ALIGN_CENTER; + t.pStr = buf; + SetContextFont (TinyFont); + + if (crew_delta != 0) + { + if (crew_delta != UNDEFINED_DELTA) + { + COUNT CrewCapacity; + + if (crew_delta < 0 + && GLOBAL_SIS (CrewEnlisted) <= (COUNT)-crew_delta) + GLOBAL_SIS (CrewEnlisted) = 0; + else if ((GLOBAL_SIS (CrewEnlisted) += crew_delta) > + (CrewCapacity = GetCPodCapacity (NULL_PTR))) + GLOBAL_SIS (CrewEnlisted) = CrewCapacity; + } + + wsprintf (buf, "%u", GLOBAL_SIS (CrewEnlisted)); + GetGaugeRect (&r, TRUE); + t.baseline.y = r.corner.y + r.extent.height; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0xE, 0x00), 0x6C)); + DrawText (&t); + } + + if (fuel_delta != 0) + { + COUNT old_coarse_fuel, new_coarse_fuel; + + if (fuel_delta == UNDEFINED_DELTA) + old_coarse_fuel = (COUNT)~0; + else + { + DWORD FuelCapacity; + + old_coarse_fuel = (COUNT)( + GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE + ); + if (fuel_delta < 0 + && GLOBAL_SIS (FuelOnBoard) <= (DWORD)-fuel_delta) + GLOBAL_SIS (FuelOnBoard) = 0; + else if ((GLOBAL_SIS (FuelOnBoard) += fuel_delta) > + (FuelCapacity = GetFTankCapacity (NULL_PTR))) + GLOBAL_SIS (FuelOnBoard) = FuelCapacity; + } + + new_coarse_fuel = (COUNT)( + GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE + ); + if (new_coarse_fuel != old_coarse_fuel) + { + wsprintf (buf, "%u", new_coarse_fuel); + GetGaugeRect (&r, FALSE); + t.baseline.y = r.corner.y + r.extent.height; + t.CharCount = (COUNT)~0; + SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)); + DrawText (&t); + } + } + + if (crew_delta == UNDEFINED_DELTA) + { + DrawFlagshipName (TRUE); + DrawCaptainsName (); + DrawLanders (); + DrawStorageBays (FALSE); + } + + if (resunit_delta != 0) + { + if (resunit_delta != UNDEFINED_DELTA) + { + if (resunit_delta < 0 + && GLOBAL_SIS (ResUnits) <= (DWORD)-resunit_delta) + GLOBAL_SIS (ResUnits) = 0; + else + GLOBAL_SIS (ResUnits) += resunit_delta; + + DrawStatusMessage ((UNICODE *)~0); + } + else + { + r.corner.x = 1; + r.corner.y = 129; + r.extent.width = 62; + r.extent.height = 9; + DrawStarConBox (&r, 1, + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x8, 0x00), 0x6E)); + + if ((pMenuState == 0 + && CommData.ConversationPhrases /* Melnorme shenanigans */ + && cur_comm == MELNORME_CONVERSATION) + || (pMenuState + && (pMenuState->InputFunc == DoStarBase + || pMenuState->InputFunc == DoOutfit + || pMenuState->InputFunc == DoShipyard))) + DrawStatusMessage ((UNICODE *)~0); + else + DrawStatusMessage (NULL_PTR); + } + } + UnbatchGraphics (); + + SetContext (OldContext); +} + +COUNT +GetCrewCount (void) +{ + return (GLOBAL_SIS (CrewEnlisted)); +} + +COUNT +GetCPodCapacity (PPOINT ppt) +{ + COORD x; + COUNT slot, capacity; + + x = 207 - 13; + capacity = 0; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (GLOBAL_SIS (ModuleSlots[slot]) == CREW_POD) + { + if (ppt + && capacity <= GLOBAL_SIS (CrewEnlisted) + && capacity + CREW_POD_CAPACITY > + GLOBAL_SIS (CrewEnlisted)) + { + COUNT pod_remainder, which_row; + + pod_remainder = GLOBAL_SIS (CrewEnlisted) - capacity; + + ppt->x = x - ((pod_remainder % CREW_PER_ROW) << 1); + which_row = pod_remainder / CREW_PER_ROW; + ppt->y = 34 - (which_row << 1); + +// For Now. + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x05, 0x10, 0x05), 0x65) + ); + } + + capacity += CREW_POD_CAPACITY; + } + + x -= SHIP_PIECE_OFFSET; + } while (slot--); + + return (capacity); +} + +COUNT +GetSBayCapacity (PPOINT ppt) +{ + COORD x; + COUNT slot, capacity; + + x = 207 - 8 - 13; + capacity = 0; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (GLOBAL_SIS (ModuleSlots[slot]) == STORAGE_BAY) + { + if (ppt + && capacity < GLOBAL_SIS (TotalElementMass) + && capacity + STORAGE_BAY_CAPACITY >= + GLOBAL_SIS (TotalElementMass)) + { + COUNT bay_remainder, which_row; + COLOR color_bars[] = + { + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), + BUILD_COLOR (MAKE_RGB15 (0x1C, 0x1C, 0x1C), 0x11), + BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x18), 0x13), + BUILD_COLOR (MAKE_RGB15 (0x15, 0x15, 0x15), 0x15), + BUILD_COLOR (MAKE_RGB15 (0x12, 0x12, 0x12), 0x17), + BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), + BUILD_COLOR (MAKE_RGB15 (0xD, 0xD, 0xD), 0x1B), + BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x1D), + BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F), + BUILD_COLOR (MAKE_RGB15 (0x5, 0x5, 0x5), 0x21), + }; + + bay_remainder = GLOBAL_SIS (TotalElementMass) - capacity; + if ((which_row = bay_remainder / SBAY_MASS_PER_ROW) == 0) + SetContextForeGroundColor (BLACK_COLOR); + else + SetContextForeGroundColor (color_bars[--which_row]); + + ppt->x = x; + ppt->y = 34 - (which_row << 1); + } + + capacity += STORAGE_BAY_CAPACITY; + } + + x -= SHIP_PIECE_OFFSET; + } while (slot--); + + return (capacity); +} + +DWORD +GetFTankCapacity (PPOINT ppt) +{ + COORD x; + COUNT slot; + DWORD capacity; + + x = 200 - 13; + capacity = FUEL_RESERVE; + slot = NUM_MODULE_SLOTS - 1; + do + { + if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) + { + COUNT volume; + + volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK + ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; + if (ppt + && capacity <= GLOBAL_SIS (FuelOnBoard) + && capacity + volume > + GLOBAL_SIS (FuelOnBoard)) + { + COUNT which_row; + COLOR fuel_colors[] = + { + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7E), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7D), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7C), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), + }; + + which_row = (COUNT)( + (GLOBAL_SIS (FuelOnBoard) - capacity) + * MAX_FUEL_BARS / HEFUEL_TANK_CAPACITY + ); + ppt->x = x + 1; + if (volume == FUEL_TANK_CAPACITY) + ppt->y = 27 - which_row; + else + ppt->y = 30 - which_row; + + SetContextForeGroundColor (fuel_colors[which_row]); + SetContextBackGroundColor (fuel_colors[which_row + 1]); + } + + capacity += volume; + } + + x -= SHIP_PIECE_OFFSET; + } while (slot--); + + return (capacity); +} + +COUNT +CountSISPieces (BYTE piece_type) +{ + COUNT i, num_pieces; + + num_pieces = 0; + if (piece_type == FUSION_THRUSTER) + { + for (i = 0; i < NUM_DRIVE_SLOTS; ++i) + { + if (GLOBAL_SIS (DriveSlots[i]) == piece_type) + ++num_pieces; + } + } + else if (piece_type == TURNING_JETS) + { + for (i = 0; i < NUM_JET_SLOTS; ++i) + { + if (GLOBAL_SIS (JetSlots[i]) == piece_type) + ++num_pieces; + } + } + else + { + for (i = 0; i < NUM_MODULE_SLOTS; ++i) + { + if (GLOBAL_SIS (ModuleSlots[i]) == piece_type) + ++num_pieces; + } + } + + return (num_pieces); +} + +static TASK flash_task; +static RECT flash_rect; +static FRAME flash_frame; + +int flash_rect_func(void *blah) +{ +#define NORMAL_STRENGTH 4 +#define NORMAL_F_STRENGTH 0 + DWORD TimeIn; + SIZE strength, fstrength, incr; + + fstrength = NORMAL_F_STRENGTH; + incr = 1; + strength = NORMAL_STRENGTH; + TimeIn = GetTimeCounter (); + for (;;) + { + CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (ScreenContext); + + if (flash_rect.extent.width) + { + BatchGraphics (); + SetContextClipRect (&flash_rect); + if (flash_frame) + { +#define MIN_F_STRENGTH -3 +#define MAX_F_STRENGTH 3 + if ((fstrength += incr) > MAX_F_STRENGTH) + { + fstrength = MAX_F_STRENGTH - 1; + incr = -1; + } + else if (fstrength < MIN_F_STRENGTH) + { + fstrength = MIN_F_STRENGTH + 1; + incr = 1; + } + + if (fstrength != NORMAL_F_STRENGTH) + { + STAMP s; + + ClearDrawable (); + + SetGraphicStrength (fstrength > 0 ? fstrength : -fstrength, 16); + + s.origin.x = s.origin.y = 0; + s.frame = flash_frame; + DrawStamp (&s); + + if (fstrength < 0) + SetGraphicStrength (-8, 8); // add to -(partial mask) + else + SetGraphicStrength (8, -8); // add to (partial mask) + } + + DrawFromExtraScreen (&flash_rect); + } + else + { +#define MIN_STRENGTH 4 +#define MAX_STRENGTH 6 + if ((strength += 2) > MAX_STRENGTH) + strength = MIN_STRENGTH; + + SetGraphicStrength (strength, 4); + DrawFromExtraScreen (&flash_rect); + } + + SetContextClipRect (NULL_PTR); // this will flush whatever + + SetGraphicStrength (4, 4); + + UnbatchGraphics (); + } + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 16)); + } + + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +void +SetFlashRect (PRECT pRect, FRAME f) +{ + RECT clip_r, temp_r, old_r; + CONTEXT OldContext; + FRAME old_f; + + if (pRect != (PRECT)~0L) + { + GetContextClipRect (&clip_r); + OldContext = SetContext (ScreenContext); + } + else + { + OldContext = SetContext (StatusContext); + GetContextClipRect (&clip_r); + pRect = &temp_r; + temp_r.corner.x = RADAR_X - clip_r.corner.x; + temp_r.corner.y = RADAR_Y - clip_r.corner.y; + temp_r.extent.width = RADAR_WIDTH; + temp_r.extent.height = RADAR_HEIGHT; + SetContext (ScreenContext); + } + + old_r = flash_rect; + old_f = flash_frame; + if (pRect == 0 || pRect->extent.width == 0) + { + flash_rect.extent.width = 0; + if (flash_task) + { + DeleteTask (flash_task); + flash_task = 0; + } + } + else + { + flash_rect = *pRect; + flash_rect.corner.x += clip_r.corner.x; + flash_rect.corner.y += clip_r.corner.y; + flash_rect.extent.height += flash_rect.corner.y & 1; + flash_rect.corner.y &= ~1; + + if (flash_task == 0) + flash_task = AddTask (flash_rect_func, 2048); + } + + flash_frame = f; + + if (old_r.extent.width + && (old_r.extent.width != flash_rect.extent.width + || old_r.extent.height != flash_rect.extent.height + || old_r.corner.x != flash_rect.corner.x + || old_r.corner.y != flash_rect.corner.y + || old_f != flash_frame)) + { + DrawFromExtraScreen (&old_r); + } + + if (flash_rect.extent.width) + { + LoadIntoExtraScreen (&flash_rect); + } + + SetContext (OldContext); +} + +void +DrawMenuStateStrings (BYTE beg_index, BYTE NewState) +{ + BYTE end_index; + RECT r; + STAMP s; + CONTEXT OldContext; + extern FRAME PlayFrame; + + switch (beg_index) + { + case PM_SCAN: + end_index = PM_NAVIGATE; + break; + case PM_MIN_SCAN: + end_index = PM_LAUNCH_LANDER; + break; + case PM_SAVE_GAME: + end_index = PM_EXIT_MENU1; + break; + case PM_CONVERSE: + end_index = PM_SAVE_LOAD1; + break; + case PM_FUEL: + end_index = PM_EXIT_MENU2; + break; + case PM_CREW: + end_index = PM_EXIT_MENU3; + break; + case PM_SOUND_ON: + end_index = PM_EXIT_MENU4; + break; + default: + end_index = beg_index; + break; + } + + s.frame = 0; + if (NewState <= end_index - beg_index) + s.frame = SetAbsFrameIndex (PlayFrame, beg_index + NewState); + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (StatusContext); + GetContextClipRect (&r); + s.origin.x = RADAR_X - r.corner.x; + s.origin.y = RADAR_Y - r.corner.y; + r.corner.x = s.origin.x - 1; + r.corner.y = s.origin.y - 11; + r.extent.width = RADAR_WIDTH + 2; + r.extent.height = 11; + BatchGraphics (); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawFilledRectangle (&r); + if (s.frame) + { + DrawStamp (&s); + switch (beg_index + NewState) + { + TEXT t; + UNICODE buf[4]; + + case PM_CREW: + t.baseline.x = s.origin.x + RADAR_WIDTH - 2; + t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; + t.align = ALIGN_RIGHT; + t.CharCount = (COUNT)~0; + t.pStr = buf; + wsprintf (buf, "%u", GLOBAL (CrewCost)); + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); + DrawText (&t); + break; + case PM_FUEL: + t.baseline.x = s.origin.x + RADAR_WIDTH - 2; + t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; + t.align = ALIGN_RIGHT; + t.CharCount = (COUNT)~0; + t.pStr = buf; + wsprintf (buf, "%u", GLOBAL (FuelCost)); + SetContextFont (TinyFont); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); + DrawText (&t); + break; + } + } + UnbatchGraphics (); + if (flash_task + && flash_rect.corner.x == RADAR_X + && flash_rect.corner.y == RADAR_Y + && flash_rect.extent.width == RADAR_WIDTH + && flash_rect.extent.height == RADAR_HEIGHT) + SetFlashRect ((PRECT)~0L, (FRAME)0); + SetContext (OldContext); + ClearSemaphore (&GraphicsSem); +} + +void +SaveFlagshipState (void) +{ + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENTPTR ElementPtr; + + LockElement (hElement, &ElementPtr); + hNextElement = GetSuccElement (ElementPtr); + if (ElementPtr->state_flags & PLAYER_SHIP) + { + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( + StarShipPtr->ShipFacing + 1, 0 + ); + hNextElement = 0; + } + UnlockElement (hElement); + } + } + else if (pSolarSysState) + { + UWORD index1, index2; + FRAME frame; + + frame = GLOBAL (ShipStamp.frame); + + if (pSolarSysState->MenuState.Initialized < 3) + { + index1 = GetFrameIndex (frame) + 1; + if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) + index2 = 0; + else + { + index2 = (UWORD)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc + 1); + GLOBAL (ip_location) = + pSolarSysState->SunDesc[0].location; + } + } + else + { + if (GET_GAME_STATE (PLANETARY_CHANGE)) + { + PutPlanetInfo (); + SET_GAME_STATE (PLANETARY_CHANGE, 0); + } + + index1 = LOWORD (frame); + index2 = 1; + if (pSolarSysState->pOrbitalDesc != + pSolarSysState->pBaseDesc->pPrevDesc) + index2 += pSolarSysState->pOrbitalDesc + - pSolarSysState->pBaseDesc + 1; + index2 = MAKE_WORD (HIWORD (frame), index2); + } + + GLOBAL (ShipStamp.frame) = + (FRAME)MAKE_DWORD (index1, index2); + } +} + diff --git a/sc2/src/sc2code/sis.h b/sc2/src/sc2code/sis.h new file mode 100644 index 000000000..435732711 --- /dev/null +++ b/sc2/src/sc2code/sis.h @@ -0,0 +1,252 @@ +#ifndef _SIS_H +#define _SIS_H + +#include "planets/planets.h" + +enum +{ + PM_SCAN = 0, + PM_STARMAP, + PM_DEVICES, + PM_CARGO, + PM_ROSTER, + PM_SAVE_LOAD0, + PM_NAVIGATE, + + PM_MIN_SCAN, + PM_ENE_SCAN, + PM_BIO_SCAN, + PM_EXIT_MENU0, + PM_AUTO_SCAN, + PM_LAUNCH_LANDER, + + PM_SAVE_GAME, + PM_LOAD_GAME, + PM_CHANGE_SETTINGS, + PM_EXIT_MENU1, + + PM_CONVERSE, + PM_ATTACK, + PM_SAVE_LOAD1, + + PM_FUEL, + PM_MODULE, + PM_SAVE_LOAD2, + PM_EXIT_MENU2, + + PM_CREW, + PM_SAVE_LOAD3, + PM_EXIT_MENU3, + + PM_SOUND_ON, + PM_SOUND_OFF, + PM_MUSIC_ON, + PM_MUSIC_OFF, + PM_CYBORG_OFF, + PM_CYBORG_NORMAL, + PM_CYBORG_DOUBLE, + PM_CYBORG_SUPER, + PM_CHANGE_CAPTAIN, + PM_CHANGE_SHIP, + PM_EXIT_MENU4 +}; + +#define CLEAR_SIS_RADAR (1 << 2) +#define DRAW_SIS_DISPLAY (1 << 3) + +#define UNDEFINED_DELTA 0x7FFF + +#define RADAR_X (4 + (SCREEN_WIDTH - STATUS_WIDTH - SAFE_X)) +#define RADAR_WIDTH (STATUS_WIDTH - 8) +#define RADAR_HEIGHT 53 +#define RADAR_Y (SIS_ORG_Y + SIS_SCREEN_HEIGHT - RADAR_HEIGHT) +#define NUM_RADAR_SCREENS 12 +#define MAG_SHIFT 2 /* driving on planet */ + +#define SHIP_NAME_WIDTH 60 +#define SHIP_NAME_HEIGHT 7 + +#define NUM_DRIVE_SLOTS 11 +#define NUM_JET_SLOTS 8 +#define NUM_MODULE_SLOTS 16 + +#define CREW_POD_CAPACITY 50 +#define STORAGE_BAY_CAPACITY 500 /* km cubed */ +#define FUEL_TANK_SCALE 100 +#define FUEL_TANK_CAPACITY (50 * FUEL_TANK_SCALE) +#define HEFUEL_TANK_CAPACITY (100 * FUEL_TANK_SCALE) +#define MODULE_COST_SCALE 50 + +#define CREW_EXPENSE_THRESHOLD 1000 + +#define CREW_PER_ROW 5 +#define SBAY_MASS_PER_ROW 50 + +#define MAX_FUEL_BARS 10 +#define FUEL_VOLUME_PER_ROW (HEFUEL_TANK_CAPACITY / MAX_FUEL_BARS) +#define FUEL_RESERVE FUEL_VOLUME_PER_ROW + +#define MAX_COMBAT_SHIPS 12 +#define MAX_BATTLE_GROUPS 64 + +#define IP_SHIP_THRUST_INCREMENT 8 +#define IP_SHIP_TURN_WAIT 17 +#define IP_SHIP_TURN_DECREMENT 2 + +#define BOGUS_MASS 5 + +#define BIO_CREDIT_VALUE 2 + +enum +{ + PLANET_LANDER = 0, + /* thruster types */ + FUSION_THRUSTER, + /* jet types */ + TURNING_JETS, + /* module types */ + CREW_POD, + STORAGE_BAY, + FUEL_TANK, + HIGHEFF_FUELSYS, + DYNAMO_UNIT, + SHIVA_FURNACE, + GUN_WEAPON, + BLASTER_WEAPON, + CANNON_WEAPON, + TRACKING_SYSTEM, + ANTIMISSILE_DEFENSE, + + NUM_PURCHASE_MODULES, + + BOMB_MODULE_0 = NUM_PURCHASE_MODULES, + BOMB_MODULE_1, + BOMB_MODULE_2, + BOMB_MODULE_3, + BOMB_MODULE_4, + BOMB_MODULE_5, + + NUM_MODULES = 20 /* must be last entry */ +}; + +#define EMPTY_SLOT NUM_MODULES +#define NUM_BOMB_MODULES 10 + +#define DRIVE_SIDE_X (31 - 13) +#define DRIVE_SIDE_Y 56 +#define DRIVE_TOP_X (33 - 13) +#define DRIVE_TOP_Y (65 + 21) + +#define JET_SIDE_X (71 - 13) +#define JET_SIDE_Y 48 +#define JET_TOP_X (70 - 13) +#define JET_TOP_Y (73 + 21) + +#define MODULE_SIDE_X (17 - 13) +#define MODULE_SIDE_Y 14 +#define MODULE_TOP_X (17 - 13) +#define MODULE_TOP_Y (96 + 21) + +#define SHIP_PIECE_OFFSET 12 + +#define MAX_BUILT_SHIPS 12 +#define MAX_LANDERS 10 + +#define SUPPORT_SHIP_PTS \ + {3 + 0, 30 + (2 * 16)}, \ + {3 + 42, 30 + (2 * 16)}, \ + {3 + 0, 30 + (3 * 16)}, \ + {3 + 42, 30 + (3 * 16)}, \ + {3 + 0, 30 + (1 * 16)}, \ + {3 + 42, 30 + (1 * 16)}, \ + {3 + 0, 30 + (4 * 16)}, \ + {3 + 42, 30 + (4 * 16)}, \ + {3 + 0, 30 + (0 * 16)}, \ + {3 + 42, 30 + (0 * 16)}, \ + {3 + 0, 30 + (5 * 16)}, \ + {3 + 42, 30 + (5 * 16)}, + +#define SIS_MESSAGE_WIDTH (SIS_SCREEN_WIDTH - 69 - 2) +#define SIS_MESSAGE_HEIGHT 8 +#define SIS_TITLE_WIDTH 55 +#define SIS_TITLE_HEIGHT 8 +#define STATUS_MESSAGE_WIDTH 60 +#define STATUS_MESSAGE_HEIGHT 7 + +typedef struct +{ + long log_x, log_y; + + DWORD ResUnits; + + DWORD FuelOnBoard; + COUNT CrewEnlisted; + COUNT TotalElementMass, TotalBioMass; + + BYTE ModuleSlots[NUM_MODULE_SLOTS]; + BYTE DriveSlots[NUM_DRIVE_SLOTS]; + BYTE JetSlots[NUM_JET_SLOTS]; + + BYTE NumLanders; + + COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES]; + + UNICODE ShipName[16]; + UNICODE CommanderName[16]; + UNICODE PlanetName[16]; +} SIS_STATE; +typedef SIS_STATE *PSIS_STATE; + +#define MAX_EXCLUSIVE_DEVICES 16 + +typedef struct +{ + SIS_STATE SS; + BYTE Activity; + BYTE Flags; + BYTE day_index, month_index; + COUNT year_index; + BYTE MCreditLo, MCreditHi; + BYTE NumShips, NumDevices; + BYTE ShipList[MAX_BUILT_SHIPS]; + BYTE DeviceList[MAX_EXCLUSIVE_DEVICES]; +} SUMMARY_DESC; + +#define OVERRIDE_LANDER_FLAGS (1 << 7) +#define AFTER_BOMB_INSTALLED (1 << 7) + +extern BOOLEAN InitSIS (void); +extern void UninitSIS (void); + +extern void SeedUniverse (void); +extern BOOLEAN LoadHyperspace (void); +extern BOOLEAN FreeHyperspace (void); +extern void MoveSIS (PSIZE pdx, PSIZE pdy); +extern void RepairSISBorder (void); +extern void InitSISContexts (void); +extern void DrawSISFrame (void); +extern void ClearSISRect (BYTE ClearFlags); +extern void DrawHyperCoords (POINT puniverse); +extern void DrawSISTitle (UNICODE *pStr); +extern void DrawSISMessage (UNICODE *pStr); +extern void DrawGameDate (void); +extern void DateToString (UNICODE *buf, BYTE month_index, BYTE day_index, + COUNT year_index); +extern void DrawStatusMessage (UNICODE *pStr); +extern void DrawLanders (void); +extern void DrawStorageBays (BOOLEAN Refresh); +extern void DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int + resunit_delta); +extern COUNT GetCrewCount (void); +extern COUNT GetCPodCapacity (PPOINT ppt); +extern COUNT GetLBayCapacity (PPOINT ppt); +extern COUNT GetSBayCapacity (PPOINT ppt); +extern DWORD GetFTankCapacity (PPOINT ppt); +extern COUNT CountSISPieces (BYTE piece_type); +extern void DrawMenuStateStrings (BYTE beg_index, BYTE NewState); +extern void DoMenuOptions (void); +extern void DrawFlagshipName (BOOLEAN InStatusArea); +extern void DrawCaptainsName (void); + +#endif /* _SIS_H */ + diff --git a/sc2/src/sc2code/sounds.h b/sc2/src/sc2code/sounds.h new file mode 100644 index 000000000..dd44191b9 --- /dev/null +++ b/sc2/src/sc2code/sounds.h @@ -0,0 +1,33 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SOUNDS_H +#define _SOUNDS_H + +typedef enum +{ + GRAB_CREW = 0, + SHIP_EXPLODES, + TARGET_DAMAGED_FOR_1_PT, + TARGET_DAMAGED_FOR_2_3_PT, + TARGET_DAMAGED_FOR_4_5_PT, + TARGET_DAMAGED_FOR_6_PLUS_PT +} SOUND_EFFECTS; + +#endif /* _SOUNDS_H */ + diff --git a/sc2/src/sc2code/star3do.res b/sc2/src/sc2code/star3do.res new file mode 100644 index 000000000..4d3690ca6 --- /dev/null +++ b/sc2/src/sc2code/star3do.res @@ -0,0 +1,790 @@ +INCLUDE star3do.typ + +PACKAGE INIT_PACKAGE starcon.pkg + KEY_CONFIG JOYSTICK_KEYS starcon.key +PATH lbm + STRTAB STARCON_COLOR_MAP scclrtab.ct + +PACKAGE TITLE_PACKAGE starcon.pkg + GFXRES TITLE_ANIM title.ani + +PATH . +PACKAGE ARILOU_SHIP_PACKAGE starcon.pkg + RES_INDEX ARILOU_SHIP_INDEX arilou.shp +PACKAGE CHMMR_SHIP_PACKAGE starcon.pkg + RES_INDEX CHMMR_SHIP_INDEX chmmr.shp +PACKAGE EARTHLING_SHIP_PACKAGE starcon.pkg + RES_INDEX EARTHLING_SHIP_INDEX human.shp +PACKAGE ORZ_SHIP_PACKAGE starcon.pkg + RES_INDEX ORZ_SHIP_INDEX orz.shp +PACKAGE PKUNK_SHIP_PACKAGE starcon.pkg + RES_INDEX PKUNK_SHIP_INDEX pkunk.shp +PACKAGE SHOFIXTI_SHIP_PACKAGE starcon.pkg + RES_INDEX SHOFIXTI_SHIP_INDEX shofixti.shp +PACKAGE SPATHI_SHIP_PACKAGE starcon.pkg + RES_INDEX SPATHI_SHIP_INDEX spathi.shp +PACKAGE SUPOX_SHIP_PACKAGE starcon.pkg + RES_INDEX SUPOX_SHIP_INDEX supox.shp +PACKAGE THRADD_SHIP_PACKAGE starcon.pkg + RES_INDEX THRADD_SHIP_INDEX thradd.shp +PACKAGE UTWIG_SHIP_PACKAGE starcon.pkg + RES_INDEX UTWIG_SHIP_INDEX utwig.shp +PACKAGE VUX_SHIP_PACKAGE starcon.pkg + RES_INDEX VUX_SHIP_INDEX vux.shp +PACKAGE YEHAT_SHIP_PACKAGE starcon.pkg + RES_INDEX YEHAT_SHIP_INDEX yehat.shp +PACKAGE MELNORME_SHIP_PACKAGE starcon.pkg + RES_INDEX MELNORME_SHIP_INDEX melnorme.shp +PACKAGE DRUUGE_SHIP_PACKAGE starcon.pkg + RES_INDEX DRUUGE_SHIP_INDEX druuge.shp +PACKAGE ILWRATH_SHIP_PACKAGE starcon.pkg + RES_INDEX ILWRATH_SHIP_INDEX ilwrath.shp +PACKAGE MYCON_SHIP_PACKAGE starcon.pkg + RES_INDEX MYCON_SHIP_INDEX mycon.shp +PACKAGE SLYLANDRO_SHIP_PACKAGE starcon.pkg + RES_INDEX SLYLANDRO_SHIP_INDEX slylandr.shp +PACKAGE UMGAH_SHIP_PACKAGE starcon.pkg + RES_INDEX UMGAH_SHIP_INDEX umgah.shp +PACKAGE URQUAN_SHIP_PACKAGE starcon.pkg + RES_INDEX URQUAN_SHIP_INDEX urquan.shp +PACKAGE ZOQFOTPIK_SHIP_PACKAGE starcon.pkg + RES_INDEX ZOQFOTPIK_SHIP_INDEX zoqfot.shp +PACKAGE SYREEN_SHIP_PACKAGE starcon.pkg + RES_INDEX SYREEN_SHIP_INDEX syreen.shp +PACKAGE BLACKURQ_SHIP_PACKAGE starcon.pkg + RES_INDEX BLACKURQ_SHIP_INDEX blackurq.shp +PACKAGE ANDROSYN_SHIP_PACKAGE starcon.pkg + RES_INDEX ANDROSYN_SHIP_INDEX androsyn.shp +PACKAGE CHENJESU_SHIP_PACKAGE starcon.pkg + RES_INDEX CHENJESU_SHIP_INDEX chenjesu.shp +PACKAGE MMRNMHRM_SHIP_PACKAGE starcon.pkg + RES_INDEX MMRNMHRM_SHIP_INDEX mmrnmhrm.shp + +PATH lbm +PACKAGE KERNEL_PACKAGE starcon.pkg + FONTRES STARCON_FONT starcon.fon + FONTRES TINY_FONT tiny.fon + GFXRES STATUS_MASK_PMAP_ANIM status.ani + GFXRES ACTIVITY_ANIM activity.ani + STRTAB STARCON_GAME_STRINGS starcon.txt + +PACKAGE SC2KERNEL_PACKAGE starcon.pkg + GFXRES PLAYMENU_ANIM playmenu.ani + +PACKAGE MICROFONT_PACKAGE starcon.pkg + FONTRES MICRO_FONT micro.fon + +PACKAGE SC2DATA_PACKAGE starcon.pkg + GFXRES FLAGSTAT_MASK_PMAP_ANIM flagstat.ani + GFXRES MISCDATA_MASK_PMAP_ANIM miscdata.ani + +PACKAGE MENU_SOUND_PACKAGE starcon.pkg + SNDRES MENU_SOUNDS menusnd.snd + +PACKAGE SOUND_PACKAGE starcon.pkg + SNDRES GAME_SOUNDS gamesnd.snd + +PACKAGE SPACE_PACKAGE starcon.pkg + GFXRES STAR_MASK_PMAP_ANIM stars.ani + + GFXRES ASTEROID_BIG_MASK_PMAP_ANIM astbig.ani + GFXRES ASTEROID_MED_MASK_PMAP_ANIM astmed.ani + GFXRES ASTEROID_SML_MASK_PMAP_ANIM astsml.ani + + GFXRES BLAST_BIG_MASK_PMAP_ANIM blabig.ani + GFXRES BLAST_MED_MASK_PMAP_ANIM blamed.ani + GFXRES BLAST_SML_MASK_PMAP_ANIM blasml.ani + + GFXRES BOOM_BIG_MASK_PMAP_ANIM boobig.ani + GFXRES BOOM_MED_MASK_PMAP_ANIM boomed.ani + GFXRES BOOM_SML_MASK_PMAP_ANIM boosml.ani + +PACKAGE AMBIENT_HYPER_PACKAGE starcon.pkg + GFXRES AMBIENT_MASK_PMAP_ANIM ambanim.ani +PACKAGE HYPER_PACKAGE starcon.pkg + GFXRES HYPERSTARS_MASK_PMAP_ANIM hyperstr.ani + STRTAB HYPER_COLOR_TAB hyperpal.ct +PACKAGE ARISPACE_PACKAGE starcon.pkg + GFXRES ARISPACE_MASK_PMAP_ANIM arispace.ani + STRTAB ARISPACE_COLOR_TAB arispace.ct + +PACKAGE HYPERSPACE_MUSIC_PACKAGE starcon.pkg + MUSICRES HYPERSPACE_MUSIC hyper.mod +PACKAGE QUASISPACE_MUSIC_PACKAGE starcon.pkg + MUSICRES QUASISPACE_MUSIC arispace.mod + +PATH ipanims +PACKAGE INIT_PACKAGE starcon.pkg + GFXRES IPBKGND_MASK_PMAP_ANIM obbkgnd.ani + +PACKAGE IP_PACKAGE starcon.pkg + GFXRES SISIP_MASK_PMAP_ANIM sis_ip.ani + GFXRES ORBPLAN_MASK_PMAP_ANIM orbplan.ani + STRTAB ORBPLAN_COLOR_MAP orbplan.ct + GFXRES SUN_MASK_PMAP_ANIM ip_sun.ani + +PACKAGE LANDER_PACKAGE starcon.pkg + GFXRES LANDER_MASK_PMAP_ANIM lander.ani + SNDRES LANDER_SOUNDS landsnds.snd + GFXRES QUAKE_MASK_PMAP_ANIM quake.ani + GFXRES LIGHTNING_MASK_ANIM lightnin.ani + GFXRES LAVA_MASK_PMAP_ANIM lavaspot.ani + GFXRES LANDER_SHIELD_MASK_ANIM lndrshld.ani + GFXRES LANDER_LAUNCH_MASK_PMAP_ANIM launch.ani + GFXRES LANDER_RETURN_MASK_PMAP_ANIM return.ani +PACKAGE ORBIT_VIEW_PACKAGE starcon.pkg + GFXRES ORBIT_VIEW_ANIM orbview.ani + +PACKAGE EARTH_PACKAGE starcon.pkg + GFXRES EARTH_MASK_ANIM eartmask.ani + +PACKAGE CANNISTER_PACKAGE starcon.pkg + GFXRES CANNISTER_MASK_PMAP_ANIM lifecan.ani + +PACKAGE LIFE00_PACKAGE starcon.pkg + GFXRES LIFE00_MASK_PMAP_ANIM lifea.ani +PACKAGE LIFE01_PACKAGE starcon.pkg + GFXRES LIFE01_MASK_PMAP_ANIM lifeb.ani +PACKAGE LIFE02_PACKAGE starcon.pkg + GFXRES LIFE02_MASK_PMAP_ANIM lifec.ani +PACKAGE LIFE03_PACKAGE starcon.pkg + GFXRES LIFE03_MASK_PMAP_ANIM lifed.ani +PACKAGE LIFE04_PACKAGE starcon.pkg + GFXRES LIFE04_MASK_PMAP_ANIM lifee.ani +PACKAGE LIFE05_PACKAGE starcon.pkg + GFXRES LIFE05_MASK_PMAP_ANIM lifef.ani +PACKAGE LIFE06_PACKAGE starcon.pkg + GFXRES LIFE06_MASK_PMAP_ANIM lifeg.ani +PACKAGE LIFE07_PACKAGE starcon.pkg + GFXRES LIFE07_MASK_PMAP_ANIM lifeh.ani +PACKAGE LIFE08_PACKAGE starcon.pkg + GFXRES LIFE08_MASK_PMAP_ANIM lifei.ani +PACKAGE LIFE09_PACKAGE starcon.pkg + GFXRES LIFE09_MASK_PMAP_ANIM lifej.ani +PACKAGE LIFE10_PACKAGE starcon.pkg + GFXRES LIFE10_MASK_PMAP_ANIM lifek.ani +PACKAGE LIFE11_PACKAGE starcon.pkg + GFXRES LIFE11_MASK_PMAP_ANIM lifel.ani +PACKAGE LIFE12_PACKAGE starcon.pkg + GFXRES LIFE12_MASK_PMAP_ANIM lifem.ani +PACKAGE LIFE13_PACKAGE starcon.pkg + GFXRES LIFE13_MASK_PMAP_ANIM lifen.ani +PACKAGE LIFE14_PACKAGE starcon.pkg + GFXRES LIFE14_MASK_PMAP_ANIM lifeo.ani +PACKAGE LIFE15_PACKAGE starcon.pkg + GFXRES LIFE15_MASK_PMAP_ANIM lifep.ani +PACKAGE LIFE16_PACKAGE starcon.pkg + GFXRES LIFE16_MASK_PMAP_ANIM lifeq.ani +PACKAGE LIFE17_PACKAGE starcon.pkg + GFXRES LIFE17_MASK_PMAP_ANIM lifer.ani +PACKAGE LIFE18_PACKAGE starcon.pkg + GFXRES LIFE18_MASK_PMAP_ANIM lifes.ani +PACKAGE LIFE19_PACKAGE starcon.pkg + GFXRES LIFE19_MASK_PMAP_ANIM lifet.ani +PACKAGE LIFE20_PACKAGE starcon.pkg + GFXRES LIFE20_MASK_PMAP_ANIM lifew.ani +PACKAGE LIFE21_PACKAGE starcon.pkg + GFXRES LIFE21_MASK_PMAP_ANIM lifex.ani +PACKAGE LIFE22_PACKAGE starcon.pkg + GFXRES LIFE22_MASK_PMAP_ANIM lifey.ani +PACKAGE LIFE23_PACKAGE starcon.pkg + GFXRES LIFE23_MASK_PMAP_ANIM lifeu.ani +PACKAGE LIFE24_PACKAGE starcon.pkg + GFXRES LIFE24_MASK_PMAP_ANIM lifev.ani +PACKAGE LIFE25_PACKAGE starcon.pkg + GFXRES LIFE25_MASK_PMAP_ANIM lifez.ani + +PACKAGE OOLITE_PACKAGE starcon.pkg + STRTAB OOLITE_COLOR_TAB str_cts_.ct + STRTAB OOLITE_XLAT_TAB mtl2xlts.xlt +PACKAGE YTTRIC_COLOR_PACKAGE starcon.pkg + STRTAB YTTRIC_COLOR_TAB wr1_cts_.ct +PACKAGE YTTRIC_XLAT_PACKAGE starcon.pkg + STRTAB YTTRIC_XLAT_TAB rst_xlts.xlt +PACKAGE QD_COLOR_PACKAGE starcon.pkg + STRTAB QUASI_DEGENERATE_COLOR_TAB co2_cts_.ct +PACKAGE QD_XLAT_PACKAGE starcon.pkg + STRTAB QUASI_DEGENERATE_XLAT_TAB bnd_xlts.xlt +PACKAGE LANTHANIDE_COLOR_PACKAGE starcon.pkg + STRTAB LANTHANIDE_COLOR_TAB ylgscts_.ct +PACKAGE TREASURE_COLOR_PACKAGE starcon.pkg + STRTAB TREASURE_COLOR_TAB lll_cts_.ct +PACKAGE UREA_COLOR_PACKAGE starcon.pkg + STRTAB UREA_COLOR_TAB ylgscts_.ct +PACKAGE UREA_XLAT_PACKAGE starcon.pkg + STRTAB UREA_XLAT_TAB den_xlts.xlt +PACKAGE METAL_PACKAGE starcon.pkg + STRTAB METAL_COLOR_TAB mtl_cts_.ct + STRTAB METAL_XLAT_TAB mtl1xlts.xlt +PACKAGE RADIOACTIVE_COLOR_PACKAGE starcon.pkg + STRTAB RADIOACTIVE_COLOR_TAB rrr_cts_.ct +PACKAGE OPALESCENT_COLOR_PACKAGE starcon.pkg + STRTAB OPALESCENT_COLOR_TAB ice_cts_.ct +PACKAGE OPALESCENT_XLAT_PACKAGE starcon.pkg + STRTAB OPALESCENT_XLAT_TAB ice_xlts.xlt +PACKAGE CYANIC_COLOR_PACKAGE starcon.pkg + STRTAB CYANIC_COLOR_TAB qqq_cts_.ct +PACKAGE ACID_COLOR_PACKAGE starcon.pkg + STRTAB ACID_COLOR_TAB rst_cts_.ct +PACKAGE ALKALI_COLOR_PACKAGE starcon.pkg + STRTAB ALKALI_COLOR_TAB bnd_cts_.ct +PACKAGE HALIDE_COLOR_PACKAGE starcon.pkg + STRTAB HALIDE_COLOR_TAB rdx_cts_.ct +PACKAGE GREEN_COLOR_PACKAGE starcon.pkg + STRTAB GREEN_COLOR_TAB nnn_cts_.ct +PACKAGE COPPER_COLOR_PACKAGE starcon.pkg + STRTAB COPPER_COLOR_TAB qqq_cts_.ct +PACKAGE CARBIDE_COLOR_PACKAGE starcon.pkg + STRTAB CARBIDE_COLOR_TAB rrr_cts_.ct +PACKAGE ULTRAMARINE_COLOR_PACKAGE starcon.pkg + STRTAB ULTRAMARINE_COLOR_TAB den_cts_.ct +PACKAGE NOBLE_COLOR_PACKAGE starcon.pkg + STRTAB NOBLE_COLOR_TAB blgscts_.ct +PACKAGE AZURE_COLOR_PACKAGE starcon.pkg + STRTAB AZURE_COLOR_TAB www_cts_.ct +PACKAGE CHONDRITE_PACKAGE starcon.pkg + STRTAB CHONDRITE_COLOR_TAB grv_cts_.ct + STRTAB CHONDRITE_XLAT_TAB grv_xlts.xlt +PACKAGE PURPLE_COLOR_PACKAGE starcon.pkg + STRTAB PURPLE_COLOR_TAB vigscts_.ct +PACKAGE SUPER_DENSE_COLOR_PACKAGE starcon.pkg + STRTAB SUPER_DENSE_COLOR_TAB kkk_cts_.ct +PACKAGE PELLUCID_COLOR_PACKAGE starcon.pkg + STRTAB PELLUCID_COLOR_TAB prgscts_.ct +PACKAGE DUST_COLOR_PACKAGE starcon.pkg + STRTAB DUST_COLOR_TAB dst_cts_.ct +PACKAGE MAROON_COLOR_PACKAGE starcon.pkg + STRTAB MAROON_COLOR_TAB dst_cts_.ct +PACKAGE CIMMERIAN_COLOR_PACKAGE starcon.pkg + STRTAB CIMMERIAN_COLOR_TAB jjj_cts_.ct +PACKAGE INFRARED_COLOR_PACKAGE starcon.pkg + STRTAB INFRARED_COLOR_TAB dst_cts_.ct +PACKAGE SELENIC_COLOR_PACKAGE starcon.pkg + STRTAB SELENIC_COLOR_TAB lit_cts_.ct +PACKAGE AURIC_COLOR_PACKAGE starcon.pkg + STRTAB AURIC_COLOR_TAB ylgscts_.ct +PACKAGE FLUORESCENT_COLOR_PACKAGE starcon.pkg + STRTAB FLUORESCENT_COLOR_TAB vigscts_.ct +PACKAGE ULTRAVIOLET_COLOR_PACKAGE starcon.pkg + STRTAB ULTRAVIOLET_COLOR_TAB vigscts_.ct +PACKAGE PLUTONIC_COLOR_PACKAGE starcon.pkg + STRTAB PLUTONIC_COLOR_TAB orgscts_.ct +PACKAGE RAINBOW_COLOR_PACKAGE starcon.pkg + STRTAB RAINBOW_COLOR_TAB rai_cts_.ct + STRTAB RAINBOW_XLAT_TAB rai_xlts.xlt +PACKAGE CRACKED_PACKAGE starcon.pkg + STRTAB CRACKED_COLOR_TAB hel_cts_.ct + STRTAB CRACKED_XLAT_TAB hel_xlts.xlt +PACKAGE SAPPHIRE_COLOR_PACKAGE starcon.pkg + STRTAB SAPPHIRE_COLOR_TAB cry_cts_.ct +PACKAGE SAPPHIRE_XLAT_PACKAGE starcon.pkg + STRTAB SAPPHIRE_XLAT_TAB cry_xlts.xlt +PACKAGE ORGANIC_COLOR_PACKAGE starcon.pkg + STRTAB ORGANIC_COLOR_TAB bnd_cts_.ct +PACKAGE XENOLITHIC_COLOR_PACKAGE starcon.pkg + STRTAB XENOLITHIC_COLOR_TAB cygscts_.ct +PACKAGE REDUX_PACKAGE starcon.pkg + STRTAB REDUX_COLOR_TAB rdx_cts_.ct + STRTAB REDUX_XLAT_TAB rdx1xlts.xlt +PACKAGE PRIMORDIAL_COLOR_PACKAGE starcon.pkg + STRTAB PRIMORDIAL_COLOR_TAB co2_cts_.ct +PACKAGE EMERALD_COLOR_PACKAGE starcon.pkg + STRTAB EMERALD_COLOR_TAB eme_cts_.ct +PACKAGE CHLORINE_COLOR_PACKAGE starcon.pkg + STRTAB CHLORINE_COLOR_TAB rst_cts_.ct +PACKAGE CHLORINE_XLAT_PACKAGE starcon.pkg + STRTAB CHLORINE_XLAT_TAB h2o_xlts.xlt +PACKAGE MAGNETIC_COLOR_PACKAGE starcon.pkg + STRTAB MAGNETIC_COLOR_TAB rdx_cts_.ct +PACKAGE WATER_COLOR_PACKAGE starcon.pkg + STRTAB WATER_COLOR_TAB h2o_cts_.ct +PACKAGE TELLURIC_COLOR_PACKAGE starcon.pkg + STRTAB TELLURIC_COLOR_TAB h2o_cts_.ct +PACKAGE HYDROCARBON_COLOR_PACKAGE starcon.pkg + STRTAB HYDROCARBON_COLOR_TAB www_cts_.ct +PACKAGE IODINE_COLOR_PACKAGE starcon.pkg + STRTAB IODINE_COLOR_TAB co2_cts_.ct +PACKAGE VINYLOGOUS_COLOR_PACKAGE starcon.pkg + STRTAB VINYLOGOUS_COLOR_TAB wr1_cts_.ct +PACKAGE RUBY_COLOR_PACKAGE starcon.pkg + STRTAB RUBY_COLOR_TAB rub_cts_.ct +PACKAGE MAGMA_COLOR_PACKAGE starcon.pkg + STRTAB MAGMA_COLOR_TAB rrr_cts_.ct +PACKAGE CRIMSON_COLOR_PACKAGE starcon.pkg + STRTAB CRIMSON_COLOR_TAB bbb_cts_.ct + +PACKAGE GAS_XLAT_PACKAGE starcon.pkg + STRTAB GAS_XLAT_TAB gasg.xlt + +PACKAGE BLU_GAS_CT_PACKAGE starcon.pkg + STRTAB BLU_GAS_COLOR_TAB blugasgi.ct +PACKAGE CYA_GAS_CT_PACKAGE starcon.pkg + STRTAB CYA_GAS_COLOR_TAB cyagasgi.ct +PACKAGE GRN_GAS_CT_PACKAGE starcon.pkg + STRTAB GRN_GAS_COLOR_TAB grngasgi.ct +PACKAGE GRY_GAS_CT_PACKAGE starcon.pkg + STRTAB GRY_GAS_COLOR_TAB grygasgi.ct +PACKAGE ORA_GAS_CT_PACKAGE starcon.pkg + STRTAB ORA_GAS_COLOR_TAB oragasgi.ct +PACKAGE PUR_GAS_CT_PACKAGE starcon.pkg + STRTAB PUR_GAS_COLOR_TAB purgasgi.ct +PACKAGE RED_GAS_CT_PACKAGE starcon.pkg + STRTAB RED_GAS_COLOR_TAB redgasgi.ct +PACKAGE VIO_GAS_CT_PACKAGE starcon.pkg + STRTAB VIO_GAS_COLOR_TAB viogasgi.ct +PACKAGE YEL_GAS_CT_PACKAGE starcon.pkg + STRTAB YEL_GAS_COLOR_TAB yelgasgi.ct + +PACKAGE REPORT_PACKAGE starcon.pkg + FONTRES LANDER_FONT lander.fon +PACKAGE MOONBASE_PACKAGE starcon.pkg + GFXRES MOONBASE_MASK_PMAP_ANIM moonbase.ani + STRTAB MOONBASE_STRTAB moonbase.txt +PACKAGE MAIDENS_PACKAGE starcon.pkg + GFXRES MAIDENS_MASK_PMAP_ANIM maidens.ani + STRTAB MAIDENS_STRTAB maidens.txt +PACKAGE CHMMR_BASE_PACKAGE starcon.pkg + STRTAB CHMMR_BASE_STRTAB chmmrbas.txt +PACKAGE AQUA_PACKAGE starcon.pkg + GFXRES AQUA_MASK_PMAP_ANIM aquhelix.ani + STRTAB AQUA_STRTAB aquhelix.txt +PACKAGE BURV_BCS_PACKAGE starcon.pkg + GFXRES BURV_BCS_MASK_PMAP_ANIM drutrans.ani + STRTAB BURV_BCS_STRTAB drutrans.txt +PACKAGE TAALO_DEVICE_PACKAGE starcon.pkg + GFXRES TAALO_DEVICE_MASK_PMAP_ANIM taadevic.ani + STRTAB TAALO_DEVICE_STRTAB taadevic.txt +PACKAGE SUN_DEVICE_PACKAGE starcon.pkg + GFXRES SUN_DEVICE_MASK_PMAP_ANIM sundevic.ani + STRTAB SUN_DEVICE_STRTAB sundevic.txt +PACKAGE VAULT_PACKAGE starcon.pkg + GFXRES VAULT_MASK_PMAP_ANIM syrvault.ani + STRTAB VAULT_STRTAB syrvault.txt +PACKAGE WRECK_PACKAGE starcon.pkg + GFXRES WRECK_MASK_PMAP_ANIM urqwreck.ani + STRTAB WRECK_STRTAB urqwreck.txt +PACKAGE BOMB_PACKAGE starcon.pkg + GFXRES BOMB_MASK_PMAP_ANIM utwbomb.ani + STRTAB BOMB_STRTAB utwbomb.txt +PACKAGE BEAST_PACKAGE starcon.pkg + STRTAB BEAST_STRTAB vuxbeast.txt +PACKAGE EGG_CASE_PACKAGE starcon.pkg + GFXRES EGG_CASE_MASK_PMAP_ANIM eggcase.ani + STRTAB EGG_CASE_STRTAB eggcase.txt +PACKAGE SPAPLUTO_PACKAGE starcon.pkg + GFXRES SPAPLUTO_MASK_PMAP_ANIM spapluto.ani + STRTAB SPAPLUTO_STRTAB spapluto.txt +PACKAGE BURV_RUINS_PACKAGE starcon.pkg + STRTAB BURV_RUINS_STRTAB burruins.txt +PACKAGE ANDROSYNTH_RUINS_PACKAGE starcon.pkg + STRTAB ANDROSYNTH_RUINS_STRTAB andruins.txt +PACKAGE DRUUGE_RUINS_PACKAGE starcon.pkg + STRTAB DRUUGE_RUINS_STRTAB sphere.txt +PACKAGE PKUNK_RUINS_PACKAGE starcon.pkg + STRTAB PKUNK_RUINS_STRTAB spindle.txt +PACKAGE RACE_RUINS_PACKAGE starcon.pkg + GFXRES RUINS_MASK_PMAP_ANIM ruins.ani +PACKAGE RACE_RUINS_TEXT_PACKAGE starcon.pkg + STRTAB RUINS_STRTAB ruins.txt +PACKAGE UMGAH_BCS_PACKAGE starcon.pkg + GFXRES UMGAH_BCS_MASK_PMAP_ANIM umgtrans.ani + STRTAB UMGAH_BCS_STRTAB umgtrans.txt + +PACKAGE IP_MUSIC_PACKAGE starcon.pkg + MUSICRES IP_MUSIC space.mod +PACKAGE ORBIT_MUSIC_PACKAGE starcon.pkg + MUSICRES ORBIT1_MUSIC orbit1.mod + MUSICRES ORBIT2_MUSIC orbit2.mod + MUSICRES ORBIT3_MUSIC orbit3.mod + MUSICRES ORBIT4_MUSIC orbit4.mod + MUSICRES ORBIT5_MUSIC orbit5.mod + +PATH melee +PACKAGE MELEE_BGROUND_PACKAGE starcon.pkg + GFXRES MELEE_SCREEN_PMAP_ANIM melebkgd.ani +PACKAGE MELEE_PICK_PACKAGE starcon.pkg + GFXRES MELEE_PICK_MASK_PMAP_ANIM melee.ani + +PATH lbm +PACKAGE SC2_SEGUE_PACKAGE starcon.pkg + GFXRES SEGUE_PMAP_ANIM segue.ani + MUSICRES REDALERT_MUSIC redalert.mod +PACKAGE SC2_PICK_PACKAGE starcon.pkg + GFXRES SC2_PICK_PMAP_ANIM pickship.ani + +PATH . +PACKAGE ARILOU_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX ARILOU_CONVERSATION arilou.con +PACKAGE CHMMR_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX CHMMR_CONVERSATION chmmr.con +PACKAGE COMMANDER_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX COMMANDER_CONVERSATION comandr.con +PACKAGE ORZ_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX ORZ_CONVERSATION orz.con +PACKAGE PKUNK_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX PKUNK_CONVERSATION pkunk.con +PACKAGE SHOFIXTI_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SHOFIXTI_CONVERSATION shofixt.con +PACKAGE SPATHI_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SPATHI_CONVERSATION spathi.con +PACKAGE SUPOX_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SUPOX_CONVERSATION supox.con +PACKAGE THRADD_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX THRADD_CONVERSATION thradd.con +PACKAGE UTWIG_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX UTWIG_CONVERSATION utwig.con +PACKAGE VUX_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX VUX_CONVERSATION vux.con +PACKAGE YEHAT_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX YEHAT_CONVERSATION yehat.con +PACKAGE MELNORME_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX MELNORME_CONVERSATION melnorm.con +PACKAGE DRUUGE_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX DRUUGE_CONVERSATION druuge.con +PACKAGE ILWRATH_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX ILWRATH_CONVERSATION ilwrath.con +PACKAGE MYCON_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX MYCON_CONVERSATION mycon.con +PACKAGE SLYLANDRO_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SLYLANDRO_CONVERSATION slyland.con +PACKAGE UMGAH_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX UMGAH_CONVERSATION umgah.con +PACKAGE URQUAN_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX URQUAN_CONVERSATION urquan.con +PACKAGE ZOQFOTPIK_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX ZOQFOTPIK_CONVERSATION zoqfot.con +PACKAGE SYREEN_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SYREEN_CONVERSATION syreen.con +PACKAGE BLACKURQ_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX BLACKURQ_CONVERSATION blackur.con +PACKAGE TALKING_PET_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX TALKING_PET_CONVERSATION talkpet.con +PACKAGE SLYLANDRO_HOME_CONVERSATION_PACKAGE starcon.pkg + RES_INDEX SLYLANDRO_HOME_CONVERSATION slyhome.con + +PATH lbm +PACKAGE PLAYER_CONVERSATION_PACKAGE starcon.pkg + FONTRES PLAYER_FONT player.fon + +PATH . +PACKAGE SIS_PACKAGE starcon.pkg + RES_INDEX SIS_RES_INDEX sis.dat +PACKAGE SAMATRA_PACKAGE starcon.pkg + RES_INDEX SAMATRA_RES_INDEX lastbat.sc2 +PACKAGE URQUAN_PROBE_PACKAGE starcon.pkg + RES_INDEX PROBE_RES_INDEX probe.sc2 + +PATH lbm +PACKAGE RESTART_PACKAGE starcon.pkg + GFXRES RESTART_PMAP_ANIM newgame.ani + +PACKAGE MODULE_PACKAGE starcon.pkg + GFXRES MODULES_PMAP_ANIM modules.ani + +PACKAGE OUTFIT_PACKAGE starcon.pkg + GFXRES SISMODS_MASK_PMAP_ANIM sismods.ani + GFXRES OUTFIT_PMAP_ANIM outfit.ani +PACKAGE OUTFIT_MUSIC_PACKAGE starcon.pkg + MUSICRES OUTFIT_MUSIC outfit.mod + +PACKAGE BLUEPRINT_PACKAGE starcon.pkg + GFXRES SISBLU_MASK_ANIM sisblu.ani + GFXRES SHIPYARD_PMAP_ANIM shipyard.ani +PACKAGE SHIPYARD_MUSIC_PACKAGE starcon.pkg + MUSICRES SHIPYARD_MUSIC shipyard.mod + +PACKAGE STARBASE_PACKAGE starcon.pkg + MUSICRES STARBASE_MUSIC starbase.mod + GFXRES STARBASE_ANIM starbase.ani + +PACKAGE SAMATRA_BATTLE_PACKAGE starcon.pkg + GFXRES SAMATRA_BIG_MASK_PMAP_ANIM sam__big.ani + +PACKAGE SHIELDED_BATTLE_PACKAGE starcon.pkg + GFXRES SHIELDED_BIG_MASK_PMAP_ANIM shie_big.ani + GFXRES SHIELDED_MED_MASK_PMAP_ANIM shie_med.ani + GFXRES SHIELDED_SML_MASK_PMAP_ANIM shie_sml.ani + +PACKAGE PLANET00_PACKAGE starcon.pkg + GFXRES PLANET00_BIG_MASK_PMAP_ANIM ool__big.ani + GFXRES PLANET00_MED_MASK_PMAP_ANIM ool__med.ani + GFXRES PLANET00_SML_MASK_PMAP_ANIM ool__sml.ani +PACKAGE PLANET01_PACKAGE starcon.pkg + GFXRES PLANET01_BIG_MASK_PMAP_ANIM ytt__big.ani + GFXRES PLANET01_MED_MASK_PMAP_ANIM ytt__med.ani + GFXRES PLANET01_SML_MASK_PMAP_ANIM ytt__sml.ani +PACKAGE PLANET02_PACKAGE starcon.pkg + GFXRES PLANET02_BIG_MASK_PMAP_ANIM deg__big.ani + GFXRES PLANET02_MED_MASK_PMAP_ANIM deg__med.ani + GFXRES PLANET02_SML_MASK_PMAP_ANIM deg__sml.ani +PACKAGE PLANET03_PACKAGE starcon.pkg + GFXRES PLANET03_BIG_MASK_PMAP_ANIM lan__big.ani + GFXRES PLANET03_MED_MASK_PMAP_ANIM lan__med.ani + GFXRES PLANET03_SML_MASK_PMAP_ANIM lan__sml.ani +PACKAGE PLANET04_PACKAGE starcon.pkg + GFXRES PLANET04_BIG_MASK_PMAP_ANIM tre__big.ani + GFXRES PLANET04_MED_MASK_PMAP_ANIM tre__med.ani + GFXRES PLANET04_SML_MASK_PMAP_ANIM tre__sml.ani +PACKAGE PLANET05_PACKAGE starcon.pkg + GFXRES PLANET05_BIG_MASK_PMAP_ANIM ure__big.ani + GFXRES PLANET05_MED_MASK_PMAP_ANIM ure__med.ani + GFXRES PLANET05_SML_MASK_PMAP_ANIM ure__sml.ani +PACKAGE PLANET06_PACKAGE starcon.pkg + GFXRES PLANET06_BIG_MASK_PMAP_ANIM mtl__big.ani + GFXRES PLANET06_MED_MASK_PMAP_ANIM mtl__med.ani + GFXRES PLANET06_SML_MASK_PMAP_ANIM mtl__sml.ani +PACKAGE PLANET07_PACKAGE starcon.pkg + GFXRES PLANET07_BIG_MASK_PMAP_ANIM rad__big.ani + GFXRES PLANET07_MED_MASK_PMAP_ANIM rad__med.ani + GFXRES PLANET07_SML_MASK_PMAP_ANIM rad__sml.ani +PACKAGE PLANET08_PACKAGE starcon.pkg + GFXRES PLANET08_BIG_MASK_PMAP_ANIM opa__big.ani + GFXRES PLANET08_MED_MASK_PMAP_ANIM opa__med.ani + GFXRES PLANET08_SML_MASK_PMAP_ANIM opa__sml.ani +PACKAGE PLANET09_PACKAGE starcon.pkg + GFXRES PLANET09_BIG_MASK_PMAP_ANIM cya__big.ani + GFXRES PLANET09_MED_MASK_PMAP_ANIM cya__med.ani + GFXRES PLANET09_SML_MASK_PMAP_ANIM cya__sml.ani +PACKAGE PLANET10_PACKAGE starcon.pkg + GFXRES PLANET10_BIG_MASK_PMAP_ANIM aci__big.ani + GFXRES PLANET10_MED_MASK_PMAP_ANIM aci__med.ani + GFXRES PLANET10_SML_MASK_PMAP_ANIM aci__sml.ani +PACKAGE PLANET11_PACKAGE starcon.pkg + GFXRES PLANET11_BIG_MASK_PMAP_ANIM alk__big.ani + GFXRES PLANET11_MED_MASK_PMAP_ANIM alk__med.ani + GFXRES PLANET11_SML_MASK_PMAP_ANIM alk__sml.ani +PACKAGE PLANET12_PACKAGE starcon.pkg + GFXRES PLANET12_BIG_MASK_PMAP_ANIM hal__big.ani + GFXRES PLANET12_MED_MASK_PMAP_ANIM hal__med.ani + GFXRES PLANET12_SML_MASK_PMAP_ANIM hal__sml.ani +PACKAGE PLANET13_PACKAGE starcon.pkg + GFXRES PLANET13_BIG_MASK_PMAP_ANIM gre__big.ani + GFXRES PLANET13_MED_MASK_PMAP_ANIM gre__med.ani + GFXRES PLANET13_SML_MASK_PMAP_ANIM gre__sml.ani +PACKAGE PLANET14_PACKAGE starcon.pkg + GFXRES PLANET14_BIG_MASK_PMAP_ANIM cop__big.ani + GFXRES PLANET14_MED_MASK_PMAP_ANIM cop__med.ani + GFXRES PLANET14_SML_MASK_PMAP_ANIM cop__sml.ani +PACKAGE PLANET15_PACKAGE starcon.pkg + GFXRES PLANET15_BIG_MASK_PMAP_ANIM car__big.ani + GFXRES PLANET15_MED_MASK_PMAP_ANIM car__med.ani + GFXRES PLANET15_SML_MASK_PMAP_ANIM car__sml.ani +PACKAGE PLANET16_PACKAGE starcon.pkg + GFXRES PLANET16_BIG_MASK_PMAP_ANIM ult__big.ani + GFXRES PLANET16_MED_MASK_PMAP_ANIM ult__med.ani + GFXRES PLANET16_SML_MASK_PMAP_ANIM ult__sml.ani +PACKAGE PLANET17_PACKAGE starcon.pkg + GFXRES PLANET17_BIG_MASK_PMAP_ANIM nob__big.ani + GFXRES PLANET17_MED_MASK_PMAP_ANIM nob__med.ani + GFXRES PLANET17_SML_MASK_PMAP_ANIM nob__sml.ani +PACKAGE PLANET18_PACKAGE starcon.pkg + GFXRES PLANET18_BIG_MASK_PMAP_ANIM azu__big.ani + GFXRES PLANET18_MED_MASK_PMAP_ANIM azu__med.ani + GFXRES PLANET18_SML_MASK_PMAP_ANIM azu__sml.ani +PACKAGE PLANET19_PACKAGE starcon.pkg + GFXRES PLANET19_BIG_MASK_PMAP_ANIM cho__big.ani + GFXRES PLANET19_MED_MASK_PMAP_ANIM cho__med.ani + GFXRES PLANET19_SML_MASK_PMAP_ANIM cho__sml.ani +PACKAGE PLANET20_PACKAGE starcon.pkg + GFXRES PLANET20_BIG_MASK_PMAP_ANIM pur__big.ani + GFXRES PLANET20_MED_MASK_PMAP_ANIM pur__med.ani + GFXRES PLANET20_SML_MASK_PMAP_ANIM pur__sml.ani +PACKAGE PLANET21_PACKAGE starcon.pkg + GFXRES PLANET21_BIG_MASK_PMAP_ANIM sup__big.ani + GFXRES PLANET21_MED_MASK_PMAP_ANIM sup__med.ani + GFXRES PLANET21_SML_MASK_PMAP_ANIM sup__sml.ani +PACKAGE PLANET22_PACKAGE starcon.pkg + GFXRES PLANET22_BIG_MASK_PMAP_ANIM pel__big.ani + GFXRES PLANET22_MED_MASK_PMAP_ANIM pel__med.ani + GFXRES PLANET22_SML_MASK_PMAP_ANIM pel__sml.ani +PACKAGE PLANET23_PACKAGE starcon.pkg + GFXRES PLANET23_BIG_MASK_PMAP_ANIM dus__big.ani + GFXRES PLANET23_MED_MASK_PMAP_ANIM dus__med.ani + GFXRES PLANET23_SML_MASK_PMAP_ANIM dus__sml.ani +PACKAGE PLANET24_PACKAGE starcon.pkg + GFXRES PLANET24_BIG_MASK_PMAP_ANIM mar__big.ani + GFXRES PLANET24_MED_MASK_PMAP_ANIM mar__med.ani + GFXRES PLANET24_SML_MASK_PMAP_ANIM mar__sml.ani +PACKAGE PLANET25_PACKAGE starcon.pkg + GFXRES PLANET25_BIG_MASK_PMAP_ANIM cim__big.ani + GFXRES PLANET25_MED_MASK_PMAP_ANIM cim__med.ani + GFXRES PLANET25_SML_MASK_PMAP_ANIM cim__sml.ani +PACKAGE PLANET26_PACKAGE starcon.pkg + GFXRES PLANET26_BIG_MASK_PMAP_ANIM inf__big.ani + GFXRES PLANET26_MED_MASK_PMAP_ANIM inf__med.ani + GFXRES PLANET26_SML_MASK_PMAP_ANIM inf__sml.ani +PACKAGE PLANET27_PACKAGE starcon.pkg + GFXRES PLANET27_BIG_MASK_PMAP_ANIM sel__big.ani + GFXRES PLANET27_MED_MASK_PMAP_ANIM sel__med.ani + GFXRES PLANET27_SML_MASK_PMAP_ANIM sel__sml.ani +PACKAGE PLANET28_PACKAGE starcon.pkg + GFXRES PLANET28_BIG_MASK_PMAP_ANIM aur__big.ani + GFXRES PLANET28_MED_MASK_PMAP_ANIM aur__med.ani + GFXRES PLANET28_SML_MASK_PMAP_ANIM aur__sml.ani +PACKAGE PLANET29_PACKAGE starcon.pkg + GFXRES PLANET29_BIG_MASK_PMAP_ANIM flu__big.ani + GFXRES PLANET29_MED_MASK_PMAP_ANIM flu__med.ani + GFXRES PLANET29_SML_MASK_PMAP_ANIM flu__sml.ani +PACKAGE PLANET30_PACKAGE starcon.pkg + GFXRES PLANET30_BIG_MASK_PMAP_ANIM ult__big.ani + GFXRES PLANET30_MED_MASK_PMAP_ANIM ult__med.ani + GFXRES PLANET30_SML_MASK_PMAP_ANIM ult__sml.ani +PACKAGE PLANET31_PACKAGE starcon.pkg + GFXRES PLANET31_BIG_MASK_PMAP_ANIM plu__big.ani + GFXRES PLANET31_MED_MASK_PMAP_ANIM plu__med.ani + GFXRES PLANET31_SML_MASK_PMAP_ANIM plu__sml.ani +PACKAGE PLANET32_PACKAGE starcon.pkg + GFXRES PLANET32_BIG_MASK_PMAP_ANIM rai__big.ani + GFXRES PLANET32_MED_MASK_PMAP_ANIM rai__med.ani + GFXRES PLANET32_SML_MASK_PMAP_ANIM rai__sml.ani +PACKAGE PLANET33_PACKAGE starcon.pkg + GFXRES PLANET33_BIG_MASK_PMAP_ANIM cra__big.ani + GFXRES PLANET33_MED_MASK_PMAP_ANIM cra__med.ani + GFXRES PLANET33_SML_MASK_PMAP_ANIM cra__sml.ani +PACKAGE PLANET34_PACKAGE starcon.pkg + GFXRES PLANET34_BIG_MASK_PMAP_ANIM sap__big.ani + GFXRES PLANET34_MED_MASK_PMAP_ANIM sap__med.ani + GFXRES PLANET34_SML_MASK_PMAP_ANIM sap__sml.ani +PACKAGE PLANET35_PACKAGE starcon.pkg + GFXRES PLANET35_BIG_MASK_PMAP_ANIM org__big.ani + GFXRES PLANET35_MED_MASK_PMAP_ANIM org__med.ani + GFXRES PLANET35_SML_MASK_PMAP_ANIM org__sml.ani +PACKAGE PLANET36_PACKAGE starcon.pkg + GFXRES PLANET36_BIG_MASK_PMAP_ANIM xen__big.ani + GFXRES PLANET36_MED_MASK_PMAP_ANIM xen__med.ani + GFXRES PLANET36_SML_MASK_PMAP_ANIM xen__sml.ani +PACKAGE PLANET37_PACKAGE starcon.pkg + GFXRES PLANET37_BIG_MASK_PMAP_ANIM red__big.ani + GFXRES PLANET37_MED_MASK_PMAP_ANIM red__med.ani + GFXRES PLANET37_SML_MASK_PMAP_ANIM red__sml.ani +PACKAGE PLANET38_PACKAGE starcon.pkg + GFXRES PLANET38_BIG_MASK_PMAP_ANIM pri__big.ani + GFXRES PLANET38_MED_MASK_PMAP_ANIM pri__med.ani + GFXRES PLANET38_SML_MASK_PMAP_ANIM pri__sml.ani +PACKAGE PLANET39_PACKAGE starcon.pkg + GFXRES PLANET39_BIG_MASK_PMAP_ANIM eme__big.ani + GFXRES PLANET39_MED_MASK_PMAP_ANIM eme__med.ani + GFXRES PLANET39_SML_MASK_PMAP_ANIM eme__sml.ani +PACKAGE PLANET40_PACKAGE starcon.pkg + GFXRES PLANET40_BIG_MASK_PMAP_ANIM chl__big.ani + GFXRES PLANET40_MED_MASK_PMAP_ANIM chl__med.ani + GFXRES PLANET40_SML_MASK_PMAP_ANIM chl__sml.ani +PACKAGE PLANET41_PACKAGE starcon.pkg + GFXRES PLANET41_BIG_MASK_PMAP_ANIM mgn__big.ani + GFXRES PLANET41_MED_MASK_PMAP_ANIM mgn__med.ani + GFXRES PLANET41_SML_MASK_PMAP_ANIM mgn__sml.ani +PACKAGE PLANET42_PACKAGE starcon.pkg + GFXRES PLANET42_BIG_MASK_PMAP_ANIM wat__big.ani + GFXRES PLANET42_MED_MASK_PMAP_ANIM wat__med.ani + GFXRES PLANET42_SML_MASK_PMAP_ANIM wat__sml.ani +PACKAGE PLANET43_PACKAGE starcon.pkg + GFXRES PLANET43_BIG_MASK_PMAP_ANIM tel__big.ani + GFXRES PLANET43_MED_MASK_PMAP_ANIM tel__med.ani + GFXRES PLANET43_SML_MASK_PMAP_ANIM tel__sml.ani +PACKAGE PLANET44_PACKAGE starcon.pkg + GFXRES PLANET44_BIG_MASK_PMAP_ANIM hyd__big.ani + GFXRES PLANET44_MED_MASK_PMAP_ANIM hyd__med.ani + GFXRES PLANET44_SML_MASK_PMAP_ANIM hyd__sml.ani +PACKAGE PLANET45_PACKAGE starcon.pkg + GFXRES PLANET45_BIG_MASK_PMAP_ANIM iod__big.ani + GFXRES PLANET45_MED_MASK_PMAP_ANIM iod__med.ani + GFXRES PLANET45_SML_MASK_PMAP_ANIM iod__sml.ani +PACKAGE PLANET46_PACKAGE starcon.pkg + GFXRES PLANET46_BIG_MASK_PMAP_ANIM vin__big.ani + GFXRES PLANET46_MED_MASK_PMAP_ANIM vin__med.ani + GFXRES PLANET46_SML_MASK_PMAP_ANIM vin__sml.ani +PACKAGE PLANET47_PACKAGE starcon.pkg + GFXRES PLANET47_BIG_MASK_PMAP_ANIM rub__big.ani + GFXRES PLANET47_MED_MASK_PMAP_ANIM rub__med.ani + GFXRES PLANET47_SML_MASK_PMAP_ANIM rub__sml.ani +PACKAGE PLANET48_PACKAGE starcon.pkg + GFXRES PLANET48_BIG_MASK_PMAP_ANIM mgm__big.ani + GFXRES PLANET48_MED_MASK_PMAP_ANIM mgm__med.ani + GFXRES PLANET48_SML_MASK_PMAP_ANIM mgm__sml.ani +PACKAGE PLANET49_PACKAGE starcon.pkg + GFXRES PLANET49_BIG_MASK_PMAP_ANIM cri__big.ani + GFXRES PLANET49_MED_MASK_PMAP_ANIM cri__med.ani + GFXRES PLANET49_SML_MASK_PMAP_ANIM cri__sml.ani +PACKAGE PLANET50_PACKAGE starcon.pkg + GFXRES PLANET50_BIG_MASK_PMAP_ANIM blg__big.ani + GFXRES PLANET50_MED_MASK_PMAP_ANIM blg__med.ani + GFXRES PLANET50_SML_MASK_PMAP_ANIM blg__sml.ani +PACKAGE PLANET51_PACKAGE starcon.pkg + GFXRES PLANET51_BIG_MASK_PMAP_ANIM cyg__big.ani + GFXRES PLANET51_MED_MASK_PMAP_ANIM cyg__med.ani + GFXRES PLANET51_SML_MASK_PMAP_ANIM cyg__sml.ani +PACKAGE PLANET52_PACKAGE starcon.pkg + GFXRES PLANET52_BIG_MASK_PMAP_ANIM gng__big.ani + GFXRES PLANET52_MED_MASK_PMAP_ANIM gng__med.ani + GFXRES PLANET52_SML_MASK_PMAP_ANIM gng__sml.ani +PACKAGE PLANET53_PACKAGE starcon.pkg + GFXRES PLANET53_BIG_MASK_PMAP_ANIM gyg__big.ani + GFXRES PLANET53_MED_MASK_PMAP_ANIM gyg__med.ani + GFXRES PLANET53_SML_MASK_PMAP_ANIM gyg__sml.ani +PACKAGE PLANET54_PACKAGE starcon.pkg + GFXRES PLANET54_BIG_MASK_PMAP_ANIM org__big.ani + GFXRES PLANET54_MED_MASK_PMAP_ANIM org__med.ani + GFXRES PLANET54_SML_MASK_PMAP_ANIM org__sml.ani +PACKAGE PLANET55_PACKAGE starcon.pkg + GFXRES PLANET55_BIG_MASK_PMAP_ANIM pug__big.ani + GFXRES PLANET55_MED_MASK_PMAP_ANIM pug__med.ani + GFXRES PLANET55_SML_MASK_PMAP_ANIM pug__sml.ani +PACKAGE PLANET56_PACKAGE starcon.pkg + GFXRES PLANET56_BIG_MASK_PMAP_ANIM reg__big.ani + GFXRES PLANET56_MED_MASK_PMAP_ANIM reg__med.ani + GFXRES PLANET56_SML_MASK_PMAP_ANIM reg__sml.ani +PACKAGE PLANET57_PACKAGE starcon.pkg + GFXRES PLANET57_BIG_MASK_PMAP_ANIM vig__big.ani + GFXRES PLANET57_MED_MASK_PMAP_ANIM vig__med.ani + GFXRES PLANET57_SML_MASK_PMAP_ANIM vig__sml.ani +PACKAGE PLANET58_PACKAGE starcon.pkg + GFXRES PLANET58_BIG_MASK_PMAP_ANIM yeg__big.ani + GFXRES PLANET58_MED_MASK_PMAP_ANIM yeg__med.ani + GFXRES PLANET58_SML_MASK_PMAP_ANIM yeg__sml.ani + +PACKAGE BATTLE_MUSIC_PACKAGE starcon.pkg + MUSICRES BATTLE_MUSIC battle.mod + +PACKAGE CREDIT00_PACKAGE starcon.pkg + GFXRES CREDIT00_ANIM credit00.ani +PACKAGE CREDIT01_PACKAGE starcon.pkg + GFXRES CREDIT01_ANIM credit01.ani +PACKAGE CREDIT02_PACKAGE starcon.pkg + GFXRES CREDIT02_ANIM credit02.ani +PACKAGE CREDIT03_PACKAGE starcon.pkg + GFXRES CREDIT03_ANIM credit03.ani +PACKAGE CREDIT04_PACKAGE starcon.pkg + GFXRES CREDIT04_ANIM credit04.ani +PACKAGE CREDIT05_PACKAGE starcon.pkg + GFXRES CREDIT05_ANIM credit05.ani +PACKAGE CREDIT06_PACKAGE starcon.pkg + GFXRES CREDIT06_ANIM credit06.ani +PACKAGE CREDIT07_PACKAGE starcon.pkg + GFXRES CREDIT07_ANIM credit07.ani +PACKAGE CREDIT08_PACKAGE starcon.pkg + GFXRES CREDIT08_ANIM credit08.ani +PACKAGE CREDIT09_PACKAGE starcon.pkg + GFXRES CREDIT09_ANIM credit09.ani +PACKAGE CREDIT10_PACKAGE starcon.pkg + GFXRES CREDIT10_ANIM credit10.ani +PACKAGE CREDIT11_PACKAGE starcon.pkg + GFXRES CREDIT11_ANIM credit11.ani +PACKAGE CREDIT12_PACKAGE starcon.pkg + GFXRES CREDIT12_ANIM credit12.ani +PACKAGE CREDIT13_PACKAGE starcon.pkg + GFXRES CREDIT13_ANIM credit13.ani +PACKAGE CREDIT14_PACKAGE starcon.pkg + GFXRES CREDIT14_ANIM credit14.ani +PACKAGE CREDIT15_PACKAGE starcon.pkg + GFXRES CREDIT15_ANIM credit15.ani +PACKAGE CREDIT16_PACKAGE starcon.pkg + GFXRES CREDIT16_ANIM credit16.ani +PACKAGE CREDIT17_PACKAGE starcon.pkg + GFXRES CREDIT17_ANIM credit17.ani +PACKAGE CREDIT18_PACKAGE starcon.pkg + GFXRES CREDIT18_ANIM credit18.ani +PACKAGE CREDIT19_PACKAGE starcon.pkg + GFXRES CREDIT19_ANIM credit19.ani +PACKAGE CREDIT_MUSIC_PACKAGE starcon.pkg + MUSICRES CREDITS_MUSIC credits.mod + diff --git a/sc2/src/sc2code/star3do.typ b/sc2/src/sc2code/star3do.typ new file mode 100644 index 000000000..5da2f5a74 --- /dev/null +++ b/sc2/src/sc2code/star3do.typ @@ -0,0 +1,9 @@ +TYPE KEY_CONFIG +TYPE GFXRES +TYPE FONTRES +TYPE STRTAB +TYPE SNDRES +TYPE MUSICRES + +TYPE RES_INDEX +TYPE CODE diff --git a/sc2/src/sc2code/starbase.c b/sc2/src/sc2code/starbase.c new file mode 100644 index 000000000..4463c42c0 --- /dev/null +++ b/sc2/src/sc2code/starbase.c @@ -0,0 +1,568 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "SDL_wrapper.h" + +PMENU_STATE pMenuState; + +static void +DrawBaseStateStrings (STARBASE_STATE OldState, STARBASE_STATE NewState) +{ + TEXT t; + //STRING locString; + + SetContext (ScreenContext); + SetContextFont (StarConFont); + SetContextForeGroundColor (BLACK_COLOR); + + t.baseline.x = 73 - 4 + SAFE_X; + t.align = ALIGN_CENTER; + + if (OldState == (STARBASE_STATE)~0) + { + t.baseline.y = 106 + 28 + (SAFE_Y + 4); + for (OldState = TALK_COMMANDER; OldState < DEPART_BASE; ++OldState) + { + if (OldState != NewState) + { + t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + OldState); + t.CharCount = (COUNT)~0; + DrawText (&t); + } + t.baseline.y += (23 - 4); + } + } + + t.baseline.y = 106 + 28 + (SAFE_Y + 4) + ((23 - 4) * OldState); + t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + OldState); + t.CharCount = (COUNT)~0; + DrawText (&t); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E)); + t.baseline.y = 106 + 28 + (SAFE_Y + 4) + ((23 - 4) * NewState); + t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + NewState); + t.CharCount = (COUNT)~0; + DrawText (&t); +} + +void +DrawShipPiece (PMENU_STATE pMS, COUNT which_piece, COUNT which_slot, + BOOLEAN DrawBluePrint) +{ + COLOR OldColor; + RECT r; + STAMP Side, Top; + SBYTE RepairSlot; + + RepairSlot = 0; + switch (which_piece) + { + case FUSION_THRUSTER: + case EMPTY_SLOT + 0: + Side.origin.x = DRIVE_SIDE_X; + Side.origin.y = DRIVE_SIDE_Y; + Top.origin.x = DRIVE_TOP_X; + Top.origin.y = DRIVE_TOP_Y; + break; + case TURNING_JETS: + case EMPTY_SLOT + 1: + Side.origin.x = JET_SIDE_X; + Side.origin.y = JET_SIDE_Y; + Top.origin.x = JET_TOP_X; + Top.origin.y = JET_TOP_Y; + break; + default: + if (which_piece < EMPTY_SLOT + 2) + { + RepairSlot = 1; + if (which_piece < EMPTY_SLOT + && (which_slot == 0 + || GLOBAL_SIS (ModuleSlots[ + which_slot - 1 + ]) < EMPTY_SLOT)) + ++RepairSlot; + } + else if (!DrawBluePrint) + { + if (which_slot == 0 || which_slot >= NUM_MODULE_SLOTS - 3) + ++which_piece; + + if (which_slot < NUM_MODULE_SLOTS - 1 + && GLOBAL_SIS (ModuleSlots[ + which_slot + 1 + ]) < EMPTY_SLOT) + { + RepairSlot = -1; + if (which_piece == EMPTY_SLOT + 3 + || which_slot + 1 == NUM_MODULE_SLOTS - 3) + --RepairSlot; + } + } + Side.origin.x = MODULE_SIDE_X; + Side.origin.y = MODULE_SIDE_Y; + Top.origin.x = MODULE_TOP_X; + Top.origin.y = MODULE_TOP_Y; + break; + } + + Side.origin.x += which_slot * SHIP_PIECE_OFFSET; + if (RepairSlot < 0) + { + Side.frame = SetAbsFrameIndex (pMS->ModuleFrame, + ((NUM_MODULES - 1) + (6 - 2)) + (NUM_MODULES + 6) + - (RepairSlot + 1)); + DrawStamp (&Side); + } + else if (RepairSlot) + { + r.corner = Side.origin; + r.extent.width = SHIP_PIECE_OFFSET; + r.extent.height = 1; + OldColor = SetContextForeGroundColor (BLACK_COLOR); + DrawFilledRectangle (&r); + r.corner.y += 23 - 1; + DrawFilledRectangle (&r); + + r.extent.width = 1; + r.extent.height = 8; + if (RepairSlot == 2) + { + r.corner = Side.origin; + DrawFilledRectangle (&r); + r.corner.y += 15; + DrawFilledRectangle (&r); + } + if (which_slot < (NUM_MODULE_SLOTS - 1)) + { + r.corner = Side.origin; + r.corner.x += SHIP_PIECE_OFFSET; + DrawFilledRectangle (&r); + r.corner.y += 15; + DrawFilledRectangle (&r); + } + } + + if (DrawBluePrint) + { + if (RepairSlot) + SetContextForeGroundColor (OldColor); + Side.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece - 1); + DrawFilledStamp (&Side); + } + else + { + Top.origin.x += which_slot * SHIP_PIECE_OFFSET; + if (RepairSlot < 0) + { + Top.frame = SetRelFrameIndex (Side.frame, -((NUM_MODULES - 1) + 6)); + DrawStamp (&Top); + } + else if (RepairSlot) + { + r.corner = Top.origin; + r.extent.width = SHIP_PIECE_OFFSET; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.y += 32 - 1; + DrawFilledRectangle (&r); + + r.extent.width = 1; + r.extent.height = 12; + if (RepairSlot == 2) + { + r.corner = Top.origin; + DrawFilledRectangle (&r); + r.corner.y += 20; + DrawFilledRectangle (&r); + } + RepairSlot = (which_slot < NUM_MODULE_SLOTS - 1); + if (RepairSlot) + { + r.corner = Top.origin; + r.corner.x += SHIP_PIECE_OFFSET; + DrawFilledRectangle (&r); + r.corner.y += 20; + DrawFilledRectangle (&r); + } + } + + Top.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece); + DrawStamp (&Top); + + Side.frame = SetRelFrameIndex (Top.frame, (NUM_MODULES - 1) + 6); + DrawStamp (&Side); + + if (which_slot == 1 && which_piece == EMPTY_SLOT + 2) + { + STAMP s; + + s.origin = Top.origin; + s.origin.x -= SHIP_PIECE_OFFSET; + s.frame = SetAbsFrameIndex (pMS->ModuleFrame, NUM_MODULES + 5); + DrawStamp (&s); + s.origin = Side.origin; + s.origin.x -= SHIP_PIECE_OFFSET; + s.frame = SetRelFrameIndex (s.frame, (NUM_MODULES - 1) + 6); + DrawStamp (&s); + } + + if (RepairSlot) + { + Top.origin.x += SHIP_PIECE_OFFSET; + Side.origin.x += SHIP_PIECE_OFFSET; + which_piece = GLOBAL_SIS (ModuleSlots[++which_slot]); + if (which_piece == EMPTY_SLOT + 2 + && which_slot >= NUM_MODULE_SLOTS - 3) + ++which_piece; + + Top.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece); + DrawStamp (&Top); + + Side.frame = SetRelFrameIndex (Top.frame, (NUM_MODULES - 1) + 6); + DrawStamp (&Side); + } + } +} + +int rotate_starbase(void* blah) +{ + DWORD TimeIn; + STAMP s; + + s.origin.x = s.origin.y = 0; +s.origin.x = SAFE_X, s.origin.y = SAFE_Y + 4; + s.frame = IncFrameIndex (pMenuState->CurFrame); + TimeIn = GetTimeCounter (); + for (;;) + { + //CONTEXT OldContext; + + SetSemaphore (&GraphicsSem); + DrawStamp (&s); + s.frame = IncFrameIndex (s.frame); + if (s.frame == pMenuState->CurFrame) + s.frame = IncFrameIndex (s.frame); + ClearSemaphore (&GraphicsSem); + + TimeIn = SleepTask (TimeIn + (ONE_SECOND / 20)); + } + + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +BOOLEAN +DoStarBase (INPUT_STATE InputState, PMENU_STATE pMS) +{ + if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + { + pMS->CurState = DEPART_BASE; + goto ExitStarBase; + } + + if (!pMS->Initialized) + { + STAMP s; + + LastActivity &= ~CHECK_LOAD; + pMS->InputFunc = DoStarBase; + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + + if (pMS->hMusic) + { + StopMusic (); + DestroyMusic (pMS->hMusic); + pMS->hMusic = 0; + } + + if (pMS->flash_task) + { + DeleteTask (pMS->flash_task); + pMS->flash_task = 0; + } + + pMS->Initialized = TRUE; + SetContext (ScreenContext); + SetContextDrawState (DEST_PIXMAP | DRAW_REPLACE); + + ClearSemaphore (&GraphicsSem); + + s.origin.x = s.origin.y = 0; +s.origin.x = SAFE_X, s.origin.y = SAFE_Y + 4; + s.frame = CaptureDrawable (LoadGraphic (STARBASE_ANIM)); + pMS->CurFrame = s.frame; + pMS->hMusic = LoadMusicInstance (STARBASE_MUSIC); + + SetSemaphore (&GraphicsSem); + BatchGraphics (); + SetContextBackGroundColor (BLACK_COLOR); + ClearDrawable (); + DrawStamp (&s); + DrawBaseStateStrings ((STARBASE_STATE)~0, pMS->CurState); +{ + RECT r; + + r.corner.x = 0; + r.corner.y = 0; + r.extent.width = SCREEN_WIDTH; + r.extent.height = SCREEN_HEIGHT; + ScreenTransition (3, &r); +} + PlayMusic (pMS->hMusic, TRUE, 1); + UnbatchGraphics (); + pMS->flash_task = AddTask (rotate_starbase, 4096); + ClearSemaphore (&GraphicsSem); + } + else if ((InputState & DEVICE_BUTTON1) + || GET_GAME_STATE (MOONBASE_ON_SHIP) + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { +ExitStarBase: + SetSemaphore (&GraphicsSem); + if (pMS->flash_task) + { + DeleteTask (pMS->flash_task); + pMS->flash_task = 0; + } + DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); + pMS->CurFrame = 0; + ClearSemaphore (&GraphicsSem); + StopMusic (); + if (pMS->hMusic) + { + DestroyMusic (pMS->hMusic); + pMS->hMusic = 0; + } + + if (pMS->CurState == DEPART_BASE) + { + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + SET_GAME_STATE (STARBASE_VISITED, 0); + } + return (FALSE); + } + + pMS->Initialized = FALSE; + if (pMS->CurState == TALK_COMMANDER) + { + InitCommunication (COMMANDER_CONVERSATION); + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); + } + else + { + BYTE OldState; + + switch (OldState = pMS->CurState) + { + case OUTFIT_STARSHIP: + pMS->InputFunc = DoOutfit; + break; + case SHIPYARD: + pMS->InputFunc = DoShipyard; + break; + } + + DoInput ((PVOID)pMS); + + pMS->Initialized = FALSE; + pMS->CurState = OldState; + pMS->InputFunc = DoStarBase; + } + } + else + { + STARBASE_STATE NewState; + + NewState = pMS->CurState; + if (GetInputXComponent (InputState) < 0 + || GetInputYComponent (InputState) < 0) + { + if (NewState-- == TALK_COMMANDER) + NewState = DEPART_BASE; + } + else if (GetInputXComponent (InputState) > 0 + || GetInputYComponent (InputState) > 0) + { + if (NewState++ == DEPART_BASE) + NewState = TALK_COMMANDER; + } + + if (NewState != pMS->CurState) + { + SetSemaphore (&GraphicsSem); + DrawBaseStateStrings (pMS->CurState, NewState); + ClearSemaphore (&GraphicsSem); + pMS->CurState = NewState; + } + } + + return (TRUE); +} + +void +VisitStarBase (void) +{ + MENU_STATE MenuState; + CONTEXT OldContext; + + if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + CurStarDescPtr = 0; + goto TimePassage; + } + else if (!GET_GAME_STATE (STARBASE_AVAILABLE)) + { + HSTARSHIP hStarShip; + SHIP_FRAGMENTPTR FragPtr; + + pMenuState = 0; + + InitCommunication (COMMANDER_CONVERSATION); + if (!GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER) + || (GLOBAL (CurrentActivity) & CHECK_ABORT)) + goto ExitStarBase; + + hStarShip = CloneShipFragment ( + ILWRATH_SHIP, + &GLOBAL (npc_built_ship_q), 7 + ); + FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + SET_RACE_ID (FragPtr, (BYTE)~0); + UnlockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip + ); + + InitCommunication (ILWRATH_CONVERSATION); + if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 + || (GLOBAL (CurrentActivity) & CHECK_ABORT)) + return; + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); + + { +#define LOST_DAYS 14 + COUNT i; + BYTE clut_buf[1]; + + pMenuState = &MenuState; + InitCommunication (COMMANDER_CONVERSATION); + +TimePassage: + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); + clut_buf[0] = FadeAllToBlack; + SleepTask (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2)); + for (i = 0; i < LOST_DAYS; ++i) + { + while (ClockTick () > 0) + ; + + ResumeGameClock (); + SleepTask (GetTimeCounter () + 2); + SuspendGameClock (); + } + } + } + + pMenuState = &MenuState; + + memset ((PMENU_STATE)&MenuState, 0, sizeof (MenuState)); + + MenuState.InputFunc = DoStarBase; + if (GET_GAME_STATE (MOONBASE_ON_SHIP) + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + MenuState.Initialized = TRUE; + MenuState.CurState = TALK_COMMANDER; + } + + OldContext = SetContext (ScreenContext); + DoInput ((PVOID)pMenuState); + SetContext (OldContext); + + pMenuState = 0; + +ExitStarBase: + if (!(GLOBAL (CurrentActivity) & (CHECK_LOAD | CHECK_ABORT))) + { + extern ACTIVITY NextActivity; + + SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); + GLOBAL (CurrentActivity) = CHECK_LOAD; + NextActivity = MAKE_WORD (IN_INTERPLANETARY, 0) + | START_INTERPLANETARY; + } +} + +COUNT +WrapText (UNICODE *pStr, COUNT len, TEXT *tarray, SIZE field_width) +{ + COUNT num_lines; + + num_lines = 0; + do + { + RECT r; + COUNT OldCount; + + tarray->align = ALIGN_LEFT; /* set alignment to something */ + tarray->pStr = pStr; + tarray->CharCount = 1; + ++num_lines; + + do + { + OldCount = tarray->CharCount; + while (*++pStr != ' ' && (COUNT)(pStr - tarray->pStr) < len) + ; + tarray->CharCount = pStr - tarray->pStr; + TextRect (tarray, &r, NULL_PTR); + } while (tarray->CharCount < len && r.extent.width < field_width); + + if (r.extent.width >= field_width) + { + if ((tarray->CharCount = OldCount) == 1) + { + do + { + ++tarray->CharCount; + TextRect (tarray, &r, NULL_PTR); + } while (r.extent.width < field_width); + --tarray->CharCount; + } + } + + pStr = tarray->pStr + tarray->CharCount; + len -= tarray->CharCount; + ++tarray; + + if (len && (r.extent.width < field_width || OldCount > 1)) + { + ++pStr; /* skip white space */ + --len; + } + + } while (len); + + return (num_lines); +} + diff --git a/sc2/src/sc2code/starbase.h b/sc2/src/sc2code/starbase.h new file mode 100644 index 000000000..18a1b5773 --- /dev/null +++ b/sc2/src/sc2code/starbase.h @@ -0,0 +1,70 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STARBASE_H +#define _STARBASE_H + +enum +{ + TALK_COMMANDER = 0, + OUTFIT_STARSHIP, + SHIPYARD, + DEPART_BASE +}; +typedef BYTE STARBASE_STATE; + +#define FIELD_WIDTH (STATUS_WIDTH - 5) + +typedef struct menu_state +{ + BOOLEAN (*InputFunc) (INPUT_STATE InputState, struct menu_state + *pMS); + COUNT MenuRepeatDelay; + + SIZE Initialized; + + BYTE CurState; + FRAME CurFrame; + STRING CurString; + POINT first_item; + SIZE delta_item; + + FRAME ModuleFrame; + TASK flash_task; + RECT flash_rect0, + flash_rect1; + FRAME flash_frame0, + flash_frame1; + + MUSIC_REF hMusic; +} MENU_STATE; +typedef MENU_STATE *PMENU_STATE; + +extern PMENU_STATE pMenuState; + +extern void VisitStarBase (void); +extern BOOLEAN DoStarBase (INPUT_STATE InputState, PMENU_STATE pMS); +extern BOOLEAN DoOutfit (INPUT_STATE InputState, PMENU_STATE pMS); +extern BOOLEAN DoShipyard (INPUT_STATE InputState, PMENU_STATE pMS); +extern void DrawShipPiece (PMENU_STATE pMS, COUNT which_piece, COUNT + which_slot, BOOLEAN DrawBluePrint); + +extern const char starbase_str_array[][20]; + +#endif /* _STARBASE_H */ + diff --git a/sc2/src/sc2code/starcon.c b/sc2/src/sc2code/starcon.c new file mode 100644 index 000000000..4c53436d4 --- /dev/null +++ b/sc2/src/sc2code/starcon.c @@ -0,0 +1,1004 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +//Added by Chris + +void Logo (void); + +//End Added by Chris + +enum +{ + CLOSING = 0, + OPENING +}; + +int arilou_gate_task(void* Blah) +{ + BYTE counter; + DWORD TimeIn; + + TimeIn = GetTimeCounter (); + + counter = GET_GAME_STATE (ARILOU_SPACE_COUNTER); + for (;;) + { + SetSemaphore (&GLOBAL (GameClock.clock_sem)); + + if (GET_GAME_STATE (ARILOU_SPACE) == OPENING) + { + if (++counter == 10) + counter = 9; + } + else + { + if (counter-- == 0) + counter = 0; + } + + SetSemaphore (&GraphicsSem); + SET_GAME_STATE (ARILOU_SPACE_COUNTER, counter); + ClearSemaphore (&GraphicsSem); + + ClearSemaphore (&GLOBAL (GameClock.clock_sem)); + TimeIn = SleepTask (TimeIn + BATTLE_FRAME_RATE); + } + + (void) Blah; /* Satisfying compiler (unused parameter) */ + return(0); +} + +static void +arilou_entrance_event (void) +{ + SET_GAME_STATE (ARILOU_SPACE, OPENING); + AddEvent (RELATIVE_EVENT, 0, 3, 0, ARILOU_EXIT_EVENT); +} + +static void +arilou_exit_event (void) +{ + COUNT month_index, year_index; + + year_index = GLOBAL (GameClock.year_index); + if ((month_index = GLOBAL (GameClock.month_index) % 12) == 0) + ++year_index; + ++month_index; + + SET_GAME_STATE (ARILOU_SPACE, CLOSING); + AddEvent (ABSOLUTE_EVENT, + month_index, 17, year_index, ARILOU_ENTRANCE_EVENT); +} + +void +SetRaceDest (BYTE which_race, COORD x, COORD y, BYTE days_left, BYTE + func_index) +{ + HSTARSHIP hStarShip; + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), which_race); + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + + TemplatePtr->ShipInfo.dest_loc.x = x; + TemplatePtr->ShipInfo.dest_loc.y = y; + TemplatePtr->ShipInfo.days_left = days_left; + TemplatePtr->ShipInfo.func_index = func_index; + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); +} + +static void +check_race_growth (void) +{ + HSTARSHIP hStarShip, hNextShip; + + for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip; hStarShip = hNextShip) + { + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + hNextShip = _GetSuccLink (TemplatePtr); + + if (TemplatePtr->ShipInfo.actual_strength + && TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) + { + SIZE delta_strength; + + delta_strength = (SBYTE)TemplatePtr->ShipInfo.energy_level; + if (TemplatePtr->ShipInfo.growth_err_term <= + TemplatePtr->ShipInfo.growth_fract) + { + if (delta_strength <= 0) + --delta_strength; + else + ++delta_strength; + } + TemplatePtr->ShipInfo.growth_err_term -= + TemplatePtr->ShipInfo.growth_fract; + + delta_strength += TemplatePtr->ShipInfo.actual_strength; + if (delta_strength <= 0) + { + delta_strength = 0; + TemplatePtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + } + else if (delta_strength > MAX_FLEET_STRENGTH) + delta_strength = MAX_FLEET_STRENGTH; + + TemplatePtr->ShipInfo.actual_strength = (COUNT)delta_strength; + if (TemplatePtr->ShipInfo.actual_strength && TemplatePtr->ShipInfo.days_left) + { + TemplatePtr->ShipInfo.loc.x += + (TemplatePtr->ShipInfo.dest_loc.x + - TemplatePtr->ShipInfo.loc.x) + / TemplatePtr->ShipInfo.days_left; + TemplatePtr->ShipInfo.loc.y += + (TemplatePtr->ShipInfo.dest_loc.y + - TemplatePtr->ShipInfo.loc.y) + / TemplatePtr->ShipInfo.days_left; + + if (--TemplatePtr->ShipInfo.days_left == 0 + && TemplatePtr->ShipInfo.func_index != (BYTE)~0) + EventHandler (TemplatePtr->ShipInfo.func_index); + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + } +} + +static void +black_urquan_genocide (void) +{ + BYTE Index; + long best_dist; + SIZE best_dx, best_dy; + HSTARSHIP hStarShip, hNextShip; + HSTARSHIP hBlackUrquan; + EXTENDED_SHIP_FRAGMENTPTR BlackUrquanPtr; + + hBlackUrquan = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), BLACK_URQUAN_SHIP + ); + BlackUrquanPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hBlackUrquan + ); + + best_dist = -1; + best_dx = SOL_X - BlackUrquanPtr->ShipInfo.loc.x; + best_dy = SOL_Y - BlackUrquanPtr->ShipInfo.loc.y; + for (Index = 0, hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); + hStarShip; ++Index, hStarShip = hNextShip) + { + EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; + + TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + hNextShip = _GetSuccLink (TemplatePtr); + + if (Index != BLACK_URQUAN_SHIP + && Index != URQUAN_SHIP + && TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) + { + SIZE dx, dy; + + dx = TemplatePtr->ShipInfo.loc.x - BlackUrquanPtr->ShipInfo.loc.x; + dy = TemplatePtr->ShipInfo.loc.y - BlackUrquanPtr->ShipInfo.loc.y; + if (dx == 0 && dy == 0) + { + TemplatePtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + TemplatePtr->ShipInfo.actual_strength = 0; + } + else if (TemplatePtr->ShipInfo.actual_strength) + { + long dist; + + dist = (long)dx * dx + (long)dy * dy; + if (best_dist < 0 || dist < best_dist || Index == DRUUGE_SHIP) + { + best_dist = dist; + best_dx = dx; + best_dy = dy; + + if (Index == DRUUGE_SHIP) + hNextShip = 0; + } + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hStarShip + ); + } + + if (best_dist < 0 && best_dx == 0 && best_dy == 0) + { + GLOBAL (CurrentActivity) &= ~IN_BATTLE; + GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; + + SET_GAME_STATE (KOHR_AH_KILLED_ALL, 1); + } + else + { + COUNT speed; + + if (best_dist < 0) + best_dist = (long)best_dx * best_dx + + (long)best_dy * best_dy; + + speed = square_root (best_dist) / 158; + if (speed == 0) + speed = 1; + else if (speed > 255) + speed = 255; + + SET_GAME_STATE (KOHR_AH_FRENZY, 1); + SET_GAME_STATE (KOHR_AH_VISITS, 0); + SET_GAME_STATE (KOHR_AH_REASONS, 0); + SET_GAME_STATE (KOHR_AH_PLEAD, 0); + SET_GAME_STATE (KOHR_AH_INFO, 0); + SET_GAME_STATE (URQUAN_VISITS, 0); + SetRaceDest (BLACK_URQUAN_SHIP, + BlackUrquanPtr->ShipInfo.loc.x + best_dx, + BlackUrquanPtr->ShipInfo.loc.y + best_dy, + (BYTE)speed, KOHR_AH_GENOCIDE_EVENT); + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hBlackUrquan + ); +} + +static void +pkunk_mission (void) +{ + HSTARSHIP hPkunk; + EXTENDED_SHIP_FRAGMENTPTR PkunkPtr; + + hPkunk = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), PKUNK_SHIP + ); + PkunkPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hPkunk + ); + + if (PkunkPtr->ShipInfo.actual_strength) + { + BYTE MissionState; + + MissionState = GET_GAME_STATE (PKUNK_MISSION); + if (PkunkPtr->ShipInfo.days_left == 0 && MissionState) + { + if ((MissionState & 1) + /* made it to Yehat space */ + || (PkunkPtr->ShipInfo.loc.x == 4970 + && PkunkPtr->ShipInfo.loc.y == 400)) + PkunkPtr->ShipInfo.actual_strength = 0; + else if (PkunkPtr->ShipInfo.loc.x == 502 + && PkunkPtr->ShipInfo.loc.y == 401 + && GET_GAME_STATE (PKUNK_ON_THE_MOVE)) + { + SET_GAME_STATE (PKUNK_ON_THE_MOVE, 0); + AddEvent (RELATIVE_EVENT, 3, 0, 0, ADVANCE_PKUNK_MISSION); + UnlockStarShip ( + &GLOBAL (avail_race_q), + hPkunk + ); + return; + } + } + + if (PkunkPtr->ShipInfo.actual_strength == 0) + { + SET_GAME_STATE (YEHAT_ABSORBED_PKUNK, 1); + PkunkPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING); + } + else + { + COORD x, y; + + if (!(MissionState & 1)) + { + x = 4970; + y = 400; + } + else + { + x = 502; + y = 401; + } + SET_GAME_STATE (PKUNK_ON_THE_MOVE, 1); + SET_GAME_STATE (PKUNK_SWITCH, 0); + SetRaceDest (PKUNK_SHIP, x, y, + (BYTE)((365 >> 1) - PkunkPtr->ShipInfo.days_left), + ADVANCE_PKUNK_MISSION); + } + SET_GAME_STATE (PKUNK_MISSION, MissionState + 1); + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hPkunk + ); +} + +static void +thradd_mission (void) +{ + BYTE MissionState; + HSTARSHIP hThradd; + EXTENDED_SHIP_FRAGMENTPTR ThraddPtr; + + hThradd = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), THRADDASH_SHIP + ); + ThraddPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hThradd + ); + + MissionState = GET_GAME_STATE (THRADD_MISSION); + if (ThraddPtr->ShipInfo.actual_strength && MissionState < 3) + { + if (MissionState & 1) + { + SIZE strength_loss; + + AddEvent (RELATIVE_EVENT, 0, 14, 0, ADVANCE_THRADD_MISSION); + strength_loss = (SIZE)(ThraddPtr->ShipInfo.actual_strength >> 1); + + ThraddPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / 14); + ThraddPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % 14) << 8) / 14); + ThraddPtr->ShipInfo.growth_err_term = 255 >> 1; + } + else + { + COORD x, y; + + if (MissionState == 0) + { + x = 4879; + y = 7201; + } + else + { + x = 2535; + y = 8358; + + ThraddPtr->ShipInfo.energy_level = 0; + ThraddPtr->ShipInfo.growth_fract = 0; + } + SetRaceDest (THRADDASH_SHIP, x, y, 14, ADVANCE_THRADD_MISSION); + } + } + SET_GAME_STATE (THRADD_MISSION, MissionState + 1); + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hThradd + ); +} + +static void +ilwrath_mission (void) +{ + HSTARSHIP hIlwrath, hThradd; + EXTENDED_SHIP_FRAGMENTPTR IlwrathPtr, ThraddPtr; + + hIlwrath = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), ILWRATH_SHIP + ); + IlwrathPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hIlwrath + ); + hThradd = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), THRADDASH_SHIP + ); + ThraddPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hThradd + ); + + if (IlwrathPtr->ShipInfo.loc.x == ((2500 + 2535) >> 1) + && IlwrathPtr->ShipInfo.loc.y == ((8070 + 8358) >> 1)) + { + IlwrathPtr->ShipInfo.actual_strength = + ThraddPtr->ShipInfo.actual_strength = 0; + IlwrathPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + ThraddPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + } + else if (IlwrathPtr->ShipInfo.actual_strength) + { + if (IlwrathPtr->ShipInfo.dest_loc.x != 2500 + || IlwrathPtr->ShipInfo.dest_loc.y != 8070) + SetRaceDest (ILWRATH_SHIP, 2500, 8070, 90, ADVANCE_ILWRATH_MISSION); + else + { +#define MADD_LENGTH 128 + SIZE strength_loss; + + SET_GAME_STATE (ILWRATH_FIGHT_THRADDASH, 1); + SET_GAME_STATE (HELIX_UNPROTECTED, 1); + strength_loss = (SIZE)IlwrathPtr->ShipInfo.actual_strength; + IlwrathPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / MADD_LENGTH); + IlwrathPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % MADD_LENGTH) << 8) / MADD_LENGTH); + SetRaceDest (ILWRATH_SHIP, + (2500 + 2535) >> 1, + (8070 + 8358) >> 1, + MADD_LENGTH - 1, + ADVANCE_ILWRATH_MISSION); + + strength_loss = (SIZE)ThraddPtr->ShipInfo.actual_strength; + ThraddPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / MADD_LENGTH); + ThraddPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % MADD_LENGTH) << 8) / MADD_LENGTH); + SetRaceDest (THRADDASH_SHIP, + (2500 + 2535) >> 1, + (8070 + 8358) >> 1, + MADD_LENGTH, (BYTE)~0); + SET_GAME_STATE (THRADD_VISITS, 0); + if (ThraddPtr->ShipInfo.ship_flags & GOOD_GUY) + ActivateStarShip (THRADDASH_SHIP, -1); + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hThradd + ); + UnlockStarShip ( + &GLOBAL (avail_race_q), + hIlwrath + ); +} + +static void +utwig_supox_mission (void) +{ + BYTE MissionState; + HSTARSHIP hUtwig, hSupox; + EXTENDED_SHIP_FRAGMENTPTR UtwigPtr, SupoxPtr; + + hUtwig = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), UTWIG_SHIP + ); + UtwigPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hUtwig + ); + hSupox = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), SUPOX_SHIP + ); + SupoxPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hSupox + ); + + MissionState = GET_GAME_STATE (UTWIG_SUPOX_MISSION); + if (UtwigPtr->ShipInfo.actual_strength && MissionState < 5) + { + if (MissionState == 1) + { + SIZE strength_loss; + + AddEvent (RELATIVE_EVENT, 0, (160 >> 1), 0, ADVANCE_UTWIG_SUPOX_MISSION); + + strength_loss = (SIZE)(UtwigPtr->ShipInfo.actual_strength >> 1); + UtwigPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / 160); + UtwigPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % 160) << 8) / 160); + UtwigPtr->ShipInfo.growth_err_term = 255 >> 1; + + strength_loss = (SIZE)(SupoxPtr->ShipInfo.actual_strength >> 1); + if (strength_loss) + { + SupoxPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / 160); + SupoxPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % 160) << 8) / 160); + SupoxPtr->ShipInfo.growth_err_term = 255 >> 1; + } + + SET_GAME_STATE (UTWIG_WAR_NEWS, 0); + SET_GAME_STATE (SUPOX_WAR_NEWS, 0); + } + else if (MissionState == 2) + { + AddEvent (RELATIVE_EVENT, 0, (160 >> 1), 0, ADVANCE_UTWIG_SUPOX_MISSION); + ++MissionState; + } + else + { + COORD ux, uy, sx, sy; + + if (MissionState == 0) + { + ux = 7208; + uy = 7000; + + sx = 6479; + sy = 7541; + } + else + { + ux = 8534; + uy = 8797; + + sx = 7468; + sy = 9246; + + UtwigPtr->ShipInfo.energy_level = 0; + UtwigPtr->ShipInfo.growth_fract = 0; + SupoxPtr->ShipInfo.energy_level = 0; + SupoxPtr->ShipInfo.growth_fract = 0; + + SET_GAME_STATE (UTWIG_WAR_NEWS, 0); + SET_GAME_STATE (SUPOX_WAR_NEWS, 0); + } + SET_GAME_STATE (UTWIG_VISITS, 0); + SET_GAME_STATE (UTWIG_INFO, 0); + SET_GAME_STATE (SUPOX_VISITS, 0); + SET_GAME_STATE (SUPOX_INFO, 0); + SetRaceDest (UTWIG_SHIP, ux, uy, 21, ADVANCE_UTWIG_SUPOX_MISSION); + SetRaceDest (SUPOX_SHIP, sx, sy, 21, (BYTE)~0); + } + } + SET_GAME_STATE (UTWIG_SUPOX_MISSION, MissionState + 1); + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hSupox + ); + UnlockStarShip ( + &GLOBAL (avail_race_q), + hUtwig + ); +} + +static void +mycon_mission (void) +{ + HSTARSHIP hMycon; + EXTENDED_SHIP_FRAGMENTPTR MyconPtr; + + hMycon = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), MYCON_SHIP + ); + MyconPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hMycon + ); + + if (MyconPtr->ShipInfo.actual_strength) + { + if (MyconPtr->ShipInfo.energy_level) + { + SET_GAME_STATE (MYCON_KNOW_AMBUSH, 1); + SetRaceDest (MYCON_SHIP, 6392, 2200, 30, (BYTE)~0); + + MyconPtr->ShipInfo.energy_level = 0; + MyconPtr->ShipInfo.growth_fract = 0; + } + else if (MyconPtr->ShipInfo.loc.x != 6858 + || MyconPtr->ShipInfo.loc.y != 577) + SetRaceDest (MYCON_SHIP, 6858, 577, 30, ADVANCE_MYCON_MISSION); + else + { + SIZE strength_loss; + + AddEvent (RELATIVE_EVENT, 0, 14, 0, ADVANCE_MYCON_MISSION); + strength_loss = (SIZE)(MyconPtr->ShipInfo.actual_strength >> 1); + MyconPtr->ShipInfo.energy_level = + (BYTE)(-strength_loss / 14); + MyconPtr->ShipInfo.growth_fract = + (BYTE)(((strength_loss % 14) << 8) / 14); + MyconPtr->ShipInfo.growth_err_term = 255 >> 1; + } + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hMycon + ); +} + +void +EventHandler (BYTE selector) +{ + switch (selector) + { + case ARILOU_ENTRANCE_EVENT: + arilou_entrance_event (); + break; + case ARILOU_EXIT_EVENT: + arilou_exit_event (); + break; + case HYPERSPACE_ENCOUNTER_EVENT: + check_race_growth (); + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE + && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + extern void check_hyperspace_encounter (void); + + check_hyperspace_encounter (); + } + + AddEvent (RELATIVE_EVENT, 0, 1, 0, HYPERSPACE_ENCOUNTER_EVENT); + break; + case KOHR_AH_VICTORIOUS_EVENT: + if (GET_GAME_STATE (UTWIG_SUPOX_MISSION)) + { + AddEvent (RELATIVE_EVENT, 0, 0, 1, KOHR_AH_GENOCIDE_EVENT); + break; + } + case KOHR_AH_GENOCIDE_EVENT: + if (!GET_GAME_STATE (KOHR_AH_FRENZY) + && LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && CurStarDescPtr->Index == SAMATRA_DEFINED) + AddEvent (RELATIVE_EVENT, 0, 7, 0, KOHR_AH_GENOCIDE_EVENT); + else + black_urquan_genocide (); + break; + case ADVANCE_PKUNK_MISSION: + pkunk_mission (); + break; + case ADVANCE_THRADD_MISSION: + thradd_mission (); + break; + case ZOQFOT_DISTRESS_EVENT: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && CurStarDescPtr->Index == ZOQFOT_DEFINED) + AddEvent (RELATIVE_EVENT, 0, 7, 0, ZOQFOT_DISTRESS_EVENT); + else + { + SET_GAME_STATE (ZOQFOT_DISTRESS, 1); + AddEvent (RELATIVE_EVENT, 6, 0, 0, ZOQFOT_DEATH_EVENT); + } + break; + case ZOQFOT_DEATH_EVENT: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && CurStarDescPtr->Index == ZOQFOT_DEFINED) + AddEvent (RELATIVE_EVENT, 0, 7, 0, ZOQFOT_DEATH_EVENT); + else if (GET_GAME_STATE (ZOQFOT_DISTRESS)) + { + HSTARSHIP hZoqFot; + EXTENDED_SHIP_FRAGMENTPTR ZoqFotPtr; + + hZoqFot = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), ZOQFOTPIK_SHIP + ); + ZoqFotPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hZoqFot + ); + ZoqFotPtr->ShipInfo.actual_strength = 0; + ZoqFotPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); + UnlockStarShip ( + &GLOBAL (avail_race_q), + hZoqFot + ); + + SET_GAME_STATE (ZOQFOT_DISTRESS, 2); + } + break; + case SHOFIXTI_RETURN_EVENT: + ActivateStarShip (SHOFIXTI_SHIP, 0); + GLOBAL (CrewCost) -= 2; + /* crew is not an issue anymore */ + SET_GAME_STATE (CREW_PURCHASED0, 0); + SET_GAME_STATE (CREW_PURCHASED1, 0); + break; + case ADVANCE_UTWIG_SUPOX_MISSION: + utwig_supox_mission (); + break; + case SPATHI_SHIELD_EVENT: + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY + && CurStarDescPtr->Index == SPATHI_DEFINED) + AddEvent (RELATIVE_EVENT, 0, 7, 0, SPATHI_SHIELD_EVENT); + else + { + HSTARSHIP hSpathi; + EXTENDED_SHIP_FRAGMENTPTR SpathiPtr; + + hSpathi = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), SPATHI_SHIP + ); + SpathiPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hSpathi + ); + + if (SpathiPtr->ShipInfo.actual_strength) + { + ActivateStarShip (SPATHI_SHIP, -1); + SET_GAME_STATE (SPATHI_SHIELDED_SELVES, 1); + SpathiPtr->ShipInfo.actual_strength = 0; + } + + UnlockStarShip ( + &GLOBAL (avail_race_q), + hSpathi + ); + } + break; + case ADVANCE_ILWRATH_MISSION: + ilwrath_mission (); + break; + case ADVANCE_MYCON_MISSION: + mycon_mission (); + break; + case ARILOU_UMGAH_CHECK: + SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 2); + break; + case YEHAT_REBEL_EVENT: + { + HSTARSHIP hRebel, hRoyalist; + EXTENDED_SHIP_FRAGMENTPTR RebelPtr, RoyalistPtr; + + hRebel = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), YEHAT_REBEL_SHIP + ); + RebelPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hRebel + ); + hRoyalist = GetStarShipFromIndex ( + &GLOBAL (avail_race_q), YEHAT_SHIP + ); + RoyalistPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( + &GLOBAL (avail_race_q), + hRoyalist + ); + RebelPtr->ShipInfo.actual_strength = + RoyalistPtr->ShipInfo.actual_strength = + RoyalistPtr->ShipInfo.actual_strength * 2 / 3; + RebelPtr->ShipInfo.loc.x = 5150; + RebelPtr->ShipInfo.loc.y = 0; + UnlockStarShip ( + &GLOBAL (avail_race_q), + hRoyalist + ); + UnlockStarShip ( + &GLOBAL (avail_race_q), + hRebel + ); + ActivateStarShip (YEHAT_REBEL_SHIP, SPHERE_TRACKING); + break; + } + case SLYLANDRO_RAMP_UP: + if (!GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) + { + BYTE ramp_factor; + + ramp_factor = GET_GAME_STATE (SLYLANDRO_MULTIPLIER); + if (++ramp_factor <= 4) + { + SET_GAME_STATE (SLYLANDRO_MULTIPLIER, ramp_factor); + AddEvent (RELATIVE_EVENT, 0, 182, 0, SLYLANDRO_RAMP_UP); + } + } + break; + case SLYLANDRO_RAMP_DOWN: + { + BYTE ramp_factor; + + ramp_factor = GET_GAME_STATE (SLYLANDRO_MULTIPLIER); + if (--ramp_factor) + AddEvent (RELATIVE_EVENT, 0, 23, 0, SLYLANDRO_RAMP_DOWN); + SET_GAME_STATE (SLYLANDRO_MULTIPLIER, ramp_factor); + } + break; + } +} + +#define DEBUG_PSYTRON 0 + +int Starcon2Main(void* blah) +{ +#if DEBUG_PSYTRON || CREATE_JOURNAL +{ +int ac = argc; +char **av = argv; + +while (--ac > 0) +{ + ++av; + if ((*av)[0] == '-') + { + switch ((*av)[1]) + { +#ifdef DEBUG_PSYTRON + case 'd': + { + extern BYTE debug_psytron; + + debug_psytron = atoi (&(*av)[2]); + break; + } +#endif //DEBUG_PSYTRON +#if CREATE_JOURNAL + case 'j': + ++battle_counter; + break; +#endif //CREATE_JOURNAL + } + } +} +} +#endif //DEBUG_PSYTRON || CREATE_JOURNAL + + Logo (); + + if (LoadKernel (0,0)) + { + extern BOOLEAN StartGame (void); + + printf("We've loaded the Kernel\n"); + +// OpenJournal (); + while (StartGame ()) + { + InitSIS (); + InitGameClock (); + + AddEvent (RELATIVE_EVENT, 0, 1, 0, HYPERSPACE_ENCOUNTER_EVENT); + AddEvent (ABSOLUTE_EVENT, 3, 17, START_YEAR, ARILOU_ENTRANCE_EVENT); + AddEvent (RELATIVE_EVENT, 0, 0, YEARS_TO_KOHRAH_VICTORY, + KOHR_AH_VICTORIOUS_EVENT); + AddEvent (RELATIVE_EVENT, 0, 0, 0, SLYLANDRO_RAMP_UP); + do + { + extern ACTIVITY NextActivity; +#ifdef TESTING +COUNT sc; +extern COUNT _simple_count; + +sc = _simple_count; +#endif //TESTING + if (GameClockRunning ()) + SuspendGameClock (); + + if (!((GLOBAL (CurrentActivity) | NextActivity) & CHECK_LOAD)) + ZeroVelocityComponents ( + &GLOBAL (velocity) + ); + //not going into talking pet conversation + else if (GLOBAL (CurrentActivity) & CHECK_LOAD) + GLOBAL (CurrentActivity) = NextActivity; + + if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + { + GLOBAL (CurrentActivity) |= START_ENCOUNTER; + if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0 + || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) + VisitStarBase (); + else + RaceCommunication (); + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) + { + GLOBAL (CurrentActivity) &= ~START_ENCOUNTER; + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; + } + } + else if (GLOBAL (CurrentActivity) & START_INTERPLANETARY) + { + GLOBAL (CurrentActivity) = MAKE_WORD (IN_INTERPLANETARY, 0); + + ExploreSolarSys (); +#ifdef TESTING +if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) +&& GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) +{ +if (!(GLOBAL (CurrentActivity) & START_ENCOUNTER) + && (CurStarDescPtr = FindStar (NULL_PTR, + &GLOBAL (autopilot), 0, 0))) +{ + GLOBAL (autopilot.x) = ~0; + GLOBAL (autopilot.y) = ~0; + GLOBAL (ShipStamp.frame) = 0; + GLOBAL (CurrentActivity) |= START_INTERPLANETARY; +} +} +#endif //TESTING + } + else + { + TASK ArilouTask; + + GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0); + + ArilouTask = AddTask (arilou_gate_task, 128); + + TaskSwitch (); + + Battle (); + if (ArilouTask) + DeleteTask (ArilouTask); + } +#ifdef TESTING +if (_simple_count != sc) printf ("%d difference!\n", (int)_simple_count - (int)sc); +#endif //TESTING + + SetSemaphore (&GraphicsSem); + SetFlashRect (NULL_PTR, (FRAME)0); + ClearSemaphore (&GraphicsSem); + + LastActivity = GLOBAL (CurrentActivity); + + if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) + && (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE + //if died for some reason + || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0)) + { + if (GET_GAME_STATE (KOHR_AH_KILLED_ALL)) + InitCommunication (BLACKURQ_CONVERSATION); + //surrendered to Ur-Quan + else if (GLOBAL (CurrentActivity) & CHECK_RESTART) + GLOBAL (CurrentActivity) &= ~CHECK_RESTART; + break; + } + } while (!(GLOBAL (CurrentActivity) & CHECK_ABORT)); + + StopSound (); + UninitGameClock (); + UninitSIS (); + } +// CloseJournal (); + } + else + { + printf("Kernel failed to load!\n"); + } + FreeKernel (); + + (void) blah; /* Satisfying compiler (unused parameter) */ + return(0); +} diff --git a/sc2/src/sc2code/starcon.h b/sc2/src/sc2code/starcon.h new file mode 100644 index 000000000..925ddb6ef --- /dev/null +++ b/sc2/src/sc2code/starcon.h @@ -0,0 +1,238 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STARCON_H +#define _STARCON_H + +#define MAX_PLAYERS 4 +#define NUM_PLAYERS 2 +#define NUM_SIDES 2 + +extern int ScreenWidth; +extern int ScreenHeight; + +#define SCREEN_WIDTH ScreenWidth +#define SCREEN_HEIGHT ScreenHeight +#define SIS_ORG_X (7 + SAFE_X) +#define SIS_ORG_Y (10 + SAFE_Y) +#define STATUS_WIDTH 64 +#define STATUS_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2)) +#define SPACE_WIDTH (SCREEN_WIDTH - STATUS_WIDTH - (SAFE_X * 2)) +#define SPACE_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2)) +#define SIS_SCREEN_WIDTH (SPACE_WIDTH - 14) +#define SIS_SCREEN_HEIGHT (SPACE_HEIGHT - 13) + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "../port.h" +#include +#include +#include "gfxlib.h" +#include "inplib.h" +#include "timlib.h" +#include "sndlib.h" +#include "strlib.h" +#include "mathlib.h" +#include "reslib.h" +#include "restypes.h" +#include "resinst.h" +#include "displist.h" +#include "nameref.h" +#include "units.h" +#include "velocity.h" +#include "element.h" +#include "races.h" +#include "weapon.h" +#include "collide.h" +#include "build.h" +#include "intel.h" +#include "sounds.h" +#include "demo.h" +#include "starbase.h" +#include "sis.h" +#include "state.h" +#include "globdata.h" +#include "encount.h" + +#define HUMAN_CONTROL (BYTE)(1 << 0) +#define CYBORG_CONTROL (BYTE)(1 << 1) +#define PSYTRON_CONTROL (BYTE)(1 << 2) +#define COMPUTER_CONTROL (CYBORG_CONTROL | PSYTRON_CONTROL) + +#define STANDARD_RATING (BYTE)(1 << 3) +#define GOOD_RATING (BYTE)(1 << 4) +#define AWESOME_RATING (BYTE)(1 << 5) + +#define SELECT_RATE 20 +#define INVALID_INPUT ((INPUT_STATE)0xFF) +#define INPUT_TIMED_OUT ((INPUT_STATE)0) + +#define BLACK_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) +#define LTGRAY_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) +#define DKGRAY_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) +#define WHITE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + +#define NORMAL_ILLUMINATED_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) +#define NORMAL_SHADOWED_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) +#define HIGHLIGHT_ILLUMINATED_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) +#define HIGHLIGHT_SHADOWED_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) +#define MENU_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) +#define MENU_FOREGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) +#define MENU_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) +#define MENU_HIGHLIGHT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) + +#define STATUS_ILLUMINATED_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) +#define STATUS_SHADOWED_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) +#define STATUS_SHAPE_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) +#define STATUS_SHAPE_OUTLINE_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + +#define CONTROL_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) + +#define ALLIANCE_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) +#define HIERARCHY_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) +#define ALLIANCE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) +#define HIERARCHY_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) +#define ALLIANCE_BOX_HIGHLIGHT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) +#define HIERARCHY_BOX_HIGHLIGHT_COLOR HIERARCHY_BACKGROUND_COLOR + +#define MESSAGE_BACKGROUND_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) +#define MESSAGE_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) + +enum +{ + FadeAllToWhite = 250, + FadeSomeToWhite, + FadeAllToBlack, + FadeAllToColor, + FadeSomeToBlack, + FadeSomeToColor +}; + +#define SetPlayerIconColor(wp, z) \ + if ((wp) == 0) \ + SetContextForeGroundColor ((COLOR)((z) >= 0 ? \ + BUILD_COLOR (MAKE_RGB15 (0xA, 0x1F, 0x1F), 0x0B) : \ + BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03))); \ + else \ + SetContextForeGroundColor ((COLOR)((z) >= 0 ? \ + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0xA), 0x0C) : \ + BUILD_COLOR (MAKE_RGB15 (0x14, 0xA, 0x00), 0x06))) + +#define CONTROL_STRING_INDEX 0 +#define USING_STRING_INDEX 1 +#define RATING_STRING_INDEX 2 +#define OK_STRING_INDEX 3 +#define LABEL_STRING_COUNT (OK_STRING_INDEX + 1) + +#define MENU_REPEAT_DELAY (ONE_SECOND >> 1) + +extern ACTIVITY LastActivity; +extern BYTE PlayerControl[NUM_PLAYERS]; +extern SIZE cur_player, cur_race; +extern QUEUE disp_q; +extern SIZE battle_counter; +extern FRAME stars_in_space; +extern MEM_HANDLE hResIndex; +extern CONTEXT ScreenContext, StatusContext, + SpaceContext, OffScreenContext, + RadarContext, TaskContext; +extern FRAME BackFrame; +extern SIZE screen_width, screen_height; +extern FRAME Screen, RadarFrame; +extern FONT StarConFont, MicroFont, TinyFont; +extern BOOLEAN PagingEnabled; +extern INPUT_REF ArrowInput, ComputerInput, NormalInput, SerialInput, + JoystickInput[NUM_PLAYERS], KeyboardInput[NUM_PLAYERS], + CombinedInput[NUM_PLAYERS], PlayerInput[NUM_PLAYERS]; +extern FRAME ActivityFrame; +extern SOUND MenuSounds, GameSounds; +extern QUEUE race_q[NUM_PLAYERS]; +extern SEMAPHORE GraphicsSem; +extern STRING GameStrings; + +typedef enum +{ + PACKAGE_ERROR, + LOAD_ERROR, + SAVE_ERROR +} DISK_ERROR; + +extern void Introduction (void); +extern BOOLEAN TheftProtection (BOOLEAN WaitForInput); + +extern void SetFlashRect (PRECT pRect, FRAME f); + +extern void DrawStarConBox (PRECT pRect, SIZE BorderWidth, COLOR + TopLeftColor, COLOR BottomRightColor, BOOLEAN FillInterior, COLOR + InteriorColor); +extern INPUT_STATE ConfirmExit (void); +extern DWORD SeedRandomNumbers (void); +extern BOOLEAN StarConDiskError (PSTR pFileName); +extern void ReportDiskError (PSTR pFileName, DISK_ERROR ErrorCondition); +extern void DoInput (PVOID pInputState); +extern INPUT_STATE game_input (INPUT_REF InputRef, INPUT_STATE + InputState); +extern INPUT_STATE combined_input0 (INPUT_REF InputRef, INPUT_STATE + InputState); +extern INPUT_STATE combined_input1 (INPUT_REF InputRef, INPUT_STATE + InputState); +extern BOOLEAN Battle (void); +extern void EncounterBattle (void); +extern void SetPlayerInput (void); +extern BOOLEAN InitContexts (void); +extern void UninitContexts (void); +extern COUNT WrapText (UNICODE *pStr, COUNT len, TEXT *tarray, SIZE + field_width); + +extern void ToggleMusic (void); +extern void PlayMusic (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE + Priority); +extern void StopMusic (void); +extern void ResumeMusic (void); +extern void PauseMusic (void); +extern void ToggleSoundEffect (void); +extern void PlaySoundEffect (SOUND S, COUNT Channel, BYTE Priority); + +extern BOOLEAN CopyProtection (void); + +/* dummy.c */ +extern void SetSoundTracking (BOOLEAN toggle); +extern void GetSoundTrackingBuf (PSBYTE pdigi_buf); + +extern void StopVid (void); +extern void PlayVid (MEM_HANDLE VidRef, BOOLEAN Continuous); +extern MEM_HANDLE LoadVidFile (PSTR pStr); +extern MEM_HANDLE LoadVidInstance (DWORD res); +extern MEM_HANDLE VidPlaying (void); +extern BOOLEAN DestroyVid (MEM_HANDLE VidRef); + +extern DRAWABLE CreatePixmapRegion (FRAME Frame, PPOINT pOrg, SIZE width, + SIZE height); + +extern void SetPrimNextLink (PPRIMITIVE pPrim, COUNT Link); +extern COUNT GetPrimNextLink (PPRIMITIVE pPrim); + +//Added by Chris + +void AlienTalkSegue (COUNT wait_track); + +#include "appglue.h" + +#endif /* _STARCON_H */ + diff --git a/sc2/src/sc2code/starmap.c b/sc2/src/sc2code/starmap.c new file mode 100644 index 000000000..b95c8ef15 --- /dev/null +++ b/sc2/src/sc2code/starmap.c @@ -0,0 +1,121 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +STAR_DESCPTR star_array; +STAR_DESCPTR CurStarDescPtr = 0; + +STAR_DESCPTR +FindStar (STAR_DESCPTR LastSDPtr, PPOINT puniverse, SIZE xbounds, SIZE + ybounds) +{ + COORD min_y, max_y; + SIZE lo, hi; + STAR_DESCPTR BaseSDPtr; + + if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) + { + BaseSDPtr = star_array; + hi = NUM_SOLAR_SYSTEMS - 1; + } + else + { +#define NUM_HYPER_VORTICES 15 + BaseSDPtr = &star_array[NUM_SOLAR_SYSTEMS + 1]; + hi = (NUM_HYPER_VORTICES + 1) - 1; + } + + if (LastSDPtr == NULL_PTR) + lo = 0; + else if ((lo = LastSDPtr - BaseSDPtr + 1) > hi) + return (0); + else + hi = lo; + + if (ybounds <= 0) + min_y = max_y = puniverse->y; + else + { + min_y = puniverse->y - ybounds; + max_y = puniverse->y + ybounds; + } + + while (lo < hi) + { + SIZE mid; + + mid = (lo + hi) >> 1; + if (BaseSDPtr[mid].star_pt.y >= min_y) + hi = mid - 1; + else + lo = mid + 1; + } + + LastSDPtr = &BaseSDPtr[lo]; + if (ybounds < 0 || LastSDPtr->star_pt.y <= max_y) + { + COORD min_x, max_x; + + if (xbounds <= 0) + min_x = max_x = puniverse->x; + else + { + min_x = puniverse->x - xbounds; + max_x = puniverse->x + xbounds; + } + + do + { + if ((ybounds < 0 || LastSDPtr->star_pt.y >= min_y) + && (xbounds < 0 + || (LastSDPtr->star_pt.x >= min_x + && LastSDPtr->star_pt.x <= max_x)) + ) + return (LastSDPtr); + } while ((++LastSDPtr)->star_pt.y <= max_y); + } + + return (0); +} + +void +GetClusterName (STAR_DESCPTR pSD, UNICODE buf[]) +{ + UNICODE *pBuf, *pStr; + + pBuf = buf; + if (pSD->Prefix) + { + pStr = GAME_STRING (STAR_NUMBER_BASE + pSD->Prefix - 1); + if (pStr) + { + while ((*pBuf++ = *pStr++)) + ; + pBuf[-1] = ' '; + } + } + if ((pStr = GAME_STRING (pSD->Postfix)) == 0) + *pBuf = '\0'; + else + { + while ((*pBuf++ = *pStr++)) + ; + } +} + diff --git a/sc2/src/sc2code/state.c b/sc2/src/sc2code/state.c new file mode 100644 index 000000000..310f06aab --- /dev/null +++ b/sc2/src/sc2code/state.c @@ -0,0 +1,169 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +void +InitPlanetInfo (void) +{ + PVOID fp; + + fp = OpenResFile (STARINFO_FILE, "wb"); + if (fp) + { + DWORD offset; + STAR_DESCPTR pSD; + + offset = 0; + pSD = &star_array[0]; + do + { + WriteResFile (&offset, sizeof (offset), 1, fp); + ++pSD; + } while (pSD->star_pt.x <= MAX_X_UNIVERSE + && pSD->star_pt.y <= MAX_Y_UNIVERSE); + + CloseResFile (fp); + } +} + +void +UninitPlanetInfo (void) +{ + unlink (STARINFO_FILE); +} + +void +GetPlanetInfo (void) +{ + PVOID fp; + + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] = + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] = + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] = 0; + fp = OpenResFile (STARINFO_FILE, "rb"); + if (fp) + { + COUNT star_index, planet_index, moon_index; + DWORD offset; + + star_index = (COUNT)(CurStarDescPtr - star_array); + planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc); + if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) + moon_index = 0; + else + moon_index = (COUNT)(pSolarSysState->pOrbitalDesc + - pSolarSysState->MoonDesc + 1); + + SeekResFile (fp, star_index * sizeof (offset), SEEK_SET); + ReadResFile (&offset, sizeof (offset), 1, fp); + + if (offset) + { + COUNT i; + + for (i = 0; i < planet_index; ++i) + offset += sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1); + + offset += sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ) * moon_index; + + SeekResFile (fp, offset, SEEK_SET); + ReadResFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, + sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ), 1, fp); + } + + CloseResFile (fp); + } +} + +void +PutPlanetInfo (void) +{ + PVOID fp; + + fp = OpenResFile (STARINFO_FILE, "r+b"); + if (fp) + { + COUNT i; + COUNT star_index, planet_index, moon_index; + DWORD offset; + + star_index = (COUNT)(CurStarDescPtr - star_array); + planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc + - pSolarSysState->PlanetDesc); + if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) + moon_index = 0; + else + moon_index = (COUNT)(pSolarSysState->pOrbitalDesc + - pSolarSysState->MoonDesc + 1); + + SeekResFile (fp, star_index * sizeof (offset), SEEK_SET); + ReadResFile (&offset, sizeof (offset), 1, fp); + + if (offset == 0) + { + DWORD ScanRetrieveMask[NUM_SCAN_TYPES] = + { + 0, 0, 0, + }; + + offset = LengthResFile (fp); + + SeekResFile (fp, star_index * sizeof (offset), SEEK_SET); + WriteResFile (&offset, sizeof (offset), 1, fp); + + SeekResFile (fp, offset, SEEK_SET); + for (i = 0; i < pSolarSysState->SunDesc[0].NumPlanets; ++i) + { + COUNT j; + + WriteResFile (ScanRetrieveMask, sizeof (ScanRetrieveMask), 1, fp); + for (j = 0; j < pSolarSysState->PlanetDesc[i].NumPlanets; ++j) + WriteResFile (ScanRetrieveMask, sizeof (ScanRetrieveMask), 1, fp); + } + } + + for (i = 0; i < planet_index; ++i) + offset += sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1); + + offset += sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ) * moon_index; + + SeekResFile (fp, offset, SEEK_SET); + WriteResFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, + sizeof ( + pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask + ), 1, fp); + + CloseResFile (fp); + } +} + diff --git a/sc2/src/sc2code/state.h b/sc2/src/sc2code/state.h new file mode 100644 index 000000000..9d8c0ae6b --- /dev/null +++ b/sc2/src/sc2code/state.h @@ -0,0 +1,55 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STATE_H +#define _STATE_H + +extern void InitPlanetInfo (void); +extern void UninitPlanetInfo (void); +extern void GetPlanetInfo (void); +extern void PutPlanetInfo (void); + +extern void InitGroupInfo (BOOLEAN FirstTime); +extern void UninitGroupInfo (void); +extern BOOLEAN GetGroupInfo (DWORD offset, BYTE which_group); +extern DWORD PutGroupInfo (DWORD offset, BYTE which_group); +extern void BuildGroups (void); + +extern BOOLEAN GameOptions (void); + +#define MAX_DESC_CHARS 60 +typedef UNICODE GAME_DESC[MAX_DESC_CHARS + 1]; + +#define STARINFO_FILE "starinfo.dat" +#define STAR_BUFSIZE (NUM_SOLAR_SYSTEMS * sizeof (DWORD) \ + + 3800 * (3 * sizeof (DWORD))) +#define RANDGRPINFO_FILE "randgrp.dat" +#define RAND_BUFSIZE (4 * 1024) +#define DEFGRPINFO_FILE "defgrp.dat" +#define DEF_BUFSIZE (10 * 1024) + +typedef enum +{ + STARINFO, + RANDGRPINFO, + DEFGRPINFO +} INFO_TYPE; + + +#endif /* _STATE_H */ + diff --git a/sc2/src/sc2code/status.c b/sc2/src/sc2code/status.c new file mode 100644 index 000000000..97ca8c056 --- /dev/null +++ b/sc2/src/sc2code/status.c @@ -0,0 +1,550 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "starcon.h" + +static void +CaptainsWindow (CAPTAIN_STUFFPTR CSPtr, COORD y, register ELEMENT_FLAGS + delta_status_flags, register ELEMENT_FLAGS cur_status_flags, + COUNT Pass) +{ + STAMP Stamp; + + Stamp.origin.x = CAPTAIN_XOFFS; + Stamp.origin.y = y + CAPTAIN_YOFFS; + + if (delta_status_flags & LEFT) + { + Stamp.frame = CSPtr->turn; + if (!(delta_status_flags & RIGHT)) + { + Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); + if (Pass == 2) + { + if (cur_status_flags & LEFT) + Stamp.frame = IncFrameIndex (Stamp.frame); + else + Stamp.frame = DecFrameIndex (Stamp.frame); + } + } + else if (cur_status_flags & RIGHT) + { + if (Pass == 1) + Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); + else + Stamp.frame = IncFrameIndex (Stamp.frame); + DrawStamp (&Stamp); + Stamp.frame = DecFrameIndex (Stamp.frame); + } + else + { + if (Pass == 1) + Stamp.frame = IncFrameIndex (Stamp.frame); + else + Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); + DrawStamp (&Stamp); + Stamp.frame = IncFrameIndex (Stamp.frame); + } + DrawStamp (&Stamp); + } + else if (delta_status_flags & RIGHT) + { + Stamp.frame = CSPtr->turn; + Stamp.frame = IncFrameIndex (Stamp.frame); + if (Pass == 2) + { + if (cur_status_flags & RIGHT) + Stamp.frame = DecFrameIndex (Stamp.frame); + else + Stamp.frame = IncFrameIndex (Stamp.frame); + } + DrawStamp (&Stamp); + } + + if (delta_status_flags & THRUST) + { + Stamp.frame = CSPtr->thrust; + if (Pass == 1) + Stamp.frame = IncFrameIndex (Stamp.frame); + else if (cur_status_flags & THRUST) + Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); + DrawStamp (&Stamp); + } + if (delta_status_flags & WEAPON) + { + Stamp.frame = CSPtr->weapon; + if (Pass == 1) + Stamp.frame = IncFrameIndex (Stamp.frame); + else if (cur_status_flags & WEAPON) + Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); + DrawStamp (&Stamp); + } + if (delta_status_flags & SPECIAL) + { + Stamp.frame = CSPtr->special; + if (Pass == 1) + Stamp.frame = IncFrameIndex (Stamp.frame); + else if (cur_status_flags & SPECIAL) + Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); + DrawStamp (&Stamp); + } +} + +void +DrawBattleCrewAmount (BOOLEAN CountPlayer) +{ +#define MAX_CREW_DIGITS 3 + RECT r; + TEXT t; + UNICODE buf[10]; + + t.baseline.x = 10; + t.baseline.y = 168; + t.align = ALIGN_LEFT; + t.pStr = buf; + t.CharCount = (COUNT)~0; + + r.corner.x = t.baseline.x; + r.corner.y = t.baseline.y - 5; + r.extent.width = 6 * MAX_CREW_DIGITS + 1; + r.extent.height = 5; + + wsprintf (buf, "%u", + GLOBAL_SIS (CrewEnlisted) + + (CountPlayer ? 1 : 0)); + SetContextFont (StarConFont); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawFilledRectangle (&r); + SetContextForeGroundColor (BLACK_COLOR); + DrawText (&t); +} + +void +DrawCaptainsWindow (STARSHIPPTR StarShipPtr) +{ + COORD y, y_offs; + RECT r; + STAMP s; + FRAME Frame; + RACE_DESCPTR RDPtr; + + RDPtr = StarShipPtr->RaceDescPtr; + Frame = RDPtr->ship_data.captain_control.background; + if (Frame) + { + Frame = SetAbsFrameIndex (Frame, 0); + RDPtr->ship_data.captain_control.background = Frame; + Frame = SetRelFrameIndex (Frame, 1); + RDPtr->ship_data.captain_control.turn = Frame; + Frame = SetRelFrameIndex (Frame, 5); + RDPtr->ship_data.captain_control.thrust = Frame; + Frame = SetRelFrameIndex (Frame, 3); + RDPtr->ship_data.captain_control.weapon = Frame; + Frame = SetRelFrameIndex (Frame, 3); + RDPtr->ship_data.captain_control.special = Frame; + } + + BatchGraphics (); + + y_offs = CAPTAIN_YOFFS + + ((RDPtr->ship_info.ship_flags & GOOD_GUY) ? + GOOD_GUY_YOFFS : BAD_GUY_YOFFS); + r.corner.x = CAPTAIN_XOFFS - 2; + r.corner.y = y_offs - 4; + r.extent.width = STATUS_WIDTH - CAPTAIN_XOFFS; + r.extent.height = SHIP_STATUS_HEIGHT - CAPTAIN_YOFFS + 2; + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0xA, 0xA, 0xA), 0x08)); + DrawFilledRectangle (&r); + + y = y_offs - CAPTAIN_YOFFS; + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.x = 1; + r.corner.y = SHIP_INFO_HEIGHT + y; + r.extent.width = 1; + r.extent.height = (SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT - 2); + DrawFilledRectangle (&r); + r.corner.x = 0; + ++r.extent.height; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = STATUS_WIDTH - 1; + r.corner.y = SHIP_INFO_HEIGHT + y; + r.extent.width = 1; + r.extent.height = SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT; + DrawFilledRectangle (&r); + r.corner.x = STATUS_WIDTH - 2; + DrawFilledRectangle (&r); + r.corner.x = 1; + r.extent.width = STATUS_WIDTH - 2; + r.corner.y = (SHIP_STATUS_HEIGHT - 2) + y; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = 0; + ++r.extent.width; + ++r.corner.y; + DrawFilledRectangle (&r); + + { + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F)); + r.corner.x = 59; + r.corner.y = y_offs; + r.extent.width = 1; + r.extent.height = 30; + DrawFilledRectangle (&r); + r.corner.x = 3; + r.corner.y += 30; + r.extent.width = 57; + r.extent.height = 1; + DrawFilledRectangle (&r); + + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); + r.corner.x = 3; + r.extent.width = 57; + r.corner.y = y_offs - 1; + r.extent.height = 1; + DrawFilledRectangle (&r); + r.corner.x = 3; + r.extent.width = 1; + r.corner.y = y_offs; + r.extent.height = 30; + DrawFilledRectangle (&r); + + s.frame = RDPtr->ship_data.captain_control.background; + s.origin.x = CAPTAIN_XOFFS; + s.origin.y = y_offs; + DrawStamp (&s); + } + + if (StarShipPtr->captains_name_index == 0) + { + if (RDPtr->ship_info.ship_flags & GOOD_GUY) + { + TEXT t; + + t.baseline.x = STATUS_WIDTH >> 1; + t.baseline.y = y_offs + 6; + t.align = ALIGN_CENTER; + t.pStr = GLOBAL_SIS (CommanderName); + t.CharCount = (COUNT)~0; + DrawBattleCrewAmount (TRUE); + SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); + SetContextFont (TinyFont); + DrawText (&t); + } + } + + UnbatchGraphics (); +} + +BOOLEAN +DeltaEnergy (ELEMENTPTR ElementPtr, SIZE energy_delta) +{ + BOOLEAN retval; + STARSHIPPTR StarShipPtr; + SHIP_INFOPTR ShipInfoPtr; + + retval = TRUE; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; + if (energy_delta >= 0) + { + if ((BYTE)(ShipInfoPtr->energy_level + (BYTE)energy_delta) > + ShipInfoPtr->max_energy) + energy_delta = ShipInfoPtr->max_energy + - ShipInfoPtr->energy_level; + } + else + { + if ((BYTE)-energy_delta > ShipInfoPtr->energy_level) + { + retval = FALSE; + } + } + + if (!retval) + StarShipPtr->cur_status_flags |= LOW_ON_ENERGY; + else + { + StarShipPtr->cur_status_flags &= ~LOW_ON_ENERGY; + StarShipPtr->energy_counter = + StarShipPtr->RaceDescPtr->characteristics.energy_wait; + + DeltaStatistics (StarShipPtr, 0, energy_delta); + } + + return (retval); +} + +BOOLEAN +DeltaCrew (ELEMENTPTR ElementPtr, SIZE crew_delta) +{ + BOOLEAN retval; + STARSHIPPTR StarShipPtr; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE + && (ElementPtr->state_flags & BAD_GUY)) + return (TRUE); /* Samatra can't be crew-modified */ + + retval = TRUE; + GetElementStarShip (ElementPtr, &StarShipPtr); + if (crew_delta > 0) + { + SHIP_INFOPTR ShipInfoPtr; + + ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; + if ((ElementPtr->crew_level += (BYTE)crew_delta) > + ShipInfoPtr->max_crew) + { + crew_delta = ShipInfoPtr->max_crew + - ShipInfoPtr->crew_level; + ElementPtr->crew_level = + ShipInfoPtr->max_crew; + } + } + else if (crew_delta < 0) + { + if (ElementPtr->crew_level > (BYTE)-crew_delta) + ElementPtr->crew_level += (BYTE)crew_delta; + else + { + crew_delta = -(SIZE)ElementPtr->crew_level; + ElementPtr->crew_level = 0; + retval = FALSE; + } + } + + DeltaStatistics (StarShipPtr, crew_delta, 0); + + return (retval); +} + +void +PreProcessStatus (PELEMENT ShipPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->captains_name_index + || (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY)) + { + register ELEMENT_FLAGS old_status_flags, cur_status_flags; + CAPTAIN_STUFFPTR CSPtr; + + cur_status_flags = StarShipPtr->cur_status_flags; + old_status_flags = StarShipPtr->old_status_flags; + old_status_flags ^= cur_status_flags; + + CSPtr = &StarShipPtr->RaceDescPtr->ship_data.captain_control; + old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + if (old_status_flags) + { + CaptainsWindow (CSPtr, + (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY) ? + GOOD_GUY_YOFFS : BAD_GUY_YOFFS, + old_status_flags, cur_status_flags, 1); + } + } +} + +void +PostProcessStatus (PELEMENT ShipPtr) +{ + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->captains_name_index + || (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY)) + { + COORD y; + register ELEMENT_FLAGS cur_status_flags, old_status_flags; + + + cur_status_flags = StarShipPtr->cur_status_flags; + + y = (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY) ? + GOOD_GUY_YOFFS : BAD_GUY_YOFFS; + + if (ShipPtr->crew_level == 0) + { + StarShipPtr->cur_status_flags &= + ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + + if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + { +#define CAPTAIN_WIDTH 55 +#define CAPTAIN_HEIGHT 30 + BYTE i; + COLOR c; + RECT r; + + i = (BYTE)(NUM_EXPLOSION_FRAMES * 3 - 1) - ShipPtr->life_span; + if (i <= 4) + { + COLOR flash_tab0[] = + { + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), + }; + + c = flash_tab0[i]; + r.corner.x = CAPTAIN_XOFFS; + r.corner.y = y + CAPTAIN_YOFFS; + r.extent.width = CAPTAIN_WIDTH; + r.extent.height = CAPTAIN_HEIGHT; + } + else + { + SetContextForeGroundColor (BLACK_COLOR); + if ((i -= 5) <= 14) + { + COLOR flash_tab1[] = + { + BUILD_COLOR (MAKE_RGB15 (0x1E, 0x1F, 0x12), 0x70), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0xA), 0x0E), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7C), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7D), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7E), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7F), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + }; + + c = flash_tab1[i]; + r.corner.x = CAPTAIN_XOFFS + i; + r.corner.y = y + CAPTAIN_YOFFS + i; + r.extent.width = CAPTAIN_WIDTH - (i << 1); + r.extent.height = CAPTAIN_HEIGHT - (i << 1); + if (r.extent.height == 2) + ++r.extent.height; + DrawRectangle (&r); + ++r.corner.x; + ++r.corner.y; + r.extent.width -= 2; + r.extent.height -= 2; + } + else if ((i -= 15) <= 4) + { + r.corner.y = y + (CAPTAIN_YOFFS + 15); + r.extent.width = i + 1; + r.extent.height = 1; + switch (i) + { + case 0: + r.corner.x = CAPTAIN_XOFFS + 15; + i = CAPTAIN_WIDTH - ((15 + 1) << 1); + c = BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C); + break; + case 1: + r.corner.x = CAPTAIN_XOFFS + 16; + i = CAPTAIN_WIDTH - ((17 + 1) << 1); + c = BUILD_COLOR (MAKE_RGB15 (0x7, 0x00, 0x00), 0x2F); + break; + case 2: + r.corner.x = CAPTAIN_XOFFS + 18; + i = CAPTAIN_WIDTH - ((20 + 1) << 1); + c = BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A); + break; + case 3: + r.corner.x = CAPTAIN_XOFFS + 21; + i = CAPTAIN_WIDTH - ((24 + 1) << 1); + c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x29); + break; + case 4: + r.corner.x = CAPTAIN_XOFFS + 25; + i = 1; + r.extent.width = 2; + c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x50, 0x5), 0x28); + break; + } + DrawFilledRectangle (&r); + r.corner.x += i + r.extent.width; + DrawFilledRectangle (&r); + r.corner.x -= i; + r.extent.width = i; + } + else + { + if ((i -= 5) > 2) + c = BLACK_COLOR; + else + { + COLOR flash_tab2[] = + { + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2D), + BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2E), + }; + + c = flash_tab2[i]; + } + r.corner.x = CAPTAIN_XOFFS + + (CAPTAIN_WIDTH >> 1); + r.corner.y = y + CAPTAIN_YOFFS + + ((CAPTAIN_HEIGHT + 1) >> 1); + r.extent.width = 1; + r.extent.height = 1; + } + } + SetContextForeGroundColor (c); + DrawFilledRectangle (&r); + } + } + + old_status_flags = StarShipPtr->old_status_flags; + old_status_flags = (old_status_flags ^ cur_status_flags) & + (LEFT | RIGHT | THRUST | WEAPON | SPECIAL | LOW_ON_ENERGY); + + if (old_status_flags) + { + if (old_status_flags & LOW_ON_ENERGY) + { + if (!(cur_status_flags & LOW_ON_ENERGY)) + DrawCrewFuelString (y, 1); + else + DrawCrewFuelString (y, -1); + } + + old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + if (old_status_flags) + { + CaptainsWindow ( + &StarShipPtr->RaceDescPtr->ship_data.captain_control, + y, old_status_flags, cur_status_flags, 2); + } + } + + StarShipPtr->old_status_flags = cur_status_flags; + } +} + diff --git a/sc2/src/sc2code/tactrans.c b/sc2/src/sc2code/tactrans.c new file mode 100644 index 000000000..6482f6a57 --- /dev/null +++ b/sc2/src/sc2code/tactrans.c @@ -0,0 +1,575 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +BOOLEAN +OpponentAlive (STARSHIPPTR TestStarShipPtr) +{ + HELEMENT hElement, hSuccElement; + + for (hElement = GetHeadElement (); hElement; hElement = hSuccElement) + { + ELEMENTPTR ElementPtr; + STARSHIPPTR StarShipPtr; + + LockElement (hElement, &ElementPtr); + hSuccElement = GetSuccElement (ElementPtr); + GetElementStarShip (ElementPtr, &StarShipPtr); + UnlockElement (hElement); + + if (StarShipPtr + && StarShipPtr != TestStarShipPtr + && StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + { + return (FALSE); + } + } + + return (TRUE); +} + +void +new_ship (PELEMENT DeadShipPtr) +{ + STARSHIPPTR DeadStarShipPtr; + + ProcessSound ((SOUND)~0); + + GetElementStarShip (DeadShipPtr, &DeadStarShipPtr); + if (!(DeadShipPtr->state_flags & PLAYER_SHIP)) + { + if (DeadShipPtr->life_span) /* must be pre-processing */ + return; + } + else + { + BOOLEAN MusicStarted; + HELEMENT hElement, hSuccElement; + + DeadStarShipPtr->ShipFacing = + DeadStarShipPtr->RaceDescPtr->ship_info.var2; + DeadStarShipPtr->special_counter = + DeadStarShipPtr->RaceDescPtr->ship_info.crew_level; + if (DeadStarShipPtr) + { + StopMusic (); + DeadStarShipPtr->RaceDescPtr->ship_info.crew_level = 0; + } + + MusicStarted = FALSE; + DeadShipPtr->turn_wait = (BYTE)( + DeadShipPtr->state_flags & (GOOD_GUY | BAD_GUY) + ); + for (hElement = GetHeadElement (); hElement; hElement = hSuccElement) + { + ELEMENTPTR ElementPtr; + STARSHIPPTR StarShipPtr; + + LockElement (hElement, &ElementPtr); + hSuccElement = GetSuccElement (ElementPtr); + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr == DeadStarShipPtr) + { + SetElementStarShip (ElementPtr, 0); + + if (!(ElementPtr->state_flags & CREW_OBJECT) + || ElementPtr->preprocess_func != crew_preprocess) + { + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + ElementPtr->life_span = 0; + ElementPtr->state_flags = + NONSOLID | DISAPPEARING | FINITE_LIFE; + ElementPtr->preprocess_func = + ElementPtr->postprocess_func = + ElementPtr->death_func = 0; + ElementPtr->collision_func = 0; + } + } + + if (StarShipPtr + && (StarShipPtr->cur_status_flags & PLAY_VICTORY_DITTY)) + { + MusicStarted = TRUE; + PlayMusic ((MUSIC_REF)StarShipPtr->RaceDescPtr-> + ship_data.victory_ditty, FALSE, 3); + StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY; + } + + UnlockElement (hElement); + } + + DeadShipPtr->life_span = MusicStarted ? + (ONE_SECOND * 3) / BATTLE_FRAME_RATE : 1; + DeadShipPtr->death_func = new_ship; + DeadShipPtr->preprocess_func = new_ship; + SetElementStarShip (DeadShipPtr, DeadStarShipPtr); + } + + if (DeadShipPtr->life_span +#if !DEMO_MODE + || PLRPlaying ((MUSIC_REF)~0) +#endif /* DEMO_MODE */ + ) + { + DeadShipPtr->state_flags &= ~DISAPPEARING; + ++DeadShipPtr->life_span; + } + else + { + BOOLEAN RestartMusic; + + StopMusic (); + StopSound (); + + SetElementStarShip (DeadShipPtr, 0); + RestartMusic = OpponentAlive (DeadStarShipPtr); + + free_ship (DeadStarShipPtr, TRUE); +UnbatchGraphics (); + if (GetNextStarShip (DeadStarShipPtr, + WHICH_SIDE (DeadShipPtr->turn_wait)) && RestartMusic) + BattleSong (TRUE); + else if (LOBYTE (battle_counter) == 0 + || HIBYTE (battle_counter) == 0) + GLOBAL (CurrentActivity) &= ~IN_BATTLE; +BatchGraphics (); + } +} + +void +explosion_preprocess (PELEMENT ShipPtr) +{ + BYTE i; + + i = (NUM_EXPLOSION_FRAMES * 3) - ShipPtr->life_span; + switch (i) + { + case 25: + ShipPtr->preprocess_func = NULL_PTR; + case 0: + case 1: + case 2: + case 20: + case 21: + case 22: + case 23: + case 24: + i = 1; + break; + case 3: + case 4: + case 5: + case 18: + case 19: + i = 2; + break; + case 15: + SetPrimType (&DisplayArray[ShipPtr->PrimIndex], NO_PRIM); + ShipPtr->state_flags |= CHANGING; + default: + i = 3; + break; + } + + do + { + HELEMENT hElement; + + hElement = AllocElement (); + if (hElement) + { + COUNT angle, dist; + DWORD rand_val; + ELEMENTPTR ElementPtr; + extern FRAME explosion[]; + + PutElement (hElement); + LockElement (hElement, &ElementPtr); + ElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + ElementPtr->life_span = 9; + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); + ElementPtr->current.image.farray = explosion; + ElementPtr->current.image.frame = explosion[0]; + rand_val = Random (); + angle = LOBYTE (HIWORD (rand_val)); + dist = DISPLAY_TO_WORLD (LOBYTE (LOWORD (rand_val)) % 8); + if (HIBYTE (LOWORD (rand_val)) < 256 * 1 / 3) + dist += DISPLAY_TO_WORLD (8); + ElementPtr->current.location.x = + ShipPtr->current.location.x + + COSINE (angle, dist); + ElementPtr->current.location.y = + ShipPtr->current.location.y + + SINE (angle, dist); + ElementPtr->preprocess_func = animation_preprocess; + rand_val = Random (); + angle = LOBYTE (LOWORD (rand_val)); + dist = WORLD_TO_VELOCITY ( + DISPLAY_TO_WORLD (HIBYTE (LOWORD (rand_val)) % 5) + ); + SetVelocityComponents (&ElementPtr->velocity, + COSINE (angle, dist), + SINE (angle, dist)); + UnlockElement (hElement); + } + } while (--i); +} + +void +ship_death (PELEMENT ShipPtr) +{ + STARSHIPPTR StarShipPtr, VictoriousStarShipPtr; + HELEMENT hElement, hNextElement; + ELEMENTPTR ElementPtr; + + StopMusic (); + + if (ShipPtr->mass_points <= MAX_SHIP_MASS) + { + if (WHICH_SIDE (ShipPtr->state_flags)) + battle_counter -= MAKE_WORD (0, 1); + else + battle_counter -= MAKE_WORD (1, 0); + } + + VictoriousStarShipPtr = 0; + for (hElement = GetHeadElement (); hElement; hElement = hNextElement) + { + LockElement (hElement, &ElementPtr); + if ((ElementPtr->state_flags & PLAYER_SHIP) + && ElementPtr != (ELEMENTPTR)ShipPtr + /* and not running away */ + && ElementPtr->mass_points <= MAX_SHIP_MASS) + { + GetElementStarShip (ElementPtr, &VictoriousStarShipPtr); + if (VictoriousStarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + VictoriousStarShipPtr = 0; + else + VictoriousStarShipPtr->cur_status_flags |= PLAY_VICTORY_DITTY; + + UnlockElement (hElement); + break; + } + hNextElement = GetSuccElement (ElementPtr); + UnlockElement (hElement); + } + + GetElementStarShip (ShipPtr, &StarShipPtr); + StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY; + + DeltaEnergy ((ELEMENTPTR)ShipPtr, + -(SIZE)StarShipPtr->RaceDescPtr->ship_info.energy_level); + + ShipPtr->life_span = NUM_EXPLOSION_FRAMES * 3; + ShipPtr->state_flags &= ~DISAPPEARING; + ShipPtr->state_flags |= FINITE_LIFE | NONSOLID; + ShipPtr->postprocess_func = PostProcessStatus; + ShipPtr->death_func = new_ship; + ShipPtr->hTarget = 0; + ZeroVelocityComponents (&((ELEMENTPTR)ShipPtr)->velocity); + if (ShipPtr->crew_level) /* only happens for shofixti self-destruct */ + { + + PlaySound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1 + ), GAME_SOUND_PRIORITY + 1); + + DeltaCrew ((ELEMENTPTR)ShipPtr, -(SIZE)ShipPtr->crew_level); + if (VictoriousStarShipPtr == 0) + StarShipPtr->cur_status_flags |= PLAY_VICTORY_DITTY; + } + else + { + ShipPtr->preprocess_func = explosion_preprocess; + + PlaySound (SetAbsSoundIndex (GameSounds, SHIP_EXPLODES), + GAME_SOUND_PRIORITY + 1); + } +} + +#define START_ION_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) + +void +spawn_ion_trail (PELEMENT ElementPtr) +{ + + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hIonElement; + + hIonElement = AllocElement (); + if (hIonElement) + { +#define ION_LIFE 1 + COUNT angle; + RECT r; + ELEMENTPTR IonElementPtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; + GetFrameRect (StarShipPtr->RaceDescPtr->ship_data.ship[0], &r); + r.extent.height = DISPLAY_TO_WORLD (r.extent.height + r.corner.y); + + InsertElement (hIonElement, GetHeadElement ()); + LockElement (hIonElement, &IonElementPtr); + IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + IonElementPtr->life_span = IonElementPtr->thrust_wait = ION_LIFE; + SetPrimType (&DisplayArray[IonElementPtr->PrimIndex], POINT_PRIM); + SetPrimColor ( + &DisplayArray[IonElementPtr->PrimIndex], START_ION_COLOR + ); + IonElementPtr->current.image.frame = DecFrameIndex (stars_in_space); + IonElementPtr->current.image.farray = &stars_in_space; + IonElementPtr->current.location = ElementPtr->current.location; + IonElementPtr->current.location.x += + (COORD)COSINE (angle, r.extent.height); + IonElementPtr->current.location.y += + (COORD)SINE (angle, r.extent.height); + IonElementPtr->death_func = spawn_ion_trail; + + SetElementStarShip (IonElementPtr, StarShipPtr); + + { + /* normally done during preprocess, but because + * object is being inserted at head rather than + * appended after tail it may never get preprocessed. + */ + IonElementPtr->next = IonElementPtr->current; + --IonElementPtr->life_span; + IonElementPtr->state_flags |= PRE_PROCESS; + } + + UnlockElement (hIonElement); + } + } + else + { + COLOR color_tab[] = + { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), + BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), + BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), + BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), + BUILD_COLOR (MAKE_RGB15 (0xF, 0x00, 0x00), 0x2e), + BUILD_COLOR (MAKE_RGB15 (0xB, 0x00, 0x00), 0x2f), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xE, 0x00), 0x7c), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0xA, 0x00), 0x7d), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x7, 0x00), 0x7e), + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x3, 0x00), 0x7f), }; +#define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) + + COUNT color_index = 0; + COLOR Color; + + Color = COLOR_256 (GetPrimColor (&DisplayArray[ElementPtr->PrimIndex])); + if (Color != 0x2F) + { + ElementPtr->life_span = ElementPtr->thrust_wait; + + ++Color; + if (Color > 0x7F) + Color = 0x2A; + if (Color <= 0x2f && Color >= 0x2a) + color_index = Color - 0x2a; + else /* color is between 0x7a and 0x7f */ + color_index = (Color - 0x7a) + (NUM_TAB_COLORS >> 1); + SetPrimColor ( + &DisplayArray[ElementPtr->PrimIndex], color_tab[color_index] + ); + + ElementPtr->state_flags &= ~DISAPPEARING; + ElementPtr->state_flags |= CHANGING; + } + } +} + +void +ship_transition (PELEMENT ElementPtr) +{ + if (ElementPtr->state_flags & PLAYER_SHIP) + { + if (ElementPtr->state_flags & APPEARING) + { + ElementPtr->life_span = HYPERJUMP_LIFE; + ElementPtr->preprocess_func = ship_transition; + ElementPtr->postprocess_func = NULL_PTR; + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; + } + else if (ElementPtr->life_span < HYPERJUMP_LIFE) + { + if (ElementPtr->life_span == NORMAL_LIFE + && ElementPtr->crew_level) + { + ElementPtr->current.image.frame = + ElementPtr->next.image.frame = + SetEquFrameIndex ( + ElementPtr->current.image.farray[0], + ElementPtr->current.image.frame); + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); + InitIntersectStartPoint (ElementPtr); + InitIntersectEndPoint (ElementPtr); + InitIntersectFrame (ElementPtr); + ZeroVelocityComponents (&((ELEMENTPTR)ElementPtr)->velocity); + ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->preprocess_func = ship_preprocess; + ElementPtr->postprocess_func = ship_postprocess; + } + + return; + } + } + + { + HELEMENT hShipImage; + ELEMENTPTR ShipImagePtr; + STARSHIPPTR StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + LockElement (StarShipPtr->hShip, &ShipImagePtr); + + if (!(ShipImagePtr->state_flags & NONSOLID)) + { + ElementPtr->preprocess_func = NULL_PTR; + } + else if ((hShipImage = AllocElement ())) + { +#define TRANSITION_SPEED DISPLAY_TO_WORLD (40) +#define TRANSITION_LIFE 1 + COUNT angle; + + PutElement (hShipImage); + + angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); + + LockElement (hShipImage, &ShipImagePtr); + ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; + ShipImagePtr->life_span = ShipImagePtr->thrust_wait = TRANSITION_LIFE; + SetPrimType (&DisplayArray[ShipImagePtr->PrimIndex], STAMPFILL_PRIM); + SetPrimColor ( + &DisplayArray[ShipImagePtr->PrimIndex], START_ION_COLOR + ); + ShipImagePtr->current.image = ElementPtr->current.image; + ShipImagePtr->current.location = ElementPtr->current.location; + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + { + ShipImagePtr->current.location.x += + COSINE (angle, TRANSITION_SPEED); + ShipImagePtr->current.location.y += + SINE (angle, TRANSITION_SPEED); + ElementPtr->preprocess_func = NULL_PTR; + } + else if (ElementPtr->crew_level) + { + ShipImagePtr->current.location.x -= + COSINE (angle, TRANSITION_SPEED) + * (ElementPtr->life_span - 1); + ShipImagePtr->current.location.y -= + SINE (angle, TRANSITION_SPEED) + * (ElementPtr->life_span - 1); + + ShipImagePtr->current.location.x = + WRAP_X (ShipImagePtr->current.location.x); + ShipImagePtr->current.location.y = + WRAP_Y (ShipImagePtr->current.location.y); + } + ShipImagePtr->preprocess_func = ship_transition; + ShipImagePtr->death_func = spawn_ion_trail; + SetElementStarShip (ShipImagePtr, StarShipPtr); + + UnlockElement (hShipImage); + } + + UnlockElement (StarShipPtr->hShip); + } +} + +void +flee_preprocess (PELEMENT ElementPtr) +{ + STARSHIPPTR StarShipPtr; + + if (--ElementPtr->turn_wait == 0) + { + SIZE dir; + COLOR c; + COLOR color_tab[] = + { + BUILD_COLOR (MAKE_RGB15 (31, 25, 25), 0x24), + BUILD_COLOR (MAKE_RGB15 (31, 19, 19), 0x25), + BUILD_COLOR (MAKE_RGB15 (31, 15, 15), 0x26), + BUILD_COLOR (MAKE_RGB15 (31, 10, 10), 0x27), + BUILD_COLOR (MAKE_RGB15 (31, 4, 4), 0x28), + BUILD_COLOR (MAKE_RGB15 (31, 0, 0), 0x29), + BUILD_COLOR (MAKE_RGB15 (27, 0, 0), 0x2A), + BUILD_COLOR (MAKE_RGB15 (23, 0, 0), 0x2B), + BUILD_COLOR (MAKE_RGB15 (19, 0, 0), 0x2C), + BUILD_COLOR (MAKE_RGB15 (14, 0, 0), 0x2D), + BUILD_COLOR (MAKE_RGB15 (10, 0, 0), 0x2E), + }; + + dir = HINIBBLE (ElementPtr->thrust_wait) - 1; + + c = COLOR_256 (GetPrimColor (&DisplayArray[ElementPtr->PrimIndex])); + if (c == 0x24) + dir = -dir; + c += dir; + c = color_tab[c - 0x24]; + SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], c); + + if (COLOR_256 (c) == 0x2E) + { + dir = -dir; + --ElementPtr->thrust_wait; + } + dir += 1; + + ElementPtr->turn_wait = LONIBBLE (ElementPtr->thrust_wait); + if (ElementPtr->turn_wait) + { + ElementPtr->thrust_wait = MAKE_BYTE (ElementPtr->turn_wait, dir); + ElementPtr->turn_wait = ((ElementPtr->turn_wait - 1) >> 1) + 1; + } + else if (COLOR_256 (c) != 0x24) + { + ElementPtr->thrust_wait = MAKE_BYTE (0, dir); + ElementPtr->turn_wait = 1; + } + else + { + ElementPtr->death_func = new_ship; + ElementPtr->crew_level = 0; + + ElementPtr->life_span = HYPERJUMP_LIFE + 1; + ElementPtr->preprocess_func = ship_transition; + ElementPtr->postprocess_func = NULL_PTR; + SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); + ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; + } + } + + GetElementStarShip (ElementPtr, &StarShipPtr); + StarShipPtr->cur_status_flags + &= ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); + PreProcessStatus (ElementPtr); +} diff --git a/sc2/src/sc2code/test.c b/sc2/src/sc2code/test.c new file mode 100644 index 000000000..42e9b8ea3 --- /dev/null +++ b/sc2/src/sc2code/test.c @@ -0,0 +1,25 @@ +#include +#include +#include "sndlib.h" +#include "SDL_wrapper.h" + +int +main (int argc, char *argv[]) +{ + InitSound (argc, argv); + + while (1) + { + COUNT sound_index; + + printf ("Sound #: "); + if (fscanf (stdin, "%u", &sound_index) != 1) + break; + + PlaySound (sound_index, GAME_SOUND_PRIORITY); + } + + UninitSound (); + + exit (EXIT_SUCCESS); +} diff --git a/sc2/src/sc2code/trans.c b/sc2/src/sc2code/trans.c new file mode 100644 index 000000000..35dee117d --- /dev/null +++ b/sc2/src/sc2code/trans.c @@ -0,0 +1,152 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +SIZE sinetab[] = +{ + -FLT_ADJUST (1.000000), + -FLT_ADJUST (0.995185), + -FLT_ADJUST (0.980785), + -FLT_ADJUST (0.956940), + -FLT_ADJUST (0.923880), + -FLT_ADJUST (0.881921), + -FLT_ADJUST (0.831470), + -FLT_ADJUST (0.773010), + -FLT_ADJUST (0.707107), + -FLT_ADJUST (0.634393), + -FLT_ADJUST (0.555570), + -FLT_ADJUST (0.471397), + -FLT_ADJUST (0.382683), + -FLT_ADJUST (0.290285), + -FLT_ADJUST (0.195090), + -FLT_ADJUST (0.098017), + FLT_ADJUST (0.000000), + FLT_ADJUST (0.098017), + FLT_ADJUST (0.195090), + FLT_ADJUST (0.290285), + FLT_ADJUST (0.382683), + FLT_ADJUST (0.471397), + FLT_ADJUST (0.555570), + FLT_ADJUST (0.634393), + FLT_ADJUST (0.707107), + FLT_ADJUST (0.773010), + FLT_ADJUST (0.831470), + FLT_ADJUST (0.881921), + FLT_ADJUST (0.923880), + FLT_ADJUST (0.956940), + FLT_ADJUST (0.980785), + FLT_ADJUST (0.995185), + FLT_ADJUST (1.000000), + FLT_ADJUST (0.995185), + FLT_ADJUST (0.980785), + FLT_ADJUST (0.956940), + FLT_ADJUST (0.923880), + FLT_ADJUST (0.881921), + FLT_ADJUST (0.831470), + FLT_ADJUST (0.773010), + FLT_ADJUST (0.707107), + FLT_ADJUST (0.634393), + FLT_ADJUST (0.555570), + FLT_ADJUST (0.471397), + FLT_ADJUST (0.382683), + FLT_ADJUST (0.290285), + FLT_ADJUST (0.195090), + FLT_ADJUST (0.098017), + FLT_ADJUST (0.000000), + -FLT_ADJUST (0.098017), + -FLT_ADJUST (0.195090), + -FLT_ADJUST (0.290285), + -FLT_ADJUST (0.382683), + -FLT_ADJUST (0.471397), + -FLT_ADJUST (0.555570), + -FLT_ADJUST (0.634393), + -FLT_ADJUST (0.707107), + -FLT_ADJUST (0.773010), + -FLT_ADJUST (0.831470), + -FLT_ADJUST (0.881921), + -FLT_ADJUST (0.923880), + -FLT_ADJUST (0.956940), + -FLT_ADJUST (0.980785), + -FLT_ADJUST (0.995185), +}; + +COUNT +ARCTAN (SIZE delta_x, SIZE delta_y) +{ + register SIZE v1, v2; + static COUNT atantab[] = + { + 0, + 0, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 6, + 6, + 6, + 6, + 7, + 7, + 7, + 7, + 7, + 7, + 8, + 8, + 8, + }; + + v1 = delta_x; + v2 = delta_y; + if (v1 == 0 && v2 == 0) + return (FULL_CIRCLE); + + if (v1 < 0) + v1 = -v1; + if (v2 < 0) + v2 = -v2; + if (v1 > v2) + v1 = QUADRANT + - atantab[(((DWORD)v2 << (CIRCLE_SHIFT - 1)) + (v1 >> 1)) / v1]; + else + v1 = atantab[(((DWORD)v1 << (CIRCLE_SHIFT - 1)) + (v2 >> 1)) / v2]; + + if (delta_x < 0) + v1 = FULL_CIRCLE - v1; + if (delta_y > 0) + v1 = HALF_CIRCLE - v1; + + return (NORMALIZE_ANGLE (v1)); +} + diff --git a/sc2/src/sc2code/units.h b/sc2/src/sc2code/units.h new file mode 100644 index 000000000..03510676d --- /dev/null +++ b/sc2/src/sc2code/units.h @@ -0,0 +1,138 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UNITS_H +#define _UNITS_H + +#define ZOOM_SHIFT 8 +#define MAX_ZOOM_OUT (4 << ZOOM_SHIFT) + +#define MAX_REDUCTION 3 +#define MAX_VIS_REDUCTION 2 +#define REDUCTION_SHIFT 1 +#define NUM_VIEWS (MAX_VIS_REDUCTION + 1) + +#define ONE_SHIFT 2 +#define BACKGROUND_SHIFT 3 +#define SCALED_ONE (1 << ONE_SHIFT) +#define DISPLAY_TO_WORLD(x) ((x)<>ONE_SHIFT) +#define DISPLAY_ALIGN(x) ((COORD)(x)&~(SCALED_ONE-1)) +#define DISPLAY_ALIGN_X(x) ((COORD)((COUNT)(x)%LOG_SPACE_WIDTH)&~(SCALED_ONE-1)) +#define DISPLAY_ALIGN_Y(y) ((COORD)((COUNT)(y)%LOG_SPACE_HEIGHT)&~(SCALED_ONE-1)) + +#define LOG_SPACE_WIDTH \ + (DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_REDUCTION) +#define LOG_SPACE_HEIGHT \ + (DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_REDUCTION) +#define TRANSITION_WIDTH \ + (DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_VIS_REDUCTION) +#define TRANSITION_HEIGHT \ + (DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_VIS_REDUCTION) + +#define MAX_X_UNIVERSE 9999 +#define MAX_Y_UNIVERSE 9999 +#define MAX_X_LOGICAL \ + ((UNIVERSE_TO_LOGX (MAX_X_UNIVERSE + 1) > UNIVERSE_TO_LOGX (-1) ? \ + UNIVERSE_TO_LOGX (MAX_X_UNIVERSE) : UNIVERSE_TO_LOGX (-1)) \ + - 1L) +#define MAX_Y_LOGICAL \ + ((UNIVERSE_TO_LOGY (MAX_Y_UNIVERSE + 1) > UNIVERSE_TO_LOGY (-1) ? \ + UNIVERSE_TO_LOGY (MAX_Y_UNIVERSE) : UNIVERSE_TO_LOGY (-1)) \ + - 1L) +#define SECTOR_WIDTH 195 +#define SECTOR_HEIGHT 25 + +#define SPHERE_RADIUS_INCREMENT 11 + +#define MAX_FLEET_STRENGTH (254 * SPHERE_RADIUS_INCREMENT) + +#define UNIT_SCREEN_WIDTH 63 +#define UNIT_SCREEN_HEIGHT 50 + +#define LOGX_TO_UNIVERSE(lx) \ + (COORD)( \ + ((long)(lx) \ + * ((MAX_X_UNIVERSE + 1) >> 4)) \ + * 10 \ + / ((long)((LOG_SPACE_WIDTH) >> 4) \ + * SECTOR_WIDTH) \ + ) +#define LOGY_TO_UNIVERSE(ly) \ + (COORD)( \ + MAX_Y_UNIVERSE - (COORD)(((long)(ly) \ + * ((MAX_Y_UNIVERSE + 1) >> 4)) \ + / ((long)((LOG_SPACE_HEIGHT) >> 4) \ + * SECTOR_HEIGHT)) \ + ) +#define UNIVERSE_TO_LOGX(ux) \ + ( \ + ((long)(ux) \ + * ((long)((LOG_SPACE_WIDTH) >> 4) * SECTOR_WIDTH) \ + + ((((MAX_X_UNIVERSE + 1) >> 4) * 10) >> 1)) \ + / (((MAX_X_UNIVERSE + 1) >> 4) * 10) \ + ) +#define UNIVERSE_TO_LOGY(uy) \ + ( \ + ((long)(MAX_Y_UNIVERSE - (uy)) \ + * ((long)((LOG_SPACE_HEIGHT) >> 4) * SECTOR_HEIGHT) \ + + (((MAX_Y_UNIVERSE + 1) >> 4) >> 1)) \ + / ((MAX_Y_UNIVERSE + 1) >> 4) \ + ) + +#define CIRCLE_SHIFT 6 +#define FULL_CIRCLE (1 << CIRCLE_SHIFT) +#define OCTANT_SHIFT (CIRCLE_SHIFT - 3) /* (1 << 3) == 8 */ +#define HALF_CIRCLE (FULL_CIRCLE >> 1) +#define QUADRANT (FULL_CIRCLE >> 2) +#define OCTANT (FULL_CIRCLE >> 3) + +#define FACING_SHIFT 4 + +#define ANGLE_TO_FACING(a) (((a)+(1<<(CIRCLE_SHIFT-FACING_SHIFT-1))) \ + >>(CIRCLE_SHIFT-FACING_SHIFT)) +#define FACING_TO_ANGLE(f) ((f)<<(CIRCLE_SHIFT-FACING_SHIFT)) + +#define NORMALIZE_ANGLE(a) ((COUNT)(a)&(FULL_CIRCLE-1)) +#define NORMALIZE_FACING(f) ((COUNT)(f)&((1 << FACING_SHIFT)-1)) + +#define SIN_SHIFT 14 +#define SIN_SCALE (1 << SIN_SHIFT) +#define INT_ADJUST(x) ((x)<>SIN_SHIFT) +#define ROUND(x,y) ((x)+((x)>=0?((y)>>1):-((y)>>1))) + +extern SIZE sinetab[]; +#define SINVAL(a) sinetab[NORMALIZE_ANGLE(a)] +#define COSVAL(a) SINVAL((a)+QUADRANT) +#define SINE(a,m) ((SIZE)((((long)SINVAL(a))*(long)(m))>>SIN_SHIFT)) +#define COSINE(a,m) SINE((a)+QUADRANT,m) +extern COUNT ARCTAN (SIZE delta_x, SIZE delta_y); + +#define WRAP_VAL(v,w) ((COUNT)((v)<0?((v)+(w)):((v)>=(w)?((v)-(w)):(v)))) +#define WRAP_X(x) WRAP_VAL(x,LOG_SPACE_WIDTH) +#define WRAP_Y(y) WRAP_VAL(y,LOG_SPACE_HEIGHT) +#define WRAP_DELTA_X(dx) ((dx)<0 ? \ + ((-(dx)<=LOG_SPACE_WIDTH>>1)?(dx):(LOG_SPACE_WIDTH+(dx))) : \ + (((dx)<=LOG_SPACE_WIDTH>>1)?(dx):((dx)-LOG_SPACE_WIDTH))) +#define WRAP_DELTA_Y(dy) ((dy)<0 ? \ + ((-(dy)<=LOG_SPACE_HEIGHT>>1)?(dy):(LOG_SPACE_HEIGHT+(dy))) : \ + (((dy)<=LOG_SPACE_HEIGHT>>1)?(dy):((dy)-LOG_SPACE_HEIGHT))) +#endif /* _UNITS_H */ + diff --git a/sc2/src/sc2code/utils.c b/sc2/src/sc2code/utils.c new file mode 100644 index 000000000..bc3a1ada9 --- /dev/null +++ b/sc2/src/sc2code/utils.c @@ -0,0 +1,209 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" +#include "commglue.h" +#include "SDL_wrapper.h" + +void +DrawStarConBox (PRECT pRect, SIZE BorderWidth, COLOR TopLeftColor, COLOR + BottomRightColor, BOOLEAN FillInterior, COLOR InteriorColor) +{ + RECT locRect; + + if (BorderWidth == 0) + BorderWidth = 2; + else + { + SetContextForeGroundColor (TopLeftColor); + locRect.corner = pRect->corner; + locRect.extent.width = pRect->extent.width; + locRect.extent.height = 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + ++locRect.corner.y; + locRect.extent.width -= 2; + DrawFilledRectangle (&locRect); + } + + locRect.corner = pRect->corner; + locRect.extent.width = 1; + locRect.extent.height = pRect->extent.height; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + ++locRect.corner.y; + locRect.extent.height -= 2; + DrawFilledRectangle (&locRect); + } + + SetContextForeGroundColor (BottomRightColor); + locRect.corner.x = pRect->corner.x + pRect->extent.width - 1; + locRect.corner.y = pRect->corner.y + 1; + locRect.extent.height = pRect->extent.height - 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + --locRect.corner.x; + ++locRect.corner.y; + locRect.extent.height -= 2; + DrawFilledRectangle (&locRect); + } + + locRect.corner.x = pRect->corner.x; + locRect.extent.width = pRect->extent.width; + locRect.corner.y = pRect->corner.y + pRect->extent.height - 1; + locRect.extent.height = 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + --locRect.corner.y; + locRect.extent.width -= 2; + DrawFilledRectangle (&locRect); + } + } + + if (FillInterior) + { + SetContextForeGroundColor (InteriorColor); + locRect.corner.x = pRect->corner.x + BorderWidth; + locRect.corner.y = pRect->corner.y + BorderWidth; + locRect.extent.width = pRect->extent.width - (BorderWidth << 1); + locRect.extent.height = pRect->extent.height - (BorderWidth << 1); + DrawFilledRectangle (&locRect); + } +} + +DWORD +SeedRandomNumbers (void) +{ + DWORD cur_time; + + SeedRandom (cur_time = GetTimeCounter ()); + + return (cur_time); +} + +void +WaitForNoInput (SIZE Duration) +{ + INPUT_STATE PressState; + + PressState = AnyButtonPress (FALSE); + if (Duration < 0) + { + if (PressState) + return; + Duration = -Duration; + } + else if (!PressState) + return; + + { + DWORD TimeOut; + INPUT_STATE ButtonState; + + TimeOut = GetTimeCounter () + Duration; + do + { + ButtonState = AnyButtonPress (FALSE); + if (PressState) + { + PressState = ButtonState; + ButtonState = 0; + } + } while (!ButtonState && TaskSwitch () <= TimeOut); + } +} + +BOOLEAN +PauseGame (void) +{ + RECT r; + STAMP s; + BOOLEAN ClockActive; + CONTEXT OldContext; + FRAME F; + HOT_SPOT OldHot; + + if (ActivityFrame == 0 + || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_PAUSE)) + || (LastActivity & (CHECK_LOAD | CHECK_RESTART))) + return (FALSE); + + GLOBAL (CurrentActivity) |= CHECK_PAUSE; + + ClockActive = (BOOLEAN)( + LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE + && GameClockRunning () + ); + if (ClockActive) + SuspendGameClock (); + else if (CommData.ConversationPhrases && PlayingTrack ()) + PauseTrack (); + + SetSemaphore (&GraphicsSem); + OldContext = SetContext (ScreenContext); + OldHot = SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); + + GetFrameRect (ActivityFrame, &r); + r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; + r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; + s.origin = r.corner; + s.frame = ActivityFrame; + F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); + DrawStamp (&s); + + FlushGraphics (); + + { + BYTE scan; + + scan = KBDToUNICODE (SK_F1); + while (KeyDown (scan)) + TaskSwitch (); + } + + FlushInput (); + while (KeyHit () != SK_F1) + TaskSwitch (); + + s.frame = F; + DrawStamp (&s); + DestroyDrawable (ReleaseDrawable (s.frame)); + + SetFrameHot (Screen, OldHot); + SetContext (OldContext); + + WaitForNoInput (ONE_SECOND / 4); + FlushInput (); + ClearSemaphore (&GraphicsSem); + + if (ClockActive) + ResumeGameClock (); + else if (CommData.ConversationPhrases && PlayingTrack ()) + ResumeTrack (); + + TaskSwitch (); + GLOBAL (CurrentActivity) &= ~CHECK_PAUSE; + return (TRUE); +} diff --git a/sc2/src/sc2code/velocity.c b/sc2/src/sc2code/velocity.c new file mode 100644 index 000000000..fc73940df --- /dev/null +++ b/sc2/src/sc2code/velocity.c @@ -0,0 +1,152 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "starcon.h" + +#define VELOCITY_REMAINDER(v) ((v) & (VELOCITY_SCALE - 1)) + +void +GetCurrentVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE + pdy) +{ + *pdx = WORLD_TO_VELOCITY (velocityptr->vector.width) + + (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width)); + *pdy = WORLD_TO_VELOCITY (velocityptr->vector.height) + + (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height)); +} + +void +GetNextVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE pdy, + COUNT num_frames) +{ + COUNT e; + + e = (COUNT)((COUNT)velocityptr->error.width + + ((COUNT)velocityptr->fract.width * num_frames)); + *pdx = (velocityptr->vector.width * num_frames) + + ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.width)) + * (e >> VELOCITY_SHIFT)); + velocityptr->error.width = VELOCITY_REMAINDER (e); + + e = (COUNT)((COUNT)velocityptr->error.height + + ((COUNT)velocityptr->fract.height * num_frames)); + *pdy = (velocityptr->vector.height * num_frames) + + ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.height)) + * (e >> VELOCITY_SHIFT)); + velocityptr->error.height = VELOCITY_REMAINDER (e); +} + +void +SetVelocityVector (register VELOCITYPTR velocityptr, register SIZE + magnitude, COUNT facing) +{ + register COUNT angle; + register SIZE dx, dy; + + angle = velocityptr->TravelAngle = + FACING_TO_ANGLE (NORMALIZE_FACING (facing)); + magnitude = WORLD_TO_VELOCITY (magnitude); + dx = COSINE (angle, magnitude); + dy = SINE (angle, magnitude); + if (dx >= 0) + { + velocityptr->vector.width = VELOCITY_TO_WORLD (dx); + velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0); + } + else + { + dx = -dx; + velocityptr->vector.width = -VELOCITY_TO_WORLD (dx); + velocityptr->incr.width = + MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1)); + } + if (dy >= 0) + { + velocityptr->vector.height = VELOCITY_TO_WORLD (dy); + velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0); + } + else + { + dy = -dy; + velocityptr->vector.height = -VELOCITY_TO_WORLD (dy); + velocityptr->incr.height = + MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1)); + } + + velocityptr->fract.width = VELOCITY_REMAINDER (dx); + velocityptr->fract.height = VELOCITY_REMAINDER (dy); + velocityptr->error.width = velocityptr->error.height = 0; +} + +void +SetVelocityComponents (register VELOCITYPTR velocityptr, register SIZE + dx, register SIZE dy) +{ + COUNT angle; + + if ((angle = ARCTAN (dx, dy)) == FULL_CIRCLE) + { + ZeroVelocityComponents (velocityptr); + } + else + { + if (dx >= 0) + { + velocityptr->vector.width = VELOCITY_TO_WORLD (dx); + velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0); + } + else + { + dx = -dx; + velocityptr->vector.width = -VELOCITY_TO_WORLD (dx); + velocityptr->incr.width = + MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1)); + } + if (dy >= 0) + { + velocityptr->vector.height = VELOCITY_TO_WORLD (dy); + velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0); + } + else + { + dy = -dy; + velocityptr->vector.height = -VELOCITY_TO_WORLD (dy); + velocityptr->incr.height = + MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1)); + } + + velocityptr->fract.width = VELOCITY_REMAINDER (dx); + velocityptr->fract.height = VELOCITY_REMAINDER (dy); + velocityptr->error.width = velocityptr->error.height = 0; + } + + velocityptr->TravelAngle = angle; +} + +void +DeltaVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE dy) +{ + + dx += WORLD_TO_VELOCITY (velocityptr->vector.width) + + (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width)); + dy += WORLD_TO_VELOCITY (velocityptr->vector.height) + + (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height)); + + SetVelocityComponents (velocityptr, dx, dy); +} + diff --git a/sc2/src/sc2code/velocity.h b/sc2/src/sc2code/velocity.h new file mode 100644 index 000000000..30146c7c3 --- /dev/null +++ b/sc2/src/sc2code/velocity.h @@ -0,0 +1,56 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VELOCITY_H +#define _VELOCITY_H + +#include /* for memset */ + +typedef struct velocity_desc +{ + COUNT TravelAngle; + EXTENT vector; + EXTENT fract; + EXTENT error; + EXTENT incr; +} VELOCITY_DESC; +typedef VELOCITY_DESC *PVELOCITY; +typedef PVELOCITY VELOCITYPTR; + +#define ZeroVelocityComponents(pv) memset(pv,0,sizeof (*(pv))) +#define GetVelocityTravelAngle(pv) (pv)->TravelAngle + +extern void GetCurrentVelocityComponents (VELOCITYPTR velocityptr, PSIZE + pdx, PSIZE pdy); +extern void GetNextVelocityComponents (VELOCITYPTR velocityptr, PSIZE + pdx, PSIZE pdy, COUNT num_frames); +extern void SetVelocityVector (VELOCITYPTR velocityptr, SIZE magnitude, + COUNT facing); +extern void SetVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE + dy); +extern void DeltaVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, + SIZE dy); + +#define VELOCITY_SHIFT 5 +#define VELOCITY_SCALE (1<>VELOCITY_SHIFT) +#define WORLD_TO_VELOCITY(l) ((l)< +#include "starcon.h" + +HELEMENT +initialize_laser (PLASER_BLOCK pLaserBlock) +{ + HELEMENT hLaserElement; + + hLaserElement = AllocElement (); + if (hLaserElement) + { +#define LASER_LIFE 1 + ELEMENTPTR LaserElementPtr; + + LockElement (hLaserElement, &LaserElementPtr); + LaserElementPtr->hit_points = 1; + LaserElementPtr->mass_points = 1; + LaserElementPtr->state_flags = + APPEARING | FINITE_LIFE | pLaserBlock->sender; + LaserElementPtr->life_span = LASER_LIFE; + LaserElementPtr->collision_func = + (void (*) (struct element *ElementPtr0, PPOINT pPt0, + struct element *ElementPtr1, PPOINT pPt1)) + weapon_collision; + LaserElementPtr->blast_offset = 1; + + LaserElementPtr->current.location.x = pLaserBlock->cx + + COSINE (FACING_TO_ANGLE (pLaserBlock->face), + DISPLAY_TO_WORLD (pLaserBlock->pixoffs)); + LaserElementPtr->current.location.y = pLaserBlock->cy + + SINE (FACING_TO_ANGLE (pLaserBlock->face), + DISPLAY_TO_WORLD (pLaserBlock->pixoffs)); + SetPrimType (&DisplayArray[LaserElementPtr->PrimIndex], LINE_PRIM); + SetPrimColor (&DisplayArray[LaserElementPtr->PrimIndex], pLaserBlock->color); + LaserElementPtr->current.image.frame = DecFrameIndex (stars_in_space); + LaserElementPtr->current.image.farray = &stars_in_space; + SetVelocityComponents (&LaserElementPtr->velocity, + WORLD_TO_VELOCITY ((pLaserBlock->cx + pLaserBlock->ex) + - LaserElementPtr->current.location.x), + WORLD_TO_VELOCITY ((pLaserBlock->cy + pLaserBlock->ey) + - LaserElementPtr->current.location.y)); + UnlockElement (hLaserElement); + } + + return (hLaserElement); +} + +HELEMENT +initialize_missile (PMISSILE_BLOCK pMissileBlock) +{ + HELEMENT hMissileElement; + + hMissileElement = AllocElement (); + if (hMissileElement) + { + SIZE delta_x, delta_y; + COUNT angle; + ELEMENTPTR MissileElementPtr; + + LockElement (hMissileElement, &MissileElementPtr); + MissileElementPtr->hit_points = (BYTE)pMissileBlock->hit_points; + MissileElementPtr->mass_points = (BYTE)pMissileBlock->damage; + MissileElementPtr->state_flags = + APPEARING | FINITE_LIFE | pMissileBlock->sender; + MissileElementPtr->life_span = pMissileBlock->life; + SetPrimType (&DisplayArray[MissileElementPtr->PrimIndex], STAMP_PRIM); + MissileElementPtr->current.image.farray = pMissileBlock->farray; + MissileElementPtr->current.image.frame = + SetAbsFrameIndex (pMissileBlock->farray[0], pMissileBlock->index); + MissileElementPtr->preprocess_func = pMissileBlock->preprocess_func; + MissileElementPtr->collision_func = + (void (*) (struct element + *ElementPtr0, PPOINT + pPt0, struct element + *ElementPtr1, PPOINT + pPt1)) weapon_collision; + MissileElementPtr->blast_offset = (BYTE)pMissileBlock->blast_offs; + + angle = FACING_TO_ANGLE (pMissileBlock->face); + MissileElementPtr->current.location.x = pMissileBlock->cx + + COSINE (angle, + DISPLAY_TO_WORLD (pMissileBlock->pixoffs)); + MissileElementPtr->current.location.y = pMissileBlock->cy + + SINE (angle, + DISPLAY_TO_WORLD (pMissileBlock->pixoffs)); + + delta_x = COSINE (angle, + WORLD_TO_VELOCITY (pMissileBlock->speed)); + delta_y = SINE (angle, + WORLD_TO_VELOCITY (pMissileBlock->speed)); + SetVelocityComponents (&MissileElementPtr->velocity, + delta_x, delta_y); + + MissileElementPtr->current.location.x -= VELOCITY_TO_WORLD (delta_x); + MissileElementPtr->current.location.y -= VELOCITY_TO_WORLD (delta_y); + UnlockElement (hMissileElement); + } + + return (hMissileElement); +} + +HELEMENT +weapon_collision (PELEMENT + WeaponElementPtr, PPOINT + pWPt, PELEMENT + HitElementPtr, PPOINT + pHPt) +{ + SIZE damage; + HELEMENT hBlastElement; + + if (WeaponElementPtr->state_flags & COLLISION) /* if already did effect */ + return ((HELEMENT)0); + + damage = (SIZE)WeaponElementPtr->mass_points; + if (damage + && ((HitElementPtr->state_flags & FINITE_LIFE) + || HitElementPtr->life_span == NORMAL_LIFE)) +#ifdef NEVER + && + /* lasers from the same ship can't hit each other */ + (GetPrimType (&DisplayArray[HitElementPtr->PrimIndex]) != LINE_PRIM + || GetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex]) != LINE_PRIM + || (HitElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) != + (WeaponElementPtr->state_flags & (GOOD_GUY | BAD_GUY)))) +#endif /* NEVER */ + { + do_damage ((ELEMENTPTR)HitElementPtr, damage); + if (HitElementPtr->hit_points) + WeaponElementPtr->state_flags |= COLLISION; + } + + if (!(HitElementPtr->state_flags & FINITE_LIFE) + || (!(/* WeaponElementPtr->state_flags + & */ HitElementPtr->state_flags & COLLISION) + && WeaponElementPtr->hit_points <= HitElementPtr->mass_points)) + { + if (damage) + { + damage = TARGET_DAMAGED_FOR_1_PT + (damage >> 1); + if (damage > TARGET_DAMAGED_FOR_6_PLUS_PT) + damage = TARGET_DAMAGED_FOR_6_PLUS_PT; + ProcessSound (SetAbsSoundIndex (GameSounds, damage)); + } + + if (GetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex]) != LINE_PRIM) + WeaponElementPtr->state_flags |= DISAPPEARING; + + WeaponElementPtr->hit_points = 0; + WeaponElementPtr->life_span = 0; + WeaponElementPtr->state_flags |= COLLISION | NONSOLID; + + hBlastElement = AllocElement (); + if (hBlastElement) + { + COUNT blast_index; + SIZE blast_offs; + COUNT angle, num_blast_frames; + ELEMENTPTR BlastElementPtr; + extern FRAME blast[]; + + PutElement (hBlastElement); + LockElement (hBlastElement, &BlastElementPtr); + BlastElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID + | (WeaponElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); + SetPrimType (&DisplayArray[BlastElementPtr->PrimIndex], STAMP_PRIM); + + BlastElementPtr->current.location.x = DISPLAY_TO_WORLD (pWPt->x); + BlastElementPtr->current.location.y = DISPLAY_TO_WORLD (pWPt->y); + + angle = GetVelocityTravelAngle (&WeaponElementPtr->velocity); + if ((blast_offs = WeaponElementPtr->blast_offset) > 0) + { + BlastElementPtr->current.location.x += + COSINE (angle, + DISPLAY_TO_WORLD (blast_offs)); + BlastElementPtr->current.location.y += + SINE (angle, + DISPLAY_TO_WORLD (blast_offs)); + } + + blast_index = NORMALIZE_FACING ( + ANGLE_TO_FACING (angle + HALF_CIRCLE) + ); + blast_index = ((blast_index >> 2) << 1) + (blast_index & 0x3 ? 1 : 0); + + if ((num_blast_frames = + GetFrameCount (WeaponElementPtr->next.image.frame)) <= + ANGLE_TO_FACING (FULL_CIRCLE)) + { + BlastElementPtr->life_span = 2; + BlastElementPtr->current.image.farray = blast; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex (blast[0], blast_index); + } + else + { + BlastElementPtr->life_span = num_blast_frames + - ANGLE_TO_FACING (FULL_CIRCLE); + BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; + BlastElementPtr->preprocess_func = animation_preprocess; + BlastElementPtr->current.image.farray = + WeaponElementPtr->next.image.farray; + BlastElementPtr->current.image.frame = + SetAbsFrameIndex ( + BlastElementPtr->current.image.farray[0], + ANGLE_TO_FACING (FULL_CIRCLE)); + } + + UnlockElement (hBlastElement); + + return (hBlastElement); + } + } + + (void) pHPt; /* Satisfying compiler (unused parameter) */ + return ((HELEMENT)0); +} + +FRAME +ModifySilhouette (ELEMENTPTR + ElementPtr, PSTAMP + modify_stamp, BYTE + modify_flags) +{ + FRAME f; + RECT r, or; + INTERSECT_CONTROL ShipIntersect, ObjectIntersect; + STARSHIPPTR StarShipPtr; + CONTEXT OldContext; + + f = 0; + ObjectIntersect.IntersectStamp = *modify_stamp; + GetFrameRect (ObjectIntersect.IntersectStamp.frame, &or); + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (modify_flags & MODIFY_IMAGE) + { + if ((ShipIntersect.IntersectStamp.frame = + StarShipPtr->silhouette) == 0) + return (0); + + GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); + + ShipIntersect.IntersectStamp.origin.x = + ShipIntersect.IntersectStamp.origin.y = 0; + ShipIntersect.EndPoint = ShipIntersect.IntersectStamp.origin; + do + { + ObjectIntersect.IntersectStamp.origin.x = ((COUNT)Random () + % (r.extent.width - or.extent.width)) + + ((or.extent.width - r.extent.width) >> 1); + ObjectIntersect.IntersectStamp.origin.y = ((COUNT)Random () + % (r.extent.height - or.extent.height)) + + ((or.extent.height - r.extent.height) >> 1); + ObjectIntersect.EndPoint = + ObjectIntersect.IntersectStamp.origin; + } while (!DrawablesIntersect (&ObjectIntersect, + &ShipIntersect, MAX_TIME_VALUE)); + + ObjectIntersect.IntersectStamp.origin.x += STATUS_WIDTH >> 1; + ObjectIntersect.IntersectStamp.origin.y += 31; + } + + ObjectIntersect.IntersectStamp.origin.y += + (WHICH_SIDE (ElementPtr->state_flags) + ? BAD_GUY_YOFFS : GOOD_GUY_YOFFS); + + if (modify_flags & MODIFY_SWAP) + { + or.corner.x += ObjectIntersect.IntersectStamp.origin.x; + or.corner.y += ObjectIntersect.IntersectStamp.origin.y; + InitShipStatus (StarShipPtr, &or); + } + else + { + OldContext = SetContext (StatusContext); + DrawStamp (&ObjectIntersect.IntersectStamp); + SetContext (OldContext); + } + + return (f); +} + +SIZE +TrackShip (ELEMENTPTR Tracker, + PCOUNT pfacing) +{ + SIZE best_delta_facing, best_delta; + HELEMENT hShip, hNextShip; + ELEMENTPTR Trackee; + + best_delta = 0; + best_delta_facing = -1; + hShip = Tracker->hTarget; + if (hShip) + { + LockElement (hShip, &Trackee); + Tracker->hTarget = hNextShip = 0; + + goto CheckTracking; + } + + for (hShip = GetHeadElement (); hShip != 0; hShip = hNextShip) + { + LockElement (hShip, &Trackee); + hNextShip = GetSuccElement (Trackee); + if ((Trackee->state_flags & PLAYER_SHIP) + && (Trackee->state_flags & (GOOD_GUY | BAD_GUY)) != + (Tracker->state_flags & (GOOD_GUY | BAD_GUY)) + && (!OBJECT_CLOAKED (Trackee) + || ((Tracker->state_flags & PLAYER_SHIP) + && (Tracker->state_flags & APPEARING)) + )) + { + STARSHIPPTR StarShipPtr; + +CheckTracking: + GetElementStarShip (Trackee, &StarShipPtr); + if (Trackee->life_span + && StarShipPtr->RaceDescPtr->ship_info.crew_level) + { + SIZE delta_x, delta_y, delta_facing; + + if (Tracker->state_flags & PRE_PROCESS) + { + delta_x = Trackee->next.location.x + - Tracker->next.location.x; + delta_y = Trackee->next.location.y + - Tracker->next.location.y; + } + else + { + delta_x = Trackee->current.location.x + - Tracker->current.location.x; + delta_y = Trackee->current.location.y + - Tracker->current.location.y; + } + + delta_x = WRAP_DELTA_X (delta_x); + delta_y = WRAP_DELTA_Y (delta_y); + delta_facing = NORMALIZE_FACING ( + ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - *pfacing + ); + + if (delta_x < 0) + delta_x = -delta_x; + if (delta_y < 0) + delta_y = -delta_y; + delta_x += delta_y; + + if (best_delta == 0 || delta_x < best_delta) + { + best_delta = delta_x; + best_delta_facing = delta_facing; + Tracker->hTarget = hShip; + } + } + } + UnlockElement (hShip); + } + + if (best_delta_facing > 0) + { + COUNT facing; + + facing = *pfacing; + if (best_delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) + facing += (((BYTE)Random () & 1) << 1) - 1; + else if (best_delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) + ++facing; + else + --facing; + *pfacing = NORMALIZE_FACING (facing); + } + + return (best_delta_facing); +} + diff --git a/sc2/src/sc2code/weapon.h b/sc2/src/sc2code/weapon.h new file mode 100644 index 000000000..fc5fb3072 --- /dev/null +++ b/sc2/src/sc2code/weapon.h @@ -0,0 +1,58 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _WEAPON_H +#define _WEAPON_H + +typedef struct +{ + COORD cx, cy, ex, ey; + ELEMENT_FLAGS sender; + SIZE pixoffs; + COUNT face; + COLOR color; +} LASER_BLOCK; +typedef LASER_BLOCK *PLASER_BLOCK; + +typedef struct +{ + COORD cx, cy; + ELEMENT_FLAGS sender; + SIZE pixoffs, speed, hit_points, damage; + COUNT face, index, life; + PFRAME farray; + void (*preprocess_func) (PELEMENT ElementPtr); + SIZE blast_offs; +} MISSILE_BLOCK; +typedef MISSILE_BLOCK *PMISSILE_BLOCK; + +extern HELEMENT initialize_laser (PLASER_BLOCK pLaserBlock); +extern HELEMENT initialize_missile (PMISSILE_BLOCK pMissileBlock); +extern HELEMENT weapon_collision (PELEMENT ElementPtr0, PPOINT pPt0, + PELEMENT ElementPtr1, PPOINT pPt1); +extern SIZE TrackShip (ELEMENTPTR Tracker, PCOUNT pfacing); +extern void Untarget (ELEMENTPTR ElementPtr); + +#define MODIFY_IMAGE (1 << 0) +#define MODIFY_SWAP (1 << 1) + +extern FRAME ModifySilhouette (ELEMENTPTR ElementPtr, PSTAMP + modify_stamp, BYTE modify_flags); + +#endif /* _WEAPON_H */ + diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c new file mode 100644 index 000000000..3860512ef --- /dev/null +++ b/sc2/src/starcon2.c @@ -0,0 +1,561 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +/**************************************** + + Star Control II: 3DO => SDL Port + + Copyright Toys for Bob, 2002 + + starcon2.cpp programmer: Chris Nelson + +*****************************************/ + +#include "SDL_wrapper.h" + +//Global Variables for the wrapper. + +Uint8 KeyboardDown[512]; +#define KBDBUFSIZE (1 << 8) +static int kbdhead, kbdtail; +static Uint16 kbdbuf[KBDBUFSIZE]; + +UBYTE ControlA; +UBYTE ControlB; +UBYTE ControlC; +UBYTE ControlX; +UBYTE ControlStart; +UBYTE ControlLeftShift; +UBYTE ControlRightShift; + +int ScreenWidth; +int ScreenHeight; +int ScreenWidthActual; +int ScreenHeightActual; +int ScreenBPPActual; + +SDL_Surface *ExtraScreen; + +int TFB_DEBUG_HALT; + +Uint16 +GetUNICODEKey () +{ + if (kbdtail != kbdhead) + { + Uint16 ch; + + ch = kbdbuf[kbdhead]; + kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); + return (ch); + } + + return (0); +} + +void +FlushInput () +{ + kbdtail = kbdhead = 0; +} + +void +ProcessKeyboardEvent(const SDL_Event *Event) +{ + if(Event->key.keysym.sym == SDLK_TAB && Event->type == SDL_KEYDOWN) + { + SDL_GL_SwapBuffers(); //Debug: Hit tab to swap buffers + } + else if(Event->key.keysym.sym == SDLK_BACKQUOTE) + { + exit(0); + } + else//if(Event->type == SDL_KEYDOWN) + { + if (Event->type == SDL_KEYDOWN) + { + if ((kbdbuf[kbdtail] = Event->key.keysym.unicode) + || (kbdbuf[kbdtail] = Event->key.keysym.sym) <= 0x7F) + { + kbdtail = (kbdtail + 1) & (KBDBUFSIZE - 1); + if (kbdtail == kbdhead) + kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); + } + KeyboardDown[Event->key.keysym.sym]=TRUE; + } + else + { + KeyboardDown[Event->key.keysym.sym]=FALSE; + } + } + + if (Event->key.keysym.sym == SDLK_BACKSPACE && Event->type == SDL_KEYDOWN) + { + //Stop + Start Starcon running. + + //TFB_DEBUG_HALT = !TFB_DEBUG_HALT; + } + + if (Event->type == SDL_KEYDOWN && TFB_DEBUG_HALT) + { + //Used for debugging Buffer copy operations + + if (Event->key.keysym.sym==SDLK_d) + { + //Draw + + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + + // + + glDrawBuffer (GL_BACK_LEFT); + glLoadIdentity (); + glOrtho (0, ScreenWidth, ScreenHeight, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glDisable (GL_SCISSOR_TEST); + + glBegin (GL_QUADS); + { + glColor3f (rand() % 2, rand () % 2, rand () % 2); + glVertex2i (0, ScreenHeight); + //glColor3f (rand() % 2, rand() % 2, rand() % 2); + glVertex2i(0, 0); + //glColor3f (rand() % 2, rand () % 2, rand () % 2); + glVertex2i (ScreenWidth, 0); + glColor3f (rand() % 2, rand () % 2, rand () % 2); + glVertex2i(ScreenWidth, ScreenHeight); + } + glEnd(); + + // + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } + if (Event->key.keysym.sym == SDLK_s) + { + SDL_GL_SwapBuffers(); + } + if (Event->key.keysym.sym == SDLK_c) + { + //Copy from front to back + glReadBuffer(GL_FRONT); + glDrawBuffer(GL_BACK); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho (0, ScreenWidthActual, ScreenHeightActual, 0, -1, 1); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glRasterPos2d (0, ScreenHeightActual - .1); + //Re "-.1": All values 0 < x < .5 work. Strange!! + + glDisable (GL_SCISSOR_TEST); + glCopyPixels (0, 0, ScreenWidthActual, ScreenHeightActual, + GL_COLOR); + + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + } + } +} + +void ProcessJoystickEvent (const SDL_Event* Event) +{ + SDL_Event PseudoEvent; + + return; + + if (Event->type == SDL_JOYAXISMOTION) + { + if (Event->jaxis.axis == 0) + { + //x-axis + + if (Event->jaxis.value <= -5) //Left + { + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = SDLK_LEFT; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_RIGHT; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jaxis.value >= 5) //Right + { + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_LEFT; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = SDLK_RIGHT; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jaxis.value > -5 && Event->jaxis.value < 5) + //Neither Left nor Right + { + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_LEFT; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_RIGHT; + ProcessKeyboardEvent (&PseudoEvent); + } + } + if (Event->jaxis.axis == 1) + { + //y-axis + + if (Event->jaxis.value <= -5) //Down + { + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = SDLK_DOWN; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_UP; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jaxis.value >= 5) //Up + { + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_DOWN; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = SDLK_UP; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jaxis.value >-5 && Event->jaxis.value < 5) + //Neither Down nor Up + { + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_DOWN; + ProcessKeyboardEvent (&PseudoEvent); + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = SDLK_UP; + ProcessKeyboardEvent (&PseudoEvent); + } + } + } + if (Event->type == SDL_JOYBUTTONDOWN) + { + printf("Joystick %i down\n", Event->jbutton.button); + + if (Event->jbutton.button % 3 == 0) + { + //Mimic the Primary key + + PseudoEvent.type=SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = ControlA; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jbutton.button % 3 == 1) + { + //Mimic the Secondary key + + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = ControlB; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jbutton.button % 3 == 2) + { + //Mimic the Tertiary key + + PseudoEvent.type = SDL_KEYDOWN; + PseudoEvent.key.keysym.sym = ControlC; + ProcessKeyboardEvent (&PseudoEvent); + } + } + if (Event->type == SDL_JOYBUTTONUP) + { + if (Event->jbutton.button % 3 == 0) + { + //Mimic the Primary key + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = ControlA; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jbutton.button % 3 == 1) + { + //Mimic the Secondary key + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = ControlB; + ProcessKeyboardEvent (&PseudoEvent); + } + if (Event->jbutton.button % 3 == 2) + { + //Mimic the Tertiary key + + PseudoEvent.type = SDL_KEYUP; + PseudoEvent.key.keysym.sym = ControlC; + ProcessKeyboardEvent (&PseudoEvent); + } + } +} + + +int +main(int argc, char *argv[]) +{ + SDL_Surface* Screen; + SDL_Joystick *Joystick1; + SDL_Event Event; + SDL_version compile_version; + + char SoundcardName[256]; + char VideoName[256]; + int audio_rate,audio_channels; + Uint16 audio_format; + + int a,i; + + //FILE* Debug; + //Debug = fopen ("Debug.txt","w"); _dup2(fileno(Debug),1); + + //Begin System Initialization + + printf("Initializing SDL.\n"); + + if ((SDL_Init (SDL_INIT_VIDEO + | SDL_INIT_AUDIO + | SDL_INIT_JOYSTICK + | SDL_INIT_NOPARACHUTE //For Debugging in MSVC++ + ) == -1)) + { + printf("Could not initialize SDL: %s.\n", SDL_GetError()); + exit(-1); + } + SDL_VideoDriverName (VideoName, sizeof (VideoName)); + printf("SDL driver used: %s\n", VideoName); + // Set the environment variable SDL_VIDEODRIVER to override + // For Linux: x11 (default), dga, fbcon, directfb, svgalib, + // ggi, aalib + // For Windows: directx (default), windib + atexit (SDL_Quit); + + printf ("SDL initialized.\n"); + + SDL_EnableUNICODE (1); + + printf ("Initializing Screen.\n"); + + ScreenWidth = 320; + ScreenHeight = 240; + ScreenWidthActual = 640; + ScreenHeightActual = 480; + ScreenBPPActual = 16; + + switch(ScreenBPPActual) { + case 8: + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 2); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 3); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 3); + break; + case 15: + case 16: + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + break; + case 24: + case 32: + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + break; + } + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, ScreenBPPActual); + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); + + Screen = SDL_SetVideoMode ( + ScreenWidthActual, ScreenHeightActual, ScreenBPPActual, + 0 +// | SDL_HWSURFACE +// | SDL_DOUBLEBUF + | SDL_OPENGL + | SDL_ANYFORMAT +// | SDL_FULLSCREEN + ); + if (Screen == NULL) + { + printf ("Couldn't set %ix%ix%i video mode: %s\n", + ScreenWidthActual, ScreenHeightActual, ScreenBPPActual, + SDL_GetError ()); + exit(-1); + } + else + { + printf ("Set the resolution to: %ix%ix%i\n", + SDL_GetVideoSurface()->w, SDL_GetVideoSurface()->h, + SDL_GetVideoSurface()->format->BitsPerPixel); + printf("OpenGL renderer: %s version: %s\n", glGetString(GL_RENDERER), + glGetString(GL_VERSION)); + + } + + //glShadeModel (GL_SMOOTH); + glClearColor (0,0,0,0); + glViewport (0, 0, ScreenWidthActual, ScreenHeightActual); + glDrawBuffer (GL_FRONT_LEFT); + glClear (GL_COLOR_BUFFER_BIT); + SDL_GL_SwapBuffers (); //Clear both buffers at init + glClear (GL_COLOR_BUFFER_BIT); + glEnable (GL_ALPHA_TEST); + glDisable (GL_DITHER); + glAlphaFunc (GL_GREATER, 0); + + printf ("%i joysticks were found.\n", SDL_NumJoysticks ()); + if(SDL_NumJoysticks() > 0) + { + printf ("The names of the joysticks are:\n"); + for(i = 0; i < SDL_NumJoysticks (); i++) + { + printf(" %s\n", SDL_JoystickName (i)); + } + SDL_JoystickEventState (SDL_ENABLE); + Joystick1 = SDL_JoystickOpen (0); + if (SDL_NumJoysticks () > 1) + SDL_JoystickOpen(1); + } + + if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096)) + { + printf ("Unable to open audio!\n"); + exit (-1); + } + atexit (Mix_CloseAudio); + + SDL_AudioDriverName (SoundcardName, sizeof (SoundcardName)); + + Mix_QuerySpec (&audio_rate, &audio_format, &audio_channels); + printf ("Opened %s at %d Hz %d bit %s, %d bytes audio buffer\n", + SoundcardName, audio_rate, audio_format & 0xFF, + audio_channels > 1 ? "stereo" : "mono", 4096); + + MIX_VERSION (&compile_version); + printf ("Compiled with SDL_mixer version: %d.%d.%d\n", + compile_version.major, + compile_version.minor, + compile_version.patch); + printf ("Running with SDL_mixer version: %d.%d.%d\n", + Mix_Linked_Version()->major, + Mix_Linked_Version()->minor, + Mix_Linked_Version()->patch); + + //SDL_ShowCursor (SDL_DISABLE); + + GraphicsSem = SDL_CreateSemaphore (1); + _MemorySem = SDL_CreateSemaphore (1); + + //End System Initialization + + //Begin Game Initialization + + for(a = 0; a < 512; a++) + { + KeyboardDown[a] = FALSE; + //KeyboardStroke[a] = FALSE; + } + ControlA = SDLK_f; + ControlB = SDLK_d; + ControlC = SDLK_s; + ControlX = SDLK_a; + ControlStart = SDLK_RETURN; + ControlLeftShift = SDLK_LSHIFT; + ControlRightShift = SDLK_RSHIFT; + + //End Game Initialization + + TFB_DEBUG_HALT = 0; + + //Begin MultiThreading + + printf ("\n---\n\n"); + + SDL_CreateThread (Starcon2Main, NULL); + + //End MultiThreading + + //Start Test Code + + //End Test Code + + //Start main game loop here + + for (;;) + { + //Process Events + + while (SDL_PollEvent (&Event)) + { + switch (Event.type) { + case SDL_ACTIVEEVENT: /* Loose/gain visibility */ + // TODO + break; + case SDL_KEYDOWN: /* Key pressed */ + case SDL_KEYUP: /* Key released */ + ProcessKeyboardEvent (&Event); + break; + case SDL_JOYAXISMOTION: /* Joystick axis motion */ + case SDL_JOYBUTTONDOWN: /* Joystick button pressed */ + case SDL_JOYBUTTONUP: /* Joystick button released */ + ProcessJoystickEvent (&Event); + break; + case SDL_QUIT: + exit (0); + break; + case SDL_VIDEORESIZE: /* User resized video mode */ + // TODO + break; + case SDL_VIDEOEXPOSE: /* Screen needs to be redrawn */ + // TODO + break; + default: + break; + } + } + + TFB_FlushGraphics (); + + //Still testing this... Should fix sticky input soon... + /* + { + Uint8* Temp; + + SDL_PumpEvents (); + Temp = SDL_GetKeyState (NULL); + for(a = 0; a < 512; a++) + { + KeyboardDown[a] = Temp[a]; + } + } + */ + } +} diff --git a/sc2/src/trackplayer.c b/sc2/src/trackplayer.c new file mode 100644 index 000000000..622486f6d --- /dev/null +++ b/sc2/src/trackplayer.c @@ -0,0 +1,194 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +/**************************************** + + Star Control II: 3DO => SDL Port + + Copyright Toys for Bob, 2002 + + starcon2.cpp programmer: Chris Nelson + +*****************************************/ + +#include "SDL_wrapper.h" + +#define VOICE_CHANNEL 0 + +extern int do_subtitles (UNICODE *pStr); + +static int tct, tcur, no_voice; +#define MAX_CLIPS 50 +static struct +{ + int text_spliced; + Mix_Chunk *chunk; + UNICODE *text; +} track_clip[MAX_CLIPS]; + +void +JumpTrack (int abort) +{ + Mix_ChannelFinished (0); + + if (track_clip[tcur].chunk) + Mix_HaltChannel (VOICE_CHANNEL); + + no_voice = 1; + do_subtitles ((void *)~0); + + if (abort) + tcur = tct; +} + +static void +advance_track (int channel_finished) +{ + if (channel_finished <= VOICE_CHANNEL) + { + if (channel_finished == VOICE_CHANNEL) + ++tcur; + if (tcur < tct) + { + Mix_PlayChannel (VOICE_CHANNEL, track_clip[tcur].chunk, 0); + do_subtitles (0); + } + else if (channel_finished == VOICE_CHANNEL) + { + --tcur; + no_voice = 1; + } + } +} + +void +ResumeTrack () +{ + if (tcur < tct) + { + if (Mix_Playing /* Mix_Paused */ (VOICE_CHANNEL)) + Mix_Resume (VOICE_CHANNEL); + else if (!no_voice) + { + if (tcur == 0) + Mix_ChannelFinished (advance_track); + advance_track (-1); + } + } +} + +COUNT +PlayingTrack () +{ + if (tcur < tct) + { + if (do_subtitles (track_clip[tcur].text) + || (no_voice && ++tcur < tct && do_subtitles (0))) + return (tcur + 1); + else if (track_clip[tcur].chunk) + return (Mix_Playing (VOICE_CHANNEL) ? (COUNT)(tcur + 1) : 0); + } + + return (0); +} + +void +StopTrack () +{ + Mix_ChannelFinished (0); + Mix_HaltChannel (VOICE_CHANNEL); + + while (tct--) + { + if (track_clip[tct].text_spliced) + { + track_clip[tct].text_spliced = 0; + HFree (track_clip[tct].text); + track_clip[tct].text = 0; + } + if (track_clip[tct].chunk) + { + Mix_FreeChunk (track_clip[tct].chunk); + track_clip[tct].chunk = 0; + } + } + tct = tcur = 0; + no_voice = 0; + do_subtitles (0); +} + +void +SpliceTrack (UNICODE *TrackName, UNICODE *TrackText) +{ + if (TrackText) + { + if (TrackName == 0) + { + if (tct) + { + int slen1, slen2; + UNICODE *oTT; + + oTT = track_clip[tct - 1].text; + slen1 = wstrlen (oTT); + slen2 = wstrlen (TrackText); + if (track_clip[tct - 1].text_spliced) + track_clip[tct - 1].text = HRealloc (oTT, slen1 + slen2 + 1); + else + { + track_clip[tct - 1].text = HMalloc (slen1 + slen2 + 1); + wstrcpy (track_clip[tct - 1].text, oTT); + track_clip[tct - 1].text_spliced = 1; + } + wstrcpy (&track_clip[tct - 1].text[slen1], TrackText); + } + } + else if (tct < MAX_CLIPS) + { + track_clip[tct].text = TrackText; + track_clip[tct].chunk = Mix_LoadWAV (TrackName); + track_clip[tct].text_spliced = 0; + ++tct; + } + } +} + +void +PauseTrack () +{ + if (tcur < tct && track_clip[tcur].chunk) + Mix_Pause (VOICE_CHANNEL); +} + +void +FastReverse () +{ + JumpTrack (0); + no_voice = 0; + tcur = 0; + ResumeTrack (); +} + +void +FastForward () +{ + JumpTrack (0); +// no_voice = 0; +}