Import Debian changes 0.8.10-20
amphetamine (0.8.10-20) unstable; urgency=medium
* Team upload.
* Switch to compat level 11.
* wrap-and-sort -sa.
* Declare compliance with Debian Policy 4.1.4.
* Update homepage address and point to tracker.debian.org because the old one
is gone.
* Move the package to Git and salsa.debian.org.
* Drop deprecated amphetamine.menu file.
* Add a comment in German to desktop file.
* Remove 000_gcc_m68k.diff because it is unused.
Markus Koschany
5 years ago
0 | KNOWN PROBLEMS | |
1 | ||
2 | - Clipping sometimes fails, i.e. you can walk through walls or get stuck | |
3 | - There's a problem with flying monsters. They sometimes get stuck | |
4 | in the wall or will stick at the top of the screen an won't go | |
5 | away until a new level is entered. Sometimes, the game gets completely | |
6 | corrupted; the player may end up in the wall with the monster and die. | |
7 | - There is a problem with C++ destructors not being called because they | |
8 | are not declared "virtual" when the actually should. E.g. in | |
9 | CApplication::UnloadLevelData(), instances of different subclasses of | |
10 | CThing are deleted through a CThing pointer; as a result only | |
11 | CThing::~CThing() is actually called, but not the destructor of the | |
12 | actual subclasses. Unfortunately, there seem to be bugs in some of those | |
13 | destructors. When just declaring CThings's of even CObject's destructor | |
14 | virtual, the game becomes very unstable and crashes on changing between | |
15 | different levels. |
0 | GNU GENERAL PUBLIC LICENSE | |
1 | Version 2, June 1991 | |
2 | ||
3 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |
4 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | Everyone is permitted to copy and distribute verbatim copies | |
6 | of this license document, but changing it is not allowed. | |
7 | ||
8 | Preamble | |
9 | ||
10 | The licenses for most software are designed to take away your | |
11 | freedom to share and change it. By contrast, the GNU General Public | |
12 | License is intended to guarantee your freedom to share and change free | |
13 | software--to make sure the software is free for all its users. This | |
14 | General Public License applies to most of the Free Software | |
15 | Foundation's software and to any other program whose authors commit to | |
16 | using it. (Some other Free Software Foundation software is covered by | |
17 | the GNU Library General Public License instead.) You can apply it to | |
18 | your programs, too. | |
19 | ||
20 | When we speak of free software, we are referring to freedom, not | |
21 | price. Our General Public Licenses are designed to make sure that you | |
22 | have the freedom to distribute copies of free software (and charge for | |
23 | this service if you wish), that you receive source code or can get it | |
24 | if you want it, that you can change the software or use pieces of it | |
25 | in new free programs; and that you know you can do these things. | |
26 | ||
27 | To protect your rights, we need to make restrictions that forbid | |
28 | anyone to deny you these rights or to ask you to surrender the rights. | |
29 | These restrictions translate to certain responsibilities for you if you | |
30 | distribute copies of the software, or if you modify it. | |
31 | ||
32 | For example, if you distribute copies of such a program, whether | |
33 | gratis or for a fee, you must give the recipients all the rights that | |
34 | you have. You must make sure that they, too, receive or can get the | |
35 | source code. And you must show them these terms so they know their | |
36 | rights. | |
37 | ||
38 | We protect your rights with two steps: (1) copyright the software, and | |
39 | (2) offer you this license which gives you legal permission to copy, | |
40 | distribute and/or modify the software. | |
41 | ||
42 | Also, for each author's protection and ours, we want to make certain | |
43 | that everyone understands that there is no warranty for this free | |
44 | software. If the software is modified by someone else and passed on, we | |
45 | want its recipients to know that what they have is not the original, so | |
46 | that any problems introduced by others will not reflect on the original | |
47 | authors' reputations. | |
48 | ||
49 | Finally, any free program is threatened constantly by software | |
50 | patents. We wish to avoid the danger that redistributors of a free | |
51 | program will individually obtain patent licenses, in effect making the | |
52 | program proprietary. To prevent this, we have made it clear that any | |
53 | patent must be licensed for everyone's free use or not licensed at all. | |
54 | ||
55 | The precise terms and conditions for copying, distribution and | |
56 | modification follow. | |
57 | ||
58 | GNU GENERAL PUBLIC LICENSE | |
59 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
60 | ||
61 | 0. This License applies to any program or other work which contains | |
62 | a notice placed by the copyright holder saying it may be distributed | |
63 | under the terms of this General Public License. The "Program", below, | |
64 | refers to any such program or work, and a "work based on the Program" | |
65 | means either the Program or any derivative work under copyright law: | |
66 | that is to say, a work containing the Program or a portion of it, | |
67 | either verbatim or with modifications and/or translated into another | |
68 | language. (Hereinafter, translation is included without limitation in | |
69 | the term "modification".) Each licensee is addressed as "you". | |
70 | ||
71 | Activities other than copying, distribution and modification are not | |
72 | covered by this License; they are outside its scope. The act of | |
73 | running the Program is not restricted, and the output from the Program | |
74 | is covered only if its contents constitute a work based on the | |
75 | Program (independent of having been made by running the Program). | |
76 | Whether that is true depends on what the Program does. | |
77 | ||
78 | 1. You may copy and distribute verbatim copies of the Program's | |
79 | source code as you receive it, in any medium, provided that you | |
80 | conspicuously and appropriately publish on each copy an appropriate | |
81 | copyright notice and disclaimer of warranty; keep intact all the | |
82 | notices that refer to this License and to the absence of any warranty; | |
83 | and give any other recipients of the Program a copy of this License | |
84 | along with the Program. | |
85 | ||
86 | You may charge a fee for the physical act of transferring a copy, and | |
87 | you may at your option offer warranty protection in exchange for a fee. | |
88 | ||
89 | 2. You may modify your copy or copies of the Program or any portion | |
90 | of it, thus forming a work based on the Program, and copy and | |
91 | distribute such modifications or work under the terms of Section 1 | |
92 | above, provided that you also meet all of these conditions: | |
93 | ||
94 | a) You must cause the modified files to carry prominent notices | |
95 | stating that you changed the files and the date of any change. | |
96 | ||
97 | b) You must cause any work that you distribute or publish, that in | |
98 | whole or in part contains or is derived from the Program or any | |
99 | part thereof, to be licensed as a whole at no charge to all third | |
100 | parties under the terms of this License. | |
101 | ||
102 | c) If the modified program normally reads commands interactively | |
103 | when run, you must cause it, when started running for such | |
104 | interactive use in the most ordinary way, to print or display an | |
105 | announcement including an appropriate copyright notice and a | |
106 | notice that there is no warranty (or else, saying that you provide | |
107 | a warranty) and that users may redistribute the program under | |
108 | these conditions, and telling the user how to view a copy of this | |
109 | License. (Exception: if the Program itself is interactive but | |
110 | does not normally print such an announcement, your work based on | |
111 | the Program is not required to print an announcement.) | |
112 | ||
113 | These requirements apply to the modified work as a whole. If | |
114 | identifiable sections of that work are not derived from the Program, | |
115 | and can be reasonably considered independent and separate works in | |
116 | themselves, then this License, and its terms, do not apply to those | |
117 | sections when you distribute them as separate works. But when you | |
118 | distribute the same sections as part of a whole which is a work based | |
119 | on the Program, the distribution of the whole must be on the terms of | |
120 | this License, whose permissions for other licensees extend to the | |
121 | entire whole, and thus to each and every part regardless of who wrote it. | |
122 | ||
123 | Thus, it is not the intent of this section to claim rights or contest | |
124 | your rights to work written entirely by you; rather, the intent is to | |
125 | exercise the right to control the distribution of derivative or | |
126 | collective works based on the Program. | |
127 | ||
128 | In addition, mere aggregation of another work not based on the Program | |
129 | with the Program (or with a work based on the Program) on a volume of | |
130 | a storage or distribution medium does not bring the other work under | |
131 | the scope of this License. | |
132 | ||
133 | 3. You may copy and distribute the Program (or a work based on it, | |
134 | under Section 2) in object code or executable form under the terms of | |
135 | Sections 1 and 2 above provided that you also do one of the following: | |
136 | ||
137 | a) Accompany it with the complete corresponding machine-readable | |
138 | source code, which must be distributed under the terms of Sections | |
139 | 1 and 2 above on a medium customarily used for software interchange; or, | |
140 | ||
141 | b) Accompany it with a written offer, valid for at least three | |
142 | years, to give any third party, for a charge no more than your | |
143 | cost of physically performing source distribution, a complete | |
144 | machine-readable copy of the corresponding source code, to be | |
145 | distributed under the terms of Sections 1 and 2 above on a medium | |
146 | customarily used for software interchange; or, | |
147 | ||
148 | c) Accompany it with the information you received as to the offer | |
149 | to distribute corresponding source code. (This alternative is | |
150 | allowed only for noncommercial distribution and only if you | |
151 | received the program in object code or executable form with such | |
152 | an offer, in accord with Subsection b above.) | |
153 | ||
154 | The source code for a work means the preferred form of the work for | |
155 | making modifications to it. For an executable work, complete source | |
156 | code means all the source code for all modules it contains, plus any | |
157 | associated interface definition files, plus the scripts used to | |
158 | control compilation and installation of the executable. However, as a | |
159 | special exception, the source code distributed need not include | |
160 | anything that is normally distributed (in either source or binary | |
161 | form) with the major components (compiler, kernel, and so on) of the | |
162 | operating system on which the executable runs, unless that component | |
163 | itself accompanies the executable. | |
164 | ||
165 | If distribution of executable or object code is made by offering | |
166 | access to copy from a designated place, then offering equivalent | |
167 | access to copy the source code from the same place counts as | |
168 | distribution of the source code, even though third parties are not | |
169 | compelled to copy the source along with the object code. | |
170 | ||
171 | 4. You may not copy, modify, sublicense, or distribute the Program | |
172 | except as expressly provided under this License. Any attempt | |
173 | otherwise to copy, modify, sublicense or distribute the Program is | |
174 | void, and will automatically terminate your rights under this License. | |
175 | However, parties who have received copies, or rights, from you under | |
176 | this License will not have their licenses terminated so long as such | |
177 | parties remain in full compliance. | |
178 | ||
179 | 5. You are not required to accept this License, since you have not | |
180 | signed it. However, nothing else grants you permission to modify or | |
181 | distribute the Program or its derivative works. These actions are | |
182 | prohibited by law if you do not accept this License. Therefore, by | |
183 | modifying or distributing the Program (or any work based on the | |
184 | Program), you indicate your acceptance of this License to do so, and | |
185 | all its terms and conditions for copying, distributing or modifying | |
186 | the Program or works based on it. | |
187 | ||
188 | 6. Each time you redistribute the Program (or any work based on the | |
189 | Program), the recipient automatically receives a license from the | |
190 | original licensor to copy, distribute or modify the Program subject to | |
191 | these terms and conditions. You may not impose any further | |
192 | restrictions on the recipients' exercise of the rights granted herein. | |
193 | You are not responsible for enforcing compliance by third parties to | |
194 | this License. | |
195 | ||
196 | 7. If, as a consequence of a court judgment or allegation of patent | |
197 | infringement or for any other reason (not limited to patent issues), | |
198 | conditions are imposed on you (whether by court order, agreement or | |
199 | otherwise) that contradict the conditions of this License, they do not | |
200 | excuse you from the conditions of this License. If you cannot | |
201 | distribute so as to satisfy simultaneously your obligations under this | |
202 | License and any other pertinent obligations, then as a consequence you | |
203 | may not distribute the Program at all. For example, if a patent | |
204 | license would not permit royalty-free redistribution of the Program by | |
205 | all those who receive copies directly or indirectly through you, then | |
206 | the only way you could satisfy both it and this License would be to | |
207 | refrain entirely from distribution of the Program. | |
208 | ||
209 | If any portion of this section is held invalid or unenforceable under | |
210 | any particular circumstance, the balance of the section is intended to | |
211 | apply and the section as a whole is intended to apply in other | |
212 | circumstances. | |
213 | ||
214 | It is not the purpose of this section to induce you to infringe any | |
215 | patents or other property right claims or to contest validity of any | |
216 | such claims; this section has the sole purpose of protecting the | |
217 | integrity of the free software distribution system, which is | |
218 | implemented by public license practices. Many people have made | |
219 | generous contributions to the wide range of software distributed | |
220 | through that system in reliance on consistent application of that | |
221 | system; it is up to the author/donor to decide if he or she is willing | |
222 | to distribute software through any other system and a licensee cannot | |
223 | impose that choice. | |
224 | ||
225 | This section is intended to make thoroughly clear what is believed to | |
226 | be a consequence of the rest of this License. | |
227 | ||
228 | 8. If the distribution and/or use of the Program is restricted in | |
229 | certain countries either by patents or by copyrighted interfaces, the | |
230 | original copyright holder who places the Program under this License | |
231 | may add an explicit geographical distribution limitation excluding | |
232 | those countries, so that distribution is permitted only in or among | |
233 | countries not thus excluded. In such case, this License incorporates | |
234 | the limitation as if written in the body of this License. | |
235 | ||
236 | 9. The Free Software Foundation may publish revised and/or new versions | |
237 | of the General Public License from time to time. Such new versions will | |
238 | be similar in spirit to the present version, but may differ in detail to | |
239 | address new problems or concerns. | |
240 | ||
241 | Each version is given a distinguishing version number. If the Program | |
242 | specifies a version number of this License which applies to it and "any | |
243 | later version", you have the option of following the terms and conditions | |
244 | either of that version or of any later version published by the Free | |
245 | Software Foundation. If the Program does not specify a version number of | |
246 | this License, you may choose any version ever published by the Free Software | |
247 | Foundation. | |
248 | ||
249 | 10. If you wish to incorporate parts of the Program into other free | |
250 | programs whose distribution conditions are different, write to the author | |
251 | to ask for permission. For software which is copyrighted by the Free | |
252 | Software Foundation, write to the Free Software Foundation; we sometimes | |
253 | make exceptions for this. Our decision will be guided by the two goals | |
254 | of preserving the free status of all derivatives of our free software and | |
255 | of promoting the sharing and reuse of software generally. | |
256 | ||
257 | NO WARRANTY | |
258 | ||
259 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |
260 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |
261 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |
262 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |
263 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
264 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |
265 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |
266 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |
267 | REPAIR OR CORRECTION. | |
268 | ||
269 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
270 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |
271 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |
272 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |
273 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |
274 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |
275 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |
276 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |
277 | POSSIBILITY OF SUCH DAMAGES. | |
278 | ||
279 | END OF TERMS AND CONDITIONS |
0 | March 25th, 2002: | |
1 | ||
2 | Shape.cpp, Surface.cpp: | |
3 | - included <memory.h> | |
4 | ||
5 | System.hpp, Makefile: | |
6 | Endianness is now autodetected through SDL_BYTEORDER, so there is | |
7 | no need for the BYTE_ORDER variable in the Makefile anymore. | |
8 | ||
9 | Object.cpp, Things.cpp, Monster.cpp, Monstrxx.cpp: | |
10 | Initialize some more member variables in the constructors, especially in | |
11 | Monstrxx.cpp. Some of the variables where indeed uninitialized, e.g. | |
12 | "lastShoot", "currentShootDelay", and "nextShootTime". These changes | |
13 | fix the bug where mosters just seem to freeze and don't move | |
14 | and shoot despite being "alive". | |
15 | ||
16 | September 17th, 2001: | |
17 | ||
18 | Level.cpp: | |
19 | - included <string.h>. | |
20 | Amphetamine should now compile under Linux Mandrake 8.0. | |
21 | ||
22 | March 27th, 2001: | |
23 | ||
24 | Endianess is now controlled by a seperate variable "BYTE_ORDER", which can | |
25 | be set to either "LITTLE_ENDIAN" (the default) or "BIG_ENDIAN". | |
26 | ||
27 | -------------------------------------------------------------------------- | |
28 | ||
29 | CMaskedShape::Encode(), | |
30 | CMaskedShape::RenderShapeClipped() | |
31 | CMaskedShape::RenderShapeUnclipped() | |
32 | ||
33 | These functions make must read/write 4-byte words at unaligned memory | |
34 | locations. To avoid problems on architectures that require strict | |
35 | alignment, the macros SET_LONG and GET_LONG perform slow byte-wise | |
36 | access by default. If you are on IA-32 and "make" detects this, the | |
37 | macro __OPT_MEM_ACCESS__ will be defined to enable faster versions of | |
38 | SET_LONG and GET_LONG. | |
39 | ||
40 | -------------------------------------------------------------------------- | |
41 | ||
42 | Surface.cpp: CGraphicSurface::PaintGraphic() | |
43 | - replaced alignment dependent memory copy code by a call to "memcpy", | |
44 | because it's fast enough and simpler this way | |
45 | ||
46 | Shape.cpp: CTexture::RenderShape() and CBackground::RenderShape() | |
47 | - replaced alignment dependent memory copy code by a call to "memcpy", | |
48 | because it's fast enough and simpler this way | |
49 | ||
50 | System.cpp/.hpp: | |
51 | - removed support for libsge |
0 | 1. Make sure SDL is installed correctly. | |
1 | ||
2 | 2. Have a look at the 'Makefile' and edit it where appropriate. | |
3 | - 'USE_LIB_XPM=FALSE' if you don't have libXpm | |
4 | ||
5 | 3. Type 'make'. This should build the Amphetamine binary. You can safely | |
6 | ignore the numerous warnings. If the compilation fails, you are in | |
7 | in trouble. Try to tweak the 'Makefile'. You have to delete | |
8 | '-funroll-loops' if you are still using gcc 2.7.2.3 | |
9 | ||
10 | 4. Become root and type 'make install'. This will install the binary to | |
11 | the directory specified in the makefile (default is '/usr/local/games/amph'). | |
12 | It will also create a symbolic link. | |
13 | ||
14 | 5. You have managed the difficult bit. Now, you have to install the data files | |
15 | required by the game. Get 'amphetamine-${VERSION}.tar.bz' an do: | |
16 | - cd /usr/local/games | |
17 | - bzip2 -cd ~/amphetamine-data-0.8.tar.bz | tar xv | |
18 | ||
19 | (Note: the exact commands depend on your syste configuration) | |
20 | ||
21 | 6. type 'amph' in order to run the game and have fun! |
0 | #=============== | |
1 | # User settings | |
2 | #=============== | |
3 | ||
4 | # Install Paths | |
5 | PREFIX := /usr/local | |
6 | INSTALL_DIR := ${PREFIX}/games/amph | |
7 | ||
8 | # Libraries | |
9 | USE_LIB_XPM := TRUE | |
10 | ||
11 | SDL_CONFIG := sdl-config | |
12 | SDL_HEADERS := $(shell $(SDL_CONFIG) --cflags) | |
13 | SDL_LIBS := $(shell $(SDL_CONFIG) --libs) | |
14 | ||
15 | #======================================================= | |
16 | # You should not have to change anything below | |
17 | ||
18 | # Useful directories | |
19 | ||
20 | MYCODEDIR := ./src | |
21 | ||
22 | # Directories to search for header files | |
23 | ||
24 | SEARCHDIRS := -I${MYCODEDIR} ${SDL_HEADERS} | |
25 | ||
26 | # makemake variables | |
27 | ||
28 | LINKER := g++ | |
29 | DEPENDFLAGS := -g ${SEARCHDIRS} | |
30 | TOUCHHEADERS := ${MYCODEDIR}/*.h | |
31 | ||
32 | # C | |
33 | ||
34 | CC := gcc | |
35 | CFLAGS = ${DEPENDFLAGS} | |
36 | ||
37 | # C++ | |
38 | ||
39 | CXX := g++ | |
40 | CXXFLAGS = ${DEPENDFLAGS} -O9 -funroll-loops -fomit-frame-pointer -ffast-math -Wcast-align | |
41 | ||
42 | %.o : %.cpp | |
43 | ${CXX} ${CPPFLAGS} -c $< ${CXXFLAGS} -o $@ | |
44 | ||
45 | %.o : %.cxx | |
46 | ${CXX} ${CPPFLAGS} -c $< ${CXXFLAGS} | |
47 | ||
48 | # C preprocessor (C, C++, FORTRAN) | |
49 | CPPFLAGS = -DINSTALL_DIR="\"${INSTALL_DIR}\"" | |
50 | ||
51 | ifeq ($(USE_LIB_XPM), TRUE) | |
52 | CPPFLAGS := $(CPPFLAGS) -D_USE_LIB_XPM | |
53 | endif | |
54 | ||
55 | # Allow unaligned memory access on IA-32 | |
56 | ifeq ($(HOSTTYPE),i386) | |
57 | CPPFLAGS := $(CPPFLAGS) -D__OPT_MEM_ACCESS__ | |
58 | endif | |
59 | ||
60 | # linker | |
61 | ||
62 | LOADLIBES := -lm $(SDL_LIBS) | |
63 | ||
64 | ifeq ($(USE_LIB_XPM),TRUE) | |
65 | LOADLIBES := $(LOADLIBES) -lXpm -lXt | |
66 | endif | |
67 | ||
68 | LDFLAGS = -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib | |
69 | ||
70 | .PHONY : default | |
71 | default : amph | |
72 | ||
73 | .PHONY : install | |
74 | install: amph | |
75 | @./mkinstalldirs ${INSTALL_DIR} | |
76 | @install -c ./amph ${INSTALL_DIR} | |
77 | @strip ${INSTALL_DIR}/amph | |
78 | @ln -s ${INSTALL_DIR}/amph ${PREFIX}/bin/amph | |
79 | ||
80 | # This is what makemake added | |
81 | ||
82 | ||
83 | # amph | |
84 | ||
85 | amph : ./src/Element.o ./src/File.o ./src/Gifload.o ./src/Graphfil.o ./src/Gui.o ./src/Appl.o ./src/Bullet.o ./src/Clut.o ./src/ConstVal.o ./src/Creeper.o ./src/Item.o ./src/Level.o ./src/Main.o ./src/Monster.o ./src/Monstrxx.o ./src/Object.o ./src/ObjInfo.o ./src/Player.o ./src/Pltform.o ./src/Shape.o ./src/ShapeLd.o ./src/Surface.o ./src/Thing.o ./src/Weapon.o ./src/System.o ./src/SndSys.o ./src/SoundList.o | |
86 | ${LINKER} ${LDFLAGS} -o $@ ${filter-out %.a %.so, $^} ${LOADLIBES} | |
87 | ||
88 | ||
89 | # target for making everything | |
90 | ||
91 | .PHONY : all | |
92 | all: amph | |
93 | ||
94 | ||
95 | # target for removing all object files | |
96 | ||
97 | .PHONY : tidy | |
98 | tidy:: | |
99 | @${RM} core ./src/Appl.o ./src/Bullet.o ./src/Clut.o ./src/ConstVal.o ./src/Creeper.o ./src/Element.o ./src/File.o ./src/Gifload.o ./src/Graphfil.o ./src/Gui.o ./src/Item.o ./src/Level.o ./src/Main.o ./src/Monster.o ./src/Monstrxx.o ./src/ObjInfo.o ./src/Object.o ./src/Player.o ./src/Pltform.o ./src/Shape.o ./src/ShapeLd.o ./src/SndSys.o ./src/SoundList.o ./src/Surface.o ./src/System.o ./src/Thing.o ./src/Weapon.o | |
100 | ||
101 | # target for removing all object files | |
102 | ||
103 | .PHONY : clean | |
104 | clean:: tidy | |
105 | @${RM} amph | |
106 | ||
107 | # list of all source files | |
108 | ||
109 | MM_ALL_SOURCES := ./src/Appl.cpp ./src/Bullet.cpp ./src/Clut.cpp ./src/ConstVal.cpp ./src/Creeper.cpp ./src/Element.cpp ./src/File.cpp ./src/Gifload.cpp ./src/Graphfil.cpp ./src/Gui.cpp ./src/Item.cpp ./src/Level.cpp ./src/Main.cpp ./src/Monster.cpp ./src/Monstrxx.cpp ./src/ObjInfo.cpp ./src/Object.cpp ./src/Player.cpp ./src/Pltform.cpp ./src/Shape.cpp ./src/ShapeLd.cpp ./src/SndSys.cpp ./src/SoundList.cpp ./src/Surface.cpp ./src/System.cpp ./src/Thing.cpp ./src/Weapon.cpp | |
110 | ||
111 | ||
112 | # target for checking a source file | |
113 | ||
114 | CHECKSYNTAXFILE := ${basename ${filter %${CHECKSTRING}, ${MM_ALL_SOURCES}}} | |
115 | ||
116 | .PHONY : checksyntax | |
117 | checksyntax: | |
118 | ifneq (${CHECKSYNTAXFILE},) | |
119 | @${MAKE} ${addsuffix .o, ${CHECKSYNTAXFILE}} | |
120 | else | |
121 | @echo No target to make ${CHECKSTRING} | |
122 | endif | |
123 | ||
124 | ||
125 | # target for touching appropriate source files | |
126 | ||
127 | .PHONY : touch | |
128 | touch: | |
129 | @echo | |
130 | @echo Please ignore \"file arguments missing\" errors | |
131 | @echo | |
132 | @echo `grep -l ${TOUCHSTRING} ${MM_ALL_SOURCES}` | |
133 | @-touch `grep -l ${TOUCHSTRING} ${MM_ALL_SOURCES}` | |
134 | @echo | |
135 | @echo `grep -l ${TOUCHSTRING} ${TOUCHHEADERS}` | |
136 | @-touch `grep -l ${TOUCHSTRING} ${TOUCHHEADERS}` | |
137 | ||
138 | ||
139 | # target for calculating dependencies | |
140 | ||
141 | .PHONY : jdepend | |
142 | jdepend: | |
143 | @makemake -depend Makefile -- ${DEPENDFLAGS} -- ./src/Appl.cpp ./src/Appl.o ./src/Bullet.cpp ./src/Bullet.o ./src/Clut.cpp ./src/Clut.o ./src/ConstVal.cpp ./src/ConstVal.o ./src/Creeper.cpp ./src/Creeper.o ./src/Element.cpp ./src/Element.o ./src/File.cpp ./src/File.o ./src/Gifload.cpp ./src/Gifload.o ./src/Graphfil.cpp ./src/Graphfil.o ./src/Gui.cpp ./src/Gui.o ./src/Item.cpp ./src/Item.o ./src/Level.cpp ./src/Level.o ./src/Main.cpp ./src/Main.o ./src/Monster.cpp ./src/Monster.o ./src/Monstrxx.cpp ./src/Monstrxx.o ./src/ObjInfo.cpp ./src/ObjInfo.o ./src/Object.cpp ./src/Object.o ./src/Player.cpp ./src/Player.o ./src/Pltform.cpp ./src/Pltform.o ./src/Shape.cpp ./src/Shape.o ./src/ShapeLd.cpp ./src/ShapeLd.o ./src/SndSys.cpp ./src/SndSys.o ./src/SoundList.cpp ./src/SoundList.o ./src/Surface.cpp ./src/Surface.o ./src/System.cpp ./src/System.o ./src/Thing.cpp ./src/Thing.o ./src/Weapon.cpp ./src/Weapon.o | |
144 | ||
145 | ||
146 | # DO NOT DELETE THIS LINE -- makemake depends on it. | |
147 | ||
148 | ./src/Appl.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
149 | ||
150 | ./src/Bullet.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
151 | ||
152 | ./src/Clut.o: ./src/AmpHead.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
153 | ||
154 | ./src/ConstVal.o: ./src/AmpHead.hpp ./src/ConstVal.hpp ./src/System.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h | |
155 | ||
156 | ./src/Creeper.o: ./src/AmpHead.hpp ./src/Creeper.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Shape.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
157 | ||
158 | ./src/Element.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
159 | ||
160 | ./src/File.o: ./src/AmpHead.hpp ./src/File.hpp ./src/System.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
161 | ||
162 | ./src/Gifload.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h | |
163 | ||
164 | ./src/Graphfil.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h | |
165 | ||
166 | ./src/Gui.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
167 | ||
168 | ./src/Item.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Item.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
169 | ||
170 | ./src/Level.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/time.h | |
171 | ||
172 | ./src/Main.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
173 | ||
174 | ./src/Monster.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
175 | ||
176 | ./src/Monstrxx.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/Monster.hpp ./src/Monstrxx.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
177 | ||
178 | ./src/ObjInfo.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Item.hpp ./src/Level.hpp ./src/Monster.hpp ./src/Monstrxx.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeDes.hpp ./src/ShapeLd.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
179 | ||
180 | ./src/Object.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
181 | ||
182 | ./src/Player.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Gui.hpp ./src/Item.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeDes.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
183 | ||
184 | ./src/Pltform.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/Monster.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Player.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
185 | ||
186 | ./src/Shape.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
187 | ||
188 | ./src/ShapeLd.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeDes.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
189 | ||
190 | ./src/SndSys.o: ./src/AmpHead.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
191 | ||
192 | ./src/SoundList.o: ./src/AmpHead.hpp ./src/SoundList.hpp ./src/System.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
193 | ||
194 | ./src/Surface.o: ./src/AmpHead.hpp ./src/Clut.hpp ./src/ConstVal.hpp ./src/Graphfil.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
195 | ||
196 | ./src/System.o: ./src/AmpHead.hpp ./src/Graphfil.hpp ./src/System.hpp /usr/include/X11/xpm.h /usr/include/fcntl.h /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h /usr/include/string.h /usr/include/sys/stat.h /usr/include/sys/time.h /usr/include/sys/types.h /usr/include/unistd.h | |
197 | ||
198 | ./src/Thing.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
199 | ||
200 | ./src/Weapon.o: ./src/AmpHead.hpp ./src/Appl.hpp ./src/Bullet.hpp ./src/ConstVal.hpp ./src/Element.hpp ./src/File.hpp ./src/Graphfil.hpp ./src/Level.hpp ./src/ObjInfo.hpp ./src/Object.hpp ./src/Pltform.hpp ./src/Shape.hpp ./src/ShapeLd.hpp ./src/SndSys.hpp ./src/SoundList.hpp ./src/Surface.hpp ./src/System.hpp ./src/Thing.hpp ./src/Weapon.hpp /usr/include/limits.h /usr/include/math.h /usr/include/stdio.h /usr/include/stdlib.h | |
201 |
0 | March 25th, 2002, 0.8.10 | |
1 | - Fixed the bug where monsters just froze after playing | |
2 | a while. | |
3 | - Endianness autodetected by SDL | |
4 | - Minor bugfixes | |
5 | ||
6 | September 17th, 2001, 0.8.9 | |
7 | - Fixed compilation bug under Linux Mandrake 8.0 (gcc 2.96) | |
8 | - Simplified configuration of the build process | |
9 | ||
10 | February 27th, 2000, 0.8.8 | |
11 | - Compiles smoother with SDL 1.0 | |
12 | - Using sdl-config in the Makefile | |
13 | - Minor bugfixes | |
14 | ||
15 | November 18th, 1999, 0.8.7 | |
16 | - An old version of ObjInfo.cpp was included with | |
17 | version 0.8.6, that prevented the game from running | |
18 | on big-endian machines. | |
19 | ||
20 | November 11th, 1999: 0.8.6 | |
21 | - Compiles and works under SPARC/Solaris | |
22 | Check the TARGET_ARCH variable in the Makefile! | |
23 | ||
24 | October 30th, 1999: 0.8.5 | |
25 | - Compiles without libXpm (no icon) | |
26 | ||
27 | October 18th, 1999: 0.8.4 | |
28 | - Even cleaner sound system :) | |
29 | ||
30 | September 4th, 1999: 0.8.3 | |
31 | - Fixed a bug that crashed the game in some situations if you | |
32 | had no sound card. | |
33 | ||
34 | September 3rd, 1999: 0.8.2 | |
35 | - Fixed some bugs in ObjInfo.cpp and ShapeLd.cpp that prevented | |
36 | compilation with gcc 2.95 (thanks to Ralph Giles and Bernhard Trummer)). | |
37 | - More fixes to the sound system | |
38 | - New command line options (try --help) | |
39 | - DGA support (option --fullscreen) | |
40 | ||
41 | July 16th, 1999: 0.8.1 | |
42 | - Fixed some bug in the sound system | |
43 | - Added some cheats (unsupported) | |
44 | - Added an icon |
0 | AUTHORS | |
1 | ||
2 | Amphetamine was created by Jonas Spillmann <jsp@stutent.ethz.ch>. | |
3 | ||
4 | The Unix/SDL version is maintained by Lukas Loehrer <loehrerl@bigfoot.com> | |
5 | ||
6 | REQUIREMENTS | |
7 | ||
8 | SDL (Simple DirectMedia Layer) version >= 1.0 | |
9 | Get it from: | |
10 | http://www.devolution.com/~slouken/projects/SDL/index.html | |
11 | ||
12 | CONTROLS | |
13 | ||
14 | left/right arrows move | |
15 | left control fire | |
16 | space bar jump | |
17 | tab action (press buttons) | |
18 | ESC menu | |
19 | ||
20 | ALT+s screenshot | |
21 | ||
22 | You can customize most controls by copying the file user.conf | |
23 | from the Amphetamine data directory to your ~/.amph directory. | |
24 | Modify it to suit your needs. | |
25 | ||
26 | GAMEPLAY | |
27 | ||
28 | Many aspect of the gameplay are controlled by the file amph.conf | |
29 | in the main Amphetamine directory. Of most interest are the options | |
30 | right at the beginning of the file that control the physics. If the | |
31 | game seems to slow/fast to you, changing some of those values may help. | |
32 | ||
33 | DGA MODE | |
34 | ||
35 | Use the option --fullscreen to enable DGA fullscreen support. I cannot test | |
36 | this myself, because my X Server does not support it properly. I am grateful | |
37 | for any feedback regarding this option. | |
38 | ||
39 | SPARC/Solaris | |
40 | ||
41 | I was told that Amphetamine runs very slow on some SPARC machines. | |
42 | ||
43 | LICENCE | |
44 | ||
45 | This program is licensed under the terms of the GNU GPL, a copy | |
46 | of which you should have received with this package. | |
47 | ||
48 | PLANS | |
49 | ||
50 | - Fixing the clipping bugs | |
51 | - Fixing the strange bug involving flying monsters |
0 | /* XPM */ | |
1 | static char * amph_xpm[] = { | |
2 | "48 48 66 1", | |
3 | " c None", | |
4 | ". c #FFCC66", | |
5 | "+ c #FFCC99", | |
6 | "@ c #FF9966", | |
7 | "# c #CC9966", | |
8 | "$ c #CC9933", | |
9 | "% c #996633", | |
10 | "& c #663333", | |
11 | "* c #996666", | |
12 | "= c #666633", | |
13 | "- c #555555", | |
14 | "; c #993333", | |
15 | "> c #FFCC33", | |
16 | ", c #FF9933", | |
17 | "' c #444444", | |
18 | ") c #CCCC66", | |
19 | "! c #666666", | |
20 | "~ c #220000", | |
21 | "{ c #FFFF66", | |
22 | "] c #330000", | |
23 | "^ c #111111", | |
24 | "/ c #CC6633", | |
25 | "( c #110000", | |
26 | "_ c #222222", | |
27 | ": c #FFFF99", | |
28 | "< c #CC6666", | |
29 | "[ c #993366", | |
30 | "} c #333300", | |
31 | "| c #663300", | |
32 | "1 c #333333", | |
33 | "2 c #CC9900", | |
34 | "3 c #996600", | |
35 | "4 c #66FFCC", | |
36 | "5 c #66FFFF", | |
37 | "6 c #66CCCC", | |
38 | "7 c #000000", | |
39 | "8 c #CCFFFF", | |
40 | "9 c #DDDDDD", | |
41 | "0 c #336600", | |
42 | "a c #004400", | |
43 | "b c #003300", | |
44 | "c c #666600", | |
45 | "d c #005500", | |
46 | "e c #006600", | |
47 | "f c #CC3333", | |
48 | "g c #007700", | |
49 | "h c #999999", | |
50 | "i c #CC9999", | |
51 | "j c #66CC66", | |
52 | "k c #999966", | |
53 | "l c #99FFFF", | |
54 | "m c #FFCCCC", | |
55 | "n c #002200", | |
56 | "o c #BBBBBB", | |
57 | "p c #001100", | |
58 | "q c #CCCC99", | |
59 | "r c #CCCCCC", | |
60 | "s c #888888", | |
61 | "t c #CC99CC", | |
62 | "u c #996699", | |
63 | "v c #EEEEEE", | |
64 | "w c #FFFFFF", | |
65 | "x c #440000", | |
66 | "y c #AAAAAA", | |
67 | "z c #FF9999", | |
68 | "A c #CC3366", | |
69 | ".+................@@@.#.@#$$%&&*&=&-;-&&%*;%*%-;", | |
70 | ".......+.+.+.+......>....,#@%'=*%*&%-&=*;=%;%;%%", | |
71 | "..............)@).@.@.@$,#,$%&*%*%!;%*~~~~~%*%*%", | |
72 | "+......+.+{+....+.....,@@,$@#*%*%%%*]~-&^~^~~%;*", | |
73 | "....++........+.$$/$#)@#,$//$/*;%;*~~~~(_~~(~~*%", | |
74 | "..+++{+.+.+.+:..@@#$@,,$<%<*%%%%[&;]]}|]|1~~~~%;", | |
75 | "....+.+........#/%/<$</*/%%<%[*%%%%~|23%/|}_]_~%", | |
76 | ".+++...+.+..)4)@%%#/<5*/*<*%*%;*%[%]32233|&(}]~*", | |
77 | "+.+..+...)...445//<655<%<%;%*%*%;*%]|||||3|}_~~%", | |
78 | ":+).+..@..@#@#665*655<%*%**%;*/*%%;|733773||7]]<", | |
79 | ".+.....$###/##<48855*%<<</*<%*;*<%*33233333|-]];", | |
80 | "+.+.+..@@#//</%98858/*<*%**%<*/*%*%%3232|33%%]%%", | |
81 | ".+.....@$$/<<%6555855<%%%<%<%<%*%<%*||||33%3|<%*", | |
82 | "+.+..@#$<<<#/*55%<<65%*<<%*;;%*/*%[%323333%|0%*/", | |
83 | ".+...#,#$</*</*<<*%<%<%*%</*%*%*/*/*|2|%|abab000", | |
84 | "+..@#$##<%</<*/*%/[%<*/%[%*<%<<;*;*00ababa_5a}|0", | |
85 | "+.###<#<%#/**%<*/*%*%;%[/%*%*;%*%%00c}d0050aa5ae", | |
86 | "..#</</%#/*/*<*/*%*/[*%<%*f*/**;5[000505d5d5a|ag", | |
87 | "+.##*<*/<%*%<%<%*f*%%%;*<%*5[5/*<53|505555505bga", | |
88 | "..@##<*<#h#iiiii#*/*<<<%;5;%%55555555588885b38j0", | |
89 | "+..@i#ik*<**<%<#iiih%%%<**[%5%5;;535555585l8jj3a", | |
90 | "..+i#ih%<*<%%**h<%i#*i*%*/%<%*5*5335505l5l5j3||a", | |
91 | ".+i#<*i*/*<*<<ii<%***#i<%*<%;%;%335%=50585555|b}", | |
92 | "m.#/<#i#hikihki#hh<%<*<ih;%*<*&;333&a008885c_5-}", | |
93 | ".//**i#ii#ii#iiii#ih<%**##*/*%*%;&=;5da888d5an}7", | |
94 | ";$iki#iiiiiiiioi#iiih<ik*kh*%<%*%*%dd5nn8cdpnan%", | |
95 | "#<##iiio+ooiimqoii##k***%<#*<%[%*%[a5aa5n&d==pa|", | |
96 | "<#i#iiiqr+momrmmmooi<s***<*i<*/*;*5ddnn5*=&daa%|", | |
97 | "#i<iimqrmrrrq99mrmiiqi#h*;/h#<*;*%%ddaaa%[%;a|/|", | |
98 | "iiiioqmm9mmmm999roqtii#uk**/h*%*%[%3|3||%*;%*3||", | |
99 | "#oqm+r9rv9999v9r9rrrqiiiii*<*h;*%%[33/||*/&;%3%3", | |
100 | "#i+rrm999vvv9vv999rroqoi#k%*<ih;*;%3/|||%*;*;%|3", | |
101 | "iiom9999vvvvvvvv9v9rroii<iiihi<%;%%%|%||<*%%%%3%", | |
102 | "imrrmvvvvvvvvvvvv999roiiiii#i#i&%@|/|||%;%&%|%%%", | |
103 | "o+rm99vvvvvwvwvvvv99rrrrooih**#*&%&%&;%[%&&%%&%*", | |
104 | "orrmvvvvvwwwwwwvvvv999roi#ik<*<&&&&&&;*%****&x;*", | |
105 | "qr999vvvwwwwwwwvvvvv9rryoiii*%*&&%&&;*%[%;%;&1&/", | |
106 | "orr9vvvvwwwwwwwwwvvv9rooiii*;&*&=&&&%*%*%*;&%&x&", | |
107 | "qo99vvvwwwwwwwwwvvv9rrrqii#*&=*&&%&&%*%[%%*%&%&&", | |
108 | "orr9vvvvwwwwwwwwvvvv99tqiiik*;*=&&&&;;*%;&&;&&&%", | |
109 | "zrrm9vvvwwwwwwvvvvvv999roi#****&%&&%%*%;&&&_&&%;", | |
110 | "oqrr9vvvvwwwwwwwvv99mmrrqoi#hk*%&;&%[%;;1&&|&%[%", | |
111 | "mr9999vvvvvwwwvvvv9rrrmoi#i**h*&=*;&%*%&&&%*;*&;", | |
112 | "q+mr999vvvvvvvvvvv99roqii<k*%*i;&=&&&;%&&;<;%%;%", | |
113 | "ioqrrm9vvvvvvvvv9999rihs#i*%*u*&&;=&&&&&&%;%<;*%", | |
114 | "iit+rr999vvvv9vvm999roi*****;#*%%&&&%&&&&%*%*%/A", | |
115 | "kiiqor99rr9v99m99mmooti**!&;***;&&=;-&=;*<%</*;%", | |
116 | "#iioroorrr99mr9mmqmiyih**!&&<*%;%&&&&&;%%;*;;;%;"}; |
19 | 19 | Try to run in DGA fullscreen mode. For this to work, you must be root. |
20 | 20 | .TP |
21 | 21 | .B \-v, \-\-version |
22 | Display version infomation and exit. | |
22 | Display version information and exit. | |
23 | 23 | .SH AUTHOR |
24 | 24 | This manual page was written by Joey Hess, |
25 | 25 | for the Debian GNU/Linux system. |
0 | 0 | [Desktop Entry] |
1 | 1 | Name=Amphetamine |
2 | 2 | GenericName=Jump and Run game |
3 | Comment=Fight evil monsters with your magic weapons. | |
3 | Comment=Fight evil monsters with your magic weapons | |
4 | Comment[de]=Bekämpfe böse Monster mit deinen magischen Waffen | |
4 | 5 | Type=Application |
5 | 6 | Exec=amph |
6 | 7 | Icon=amph |
7 | 8 | Terminal=false |
8 | 9 | Categories=Game;ActionGame; |
9 | Keywords=Games | |
10 | Keywords=jump;run;action; |
0 | amph /usr/games | |
1 | debian/amph.xpm /usr/share/pixmaps | |
0 | 2 | debian/amphetamine.desktop /usr/share/applications |
1 | debian/amph.xpm /usr/share/pixmaps | |
2 | amph /usr/games |
0 | ?package(amphetamine):needs="x11" section="Games/Action" \ | |
1 | title="Amphetamine" command="/usr/games/amph" \ | |
2 | icon="/usr/share/pixmaps/amph.xpm" |
0 | amphetamine (0.8.10-20) unstable; urgency=medium | |
1 | ||
2 | * Team upload. | |
3 | * Switch to compat level 11. | |
4 | * wrap-and-sort -sa. | |
5 | * Declare compliance with Debian Policy 4.1.4. | |
6 | * Update homepage address and point to tracker.debian.org because the old one | |
7 | is gone. | |
8 | * Move the package to Git and salsa.debian.org. | |
9 | * Drop deprecated amphetamine.menu file. | |
10 | * Add a comment in German to desktop file. | |
11 | * Remove 000_gcc_m68k.diff because it is unused. | |
12 | ||
13 | -- Markus Koschany <apo@debian.org> Thu, 17 May 2018 13:11:39 +0200 | |
14 | ||
0 | 15 | amphetamine (0.8.10-19) unstable; urgency=low |
1 | 16 | |
2 | 17 | [ Ansgar Burchardt ] |
32 | 47 | |
33 | 48 | amphetamine (0.8.10-16) unstable; urgency=low |
34 | 49 | |
35 | * build-depend on libc6-dev-i386 (closes: #640554). | |
50 | * build-depend on libc6-dev-i386 (closes: #640554). | |
36 | 51 | * use -iquote and -Wno-write-strings build flags. |
37 | 52 | * bump standards version to 3.9.2. |
38 | 53 | |
288 | 303 | |
289 | 304 | * Rebuilt with libsdl1.0, fixes missing libsdl dependancy, Closes: #55350 |
290 | 305 | * Hm, this bug seems vaguly important to me, but the submitter did not |
291 | flag it as such. Uploading to frozen, at the release manager's | |
306 | flag it as such. Uploading to frozen, at the release manager's | |
292 | 307 | discretion -- I have no strong feelings either way, but a few people on |
293 | 308 | IRC think it should go in. |
294 | 309 |
1 | 1 | Section: games |
2 | 2 | Priority: optional |
3 | 3 | Build-Depends: |
4 | debhelper (>= 9), | |
5 | libxpm-dev, | |
4 | debhelper (>= 11), | |
6 | 5 | imagemagick, |
7 | 6 | libsdl1.2-dev (>= 1.2.2-3.1), |
7 | libxpm-dev | |
8 | 8 | Maintainer: Debian Games Team <pkg-games-devel@lists.alioth.debian.org> |
9 | Uploaders: | |
9 | Uploaders: | |
10 | 10 | Sam Hocevar (Debian packages) <sam+deb@zoy.org>, |
11 | 11 | Barry deFreese <bddebian@comcast.net>, |
12 | 12 | Michael Gilbert <mgilbert@debian.org> |
13 | Standards-Version: 3.9.5 | |
14 | Homepage: http://homepage.hispeed.ch/loehrer/amph/amph.html | |
15 | Vcs-Git: git://anonscm.debian.org/pkg-games/amphetamine.git | |
16 | Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-games/packages/trunk/amphetamine/ | |
13 | Standards-Version: 4.1.4 | |
14 | Homepage: https://tracker.debian.org/pkg/amphetamine | |
15 | Vcs-Git: https://salsa.debian.org/games-team/amphetamine.git | |
16 | Vcs-Browser: https://salsa.debian.org/games-team/amphetamine | |
17 | 17 | |
18 | 18 | Package: amphetamine |
19 | 19 | Architecture: any |
20 | 20 | Depends: |
21 | 21 | amphetamine-data (>= 0.8.7-12), |
22 | ${shlibs:Depends}, | |
23 | ${misc:Depends} | |
22 | ${misc:Depends}, | |
23 | ${shlibs:Depends} | |
24 | 24 | Description: jump'n run game with unique visual effects |
25 | 25 | Amphetamine is an exciting jump'n run game that offers some unique visual |
26 | 26 | effects like colored lighting, fogging and coronas. You must fight eleven |
27 | evil monsters with your magic weapons. | |
27 | evil monsters with your magic weapons. |
44 | 44 | ** GNU General Public License for more details. |
45 | 45 | |
46 | 46 | The remainder of amphetamine was written by Jonas Spillmann |
47 | <jsp@stutent.ethz.ch>, and is is GPL'd. | |
47 | <jsp@stutent.ethz.ch>, and is is GPL'd. | |
48 | 48 | |
49 | 49 | On Debian systems, the full text of the GPL can be found in |
50 | 50 | /usr/share/common-licenses/GPL-2. |
0 | description: use gcc 4.1 for m68k build | |
1 | Index: amphetamine-0.8.10/Makefile | |
2 | =================================================================== | |
3 | --- amphetamine-0.8.10.orig/Makefile 2006-05-15 19:26:37.000000000 +0200 | |
4 | +++ amphetamine-0.8.10/Makefile 2006-05-15 19:34:04.000000000 +0200 | |
5 | @@ -13,6 +13,12 @@ | |
6 | SDL_HEADERS := $(shell $(SDL_CONFIG) --cflags) | |
7 | SDL_LIBS := $(shell $(SDL_CONFIG) --libs) | |
8 | ||
9 | +ifeq ($(shell uname -m), m68k) | |
10 | +GXX = g++-4.1 | |
11 | +else | |
12 | +GXX = g++ | |
13 | +endif | |
14 | + | |
15 | #======================================================= | |
16 | # You should not have to change anything below | |
17 | ||
18 | @@ -26,7 +32,7 @@ | |
19 | ||
20 | # makemake variables | |
21 | ||
22 | -LINKER := g++ | |
23 | +LINKER := $(GXX) | |
24 | DEPENDFLAGS := -g ${SEARCHDIRS} | |
25 | TOUCHHEADERS := ${MYCODEDIR}/*.h | |
26 | ||
27 | @@ -37,7 +43,7 @@ | |
28 | ||
29 | # C++ | |
30 | ||
31 | -CXX := g++ | |
32 | +CXX := $(GXX) | |
33 | CXXFLAGS = ${DEPENDFLAGS} -O9 -funroll-loops -fomit-frame-pointer -ffast-math -Wcast-align | |
34 | ||
35 | %.o : %.cpp |
0 | description: append to build flags | |
1 | Index: amphetamine/Makefile | |
2 | =================================================================== | |
3 | --- amphetamine.orig/Makefile 2014-04-06 04:25:09.713627611 +0000 | |
4 | +++ amphetamine/Makefile 2014-04-06 04:28:04.057623123 +0000 | |
5 | @@ -34,12 +34,12 @@ | |
6 | # C | |
7 | ||
8 | CC := gcc | |
9 | -CFLAGS = ${DEPENDFLAGS} | |
10 | +CFLAGS += ${DEPENDFLAGS} | |
11 | ||
12 | # C++ | |
13 | ||
14 | CXX := g++ | |
15 | -CXXFLAGS = ${DEPENDFLAGS} -O9 -funroll-loops -fomit-frame-pointer -ffast-math -Wcast-align | |
16 | +CXXFLAGS += ${DEPENDFLAGS} -O9 -funroll-loops -fomit-frame-pointer -ffast-math -Wcast-align | |
17 | ||
18 | %.o : %.cpp | |
19 | ${CXX} ${CPPFLAGS} -c $< ${CXXFLAGS} -o $@ | |
20 | @@ -48,7 +48,7 @@ | |
21 | ${CXX} ${CPPFLAGS} -c $< ${CXXFLAGS} | |
22 | ||
23 | # C preprocessor (C, C++, FORTRAN) | |
24 | -CPPFLAGS = -DINSTALL_DIR="\"${INSTALL_DIR}\"" | |
25 | +CPPFLAGS += -DINSTALL_DIR="\"${INSTALL_DIR}\"" | |
26 | ||
27 | ifeq ($(USE_LIB_XPM), TRUE) | |
28 | CPPFLAGS := $(CPPFLAGS) -D_USE_LIB_XPM | |
29 | @@ -67,7 +67,7 @@ | |
30 | LOADLIBES := $(LOADLIBES) -lXpm | |
31 | endif | |
32 | ||
33 | -LDFLAGS = -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib | |
34 | +LDFLAGS += -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib | |
35 | ||
36 | .PHONY : default | |
37 | default : amph |
0 | description: fix a format string issue | |
1 | --- a/src/AmpHead.hpp | |
2 | +++ b/src/AmpHead.hpp | |
3 | @@ -183,6 +183,6 @@ typedef struct { | |
4 | #define SWAP(a, b, _t) (a) = (_t)((long)a ^ (long)(b)); (b) = (_t)((long)(a) ^ (long)(b)); (a) = (_t)((long)(a) ^ (long)(b)); | |
5 | #define NZ(a, b) ((a) == 0 ? (b) : (a)) | |
6 | ||
7 | -#define MSG(message) if (logFile) fprintf(logFile, message); fflush(logFile) | |
8 | +#define MSG(message) if (logFile) fprintf(logFile, "%s", message); fflush(logFile) | |
9 | ||
10 | #endif |
0 | amph | |
1 | src/Appl.o | |
2 | src/Bullet.o | |
3 | src/Clut.o | |
4 | src/ConstVal.o | |
5 | src/Creeper.o | |
6 | src/Element.o | |
7 | src/File.o | |
8 | src/Gifload.o | |
9 | src/Graphfil.o | |
10 | src/Gui.o | |
11 | src/Item.o | |
12 | src/Level.o | |
13 | src/Main.o | |
14 | src/Monster.o | |
15 | src/Monstrxx.o | |
16 | src/ObjInfo.o | |
17 | src/Object.o | |
18 | src/Player.o | |
19 | src/Pltform.o | |
20 | src/Shape.o | |
21 | src/ShapeLd.o | |
22 | src/SndSys.o | |
23 | src/SoundList.o | |
24 | src/Surface.o | |
25 | src/System.o | |
26 | src/Thing.o | |
27 | src/Weapon.o |
0 | #! /bin/sh | |
1 | # mkinstalldirs --- make directory hierarchy | |
2 | # Author: Noah Friedman <friedman@prep.ai.mit.edu> | |
3 | # Created: 1993-05-16 | |
4 | # Public domain | |
5 | ||
6 | # $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ | |
7 | ||
8 | errstatus=0 | |
9 | ||
10 | for file | |
11 | do | |
12 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` | |
13 | shift | |
14 | ||
15 | pathcomp= | |
16 | for d | |
17 | do | |
18 | pathcomp="$pathcomp$d" | |
19 | case "$pathcomp" in | |
20 | -* ) pathcomp=./$pathcomp ;; | |
21 | esac | |
22 | ||
23 | if test ! -d "$pathcomp"; then | |
24 | echo "mkdir $pathcomp" 1>&2 | |
25 | ||
26 | mkdir "$pathcomp" || lasterr=$? | |
27 | ||
28 | if test ! -d "$pathcomp"; then | |
29 | errstatus=$lasterr | |
30 | fi | |
31 | fi | |
32 | ||
33 | pathcomp="$pathcomp/" | |
34 | done | |
35 | done | |
36 | ||
37 | exit $errstatus | |
38 | ||
39 | # mkinstalldirs ends here |
0 | #ifndef __AMP_HEADER__ | |
1 | #define __AMP_HEADER__ | |
2 | ||
3 | #include "limits.h" | |
4 | #include "float.h" | |
5 | ||
6 | const long kVersionNumber = 0x0090; | |
7 | const char kVersionString[] = "0.8.10"; // by LL | |
8 | const long kVersionKey = 10835; | |
9 | const char kMyName1[6] = "JONAS"; | |
10 | const char kMyName2[10] = "SPILLMANN"; | |
11 | const char kParFileName[] = "amph.conf"; // by LL | |
12 | const char kLogFileName[] = "logfile"; | |
13 | ||
14 | enum { | |
15 | // Gameplane | |
16 | kGamePlaneWidth = 480, | |
17 | kGamePlaneHeight = 480, | |
18 | kUserPlaneWidth = 160, | |
19 | ||
20 | // Num and size of level elements | |
21 | kElementSize = 32, | |
22 | kLevelWidth = 100, | |
23 | kLevelHeight = 20, | |
24 | ||
25 | // Screen resolution | |
26 | kScreenWidth = 1280, | |
27 | kScreenHeight = 1024, | |
28 | kScreenDepth = 8, | |
29 | ||
30 | kNumOfLevels = 15, | |
31 | ||
32 | ||
33 | // Monster classes | |
34 | kClassPlayer = 0, | |
35 | kClassCreeper = 1, | |
36 | kClassJumper = 2, | |
37 | kClassFlyer = 3, | |
38 | kClassWalker = 4, | |
39 | kClassWarg = 5, | |
40 | ||
41 | // Item classes | |
42 | kClassBackgroundItem = 0, | |
43 | kClassUnpassableItem = 1, | |
44 | kClassMovableItem = 2, | |
45 | kClassPortableItem = 3, | |
46 | ||
47 | // Flags for flags field in item info | |
48 | kItemUnpassableMask = 32768, | |
49 | kItemPortableMask = 16384, | |
50 | kItemHurtMask = 8192, | |
51 | kItemExplodesMask = 4096, | |
52 | ||
53 | ||
54 | // Flags for data field | |
55 | kPassiveLightMask = 1, | |
56 | kPassivePlatformMask = 2, | |
57 | kRightDriftMask = 4, | |
58 | kLeftDriftMask = 8, | |
59 | kIceMask = 16, | |
60 | kFlickeringMask = 32, | |
61 | kInfotextMask = 64, | |
62 | kHurtMask = 128, | |
63 | kFogMask = 256, | |
64 | kWaterMask = 512, | |
65 | kLavaMask = 1024, | |
66 | kTeleportMask = 2048, | |
67 | kExitMask = 4096, | |
68 | kSaveMask = 8192, | |
69 | kLightSwitchMask = 16384, | |
70 | kPlatformSwitchMask = 32768, | |
71 | ||
72 | // Collision codes | |
73 | kNoCollision = 0, | |
74 | kCollisionOnTop = 1, | |
75 | kCollisionOnLeft = 2, | |
76 | kCollisionOnRight = 4, | |
77 | kCollisionOnBottom = 8, | |
78 | kCollisionWithPushing = 16, | |
79 | kCollisionWithLevelBorders = 32, | |
80 | ||
81 | // Return codes for ::Think and ::Move | |
82 | kNoEvent = 0, | |
83 | kDestroyMe = 1, | |
84 | ||
85 | kCameraNo = 12 | |
86 | }; | |
87 | ||
88 | // Type IDs | |
89 | enum { | |
90 | kObject = 1, | |
91 | kElement = 1 << 1, | |
92 | kBackgroundElement =1 << 2, | |
93 | kThing = 1 << 3, | |
94 | kMonster = 1 << 4, | |
95 | kPlayer = 1 << 5, | |
96 | kItem = 1 << 6, | |
97 | kStaticItem = 1 << 7, | |
98 | kBackgroundItem = 1 << 8, | |
99 | kMovableItem = 1 << 9, | |
100 | kPortableItem = 1 << 10, | |
101 | kPlatform = 1 << 11, | |
102 | kBullet = 1 << 12, | |
103 | kSorceryBullet = 1 << 13, | |
104 | kBombBullet = 1 << 14, | |
105 | kSineBullet = 1 << 15, | |
106 | kGuidedBullet = 1 << 16, | |
107 | kCreeper = 1 << 17, | |
108 | kWalker = 1 << 18, | |
109 | kJumper = 1 << 19, | |
110 | kFlyer = 1 << 20, | |
111 | kWarg = 1 << 21, | |
112 | kCamera = 1 << 22 | |
113 | }; | |
114 | ||
115 | // Modi for drawing a shape | |
116 | enum { | |
117 | kShapemodusNormal = 0, | |
118 | kShapemodusTransparent1, | |
119 | kShapemodusTransparent2, | |
120 | kShapemodusTransparent3, | |
121 | kShapemodusRandom, | |
122 | kShapemodusWater, | |
123 | kShapemodusLava, | |
124 | kShapemodusFog, | |
125 | kShapemodusShadow, | |
126 | kShapemodusBackwardFlag = 32768 // when set, the shape is drawn horizontally inverted | |
127 | }; | |
128 | ||
129 | enum { | |
130 | kWeaponNormal = 0, | |
131 | kWeaponSorcery, | |
132 | kWeaponMultibullet, | |
133 | kWeaponBomb, | |
134 | kWeaponStaff, | |
135 | kWeaponInHand, | |
136 | kWeaponSine, | |
137 | kWeaponGuided, | |
138 | kWeaponHasWeight | |
139 | }; | |
140 | ||
141 | // Weapon stati | |
142 | enum { | |
143 | kWeaponDoesntExist, | |
144 | kWeaponOutOfMunition, | |
145 | kWeaponReady | |
146 | }; | |
147 | ||
148 | ||
149 | enum { // Portable Items | |
150 | kItemSword = 0, | |
151 | kItemPhiol, | |
152 | kItemSorcery, | |
153 | kItemBow, | |
154 | kItemScie, | |
155 | kItemHands, | |
156 | kItemBomb, | |
157 | kItemStaff, | |
158 | kItemPhiolmun, | |
159 | kItemSorcerymun, | |
160 | kItemBowmun, | |
161 | kItemSciemun, // not used | |
162 | kItemHandsmun, | |
163 | kItemBombmun, | |
164 | kItemStaffmun, | |
165 | kItemOxygen, | |
166 | kItemHelppacket | |
167 | }; | |
168 | ||
169 | struct tRect { | |
170 | short left, top, right, bottom; | |
171 | }; | |
172 | ||
173 | typedef struct { | |
174 | unsigned char red, green, blue; | |
175 | } RGBcolor; | |
176 | ||
177 | ||
178 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | |
179 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
180 | #define ABS(a) ((a) > 0 ? (a) : (-(a))) | |
181 | #define SIGN(a) ((a) >= 0 ? 1 : -1) | |
182 | #define SWAP(a, b, _t) (a) = (_t)((long)a ^ (long)(b)); (b) = (_t)((long)(a) ^ (long)(b)); (a) = (_t)((long)(a) ^ (long)(b)); | |
183 | #define NZ(a, b) ((a) == 0 ? (b) : (a)) | |
184 | ||
185 | #define MSG(message) if (logFile) fprintf(logFile, message); fflush(logFile) | |
186 | ||
187 | #endif⏎ |
0 | #include "Appl.hpp" | |
1 | #include "System.hpp" | |
2 | #include "Clut.hpp" | |
3 | #include "Gui.hpp" | |
4 | #include "SndSys.hpp" | |
5 | #include <stdio.h> | |
6 | ||
7 | extern CSystem *gSystem; | |
8 | extern CLevel *gLevel; | |
9 | extern CObjInfo *gObjInfo; | |
10 | extern CShapeManager *gShapeManager; | |
11 | extern CClutManager *gClutManager; | |
12 | extern tConstValues *gConst; | |
13 | extern CGUI *gGUI; | |
14 | extern tGUIConstants *gGUIConst; | |
15 | extern tConfigData *gConfigData; | |
16 | extern CSoundSystem *gSoundSystem; | |
17 | ||
18 | FILE *logFile; | |
19 | ||
20 | void LoadParameters(); | |
21 | void LoadGUIParameters(); // in GUI.cpp | |
22 | void StartupSoundSystem(); | |
23 | void ShutdownSoundSystem(); | |
24 | ||
25 | CApplication::CApplication() | |
26 | { | |
27 | MSG("new CSystem\n"); | |
28 | gSystem = new CSystem("Amphetamine"); | |
29 | ||
30 | MSG("LoadParameters()\n"); | |
31 | LoadParameters(); | |
32 | ||
33 | gSystem->NewWindow(0, 0, gConfigData->screenWidth, gConfigData->screenHeight); | |
34 | ||
35 | MSG("LoadGUIParameters\n"); | |
36 | LoadGUIParameters(); | |
37 | ||
38 | MSG("new CSoundSystem\n"); | |
39 | gSoundSystem = new CSoundSystem(gSystem->workingSound); | |
40 | } | |
41 | ||
42 | CApplication::~CApplication() | |
43 | { | |
44 | delete gSoundSystem; | |
45 | ||
46 | delete gConst; | |
47 | delete gGUIConst; | |
48 | delete gConfigData; | |
49 | ||
50 | gSystem->DisposeWindow(); | |
51 | delete gSystem; | |
52 | ||
53 | fclose(logFile); | |
54 | } | |
55 | ||
56 | ||
57 | void CApplication::InitGraphics() | |
58 | { | |
59 | MSG("gSystem->AllocateScreen\n"); | |
60 | gSystem->AllocateScreen(gConfigData->screenWidth, gConfigData->screenHeight, kScreenDepth); | |
61 | ||
62 | MSG("gSystem->LoadPalette\n"); | |
63 | gSystem->LoadPalette(gConst->kFilePalette); | |
64 | } | |
65 | ||
66 | void CApplication::LoadData() | |
67 | { | |
68 | long startupTime; | |
69 | ||
70 | MSG("new CClutManager\n"); | |
71 | gClutManager = new CClutManager(); | |
72 | MSG("Loading Palette\n"); | |
73 | gClutManager->LoadPalette(gSystem->palColors); | |
74 | MSG("Building Luminosity Table\n"); | |
75 | gClutManager->BuildLuminosityTable(); | |
76 | ||
77 | MSG("new CGraphicsSurface (startup)\n"); | |
78 | startup = new CGraphicSurface(kGamePlaneWidth + kUserPlaneWidth, kGamePlaneHeight); | |
79 | MSG("startup->Insert Graphic\n"); | |
80 | startup->InsertGraphic(gSystem->QualifyDataDir(gConst->kFileStartup), 0L, 0L); // by LL | |
81 | MSG("startup->PaintGraphic\n"); | |
82 | startup->PaintGraphic(0, 0, 0, kShapemodusNormal); | |
83 | MSG("startup->FlipToScreen\n"); | |
84 | startup->FlipToScreen(0, 0); | |
85 | MSG("set startupTime\n"); | |
86 | startupTime = gSystem->GetTicks() + gConst->kStartupTime; | |
87 | ||
88 | ||
89 | ||
90 | MSG("new CShapeManager\n"); | |
91 | gShapeManager = new CShapeManager(); | |
92 | MSG("new gShapeManager->LoadShapes\n"); | |
93 | gShapeManager->LoadShapes(); | |
94 | MSG("new gShapeManager->LoadBackground\n"); | |
95 | gShapeManager->LoadBackground(gConst->kFileBackground1); | |
96 | lastBackground = 1; | |
97 | ||
98 | MSG("creating plane (new CGraphicSurface\n"); | |
99 | plane = new CGraphicSurface(kGamePlaneWidth, kGamePlaneHeight); | |
100 | ||
101 | while (gSystem->GetTicks() < startupTime && !gSystem->KeyPressed(kKeySpace)) { gSystem->ProcessEvents(); } | |
102 | delete startup; | |
103 | ||
104 | MSG("new CGUI\n"); | |
105 | gGUI = new CGUI(plane); | |
106 | ||
107 | MSG("new CObjInfo\n"); | |
108 | gObjInfo = new CObjInfo(0); | |
109 | ||
110 | command = kCmdNewGameLevel2; | |
111 | ||
112 | ||
113 | } | |
114 | ||
115 | void CApplication::LoadLevelData(short levelNumber) | |
116 | { | |
117 | thingList = 0L; | |
118 | collisionThingList = 0L; | |
119 | bulletList = 0L; | |
120 | preRenderQueue = 0L; | |
121 | postRenderQueue = 0L; | |
122 | renderQueue = 0L; | |
123 | ||
124 | ||
125 | gObjInfo->LoadPlatforms(levelNumber); | |
126 | ||
127 | MSG("new CLevel\n"); | |
128 | if (command >= kLoadGameSlot0 && command <= kLoadGameSlot5) { | |
129 | char *fileName = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[command - kLoadGameSlot0]); | |
130 | gLevel = new CLevel(levelNumber, fileName); // by LL | |
131 | delete [] fileName; | |
132 | } else | |
133 | gLevel = new CLevel(levelNumber, 0L); | |
134 | ||
135 | gGUI->SetFocus((CPlayer *)gLevel->focus); | |
136 | } | |
137 | ||
138 | void CApplication::Run() | |
139 | { | |
140 | levelNumber = 0; | |
141 | ||
142 | while (command != kCmdQuit) { | |
143 | ||
144 | if (command >= kCmdNewGameLevel1 && command <= kCmdNewGameLevel4) { | |
145 | difficulty = command - kCmdNewGameLevel1; | |
146 | levelNumber = 0; | |
147 | } | |
148 | ||
149 | currentWeaponSF = gConst->kWeaponSF[difficulty]; | |
150 | currentHealthSF = gConst->kHealthSF[difficulty]; | |
151 | currentSpeedSF = gConst->kSpeedSF[difficulty]; | |
152 | ||
153 | LoadLevelData(levelNumber); | |
154 | ||
155 | if (command == kCmdNextLevel) { | |
156 | if (gLevel->player->typeID & kPlayer) ((CPlayer *)gLevel->player)->RestoreDataFromNextLevel(&savedData); | |
157 | gClutManager->FadeToColor(kFadeFromColor, kWhiteCoronaTable, plane); | |
158 | } | |
159 | ||
160 | MSG("--- RunLevel() --- \n"); | |
161 | RunLevel(); | |
162 | ||
163 | if (command == kCmdNextLevel) { | |
164 | levelNumber ++; | |
165 | gClutManager->FadeToColor(kFadeToColor, kWhiteCoronaTable, plane); | |
166 | }else if (command == kCmdPrevLevel) levelNumber --; | |
167 | ||
168 | UnloadLevelData(); | |
169 | ||
170 | } | |
171 | } | |
172 | ||
173 | void CApplication::RunLevel() | |
174 | { | |
175 | char fps[5]; | |
176 | long savedTicks = 0, ticks = 0, ttmp; | |
177 | long frameCount = 0, saveFrameCount = 0; | |
178 | tThingList *currentEntry, *tmp; | |
179 | short message; | |
180 | CThing *tmpThing; | |
181 | char* fileName; | |
182 | ||
183 | firstPlayRound = 1; | |
184 | command = kCmdNoCommand; | |
185 | syncTime = gSystem->GetTicks(); | |
186 | aveTime = 20; | |
187 | ||
188 | while (command == kCmdNoCommand) { | |
189 | frameCount ++; | |
190 | //usleep(1000); | |
191 | ||
192 | time = gSystem->GetTicks(); | |
193 | deltaTime = time - syncTime; | |
194 | aveTime = (aveTime + deltaTime) / 2; | |
195 | syncTime = time; | |
196 | ||
197 | currentEntry = thingList; | |
198 | while (currentEntry) { | |
199 | message = kNoEvent; | |
200 | ||
201 | message |= currentEntry->thing->Think(); | |
202 | ||
203 | if (message == kDestroyMe) { | |
204 | tmp = currentEntry->next; | |
205 | tmpThing = currentEntry->thing; | |
206 | tmpThing->UnlinkInLists(); | |
207 | delete tmpThing; | |
208 | currentEntry = tmp; | |
209 | } else | |
210 | currentEntry = currentEntry->next; | |
211 | } | |
212 | ||
213 | currentEntry = thingList; | |
214 | while (currentEntry) { | |
215 | message = kNoEvent; | |
216 | ||
217 | message |= currentEntry->thing->Forces(); | |
218 | ||
219 | if (message == kDestroyMe) { | |
220 | tmp = currentEntry->next; | |
221 | tmpThing = currentEntry->thing; | |
222 | tmpThing->UnlinkInLists(); | |
223 | delete tmpThing; | |
224 | currentEntry = tmp; | |
225 | } else | |
226 | currentEntry = currentEntry->next; | |
227 | } | |
228 | ||
229 | currentEntry = thingList; | |
230 | while (currentEntry) { | |
231 | currentEntry->thing->Move(); | |
232 | currentEntry = currentEntry->next; | |
233 | } | |
234 | ||
235 | ||
236 | gLevel->PaintLevel(); | |
237 | gGUI->DisplayMessages(); | |
238 | ||
239 | plane->FlipToScreen(0, 0); | |
240 | firstPlayRound = 0; | |
241 | ||
242 | gGUI->Update(); | |
243 | ||
244 | ticks = gSystem->GetTicks(); | |
245 | if (gConst->kShowFPS && ticks - savedTicks > kTicksPerSecond) { | |
246 | sprintf(fps, "%02d", saveFrameCount); | |
247 | gSystem->PaintString(fps, 500, 20, 0); | |
248 | ||
249 | sprintf(fps, "%02d", frameCount); | |
250 | gSystem->PaintString(fps, 500, 20, 255); | |
251 | saveFrameCount = frameCount; | |
252 | frameCount = 0; | |
253 | savedTicks = ticks; | |
254 | } | |
255 | ||
256 | if (gSystem->KeyPressed(kKeyEscape)) { | |
257 | command = gGUI->RunUserInterface(kMainPage); | |
258 | syncTime = gSystem->GetTicks(); | |
259 | } | |
260 | ||
261 | if (command >= kSaveGameSlot0 && command <= kSaveGameSlot5) { | |
262 | fileName = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[command - kSaveGameSlot0]); | |
263 | gLevel->WriteLevel(fileName); // by LL | |
264 | delete [] fileName; | |
265 | command = kCmdNoCommand; | |
266 | } | |
267 | if ((command == kCmdNextLevel) && (gLevel->player->typeID & kPlayer)) | |
268 | ((CPlayer *)(gLevel->player))->SaveDataToNextLevel(&savedData); | |
269 | } | |
270 | } | |
271 | ||
272 | void CApplication::UnloadLevelData() | |
273 | { | |
274 | CThing *tmp; | |
275 | ||
276 | while (thingList) { | |
277 | tmp = thingList->thing; | |
278 | tmp->UnlinkInLists(); | |
279 | delete tmp; | |
280 | } | |
281 | ||
282 | delete gLevel; | |
283 | } | |
284 | ||
285 | void CApplication::UnloadData() | |
286 | { | |
287 | delete gObjInfo; | |
288 | delete gGUI; | |
289 | gShapeManager->UnloadBackground(); | |
290 | gShapeManager->UnloadShapes(); | |
291 | delete gShapeManager; | |
292 | delete gClutManager; | |
293 | } | |
294 | ||
295 | void CApplication::Quit() | |
296 | { | |
297 | delete plane; | |
298 | gSystem->DisposeScreen(); | |
299 | } | |
300 | ||
301 | void CApplication::Enqueue(tThingList **list, CThing *newThing) | |
302 | { | |
303 | tThingList *tmp; | |
304 | ||
305 | if (!newThing) return; | |
306 | ||
307 | tmp = new tThingList; | |
308 | tmp->next = *list; | |
309 | tmp->prev = 0L; | |
310 | tmp->thing = newThing; | |
311 | ||
312 | if (*list) (*list)->prev = tmp; | |
313 | ||
314 | *list = tmp; | |
315 | } | |
316 | ||
317 | // INVARIANT: *list->prev is always 0L, i.e. *list points to the first valid entry in the list | |
318 | void CApplication::Dequeue(tThingList **list, CThing *remove) | |
319 | { | |
320 | tThingList *tmp = *list; | |
321 | ||
322 | if (remove) { | |
323 | while (tmp) { | |
324 | if (tmp->thing == remove) { | |
325 | if (tmp == *list) *list = tmp->next; | |
326 | if (tmp->next) tmp->next->prev = tmp->prev; | |
327 | if (tmp->prev) tmp->prev->next = tmp->next; | |
328 | delete tmp; | |
329 | ||
330 | return; | |
331 | } | |
332 | tmp = tmp->next; | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | ||
338 | /*void CApplication::InsertCollisionThing(CThing *newThing) | |
339 | { | |
340 | if (!newThing) return; | |
341 | ||
342 | if (!collisionThingList) { | |
343 | newThing->nextCollisionThing = 0L; | |
344 | newThing->prevCollisionThing = 0L; | |
345 | collisionThingList = newThing; | |
346 | } else { | |
347 | newThing->prevCollisionThing = 0L; | |
348 | newThing->nextCollisionThing = collisionThingList; | |
349 | collisionThingList->prevCollisionThing = newThing; | |
350 | collisionThingList = newThing; | |
351 | } | |
352 | } | |
353 | ||
354 | void CApplication::RemoveCollisionThing(CThing *remove) | |
355 | { | |
356 | if (collisionThingList == remove) collisionThingList = collisionThingList->nextCollisionThing; | |
357 | if (remove->nextCollisionThing) remove->nextCollisionThing->prevCollisionThing = remove->prevCollisionThing; | |
358 | if (remove->prevCollisionThing) remove->prevCollisionThing->nextCollisionThing = remove->nextCollisionThing; | |
359 | } | |
360 | ||
361 | void CApplication::InsertBullet(CBullet *newBullet) | |
362 | { | |
363 | if (!newBullet) return; | |
364 | ||
365 | if (!bulletList) { | |
366 | newBullet->nextBullet = 0L; | |
367 | newBullet->prevBullet = 0L; | |
368 | bulletList = newBullet; | |
369 | } else { | |
370 | newBullet->prevBullet = 0L; | |
371 | newBullet->nextBullet = bulletList; | |
372 | bulletList->prevBullet = newBullet; | |
373 | bulletList = newBullet; | |
374 | } | |
375 | } | |
376 | ||
377 | void CApplication::RemoveBullet(CBullet *remove) | |
378 | { | |
379 | if (bulletList == remove) bulletList = bulletList->nextBullet; | |
380 | if (remove->nextBullet) remove->nextBullet->prevBullet = remove->prevBullet; | |
381 | if (remove->prevBullet) remove->prevBullet->nextBullet = remove->nextBullet; | |
382 | } | |
383 | ||
384 | ||
385 | void CApplication::InsertPreRenderThing(CThing *newThing) | |
386 | { | |
387 | if (!newThing) return; | |
388 | ||
389 | if (!preRenderQueue) { | |
390 | newThing->nextPreRenderThing = 0L; | |
391 | newThing->prevPreRenderThing = 0L; | |
392 | collisionThingList = newThing; | |
393 | } else { | |
394 | newThing->prevPreRenderThing = 0L; | |
395 | newThing->nextPreRenderThing = preRenderQueue; | |
396 | preRenderQueue->prevPreRenderThing = newThing; | |
397 | preRenderQueue = newThing; | |
398 | } | |
399 | } | |
400 | ||
401 | void CApplication::RemovePreRenderThing(CThing *remove) | |
402 | { | |
403 | if (preRenderQueue == remove) bulletList = bulletList->nextBullet; | |
404 | if (remove->nextBullet) remove->nextBullet->prevBullet = remove->prevBullet; | |
405 | if (remove->prevBullet) remove->prevBullet->nextBullet = remove->nextBullet; | |
406 | }*/⏎ |
0 | #ifndef __AMP_APPL__ | |
1 | #define __AMP_APPL__ | |
2 | ||
3 | #include "AmpHead.hpp" | |
4 | #include "System.hpp" | |
5 | #include "Level.hpp" | |
6 | #include "ObjInfo.hpp" | |
7 | #include "Bullet.hpp" | |
8 | #include "ConstVal.hpp" | |
9 | ||
10 | enum { // commands | |
11 | kCmdNoCommand, | |
12 | kCmdNextLevel, | |
13 | kCmdPrevLevel, | |
14 | kCmdQuit, | |
15 | kCmdNewGameLevel1, | |
16 | kCmdNewGameLevel2, | |
17 | kCmdNewGameLevel3, | |
18 | kCmdNewGameLevel4, | |
19 | kSaveGameSlot0, | |
20 | kSaveGameSlot1, | |
21 | kSaveGameSlot2, | |
22 | kSaveGameSlot3, | |
23 | kSaveGameSlot4, | |
24 | kSaveGameSlot5, | |
25 | ||
26 | kLoadGameSlot0, | |
27 | kLoadGameSlot1, | |
28 | kLoadGameSlot2, | |
29 | kLoadGameSlot3, | |
30 | kLoadGameSlot4, | |
31 | kLoadGameSlot5 | |
32 | }; | |
33 | ||
34 | struct tThingList { | |
35 | tThingList *next, *prev; | |
36 | CThing *thing; | |
37 | }; | |
38 | ||
39 | struct tPlayerData { | |
40 | short munition[8]; | |
41 | short weaponStatus[8]; | |
42 | ||
43 | short currentWeapon; | |
44 | short oxygen; | |
45 | short health; | |
46 | }; | |
47 | ||
48 | class CApplication { | |
49 | protected: | |
50 | tPlayerData savedData; | |
51 | CGraphicSurface *startup; | |
52 | ||
53 | public: | |
54 | tThingList *thingList; | |
55 | tThingList *collisionThingList; | |
56 | tThingList *bulletList; | |
57 | tThingList *preRenderQueue; | |
58 | tThingList *postRenderQueue; | |
59 | tThingList *renderQueue; | |
60 | ||
61 | CGraphicSurface *plane; | |
62 | ||
63 | CPlatform *platformTable[kNumPlatforms]; | |
64 | short lastBackground; | |
65 | ||
66 | short firstPlayRound; | |
67 | long syncTime; // current time in ticks, but only once each play round measured | |
68 | short command; | |
69 | short difficulty; | |
70 | double currentWeaponSF, currentHealthSF, currentSpeedSF; | |
71 | short levelNumber; | |
72 | long time; | |
73 | long deltaTime; | |
74 | long aveTime; | |
75 | ||
76 | CApplication(); | |
77 | ~CApplication(); | |
78 | ||
79 | void InitGraphics(); | |
80 | void LoadData(); | |
81 | void LoadLevelData(short levelNumber); | |
82 | void Run(); | |
83 | void RunLevel(); | |
84 | void UnloadLevelData(); | |
85 | void UnloadData(); | |
86 | void Quit(); | |
87 | ||
88 | void Enqueue(tThingList **list, CThing *newThing); | |
89 | void Dequeue(tThingList **list, CThing *remove); | |
90 | ||
91 | /*void InsertThing(CThing *newThing); | |
92 | void RemoveThing(CThing *remove); | |
93 | void InsertCollisionThing(CThing *newThing); | |
94 | void RemoveCollisionThing(CThing *remove); | |
95 | void InsertBullet(CBullet *newBullet); | |
96 | void RemoveBullet(CBullet *remove); | |
97 | void InsertPreRenderThing(CThing *newThing); | |
98 | void RemovePreRenderThing(CThing *remove); | |
99 | void InsertPostRenderThing(CThing *newThing); | |
100 | void RemovePostRenderThing(CThing *remove);*/ | |
101 | ||
102 | }; | |
103 | ||
104 | #endif⏎ |
0 | #include "Bullet.hpp" | |
1 | #include "Monster.hpp" | |
2 | #include <math.h> | |
3 | #include "ShapeLd.hpp" | |
4 | #include "Appl.hpp" | |
5 | #include "Clut.hpp" | |
6 | #include "SndSys.hpp" | |
7 | ||
8 | extern CShapeManager *gShapeManager; | |
9 | extern CApplication *gApplication; | |
10 | extern CSystem *gSystem; | |
11 | extern tConstValues *gConst; | |
12 | extern CLevel *gLevel; | |
13 | extern CClutManager *gClutManager; | |
14 | extern CObjInfo *gObjInfo; | |
15 | extern CSoundSystem *gSoundSystem; | |
16 | ||
17 | CBullet::CBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CThing(initx, inity, width, height, number) | |
18 | { | |
19 | typeID |= kBullet; | |
20 | LinkInLists(); | |
21 | ||
22 | if (weaponInfo) { | |
23 | info = weaponInfo; | |
24 | weight = info->art == kWeaponHasWeight ? 10 : 0; | |
25 | weightless = 0; | |
26 | background = 0; | |
27 | /*xs = xm - gConst->kBulletWidth / 2; | |
28 | ys = ym - gConst->kBulletWidth / 2; | |
29 | xe = xm + gConst->kBulletWidth / 2; | |
30 | ye = ym + gConst->kBulletWidth / 2;*/ | |
31 | ||
32 | OnAllocate(); | |
33 | ||
34 | shooter = source; | |
35 | targetposition = targetpos; | |
36 | ||
37 | if (projectile2) { | |
38 | for (short n = 0; n < gConst->kBulletTailLength; n ++) { | |
39 | tailX[n] = -1; | |
40 | tailY[n] = -1; | |
41 | } | |
42 | tailStep = 0; | |
43 | } | |
44 | ||
45 | directionUnitx = directionx * gConst->kVelocityUnit / sqrt(directionx * directionx + directiony * directiony); | |
46 | directionUnity = directiony * gConst->kVelocityUnit / sqrt(directionx * directionx + directiony * directiony); | |
47 | ||
48 | action = kInFlight; | |
49 | ||
50 | forceVectorX = 0; | |
51 | forceVectorY = 0; | |
52 | resForceX = resForceY = 0; | |
53 | ||
54 | lastTime = gSystem->GetTicks(); | |
55 | deltaTime = 0; | |
56 | } | |
57 | } | |
58 | ||
59 | void CBullet::OnAllocate() | |
60 | { | |
61 | projectile1 = gShapeManager->FindShape(info->projectileShapes[0], 0); | |
62 | projectile2 = gShapeManager->FindShape(info->projectileShapes[1], 0); | |
63 | ||
64 | if (projectile2) { | |
65 | tailX = new short [gConst->kBulletTailLength]; | |
66 | tailY = new short [gConst->kBulletTailLength]; | |
67 | }else{ | |
68 | tailX = tailY = 0L; | |
69 | } | |
70 | ||
71 | currentDetonationShape = 0L; | |
72 | ||
73 | for (short n = 0; n < 5; n ++) detonation[n] = gShapeManager->FindShape(info->detonationShapes[n], 0); | |
74 | } | |
75 | ||
76 | CBullet::~CBullet() | |
77 | { | |
78 | if (projectile2) { | |
79 | delete [] tailX; | |
80 | delete [] tailY; | |
81 | } | |
82 | } | |
83 | ||
84 | void CBullet::LinkInLists() | |
85 | { | |
86 | gApplication->Enqueue(&gApplication->thingList, this); | |
87 | gApplication->Enqueue(&gApplication->bulletList, this); | |
88 | gApplication->Enqueue(&gApplication->renderQueue, this); | |
89 | } | |
90 | ||
91 | void CBullet::UnlinkInLists() | |
92 | { | |
93 | gApplication->Dequeue(&gApplication->thingList, this); | |
94 | gApplication->Dequeue(&gApplication->bulletList, this); | |
95 | gApplication->Dequeue(&gApplication->renderQueue, this); | |
96 | } | |
97 | ||
98 | short CBullet::Think() | |
99 | { | |
100 | CObject::Think(); | |
101 | ||
102 | Gravitation(); | |
103 | ||
104 | if (directionUnitx) forceVectorX = directionUnitx * info->speed * deltaTime; | |
105 | if (directionUnity) forceVectorY = directionUnity * info->speed * deltaTime; | |
106 | ||
107 | return kNoEvent; | |
108 | } | |
109 | ||
110 | short CBullet::Forces() | |
111 | { | |
112 | short collisionCode, collisionObject; | |
113 | tThingList *entry; | |
114 | CElement *element; | |
115 | ||
116 | if (action == kInFlight) { | |
117 | CObject::Forces(); | |
118 | //collisionCode = ExertForce(resForceX, resForceY, collisionObject, &obstacle); | |
119 | ||
120 | if (xm < 0 || ym < 0 || xm > kLevelWidth * kElementSize + kElementSize || ym > kLevelHeight * kElementSize + kElementSize) { | |
121 | Detonate(kCollisionWithLevelBorders, 0L); | |
122 | return kNoEvent; | |
123 | } | |
124 | ||
125 | element = gLevel->GetElement(xm, ym); | |
126 | if (element && !element->background) { | |
127 | Detonate(0, 0L); | |
128 | return kNoEvent; | |
129 | } | |
130 | ||
131 | entry = gApplication->collisionThingList; | |
132 | while (entry) { | |
133 | if (entry->thing != this && entry->thing != shooter && !(entry->thing->typeID & (kBullet | kStaticItem | kPortableItem)) && entry->thing->CollisionPossible(xm, ym)) { | |
134 | Detonate(0, entry->thing); | |
135 | entry = 0L; | |
136 | }else entry = entry->next; | |
137 | } | |
138 | ||
139 | return kNoEvent; | |
140 | ||
141 | }else if (action == kInDetonation) { | |
142 | return DetonationAnimation(); | |
143 | } | |
144 | ||
145 | return kNoEvent; | |
146 | } | |
147 | ||
148 | ||
149 | void CBullet::Detonate(short collisionCode, CObject *victim) | |
150 | { | |
151 | action = kInDetonation; | |
152 | detonationStartTime = lastTime; | |
153 | ||
154 | noDetonation = collisionCode == kCollisionWithLevelBorders; | |
155 | ||
156 | Damage(victim); | |
157 | ||
158 | gSoundSystem->Play(gSoundSystem->weaponHitSounds[thingNumber], xm, ym); | |
159 | ||
160 | if (shooter && !(shooter->typeID & kPlayer)) { | |
161 | if ((directionUnitx > 0 && xe >= targetposition) || (directionUnitx < 0 && xs <= targetposition)) | |
162 | ((CMonster *)shooter)->OnShootSuccessful(); | |
163 | else ((CMonster *)shooter)->OnShootNotSuccessful(); | |
164 | } | |
165 | } | |
166 | ||
167 | ||
168 | short CBullet::DetonationAnimation() | |
169 | { | |
170 | long frame = (long)((double)(lastTime - detonationStartTime) * gConst->kDetonationFrameTime); | |
171 | ||
172 | if (frame > 4 || noDetonation) { | |
173 | currentDetonationShape = 0L; | |
174 | return kDestroyMe; | |
175 | ||
176 | }else{ | |
177 | currentDetonationShape = detonation[frame]; | |
178 | return kNoEvent; | |
179 | } | |
180 | } | |
181 | ||
182 | // --------------------------------------- | |
183 | void CBullet::Damage(CObject *victim) | |
184 | // called from CBullet::DetonationAnimation | |
185 | // sends a TestForDamage-Event to all collision objects | |
186 | { | |
187 | if (info->rad) { | |
188 | tThingList *currentEntry = gApplication->collisionThingList; | |
189 | ||
190 | while (currentEntry) { | |
191 | if (currentEntry->thing != this) currentEntry->thing->TestForDamage(xs, ys, info->rad, info->damage); | |
192 | currentEntry = currentEntry->next; | |
193 | } | |
194 | }else{ | |
195 | if (victim && victim != shooter && victim->typeID & kThing) ((CThing *)victim)->OnDamage(info->damage); | |
196 | } | |
197 | } | |
198 | ||
199 | ||
200 | void CBullet::Move() | |
201 | { | |
202 | if (action == kInFlight) CThing::Move(); | |
203 | ||
204 | if (projectile2) { | |
205 | if (tailStep > gConst->kBulletTailDistance) { | |
206 | for (short n = gConst->kBulletTailLength -2; n >= 0; n --) { | |
207 | tailX[n + 1] = tailX[n]; | |
208 | tailY[n + 1] = tailY[n]; | |
209 | } | |
210 | tailX[0] = (short)xs; | |
211 | tailY[0] = (short)ys; | |
212 | tailStep = 0; | |
213 | }else tailStep += gConst->kVelocityUnit * info->speed * deltaTime; | |
214 | } | |
215 | } | |
216 | ||
217 | void CBullet::Render(short planeX, short planeY, tRect *clipRect) | |
218 | { | |
219 | short tailMode; | |
220 | if (info->effect != kLightningNoEffect) gClutManager->DrawLightning(xm, ym, info->effect, gApplication->plane); | |
221 | ||
222 | if (action == kInFlight) { | |
223 | if (resForceX < 0) modus |= kShapemodusBackwardFlag; | |
224 | if (projectile1) projectile1->RenderShape(xs - planeX, ys - planeY, clipRect, | |
225 | modus, 0, gApplication->plane); | |
226 | }else{ | |
227 | if (currentDetonationShape) currentDetonationShape->RenderShape(xs - planeX, ys - planeY, clipRect, | |
228 | modus, 0, gApplication->plane); | |
229 | } | |
230 | if (projectile2) { | |
231 | for (short n = 0; n < gConst->kBulletTailLength; n ++) { | |
232 | if (n < gConst->kBulletTailLength / 3) tailMode = kShapemodusTransparent1; | |
233 | else if (n > gConst->kBulletTailLength * 2 / 3) tailMode = kShapemodusTransparent3; | |
234 | else tailMode = kShapemodusTransparent2; | |
235 | ||
236 | if (tailX[n] != -1) projectile2->RenderShape(tailX[n] + (short)xs - tailX[0] - planeX, tailY[n] + (short)ys - tailY[0] - planeY, clipRect, tailMode, 0, gApplication->plane); | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | short CBullet::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
242 | { | |
243 | if (action != kInDetonation && | |
244 | ((top >= ys && top <= ye) || (bottom >= ys && bottom <= ye)) && | |
245 | sender != shooter && !(sender->typeID & kBullet)) { | |
246 | if (left >= xs && left <= xe) Detonate(kCollisionOnRight, sender); | |
247 | if (right >= xs && right <= xe) Detonate(kCollisionOnLeft, sender); | |
248 | } | |
249 | return kNoCollision; | |
250 | } | |
251 | ||
252 | ||
253 | short CBullet::AmIATreatment(double victimxs, double victimys, double victimxe, double victimye, double &fx, double &fy) | |
254 | { | |
255 | double coll; | |
256 | ||
257 | if ((xm - victimxs) * (xm - victimxs) + (ym - victimys) * (ym - victimys) < gConst->kTreatDistance * gConst->kTreatDistance && | |
258 | SIGN(victimxs - xs) == SIGN(resForceX)) { | |
259 | fx = resForceX; fy = resForceY; | |
260 | ||
261 | if (ABS(resForceX) > ABS(resForceY)) { | |
262 | coll = ym + resForceY * (victimxs - xm) / resForceX; | |
263 | if (coll > victimys - (ye - ys) && coll < victimye + (ye - ys)) return 1; else return 0; | |
264 | }else{ | |
265 | coll = xm + resForceX * (victimys - ym) / resForceY; | |
266 | if (coll > victimxs - (xe - xs) && coll < victimxe + (xe - xs)) return 1; else return 0; | |
267 | } | |
268 | }else return 0; | |
269 | } | |
270 | ||
271 | ||
272 | CSorceryBullet::CSorceryBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) | |
273 | { | |
274 | typeID |= kSorceryBullet; | |
275 | numBounces = 0; | |
276 | } | |
277 | ||
278 | CSorceryBullet::~CSorceryBullet() {} | |
279 | ||
280 | short CSorceryBullet::Forces() | |
281 | { | |
282 | short collisionCode, collisionObject; | |
283 | double savedForcex = forceVectorX, savedForcey = forceVectorY; | |
284 | CObject *collObj; | |
285 | ||
286 | if (action == kInFlight) { | |
287 | CObject::Forces(); | |
288 | ||
289 | collisionCode = ExertForce(resForceX, resForceY, collisionObject, &collObj); | |
290 | if (collisionCode && collObj != shooter) { | |
291 | if (collisionObject & (kElement | kItem | kPlatform) || collObj == shooter) { | |
292 | ||
293 | if (numBounces < gConst->kNumOfBounces) { | |
294 | ||
295 | numBounces ++; | |
296 | ||
297 | if (collisionCode & kCollisionOnTop || collisionCode & kCollisionOnBottom) { | |
298 | forceVectorY = -savedForcey; | |
299 | directionUnity *= -1.0; | |
300 | } | |
301 | if (collisionCode & kCollisionOnLeft || collisionCode & kCollisionOnRight) { | |
302 | forceVectorX = -savedForcex; | |
303 | directionUnitx *= -1.0; | |
304 | } | |
305 | }else{ | |
306 | Detonate(collisionCode, collObj); | |
307 | } | |
308 | }else{ | |
309 | Detonate(collisionCode, collObj); | |
310 | } | |
311 | } | |
312 | }else if (action == kInDetonation) { | |
313 | return DetonationAnimation(); | |
314 | } | |
315 | ||
316 | return kNoEvent; | |
317 | } | |
318 | ||
319 | ||
320 | CBombBullet::CBombBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) | |
321 | { | |
322 | weight = 5; | |
323 | action = kInFlight; | |
324 | detonate = 0; | |
325 | } | |
326 | ||
327 | CBombBullet::~CBombBullet() {} | |
328 | ||
329 | short CBombBullet::Forces() | |
330 | { | |
331 | short collisionObject, returnCode, collisionCode; | |
332 | CObject *obstacle; | |
333 | short dx, dy; | |
334 | ||
335 | if (action != kInDetonation) { | |
336 | CObject::Forces(); | |
337 | ||
338 | collisionCode = ExertForce(resForceX, resForceY, collisionObject, &obstacle); | |
339 | if (collisionCode) { | |
340 | if (collisionObject == kMonster) detonate = 1; | |
341 | } | |
342 | if (detonate == 1) { | |
343 | Detonate(collisionCode, obstacle); | |
344 | if (detonation[0]) detonation[0]->AllowPixelAccess(dx, dy); | |
345 | ys = ye - dy; ye = ys + dy; ym = (ye - ys) / 2; | |
346 | detonate = 2; | |
347 | } | |
348 | }else return DetonationAnimation(); | |
349 | ||
350 | return kNoEvent; | |
351 | } | |
352 | ||
353 | CSineBullet::CSineBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, short rad, short per) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) | |
354 | { | |
355 | typeID |= kSineBullet; | |
356 | ||
357 | distance = 0; | |
358 | radius = rad; | |
359 | period = 2.0 * 3.141 / (double)per; | |
360 | } | |
361 | ||
362 | CSineBullet::~CSineBullet() {} | |
363 | ||
364 | short CSineBullet::Think() | |
365 | { | |
366 | CObject::Think(); | |
367 | ||
368 | Gravitation(); | |
369 | ||
370 | forceVectorX = gConst->kVelocityUnit * info->speed * deltaTime * SIGN(directionUnitx); | |
371 | distance += forceVectorX; | |
372 | forceVectorY = -radius * period * cos(distance * period); | |
373 | ||
374 | return kNoEvent; | |
375 | } | |
376 | ||
377 | ||
378 | CGuidedBullet::CGuidedBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, CThing *tg) : CBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos) | |
379 | { | |
380 | typeID |= kGuidedBullet; | |
381 | ||
382 | target = tg; | |
383 | ||
384 | if (target) { | |
385 | initAbstSign = SIGN(target->xs - xs); | |
386 | ||
387 | lastfx = target->xs - xs; | |
388 | lastfy = target->ys - ys; | |
389 | lastf = sqrt(lastfx * lastfx + lastfy * lastfy); | |
390 | } | |
391 | } | |
392 | ||
393 | CGuidedBullet::~CGuidedBullet() {} | |
394 | ||
395 | short CGuidedBullet::Think() | |
396 | { | |
397 | double abstx, absty, abst; | |
398 | double alpha, tmp; | |
399 | double a, b, phi1, phi2, dPhi; | |
400 | ||
401 | CObject::Think(); | |
402 | ||
403 | if (target) { | |
404 | abstx = target->xs - xs; | |
405 | absty = target->ys - ys; | |
406 | ||
407 | a = sqrt(lastfx * lastfx + lastfy * lastfy); | |
408 | b = sqrt(abstx*abstx+absty*absty); | |
409 | phi1=asin(lastfy / a); if (lastfx<0) phi1=phi1*(-1.0); | |
410 | phi2=asin(absty/b); if (abstx<0) phi2=phi2*(-1.0); | |
411 | dPhi=phi2-phi1; | |
412 | if (fabs(dPhi)>gConst->kMaxTurnAngle) dPhi=SIGN(dPhi)*gConst->kMaxTurnAngle; | |
413 | ||
414 | tmp=cos(dPhi)*lastfx-sin(dPhi)*lastfy; | |
415 | lastfy=sin(dPhi)*lastfx+cos(dPhi)*lastfy; | |
416 | lastfx = tmp; | |
417 | } | |
418 | ||
419 | forceVectorX = lastfx * gConst->kVelocityUnit * info->speed * deltaTime / lastf; | |
420 | forceVectorY = lastfy * gConst->kVelocityUnit * info->speed * deltaTime / lastf; | |
421 | ||
422 | return kNoEvent; | |
423 | } | |
424 | ||
425 | CStaffBullet::CStaffBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *source, double targetpos, CThing *tg) : CGuidedBullet(initx, inity, width, height, number, weaponInfo, directionx, directiony, source, targetpos, tg) | |
426 | { | |
427 | lastMonsterScanTime = 0; | |
428 | } | |
429 | ||
430 | const double kStaffBulletRad = 40.0; | |
431 | const long kMonsterScanTime = 200; | |
432 | ||
433 | short CStaffBullet::Think() | |
434 | { | |
435 | tThingList *currentEntry; | |
436 | ||
437 | if (!target && lastMonsterScanTime < lastTime) { | |
438 | ||
439 | currentEntry = gApplication->collisionThingList; | |
440 | while (currentEntry) { | |
441 | if (currentEntry->thing->typeID & kMonster && currentEntry->thing != shooter) { | |
442 | if ((currentEntry->thing->xm - xm) * (currentEntry->thing->xm - xm) * 0.5 + | |
443 | (currentEntry->thing->ym - ym) * (currentEntry->thing->ym - ym) < kStaffBulletRad * kStaffBulletRad) { | |
444 | target = currentEntry->thing; | |
445 | } | |
446 | } | |
447 | currentEntry = currentEntry->next; | |
448 | } | |
449 | lastMonsterScanTime = lastTime + kMonsterScanTime; | |
450 | ||
451 | return CBullet::Think(); | |
452 | } else if (target) | |
453 | return CGuidedBullet::Think(); | |
454 | else | |
455 | return kNoEvent; | |
456 | } | |
457 | ||
458 | ||
459 | short CBullet::Write(FILE *f) | |
460 | { | |
461 | long size = 0; | |
462 | ||
463 | WRITEDATA(size); | |
464 | WRITEDATA(typeID); | |
465 | WRITEDATA(thingNumber); | |
466 | ||
467 | size += CThing::Write(f); | |
468 | ||
469 | if (tailX) { | |
470 | for (short n = 0; n < gConst->kBulletTailLength; n ++) { | |
471 | WRITEDATA(tailX[n]); | |
472 | WRITEDATA(tailY[n]); | |
473 | } | |
474 | } | |
475 | ||
476 | WRITEDATA(tailStep); | |
477 | WRITEDATA(targetposition); | |
478 | WRITEDATA(directionUnitx); | |
479 | WRITEDATA(directionUnity); | |
480 | WRITEDATA(action); | |
481 | WRITEDATA(detonationStartTime); | |
482 | WRITEDATA(noDetonation); | |
483 | ||
484 | FINISHWRITE; | |
485 | ||
486 | return size; | |
487 | } | |
488 | ||
489 | void CBullet::Read(FILE *f) | |
490 | { | |
491 | long size = 0; | |
492 | ||
493 | READDATA(size); | |
494 | READDATA(typeID); | |
495 | READDATA(thingNumber); | |
496 | ||
497 | CThing::Read(f); | |
498 | ||
499 | info = gObjInfo->FindWeapon(thingNumber); | |
500 | shooter = 0L; | |
501 | ||
502 | OnAllocate(); | |
503 | ||
504 | if (projectile2) { | |
505 | for (short n = 0; n < gConst->kBulletTailLength; n ++) { | |
506 | READDATA(tailX[n]); | |
507 | READDATA(tailY[n]); | |
508 | } | |
509 | } | |
510 | ||
511 | READDATA(tailStep); | |
512 | READDATA(targetposition); | |
513 | READDATA(directionUnitx); | |
514 | READDATA(directionUnity); | |
515 | READDATA(action); | |
516 | READDATA(detonationStartTime); | |
517 | READDATA(noDetonation); | |
518 | } | |
519 | ||
520 | ||
521 | short CSorceryBullet::Write(FILE *f) | |
522 | { | |
523 | long size = 0; | |
524 | ||
525 | WRITEDATA(size); | |
526 | WRITEDATA(typeID); | |
527 | WRITEDATA(thingNumber); | |
528 | ||
529 | size += CBullet::Write(f); | |
530 | ||
531 | WRITEDATA(numBounces); | |
532 | ||
533 | FINISHWRITE; | |
534 | ||
535 | return size; | |
536 | } | |
537 | ||
538 | void CSorceryBullet::Read(FILE *f) | |
539 | { | |
540 | long size = 0; | |
541 | ||
542 | READDATA(size); | |
543 | READDATA(typeID); | |
544 | READDATA(thingNumber); | |
545 | ||
546 | CBullet::Read(f); | |
547 | ||
548 | READDATA(numBounces); | |
549 | } | |
550 | ||
551 | short CBombBullet::Write(FILE *f) | |
552 | { | |
553 | long size = 0; | |
554 | ||
555 | WRITEDATA(size); | |
556 | WRITEDATA(typeID); | |
557 | WRITEDATA(thingNumber); | |
558 | ||
559 | size += CBullet::Write(f); | |
560 | ||
561 | WRITEDATA(detonate); | |
562 | ||
563 | FINISHWRITE; | |
564 | ||
565 | return size; | |
566 | } | |
567 | ||
568 | void CBombBullet::Read(FILE *f) | |
569 | { | |
570 | long size = 0; | |
571 | ||
572 | READDATA(size); | |
573 | READDATA(typeID); | |
574 | READDATA(thingNumber); | |
575 | ||
576 | CBullet::Read(f); | |
577 | ||
578 | READDATA(detonate); | |
579 | } | |
580 | ||
581 | short CSineBullet::Write(FILE *f) | |
582 | { | |
583 | long size = 0; | |
584 | ||
585 | WRITEDATA(size); | |
586 | WRITEDATA(typeID); | |
587 | WRITEDATA(thingNumber); | |
588 | ||
589 | size += CBullet::Write(f); | |
590 | ||
591 | WRITEDATA(distance); | |
592 | WRITEDATA(radius); | |
593 | WRITEDATA(period); | |
594 | ||
595 | FINISHWRITE; | |
596 | ||
597 | return size; | |
598 | } | |
599 | ||
600 | void CSineBullet::Read(FILE *f) | |
601 | { | |
602 | long size = 0; | |
603 | ||
604 | READDATA(size); | |
605 | READDATA(typeID); | |
606 | READDATA(thingNumber); | |
607 | ||
608 | CBullet::Read(f); | |
609 | ||
610 | READDATA(distance); | |
611 | READDATA(radius); | |
612 | READDATA(period); | |
613 | } | |
614 | ||
615 | short CGuidedBullet::Write(FILE *f) | |
616 | { | |
617 | long size = 0; | |
618 | ||
619 | WRITEDATA(size); | |
620 | WRITEDATA(typeID); | |
621 | WRITEDATA(thingNumber); | |
622 | ||
623 | size += CBullet::Write(f); | |
624 | ||
625 | WRITEDATA(initAbstSign); | |
626 | WRITEDATA(lastfx); | |
627 | WRITEDATA(lastfy); | |
628 | WRITEDATA(lastf); | |
629 | ||
630 | FINISHWRITE; | |
631 | ||
632 | return size; | |
633 | } | |
634 | ||
635 | void CGuidedBullet::Read(FILE *f) | |
636 | { | |
637 | long size = 0; | |
638 | ||
639 | READDATA(size); | |
640 | READDATA(typeID); | |
641 | READDATA(thingNumber); | |
642 | ||
643 | CBullet::Read(f); | |
644 | ||
645 | READDATA(initAbstSign); | |
646 | READDATA(lastfx); | |
647 | READDATA(lastfy); | |
648 | READDATA(lastf); | |
649 | } |
0 | #ifndef __AMP_BULLET__ | |
1 | #define __AMP_BULLET__ | |
2 | ||
3 | #include "Thing.hpp" | |
4 | #include "ObjInfo.hpp" | |
5 | #include "Shape.hpp" | |
6 | ||
7 | enum { | |
8 | kInFlight, | |
9 | kInDetonation, | |
10 | kWaitForDetonation // only for bombs | |
11 | }; | |
12 | ||
13 | class CBullet : public CThing { | |
14 | protected: | |
15 | CShape *projectile1; | |
16 | CShape *projectile2; | |
17 | CShape *detonation[5]; | |
18 | ||
19 | short *tailX, *tailY; | |
20 | double tailStep; | |
21 | ||
22 | CThing *shooter; | |
23 | double targetposition; | |
24 | ||
25 | tWeaponInfo *info; | |
26 | double directionUnitx; | |
27 | double directionUnity; | |
28 | ||
29 | short action; | |
30 | CShape *currentDetonationShape; | |
31 | long detonationStartTime; | |
32 | short noDetonation; | |
33 | ||
34 | void Detonate(short collisionCode, CObject *); | |
35 | short DetonationAnimation(); | |
36 | void Damage(CObject *); | |
37 | ||
38 | public: | |
39 | CBullet *nextBullet, *prevBullet; | |
40 | ||
41 | CBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); | |
42 | ~CBullet(); | |
43 | ||
44 | void OnAllocate(); | |
45 | void LinkInLists(); | |
46 | void UnlinkInLists(); | |
47 | ||
48 | virtual short Think(); | |
49 | void Move(); | |
50 | short Forces(); | |
51 | void Render(short planeX, short planeY, tRect *clipRect); | |
52 | short AmIATreatment(double victimxs, double victimys, double victimxe, double victimye, double &fx, double &fy); | |
53 | short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
54 | ||
55 | virtual short Write(FILE *f); | |
56 | virtual void Read(FILE *f); | |
57 | }; | |
58 | ||
59 | ||
60 | class CSorceryBullet : public CBullet { | |
61 | protected: | |
62 | short numBounces; | |
63 | ||
64 | public: | |
65 | CSorceryBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); | |
66 | ~CSorceryBullet(); | |
67 | ||
68 | short Forces(); | |
69 | short Write(FILE *f); | |
70 | void Read(FILE *f); | |
71 | }; | |
72 | ||
73 | class CBomb; | |
74 | ||
75 | class CBombBullet : public CBullet { | |
76 | friend class CBomb; | |
77 | ||
78 | protected: | |
79 | short detonate; | |
80 | ||
81 | public: | |
82 | CBombBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos); | |
83 | ~CBombBullet(); | |
84 | ||
85 | short Forces(); | |
86 | short Write(FILE *f); | |
87 | void Read(FILE *f); | |
88 | }; | |
89 | ||
90 | class CSineBullet : public CBullet { | |
91 | protected: | |
92 | double distance; | |
93 | double radius; | |
94 | double period; | |
95 | ||
96 | public: | |
97 | CSineBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, short rad, short period); | |
98 | ~CSineBullet(); | |
99 | ||
100 | short Think(); | |
101 | short Write(FILE *f); | |
102 | void Read(FILE *f); | |
103 | }; | |
104 | ||
105 | ||
106 | class CGuidedBullet : public CBullet { | |
107 | protected: | |
108 | CThing *target; | |
109 | double initAbstSign; | |
110 | double lastfx, lastfy, lastf; | |
111 | ||
112 | public: | |
113 | CGuidedBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, CThing *tg); | |
114 | ~CGuidedBullet(); | |
115 | ||
116 | virtual short Think(); | |
117 | short Write(FILE *f); | |
118 | void Read(FILE *f); | |
119 | }; | |
120 | ||
121 | class CStaffBullet : public CGuidedBullet { | |
122 | protected: | |
123 | long lastMonsterScanTime; | |
124 | ||
125 | public: | |
126 | CStaffBullet(short initx, short inity, short width, short height, short number, tWeaponInfo *weaponInfo, double directionx, double directiony, CThing *shooter, double targetpos, CThing *tg); | |
127 | ~CStaffBullet(); | |
128 | ||
129 | short Think(); | |
130 | }; | |
131 | ||
132 | ||
133 | #endif |
0 | #include "Clut.hpp" | |
1 | #include "System.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | #include "Level.hpp" | |
4 | #include "ShapeLd.hpp" | |
5 | ||
6 | extern tConstValues *gConst; | |
7 | extern tConfigData *gConfigData; | |
8 | extern CLevel *gLevel; | |
9 | extern CSystem *gSystem; | |
10 | extern CShapeManager *gShapeManager; | |
11 | extern FILE *logFile; | |
12 | ||
13 | const short kWaterTransparence = 60; // percent of blue | |
14 | const short kLavaTransparence = 80; // percent of red and *3 percent of green | |
15 | const double kFogFactor = 0.8; | |
16 | ||
17 | short WeightenedRandom(short anz); | |
18 | ||
19 | CClutManager::CClutManager() | |
20 | { | |
21 | long maxRadiant, radiant; | |
22 | short j, k, val; | |
23 | ||
24 | for (short n = 0; n < kMaxLuminosityLevel * 2; n ++) { | |
25 | luminosityTable[n] = new unsigned char [256]; | |
26 | } | |
27 | ||
28 | transparentTable1 = new unsigned char * [256]; | |
29 | transparentTable2 = new unsigned char * [256]; | |
30 | transparentTable3 = new unsigned char * [256]; | |
31 | for (j = 0; j < 256; j ++) { | |
32 | transparentTable1[j] = new unsigned char [256]; | |
33 | transparentTable2[j] = new unsigned char [256]; | |
34 | transparentTable3[j] = new unsigned char [256]; | |
35 | } | |
36 | ||
37 | blueLightningTable = new unsigned char * [gConst->kLightningRadiant]; | |
38 | redLightningTable = new unsigned char * [gConst->kLightningRadiant]; | |
39 | greenLightningTable = new unsigned char * [gConst->kLightningRadiant]; | |
40 | yellowLightningTable = new unsigned char * [gConst->kLightningRadiant]; | |
41 | purpleLightningTable = new unsigned char * [gConst->kLightningRadiant]; | |
42 | ||
43 | whiteCoronaTable = new unsigned char * [gConst->kLightningRadiant]; | |
44 | yellowCoronaTable = new unsigned char * [gConst->kLightningRadiant]; | |
45 | blueCoronaTable = new unsigned char * [gConst->kLightningRadiant]; | |
46 | ||
47 | for (j = 0; j < gConst->kLightningRadiant; j ++) { | |
48 | blueLightningTable[j] = new unsigned char [256]; | |
49 | redLightningTable[j] = new unsigned char [256]; | |
50 | greenLightningTable[j] = new unsigned char [256]; | |
51 | yellowLightningTable[j] = new unsigned char [256]; | |
52 | purpleLightningTable[j] = new unsigned char [256]; | |
53 | ||
54 | whiteCoronaTable[j] = new unsigned char [256]; | |
55 | yellowCoronaTable[j] = new unsigned char [256]; | |
56 | blueCoronaTable[j] = new unsigned char [256]; | |
57 | } | |
58 | radiantTable = new unsigned char [gConst->kLightningRadiant * gConst->kLightningRadiant]; | |
59 | maxRadiant = gConst->kLightningRadiant * gConst->kLightningRadiant; | |
60 | ||
61 | for (j = 0; j < gConst->kLightningRadiant; j ++) { | |
62 | for (k = 0; k < gConst->kLightningRadiant; k ++) { | |
63 | radiant = j * j + k * k; | |
64 | if (radiant > maxRadiant) | |
65 | radiantTable [j * gConst->kLightningRadiant + k] = gConst->kLightningRadiant -1; | |
66 | else { | |
67 | val = radiant * gConst->kLightningRadiant / maxRadiant + WeightenedRandom(5) - 1; | |
68 | radiantTable [j * gConst->kLightningRadiant + k] = MIN(val, gConst->kLightningRadiant - 1); | |
69 | } | |
70 | } | |
71 | } | |
72 | coronas[0].values = coronas[1].values = coronas[2].values = 0L; | |
73 | } | |
74 | ||
75 | CClutManager::~CClutManager() | |
76 | { | |
77 | short n; | |
78 | ||
79 | if (coronas[0].values) delete [] coronas[0].values; | |
80 | if (coronas[1].values) delete [] coronas[1].values; | |
81 | if (coronas[2].values) delete [] coronas[2].values; | |
82 | ||
83 | for (n = 0; n < kMaxLuminosityLevel * 2; n ++) { | |
84 | delete [] luminosityTable[n]; | |
85 | } | |
86 | for (n = 0; n < gConst->kLightningRadiant; n ++) { | |
87 | delete [] blueLightningTable[n]; | |
88 | delete [] redLightningTable[n]; | |
89 | delete [] greenLightningTable[n]; | |
90 | delete [] yellowLightningTable[n]; | |
91 | delete [] purpleLightningTable[n]; | |
92 | ||
93 | delete [] whiteCoronaTable[n]; | |
94 | delete [] yellowCoronaTable[n]; | |
95 | delete [] blueCoronaTable[n]; | |
96 | } | |
97 | delete [] blueLightningTable; | |
98 | delete [] redLightningTable; | |
99 | delete [] greenLightningTable; | |
100 | delete [] yellowLightningTable; | |
101 | delete [] purpleLightningTable; | |
102 | ||
103 | delete [] whiteCoronaTable; | |
104 | delete [] yellowCoronaTable; | |
105 | delete [] blueCoronaTable; | |
106 | ||
107 | delete [] radiantTable; | |
108 | } | |
109 | ||
110 | ||
111 | // -------------------------------------- | |
112 | short WeightenedRandom(short anz) | |
113 | // Returns a number which the possibility that the number is 1 is 1/2, for 2 is 1 / 3, for 3 is 1/4 etc. | |
114 | { | |
115 | long maxSum = 0, n; | |
116 | long randValue; | |
117 | ||
118 | for (n = 1; n <= anz; n ++) maxSum += 100 / n; | |
119 | ||
120 | randValue = rand() * maxSum / RAND_MAX; | |
121 | maxSum = 0; | |
122 | for (n = 1; n <= anz; n ++) { | |
123 | if (randValue >= maxSum && randValue < maxSum + 100 / n) return n; | |
124 | maxSum += 100 / n; | |
125 | } | |
126 | return 1; | |
127 | } | |
128 | ||
129 | // ---------------------------------------------- | |
130 | void CClutManager::LoadPalette(RGBcolor *pal) | |
131 | // Writing the palette from the AmpGraf.gif file into the color manager | |
132 | { | |
133 | short j, k; | |
134 | ||
135 | for (short n = 0; n < 256; n ++) { | |
136 | palette[n].red = pal[n].red; | |
137 | palette[n].green = pal[n].green; | |
138 | palette[n].blue = pal[n].blue; | |
139 | } | |
140 | SWAP(palette[0].red, palette[255].red, unsigned char); | |
141 | SWAP(palette[0].green, palette[255].green, unsigned char); | |
142 | SWAP(palette[0].blue, palette[255].blue, unsigned char); | |
143 | } | |
144 | ||
145 | ||
146 | // -------------------------------------------------------- | |
147 | void CClutManager::BuildLuminosityTable() | |
148 | // Builds the luminosity and the color tables | |
149 | { | |
150 | unsigned char color; | |
151 | short j, k; | |
152 | FILE *fClut = fopen(gSystem->QualifyDataDir(gConst->kFileCluts), "rb"); // by LL | |
153 | short index, index2; | |
154 | short mode = 0; | |
155 | ||
156 | if (!fClut) { | |
157 | fClut = fopen(gSystem->QualifyDataDir(gConst->kFileCluts), "wb"); // by LL | |
158 | if (!fClut) MSG("!!! File not found: "); MSG(gConst->kFileCluts); MSG("\n"); | |
159 | mode = 1; | |
160 | } | |
161 | ||
162 | fseek(fClut, 0, SEEK_SET); | |
163 | ||
164 | for (short n = -kMaxLuminosityLevel; n < kMaxLuminosityLevel; n ++) { | |
165 | for (short j = 0; j < 256; j ++) { | |
166 | if (mode) { | |
167 | color = ChangeColorValues(j, SIGN(n) * gConst->kBrightnessLevels[ABS(n)], | |
168 | SIGN(n) * gConst->kBrightnessLevels[ABS(n)], | |
169 | SIGN(n) * gConst->kBrightnessLevels[ABS(n)]); | |
170 | ||
171 | luminosityTable[kMaxLuminosityLevel + n][j] = color; | |
172 | fputc(color, fClut); | |
173 | }else{ | |
174 | luminosityTable[kMaxLuminosityLevel + n][j] = (unsigned char)fgetc(fClut); | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
179 | for (j = 0; j < 256; j ++) { | |
180 | for (k = 0; k < 256; k ++) { | |
181 | if (mode) { | |
182 | transparentTable1[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) / 4 * 100 / 256, (palette[k].green - palette[j].green) / 4 * 100 / 256, (palette[k].blue - palette[j].blue) / 4 * 100 / 256); | |
183 | fputc(transparentTable1[j][k], fClut); | |
184 | transparentTable2[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) / 2 * 100 / 256, (palette[k].green - palette[j].green) / 2 * 100 / 256, (palette[k].blue - palette[j].blue) / 2 * 100 / 256); | |
185 | fputc(transparentTable2[j][k], fClut); | |
186 | transparentTable3[j][k] = ChangeColorValues(j, (palette[k].red - palette[j].red) * 3 / 4 * 100 / 256, (palette[k].green - palette[j].green) * 3 / 4 * 100 / 256, (palette[k].blue - palette[j].blue) * 3 / 4 * 100 / 256); | |
187 | fputc(transparentTable3[j][k], fClut); | |
188 | }else{ | |
189 | transparentTable1[j][k] = (unsigned char)fgetc(fClut); | |
190 | transparentTable2[j][k] = (unsigned char)fgetc(fClut); | |
191 | transparentTable3[j][k] = (unsigned char)fgetc(fClut); | |
192 | } | |
193 | ||
194 | } | |
195 | } | |
196 | ||
197 | // Calculating the lightning tables which are used to calculate the lightning around bullets | |
198 | for (j = 0; j < gConst->kLightningRadiant; j ++) { | |
199 | for (k = 0; k < 256; k ++) { | |
200 | if (mode) { | |
201 | blueLightningTable[j][k] = ChangeColorValues(k, 0, 0, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); | |
202 | fputc(blueLightningTable[j][k], fClut); | |
203 | ||
204 | redLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 70 / gConst->kLightningRadiant, 0, 0); | |
205 | fputc(redLightningTable[j][k], fClut); | |
206 | ||
207 | greenLightningTable[j][k] = ChangeColorValues(k, 0, (gConst->kLightningRadiant - j) * 60 / gConst->kLightningRadiant, 0); | |
208 | fputc(greenLightningTable[j][k], fClut); | |
209 | ||
210 | yellowLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, 0); | |
211 | fputc(yellowLightningTable[j][k], fClut); | |
212 | ||
213 | purpleLightningTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, 0, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant); | |
214 | fputc(purpleLightningTable[j][k], fClut); | |
215 | ||
216 | whiteCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); | |
217 | fputc(whiteCoronaTable[j][k], fClut); | |
218 | ||
219 | yellowCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 80 / gConst->kLightningRadiant); | |
220 | fputc(yellowCoronaTable[j][k], fClut); | |
221 | ||
222 | blueCoronaTable[j][k] = ChangeColorValues(k, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 40 / gConst->kLightningRadiant, (gConst->kLightningRadiant - j) * 100 / gConst->kLightningRadiant); | |
223 | }else{ | |
224 | blueLightningTable[j][k] = (unsigned char)fgetc(fClut); | |
225 | redLightningTable[j][k] = (unsigned char)fgetc(fClut); | |
226 | greenLightningTable[j][k] = (unsigned char)fgetc(fClut); | |
227 | yellowLightningTable[j][k] = (unsigned char)fgetc(fClut); | |
228 | purpleLightningTable[j][k] = (unsigned char)fgetc(fClut); | |
229 | whiteCoronaTable[j][k] = (unsigned char)fgetc(fClut); | |
230 | yellowCoronaTable[j][k] = (unsigned char)fgetc(fClut); | |
231 | //blueCoronaTable[j][k] = (unsigned char)fgetc(fClut); | |
232 | } | |
233 | } | |
234 | } | |
235 | ||
236 | for (j = 0; j < 256; j ++) { | |
237 | if (mode) { | |
238 | waterColorTable[j] = ChangeColorValues(j, 0, 0, kWaterTransparence); | |
239 | fputc(waterColorTable[j], fClut); | |
240 | lavaColorTable[j] = ChangeColorValues(j, kLavaTransparence, kLavaTransparence / 3, 0); | |
241 | fputc(lavaColorTable[j], fClut); | |
242 | shadowTable[j] = ChangeColorValues(j, -gConst->kShadowmodeDarkening, -gConst->kShadowmodeDarkening, -gConst->kShadowmodeDarkening); | |
243 | fputc(shadowTable[j], fClut); | |
244 | fogTable[j] = FindClosestColor(palette[j].red + (short)(double(128 - palette[j].red) * kFogFactor), palette[j].green + (short)(double(128 - palette[j].green) * kFogFactor), palette[j].blue + (short)(double(128 - palette[j].blue) * kFogFactor)); | |
245 | fputc(fogTable[j], fClut); | |
246 | }else{ | |
247 | waterColorTable[j] = (unsigned char)fgetc(fClut); | |
248 | lavaColorTable[j] = (unsigned char)fgetc(fClut); | |
249 | shadowTable[j] = (unsigned char)fgetc(fClut); | |
250 | fogTable[j] = (unsigned char)fgetc(fClut); | |
251 | } | |
252 | } | |
253 | ||
254 | fclose(fClut); | |
255 | } | |
256 | ||
257 | void CClutManager::CalculateCoronas(unsigned char *bmp, short width) | |
258 | { | |
259 | unsigned char *tmp; | |
260 | short coronaColor; | |
261 | short value; | |
262 | unsigned char *bitmap; | |
263 | ||
264 | for (short n = 0; n < kNumOfCoronas; n ++) { | |
265 | coronas[n].dx = kCoronaDescriptor[n][3]; | |
266 | coronas[n].dy = kCoronaDescriptor[n][4]; | |
267 | ||
268 | coronas[n].values = new unsigned char [coronas[n].dx * coronas[n].dy]; | |
269 | ||
270 | coronas[n].table = 0L; | |
271 | ||
272 | bitmap = bmp + kCoronaDescriptor[n][2] * width + kCoronaDescriptor[n][1]; | |
273 | for (short j = 0; j < coronas[n].dy; j ++) { | |
274 | for (short k = 0; k < coronas[n].dx; k ++) { | |
275 | if (bitmap[k] == 255) bitmap[k] = kBlackColor; | |
276 | else if (bitmap[k] == 0) bitmap[k] = kWhiteColor; | |
277 | ||
278 | value = (palette[bitmap[k]].red + palette[bitmap[k]].green + palette[bitmap[k]].blue) / 3; | |
279 | ||
280 | coronas[n].values[j * coronas[n].dx + k] = (unsigned char)(value * gConst->kLightningRadiant / 256); | |
281 | } | |
282 | bitmap += width; | |
283 | } | |
284 | } | |
285 | } | |
286 | ||
287 | ||
288 | // -------------------------------------------------- | |
289 | short CClutManager::FindClosestColor(unsigned char red, unsigned char green, unsigned char blue) | |
290 | /* In: an exact color value | |
291 | Out: color index to a color in the palette which matches the color value the exactest | |
292 | */ | |
293 | { | |
294 | long distance, minDistance = LONG_MAX; | |
295 | short n, minn = -1; | |
296 | ||
297 | for (n = 0; n < 256; n ++) { | |
298 | distance = (long)(palette[n].red - red) * (long)(palette[n].red - red) + | |
299 | (long)(palette[n].green - green) * (long)(palette[n].green - green) + | |
300 | (long)(palette[n].blue - blue) * (long)(palette[n].blue - blue); | |
301 | if (distance < minDistance) { | |
302 | minDistance = distance; | |
303 | minn = n; | |
304 | } | |
305 | } | |
306 | ||
307 | return minn; | |
308 | } | |
309 | ||
310 | // -------------------------------------------------------------- | |
311 | unsigned char CClutManager::ChangeColorValues(unsigned char color, short percentageRed, short percentageGreen, short percentageBlue) | |
312 | /* In: color which red, green and blue parts are to change | |
313 | How many percent each color has to change 100% <= x <= -100% | |
314 | Out: changed color | |
315 | */ | |
316 | { | |
317 | if (color == 0) color = kWhiteColor; | |
318 | if (color == 255) color = kBlackColor; | |
319 | ||
320 | short red = palette[color].red, green = palette[color].green, blue = palette[color].blue; | |
321 | ||
322 | if (percentageRed > 0) | |
323 | red += (unsigned char)((long)(255 - (long)palette[color].red) * percentageRed / 100); | |
324 | else red -= (unsigned char)((long)(palette[color].red) * ABS(percentageRed) / 100); | |
325 | red = MAX(0, red); red = MIN(255, red); | |
326 | ||
327 | if (percentageGreen > 0) | |
328 | green += (unsigned char)((long)(255 - (long)palette[color].green) * percentageGreen / 100); | |
329 | else green -= (unsigned char)((long)(palette[color].green) * ABS(percentageGreen) / 100); | |
330 | green = MAX(0, green); green = MIN(255, green); | |
331 | ||
332 | if (percentageBlue > 0) | |
333 | blue += (unsigned char)((long)(255 - (long)palette[color].blue) * percentageBlue / 100); | |
334 | else blue -= (unsigned char)((long)(palette[color].blue) * ABS(percentageBlue) / 100); | |
335 | blue = MAX(0, blue); blue = MIN(255, blue); | |
336 | ||
337 | return (unsigned char)FindClosestColor((unsigned char)red, (unsigned char)green, (unsigned char)blue); | |
338 | } | |
339 | ||
340 | ||
341 | void CClutManager::SetPixel(unsigned char *source, unsigned char *dest, short modus, short luminosity) | |
342 | { | |
343 | switch (modus) { | |
344 | case kShapemodusNormal: | |
345 | *dest = luminosityTable[kMaxLuminosityLevel + luminosity][*source]; | |
346 | break; | |
347 | case kShapemodusRandom: | |
348 | *dest = rand() & 255; | |
349 | break; | |
350 | case kShapemodusWater: | |
351 | *dest = waterColorTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; | |
352 | break; | |
353 | case kShapemodusLava: | |
354 | *dest = lavaColorTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; | |
355 | break; | |
356 | case kShapemodusShadow: | |
357 | *dest = shadowTable[luminosityTable[kMaxLuminosityLevel + luminosity][*dest]]; | |
358 | break; | |
359 | case kShapemodusFog: | |
360 | *dest = fogTable[luminosityTable[kMaxLuminosityLevel + luminosity][*source]]; | |
361 | break; | |
362 | case kShapemodusTransparent1: | |
363 | *dest = transparentTable1[*source][*dest]; | |
364 | break; | |
365 | case kShapemodusTransparent2: | |
366 | *dest = transparentTable2[*source][*dest]; | |
367 | break; | |
368 | case kShapemodusTransparent3: | |
369 | *dest = transparentTable3[*source][*dest]; | |
370 | break; | |
371 | default: | |
372 | *dest = *source; | |
373 | } | |
374 | } | |
375 | ||
376 | ||
377 | unsigned char **CClutManager::EffectToTable(short effect) | |
378 | { | |
379 | switch (effect) { | |
380 | case kLightningBlueEffect: | |
381 | return blueLightningTable; | |
382 | break; | |
383 | case kLightningRedEffect: | |
384 | return redLightningTable; | |
385 | break; | |
386 | case kLightningGreenEffect: | |
387 | return greenLightningTable; | |
388 | break; | |
389 | case kLightningYellowEffect: | |
390 | return yellowLightningTable; | |
391 | break; | |
392 | case kLightningPurpleEffect: | |
393 | return purpleLightningTable; | |
394 | break; | |
395 | case kWhiteCoronaTable: | |
396 | return whiteCoronaTable; | |
397 | break; | |
398 | case kYellowCoronaTable: | |
399 | return yellowCoronaTable; | |
400 | break; | |
401 | case kBlueCoronaTable: | |
402 | return blueCoronaTable; | |
403 | break; | |
404 | default: | |
405 | return 0L; | |
406 | } | |
407 | } | |
408 | ||
409 | ||
410 | // ------------------------------------------------------------------------ | |
411 | void CClutManager::DrawLightning(double xm, double ym, short effect, CGraphicSurface *surface) | |
412 | // Draws a gConst->kLightningRadinant * 2 - sqare on the screen which illuminates | |
413 | // the background in the color effect | |
414 | { | |
415 | short planeX, planeY; | |
416 | long startx, starty, endx, endy, midx, midy; | |
417 | unsigned char *baseAddr; | |
418 | short pitch; | |
419 | short j, k; | |
420 | CElement *element; | |
421 | unsigned char **table; | |
422 | ||
423 | if (gConfigData->disableLightning) return; | |
424 | ||
425 | table = EffectToTable(effect); | |
426 | ||
427 | gLevel->focus->CalcPlaneOffsets(planeX, planeY); | |
428 | midx = xm - planeX; | |
429 | midy = ym - planeY; | |
430 | ||
431 | startx = midx - gConst->kLightningRadiant; | |
432 | startx = MAX(startx, 0); | |
433 | startx = MIN(startx, kGamePlaneWidth); | |
434 | ||
435 | starty = midy - gConst->kLightningRadiant; | |
436 | starty = MAX(starty, 0); | |
437 | starty = MIN(starty, kGamePlaneHeight); | |
438 | ||
439 | endx = midx + gConst->kLightningRadiant; | |
440 | endx = MAX(endx, 0); | |
441 | endx = MIN(endx, kGamePlaneWidth); | |
442 | ||
443 | endy = midy + gConst->kLightningRadiant; | |
444 | endy = MAX(endy, 0); | |
445 | endy = MIN(endy, kGamePlaneHeight); | |
446 | ||
447 | baseAddr = surface->GetSurfacePtr(&pitch); | |
448 | baseAddr += starty * pitch; | |
449 | ||
450 | for (j = starty + 1; j < endy; j ++) { | |
451 | for (k = startx + 1; k < endx; k ++) { | |
452 | element = gLevel->level[(j + planeY) / kElementSize][(k + planeX) / kElementSize]; | |
453 | if (element->background && !(element->typeID & kBackgroundElement)) | |
454 | baseAddr[k] = table[radiantTable[ABS(j - midy) * gConst->kLightningRadiant + ABS(k - midx)]][baseAddr[k]]; | |
455 | } | |
456 | baseAddr += pitch; | |
457 | } | |
458 | ||
459 | surface->ReleaseSurface(); | |
460 | } | |
461 | ||
462 | void CClutManager::PrepareCorona(double xm, double ym, CGraphicSurface *surface) | |
463 | { | |
464 | short planeX, planeY; | |
465 | short midx, midy; | |
466 | short pitch; | |
467 | unsigned char *baseAddr; | |
468 | ||
469 | gLevel->focus->CalcPlaneOffsets(planeX, planeY); | |
470 | midx = xm - planeX; | |
471 | midy = ym - planeY; | |
472 | ||
473 | if (midx >= 0 && midx < kGamePlaneWidth && midy >= 0 && midy < kGamePlaneHeight) { | |
474 | baseAddr = surface->GetSurfacePtr(&pitch); | |
475 | baseAddr += midy * pitch + midx; | |
476 | ||
477 | *baseAddr = (unsigned char)kWhiteColor; | |
478 | ||
479 | surface->ReleaseSurface(); | |
480 | } | |
481 | } | |
482 | ||
483 | ||
484 | ||
485 | void CClutManager::DrawCorona(double xm, double ym, short coronaNum, short effect, CGraphicSurface *surface, double &coronaFader, long deltaTime) | |
486 | { | |
487 | // Draws a gConst->kLightningRadinant * 2 - sqare on the screen which illuminates | |
488 | // the background in the color effect | |
489 | short planeX, planeY; | |
490 | long startx, starty, endx, endy, midx, midy; | |
491 | short smidx, smidy; | |
492 | unsigned char *baseAddr, *origBaseAddr; | |
493 | short pitch; | |
494 | short j, k; | |
495 | ||
496 | if (gConfigData->disableCoronas) return; | |
497 | ||
498 | tCorona *corona = &coronas[coronaNum]; | |
499 | unsigned char **table = EffectToTable(effect); | |
500 | ||
501 | gLevel->focus->CalcPlaneOffsets(planeX, planeY); | |
502 | midx = xm - planeX; | |
503 | midy = ym - planeY; | |
504 | ||
505 | smidx = corona->dx / 2; | |
506 | startx = midx - smidx; | |
507 | startx = MAX(startx, 0); | |
508 | startx = MIN(startx, kGamePlaneWidth); | |
509 | ||
510 | smidy = corona->dy / 2; | |
511 | starty = midy - smidy; | |
512 | starty = MAX(starty, 0); | |
513 | starty = MIN(starty, kGamePlaneHeight); | |
514 | ||
515 | endx = midx + corona->dx / 2; | |
516 | endx = MAX(endx, 0); | |
517 | endx = MIN(endx, kGamePlaneWidth); | |
518 | ||
519 | endy = midy + corona->dy / 2; | |
520 | endy = MAX(endy, 0); | |
521 | endy = MIN(endy, kGamePlaneHeight); | |
522 | ||
523 | origBaseAddr = surface->GetSurfacePtr(&pitch); | |
524 | baseAddr = origBaseAddr + midy * pitch + midx; | |
525 | ||
526 | if (midx >= 0 && midy >= 0 && midx < kGamePlaneWidth && midy < kGamePlaneHeight && *(unsigned char *)baseAddr == kWhiteColor) { | |
527 | coronaFader += gConst->kCoronaFadeSpeed * deltaTime; | |
528 | coronaFader = MIN(1.0, coronaFader); | |
529 | }else{ | |
530 | coronaFader -= gConst->kCoronaFadeSpeed * deltaTime; | |
531 | coronaFader = MAX(0, coronaFader); | |
532 | } | |
533 | ||
534 | baseAddr = origBaseAddr + starty * pitch; | |
535 | ||
536 | for (j = starty + 1; j < endy; j ++) { | |
537 | for (k = startx + 1; k < endx; k ++) { | |
538 | baseAddr[k] = table[gConst->kLightningRadiant - 1 - (short)((double)corona->values[(smidy + (midy - j)) * corona->dx + smidx + midx - k] * coronaFader)][baseAddr[k]]; | |
539 | } | |
540 | baseAddr += pitch; | |
541 | } | |
542 | ||
543 | surface->ReleaseSurface(); | |
544 | } | |
545 | ||
546 | ||
547 | void SwapBlackWhite(Graphic_file *gf) | |
548 | { | |
549 | for (long n = 0; n < gf->width * gf->height; n ++) | |
550 | if (gf->bitmap[n] == 0) gf->bitmap[n] = kWhiteColor; else if (gf->bitmap[n] == 255) gf->bitmap[n] = kBlackColor; | |
551 | } | |
552 | ||
553 | void CClutManager::FadeToColor(short direction, short effect, CGraphicSurface *surface) | |
554 | { | |
555 | short fadeCounter = 0; | |
556 | long lastFadeTime = 0; | |
557 | short pitch, height; | |
558 | unsigned char *baseAddr; | |
559 | long size; | |
560 | unsigned char **table = EffectToTable(effect); | |
561 | short j, k; | |
562 | short border, step; | |
563 | ||
564 | if (direction == kFadeFromColor) { | |
565 | border = gConst->kLightningRadiant; | |
566 | fadeCounter = 0; | |
567 | step = 1; | |
568 | }else{ | |
569 | border = -1; | |
570 | fadeCounter = gConst->kLightningRadiant -1; | |
571 | step = -1; | |
572 | } | |
573 | ||
574 | while (fadeCounter != border) { | |
575 | if (lastFadeTime < gSystem->GetTicks()) { | |
576 | lastFadeTime = gSystem->GetTicks() + gConst->kFadeTime / gConst->kLightningRadiant; | |
577 | ||
578 | gLevel->PaintLevel(); | |
579 | ||
580 | baseAddr = surface->GetSurfacePtr(&pitch); | |
581 | ||
582 | size = surface->width * surface->height; | |
583 | for (j = 0; j < surface->height; j ++) { | |
584 | for (k = 0; k < surface->width; k ++) { | |
585 | baseAddr[k] = table[fadeCounter][baseAddr[k]]; | |
586 | } | |
587 | baseAddr += pitch; | |
588 | } | |
589 | surface->ReleaseSurface(); | |
590 | surface->FlipToScreen(0, 0); | |
591 | ||
592 | fadeCounter += step; | |
593 | } | |
594 | } | |
595 | } | |
596 | ||
597 | ||
598 | ||
599 |
0 | #ifndef __AMP_CLUTMANAGER__ | |
1 | #define __AMP_CLUTMANAGER__ | |
2 | ||
3 | #include "AmpHead.hpp" | |
4 | #include "Surface.hpp" | |
5 | ||
6 | const short kMaxLuminosityLevel = 4; | |
7 | const short kNumOfCoronas = 3; | |
8 | const short kCoronaIDs[kNumOfCoronas] = {10000, 10001, 10002}; | |
9 | ||
10 | static short kCoronaDescriptor[kNumOfCoronas][5] = { | |
11 | {10000, 317, 543, 94, 92}, | |
12 | {10001, 382, 806, 126, 126}, | |
13 | {10002, 322, 802, 40, 40} | |
14 | }; | |
15 | ||
16 | enum { | |
17 | kLightningNoEffect, | |
18 | kLightningBlueEffect, | |
19 | kLightningRedEffect, | |
20 | kLightningGreenEffect, | |
21 | kLightningYellowEffect, | |
22 | kLightningPurpleEffect, | |
23 | kYellowCoronaTable, | |
24 | kWhiteCoronaTable, | |
25 | kBlueCoronaTable | |
26 | }; | |
27 | ||
28 | enum { | |
29 | kFadeToColor, | |
30 | kFadeFromColor | |
31 | }; | |
32 | ||
33 | struct tCorona { | |
34 | unsigned char *values; | |
35 | unsigned char **table; | |
36 | short dx, dy; | |
37 | }; | |
38 | ||
39 | class CClutManager { | |
40 | protected: | |
41 | RGBcolor palette[256]; | |
42 | unsigned char *luminosityTable[256]; | |
43 | unsigned char waterColorTable[256]; | |
44 | unsigned char lavaColorTable[256]; | |
45 | unsigned char shadowTable[256]; | |
46 | unsigned char fogTable[256]; | |
47 | ||
48 | unsigned char **transparentTable1; | |
49 | unsigned char **transparentTable2; | |
50 | unsigned char **transparentTable3; | |
51 | ||
52 | unsigned char **blueLightningTable; | |
53 | unsigned char **redLightningTable; | |
54 | unsigned char **greenLightningTable; | |
55 | unsigned char **yellowLightningTable; | |
56 | unsigned char **purpleLightningTable; | |
57 | ||
58 | unsigned char **whiteCoronaTable; | |
59 | unsigned char **yellowCoronaTable; | |
60 | unsigned char **blueCoronaTable; | |
61 | ||
62 | unsigned char *radiantTable; | |
63 | ||
64 | tCorona coronas[kNumOfCoronas]; | |
65 | ||
66 | unsigned char **EffectToTable(short effect); | |
67 | ||
68 | public: | |
69 | CClutManager(); | |
70 | ~CClutManager(); | |
71 | ||
72 | short FindClosestColor(unsigned char red, unsigned char green, unsigned char blue); | |
73 | void LoadPalette(RGBcolor *pal); | |
74 | void BuildLuminosityTable(); | |
75 | void CalculateCoronas(unsigned char *, short); | |
76 | unsigned char ChangeColorValues(unsigned char color, short percentageRed, short percentageGreen, short percentageBlue); | |
77 | void SetPixel(unsigned char *source, unsigned char *dest, short modus, short luminosity); | |
78 | void DrawLightning(double xm, double ym, short effect, CGraphicSurface *surface); | |
79 | void PrepareCorona(double xm, double ym, CGraphicSurface *surface); | |
80 | void DrawCorona(double xm, double ym, short corona, short effect, CGraphicSurface *surface, double &coronaFade, long deltaTime); | |
81 | void FadeToColor(short direction, short effect, CGraphicSurface *surface); | |
82 | }; | |
83 | ||
84 | void SwapBlackWhite(Graphic_file *gf); | |
85 | ||
86 | #endif⏎ |
0 | #include "ConstVal.hpp" | |
1 | #include <stdio.h> | |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <System.hpp> | |
5 | ||
6 | extern tConstValues *gConst; | |
7 | extern tConfigData *gConfigData; | |
8 | extern FILE *logFile; | |
9 | extern CSystem *gSystem; | |
10 | ||
11 | long GetLongConstant(FILE *f, char *constName); | |
12 | double GetDoubleConstant(FILE *f, char *constName); | |
13 | void GetStringConstant(FILE *f, char *constName, char *buffer); | |
14 | ||
15 | // ------------------------------------------ | |
16 | void LoadParameters() | |
17 | // Loads the general constants from the *.par file | |
18 | { | |
19 | char levelSetString[11] = "xxLevelSet"; | |
20 | char levelBkgndString[13] = "xxLevelBkgnd"; | |
21 | FILE *paramFile = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL | |
22 | ||
23 | gConst = new tConstValues; | |
24 | ||
25 | gConst->kVelocityUnit = GetDoubleConstant(paramFile, "kVelocityUnit"); | |
26 | gConst->kPlayerAcceleration = GetDoubleConstant(paramFile, "kPlayerAcceleration"); | |
27 | gConst->kPlayerLiquidAccel = GetDoubleConstant(paramFile, "kPlayerLiquidAccel"); | |
28 | gConst->kRunScaleFactor = GetDoubleConstant(paramFile, "kRunScaleFactor"); | |
29 | gConst->kJumpVelocity = GetDoubleConstant(paramFile, "kJumpVelocity"); | |
30 | gConst->kJumpAccelerationTime = GetLongConstant(paramFile, "kJumpAccelerationTime"); | |
31 | gConst->kTeleportTime = GetLongConstant(paramFile, "kTeleportTime"); | |
32 | gConst->kPlayerWidth = GetLongConstant(paramFile, "kPlayerWidth"); | |
33 | gConst->kBulletWidth = GetLongConstant(paramFile, "kBulletWidth"); | |
34 | gConst->kFirehandNumOfBullets = GetLongConstant(paramFile, "kFirehandNumOfBullets"); | |
35 | gConst->kFirehandAngle = (double)GetLongConstant(paramFile, "kFirehandAngle") * 3.141 / 180; | |
36 | gConst->kStaffLoadTime = GetLongConstant(paramFile, "kStaffLoadTime"); | |
37 | gConst->kInitialOxygen = GetLongConstant(paramFile, "kInitialOxygen"); | |
38 | gConst->kOxygenDecrease = GetDoubleConstant(paramFile, "kOxygenDecrease"); | |
39 | gConst->kLavaDamage = GetLongConstant(paramFile, "kLavaDamage"); | |
40 | gConst->kPlayersFirstWeaponShape = GetLongConstant(paramFile, "kPlayersFirstWeaponShape"); | |
41 | gConst->kPickupTime = GetLongConstant(paramFile, "kPickupTime"); | |
42 | ||
43 | gConst->kBulletTailLength = GetLongConstant(paramFile, "kBulletTailLength"); | |
44 | gConst->kBulletTailDistance = GetLongConstant(paramFile, "kBulletTailDistance"); | |
45 | gConst->kDetonationFrameTime = GetDoubleConstant(paramFile, "kDetonationFrameTime"); | |
46 | gConst->kWalkFrameTime = GetLongConstant(paramFile, "kWalkFrameTime"); | |
47 | gConst->kShootFrameTime = GetLongConstant(paramFile, "kShootFrameTime"); | |
48 | gConst->kWeaponChangeTime = GetLongConstant(paramFile, "kWeaponChangeTime"); | |
49 | gConst->kActionDelayTime = GetLongConstant(paramFile, "kActionDelayTime"); | |
50 | gConst->kDieFrameTime = GetLongConstant(paramFile, "kDieFrameTime"); | |
51 | gConst->kDriftSpeed = GetLongConstant(paramFile, "kDriftSpeed"); | |
52 | gConst->kWeaponCarryHeight = GetLongConstant(paramFile, "kWeaponCarryHeight"); | |
53 | ||
54 | gConst->kTeleportBlinkTime = GetLongConstant(paramFile, "kTeleportBlinkTime"); | |
55 | gConst->kSavePortBlinkTime = GetLongConstant(paramFile, "kSavePortBlinkTime"); | |
56 | gConst->kExitPortBlinkTime = GetLongConstant(paramFile, "kExitPortBlinkTime"); | |
57 | ||
58 | gConst->kGravitation = GetDoubleConstant(paramFile, "kGravitation"); | |
59 | gConst->kNormalFriction = GetDoubleConstant(paramFile, "kNormalFriction"); | |
60 | gConst->kLiquidFriction = GetDoubleConstant(paramFile, "kLiquidFriction"); | |
61 | gConst->kMaxFallingSpeed = GetDoubleConstant(paramFile, "kMaxFallingSpeed"); | |
62 | ||
63 | gConst->kJumperJumpAcceleration = GetDoubleConstant(paramFile, "kJumperJumpAcceleration"); | |
64 | ||
65 | gConst->kNumOfBounces = GetLongConstant(paramFile, "kNumOfBounces"); | |
66 | gConst->kSineWeaponRad = GetLongConstant(paramFile, "kSineWeaponRad"); | |
67 | gConst->kMaxTurnAngle = (double)GetLongConstant(paramFile, "kMaxTurnAngle") * 3.141 / 180.0; | |
68 | gConst->kWargFastSpeedup = (double)GetLongConstant(paramFile, "kWargFastSpeedup"); | |
69 | gConst->kWargNearWeaponRadix = GetLongConstant(paramFile, "kWargNearWeaponRadix"); | |
70 | gConst->kWargJumpAcceleration = GetDoubleConstant(paramFile, "kWargJumpAcceleration"); | |
71 | gConst->kDelayAfterWargDeath = GetLongConstant(paramFile, "kDelayAfterWargDeath"); | |
72 | ||
73 | gConst->kActivateDistance = GetLongConstant(paramFile, "kActivateDistance"); | |
74 | gConst->kTreatDistance = GetLongConstant(paramFile, "kTreatDistance"); | |
75 | gConst->kBrightnessLevels[0] = GetLongConstant(paramFile, "kLight"); | |
76 | gConst->kBrightnessLevels[1] = GetLongConstant(paramFile, "kMedium"); | |
77 | gConst->kBrightnessLevels[2] = GetLongConstant(paramFile, "kDark"); | |
78 | gConst->kBrightnessLevels[3] = GetLongConstant(paramFile, "kVeryDark"); | |
79 | ||
80 | gConst->kWeaponSF[0] = GetDoubleConstant(paramFile, "kWeaponSF1"); | |
81 | gConst->kWeaponSF[1] = GetDoubleConstant(paramFile, "kWeaponSF2"); | |
82 | gConst->kWeaponSF[2] = GetDoubleConstant(paramFile, "kWeaponSF3"); | |
83 | gConst->kWeaponSF[3] = GetDoubleConstant(paramFile, "kWeaponSF4"); | |
84 | gConst->kHealthSF[0] = GetDoubleConstant(paramFile, "kHealthSF1"); | |
85 | gConst->kHealthSF[1] = GetDoubleConstant(paramFile, "kHealthSF2"); | |
86 | gConst->kHealthSF[2] = GetDoubleConstant(paramFile, "kHealthSF3"); | |
87 | gConst->kHealthSF[3] = GetDoubleConstant(paramFile, "kHealthSF4"); | |
88 | gConst->kSpeedSF[0] = GetDoubleConstant(paramFile, "kSpeedSF1"); | |
89 | gConst->kSpeedSF[1] = GetDoubleConstant(paramFile, "kSpeedSF2"); | |
90 | gConst->kSpeedSF[2] = GetDoubleConstant(paramFile, "kSpeedSF3"); | |
91 | gConst->kSpeedSF[3] = GetDoubleConstant(paramFile, "kSpeedSF4"); | |
92 | ||
93 | gConst->kFlickeringPeriod = GetLongConstant(paramFile, "kFlickeringPeriod"); | |
94 | gConst->kLightningRadiant = GetLongConstant(paramFile, "kLightningRadiant"); | |
95 | gConst->kBkgndScrollFactor = GetDoubleConstant(paramFile, "kBkgndScrollFactor"); | |
96 | gConst->kCoronaFadeSpeed = GetDoubleConstant(paramFile, "kCoronaFadeSpeed"); | |
97 | ||
98 | gConst->kBlessureInvulnerabilityTime = GetLongConstant(paramFile, "kBlessureInvulnerabilityTime"); | |
99 | gConst->kMonsterTouchBlessure = GetLongConstant(paramFile, "kMonsterTouchBlessure"); | |
100 | gConst->kItemExplosionRad = GetLongConstant(paramFile, "kItemExplosionRad"); | |
101 | gConst->kItemExplosionStartShape = GetLongConstant(paramFile, "kItemExplosionStartShape"); | |
102 | ||
103 | gConst->kHealthPanelColor = GetLongConstant(paramFile, "kHealthPanelColor"); | |
104 | gConst->kOxygenPanelColor = GetLongConstant(paramFile, "kOxygenPanelColor"); | |
105 | gConst->kShadowmodeDarkening = GetLongConstant(paramFile, "kShadowmodeDarkening"); | |
106 | gConst->kFadeTime = GetLongConstant(paramFile, "kFadeTime"); | |
107 | gConst->kStartupTime = GetLongConstant(paramFile, "kStartupTime"); | |
108 | ||
109 | gConst->kTextYDistance = GetLongConstant(paramFile, "kTextYDistance"); | |
110 | gConst->kCameraSpeed = GetLongConstant(paramFile, "kCameraSpeed"); | |
111 | ||
112 | gConst->kSoundMaxDistance = GetLongConstant(paramFile, "kSoundMaxDistance"); | |
113 | gConst->kSoundMinDistance = GetLongConstant(paramFile, "kSoundMinDistance"); | |
114 | ||
115 | GetStringConstant(paramFile, "kFilePalette", gConst->kFilePalette); | |
116 | GetStringConstant(paramFile, "kFileLevel", gConst->kFileLevel); | |
117 | GetStringConstant(paramFile, "kFileMonster", gConst->kFileMonster); | |
118 | GetStringConstant(paramFile, "kFileWeapon", gConst->kFileWeapon); | |
119 | GetStringConstant(paramFile, "kFileInfo", gConst->kFileInfo); | |
120 | GetStringConstant(paramFile, "kFilePlatform", gConst->kFilePlatform); | |
121 | GetStringConstant(paramFile, "kFileObjects", gConst->kFileObjects); | |
122 | GetStringConstant(paramFile, "kFileShapes", gConst->kFileShapes); | |
123 | GetStringConstant(paramFile, "kFileBackground1", gConst->kFileBackground1); | |
124 | GetStringConstant(paramFile, "kFileBackground2", gConst->kFileBackground2); | |
125 | GetStringConstant(paramFile, "kFileCluts", gConst->kFileCluts); | |
126 | GetStringConstant(paramFile, "kFileGUIs", gConst->kFileGUIs); | |
127 | GetStringConstant(paramFile, "kFileConfig", gConst->kFileConfig); | |
128 | GetStringConstant(paramFile, "kFileStartup", gConst->kFileStartup); | |
129 | ||
130 | ||
131 | GetStringConstant(paramFile, "kMonsterName1", gConst->kMonsterNames[0]); | |
132 | GetStringConstant(paramFile, "kMonsterName2", gConst->kMonsterNames[1]); | |
133 | GetStringConstant(paramFile, "kMonsterName3", gConst->kMonsterNames[2]); | |
134 | GetStringConstant(paramFile, "kMonsterName4", gConst->kMonsterNames[3]); | |
135 | GetStringConstant(paramFile, "kMonsterName5", gConst->kMonsterNames[4]); | |
136 | GetStringConstant(paramFile, "kMonsterName6", gConst->kMonsterNames[5]); | |
137 | GetStringConstant(paramFile, "kMonsterName7", gConst->kMonsterNames[6]); | |
138 | GetStringConstant(paramFile, "kMonsterName8", gConst->kMonsterNames[7]); | |
139 | GetStringConstant(paramFile, "kMonsterName9", gConst->kMonsterNames[8]); | |
140 | GetStringConstant(paramFile, "kMonsterName10", gConst->kMonsterNames[9]); | |
141 | GetStringConstant(paramFile, "kMonsterName11", gConst->kMonsterNames[10]); | |
142 | ||
143 | gConst->kMonsterNameSpeed = GetLongConstant(paramFile, "kMonsterNameSpeed"); | |
144 | gConst->kMonsterNameX = GetLongConstant(paramFile, "kMonsterNameX"); | |
145 | ||
146 | ||
147 | gConst->kShowFPS = GetLongConstant(paramFile, "kShowFPS"); | |
148 | ||
149 | for (short n = 1; n <= kNumOfLevels; n ++) { | |
150 | levelSetString[0] = (char)(n / 10) + '0'; | |
151 | levelSetString[1] = (char)(n % 10) + '0'; | |
152 | levelBkgndString[0] = (char)(n / 10) + '0'; | |
153 | levelBkgndString[1] = (char)(n % 10) + '0'; | |
154 | gConst->kShapeSets[n -1] = GetLongConstant(paramFile, levelSetString) -1; | |
155 | gConst->kBackgrounds[n -1] = GetLongConstant(paramFile, levelBkgndString); | |
156 | } | |
157 | ||
158 | fclose(paramFile); | |
159 | ||
160 | // Hier sollte auch im Home Directory gesucht werden... | |
161 | paramFile = gSystem->FindFile(gConst->kFileConfig); // by LL | |
162 | ||
163 | gConfigData->leftKey = GetLongConstant(paramFile, "LeftKey"); | |
164 | GetStringConstant(paramFile, "LeftKeyText", gConfigData->leftKeyText); | |
165 | gConfigData->rightKey = GetLongConstant(paramFile, "RightKey"); | |
166 | GetStringConstant(paramFile, "RightKeyText", gConfigData->rightKeyText); | |
167 | gConfigData->jumpKey = GetLongConstant(paramFile, "JumpKey"); | |
168 | GetStringConstant(paramFile, "JumpKeyText", gConfigData->jumpKeyText); | |
169 | gConfigData->runKey = GetLongConstant(paramFile, "RunKey"); | |
170 | GetStringConstant(paramFile, "RunKeyText", gConfigData->runKeyText); | |
171 | gConfigData->shootKey = GetLongConstant(paramFile, "ShootKey"); | |
172 | GetStringConstant(paramFile, "ShootKeyText", gConfigData->shootKeyText); | |
173 | gConfigData->nextWeaponKey = GetLongConstant(paramFile, "NextWeaponKey"); | |
174 | GetStringConstant(paramFile, "NextWeaponKeyText", gConfigData->nextWeaponKeyText); | |
175 | gConfigData->prevWeaponKey = GetLongConstant(paramFile, "PrevWeaponKey"); | |
176 | GetStringConstant(paramFile, "PrevWeaponKeyText", gConfigData->prevWeaponKeyText); | |
177 | gConfigData->activateKey = GetLongConstant(paramFile, "ActivateKey"); | |
178 | GetStringConstant(paramFile, "ActivateKeyText", gConfigData->activateKeyText); | |
179 | ||
180 | gConfigData->weapon1Key = GetLongConstant(paramFile, "Weapon1Key"); | |
181 | gConfigData->weapon2Key = GetLongConstant(paramFile, "Weapon2Key"); | |
182 | gConfigData->weapon3Key = GetLongConstant(paramFile, "Weapon3Key"); | |
183 | gConfigData->weapon4Key = GetLongConstant(paramFile, "Weapon4Key"); | |
184 | gConfigData->weapon5Key = GetLongConstant(paramFile, "Weapon5Key"); | |
185 | gConfigData->weapon6Key = GetLongConstant(paramFile, "Weapon6Key"); | |
186 | gConfigData->weapon7Key = GetLongConstant(paramFile, "Weapon7Key"); | |
187 | gConfigData->weapon8Key = GetLongConstant(paramFile, "Weapon8Key"); | |
188 | ||
189 | gConfigData->soundVolume = GetLongConstant(paramFile, "SoundVolume"); | |
190 | ||
191 | gConfigData->screenWidth = GetLongConstant(paramFile, "ScreenWidth"); | |
192 | gConfigData->screenHeight = GetLongConstant(paramFile, "ScreenHeight"); | |
193 | ||
194 | gConfigData->disableCoronas = GetLongConstant(paramFile, "DisableCoronas"); | |
195 | gConfigData->disableLightning = GetLongConstant(paramFile, "DisableLightning"); | |
196 | gConfigData->disableShapeModes = GetLongConstant(paramFile, "DisableShapeModes"); | |
197 | ||
198 | fclose(paramFile); | |
199 | } | |
200 | ||
201 | ||
202 | ||
203 | ||
204 | ||
205 | ||
206 | #define CATCHSPACES while (c == (unsigned char)' ') {c = fgetc(f); } | |
207 | ||
208 | short GetValue(FILE *f, char *constName, char *value) | |
209 | { | |
210 | char key[30]; | |
211 | char c = 0; | |
212 | short n; | |
213 | ||
214 | fseek(f, 0, SEEK_SET); | |
215 | ||
216 | while (strcmp(key, constName)) { | |
217 | c = fgetc(f); | |
218 | n = 1; | |
219 | if (c == (unsigned char)'#') { // comment | |
220 | while (fgetc(f) != (unsigned char)'\n') {} | |
221 | }else if (c == (unsigned char)'@') { | |
222 | value[0] = '\0'; | |
223 | return 0; | |
224 | }else{ | |
225 | key[0] = c; | |
226 | while (c != (unsigned char)' ' && c != (unsigned char)'=') { | |
227 | c = fgetc(f); | |
228 | key[n] = c; n ++; | |
229 | } | |
230 | key[n - 1] = '\0'; | |
231 | CATCHSPACES | |
232 | if (c != (unsigned char)'=') return 0; | |
233 | c = fgetc(f); n = 1; | |
234 | CATCHSPACES | |
235 | value[0] = c; | |
236 | while (c != (unsigned char)' ' && c != (unsigned char)'\n') { | |
237 | c = fgetc(f); | |
238 | value[n] = c; n ++; | |
239 | } | |
240 | value[n - 1] = '\0'; | |
241 | while (c != (unsigned char)'\n') {c = fgetc(f); } | |
242 | } | |
243 | } | |
244 | if (key[0] == '@') return 0; | |
245 | else return 1; | |
246 | } | |
247 | ||
248 | long GetLongConstant(FILE *f, char *constName) | |
249 | { | |
250 | char val[30]; | |
251 | ||
252 | if (GetValue(f, constName, val)) | |
253 | return atoi(val); | |
254 | else{ | |
255 | return 0; | |
256 | } | |
257 | } | |
258 | ||
259 | double GetDoubleConstant(FILE *f, char *constName) | |
260 | { | |
261 | char val[30]; | |
262 | ||
263 | if (GetValue(f, constName, val)) | |
264 | return atof(val); | |
265 | else{ | |
266 | return 0; | |
267 | } | |
268 | } | |
269 | ||
270 | void GetStringConstant(FILE *f, char *constName, char *buffer) | |
271 | { | |
272 | GetValue(f, constName, buffer); | |
273 | }⏎ |
0 | #ifndef __AMP_CONSTVAL__ | |
1 | #define __AMP_CONSTVAL__ | |
2 | ||
3 | #include "AmpHead.hpp" | |
4 | ||
5 | const short kFilenameLength = 12; | |
6 | const short kKeyDescriptionLength = 20; | |
7 | ||
8 | struct tConstValues { | |
9 | // The accelerations and velocities are measured | |
10 | // in pixel / (second * 1000) | |
11 | double kVelocityUnit; | |
12 | double kPlayerAcceleration; | |
13 | double kPlayerLiquidAccel; | |
14 | double kJumpVelocity; | |
15 | double kRunScaleFactor; | |
16 | short kJumpAccelerationTime; | |
17 | short kTeleportTime; // Time for a teleport process | |
18 | short kPlayerWidth; // Width of player used for collisions | |
19 | short kBulletWidth; // Width of bullets used for collisions | |
20 | short kFirehandNumOfBullets; // Num of bullets shots when used firehands | |
21 | double kFirehandAngle; // angle between two shoot directions | |
22 | short kStaffLoadTime; // Time to load the staff weapon | |
23 | short kInitialOxygen; // Inital amound of oxygen | |
24 | double kOxygenDecrease; // Decrease of oxygen in one second | |
25 | short kLavaDamage; // Damage caused by lava per tick | |
26 | short kPlayersFirstWeaponShape; // Players first weapon shape | |
27 | long kPickupTime; // Time the pickup shape is drawn | |
28 | ||
29 | short kBulletTailLength; // How many shapes are to be drawn at the tail of a bullet | |
30 | short kBulletTailDistance; // Distance of two shapes | |
31 | double kDetonationFrameTime; // Every 1/2 second a new detonation frame | |
32 | short kWalkFrameTime; // in ticks | |
33 | short kShootFrameTime; // Time for one shoot animation frame | |
34 | short kWeaponChangeTime; // Time between changing a weapon (Pressing x or y) | |
35 | short kActionDelayTime; // Time between two actions the player performs | |
36 | short kDieFrameTime; // Time between two die frames | |
37 | ||
38 | short kWeaponCarryHeight; // Height of carrying a weapon | |
39 | ||
40 | double kDriftSpeed; | |
41 | // Blinking times for player ports | |
42 | short kTeleportBlinkTime; | |
43 | short kSavePortBlinkTime; | |
44 | short kExitPortBlinkTime; | |
45 | ||
46 | // general physics constants | |
47 | double kGravitation; | |
48 | double kNormalFriction; | |
49 | double kLiquidFriction; | |
50 | double kMaxFallingSpeed; // max. velocity when falling | |
51 | ||
52 | // Monster movement constants | |
53 | double kJumperJumpAcceleration; | |
54 | // How often the sorcery bullet bounces off | |
55 | short kNumOfBounces; | |
56 | short kSineWeaponRad; | |
57 | double kMaxTurnAngle; // max angle a guided bullet can turn | |
58 | short kWargNearWeaponRadix; | |
59 | double kWargFastSpeedup; | |
60 | double kWargJumpAcceleration; | |
61 | ||
62 | long kDelayAfterWargDeath; // Delay before level switch after killed warg | |
63 | ||
64 | // At which distance a bullet becomes a treat for a monster | |
65 | short kTreatDistance; | |
66 | short kBrightnessLevels[4]; | |
67 | long kFlickeringPeriod; | |
68 | ||
69 | short kActivateDistance; // Distance from the player a monster starts to move | |
70 | ||
71 | double kWeaponSF[4]; | |
72 | double kHealthSF[4]; | |
73 | double kSpeedSF[4]; | |
74 | ||
75 | short kLightningRadiant; // Radius of lightning of a bullet | |
76 | double kBkgndScrollFactor; // Background scrolling speed in percent of foreground scrolling speed | |
77 | double kCoronaFadeSpeed; // How many percent of 1 the corona fades every tick | |
78 | ||
79 | short kBlessureInvulnerabilityTime; // How long is a monster invulnerable after a hurt | |
80 | short kMonsterTouchBlessure; // Blessure when touching a monster | |
81 | ||
82 | short kItemExplosionRad; | |
83 | short kItemExplosionStartShape; | |
84 | ||
85 | short kHealthPanelColor; | |
86 | short kOxygenPanelColor; | |
87 | short kShadowmodeDarkening; // Percent of darkness of shaded bodies | |
88 | short kFadeTime; // Time for entirely fading the screen | |
89 | short kStartupTime; // Time for displaying the startup screen | |
90 | ||
91 | short kSoundMaxDistance; // At which distance a sound can be heard | |
92 | short kSoundMinDistance; // At which distance a sound is maximal loud | |
93 | ||
94 | short kTextYDistance; // Distance between two lines of text displayed | |
95 | short kCameraSpeed; // Speed of camera | |
96 | ||
97 | short kShowFPS; // Indicates whether the FPS is displayed | |
98 | ||
99 | char kFilePalette[kFilenameLength]; | |
100 | char kFileLevel[kFilenameLength]; | |
101 | char kFileMonster[kFilenameLength]; | |
102 | char kFileWeapon[kFilenameLength]; | |
103 | char kFileInfo[kFilenameLength]; | |
104 | char kFilePlatform[kFilenameLength]; | |
105 | char kFileObjects[kFilenameLength]; | |
106 | char kFileShapes[kFilenameLength]; | |
107 | char kFileBackground1[kFilenameLength]; | |
108 | char kFileBackground2[kFilenameLength]; | |
109 | char kFileCluts[kFilenameLength]; | |
110 | char kFileGUIs[kFilenameLength]; | |
111 | char kFileConfig[kFilenameLength]; | |
112 | char kFileStartup[kFilenameLength]; | |
113 | ||
114 | char kMonsterNames[11][kFilenameLength]; | |
115 | short kMonsterNameSpeed; // Scrollspeed of monstername | |
116 | short kMonsterNameX; // x-pos on screen | |
117 | ||
118 | short kShapeSets[kNumOfLevels]; | |
119 | short kBackgrounds[kNumOfLevels]; | |
120 | }; | |
121 | ||
122 | ||
123 | struct tConfigData { | |
124 | short leftKey; | |
125 | char leftKeyText[kKeyDescriptionLength]; | |
126 | short rightKey; | |
127 | char rightKeyText[kKeyDescriptionLength]; | |
128 | short jumpKey; | |
129 | char jumpKeyText[kKeyDescriptionLength]; | |
130 | short runKey; | |
131 | char runKeyText[kKeyDescriptionLength]; | |
132 | short shootKey; | |
133 | char shootKeyText[kKeyDescriptionLength]; | |
134 | short nextWeaponKey; | |
135 | char nextWeaponKeyText[kKeyDescriptionLength]; | |
136 | short prevWeaponKey; | |
137 | char prevWeaponKeyText[kKeyDescriptionLength]; | |
138 | short activateKey; | |
139 | char activateKeyText[kKeyDescriptionLength]; | |
140 | ||
141 | short weapon1Key; | |
142 | short weapon2Key; | |
143 | short weapon3Key; | |
144 | short weapon4Key; | |
145 | short weapon5Key; | |
146 | short weapon6Key; | |
147 | short weapon7Key; | |
148 | short weapon8Key; | |
149 | ||
150 | short soundVolume; | |
151 | short haveSound; // by LL | |
152 | ||
153 | short screenWidth; | |
154 | short screenHeight; | |
155 | short tryFullScreen; // by LL | |
156 | ||
157 | short disableCoronas; | |
158 | short disableLightning; | |
159 | short disableShapeModes; | |
160 | }; | |
161 | ||
162 | #endif⏎ |
0 | #include "Creeper.hpp" |
0 | #include "Element.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "Gui.hpp" | |
3 | #include "SndSys.hpp" | |
4 | ||
5 | extern CApplication *gApplication; | |
6 | extern CShapeManager *gShapeManager; | |
7 | extern CSystem *gSystem; | |
8 | extern tConstValues *gConst; | |
9 | extern CLevel *gLevel; | |
10 | extern CGUI *gGUI; | |
11 | extern CSoundSystem *gSoundSystem; | |
12 | ||
13 | CElement::CElement(short initx, short inity, short width, short height, tLevelElement *levelElement) : CObject(initx, inity, width, height) | |
14 | { | |
15 | typeID |= kElement; | |
16 | ||
17 | if (levelElement) { | |
18 | brightness = 3 - LOBYTE(levelElement->light); | |
19 | brightness2 = 3 - HIBYTE(levelElement->light); | |
20 | iconID = levelElement->iconID; | |
21 | bitData = levelElement->bitData; | |
22 | lastState = 0; | |
23 | ||
24 | refNum = LOBYTE(levelElement->refNum); | |
25 | key = HIBYTE(levelElement->refNum); | |
26 | data = HIBYTE(levelElement->kind); | |
27 | ||
28 | OnAllocate(); | |
29 | ||
30 | weight = SHRT_MAX; | |
31 | background = levelElement->kind; | |
32 | } | |
33 | } | |
34 | ||
35 | void CElement::OnAllocate() | |
36 | { | |
37 | if (iconID > 0) { | |
38 | shape = gShapeManager->FindShape(iconID, brightness); | |
39 | shape2 = gShapeManager->FindShape(iconID, brightness2); | |
40 | } | |
41 | ||
42 | // If there's something on that element, allocate the struct which holds the several shapes | |
43 | if (bitData & (kPlatformSwitchMask | kLightSwitchMask | kTeleportMask | kSaveMask | kExitMask | kPassiveLightMask | kPassivePlatformMask | kRightDriftMask | kLeftDriftMask | kInfotextMask)) { | |
44 | elementThings = new tElementThings; | |
45 | ||
46 | if (bitData & kPlatformSwitchMask) { | |
47 | elementThings->platformSwitchInactive = gShapeManager->FindShape(kPlatformSwitchInactiveID, 0); | |
48 | elementThings->platformSwitchActive = gShapeManager->FindShape(kPlatformSwitchActiveID, 0); | |
49 | elementThings->referencedPlatform = gApplication->platformTable[refNum]; | |
50 | }else{ | |
51 | elementThings->platformSwitchInactive = elementThings->platformSwitchActive = 0L; | |
52 | elementThings->referencedPlatform = 0L; | |
53 | } | |
54 | if (bitData & kPassivePlatformMask) { | |
55 | elementThings->referencedPlatform = gApplication->platformTable[refNum]; | |
56 | elementThings->passiveHasChanged = 0; | |
57 | } | |
58 | ||
59 | if (bitData & kLightSwitchMask) { | |
60 | elementThings->lightSwitch = gShapeManager->FindShape(kLightSwitchInactiveID, 0); | |
61 | elementThings->lightSwitch2 = gShapeManager->FindShape(kLightSwitchActiveID, 0); | |
62 | }else{ | |
63 | elementThings->lightSwitch = elementThings->lightSwitch2 = 0L; | |
64 | } | |
65 | ||
66 | if (bitData & kTeleportMask) { | |
67 | elementThings->teleporter = gShapeManager->FindShape(kTeleportStateOne, 0); | |
68 | elementThings->teleporter2 = gShapeManager->FindShape(kTeleportStateTwo, 0); | |
69 | }else{ | |
70 | elementThings->teleporter = elementThings->teleporter2 = 0L; | |
71 | } | |
72 | elementThings->teleportBlinkTime = 0; | |
73 | ||
74 | if (bitData & kSaveMask) { | |
75 | elementThings->savePort = gShapeManager->FindShape(kSavePortStateOne, 0); | |
76 | elementThings->savePort2 = gShapeManager->FindShape(kSavePortStateTwo, 0); | |
77 | }else{ | |
78 | elementThings->savePort = elementThings->savePort2 = 0L; | |
79 | } | |
80 | elementThings->savePortBlinkTime = 0; | |
81 | ||
82 | if (bitData & kExitMask) { | |
83 | elementThings->exitPort = gShapeManager->FindShape(kExitStateOne, 0); | |
84 | elementThings->exitPort2 = gShapeManager->FindShape(kExitStateTwo, 0); | |
85 | }else{ | |
86 | elementThings->exitPort = elementThings->exitPort2 = 0L; | |
87 | } | |
88 | elementThings->exitPortBlinkTime = 0; | |
89 | ||
90 | elementThings->passiveHasChanged = 0; | |
91 | ||
92 | elementThings->drift = 0L; | |
93 | if (bitData & kLeftDriftMask) elementThings->drift = gShapeManager->FindShape (kDriftLeftID, 0); | |
94 | if (bitData & kRightDriftMask) elementThings->drift = gShapeManager->FindShape(kDriftRightID, 0); | |
95 | ||
96 | if (bitData & kInfotextMask) { | |
97 | elementThings->infoPort = gShapeManager->FindShape(kInfotextStateOne, 0); | |
98 | elementThings->infoPort2 = gShapeManager->FindShape(kInfotextStateTwo, 0); | |
99 | }else{ | |
100 | elementThings->infoPort = elementThings->infoPort2 = 0L; | |
101 | } | |
102 | elementThings->infoPortBlinkTime = 0; | |
103 | ||
104 | }else elementThings = 0L; | |
105 | } | |
106 | ||
107 | ||
108 | CElement::~CElement() | |
109 | { | |
110 | if (elementThings) delete elementThings; | |
111 | } | |
112 | ||
113 | ||
114 | void CElement::LinkPlatforms() | |
115 | { | |
116 | if (elementThings) { | |
117 | if (bitData & kPlatformSwitchMask) { | |
118 | elementThings->referencedPlatform = gApplication->platformTable[refNum]; | |
119 | }else{ | |
120 | elementThings->referencedPlatform = 0L; | |
121 | } | |
122 | if (bitData & kPassivePlatformMask) { | |
123 | elementThings->referencedPlatform = gApplication->platformTable[refNum]; | |
124 | elementThings->passiveHasChanged = 0; | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | ||
130 | void CElement::PaintElementThings(short planeX, short planeY, tRect *clipRect) | |
131 | { | |
132 | CShape *tmp; | |
133 | ||
134 | if (bitData & kPlatformSwitchMask && elementThings->referencedPlatform) | |
135 | elementThings->referencedPlatform->GetCurrentState(elementThings->platformSwitchActive, elementThings->platformSwitchInactive)->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
136 | ||
137 | if (elementThings->lightSwitch) elementThings->lightSwitch->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
138 | ||
139 | if (elementThings->teleporter) { | |
140 | elementThings->teleporter->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
141 | if (elementThings->teleportBlinkTime < gSystem->GetTicks()) { | |
142 | tmp = elementThings->teleporter; elementThings->teleporter = elementThings->teleporter2; elementThings->teleporter2 = tmp; | |
143 | elementThings->teleportBlinkTime = gSystem->GetTicks() + gConst->kTeleportBlinkTime; | |
144 | } | |
145 | } | |
146 | if (elementThings->savePort) { | |
147 | elementThings->savePort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
148 | if (elementThings->savePortBlinkTime < gSystem->GetTicks()) { | |
149 | tmp = elementThings->savePort; elementThings->savePort = elementThings->savePort2; elementThings->savePort2 = tmp; | |
150 | elementThings->savePortBlinkTime = gSystem->GetTicks() + gConst->kSavePortBlinkTime; | |
151 | } | |
152 | } | |
153 | ||
154 | if (elementThings->exitPort) { | |
155 | elementThings->exitPort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
156 | if (elementThings->exitPortBlinkTime < gSystem->GetTicks()) { | |
157 | tmp = elementThings->exitPort; elementThings->exitPort = elementThings->exitPort2; elementThings->exitPort2 = tmp; | |
158 | elementThings->exitPortBlinkTime = gSystem->GetTicks() + gConst->kExitPortBlinkTime; | |
159 | } | |
160 | } | |
161 | if (elementThings->drift) elementThings->drift->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
162 | ||
163 | if (elementThings->infoPort) { | |
164 | elementThings->infoPort->RenderShape(xs - planeX, ys - planeY, clipRect, kShapemodusNormal, 0, gApplication->plane); | |
165 | if (elementThings->infoPortBlinkTime < gSystem->GetTicks()) { | |
166 | tmp = elementThings->infoPort; elementThings->infoPort = elementThings->infoPort2; elementThings->infoPort2 = tmp; | |
167 | elementThings->infoPortBlinkTime = gSystem->GetTicks() + gConst->kExitPortBlinkTime; | |
168 | } | |
169 | } | |
170 | } | |
171 | ||
172 | void CElement::PaintElement(short planeX, short planeY, tRect *clipRect) | |
173 | { | |
174 | long timeStamp; | |
175 | ||
176 | if (shape) shape->RenderShape(xs - planeX, ys - planeY, clipRect, 0, 0, gApplication->plane); | |
177 | ||
178 | if (bitData & kFlickeringMask) { | |
179 | timeStamp = (gApplication->syncTime / gConst->kFlickeringPeriod) & 1; | |
180 | if ((long)(timeStamp) != lastState) { | |
181 | SwapLights(); | |
182 | lastState = timeStamp; | |
183 | } | |
184 | } | |
185 | ||
186 | if (elementThings) PaintElementThings(planeX, planeY, clipRect); | |
187 | } | |
188 | ||
189 | ||
190 | short CElement::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
191 | { | |
192 | short returnValue; | |
193 | double driftSpeed = 0; | |
194 | double friction = bitData & kIceMask ? 0 : gConst->kNormalFriction; | |
195 | ||
196 | if ((returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject)) & kCollisionOnBottom) { | |
197 | if (bitData & kRightDriftMask) driftSpeed = gConst->kDriftSpeed; | |
198 | if (bitData & kLeftDriftMask) driftSpeed = -gConst->kDriftSpeed; | |
199 | sender->CollisionEvent(friction, driftSpeed); | |
200 | ||
201 | } | |
202 | return returnValue; | |
203 | } | |
204 | ||
205 | // ----------------------------------------- | |
206 | short CElement::Action() | |
207 | // Is called from CPlayer::Think, when the player performs an action on that element | |
208 | // Looks if there is some action possible, and do it | |
209 | { | |
210 | if (elementThings) { // is there any action possible? | |
211 | if(elementThings->referencedPlatform) { | |
212 | elementThings->referencedPlatform->Switch(); | |
213 | } | |
214 | ||
215 | if (bitData & kLightSwitchMask) { | |
216 | SWAP(elementThings->lightSwitch, elementThings->lightSwitch2, CShape *) | |
217 | gLevel->SwitchLight(refNum); | |
218 | } | |
219 | ||
220 | if (bitData & kSaveMask) gApplication->command = gGUI->RunUserInterface(kSaveGamePage); | |
221 | ||
222 | if (bitData & kInfotextMask) gGUI->DisplayInfotext(data); | |
223 | } | |
224 | ||
225 | return bitData; | |
226 | } | |
227 | ||
228 | void CElement::PassiveAction() | |
229 | { | |
230 | if (elementThings) { | |
231 | if ((bitData & kPassiveLightMask) && !elementThings->passiveHasChanged) { | |
232 | gLevel->SwitchLight(refNum); | |
233 | elementThings->passiveHasChanged = 1; | |
234 | } | |
235 | if ((bitData & kPassivePlatformMask) && !elementThings->passiveHasChanged && elementThings->referencedPlatform) { | |
236 | elementThings->referencedPlatform->Switch(); | |
237 | elementThings->passiveHasChanged = 1; | |
238 | } | |
239 | } | |
240 | } | |
241 | ||
242 | // -------------------------------- | |
243 | void CElement::SwapLights() | |
244 | // Swaps the light textures for that element | |
245 | { | |
246 | SWAP(shape, shape2, CShape *); | |
247 | SWAP(brightness, brightness2, short); | |
248 | } | |
249 | ||
250 | // -------------------------------- | |
251 | void CElement::Teleport(double &xp, double &yp) | |
252 | // Moves the coordinates to this element | |
253 | { | |
254 | if (background) { | |
255 | xp = xs; | |
256 | yp = ys; | |
257 | } | |
258 | } | |
259 | ||
260 | ||
261 | // --------------------------------------------- | |
262 | short CElement::GetElementLiquid() | |
263 | // Returns the liquid on this element, expressed by the shape drawing modus | |
264 | { | |
265 | if (bitData & kLavaMask) return kShapemodusLava; | |
266 | if (bitData & kWaterMask) return kShapemodusWater; | |
267 | if (bitData & kFogMask) return kShapemodusFog; | |
268 | return kShapemodusNormal; | |
269 | } | |
270 | ||
271 | CBackgroundElement::CBackgroundElement(short initx, short inity, short width, short height, tLevelElement *levelElement) : CElement(initx, inity, width, height, levelElement) | |
272 | { | |
273 | typeID |= kBackgroundElement; | |
274 | ||
275 | if (levelElement) OnAllocate(); | |
276 | brightness = 0; | |
277 | } | |
278 | ||
279 | void CBackgroundElement::OnAllocate() | |
280 | { | |
281 | short params[5] = {-1, xs, ys, xe - xs, ye - ys}; | |
282 | unsigned char *tmpBmp; | |
283 | ||
284 | tmpBmp = gShapeManager->GetBackground(params[1], params[2]); | |
285 | shape = new CBackground(tmpBmp, params, 0); | |
286 | } | |
287 | ||
288 | ||
289 | CBackgroundElement::~CBackgroundElement() | |
290 | { | |
291 | delete shape; | |
292 | } | |
293 | ||
294 | void CBackgroundElement::PaintElement(short planeX, short planeY, tRect *clipRect) | |
295 | { | |
296 | long timeStamp; | |
297 | ||
298 | if (shape) shape->RenderShape(xs - planeX, ys - planeY, clipRect, planeX * gConst->kBkgndScrollFactor, 0, gApplication->plane); | |
299 | ||
300 | if (elementThings) PaintElementThings(planeX, planeY, clipRect); | |
301 | } | |
302 | ||
303 | ||
304 | ||
305 | short CElement::Write(FILE *f) | |
306 | { | |
307 | long size = 0; | |
308 | ||
309 | WRITEDATA(size); | |
310 | WRITEDATA(typeID); | |
311 | ||
312 | size += CObject::Write(f); | |
313 | ||
314 | WRITEDATA(bitData); | |
315 | WRITEDATA(lastState); | |
316 | WRITEDATA(iconID); | |
317 | WRITEDATA(brightness); | |
318 | WRITEDATA(brightness2); | |
319 | WRITEDATA(key); | |
320 | WRITEDATA(refNum); | |
321 | WRITEDATA(data); | |
322 | ||
323 | WRITEDATA(elementThings); | |
324 | if (elementThings) { | |
325 | WRITEDATA(elementThings->teleportBlinkTime); | |
326 | WRITEDATA(elementThings->savePortBlinkTime); | |
327 | WRITEDATA(elementThings->exitPortBlinkTime); | |
328 | WRITEDATA(elementThings->passiveHasChanged); | |
329 | } | |
330 | ||
331 | ||
332 | ||
333 | FINISHWRITE; | |
334 | ||
335 | return size; | |
336 | } | |
337 | ||
338 | void CElement::Read(FILE *f) | |
339 | { | |
340 | long size = 0; | |
341 | long elemThings; | |
342 | ||
343 | READDATA(size); | |
344 | READDATA(typeID); | |
345 | ||
346 | CObject::Read(f); | |
347 | ||
348 | READDATA(bitData); | |
349 | READDATA(lastState); | |
350 | READDATA(iconID); | |
351 | READDATA(brightness); | |
352 | READDATA(brightness2); | |
353 | READDATA(key); | |
354 | READDATA(refNum); | |
355 | READDATA(data); | |
356 | ||
357 | OnAllocate(); | |
358 | ||
359 | READDATA(elemThings); | |
360 | if (elementThings) { | |
361 | READDATA(elementThings->teleportBlinkTime); | |
362 | READDATA(elementThings->savePortBlinkTime); | |
363 | READDATA(elementThings->exitPortBlinkTime); | |
364 | READDATA(elementThings->passiveHasChanged); | |
365 | } | |
366 | ||
367 | ||
368 | } | |
369 | ||
370 | void CBackgroundElement::Read(FILE *f) | |
371 | { | |
372 | CElement::Read(f); | |
373 | ||
374 | OnAllocate(); | |
375 | }⏎ |
0 | #ifndef __AMP_ELEMENT__ | |
1 | #define __AMP_ELEMENT__ | |
2 | ||
3 | #include "Object.hpp" | |
4 | #include "File.hpp" | |
5 | #include "Pltform.hpp" | |
6 | ||
7 | // Added by Luke | |
8 | #define LOBYTE(x) ((unsigned char)((x) & 0xff)) | |
9 | #define HIBYTE(x) ((unsigned char)((unsigned short)(x) >> 8)) | |
10 | ||
11 | enum { | |
12 | kPlatformSwitchInactiveID = 200, | |
13 | kPlatformSwitchActiveID = 201, | |
14 | kLightSwitchInactiveID = 208, | |
15 | kLightSwitchActiveID = 209, | |
16 | kInfotextStateOne = 210, | |
17 | kInfotextStateTwo = 211, | |
18 | kSavePortStateOne = 202, | |
19 | kSavePortStateTwo = 203, | |
20 | kExitStateOne = 204, | |
21 | kExitStateTwo = 205, | |
22 | kTeleportStateOne = 206, | |
23 | kTeleportStateTwo = 207, | |
24 | kDriftLeftID = 4015, | |
25 | kDriftRightID = 4016 | |
26 | }; | |
27 | ||
28 | struct tElementThings { | |
29 | CShape *lightSwitch; | |
30 | CShape *lightSwitch2; | |
31 | CShape *platformSwitchActive; | |
32 | CShape *platformSwitchInactive; | |
33 | CPlatform *referencedPlatform; | |
34 | CShape *drift; | |
35 | ||
36 | CShape *teleporter; | |
37 | CShape *teleporter2; | |
38 | long teleportBlinkTime; | |
39 | CShape *savePort; | |
40 | CShape *savePort2; | |
41 | long savePortBlinkTime; | |
42 | CShape *exitPort; | |
43 | CShape *exitPort2; | |
44 | long exitPortBlinkTime; | |
45 | CShape *infoPort; | |
46 | CShape *infoPort2; | |
47 | long infoPortBlinkTime; | |
48 | ||
49 | short passiveHasChanged; | |
50 | }; | |
51 | ||
52 | class CPlayer; | |
53 | ||
54 | class CElement : public CObject { | |
55 | friend class CPlayer; | |
56 | protected: | |
57 | CShape *shape; | |
58 | CShape *shape2; | |
59 | short bitData; | |
60 | short lastState; | |
61 | short iconID; | |
62 | ||
63 | tElementThings *elementThings; | |
64 | ||
65 | public: | |
66 | short brightness; | |
67 | short brightness2; | |
68 | short key; | |
69 | short refNum; | |
70 | short data; | |
71 | ||
72 | CElement(short initx, short inity, short width, short height, tLevelElement *element); | |
73 | ~CElement(); | |
74 | ||
75 | void OnAllocate(); | |
76 | void LinkPlatforms(); | |
77 | ||
78 | virtual void PaintElement(short planeLeft, short planeTop, tRect *clipRect); | |
79 | void PaintElementThings(short planeLeft, short planeTop, tRect *clipRect); | |
80 | virtual short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
81 | ||
82 | short Action(); | |
83 | void PassiveAction(); | |
84 | void SwapLights(); | |
85 | void Teleport(double &xs, double &ys); | |
86 | short GetElementLiquid(); | |
87 | ||
88 | virtual short Write(FILE *f); | |
89 | virtual void Read(FILE *f); | |
90 | }; | |
91 | ||
92 | class CBackgroundElement : public CElement { | |
93 | public: | |
94 | CBackgroundElement(short initx, short inity, short width, short height, tLevelElement *element); | |
95 | ~CBackgroundElement(); | |
96 | ||
97 | void OnAllocate(); | |
98 | ||
99 | void PaintElement(short planeLeft, short planeTop, tRect *clipRect); | |
100 | ||
101 | void Read(FILE *f); | |
102 | }; | |
103 | ||
104 | #endif |
0 | #include "File.hpp" | |
1 | ||
2 | CFile::CFile() | |
3 | {} | |
4 | ||
5 | CFile::~CFile() | |
6 | {} | |
7 | ||
8 | boolVar CFile::OpenDataFile(char *name) | |
9 | { | |
10 | fileRef = fopen(name, "rb"); | |
11 | return fileRef != NULL; | |
12 | } | |
13 | ||
14 | ||
15 | void CFile::CloseDataFile() | |
16 | { | |
17 | fclose(fileRef); | |
18 | } | |
19 | ||
20 | void CFile::SetFilePos(long offset) | |
21 | { | |
22 | fseek(fileRef, offset, SEEK_SET); | |
23 | } | |
24 | ||
25 | long CFile::ReadData(void *data, long size) | |
26 | { | |
27 | return fread(data, size, 1, fileRef); | |
28 | }⏎ |
0 | #ifndef __AMP_FILES__ | |
1 | #define __AMP_FILES__ | |
2 | ||
3 | #include <stdio.h> | |
4 | #include "System.hpp" | |
5 | ||
6 | // Basic types for file input/output. Size of variable is very important | |
7 | typedef unsigned char Var1Byte; | |
8 | typedef short Var2Bytes; | |
9 | typedef long Var4Bytes ; | |
10 | typedef double Var8Bytes; | |
11 | ||
12 | /* Macros used to convert big endian to little endian and back. Data in the | |
13 | Amphetamine data files is stored in big endian (PowerPC) | |
14 | */ | |
15 | ||
16 | #define SWAP_SHORT(x) ((x << 8) | (((unsigned short)x) >> 8)) | |
17 | #define SWAP_LONG(x) ( \ | |
18 | (x << 24) | \ | |
19 | (((unsigned long)x) >> 24) | \ | |
20 | ((x & 0x0000FF00) << 8) | \ | |
21 | ((x & 0x00FF0000) >> 8) \ | |
22 | ) | |
23 | ||
24 | #define SWAP_PUT_SHORT(x) ((x) = (x << 8) | (((unsigned short)x) >> 8)) | |
25 | #define SWAP_PUT_LONG(x) ((x) = (x << 24) | (((unsigned long)x) >> 24) | \ | |
26 | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8)) | |
27 | ||
28 | #define TRANS_NUM(x) ( \ | |
29 | (sizeof(x) == sizeof(short)) ? SWAP_SHORT(x) : \ | |
30 | (sizeof(x) == sizeof(long)) ? SWAP_LONG(x) : (x)\ | |
31 | ) | |
32 | ||
33 | #ifndef __BIG_ENDIAN__ | |
34 | ||
35 | #define TRANS_PUT_NUM(x) ((sizeof(x) == sizeof(short)) ? SWAP_PUT_SHORT(x) : \ | |
36 | (sizeof(x) == sizeof(long)) ? SWAP_PUT_LONG(x) : (x)) | |
37 | #define TRANS_PUT_NUM2(x) x | |
38 | ||
39 | #else | |
40 | ||
41 | #define TRANS_PUT_NUM(x) x | |
42 | ||
43 | #define TRANS_PUT_NUM2(x) ((sizeof(x) == sizeof(short)) ? SWAP_PUT_SHORT(x) : \ | |
44 | (sizeof(x) == sizeof(long)) ? SWAP_PUT_LONG(x) : (x)) | |
45 | ||
46 | #endif | |
47 | ||
48 | ||
49 | class CFile { | |
50 | protected: | |
51 | FILE *fileRef; | |
52 | short levelNumber; | |
53 | ||
54 | boolVar OpenDataFile(char *name); | |
55 | void SetFilePos(long offset); | |
56 | long ReadData(void *buffer, long size); | |
57 | void CloseDataFile(); | |
58 | ||
59 | public: | |
60 | ||
61 | CFile(); | |
62 | ~CFile(); | |
63 | }; | |
64 | ||
65 | ||
66 | // Datastructure of level element | |
67 | struct tLevelElement { | |
68 | Var2Bytes kind; // kWall = 0, kBackground = 1 | |
69 | Var2Bytes iconID; | |
70 | Var2Bytes light; | |
71 | Var2Bytes refNum; // LoByte: Platform switch, HiByte: Light Index | |
72 | Var2Bytes bitData; | |
73 | Var2Bytes monsterRef; | |
74 | Var2Bytes itemRef; | |
75 | }; | |
76 | ||
77 | #endif |
0 | ||
1 | /* | |
2 | * xgifload.c - based strongly on... | |
3 | * | |
4 | * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. | |
5 | * | |
6 | * Copyright (c) 1988, 1989 by Patrick J. Naughton | |
7 | * | |
8 | * Author: Patrick J. Naughton | |
9 | * naughton@wind.sun.com | |
10 | * | |
11 | * Permission to use, copy, modify, and distribute this software and its | |
12 | * documentation for any purpose and without fee is hereby granted, | |
13 | * provided that the above copyright notice appear in all copies and that | |
14 | * both that copyright notice and this permission notice appear in | |
15 | * supporting documentation. | |
16 | * | |
17 | * This file is provided AS IS with no warranties of any kind. The author | |
18 | * shall have no liability with respect to the infringement of copyrights, | |
19 | * trade secrets or any patents by this file or any part thereof. In no | |
20 | * event will the author be liable for any lost revenue or profits or | |
21 | * other special, indirect and consequential damages. | |
22 | * | |
23 | * | |
24 | */ | |
25 | ||
26 | #include <stdio.h> | |
27 | #include <stdlib.h> | |
28 | #include <string.h> | |
29 | ||
30 | //#include "wt.h" | |
31 | //#include "gApplication->system->Error.h" | |
32 | //#include "wtmem.h" | |
33 | #include "Graphfil.hpp" | |
34 | #include "Appl.hpp" | |
35 | ||
36 | extern CApplication *gApplication; | |
37 | extern CSystem *gSystem; | |
38 | ||
39 | ||
40 | #define mfputc fputc | |
41 | #define mfgetc fgetc | |
42 | #define mfopen fopen | |
43 | #define mfclose fclose | |
44 | #define mfread fread | |
45 | #define mfseek fseek | |
46 | #define mftell ftell | |
47 | #define mrewind rewind | |
48 | #define mfprintf fprintf | |
49 | ||
50 | /* malloc or die . . . */ | |
51 | void *wtmalloc(size_t size) | |
52 | { | |
53 | void *news; | |
54 | ||
55 | if ((news = malloc(size)) == NULL) | |
56 | gSystem->Error("could not allocate %x bytes", size); | |
57 | ||
58 | return news; | |
59 | } | |
60 | ||
61 | ||
62 | /* realloc or die . . . */ | |
63 | void *wtrealloc(void *v, size_t size) | |
64 | { | |
65 | void *news; | |
66 | ||
67 | if ((news = realloc(v, size)) == NULL) | |
68 | gSystem->Error("could not reallocate %x bytes", size); | |
69 | ||
70 | return news; | |
71 | } | |
72 | ||
73 | ||
74 | void wtfree(void *v) | |
75 | { | |
76 | if (v == NULL) | |
77 | gSystem->Error("wtfree(NULL)", 0); | |
78 | else | |
79 | free(v); | |
80 | } | |
81 | ||
82 | ||
83 | ||
84 | typedef int gBOOLean; | |
85 | typedef unsigned char byte; | |
86 | ||
87 | #define NEXTBYTE (*ptr++) | |
88 | #define IMAGESEP 0x2c | |
89 | #define GRAPHIC_EXT 0xf9 | |
90 | #define PLAINTEXT_EXT 0x01 | |
91 | #define APPLICATION_EXT 0xff | |
92 | #define COMMENT_EXT 0xfe | |
93 | #define START_EXTENSION 0x21 | |
94 | #define INTERLACEMASK 0x40 | |
95 | #define COLORMAPMASK 0x80 | |
96 | ||
97 | int BitOffset = 0, /* Bit Offset of next code */ | |
98 | XC = 0, YC = 0, /* Output X and Y coords of current pixel */ | |
99 | Pass = 0, /* Used by output routine if interlaced pic */ | |
100 | OutCount = 0, /* Decompressor output 'stack count' */ | |
101 | RWidth, RHeight, /* screen dimensions */ | |
102 | Width, Height, /* image dimensions */ | |
103 | LeftOfs, TopOfs, /* image offset */ | |
104 | BitsPerPixel, /* Bits per pixel, read from GIF header */ | |
105 | BytesPerScanline, /* bytes per scanline in output raster */ | |
106 | ColorMapSize, /* number of colors */ | |
107 | Background, /* background color */ | |
108 | CodeSize, /* Code size, read from GIF header */ | |
109 | InitCodeSize, /* Starting code size, used during Clear */ | |
110 | Code, /* Value returned by ReadCode */ | |
111 | MaxCode, /* limiting value for current code size */ | |
112 | ClearCode, /* GIF clear code */ | |
113 | EOFCode, /* GIF end-of-information code */ | |
114 | CurCode, OldCode, InCode, /* Decompressor variables */ | |
115 | FirstFree, /* First free code, generated per GIF spec */ | |
116 | FreeCode, /* Decompressor, next free slot in hash table*/ | |
117 | FinChar, /* Decompressor variable */ | |
118 | BitMask, /* AND mask for data size */ | |
119 | ReadMask; /* Code AND mask for current code size */ | |
120 | ||
121 | gBOOLean Interlace, HasColormap; | |
122 | gBOOLean Verbose = 0; | |
123 | ||
124 | byte *Image; /* The result array */ | |
125 | byte *RawGIF; /* The heap array to hold it, raw */ | |
126 | byte *Raster; /* The raster data stream, unblocked */ | |
127 | ||
128 | /* The hash table used by the decompressor */ | |
129 | short Prefix[4096]; | |
130 | short Suffix[4096]; | |
131 | ||
132 | /* An output array used by the decompressor */ | |
133 | int OutCode[1025]; | |
134 | ||
135 | /* The color map, read from the GIF header */ | |
136 | byte Red[256], Green[256], Blue[256], used[256]; | |
137 | int numused; | |
138 | ||
139 | char *id87 = "GIF87a"; | |
140 | char *id89 = "GIF89a"; | |
141 | ||
142 | int ReadCode( void ); | |
143 | int log2( int ); | |
144 | void AddToPixel( byte ); | |
145 | ||
146 | ||
147 | Graphic_file *LoadGIF(FILE *fp, char *fname ) | |
148 | { | |
149 | Graphic_file *gfile; | |
150 | int filesize, numcols; | |
151 | register unsigned char ch, ch1; | |
152 | register byte *ptr, *ptr1; | |
153 | register int i; | |
154 | short transparency = -1; | |
155 | ||
156 | BitOffset = 0; | |
157 | XC = YC = 0; | |
158 | Pass = 0; | |
159 | OutCount = 0; | |
160 | ||
161 | /* find the size of the file */ | |
162 | mfseek(fp, 0L, 2); | |
163 | filesize = mftell(fp); | |
164 | mfseek(fp, 0L, 0); | |
165 | ||
166 | if (!(ptr = RawGIF = (byte *) malloc(filesize))) | |
167 | gSystem->Error("not enough memory to read gif file",0); | |
168 | ||
169 | if (!(Raster = (byte *) malloc(filesize))) { | |
170 | free( ptr ); | |
171 | gSystem->Error("not enough memory to read gif file",0); | |
172 | } | |
173 | ||
174 | if (mfread(ptr, filesize, 1, fp) != 1) | |
175 | gSystem->Error("GIF data read failed",0); | |
176 | ||
177 | if (strncmp((char *) ptr, id87, 6)) | |
178 | if (strncmp((char *) ptr, id89, 6)) | |
179 | gSystem->Error("not a GIF file",0); | |
180 | ||
181 | ptr += 6; | |
182 | ||
183 | /* Get variables from the GIF screen descriptor */ | |
184 | ||
185 | ch = NEXTBYTE; | |
186 | RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */ | |
187 | ch = NEXTBYTE; | |
188 | RHeight = ch + 0x100 * NEXTBYTE; | |
189 | ||
190 | if (Verbose) | |
191 | mfprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight); | |
192 | ||
193 | ch = NEXTBYTE; | |
194 | HasColormap = ((ch & COLORMAPMASK) ? 1 : 0); | |
195 | ||
196 | BitsPerPixel = (ch & 7) + 1; | |
197 | numcols = ColorMapSize = 1 << BitsPerPixel; | |
198 | BitMask = ColorMapSize - 1; | |
199 | ||
200 | Background = NEXTBYTE; /* background color... not used. */ | |
201 | ||
202 | if (NEXTBYTE) /* supposed to be NULL */ | |
203 | gSystem->Error("corrupt GIF file (bad screen descriptor)",0); | |
204 | ||
205 | /* Read in global colormap. */ | |
206 | ||
207 | if (HasColormap) { | |
208 | if (Verbose) | |
209 | mfprintf(stderr, "%s is %dx%d, %d bits per pixel, (%d colors).\n", | |
210 | fname, RWidth,RHeight,BitsPerPixel, ColorMapSize); | |
211 | ||
212 | for (i = 0; i < ColorMapSize; i++) { | |
213 | Red[i] = NEXTBYTE; | |
214 | Green[i] = NEXTBYTE; | |
215 | Blue[i] = NEXTBYTE; | |
216 | used[i] = 0; | |
217 | } | |
218 | ||
219 | numused = 0; | |
220 | } /* else no colormap in GIF file */ | |
221 | ||
222 | /* look for image separator */ | |
223 | ||
224 | for (ch = NEXTBYTE ; ch != IMAGESEP ; ch = NEXTBYTE) { | |
225 | i = ch; | |
226 | mfprintf(stderr, "EXTENSION CHARACTER: %x\n", i); | |
227 | if (ch != START_EXTENSION) | |
228 | gSystem->Error("corrupt GIF89a file",0); | |
229 | ||
230 | /* handle image extensions */ | |
231 | switch (ch = NEXTBYTE) { | |
232 | case GRAPHIC_EXT: | |
233 | ch = NEXTBYTE; | |
234 | if (ptr[0] & 0x1) { | |
235 | transparency = ptr[3]; /* transparent color index */ | |
236 | mfprintf(stderr, "transparency index: %i\n", transparency); | |
237 | } | |
238 | ptr += ch; | |
239 | break; | |
240 | case PLAINTEXT_EXT: | |
241 | break; | |
242 | case APPLICATION_EXT: | |
243 | break; | |
244 | case COMMENT_EXT: | |
245 | break; | |
246 | default: | |
247 | gSystem->Error("invalid GIF89 extension",0); | |
248 | } | |
249 | ||
250 | while ((ch = NEXTBYTE)) | |
251 | ptr += ch; | |
252 | } | |
253 | ||
254 | /* Now read in values from the image descriptor */ | |
255 | ||
256 | ch = NEXTBYTE; | |
257 | LeftOfs = ch + 0x100 * NEXTBYTE; | |
258 | ch = NEXTBYTE; | |
259 | TopOfs = ch + 0x100 * NEXTBYTE; | |
260 | ch = NEXTBYTE; | |
261 | Width = ch + 0x100 * NEXTBYTE; | |
262 | ch = NEXTBYTE; | |
263 | Height = ch + 0x100 * NEXTBYTE; | |
264 | Interlace = ((NEXTBYTE & INTERLACEMASK) ? 1 : 0); | |
265 | ||
266 | if (Verbose) | |
267 | mfprintf(stderr, "Reading a %d by %d %sinterlaced image...", | |
268 | Width, Height, (Interlace) ? "" : "non-"); | |
269 | ||
270 | gfile = new_graphic_file(); | |
271 | gfile->palette = (RGBcolor *)wtmalloc(sizeof(RGBcolor) * ColorMapSize); | |
272 | for (i = 0; i < ColorMapSize; i++) { | |
273 | gfile->palette[i].red = Red[i]; | |
274 | gfile->palette[i].green = Green[i]; | |
275 | gfile->palette[i].blue = Blue[i]; | |
276 | } | |
277 | gfile->bitmap = (unsigned char *)wtmalloc(Width * Height); | |
278 | gfile->type = gfPaletted; | |
279 | gfile->width = Width; | |
280 | gfile->height = Height; | |
281 | gfile->transparent_entry = transparency; | |
282 | ||
283 | /* Note that I ignore the possible existence of a local color map. | |
284 | * I'm told there aren't many files around that use them, and the spec | |
285 | * says it's defined for future use. This could lead to an gApplication->system->Error | |
286 | * reading some files. | |
287 | */ | |
288 | ||
289 | /* Start reading the raster data. First we get the intial code size | |
290 | * and compute decompressor constant values, based on this code size. | |
291 | */ | |
292 | ||
293 | CodeSize = NEXTBYTE; | |
294 | ClearCode = (1 << CodeSize); | |
295 | EOFCode = ClearCode + 1; | |
296 | FreeCode = FirstFree = ClearCode + 2; | |
297 | ||
298 | /* The GIF spec has it that the code size is the code size used to | |
299 | * compute the above values is the code size given in the file, but the | |
300 | * code size used in compression/decompression is the code size given in | |
301 | * the file plus one. (thus the ++). | |
302 | */ | |
303 | ||
304 | CodeSize++; | |
305 | InitCodeSize = CodeSize; | |
306 | MaxCode = (1 << CodeSize); | |
307 | ReadMask = MaxCode - 1; | |
308 | ||
309 | /* Read the raster data. Here we just transpose it from the GIF array | |
310 | * to the Raster array, turning it from a series of blocks into one long | |
311 | * data stream, which makes life much easier for ReadCode(). | |
312 | */ | |
313 | ||
314 | ptr1 = Raster; | |
315 | do { | |
316 | ch = ch1 = NEXTBYTE; | |
317 | while (ch--) *ptr1++ = NEXTBYTE; | |
318 | if ((ptr1 - Raster) > filesize) | |
319 | gSystem->Error("corrupt GIF file (unblock)",0); | |
320 | } while(ch1); | |
321 | ||
322 | free(RawGIF); /* We're done with the raw data now... */ | |
323 | ||
324 | if (Verbose) { | |
325 | mfprintf(stderr, "done.\n"); | |
326 | mfprintf(stderr, "Decompressing..."); | |
327 | } | |
328 | ||
329 | Image = gfile->bitmap; | |
330 | BytesPerScanline = Width; | |
331 | ||
332 | ||
333 | /* Decompress the file, continuing until you see the GIF EOF code. | |
334 | * One obvious enhancement is to add checking for corrupt files here. | |
335 | */ | |
336 | ||
337 | Code = ReadCode(); | |
338 | while (Code != EOFCode) { | |
339 | ||
340 | /* Clear code sets everything back to its initial value, then reads the | |
341 | * immediately subsequent code as uncompressed data. | |
342 | */ | |
343 | ||
344 | if (Code == ClearCode) { | |
345 | CodeSize = InitCodeSize; | |
346 | MaxCode = (1 << CodeSize); | |
347 | ReadMask = MaxCode - 1; | |
348 | FreeCode = FirstFree; | |
349 | CurCode = OldCode = Code = ReadCode(); | |
350 | FinChar = CurCode & BitMask; | |
351 | AddToPixel(FinChar); | |
352 | } | |
353 | else { | |
354 | ||
355 | /* If not a clear code, then must be data: save same as CurCode and InCode */ | |
356 | ||
357 | CurCode = InCode = Code; | |
358 | ||
359 | /* If greater or equal to FreeCode, not in the hash table yet; | |
360 | * repeat the last character decoded | |
361 | */ | |
362 | ||
363 | if (CurCode >= FreeCode) { | |
364 | CurCode = OldCode; | |
365 | OutCode[OutCount++] = FinChar; | |
366 | } | |
367 | ||
368 | /* Unless this code is raw data, pursue the chain pointed to by CurCode | |
369 | * through the hash table to its end; each code in the chain puts its | |
370 | * associated output code on the output queue. | |
371 | */ | |
372 | ||
373 | while (CurCode > BitMask) { | |
374 | if (OutCount > 1024) { | |
375 | gSystem->Error("Corrupt GIF file (OutCount)!", 0); | |
376 | // mfprintf(stderr,"\nCorrupt GIF file (OutCount)!\n"); | |
377 | // _exit(-1); /* calling 'exit(-1)' dumps core, so I don't */ | |
378 | } | |
379 | OutCode[OutCount++] = Suffix[CurCode]; | |
380 | CurCode = Prefix[CurCode]; | |
381 | } | |
382 | ||
383 | /* The last code in the chain is treated as raw data. */ | |
384 | ||
385 | FinChar = CurCode & BitMask; | |
386 | OutCode[OutCount++] = FinChar; | |
387 | ||
388 | /* Now we put the data out to the Output routine. | |
389 | * It's been stacked LIFO, so deal with it that way... | |
390 | */ | |
391 | ||
392 | for (i = OutCount - 1; i >= 0; i--) | |
393 | AddToPixel(OutCode[i]); | |
394 | OutCount = 0; | |
395 | ||
396 | /* Build the hash table on-the-fly. No table is stored in the file. */ | |
397 | ||
398 | Prefix[FreeCode] = OldCode; | |
399 | Suffix[FreeCode] = FinChar; | |
400 | OldCode = InCode; | |
401 | ||
402 | /* Point to the next slot in the table. If we exceed the current | |
403 | * MaxCode value, increment the code size unless it's already 12. If it | |
404 | * is, do nothing: the next code decompressed better be CLEAR | |
405 | */ | |
406 | ||
407 | FreeCode++; | |
408 | if (FreeCode >= MaxCode) { | |
409 | if (CodeSize < 12) { | |
410 | CodeSize++; | |
411 | MaxCode *= 2; | |
412 | ReadMask = (1 << CodeSize) - 1; | |
413 | } | |
414 | } | |
415 | } | |
416 | Code = ReadCode(); | |
417 | } | |
418 | ||
419 | free(Raster); | |
420 | ||
421 | if (Verbose) | |
422 | mfprintf(stderr, "done.\n"); | |
423 | //else | |
424 | //mfprintf(stderr,"(of which %d are used)\n",numused); | |
425 | ||
426 | ||
427 | return gfile; | |
428 | } | |
429 | ||
430 | ||
431 | /* Fetch the next code from the raster data stream. The codes can be | |
432 | * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to | |
433 | * maintain our location in the Raster array as a BIT Offset. We compute | |
434 | * the byte Offset into the raster array by dividing this by 8, pick up | |
435 | * three bytes, compute the bit Offset into our 24-bit chunk, shift to | |
436 | * bring the desired code to the bottom, then mask it off and return it. | |
437 | */ | |
438 | int | |
439 | ReadCode( void ) | |
440 | { | |
441 | int RawCode, ByteOffset; | |
442 | ||
443 | ByteOffset = BitOffset / 8; | |
444 | RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); | |
445 | ||
446 | if (CodeSize >= 8) | |
447 | RawCode += (0x10000 * Raster[ByteOffset + 2]); | |
448 | ||
449 | RawCode >>= (BitOffset % 8); | |
450 | BitOffset += CodeSize; | |
451 | ||
452 | return(RawCode & ReadMask); | |
453 | } | |
454 | ||
455 | void | |
456 | AddToPixel(byte Index) | |
457 | { | |
458 | if (YC<Height) | |
459 | *(Image + YC * BytesPerScanline + XC) = Index; | |
460 | ||
461 | if (!used[Index]) { used[Index]=1; numused++; } | |
462 | ||
463 | /* Update the X-coordinate, and if it overflows, update the Y-coordinate */ | |
464 | ||
465 | if (++XC == Width) { | |
466 | ||
467 | /* If a non-interlaced picture, just increment YC to the next scan line. | |
468 | * If it's interlaced, deal with the interlace as described in the GIF | |
469 | * spec. Put the decoded scan line out to the screen if we haven't gone | |
470 | * past the bottom of it | |
471 | */ | |
472 | ||
473 | XC = 0; | |
474 | if (!Interlace) YC++; | |
475 | else { | |
476 | switch (Pass) { | |
477 | case 0: | |
478 | YC += 8; | |
479 | if (YC >= Height) { | |
480 | Pass++; | |
481 | YC = 4; | |
482 | } | |
483 | break; | |
484 | case 1: | |
485 | YC += 8; | |
486 | if (YC >= Height) { | |
487 | Pass++; | |
488 | YC = 2; | |
489 | } | |
490 | break; | |
491 | case 2: | |
492 | YC += 4; | |
493 | if (YC >= Height) { | |
494 | Pass++; | |
495 | YC = 1; | |
496 | } | |
497 | break; | |
498 | case 3: | |
499 | YC += 2; | |
500 | break; | |
501 | default: | |
502 | break; | |
503 | } | |
504 | } | |
505 | } | |
506 | } | |
507 |
0 | ||
1 | /* | |
2 | ** MacWT -- a 3d game engine for the Macintosh | |
3 | ** © 1995, Bill Hayden and Nikol Software | |
4 | ** | |
5 | ** On the Internet: | |
6 | ** bmoc1@aol.com (my personal address) | |
7 | ** nikolsw@grove.ufl.edu (my school address) | |
8 | ** MacWT anonymous FTP site: ftp.circa.ufl.edu/pub/software/ufmug/mirrors/LocalSW/Hayden/ | |
9 | ** http://grove.ufl.edu:80/~nikolsw (my WWW page, containing MacWT info) | |
10 | ** | |
11 | ** based on wt, by Chris Laurel (claurel@mr.net) | |
12 | ** | |
13 | ** This program is distributed in the hope that it will be useful, | |
14 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
16 | */ | |
17 | ||
18 | ||
19 | ||
20 | #include <stdio.h> | |
21 | #include <string.h> | |
22 | //#include "wt.h" | |
23 | //#include "gApplication->system->Error.h" | |
24 | //#include "wtmem.h" | |
25 | //#include "color.h" | |
26 | #include "Graphfil.hpp" | |
27 | #include "Appl.hpp" | |
28 | ||
29 | extern CApplication *gApplication; | |
30 | extern CSystem *gSystem; | |
31 | ||
32 | #define mfputc fputc | |
33 | #define mfgetc fgetc | |
34 | #define mfopen fopen | |
35 | #define mfclose fclose | |
36 | #define mfread fread | |
37 | #define mfseek fseek | |
38 | #define mftell ftell | |
39 | #define mrewind rewind | |
40 | #define mfprintf fprintf | |
41 | ||
42 | /* MAGIC_LENGTH must be the length of the longest MAGIC string. */ | |
43 | #define MAGIC_LENGTH 5 | |
44 | #define GIF_MAGIC "GIF87" | |
45 | #define GIF89_MAGIC "GIF89" | |
46 | ||
47 | ||
48 | extern Graphic_file *LoadGIF(FILE *fp, char *filename); | |
49 | ||
50 | static Graphic_file_format check_format(FILE *fp, char *filename); | |
51 | ||
52 | ||
53 | Graphic_file *new_graphic_file() | |
54 | { | |
55 | Graphic_file *gf = (Graphic_file *)wtmalloc(sizeof(Graphic_file)); | |
56 | ||
57 | gf->transparent_entry = -1; | |
58 | ||
59 | return gf; | |
60 | } | |
61 | ||
62 | ||
63 | void free_graphic_file(Graphic_file *gfile) | |
64 | { | |
65 | if (gfile != NULL) { | |
66 | if (gfile->palette != NULL) | |
67 | wtfree(gfile->palette); | |
68 | if (gfile->bitmap != NULL) | |
69 | wtfree(gfile->bitmap); | |
70 | } | |
71 | wtfree(gfile); | |
72 | } | |
73 | ||
74 | ||
75 | /* Return 0 if the pixel is transparent, 1 if it is opaque. In any | |
76 | ** case, stuff dest with the pixel RGB value. | |
77 | */ | |
78 | short graphic_file_pixel(Graphic_file *gfile, int x, int y, RGBcolor *rgb) | |
79 | { | |
80 | if (gfile->type == gfPaletted) | |
81 | { | |
82 | int index; | |
83 | ||
84 | index = gfile->bitmap[y * gfile->width + x]; | |
85 | if (index == gfile->transparent_entry) | |
86 | return 0; | |
87 | else | |
88 | { | |
89 | *rgb = gfile->palette[index]; | |
90 | return 1; | |
91 | } | |
92 | } | |
93 | else | |
94 | { | |
95 | unsigned char *pixel = gfile->bitmap + (y * gfile->width + x) * 3; | |
96 | ||
97 | rgb->red = *pixel++; | |
98 | rgb->green = *pixel++; | |
99 | rgb->blue = *pixel; | |
100 | ||
101 | /* For now, let pure cyan be the transparent color for 1 color images. */ | |
102 | if (rgb->red == 0 && rgb->green == 255 && rgb->blue == 255) | |
103 | return 0; | |
104 | else | |
105 | return 1; | |
106 | } | |
107 | } | |
108 | ||
109 | ||
110 | Graphic_file *read_graphic_file(char *filename) | |
111 | { | |
112 | FILE *fp; | |
113 | Graphic_file_format format; | |
114 | Graphic_file *gfile = 0L; | |
115 | ||
116 | ||
117 | if ((fp = mfopen(filename, "rb")) == NULL) | |
118 | gSystem->Error("Could not open texture", 0); | |
119 | ||
120 | format = check_format(fp, filename); | |
121 | mrewind(fp); | |
122 | ||
123 | switch (format) | |
124 | { | |
125 | case formatGIF89: | |
126 | case formatGIF87: | |
127 | gfile = LoadGIF(fp, filename); | |
128 | break; | |
129 | ||
130 | case formatUnknown: | |
131 | gSystem->Error("Unknown graphic file format.", 0); | |
132 | break; | |
133 | ||
134 | default: | |
135 | gSystem->Error("The graphic file reading code is really broken.", 0); | |
136 | break; | |
137 | } | |
138 | ||
139 | if (gfile == NULL) | |
140 | gSystem->Error("gApplication->system->Error reading texture", 0); | |
141 | ||
142 | mfclose(fp); | |
143 | ||
144 | return gfile; | |
145 | } | |
146 | ||
147 | ||
148 | static Graphic_file_format check_format(FILE *fp, char *filename) | |
149 | { | |
150 | char magic[MAGIC_LENGTH]; | |
151 | ||
152 | #if __MWERKS__ || __THINKC__ | |
153 | // to read PICT or PICTR files, which are further along on the | |
154 | // evolutionary chain than to need MagicCookies or the like. | |
155 | mfread(magic, 1, MAGIC_LENGTH, fp); | |
156 | #else | |
157 | if (mfread(magic, 1, MAGIC_LENGTH, fp) != MAGIC_LENGTH) | |
158 | gSystem->Error("gApplication->system->Error reading texture", 0); | |
159 | #endif | |
160 | ||
161 | if (strncmp(magic, GIF_MAGIC, sizeof(GIF_MAGIC) - 1) == 0) | |
162 | return formatGIF87; | |
163 | else if (strncmp(magic, GIF89_MAGIC, sizeof(GIF89_MAGIC) - 1) == 0) | |
164 | return formatGIF89; | |
165 | else | |
166 | return formatPICTR; | |
167 | ||
168 | // return formatUnknown; | |
169 | } |
0 | /* | |
1 | ** wt -- a 3d game engine | |
2 | ** | |
3 | ** Copyright (C) 1994 by Chris Laurel | |
4 | ** email: claurel@mr.net | |
5 | ** snail mail: Chris Laurel, 5700 W Lake St #208, St. Louis Park, MN 55416 | |
6 | ** | |
7 | ** This program is free software; you can redistribute it and/or modify | |
8 | ** it under the terms of the GNU General Public License as published by | |
9 | ** the Free Software Foundation; either version 2 of the License, or | |
10 | ** (at your option) any later version. | |
11 | ** | |
12 | ** This program is distributed in the hope that it will be useful, | |
13 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ** GNU General Public License for more details. | |
16 | ** | |
17 | ** You should have received a copy of the GNU General Public License | |
18 | ** along with this program; if not, write to the Free Software | |
19 | ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | #include "AmpHead.hpp" | |
22 | #include "System.hpp" | |
23 | ||
24 | #ifndef __GRAPHFIL__ | |
25 | #define __GRAPHFIL__ | |
26 | ||
27 | typedef enum { formatGIF87, formatGIF89, formatPPM, formatPICTR, formatUnknown } | |
28 | Graphic_file_format; | |
29 | ||
30 | typedef enum { gfTrueColor, gfPaletted } Graphic_file_type; | |
31 | ||
32 | typedef struct { | |
33 | Graphic_file_type type; | |
34 | int height, width; | |
35 | int palette_entries; | |
36 | long transparent_entry; | |
37 | RGBcolor *palette; | |
38 | unsigned char *bitmap; | |
39 | } Graphic_file; | |
40 | ||
41 | void *wtmalloc(size_t size); | |
42 | void *wtrealloc(void *v, size_t size); | |
43 | void wtfree(void *v); | |
44 | void FatalerFehler(char *errorStr, long error); | |
45 | ||
46 | ||
47 | extern Graphic_file *new_graphic_file(void); | |
48 | extern void free_graphic_file(Graphic_file *gfile); | |
49 | extern short graphic_file_pixel(Graphic_file *gfile, int x, int y, RGBcolor *rgb); | |
50 | extern Graphic_file *read_graphic_file(char *filename); | |
51 | ||
52 | Graphic_file *LoadPPM(FILE *fp, char *filename); | |
53 | Graphic_file *LoadGIF(FILE *fp, char *fname ); | |
54 | Graphic_file *LoadPICTR(FILE *fp, char *fname ); | |
55 | ||
56 | #endif⏎ |
0 | #include "Gui.hpp" | |
1 | #include "AmpHead.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | #include "ShapeLd.hpp" | |
4 | #include "Appl.hpp" | |
5 | #include "Clut.hpp" | |
6 | #include "SndSys.hpp" | |
7 | ||
8 | extern CSystem *gSystem; | |
9 | extern tConstValues *gConst; | |
10 | extern CShapeManager *gShapeManager; | |
11 | extern CLevel *gLevel; | |
12 | extern CClutManager *gClutManager; | |
13 | extern tConfigData *gConfigData; | |
14 | extern CSoundSystem *gSoundSystem; | |
15 | ||
16 | tGUIConstants *gGUIConst; | |
17 | ||
18 | const short kHealthCurveY[10] = {0, 48, -48, 15, -15, 25, -15, 0, 0, 0}; | |
19 | const short kHealthCurveX = 5; | |
20 | const double kOxygenCurveY = 25.0; | |
21 | const double kOxygenCurveX = 2.0; | |
22 | ||
23 | short kMunitionStatusColors[3] = {220, 100, 220}; | |
24 | ||
25 | const short kKeyHitDelay = 300; | |
26 | ||
27 | const short kTitleTabulator = -30; | |
28 | const short kNameTabulator1 = 30; | |
29 | const short kNameTabulator2 = 20; | |
30 | ||
31 | double XLineCut(double r0x, double r0y, double r1x, double r1y, double x); | |
32 | void SwapBlackWhite(Graphic_file *gf); | |
33 | ||
34 | CGUI::CGUI(CGraphicSurface *curMainScreen) | |
35 | { | |
36 | tRect position; | |
37 | ||
38 | LoadMessages(); | |
39 | ||
40 | guis = read_graphic_file(gSystem->QualifyDataDir(gConst->kFileGUIs)); // by LL | |
41 | if (!guis) gSystem->Error("Error while reading the file kFileGUIs", 0); | |
42 | SwapBlackWhite(guis); | |
43 | ||
44 | healthPanel = new CGraphicSurface(gGUIConst->kHealthPanelWidth, gGUIConst->kHealthPanelHeight); | |
45 | oxygenPanel = new CGraphicSurface(gGUIConst->kOxygenPanelWidth, gGUIConst->kOxygenPanelHeight); | |
46 | weaponPanel = new CGraphicSurface(gGUIConst->kWeaponPanelWidth, gGUIConst->kWeaponPanelHeight); | |
47 | backgroundPanel = new CGraphicSurface(kUserPlaneWidth, kGamePlaneHeight); | |
48 | if (!(healthPanel && oxygenPanel && weaponPanel && backgroundPanel)) gSystem->Error("Cannot allocate panels", 0); | |
49 | ||
50 | currentMainScreen = curMainScreen; | |
51 | currentMessage = 0L; | |
52 | msgDisplayTime = 0; | |
53 | ||
54 | position.left = kGUIsPositions[3][0]; | |
55 | position.top = kGUIsPositions[3][1]; | |
56 | position.right = kGUIsPositions[3][2]; | |
57 | position.bottom = kGUIsPositions[3][3]; | |
58 | backgroundPanel->InsertGraphic(0L, guis, &position); | |
59 | backgroundPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); | |
60 | backgroundPanel->FlipToScreen(kGamePlaneWidth, 0); | |
61 | ||
62 | position.left = kGUIsPositions[0][0]; | |
63 | position.top = kGUIsPositions[0][1]; | |
64 | position.right = kGUIsPositions[0][2]; | |
65 | position.bottom = kGUIsPositions[0][3]; | |
66 | healthPanel->InsertGraphic(0L, guis, &position); | |
67 | ||
68 | position.left = kGUIsPositions[1][0]; | |
69 | position.top = kGUIsPositions[1][1]; | |
70 | position.right = kGUIsPositions[1][2]; | |
71 | position.bottom = kGUIsPositions[1][3]; | |
72 | oxygenPanel->InsertGraphic(0L, guis, &position); | |
73 | ||
74 | for (short n = 0; n <= 7; n ++) { | |
75 | position.left = kGUIsPositions[2][0]; | |
76 | position.top = kGUIsPositions[2][1] + n * (kGUIsPositions[2][3]); | |
77 | position.right = kGUIsPositions[2][2]; | |
78 | position.bottom = kGUIsPositions[2][3] + n * (kGUIsPositions[2][3]); | |
79 | weaponPanel->InsertGraphic(0L, guis, &position); | |
80 | } | |
81 | ||
82 | position.left = kGUIsPositions[4][0]; | |
83 | position.top = kGUIsPositions[4][1]; | |
84 | position.right = kGUIsPositions[4][2]; | |
85 | position.bottom = kGUIsPositions[4][3]; | |
86 | curMainScreen->InsertGraphic(0L, guis, &position); | |
87 | ||
88 | position.left = kGUIsPositions[5][0]; | |
89 | position.top = kGUIsPositions[5][1]; | |
90 | position.right = kGUIsPositions[5][2]; | |
91 | position.bottom = kGUIsPositions[5][3]; | |
92 | curMainScreen->InsertGraphic(0L, guis, &position); | |
93 | ||
94 | lastHealthPanelRefresh = 0; | |
95 | healthCurveStart = 0; | |
96 | lastOxygenPanelRefresh = 0; | |
97 | oxygenCurveStart = 0; | |
98 | } | |
99 | ||
100 | CGUI::~CGUI() | |
101 | { | |
102 | free_graphic_file(guis); | |
103 | delete healthPanel; | |
104 | delete oxygenPanel; | |
105 | delete backgroundPanel; | |
106 | delete messages; | |
107 | } | |
108 | ||
109 | void CGUI::SetFocus(CPlayer *focus) | |
110 | { | |
111 | player = focus; | |
112 | } | |
113 | ||
114 | ||
115 | void CGUI::Update() | |
116 | { | |
117 | long time = gSystem->GetTicks(); | |
118 | if (player->typeID & kPlayer && lastHealthPanelRefresh < time) { | |
119 | DrawHealthPanel(); | |
120 | lastHealthPanelRefresh = time + gGUIConst->kHealthPanelRefreshRate; | |
121 | } | |
122 | if (player->typeID & kPlayer && lastOxygenPanelRefresh < time) { | |
123 | DrawOxygenPanel(); | |
124 | lastOxygenPanelRefresh = time + gGUIConst->kOxygenPanelRefreshRate; | |
125 | } | |
126 | } | |
127 | ||
128 | void CGUI::UpdateWeapon() | |
129 | { | |
130 | short drawStart = gGUIConst->kWeaponPanelHeight - player->weapons[player->currentWeapon]->munition * gGUIConst->kWeaponPanelHeight / player->weapons[player->currentWeapon]->info->munition; | |
131 | short drawEnd = gGUIConst->kWeaponPanelHeight; | |
132 | short color; | |
133 | ||
134 | weaponPanel->PaintGraphic(player->currentWeapon, 0, 0, kShapemodusNormal); | |
135 | ||
136 | for (short n = drawStart; n < drawEnd; n ++) { | |
137 | color = gClutManager->FindClosestColor(kMunitionStatusColors[0] - kMunitionStatusColors[0] * n / 100, | |
138 | kMunitionStatusColors[1] - kMunitionStatusColors[1] * n / 100, | |
139 | kMunitionStatusColors[2] - kMunitionStatusColors[2] * n / 100); | |
140 | ||
141 | weaponPanel->DrawAntialiasedLine(gGUIConst->kWeaponPanelWidth - gGUIConst->kWeaponStatusWidth, n, gGUIConst->kWeaponPanelWidth -1, n, (unsigned char)color, kShapemodusNormal); | |
142 | } | |
143 | weaponPanel->FlipToScreen(gGUIConst->kWeaponPanelPosX, gGUIConst->kWeaponPanelPosY); | |
144 | } | |
145 | ||
146 | #define ADDHEALTH(curvePoint) curvePoint == 9 ? 0 : curvePoint +1 | |
147 | #define SUBHEALTH(curvePoint) curvePoint == 0 ? 9 : curvePoint -1 | |
148 | ||
149 | // --------------------------------------------------- | |
150 | void CGUI::DrawHealthPanel() | |
151 | // Draws the health curve panel and blits it to the screen | |
152 | { | |
153 | double ptx, pty, cury1, cury2; | |
154 | short curvePoint = 0; | |
155 | double fak; | |
156 | ||
157 | healthCurveStart --; | |
158 | if (healthCurveStart < -gGUIConst->kHealthPanelWidth) healthCurveStart = 0; | |
159 | ptx = healthCurveStart; | |
160 | ||
161 | //healthPanel->PaintRect(0, 0, kHealthPanelWidth, kHealthPanelHeight, kBlackColor); | |
162 | healthPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); | |
163 | ||
164 | while (ptx < gGUIConst->kHealthPanelWidth) { | |
165 | fak = player->health <= 0 ? SHRT_MAX : (double)player->info->energy / (double)player->health; | |
166 | cury1 = kHealthCurveY[curvePoint] / fak; | |
167 | cury2 = kHealthCurveY[ADDHEALTH(curvePoint)] / fak; | |
168 | ||
169 | if (ptx <= 0 && ptx + kHealthCurveX > 0) { | |
170 | pty = XLineCut(ptx, cury1, ptx + kHealthCurveX, cury2, 0); | |
171 | healthPanel->DrawAntialiasedLine(0, pty + gGUIConst->kHealthPanelHeight / 2, | |
172 | ptx + kHealthCurveX, | |
173 | cury2 + gGUIConst->kHealthPanelHeight / 2, | |
174 | gConst->kHealthPanelColor, kShapemodusNormal); | |
175 | ||
176 | }else if (ptx < gGUIConst->kHealthPanelWidth && ptx + kHealthCurveX >= gGUIConst->kHealthPanelWidth) { | |
177 | pty = XLineCut(ptx, cury1, ptx + kHealthCurveX, cury2, gGUIConst->kHealthPanelWidth); | |
178 | healthPanel->DrawAntialiasedLine(ptx, cury1 + gGUIConst->kHealthPanelHeight / 2, | |
179 | gGUIConst->kHealthPanelWidth, pty + gGUIConst->kHealthPanelHeight / 2, | |
180 | gConst->kHealthPanelColor, kShapemodusNormal); | |
181 | ||
182 | }else if (ptx > 0 && ptx + kHealthCurveX < gGUIConst->kHealthPanelWidth) { | |
183 | healthPanel->DrawAntialiasedLine(ptx, cury1 + gGUIConst->kHealthPanelHeight / 2, | |
184 | ptx + kHealthCurveX, cury2 + gGUIConst->kHealthPanelHeight / 2, | |
185 | gConst->kHealthPanelColor, kShapemodusNormal); | |
186 | } | |
187 | curvePoint = ADDHEALTH(curvePoint); | |
188 | ptx += kHealthCurveX; | |
189 | } | |
190 | healthPanel->FlipToScreen(gGUIConst->kHealthPanelPosX, gGUIConst->kHealthPanelPosY); | |
191 | } | |
192 | ||
193 | ||
194 | void CGUI::DrawOxygenPanel() | |
195 | { | |
196 | double ptx, pty1, pty2; | |
197 | double oxygenFactor = (double)player->oxygen / (double)gConst->kInitialOxygen; | |
198 | ||
199 | if (oxygenFactor > 1.0) oxygenFactor = 1.0; | |
200 | ||
201 | //oxygenPanel->PaintRect(0, 0, kOxygenPanelWidth, kOxygenPanelHeight, kBlackColor); | |
202 | oxygenPanel->PaintGraphic(0, 0, 0, kShapemodusNormal); | |
203 | ||
204 | oxygenCurveStart += 10.0 / 180.0 * 3.141; | |
205 | ptx = oxygenCurveStart; | |
206 | ||
207 | pty1 = kOxygenCurveY * sin(oxygenCurveStart); | |
208 | for (ptx = 0; ptx < 100; ptx += kOxygenCurveX) { | |
209 | ||
210 | pty2 = kOxygenCurveY * oxygenFactor * sin(ptx / 180 * 3.141 * 5.0 + oxygenCurveStart) + | |
211 | kOxygenCurveY * oxygenFactor / 1.5 * cos(ptx / 180 * 3.141 * 15.0 + oxygenCurveStart * 3.0); | |
212 | oxygenPanel->DrawAntialiasedLine(ptx, pty1 + gGUIConst->kOxygenPanelHeight / 2, ptx + kOxygenCurveX, pty2 + gGUIConst->kOxygenPanelHeight / 2, gConst->kOxygenPanelColor, kShapemodusNormal); | |
213 | pty1 = pty2; | |
214 | } | |
215 | ||
216 | oxygenPanel->FlipToScreen(gGUIConst->kOxygenPanelPosX, gGUIConst->kOxygenPanelPosY); | |
217 | } | |
218 | ||
219 | ||
220 | ||
221 | /* XLineCut | |
222 | ||
223 | Hinein: r0x, r0y: Anfangskoordinaten einer Linie | |
224 | r1x, r1y: Endkoordinaten einer Linie | |
225 | x: X-Abst einer zur Y-Achse parallelen Gerade | |
226 | ||
227 | Hinaus: Y-Abst des Schnittpunktes der Linie mit der Geraden | |
228 | */ | |
229 | double XLineCut(double r0x, double r0y, double r1x, double r1y, double x) | |
230 | { | |
231 | return (r0y + ((x - r0x) * (r1y - r0y)) / (r1x - r0x)); | |
232 | } | |
233 | ||
234 | ||
235 | ||
236 | short CGUI::ProcessKeyStrokes() | |
237 | { | |
238 | //gSystem->ProcessEvents(); | |
239 | ||
240 | if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyUp) && currentNumOfItems) { | |
241 | lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; | |
242 | lastItem = currentItem; | |
243 | currentItem --; | |
244 | if (currentItem < 0) currentItem = currentNumOfItems; | |
245 | gSoundSystem->Play(gSoundSystem->selMenu, player->xm, player->ym); | |
246 | ||
247 | return kKeyUp; | |
248 | } | |
249 | ||
250 | if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyDown) && currentNumOfItems) { | |
251 | lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; | |
252 | lastItem = currentItem; | |
253 | currentItem ++; | |
254 | if (currentItem > currentNumOfItems) currentItem = 0; | |
255 | gSoundSystem->Play(gSoundSystem->selMenu, player->xm, player->ym); | |
256 | ||
257 | return kKeyDown; | |
258 | } | |
259 | ||
260 | if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyReturn) && currentNumOfItems) { | |
261 | lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; | |
262 | gSoundSystem->Play(gSoundSystem->openMenu, player->xm, player->ym); | |
263 | return kKeyReturn; | |
264 | } | |
265 | if (lastKeyHit < gSystem->GetTicks() && gSystem->KeyPressed(kKeyEscape)) { | |
266 | lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; | |
267 | gSoundSystem->Play(gSoundSystem->openMenu, player->xm, player->ym); | |
268 | return kKeyEscape; | |
269 | } | |
270 | return 0; | |
271 | } | |
272 | ||
273 | ||
274 | short CGUI::NewGamePageEvents() | |
275 | { | |
276 | switch (currentItem) { | |
277 | case 0: // New Game | |
278 | return kCmdNewGameLevel1; | |
279 | break; | |
280 | ||
281 | case 1: | |
282 | return kCmdNewGameLevel2; | |
283 | break; | |
284 | ||
285 | case 2: | |
286 | return kCmdNewGameLevel3; | |
287 | break; | |
288 | ||
289 | case 3: | |
290 | return kCmdNewGameLevel4; | |
291 | break; | |
292 | ||
293 | default: | |
294 | return kNoCmdEvent; | |
295 | break; | |
296 | } | |
297 | } | |
298 | ||
299 | short CGUI::QuitPageEvents() | |
300 | { | |
301 | switch (currentItem) { | |
302 | case 0: | |
303 | return kCmdQuit; | |
304 | break; | |
305 | case 1: | |
306 | OnOpenMainPage(); | |
307 | return kNoCmdEvent; | |
308 | default: | |
309 | return kNoCmdEvent; | |
310 | } | |
311 | } | |
312 | ||
313 | short CGUI::MainPageEvents() | |
314 | { | |
315 | switch (currentItem) { | |
316 | case 0: // New Game | |
317 | OnOpenNewGamePage(); | |
318 | return kNoCmdEvent; | |
319 | break; | |
320 | ||
321 | case 1: | |
322 | OnOpenLoadPage(kLoadGamePage); | |
323 | return kNoCmdEvent; | |
324 | break; | |
325 | ||
326 | case 2: | |
327 | OnOpenHelpPage(); | |
328 | return kNoCmdEvent; | |
329 | break; | |
330 | case 3: | |
331 | OnOpenCreditsPage(); | |
332 | return kNoCmdEvent; | |
333 | break; | |
334 | ||
335 | case 4: | |
336 | OnOpenQuitPage(); | |
337 | return kNoCmdEvent; | |
338 | break; | |
339 | ||
340 | default: | |
341 | return kNoCmdEvent; | |
342 | break; | |
343 | } | |
344 | } | |
345 | ||
346 | ||
347 | short CGUI::LoadGamePageEvents() | |
348 | { | |
349 | return (page == kLoadGamePage ? kLoadGameSlot0 + currentItem : kSaveGameSlot0 + currentItem); | |
350 | } | |
351 | ||
352 | ||
353 | short CGUI::RunUserInterface(short whichPage) | |
354 | { | |
355 | short command = kNoCmdEvent; | |
356 | ||
357 | if (lastKeyHit > gSystem->GetTicks()) return kCmdNoCommand; | |
358 | lastKeyHit = gSystem->GetTicks() + gGUIConst->kKeyHitDelay; | |
359 | ||
360 | gSoundSystem->Play(gSoundSystem->entrMenu, player->xm, player->ym); | |
361 | ||
362 | switch (whichPage) { | |
363 | case kMainPage: | |
364 | OnOpenMainPage(); | |
365 | break; | |
366 | case kNewGamePage: | |
367 | OnOpenNewGamePage(); | |
368 | break; | |
369 | case kLoadGamePage: | |
370 | case kSaveGamePage: | |
371 | OnOpenLoadPage(whichPage); | |
372 | break; | |
373 | case kHelpPage: | |
374 | OnOpenHelpPage(); | |
375 | break; | |
376 | case kCreditPage: | |
377 | OnOpenCreditsPage(); | |
378 | break; | |
379 | case kQuitPage: | |
380 | OnOpenQuitPage(); | |
381 | break; | |
382 | } | |
383 | ||
384 | while (command == kNoCmdEvent) { | |
385 | ||
386 | switch (ProcessKeyStrokes()) { | |
387 | case kKeyEscape: | |
388 | if (page != kMainPage) OnOpenMainPage(); else command = kCmdNoCommand; | |
389 | break; | |
390 | ||
391 | case kKeyReturn: | |
392 | switch (page) { | |
393 | case kMainPage: | |
394 | command = MainPageEvents(); | |
395 | break; | |
396 | case kNewGamePage: | |
397 | command = NewGamePageEvents(); | |
398 | break; | |
399 | case kLoadGamePage: | |
400 | case kSaveGamePage: | |
401 | command = LoadGamePageEvents(); | |
402 | break; | |
403 | case kQuitPage: | |
404 | command = QuitPageEvents(); | |
405 | break; | |
406 | } | |
407 | break; | |
408 | } | |
409 | ||
410 | ||
411 | SelectMenuItem(); | |
412 | currentMainScreen->FlipToScreen(0, 0); | |
413 | } | |
414 | ||
415 | return command; | |
416 | } | |
417 | void CGUI::OnOpenMainPage() | |
418 | { | |
419 | gLevel->PaintLevel(); | |
420 | ||
421 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
422 | ||
423 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY, gGUIConst->kUserMainPageTitle, kShapemodusLava); | |
424 | ||
425 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 1 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry1, kShapemodusNormal); | |
426 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry2, kShapemodusNormal); | |
427 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 3 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry3, kShapemodusNormal); | |
428 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 4 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry4, kShapemodusNormal); | |
429 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 5 * gGUIConst->kUserMenuEntryDY, gGUIConst->kUserMenuEntry5, kShapemodusNormal); | |
430 | ||
431 | currentItem = lastItem = 0; | |
432 | currentNumOfItems = 4; | |
433 | page = kMainPage; | |
434 | currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; | |
435 | currentEntryDY = gGUIConst->kUserMenuEntryDY; | |
436 | ||
437 | SelectMenuItem(); | |
438 | } | |
439 | ||
440 | void CGUI::OnOpenNewGamePage() | |
441 | { | |
442 | gLevel->PaintLevel(); | |
443 | ||
444 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
445 | ||
446 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY, gGUIConst->kNewGamePageTitle, kShapemodusLava); | |
447 | ||
448 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 1 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry1, kShapemodusNormal); | |
449 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry2, kShapemodusNormal); | |
450 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 3 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry3, kShapemodusNormal); | |
451 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 4 * gGUIConst->kUserMenuEntryDY, gGUIConst->kNewGameEntry4, kShapemodusNormal); | |
452 | ||
453 | currentItem = 1; | |
454 | lastItem = 0; | |
455 | currentNumOfItems = 3; | |
456 | page = kNewGamePage; | |
457 | currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; | |
458 | currentEntryDY = gGUIConst->kUserMenuEntryDY; | |
459 | ||
460 | SelectMenuItem(); | |
461 | } | |
462 | ||
463 | ||
464 | void CGUI::OnOpenLoadPage(short whichPage) | |
465 | { | |
466 | short n; | |
467 | ||
468 | gLevel->PaintLevel(); | |
469 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
470 | ||
471 | for (n = 0; n < kNumOfSaveGameSlots; n ++) { | |
472 | char *filename = gSystem->QualifyHomeDir(gGUIConst->kSavedGames[n]); | |
473 | gLevel->GetSavedGameTitle(filename, sgTitles[n]); // by LL | |
474 | delete [] filename; | |
475 | } | |
476 | ||
477 | if (whichPage == kSaveGamePage) | |
478 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kSavePageTitle, kShapemodusLava); | |
479 | else | |
480 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kLoadPageTitle, kShapemodusLava); | |
481 | ||
482 | for (n = 0; n < kNumOfSaveGameSlots; n ++) { | |
483 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + (n + 1) * gGUIConst->kUserMenuEntryDY, sgTitles[n], kShapemodusNormal); | |
484 | } | |
485 | currentItem = lastItem = 0; | |
486 | currentNumOfItems = 5; | |
487 | page = whichPage; | |
488 | currentItemStart = gGUIConst->kUserMenuEntryPosY + gGUIConst->kUserMenuEntryDY; | |
489 | currentEntryDY = gGUIConst->kUserMenuEntryDY; | |
490 | ||
491 | SelectMenuItem(); | |
492 | } | |
493 | ||
494 | void CGUI::OnOpenHelpPage() | |
495 | { | |
496 | gLevel->PaintLevel(); | |
497 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
498 | ||
499 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kUserMenuEntryDY, gGUIConst->kHelpPageTitle, kShapemodusLava); | |
500 | ||
501 | currentMainScreen->PaintGraphic(1, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); | |
502 | ||
503 | currentItem = lastItem = -1; | |
504 | currentNumOfItems = 0; | |
505 | currentItemStart = gGUIConst->kUserMenuPosY; | |
506 | currentEntryDY = gGUIConst->kHelpMenuEntryDY; | |
507 | ||
508 | page = kHelpPage; | |
509 | } | |
510 | ||
511 | void CGUI::OnOpenCreditsPage() | |
512 | { | |
513 | gLevel->PaintLevel(); | |
514 | ||
515 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
516 | ||
517 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsPageTitle, kShapemodusLava); | |
518 | ||
519 | currentMainScreen->PaintGraphic(0, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); | |
520 | ||
521 | currentItem = lastItem = 1; | |
522 | currentNumOfItems = 0; | |
523 | currentItemStart = gGUIConst->kUserMenuEntryPosY + 7 * gGUIConst->kCreditsEntryDY; | |
524 | currentEntryDY = gGUIConst->kCreditsEntryDY; | |
525 | page = kCreditPage; | |
526 | } | |
527 | ||
528 | void CGUI::OnOpenQuitPage() | |
529 | { | |
530 | gLevel->PaintLevel(); | |
531 | ||
532 | currentMainScreen->PaintRect(gGUIConst->kUserMenuPosX, gGUIConst->kUserMenuPosY, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuWidth, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuHeight, kBlackColor, kShapemodusTransparent2); | |
533 | ||
534 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX + kTitleTabulator, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 0 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsPageTitle, kShapemodusLava); | |
535 | ||
536 | currentMainScreen->PaintGraphic(0, gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 2 * gGUIConst->kCreditsEntryDY, kShapemodusTransparent2); | |
537 | ||
538 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 8 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsEntry4, kShapemodusNormal); | |
539 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + gGUIConst->kUserMenuEntryPosY + 9 * gGUIConst->kCreditsEntryDY, gGUIConst->kCreditsEntry5, kShapemodusNormal); | |
540 | ||
541 | currentItem = lastItem = 0; | |
542 | currentNumOfItems = 1; | |
543 | currentItemStart = gGUIConst->kUserMenuEntryPosY + 8 * gGUIConst->kCreditsEntryDY; | |
544 | currentEntryDY = gGUIConst->kCreditsEntryDY; | |
545 | page = kQuitPage; | |
546 | } | |
547 | ||
548 | void CGUI::SelectMenuItem() | |
549 | { | |
550 | char *curItem; | |
551 | ||
552 | curItem = ItemToItem(lastItem); | |
553 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + currentItemStart + lastItem * currentEntryDY, curItem, kShapemodusNormal); | |
554 | ||
555 | curItem = ItemToItem(currentItem); | |
556 | currentMainScreen->DrawString(gGUIConst->kUserMenuPosX + gGUIConst->kUserMenuEntryPosX, gGUIConst->kUserMenuPosY + currentItemStart + currentItem * currentEntryDY, curItem, kShapemodusRandom); | |
557 | } | |
558 | ||
559 | ||
560 | char *CGUI::ItemToItem(short item) | |
561 | { | |
562 | switch (page) { | |
563 | case kMainPage: | |
564 | switch (item) { | |
565 | case 0: return gGUIConst->kUserMenuEntry1; break; | |
566 | case 1: return gGUIConst->kUserMenuEntry2; break; | |
567 | case 2: return gGUIConst->kUserMenuEntry3; break; | |
568 | case 3: return gGUIConst->kUserMenuEntry4; break; | |
569 | case 4: return gGUIConst->kUserMenuEntry5; break; | |
570 | default: return gGUIConst->kUserMenuEntry1; break; | |
571 | } | |
572 | break; | |
573 | ||
574 | case kNewGamePage: | |
575 | switch (item) { | |
576 | case 0: return gGUIConst->kNewGameEntry1; break; | |
577 | case 1: return gGUIConst->kNewGameEntry2; break; | |
578 | case 2: return gGUIConst->kNewGameEntry3; break; | |
579 | case 3: return gGUIConst->kNewGameEntry4; break; | |
580 | default: return gGUIConst->kNewGameEntry1; break; | |
581 | } | |
582 | break; | |
583 | ||
584 | case kLoadGamePage: | |
585 | case kSaveGamePage: | |
586 | return sgTitles[item]; | |
587 | break; | |
588 | ||
589 | case kQuitPage: | |
590 | switch (item) { | |
591 | case 0: return gGUIConst->kCreditsEntry4; break; | |
592 | case 1: return gGUIConst->kCreditsEntry5; break; | |
593 | default: return gGUIConst->kCreditsEntry5; break; | |
594 | } | |
595 | break; | |
596 | ||
597 | default: | |
598 | return 0L; | |
599 | break; | |
600 | } | |
601 | } | |
602 | ||
603 | void CGUI::DisplayInfotext(short num) | |
604 | { | |
605 | currentMessage = messages->generalMessages[num]; | |
606 | msgDisplayTime = gSystem->GetTicks() + gGUIConst->kInfoTextTime; | |
607 | } | |
608 | ||
609 | ||
610 | void CGUI::OnPickUpSomething(short what) | |
611 | { | |
612 | switch (what) { | |
613 | case kItemPhiol: | |
614 | currentMessage = messages->msgPhiol; | |
615 | break; | |
616 | case kItemSorcery: | |
617 | currentMessage = messages->msgBM; | |
618 | break; | |
619 | case kItemBow: | |
620 | currentMessage = messages->msgBow; | |
621 | break; | |
622 | case kItemScie: | |
623 | currentMessage = messages->msgScie; | |
624 | break; | |
625 | case kItemHands: | |
626 | currentMessage = messages->msgHands; | |
627 | break; | |
628 | case kItemBomb: | |
629 | currentMessage = messages->msgBombs; | |
630 | break; | |
631 | case kItemStaff: | |
632 | currentMessage = messages->msgStaff; | |
633 | break; | |
634 | case kItemPhiolmun: | |
635 | currentMessage = messages->msgPhiolMun; | |
636 | break; | |
637 | case kItemSorcerymun: | |
638 | currentMessage = messages->msgBMMun; | |
639 | break; | |
640 | case kItemBowmun: | |
641 | currentMessage = messages->msgBowMun; | |
642 | break; | |
643 | case kItemHandsmun: | |
644 | currentMessage = messages->msgHandsMun; | |
645 | break; | |
646 | case kItemBombmun: | |
647 | currentMessage = messages->msgBombsMun; | |
648 | break; | |
649 | case kItemStaffmun: | |
650 | currentMessage = messages->msgStaffMun; | |
651 | break; | |
652 | case kItemOxygen: | |
653 | currentMessage = messages->msgOxygen; | |
654 | break; | |
655 | case kItemHelppacket: | |
656 | currentMessage = messages->msgHealth; | |
657 | break; | |
658 | default: | |
659 | currentMessage = 0L; | |
660 | break; | |
661 | } | |
662 | msgDisplayTime = gSystem->GetTicks() + gGUIConst->kInfoTextTime; | |
663 | } | |
664 | ||
665 | ||
666 | void CGUI::DisplayMessages() | |
667 | { | |
668 | if (msgDisplayTime > gSystem->GetTicks() && currentMessage) | |
669 | currentMainScreen->DrawString(gGUIConst->kInfoTextLeft, gGUIConst->kInfoTextTop, currentMessage, kShapemodusTransparent1); | |
670 | } | |
671 | ||
672 | ||
673 | void CGUI::ResetTicks(long ticks) | |
674 | { | |
675 | lastKeyHit = ticks; | |
676 | ||
677 | lastHealthPanelRefresh = 0; | |
678 | healthCurveStart = 0; | |
679 | lastOxygenPanelRefresh = 0; | |
680 | oxygenCurveStart = 0; | |
681 | msgDisplayTime = 0; | |
682 | } | |
683 | ||
684 | long GetLongConstant(FILE *f, char *constName); | |
685 | double GetDoubleConstant(FILE *f, char *constName); | |
686 | void GetStringConstant(FILE *f, char *constName, char *buffer); | |
687 | ||
688 | void CGUI::LoadMessages() | |
689 | { | |
690 | FILE *f = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL | |
691 | char msgString[6] = "msgxx"; | |
692 | short n; | |
693 | ||
694 | messages = new tMessages; | |
695 | ||
696 | GetStringConstant(f, "msgPickedUpHealth", messages->msgHealth); | |
697 | GetStringConstant(f, "msgPickedUpOxygen", messages->msgOxygen); | |
698 | ||
699 | GetStringConstant(f, "msgPickedUpPhiol", messages->msgPhiol); | |
700 | GetStringConstant(f, "msgPickedUpBM", messages->msgBM); | |
701 | GetStringConstant(f, "msgPickedUpBow", messages->msgBow); | |
702 | GetStringConstant(f, "msgPickedUpScie", messages->msgScie); | |
703 | GetStringConstant(f, "msgPickedUpHands", messages->msgHands); | |
704 | GetStringConstant(f, "msgPickedUpBombs", messages->msgBombs); | |
705 | GetStringConstant(f, "msgPickedUpStaff", messages->msgStaff); | |
706 | ||
707 | GetStringConstant(f, "msgPickedUpPhiolMun", messages->msgPhiolMun); | |
708 | GetStringConstant(f, "msgPickedUpBMMun", messages->msgBMMun); | |
709 | GetStringConstant(f, "msgPickedUpBowMun", messages->msgBowMun); | |
710 | GetStringConstant(f, "msgPickedUpHandMun", messages->msgHandsMun); | |
711 | GetStringConstant(f, "msgPickedUpBombMun", messages->msgBombsMun); | |
712 | GetStringConstant(f, "msgPickedUpStaffMun", messages->msgStaffMun); | |
713 | ||
714 | for (n = 0; n < kMaxInfotexts -1; n ++) { | |
715 | msgString[3] = (char)(n / 10) + '0'; | |
716 | msgString[4] = (char)(n % 10) + '0'; | |
717 | GetStringConstant(f, msgString, messages->generalMessages[n]); | |
718 | } | |
719 | ||
720 | fclose(f); | |
721 | } | |
722 | ||
723 | ||
724 | void LoadGUIParameters() | |
725 | { | |
726 | FILE *f = fopen(gSystem->QualifyDataDir(kParFileName), "r"); // by LL | |
727 | ||
728 | gGUIConst = new tGUIConstants; | |
729 | ||
730 | gGUIConst->kHealthPanelHeight = GetLongConstant(f, "kHealthPanelHeight"); | |
731 | gGUIConst->kHealthPanelPosX = GetLongConstant(f, "kHealthPanelPosX"); | |
732 | gGUIConst->kHealthPanelPosY = GetLongConstant(f, "kHealthPanelPosY"); | |
733 | gGUIConst->kHealthPanelRefreshRate = GetLongConstant(f, "kHealthPanelRefreshRate"); | |
734 | gGUIConst->kHealthPanelWidth = GetLongConstant(f, "kHealthPanelWidth"); | |
735 | gGUIConst->kOxygenPanelHeight = GetLongConstant(f, "kOxygenPanelHeight"); | |
736 | gGUIConst->kOxygenPanelPosX = GetLongConstant(f, "kOxygenPanelPosX"); | |
737 | gGUIConst->kOxygenPanelPosY = GetLongConstant(f, "kOxygenPanelPosY"); | |
738 | gGUIConst->kOxygenPanelRefreshRate = GetLongConstant(f, "kOxygenPanelRefreshRate"); | |
739 | gGUIConst->kOxygenPanelWidth = GetLongConstant(f, "kOxygenPanelWidth"); | |
740 | gGUIConst->kWeaponPanelHeight = GetLongConstant(f, "kWeaponPanelHeight"); | |
741 | gGUIConst->kWeaponPanelPosX = GetLongConstant(f, "kWeaponPanelPosX"); | |
742 | gGUIConst->kWeaponPanelPosY = GetLongConstant(f, "kWeaponPanelPosY"); | |
743 | gGUIConst->kWeaponPanelWidth = GetLongConstant(f, "kWeaponPanelWidth"); | |
744 | gGUIConst->kWeaponStatusWidth = GetLongConstant(f, "kWeaponStatusWidth"); | |
745 | ||
746 | gGUIConst->kUserMenuEntryDY = GetLongConstant(f, "kUserMenuEntryDY"); | |
747 | gGUIConst->kUserMenuEntryPosX = GetLongConstant(f, "kUserMenuEntryPosX"); | |
748 | gGUIConst->kUserMenuEntryPosY = GetLongConstant(f, "kUserMenuEntryPosY"); | |
749 | gGUIConst->kUserMenuHeight = GetLongConstant(f, "kUserMenuHeight"); | |
750 | gGUIConst->kUserMenuPosX = GetLongConstant(f, "kUserMenuPosX"); | |
751 | gGUIConst->kUserMenuPosY = GetLongConstant(f, "kUserMenuPosY"); | |
752 | gGUIConst->kUserMenuWidth = GetLongConstant(f, "kUserMenuWidth"); | |
753 | gGUIConst->kHelpMenuEntryDY = GetLongConstant(f, "kHelpMenuEntryDY"); | |
754 | ||
755 | gGUIConst->kInfoTextLeft = GetLongConstant(f, "kInfoTextLeft"); | |
756 | gGUIConst->kInfoTextTop = GetLongConstant(f, "kInfoTextTop"); | |
757 | gGUIConst->kInfoTextTime = GetLongConstant(f, "kInfoTextTime"); | |
758 | ||
759 | GetStringConstant(f, "kUserMainPageTitle", gGUIConst->kUserMainPageTitle); | |
760 | GetStringConstant(f, "kUserMenuEntry1", gGUIConst->kUserMenuEntry1); | |
761 | GetStringConstant(f, "kUserMenuEntry2", gGUIConst->kUserMenuEntry2); | |
762 | GetStringConstant(f, "kUserMenuEntry3", gGUIConst->kUserMenuEntry3); | |
763 | GetStringConstant(f, "kUserMenuEntry4", gGUIConst->kUserMenuEntry4); | |
764 | GetStringConstant(f, "kUserMenuEntry5", gGUIConst->kUserMenuEntry5); | |
765 | ||
766 | GetStringConstant(f, "kNewGamePageTitle", gGUIConst->kNewGamePageTitle); | |
767 | GetStringConstant(f, "kNewGameEntry1", gGUIConst->kNewGameEntry1); | |
768 | GetStringConstant(f, "kNewGameEntry2", gGUIConst->kNewGameEntry2); | |
769 | GetStringConstant(f, "kNewGameEntry3", gGUIConst->kNewGameEntry3); | |
770 | GetStringConstant(f, "kNewGameEntry4", gGUIConst->kNewGameEntry4); | |
771 | ||
772 | GetStringConstant(f, "kNoSavedGame", gGUIConst->kNoSavedGame); | |
773 | GetStringConstant(f, "kSavePageTitle", gGUIConst->kSavePageTitle); | |
774 | GetStringConstant(f, "kLoadPageTitle", gGUIConst->kLoadPageTitle); | |
775 | GetStringConstant(f, "kHelpPageTitle", gGUIConst->kHelpPageTitle); | |
776 | ||
777 | GetStringConstant(f, "kSavedGame0", gGUIConst->kSavedGames[0]); | |
778 | GetStringConstant(f, "kSavedGame1", gGUIConst->kSavedGames[1]); | |
779 | GetStringConstant(f, "kSavedGame2", gGUIConst->kSavedGames[2]); | |
780 | GetStringConstant(f, "kSavedGame3", gGUIConst->kSavedGames[3]); | |
781 | GetStringConstant(f, "kSavedGame4", gGUIConst->kSavedGames[4]); | |
782 | GetStringConstant(f, "kSavedGame5", gGUIConst->kSavedGames[5]); | |
783 | ||
784 | gGUIConst->kKeyHitDelay = GetLongConstant(f, "kKeyHitDelay"); | |
785 | ||
786 | gGUIConst->kCreditsEntryDY = GetLongConstant(f, "kCreditsEntryDY"); | |
787 | GetStringConstant(f, "kCreditsPageTitle", gGUIConst->kCreditsPageTitle); | |
788 | GetStringConstant(f, "kCreditsEntry1", gGUIConst->kCreditsEntry1); | |
789 | GetStringConstant(f, "kCreditsEntry2", gGUIConst->kCreditsEntry2); | |
790 | GetStringConstant(f, "kCreditsEntry3", gGUIConst->kCreditsEntry3); | |
791 | GetStringConstant(f, "kCreditsEntry4", gGUIConst->kCreditsEntry4); | |
792 | GetStringConstant(f, "kCreditsEntry5", gGUIConst->kCreditsEntry5); | |
793 | ||
794 | ||
795 | fclose(f); | |
796 | } | |
797 | ||
798 | ⏎ |
0 | #ifndef __AMP_GUI__ | |
1 | #define __AMP_GUI__ | |
2 | ||
3 | #include "System.hpp" | |
4 | #include "Player.hpp" | |
5 | #include "Surface.hpp" | |
6 | ||
7 | const short kMaxEntryLength = 20; | |
8 | const short kNoCmdEvent = -1; | |
9 | const short kNumOfSaveGameSlots = 6; | |
10 | const short kMaxInfotexts = 45; | |
11 | ||
12 | enum { | |
13 | kMainPage, | |
14 | kNewGamePage, | |
15 | kLoadGamePage, | |
16 | kSaveGamePage, | |
17 | kCreditPage, | |
18 | kHelpPage, | |
19 | kQuitPage | |
20 | }; | |
21 | ||
22 | const short kGUIsPositions[6][4] = { | |
23 | {120, 0, 220, 100}, // health | |
24 | {120, 100, 220, 200}, // oxygen | |
25 | {0, 0, 120, 100}, // weapons | |
26 | {120, 200, 280, 680}, // board | |
27 | {0, 801, 210, 944}, // about box | |
28 | {0, 943, 210, 1091} // key config | |
29 | }; | |
30 | ||
31 | typedef struct { | |
32 | short kHealthPanelWidth, | |
33 | kHealthPanelHeight, | |
34 | kHealthPanelPosX, | |
35 | kHealthPanelPosY, | |
36 | kHealthPanelRefreshRate, | |
37 | ||
38 | kOxygenPanelWidth, | |
39 | kOxygenPanelHeight, | |
40 | kOxygenPanelPosX, | |
41 | kOxygenPanelPosY, | |
42 | kOxygenPanelRefreshRate, | |
43 | ||
44 | kWeaponPanelWidth, | |
45 | kWeaponPanelHeight, | |
46 | kWeaponPanelPosX, | |
47 | kWeaponPanelPosY, | |
48 | kWeaponStatusWidth, | |
49 | ||
50 | kUserMenuPosX, | |
51 | kUserMenuPosY, | |
52 | kUserMenuWidth, | |
53 | kUserMenuHeight, | |
54 | kUserMenuEntryPosX, | |
55 | kUserMenuEntryPosY, | |
56 | kUserMenuEntryDY; | |
57 | ||
58 | short kInfoTextLeft; | |
59 | short kInfoTextTop; | |
60 | short kInfoTextTime; | |
61 | ||
62 | short kHelpMenuEntryDY; | |
63 | ||
64 | short kKeyHitDelay; | |
65 | ||
66 | char kUserMainPageTitle[kMaxEntryLength]; | |
67 | char kUserMenuEntry1[kMaxEntryLength]; | |
68 | char kUserMenuEntry2[kMaxEntryLength]; | |
69 | char kUserMenuEntry3[kMaxEntryLength]; | |
70 | char kUserMenuEntry4[kMaxEntryLength]; | |
71 | char kUserMenuEntry5[kMaxEntryLength]; | |
72 | ||
73 | char kNewGamePageTitle[kMaxEntryLength]; | |
74 | char kNewGameEntry1[kMaxEntryLength]; | |
75 | char kNewGameEntry2[kMaxEntryLength]; | |
76 | char kNewGameEntry3[kMaxEntryLength]; | |
77 | char kNewGameEntry4[kMaxEntryLength]; | |
78 | ||
79 | char kNoSavedGame[kMaxEntryLength]; | |
80 | char kSavePageTitle[kMaxEntryLength]; | |
81 | char kLoadPageTitle[kMaxEntryLength]; | |
82 | char kHelpPageTitle[kMaxEntryLength]; | |
83 | char kSavedGames[kNumOfSaveGameSlots][kMaxEntryLength]; | |
84 | ||
85 | short kCreditsEntryDY; | |
86 | char kCreditsPageTitle[kMaxEntryLength]; | |
87 | char kCreditsEntry1[kMaxEntryLength]; | |
88 | char kCreditsEntry2[kMaxEntryLength]; | |
89 | char kCreditsEntry3[kMaxEntryLength]; | |
90 | char kCreditsEntry4[kMaxEntryLength]; | |
91 | char kCreditsEntry5[kMaxEntryLength]; | |
92 | } tGUIConstants; | |
93 | ||
94 | ||
95 | const short kMessageLength = 30; | |
96 | ||
97 | typedef struct { | |
98 | char msgHealth[kMessageLength]; | |
99 | char msgOxygen[kMessageLength]; | |
100 | ||
101 | char msgPhiol[kMessageLength]; | |
102 | char msgBM[kMessageLength]; | |
103 | char msgBow[kMessageLength]; | |
104 | char msgScie[kMessageLength]; | |
105 | char msgHands[kMessageLength]; | |
106 | char msgBombs[kMessageLength]; | |
107 | char msgStaff[kMessageLength]; | |
108 | ||
109 | char msgPhiolMun[kMessageLength]; | |
110 | char msgBMMun[kMessageLength]; | |
111 | char msgBowMun[kMessageLength]; | |
112 | char msgHandsMun[kMessageLength]; | |
113 | char msgBombsMun[kMessageLength]; | |
114 | char msgStaffMun[kMessageLength]; | |
115 | ||
116 | char generalMessages[kMaxInfotexts][kMessageLength]; | |
117 | ||
118 | } tMessages; | |
119 | ||
120 | ||
121 | class CGUI { | |
122 | protected: | |
123 | Graphic_file *guis; | |
124 | CGraphicSurface *backgroundPanel; | |
125 | CGraphicSurface *healthPanel; | |
126 | CGraphicSurface *oxygenPanel; | |
127 | CGraphicSurface *weaponPanel; | |
128 | CPlayer *player; | |
129 | tMessages *messages; | |
130 | ||
131 | long lastKeyHit; | |
132 | ||
133 | long lastHealthPanelRefresh; | |
134 | short healthCurveStart; | |
135 | long lastOxygenPanelRefresh; | |
136 | double oxygenCurveStart; | |
137 | ||
138 | CGraphicSurface *currentMainScreen; | |
139 | short currentItem, lastItem; | |
140 | short currentNumOfItems; | |
141 | short currentItemStart; | |
142 | short currentEntryDY; | |
143 | short page; | |
144 | ||
145 | char sgTitles[kNumOfSaveGameSlots][30]; | |
146 | char *currentMessage; | |
147 | long msgDisplayTime; | |
148 | ||
149 | void DrawHealthPanel(); | |
150 | void DrawOxygenPanel(); | |
151 | ||
152 | void SelectMenuItem(); | |
153 | char *ItemToItem(short item); | |
154 | ||
155 | short ProcessKeyStrokes(); | |
156 | short MainPageEvents(); | |
157 | short NewGamePageEvents(); | |
158 | short LoadGamePageEvents(); | |
159 | short QuitPageEvents(); | |
160 | ||
161 | void OnOpenMainPage(); | |
162 | void OnOpenNewGamePage(); | |
163 | void OnOpenLoadPage(short whichPage); | |
164 | void OnOpenHelpPage(); | |
165 | void OnOpenCreditsPage(); | |
166 | void OnOpenQuitPage(); | |
167 | ||
168 | void LoadMessages(); | |
169 | ||
170 | public: | |
171 | CGUI(CGraphicSurface *curMainScreen); | |
172 | ~CGUI(); | |
173 | ||
174 | void SetFocus(CPlayer *focus); | |
175 | ||
176 | void Update(); | |
177 | void UpdateWeapon(); | |
178 | short RunUserInterface(short page); | |
179 | void ResetTicks(long ticks); | |
180 | void OnPickUpSomething(short what); | |
181 | void DisplayMessages(); | |
182 | void DisplayInfotext(short num); | |
183 | }; | |
184 | ||
185 | #endif⏎ |
0 | #include "Item.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "Clut.hpp" | |
3 | #include "SndSys.hpp" | |
4 | ||
5 | extern CApplication *gApplication; | |
6 | extern CShapeManager *gShapeManager; | |
7 | extern CLevel *gLevel; | |
8 | extern tConstValues *gConst; | |
9 | extern CClutManager *gClutManager; | |
10 | extern CSoundSystem *gSoundSystem; | |
11 | ||
12 | CItem::CItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : | |
13 | CThing(initx, inity, width, height, number) | |
14 | { | |
15 | typeID |= kItem; | |
16 | ||
17 | info = itemInfo; | |
18 | shape = gShapeManager->FindShape(itemInfo->iconID, 0); | |
19 | currentShape = shape; | |
20 | detonationStartTime = -1; | |
21 | isCorona = info->iconID >= kCoronaIDs[0] && info->iconID <= kCoronaIDs[kNumOfCoronas -1]; | |
22 | coronaFader = 0.0; | |
23 | deltaTime = 0; | |
24 | dx -= 1; | |
25 | xe -= 1; | |
26 | } | |
27 | ||
28 | CItem::~CItem() | |
29 | {} | |
30 | ||
31 | short CItem::Think() | |
32 | { | |
33 | CObject::Think(); | |
34 | ||
35 | if (detonationStartTime != -1) { | |
36 | long frame = (long)((double)(lastTime - detonationStartTime) * gConst->kDetonationFrameTime); | |
37 | ||
38 | if (frame > 4) | |
39 | return kDestroyMe; | |
40 | else | |
41 | currentShape = gShapeManager->FindShape(gConst->kItemExplosionStartShape + frame, 0); | |
42 | } | |
43 | return kNoEvent; | |
44 | } | |
45 | ||
46 | void CItem::Move() | |
47 | { | |
48 | CThing::Move(); | |
49 | environmentForceX = environmentForceY = 0; | |
50 | } | |
51 | ||
52 | void CItem::Render(short planeX, short planeY, tRect *clipRect) | |
53 | { | |
54 | CElement *element = gLevel->GetElement(xm, ym); | |
55 | ||
56 | if (!isCorona && currentShape) currentShape->RenderShape(xs - planeX, ys - planeY, clipRect, | |
57 | modus, element ? element->brightness : 0, gApplication->plane); | |
58 | else if (isCorona) | |
59 | gClutManager->PrepareCorona(xm, ym, gApplication->plane); | |
60 | } | |
61 | ||
62 | void CItem::PostRender(short planeX, short planeY, tRect *clipRect) | |
63 | { | |
64 | if (isCorona) { | |
65 | CElement *element = gLevel->GetElement(xm, ym); | |
66 | gClutManager->DrawCorona(xm, ym, info->iconID - kCoronaIDs[0], element->data ? element->data : 1, gApplication->plane, coronaFader, deltaTime); | |
67 | } | |
68 | } | |
69 | ||
70 | void CItem::OnDamage(short blessure) | |
71 | { | |
72 | if (blessure && info->flags & kItemExplodesMask && detonationStartTime == -1) { | |
73 | tThingList *currentEntry = gApplication->collisionThingList; | |
74 | ||
75 | detonationStartTime = lastTime; | |
76 | ||
77 | while (currentEntry) { | |
78 | if (currentEntry->thing != this) currentEntry->thing->TestForDamage(xs, ys, gConst->kItemExplosionRad, info->data); | |
79 | currentEntry = currentEntry->next; | |
80 | } | |
81 | } | |
82 | } | |
83 | ||
84 | CStaticItem::CStaticItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : | |
85 | CItem(initx, inity, width, height, number, itemInfo) | |
86 | { | |
87 | typeID |= kStaticItem; | |
88 | background = 0; | |
89 | weight = 32000; | |
90 | weightless = 1; | |
91 | LinkInLists(); | |
92 | } | |
93 | ||
94 | CStaticItem::~CStaticItem() | |
95 | { | |
96 | } | |
97 | ||
98 | void CStaticItem::LinkInLists() | |
99 | { | |
100 | gApplication->Enqueue(&gApplication->thingList, this); | |
101 | gApplication->Enqueue(&gApplication->collisionThingList, this); | |
102 | if (isCorona) { | |
103 | gApplication->Enqueue(&gApplication->preRenderQueue, this); | |
104 | gApplication->Enqueue(&gApplication->postRenderQueue, this); | |
105 | }else gApplication->Enqueue(&gApplication->renderQueue, this); | |
106 | } | |
107 | ||
108 | void CStaticItem::UnlinkInLists() | |
109 | { | |
110 | gApplication->Dequeue(&gApplication->thingList, this); | |
111 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
112 | if (isCorona) { | |
113 | gApplication->Dequeue(&gApplication->preRenderQueue, this); | |
114 | gApplication->Dequeue(&gApplication->postRenderQueue, this); | |
115 | }else gApplication->Dequeue(&gApplication->renderQueue, this); | |
116 | } | |
117 | ||
118 | short CStaticItem::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
119 | { | |
120 | short returnValue = CThing::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); | |
121 | if (returnValue && info->flags & kItemHurtMask) { | |
122 | ((CThing *)sender)->OnDamage(info->data); | |
123 | } | |
124 | ||
125 | return returnValue; | |
126 | } | |
127 | ||
128 | ||
129 | CBackgroundItem::CBackgroundItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : | |
130 | CItem(initx, inity, width, height, number, itemInfo) | |
131 | { | |
132 | typeID |= kBackgroundItem; | |
133 | weight = 0; // Background items are hanging in the air, they don't fall, so they have no weight | |
134 | background = 1; | |
135 | weightless = 1; | |
136 | ||
137 | LinkInLists(); | |
138 | } | |
139 | ||
140 | CBackgroundItem::~CBackgroundItem() | |
141 | { | |
142 | } | |
143 | ||
144 | void CBackgroundItem::LinkInLists() | |
145 | { | |
146 | gApplication->Enqueue(&gApplication->thingList, this); | |
147 | gApplication->Enqueue(&gApplication->preRenderQueue, this); | |
148 | if (isCorona) { | |
149 | gApplication->Enqueue(&gApplication->postRenderQueue, this); | |
150 | } | |
151 | } | |
152 | ||
153 | void CBackgroundItem::UnlinkInLists() | |
154 | { | |
155 | gApplication->Dequeue(&gApplication->thingList, this); | |
156 | gApplication->Dequeue(&gApplication->preRenderQueue, this); | |
157 | if (isCorona) { | |
158 | gApplication->Dequeue(&gApplication->postRenderQueue, this); | |
159 | } | |
160 | } | |
161 | ||
162 | CMovableItem::CMovableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo) : | |
163 | CItem(initx, inity, width, height, number, itemInfo) | |
164 | { | |
165 | typeID |= kMovableItem; | |
166 | weight = 1; | |
167 | background = 0; | |
168 | LinkInLists(); | |
169 | } | |
170 | ||
171 | CMovableItem::~CMovableItem() | |
172 | { | |
173 | } | |
174 | ||
175 | void CMovableItem::LinkInLists() | |
176 | { | |
177 | gApplication->Enqueue(&gApplication->thingList, this); | |
178 | gApplication->Enqueue(&gApplication->collisionThingList, this); | |
179 | if (isCorona) { | |
180 | gApplication->Enqueue(&gApplication->preRenderQueue, this); | |
181 | gApplication->Enqueue(&gApplication->postRenderQueue, this); | |
182 | }else gApplication->Enqueue(&gApplication->renderQueue, this); | |
183 | } | |
184 | ||
185 | void CMovableItem::UnlinkInLists() | |
186 | { | |
187 | gApplication->Dequeue(&gApplication->thingList, this); | |
188 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
189 | if (isCorona) { | |
190 | gApplication->Dequeue(&gApplication->preRenderQueue, this); | |
191 | gApplication->Dequeue(&gApplication->postRenderQueue, this); | |
192 | }else gApplication->Dequeue(&gApplication->renderQueue, this); | |
193 | } | |
194 | ||
195 | ||
196 | CPortableItem::CPortableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo, short itemNo) : | |
197 | CItem(initx, inity, width, height, number, itemInfo) | |
198 | { | |
199 | typeID |= kPortableItem; | |
200 | type = itemNo; | |
201 | background = 0; | |
202 | weight = 1; | |
203 | pickedUp = 0; | |
204 | LinkInLists(); | |
205 | } | |
206 | ||
207 | CPortableItem::~CPortableItem() | |
208 | { | |
209 | } | |
210 | ||
211 | void CPortableItem::LinkInLists() | |
212 | { | |
213 | gApplication->Enqueue(&gApplication->thingList, this); | |
214 | gApplication->Enqueue(&gApplication->collisionThingList, this); | |
215 | if (isCorona) { | |
216 | gApplication->Enqueue(&gApplication->preRenderQueue, this); | |
217 | gApplication->Enqueue(&gApplication->postRenderQueue, this); | |
218 | }else gApplication->Enqueue(&gApplication->renderQueue, this); | |
219 | } | |
220 | ||
221 | void CPortableItem::UnlinkInLists() | |
222 | { | |
223 | gApplication->Dequeue(&gApplication->thingList, this); | |
224 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
225 | if (isCorona) { | |
226 | gApplication->Dequeue(&gApplication->preRenderQueue, this); | |
227 | gApplication->Dequeue(&gApplication->postRenderQueue, this); | |
228 | }else gApplication->Dequeue(&gApplication->renderQueue, this); | |
229 | } | |
230 | ||
231 | ||
232 | short CPortableItem::Think() | |
233 | { | |
234 | CObject::Think(); | |
235 | ||
236 | if (pickedUp) return kDestroyMe; else return kNoEvent; | |
237 | } | |
238 | ||
239 | short CPortableItem::PickMeUp(short &value) | |
240 | { | |
241 | value = info->data; | |
242 | pickedUp = 1; | |
243 | ||
244 | return type; | |
245 | } | |
246 | ||
247 | short CItem::Write(FILE *f) | |
248 | { | |
249 | long size = 0; | |
250 | ||
251 | WRITEDATA(size); | |
252 | WRITEDATA(typeID); | |
253 | WRITEDATA(thingNumber); | |
254 | ||
255 | size += CThing::Write(f); | |
256 | ||
257 | WRITEDATA(isCorona); | |
258 | WRITEDATA(detonationStartTime); | |
259 | ||
260 | FINISHWRITE; | |
261 | ||
262 | return size; | |
263 | } | |
264 | ||
265 | ||
266 | void CItem::Read(FILE *f) | |
267 | { | |
268 | long size = 0; | |
269 | ||
270 | READDATA(size); | |
271 | READDATA(typeID); | |
272 | READDATA(thingNumber); | |
273 | ||
274 | CThing::Read(f); | |
275 | ||
276 | READDATA(isCorona); | |
277 | READDATA(detonationStartTime); | |
278 | } | |
279 | ||
280 | short CPortableItem::Write(FILE *f) | |
281 | { | |
282 | long size = 0; | |
283 | ||
284 | WRITEDATA(size); | |
285 | WRITEDATA(typeID); | |
286 | WRITEDATA(thingNumber); | |
287 | ||
288 | size += CItem::Write(f); | |
289 | ||
290 | WRITEDATA(pickedUp); | |
291 | WRITEDATA(type); | |
292 | ||
293 | FINISHWRITE; | |
294 | ||
295 | return size; | |
296 | } | |
297 | ||
298 | ||
299 | void CPortableItem::Read(FILE *f) | |
300 | { | |
301 | long size = 0; | |
302 | ||
303 | READDATA(size); | |
304 | READDATA(typeID); | |
305 | READDATA(thingNumber); | |
306 | ||
307 | CItem::Read(f); | |
308 | ||
309 | READDATA(pickedUp); | |
310 | READDATA(type); | |
311 | }⏎ |
0 | #ifndef __AMP_ITEM__ | |
1 | #define __AMP_ITEM__ | |
2 | ||
3 | #include "Thing.hpp" | |
4 | #include "ObjInfo.hpp" | |
5 | #include "Shape.hpp" | |
6 | ||
7 | class CItem : public CThing { | |
8 | protected: | |
9 | CShape *shape; | |
10 | CShape *currentShape; | |
11 | tItemInfo *info; | |
12 | ||
13 | long detonationStartTime; | |
14 | short isCorona; | |
15 | double coronaFader; | |
16 | ||
17 | public: | |
18 | CItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); | |
19 | ~CItem(); | |
20 | ||
21 | short Think(); | |
22 | void Render(short planeX, short planeY, tRect *clipRect); | |
23 | void PostRender(short planeX, short planeY, tRect *clipRect); | |
24 | void Move(); | |
25 | ||
26 | void OnDamage(short blessure); | |
27 | ||
28 | short Write(FILE *f); | |
29 | void Read(FILE *f); | |
30 | }; | |
31 | ||
32 | class CStaticItem : public CItem { | |
33 | protected: | |
34 | ||
35 | public: | |
36 | CStaticItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); | |
37 | ~CStaticItem(); | |
38 | ||
39 | void LinkInLists(); | |
40 | void UnlinkInLists(); | |
41 | ||
42 | short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
43 | }; | |
44 | ||
45 | class CBackgroundItem : public CItem { | |
46 | protected: | |
47 | ||
48 | public: | |
49 | CBackgroundItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); | |
50 | ~CBackgroundItem(); | |
51 | ||
52 | void LinkInLists(); | |
53 | void UnlinkInLists(); | |
54 | }; | |
55 | ||
56 | class CMovableItem : public CItem { | |
57 | protected: | |
58 | ||
59 | public: | |
60 | CMovableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo); | |
61 | ~CMovableItem(); | |
62 | ||
63 | void LinkInLists(); | |
64 | void UnlinkInLists(); | |
65 | }; | |
66 | ||
67 | class CPortableItem : public CItem { | |
68 | protected: | |
69 | short pickedUp; | |
70 | short type; | |
71 | ||
72 | public: | |
73 | CPortableItem(short initx, short inity, short width, short height, short number, tItemInfo *itemInfo, short type); | |
74 | ~CPortableItem(); | |
75 | ||
76 | void LinkInLists(); | |
77 | void UnlinkInLists(); | |
78 | ||
79 | short Think(); | |
80 | short PickMeUp(short &value); | |
81 | ||
82 | short Write(FILE *f); | |
83 | void Read(FILE *f); | |
84 | }; | |
85 | ||
86 | #endif⏎ |
0 | #include <stdio.h> | |
1 | #include <string.h> | |
2 | #include <time.h> | |
3 | ||
4 | #include "Level.hpp" | |
5 | #include "Appl.hpp" | |
6 | #include "ConstVal.hpp" | |
7 | #include "Gui.hpp" | |
8 | #include "ShapeLd.hpp" | |
9 | ||
10 | extern CApplication *gApplication; | |
11 | extern CObjInfo *gObjInfo; | |
12 | extern tConstValues *gConst; | |
13 | extern CSystem *gSystem; | |
14 | extern CShapeManager *gShapeManager; | |
15 | extern tGUIConstants *gGUIConst; | |
16 | extern CGUI *gGUI; | |
17 | extern FILE *logFile; | |
18 | ||
19 | //---------------------------------------------------- | |
20 | CLevel::CLevel(short levelNumber, char *fileName) | |
21 | /* In: levelNumber: number of level to be loaded | |
22 | ||
23 | First loads the level data from file, then generating each level element object, and if there are monsters | |
24 | or items on the element, generate them | |
25 | Then create platforms | |
26 | */ | |
27 | { | |
28 | if (fileName) { | |
29 | ||
30 | ReadLevel(fileName); | |
31 | ||
32 | }else{ | |
33 | short j, k; | |
34 | tLevelElement *levelElement = new tLevelElement; | |
35 | CThing *thing; | |
36 | ||
37 | LoadBackground(levelNumber); | |
38 | ||
39 | gObjInfo->CreatePlatforms(); | |
40 | ||
41 | if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileLevel))) gSystem->Error("File kFileLevel not found or not able to open it", 0); // by LL | |
42 | ||
43 | SetFilePos(levelNumber * kLevelWidth * kLevelHeight * sizeof(tLevelElement)); | |
44 | ||
45 | MSG("Creating level\n"); | |
46 | for (j = 0; j < kLevelHeight; j ++) { | |
47 | for (k = 0; k < kLevelWidth; k ++) { | |
48 | ReadData(levelElement, sizeof(tLevelElement)); | |
49 | ||
50 | TRANS_PUT_NUM(levelElement->kind); | |
51 | TRANS_PUT_NUM(levelElement->iconID); | |
52 | TRANS_PUT_NUM(levelElement->light); | |
53 | TRANS_PUT_NUM(levelElement->refNum); | |
54 | TRANS_PUT_NUM(levelElement->bitData); | |
55 | TRANS_PUT_NUM(levelElement->monsterRef); | |
56 | TRANS_PUT_NUM(levelElement->itemRef); | |
57 | ||
58 | if (levelElement->iconID > 0) levelElement->iconID += gConst->kShapeSets[levelNumber] * 20; | |
59 | ||
60 | if (levelElement->iconID) | |
61 | level[j][k] = new CElement(k * kElementSize + kElementSize / 2, j * kElementSize + kElementSize / 2, kElementSize, kElementSize, levelElement); | |
62 | else level[j][k] = new CBackgroundElement(k * kElementSize + kElementSize / 2, j * kElementSize + kElementSize / 2, kElementSize, kElementSize, levelElement); | |
63 | ||
64 | level[j][k]->LinkPlatforms(); | |
65 | ||
66 | if (levelElement->monsterRef != -1) { | |
67 | if (levelElement->monsterRef == kCameraNo) | |
68 | thing = new CCamera(k * kElementSize, j * kElementSize, 2, 2, 0); | |
69 | else | |
70 | thing = gObjInfo->CreateMonster(levelElement->monsterRef, k, j); | |
71 | ||
72 | ||
73 | if (thing->typeID & (kPlayer | kCamera)) { | |
74 | focus = thing; | |
75 | player = thing; | |
76 | } | |
77 | } | |
78 | ||
79 | if (levelElement->itemRef != -1) { | |
80 | thing = gObjInfo->CreateItem(levelElement->itemRef, k, j); | |
81 | } | |
82 | ||
83 | } | |
84 | } | |
85 | ||
86 | delete levelElement; | |
87 | ||
88 | CloseDataFile(); | |
89 | ||
90 | gSystem->ResetTicks(0); | |
91 | gGUI->ResetTicks(0); | |
92 | } | |
93 | } | |
94 | ||
95 | ||
96 | CLevel::~CLevel() | |
97 | { | |
98 | short j, k; | |
99 | ||
100 | for (j = 0; j < kLevelHeight; j ++) { | |
101 | for (k = 0; k < kLevelWidth; k ++) { | |
102 | delete level[j][k]; | |
103 | } | |
104 | } | |
105 | } | |
106 | ||
107 | void CLevel::LoadBackground(short levelNumber) | |
108 | { | |
109 | if (gConst->kBackgrounds[levelNumber] != gApplication->lastBackground) { | |
110 | gShapeManager->UnloadBackground(); | |
111 | ||
112 | if (gConst->kBackgrounds[levelNumber] == 1) | |
113 | gShapeManager->LoadBackground(gConst->kFileBackground1); | |
114 | else | |
115 | gShapeManager->LoadBackground(gConst->kFileBackground2); | |
116 | gApplication->lastBackground = gConst->kBackgrounds[levelNumber]; | |
117 | } | |
118 | } | |
119 | ||
120 | void CLevel::PaintLevel() | |
121 | { | |
122 | short j, k; | |
123 | short planeX, planeY; | |
124 | short startElementX, startElementY, numElementsX, numElementsY; | |
125 | tRect clipRect; | |
126 | tThingList *currentEntry; | |
127 | ||
128 | focus->CalcPlaneOffsets(planeX, planeY); | |
129 | ||
130 | clipRect.left = 0; | |
131 | clipRect.top = 0; | |
132 | clipRect.right = kGamePlaneWidth; | |
133 | clipRect.bottom = kGamePlaneHeight; | |
134 | ||
135 | startElementX = planeX / kElementSize; | |
136 | startElementY = planeY / kElementSize; | |
137 | numElementsX = kGamePlaneWidth / kElementSize; | |
138 | numElementsY = kGamePlaneHeight / kElementSize; | |
139 | ||
140 | for (j = startElementY; j < startElementY + numElementsY + 1 && j < kLevelHeight; j ++) { | |
141 | for (k = startElementX; k < startElementX + numElementsX + 1 && k < kLevelWidth; k ++) { | |
142 | level[j][k]->PaintElement(planeX, planeY, &clipRect); | |
143 | } | |
144 | } | |
145 | currentEntry = gApplication->preRenderQueue; | |
146 | while (currentEntry) { | |
147 | currentEntry->thing->Render(planeX, planeY, &clipRect); | |
148 | currentEntry = currentEntry->next; | |
149 | } | |
150 | ||
151 | currentEntry = gApplication->renderQueue; | |
152 | while (currentEntry) { | |
153 | currentEntry->thing->Render(planeX, planeY, &clipRect); | |
154 | currentEntry = currentEntry->next; | |
155 | } | |
156 | ||
157 | currentEntry = gApplication->postRenderQueue; | |
158 | while (currentEntry) { | |
159 | currentEntry->thing->PostRender(planeX, planeY, &clipRect); | |
160 | currentEntry = currentEntry->next; | |
161 | } | |
162 | } | |
163 | ||
164 | ||
165 | CElement *CLevel::GetElement(double x, double y) | |
166 | { | |
167 | short elemx, elemy; | |
168 | ||
169 | elemx = (short)(x / kElementSize); | |
170 | elemy = (short)(y / kElementSize); | |
171 | ||
172 | if (elemx >= 0 && elemy >= 0 && elemx < kLevelWidth && elemy < kLevelHeight) | |
173 | return level[elemy][elemx]; | |
174 | else return 0L; | |
175 | } | |
176 | ||
177 | // ----------------------------------------------- | |
178 | void CLevel::SwitchLight(short lightID) | |
179 | // Searches all elements with key equal to key, and then change their | |
180 | // lights. Don't call this routine too often, it's slow | |
181 | { | |
182 | short j, k; | |
183 | ||
184 | for (j = 0; j < kLevelHeight; j ++) { | |
185 | for (k = 0; k < kLevelWidth; k ++) { | |
186 | if (level[j][k]->key == lightID) level[j][k]->SwapLights(); | |
187 | } | |
188 | } | |
189 | } | |
190 | ||
191 | // ----------------------------------------------- | |
192 | CElement *CLevel::FindRefnum(short refnum) | |
193 | // Finds the first element with key == refnum and returns it | |
194 | { | |
195 | short j, k; | |
196 | ||
197 | for (j = 0; j < kLevelHeight; j ++) { | |
198 | for (k = 0; k < kLevelWidth; k ++) { | |
199 | if (level[j][k]->key == refnum) return level[j][k]; | |
200 | } | |
201 | } | |
202 | return 0L; | |
203 | } | |
204 | ||
205 | ||
206 | void CLevel::WriteLevel(char *fileName) | |
207 | { | |
208 | char tmpName[12] = "tmp.sg0"; | |
209 | long versionNumber = kVersionNumber; | |
210 | long key = kVersionKey; | |
211 | time_t theTime; | |
212 | long ticks; | |
213 | long size; | |
214 | tThingList *currentEntry; | |
215 | char *tmpFileName; | |
216 | ||
217 | tmpFileName = gSystem->QualifyHomeDir(tmpName); | |
218 | remove(tmpFileName); | |
219 | FILE *f = fopen(tmpFileName, "wb"); // by LL | |
220 | if (!f) { | |
221 | gSystem->Error("Cannot open the saving file", 0); | |
222 | } | |
223 | ||
224 | MSG("Writing save file header\n"); | |
225 | fwrite(&versionNumber, sizeof(versionNumber), 1, f); | |
226 | fwrite(&key, sizeof(key), 1, f); | |
227 | theTime = time(&theTime); | |
228 | fwrite(&theTime, sizeof(theTime), 1, f); | |
229 | ticks = gSystem->GetTicks(); | |
230 | fwrite(&ticks, sizeof(ticks), 1, f); | |
231 | fwrite(&gApplication->difficulty, sizeof(gApplication->difficulty), 1, f); | |
232 | size = 0; | |
233 | fwrite(&size, sizeof(size), 1, f); | |
234 | fwrite(&gApplication->levelNumber, sizeof(gApplication->levelNumber), 1, f); | |
235 | ||
236 | MSG("Writing level elements\n"); | |
237 | for (short j = 0; j < kLevelHeight; j ++) { | |
238 | for (short k = 0; k < kLevelWidth; k ++) { | |
239 | level[j][k]->Write(f); | |
240 | } | |
241 | } | |
242 | ||
243 | MSG("Writing objects\n"); | |
244 | currentEntry = gApplication->thingList; | |
245 | while (currentEntry) { | |
246 | currentEntry->thing->Write(f); | |
247 | currentEntry = currentEntry->next; | |
248 | } | |
249 | ||
250 | size = ftell(f); | |
251 | fseek(f, sizeof(versionNumber) + sizeof(key) + sizeof(theTime) + sizeof(ticks) + sizeof(gApplication->difficulty), SEEK_SET); | |
252 | fwrite(&size, sizeof(size), 1, f); | |
253 | ||
254 | MSG("Finishing up\n"); | |
255 | fflush(f); | |
256 | fclose(f); | |
257 | ||
258 | remove(fileName); | |
259 | rename(tmpFileName, fileName); | |
260 | delete [] tmpFileName; | |
261 | } | |
262 | ||
263 | void CLevel::GetSavedGameTitle(char *fileName, char *title) | |
264 | { | |
265 | ||
266 | ||
267 | long versionNumber, key; | |
268 | time_t time; | |
269 | FILE *f = fopen(fileName, "rb"); | |
270 | tm *tp; | |
271 | ||
272 | if (f) fread(&versionNumber, sizeof(versionNumber), 1, f); | |
273 | if (f) fread(&key, sizeof(key), 1, f); | |
274 | ||
275 | if (!f || versionNumber != kVersionNumber || key != kVersionKey) | |
276 | title = strcpy(title, gGUIConst->kNoSavedGame); | |
277 | else { | |
278 | fread(&time, sizeof(time), 1, f); | |
279 | tp = localtime(&time); | |
280 | strftime(title, 20, "%d.%m.%Y, %H.%M", tp); | |
281 | } | |
282 | ||
283 | if (f) fclose(f); | |
284 | } | |
285 | ||
286 | short CLevel::ReadLevel(char *fileName) | |
287 | { | |
288 | FILE *f = fopen(fileName, "rb"); | |
289 | long versionNumber, key; | |
290 | time_t theTime; | |
291 | long ticks; | |
292 | long size, fileSize; | |
293 | long typeID = -1; | |
294 | CThing *thing; | |
295 | short thingNumber; | |
296 | short j, k; | |
297 | ||
298 | if (!f) gSystem->Error("Cannot open the saving file", 0); | |
299 | ||
300 | MSG("Reading level header\n"); | |
301 | fread(&versionNumber, sizeof(versionNumber), 1, f); if (versionNumber != kVersionNumber) return 0; | |
302 | fread(&key, sizeof(key), 1, f); if (key != kVersionKey) return 0; | |
303 | fread(&theTime, sizeof(theTime), 1, f); | |
304 | fread(&ticks, sizeof(ticks), 1, f); | |
305 | fread(&gApplication->difficulty, sizeof(gApplication->difficulty), 1, f); | |
306 | fread(&fileSize, sizeof(fileSize), 1, f); | |
307 | fread(&gApplication->levelNumber, sizeof(gApplication->levelNumber), 1, f); | |
308 | ||
309 | LoadBackground(gApplication->levelNumber); | |
310 | ||
311 | MSG("Reading level elements\n"); | |
312 | for (j = 0; j < kLevelHeight; j ++) { | |
313 | for (k = 0; k < kLevelWidth; k ++) { | |
314 | fread(&size, sizeof(size), 1, f); | |
315 | fread(&typeID, sizeof(typeID), 1, f); | |
316 | fseek(f, - (sizeof(size) + sizeof(typeID)), SEEK_CUR); | |
317 | ||
318 | if (typeID & kBackgroundElement) | |
319 | level[j][k] = new CBackgroundElement(k * kElementSize, j * kElementSize, kElementSize, kElementSize, 0L); | |
320 | else | |
321 | level[j][k] = new CElement(k * kElementSize, j * kElementSize, kElementSize, kElementSize, 0L); | |
322 | ||
323 | level[j][k]->Read(f); | |
324 | } | |
325 | } | |
326 | ||
327 | ||
328 | MSG("Reading objects\n"); | |
329 | while (!feof(f) && ftell(f) < fileSize) { | |
330 | ||
331 | ||
332 | fread(&size, sizeof(size), 1, f); | |
333 | fread(&typeID, sizeof(typeID), 1, f); | |
334 | fread(&thingNumber, sizeof(thingNumber), 1, f); | |
335 | fseek(f, - (sizeof(size) + sizeof(typeID) + sizeof(thingNumber)), SEEK_CUR); | |
336 | ||
337 | ||
338 | if (typeID & kMonster) { | |
339 | thing = gObjInfo->CreateMonster(thingNumber, 0, 0); | |
340 | ||
341 | if (typeID & kPlayer) { | |
342 | focus = thing; | |
343 | player = thing; | |
344 | } | |
345 | ||
346 | thing->Read(f); | |
347 | } | |
348 | ||
349 | if (typeID & kItem) { | |
350 | thing = gObjInfo->CreateItem(thingNumber, 0, 0); | |
351 | ||
352 | thing->Read(f); | |
353 | } | |
354 | ||
355 | if (typeID & kBullet) { | |
356 | ||
357 | if (typeID & kSorceryBullet) | |
358 | thing = new CSorceryBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); | |
359 | else if (typeID & kBombBullet) | |
360 | thing = new CBombBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); | |
361 | else if (typeID & kSineBullet) | |
362 | thing = new CSineBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0, 0, 0); | |
363 | else if (typeID & kGuidedBullet) | |
364 | thing = new CGuidedBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0, 0L); | |
365 | else | |
366 | thing = new CBullet(0, 0, 0, 0, 0, 0L, 0, 0, 0L, 0); | |
367 | ||
368 | ||
369 | ||
370 | thing->Read(f); | |
371 | } | |
372 | ||
373 | if (typeID & kPlatform) { | |
374 | thing = new CPlatform(0, 0, 0, 0, 0, 0L); | |
375 | ||
376 | thing->Read(f); | |
377 | ||
378 | gApplication->platformTable[thingNumber] = (CPlatform *)thing; | |
379 | } | |
380 | } | |
381 | ||
382 | MSG("Finishing up\n"); | |
383 | fflush(f); | |
384 | fclose(f); | |
385 | ||
386 | for (j = 0; j < kLevelHeight; j ++) { | |
387 | for (k = 0; k < kLevelWidth; k ++) { | |
388 | level[j][k]->LinkPlatforms(); | |
389 | } | |
390 | } | |
391 | ||
392 | ||
393 | gSystem->ResetTicks(ticks); | |
394 | gGUI->ResetTicks(ticks); | |
395 | ||
396 | return 1; | |
397 | } | |
398 |
0 | #ifndef __AMP_LEVEL__ | |
1 | #define __AMP_LEVEL__ | |
2 | ||
3 | #include "File.hpp" | |
4 | #include "Element.hpp" | |
5 | #include "AmpHead.hpp" | |
6 | #include "ShapeLd.hpp" | |
7 | #include "Thing.hpp" | |
8 | ||
9 | class CLevel : public CFile { | |
10 | protected: | |
11 | void LoadBackground(short levNum); | |
12 | public: | |
13 | CElement *level[kLevelHeight][kLevelWidth]; | |
14 | CThing *player; | |
15 | CThing *focus; | |
16 | ||
17 | ||
18 | CLevel(short levelNumber, char *fileName); | |
19 | ~CLevel(); | |
20 | ||
21 | void PaintLevel(); | |
22 | CElement *GetElement(double x, double y); | |
23 | void SwitchLight(short lightID); | |
24 | CElement *FindRefnum(short refnum); | |
25 | void WriteLevel(char *fileName); | |
26 | short ReadLevel(char *fileName); | |
27 | void GetSavedGameTitle(char *fileName, char *title); | |
28 | }; | |
29 | ||
30 | ||
31 | #endif⏎ |
0 | #include "System.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "Clut.hpp" | |
3 | #include "Gui.hpp" | |
4 | #include "SndSys.hpp" | |
5 | #include "string.h" | |
6 | ||
7 | // Services | |
8 | CApplication *gApplication; | |
9 | CSystem *gSystem; | |
10 | CLevel *gLevel; | |
11 | CObjInfo *gObjInfo; | |
12 | CShapeManager *gShapeManager; | |
13 | CClutManager *gClutManager; | |
14 | tConstValues *gConst; | |
15 | tConfigData *gConfigData; | |
16 | CGUI *gGUI; | |
17 | CSoundSystem *gSoundSystem; | |
18 | ||
19 | static char **my_argv; | |
20 | static int my_argc; | |
21 | ||
22 | int checkParam(const char *s) | |
23 | { | |
24 | int i; | |
25 | ||
26 | for (i=1; i<my_argc; i++) { | |
27 | if (!strcasecmp(s, my_argv[i])) { | |
28 | // printf("Detected option %s as %d\n", s, i); | |
29 | return i; | |
30 | } | |
31 | } | |
32 | return 0; | |
33 | } | |
34 | ||
35 | void showUsage() | |
36 | { | |
37 | ||
38 | printf("-ns, --nosound disable sound\n"); | |
39 | printf("-fs, --fullscreen try DGA fullscreen mode\n"); | |
40 | printf(" --version display version information and exit\n"); | |
41 | printf(" --help display this help and exit\n"); | |
42 | } | |
43 | ||
44 | void showVersion() | |
45 | { | |
46 | printf("Amphetamine %s \n", kVersionString); | |
47 | printf("Contact <loehrerl@bigfoot.com> for comments.\n"); | |
48 | } | |
49 | ||
50 | ||
51 | int checkCommandLine() | |
52 | { | |
53 | if (checkParam("--help")) { | |
54 | showUsage(); | |
55 | return -1; | |
56 | } | |
57 | ||
58 | if (checkParam("--version")) { | |
59 | showVersion(); | |
60 | return -1; | |
61 | } | |
62 | ||
63 | gConfigData = new tConfigData; | |
64 | ||
65 | gConfigData->haveSound= !(checkParam("--nosound") || checkParam("-ns")) ; | |
66 | gConfigData->tryFullScreen= checkParam("--fullscreen") || checkParam("-fs"); | |
67 | ||
68 | return 0; | |
69 | } | |
70 | ||
71 | int main(int argc, char **argv) | |
72 | { | |
73 | my_argc = argc; | |
74 | my_argv = argv; | |
75 | if (checkCommandLine()) return 0; | |
76 | ||
77 | gApplication = new CApplication(); | |
78 | gApplication->InitGraphics(); | |
79 | gApplication->LoadData(); | |
80 | gApplication->Run(); | |
81 | gApplication->UnloadData(); | |
82 | gApplication->Quit(); | |
83 | delete gApplication; | |
84 | ||
85 | return 0; | |
86 | }⏎ |
0 | #include "Monster.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | ||
4 | extern CApplication *gApplication; | |
5 | extern CShapeManager *gShapeManager; | |
6 | extern CObjInfo *gObjInfo; | |
7 | extern CLevel *gLevel; | |
8 | extern tConstValues *gConst; | |
9 | ||
10 | CMonster::CMonster(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : | |
11 | CThing(initx, inity, width, height, number) | |
12 | { | |
13 | typeID |= kMonster; | |
14 | background = 0; | |
15 | LinkInLists(); | |
16 | ||
17 | if (monsterInfo) { | |
18 | info = monsterInfo; | |
19 | ||
20 | OnAllocate(); | |
21 | ||
22 | lastWalkTime = 0; | |
23 | lastShootTime = 0; | |
24 | walkFrame = 0; | |
25 | flying = 0; | |
26 | teleportCounter = -1; | |
27 | lastBlessureTime = 0; | |
28 | dieFrameTime = 0; | |
29 | dieFrame = -1; | |
30 | speed = info->speed * gApplication->currentSpeedSF; | |
31 | } | |
32 | ||
33 | // additinal init | |
34 | lastCollisionCode = kNoCollision; | |
35 | status = kMonsterForward; | |
36 | doDarken = 0; | |
37 | } | |
38 | ||
39 | void CMonster::OnAllocate() | |
40 | { | |
41 | for (short n = 0; n < 3; n ++) { | |
42 | moveShapes[n] = gShapeManager->FindShape(info->moveShapes[n], 0); | |
43 | deathShapes[n] = gShapeManager->FindShape(info->deathShapes[n], 0); | |
44 | } | |
45 | jumpShape = gShapeManager->FindShape(info->jumpShape, 0); | |
46 | attackShape = gShapeManager->FindShape(info->attackShape, 0); | |
47 | ||
48 | weapon = CreateWeapon(info->weapon); | |
49 | currentShape = moveShapes[0]; | |
50 | ||
51 | health = info->energy * gApplication->currentHealthSF; | |
52 | } | |
53 | ||
54 | ||
55 | void CMonster::LinkInLists() | |
56 | { | |
57 | gApplication->Enqueue(&gApplication->thingList, this); | |
58 | gApplication->Enqueue(&gApplication->collisionThingList, this); | |
59 | gApplication->Enqueue(&gApplication->renderQueue, this); | |
60 | } | |
61 | ||
62 | void CMonster::UnlinkInLists() | |
63 | { | |
64 | gApplication->Dequeue(&gApplication->thingList, this); | |
65 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
66 | gApplication->Dequeue(&gApplication->renderQueue, this); | |
67 | } | |
68 | ||
69 | ||
70 | CMonster::~CMonster() | |
71 | { | |
72 | if (weapon) delete weapon; | |
73 | } | |
74 | ||
75 | ||
76 | CWeapon *CMonster::CreateWeapon(short weapon) | |
77 | { | |
78 | tWeaponInfo *tmp = gObjInfo->FindWeapon(weapon); | |
79 | CWeapon *tmpWeapon; | |
80 | ||
81 | noWeapon = 0; | |
82 | ||
83 | switch (tmp->art) { | |
84 | case kWeaponMultibullet: | |
85 | tmpWeapon = new CMultiBulletWeapon(this, tmp, attackShape, gConst->kFirehandAngle); | |
86 | break; | |
87 | case kWeaponInHand: | |
88 | tmpWeapon = new CWeapon(this, tmp, attackShape); | |
89 | noWeapon = 1; | |
90 | break; | |
91 | case kWeaponSine: | |
92 | tmpWeapon = new CSineWeapon(this, tmp, attackShape, gConst->kSineWeaponRad); | |
93 | break; | |
94 | case kWeaponGuided: | |
95 | tmpWeapon = new CGuided(this, tmp, attackShape); | |
96 | break; | |
97 | case kWeaponSorcery: | |
98 | tmpWeapon = new CSorcery(this, tmp, attackShape); | |
99 | break; | |
100 | case kWeaponNormal: | |
101 | case kWeaponHasWeight: | |
102 | default: | |
103 | tmpWeapon = new CWeapon(this, tmp, attackShape); | |
104 | break; | |
105 | } | |
106 | if (tmpWeapon) { | |
107 | tmpWeapon->weaponStatus = kWeaponReady; | |
108 | tmpWeapon->AddMunition(SHRT_MAX); | |
109 | tmpWeapon->weaponNumber = weapon; | |
110 | } | |
111 | return tmpWeapon; | |
112 | } | |
113 | ||
114 | void CMonster::Move() | |
115 | { | |
116 | ||
117 | CThing::Move(); | |
118 | ||
119 | if (ys >= kLevelHeight * kElementSize) { | |
120 | health = 0; | |
121 | OnKill(); | |
122 | } | |
123 | ||
124 | if (info->invisible) modus = kShapemodusShadow; | |
125 | ||
126 | currentShape = moveShapes[walkFrame]; | |
127 | ||
128 | if (forceVectorX && lastTime > lastWalkTime ) { | |
129 | walkFrame ++; | |
130 | walkFrame %= 3; | |
131 | lastWalkTime = lastTime + gConst->kWalkFrameTime; | |
132 | } | |
133 | ||
134 | if (forceVectorY < 0) currentShape = jumpShape; | |
135 | ||
136 | if (dieFrame != -1) { | |
137 | if (dieFrameTime < lastTime && dieFrame < 2) { | |
138 | dieFrame ++; | |
139 | dieFrameTime = lastTime + gConst->kDieFrameTime; | |
140 | ||
141 | if (dieFrame == 2) | |
142 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
143 | } | |
144 | currentShape = deathShapes[dieFrame]; | |
145 | } | |
146 | ||
147 | if (weapon) doDarken = weapon->ShootAnimation(¤tShape); | |
148 | } | |
149 | ||
150 | short CMonster::Forces() | |
151 | { | |
152 | short collisionObject; | |
153 | ||
154 | ||
155 | Gravitation(); | |
156 | ||
157 | CObject::Forces(); | |
158 | ||
159 | lastCollisionCode = ExertForce(resForceX, resForceY, collisionObject, 0L); | |
160 | if (lastCollisionCode & (kCollisionOnLeft | kCollisionOnRight)) forceVectorX = 0; | |
161 | ||
162 | return kNoEvent; | |
163 | } | |
164 | ||
165 | // -------------------------------------------------------------------- | |
166 | void CMonster::Render(short planeX, short planeY, tRect *clipRect) | |
167 | // Renders the current Shape of the monster | |
168 | { | |
169 | CElement *element = gLevel->GetElement(xm, ym); | |
170 | short screenPosx = xs - planeX, screenPosy = ys - planeY; // Position of monster on the screen | |
171 | short brightness = (element && doDarken) ? element->brightness : 0; | |
172 | ||
173 | // Teleporting... | |
174 | if (teleportCounter != -1) { | |
175 | ||
176 | if (teleportCounter > dx / 2) { | |
177 | clipRect->left = MAX(screenPosx + dx - teleportCounter, clipRect->left); | |
178 | clipRect->right = MIN(screenPosx + teleportCounter, clipRect->right); | |
179 | }else{ | |
180 | clipRect->left = MAX(screenPosx + teleportCounter, clipRect->left); | |
181 | clipRect->right = MIN(screenPosx + (xe - planeX) - teleportCounter, clipRect->right); | |
182 | } | |
183 | ||
184 | if (teleportDeltaTime < lastTime) { | |
185 | teleportCounter ++; | |
186 | teleportDeltaTime = lastTime + gConst->kTeleportTime / dx * 2; | |
187 | } | |
188 | ||
189 | if (teleportCounter == dx / 2) OnTeleport(); | |
190 | if (teleportCounter == dx) teleportCounter = -1; | |
191 | ||
192 | modus = kShapemodusRandom; | |
193 | } | |
194 | ||
195 | // Testing for blessure invulnerability | |
196 | if (lastBlessureTime > lastTime) modus = kShapemodusRandom; | |
197 | ||
198 | ||
199 | if (lookDirection == kLookingLeft) modus |= kShapemodusBackwardFlag; | |
200 | ||
201 | if (currentShape) currentShape->RenderShape(screenPosx, screenPosy, clipRect, | |
202 | modus, brightness, gApplication->plane); | |
203 | } | |
204 | ||
205 | short CMonster::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
206 | { | |
207 | short returnValue = CThing::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); | |
208 | if (returnValue && sender->typeID & kPlayer) { | |
209 | if (dieFrame == -1) ((CThing *)sender)->OnDamage(info->touchBlessure); | |
210 | if (info->canExplode && dieFrame == -1) OnKill(); | |
211 | } | |
212 | ||
213 | return returnValue; | |
214 | } | |
215 | ||
216 | short CMonster::Think() | |
217 | { | |
218 | tThingList *bulletEntry; | |
219 | short elemx, elemy; | |
220 | double directionx, directiony; | |
221 | ||
222 | CObject::Think(); | |
223 | ||
224 | if (dieFrame != -1) return kNoEvent; | |
225 | if (gApplication->firstPlayRound) OnStart(); | |
226 | ||
227 | if (ABS(FindPlayerX()) > gConst->kActivateDistance) return kNoEvent; | |
228 | ||
229 | // Checking for a treatment event | |
230 | bulletEntry = gApplication->bulletList; | |
231 | while (bulletEntry) { | |
232 | if (((CBullet *)(bulletEntry->thing))->AmIATreatment(xs, ys, xe, ye, directionx, directiony)) { | |
233 | OnTreatment(directionx, directiony); | |
234 | bulletEntry = 0L; | |
235 | }else bulletEntry = bulletEntry->next; | |
236 | } | |
237 | ||
238 | // Checking for an abyss event | |
239 | if (forceVectorX > 0) { | |
240 | elemx = (short)(xe + forceVectorX) / kElementSize; | |
241 | elemy = (short)ym / kElementSize; | |
242 | }else{ | |
243 | elemx = (short)(xs + forceVectorX) / kElementSize; | |
244 | elemy = (short)ym / kElementSize; | |
245 | } | |
246 | if ((lastCollisionCode & kCollisionOnBottom) && elemx > 0 && elemy > 0 && elemx < kLevelWidth && elemy + 1 < kLevelHeight) { | |
247 | if (gLevel->level[elemy][elemx]->background && | |
248 | gLevel->level[elemy + 1][elemx]->background) OnAbyss(); | |
249 | } | |
250 | ||
251 | // Checking for a collision event | |
252 | if (lastCollisionCode & ~kCollisionOnBottom) OnCollision(); | |
253 | ||
254 | // Checking for a landing event | |
255 | if (flying && lastCollisionCode & kCollisionOnBottom) OnLanding(); | |
256 | flying = !(lastCollisionCode & kCollisionOnBottom); | |
257 | ||
258 | // Sending an idle event | |
259 | OnIdle(); | |
260 | ||
261 | return kNoEvent; | |
262 | } | |
263 | ||
264 | void CMonster::OnStart() {} | |
265 | void CMonster::OnAbyss() {} | |
266 | void CMonster::OnCollision() {} | |
267 | void CMonster::OnLanding() {} | |
268 | void CMonster::OnIdle() {} | |
269 | void CMonster::OnTreatment(double directionx, double directiony) {} | |
270 | void CMonster::OnShootSuccessful() {} | |
271 | void CMonster::OnShootNotSuccessful() {} | |
272 | void CMonster::OnTeleport() {} | |
273 | ||
274 | ||
275 | // --------------------------------------------- | |
276 | void CMonster::OnDamage(short blessure) | |
277 | // Event occurs, when a monster is hit by something (bullet etc.) | |
278 | { | |
279 | if (dieFrame == -1 && lastBlessureTime < lastTime) { | |
280 | health -= blessure; | |
281 | if (health < 0) | |
282 | OnKill(); | |
283 | else | |
284 | lastBlessureTime = lastTime + gConst->kBlessureInvulnerabilityTime; | |
285 | } | |
286 | } | |
287 | ||
288 | ||
289 | void CMonster::OnKill() | |
290 | { | |
291 | dieFrameTime = lastTime + gConst->kDieFrameTime; | |
292 | ||
293 | dieFrame = 0; | |
294 | } | |
295 | ||
296 | void CMonster::OnTouch(CObject *touch) | |
297 | { | |
298 | if (dieFrame == -1) ((CThing *)touch)->OnDamage(info->touchBlessure); | |
299 | } | |
300 | ||
301 | ||
302 | double CMonster::FindPlayerX() | |
303 | { | |
304 | return gLevel->player->xm - xm; | |
305 | } | |
306 | ||
307 | double CMonster::FindPlayerY() | |
308 | { | |
309 | return gLevel->player->ym - ym; | |
310 | } | |
311 | ||
312 | ||
313 | short CMonster::Write(FILE *f) | |
314 | { | |
315 | long size = 0; | |
316 | ||
317 | WRITEDATA(size); | |
318 | WRITEDATA(typeID); | |
319 | WRITEDATA(thingNumber); | |
320 | ||
321 | size += CThing::Write(f); | |
322 | if (weapon) size += weapon->Write(f); | |
323 | ||
324 | WRITEDATA(speed); | |
325 | WRITEDATA(lastWalkTime); | |
326 | WRITEDATA(lastShootTime); | |
327 | WRITEDATA(walkFrame); | |
328 | WRITEDATA(status); | |
329 | WRITEDATA(lastCollisionCode); | |
330 | WRITEDATA(flying); | |
331 | WRITEDATA(teleportDeltaTime); | |
332 | WRITEDATA(teleportCounter); | |
333 | WRITEDATA(lastBlessureTime); | |
334 | WRITEDATA(dieFrameTime); | |
335 | WRITEDATA(dieFrame); | |
336 | WRITEDATA(doDarken); | |
337 | WRITEDATA(health); | |
338 | ||
339 | FINISHWRITE; | |
340 | ||
341 | return size; | |
342 | } | |
343 | ||
344 | void CMonster::Read(FILE *f) | |
345 | { | |
346 | long size = 0; | |
347 | ||
348 | READDATA(size); | |
349 | READDATA(typeID); | |
350 | READDATA(thingNumber); | |
351 | ||
352 | CThing::Read(f); | |
353 | ||
354 | OnAllocate(); | |
355 | ||
356 | if (weapon) weapon->Read(f); | |
357 | ||
358 | READDATA(speed); | |
359 | READDATA(lastWalkTime); | |
360 | READDATA(lastShootTime); | |
361 | READDATA(walkFrame); | |
362 | READDATA(status); | |
363 | READDATA(lastCollisionCode); | |
364 | READDATA(flying); | |
365 | READDATA(teleportDeltaTime); | |
366 | READDATA(teleportCounter); | |
367 | READDATA(lastBlessureTime); | |
368 | READDATA(dieFrameTime); | |
369 | READDATA(dieFrame); | |
370 | READDATA(doDarken); | |
371 | READDATA(health); | |
372 | ||
373 | if (dieFrame != -1) gApplication->Dequeue(&gApplication->collisionThingList, this); | |
374 | }⏎ |
0 | #ifndef __AMP_MONSTER__ | |
1 | #define __AMP_MONSTER__ | |
2 | ||
3 | #include "Thing.hpp" | |
4 | #include "ObjInfo.hpp" | |
5 | #include "Weapon.hpp" | |
6 | ||
7 | enum { // stati | |
8 | kMonsterForward, | |
9 | kMonsterBackward, | |
10 | kMonsterWaiting, | |
11 | kMonsterFastForward, // for Warg | |
12 | kMonsterFastBackward | |
13 | }; | |
14 | ||
15 | // if no shoots are successful, so shoot at least every 4 seconds | |
16 | const short kMonsterMaxShootDelay = 4000; | |
17 | const short kWalkerWaitAfterShooting = 800; | |
18 | ||
19 | class CMonster : public CThing { | |
20 | protected: | |
21 | CShape *moveShapes[3]; | |
22 | CShape *jumpShape; | |
23 | CShape *attackShape; | |
24 | CShape *deathShapes[3]; | |
25 | ||
26 | CWeapon *weapon; | |
27 | short noWeapon; | |
28 | ||
29 | tMonsterInfo *info; | |
30 | long lastWalkTime, lastShootTime; | |
31 | short walkFrame; | |
32 | CShape *currentShape; | |
33 | double speed; | |
34 | ||
35 | short status; | |
36 | short lastCollisionCode; | |
37 | short flying; | |
38 | long teleportDeltaTime; // actually only used by the player | |
39 | short teleportCounter; | |
40 | long lastBlessureTime; | |
41 | long dieFrameTime; | |
42 | short dieFrame; | |
43 | short doDarken; | |
44 | ||
45 | short health; | |
46 | ||
47 | // Events | |
48 | virtual void OnStart(); | |
49 | virtual void OnAbyss(); | |
50 | virtual void OnCollision(); | |
51 | virtual void OnLanding(); | |
52 | virtual void OnIdle(); | |
53 | virtual void OnTreatment(double directionx, double directiony); | |
54 | virtual void OnTeleport(); // actually only used by the player | |
55 | ||
56 | double FindPlayerX(); | |
57 | double FindPlayerY(); | |
58 | CWeapon *CreateWeapon(short weapon); | |
59 | ||
60 | public: | |
61 | CMonster(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
62 | ~CMonster(); | |
63 | ||
64 | void OnAllocate(); | |
65 | ||
66 | void LinkInLists(); | |
67 | void UnlinkInLists(); | |
68 | ||
69 | // public events | |
70 | virtual void OnShootSuccessful(); | |
71 | virtual void OnShootNotSuccessful(); | |
72 | virtual void OnDamage(short blessure); | |
73 | virtual void OnKill(); | |
74 | virtual void OnTouch(CObject *touch); | |
75 | ||
76 | virtual void Render(short planeX, short planeY, tRect *clipRect); | |
77 | short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
78 | short Think(); | |
79 | void Move(); | |
80 | short Forces(); | |
81 | ||
82 | virtual short Write(FILE *f); | |
83 | virtual void Read(FILE *f); | |
84 | }; | |
85 | ||
86 | ||
87 | ||
88 | #endif⏎ |
0 | #include "Monstrxx.hpp" | |
1 | #include "Level.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | #include "Appl.hpp" | |
4 | #include "System.hpp" | |
5 | ||
6 | extern CLevel *gLevel; | |
7 | extern tConstValues *gConst; | |
8 | extern CApplication *gApplication; | |
9 | extern CSystem *gSystem; | |
10 | ||
11 | /* ########################################### | |
12 | CREEPER CLASS EVENTS | |
13 | ############################################### */ | |
14 | CCreeper::CCreeper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) | |
15 | { | |
16 | } | |
17 | ||
18 | CCreeper::~CCreeper() | |
19 | {} | |
20 | ||
21 | void CCreeper::OnStart() | |
22 | { | |
23 | OnLanding(); | |
24 | } | |
25 | ||
26 | void CCreeper::OnLanding() | |
27 | { | |
28 | ||
29 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
30 | } | |
31 | ||
32 | void CCreeper::OnCollision() | |
33 | { | |
34 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
35 | } | |
36 | ||
37 | void CCreeper::OnAbyss() | |
38 | { | |
39 | if (FindPlayerY() < 0) status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
40 | } | |
41 | ||
42 | void CCreeper::OnIdle() | |
43 | { | |
44 | lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); | |
45 | forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); | |
46 | } | |
47 | ||
48 | ||
49 | /* ########################################### | |
50 | WALKER CLASS EVENTS | |
51 | ############################################### */ | |
52 | ||
53 | CWalker::CWalker(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) | |
54 | { | |
55 | lastShoot = 0; | |
56 | currentShootDelay = 0; | |
57 | nextShootTime = 0; | |
58 | } | |
59 | ||
60 | CWalker::~CWalker() | |
61 | {} | |
62 | ||
63 | void CWalker::OnStart() | |
64 | { | |
65 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
66 | } | |
67 | ||
68 | void CWalker::OnCollision() | |
69 | { | |
70 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
71 | } | |
72 | ||
73 | void CWalker::OnAbyss() | |
74 | { | |
75 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
76 | } | |
77 | ||
78 | void CWalker::OnIdle() | |
79 | { | |
80 | double px = FindPlayerX(); | |
81 | ||
82 | if (!noWeapon && lastTime > nextShootTime) { | |
83 | lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); | |
84 | ||
85 | if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { | |
86 | nextShootTime = lastTime + currentShootDelay; | |
87 | lastShoot = lastTime + kWalkerWaitAfterShooting; | |
88 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
89 | }; | |
90 | } | |
91 | ||
92 | lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); | |
93 | ||
94 | if (lastTime > lastShoot && lastTime > lastBlessureTime) forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); | |
95 | } | |
96 | ||
97 | ||
98 | void CWalker::OnTreatment(double directionx, double directiony) | |
99 | { | |
100 | if (directiony > 0) { | |
101 | if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; | |
102 | } | |
103 | } | |
104 | ||
105 | ||
106 | void CWalker::OnShootSuccessful() | |
107 | { | |
108 | currentShootDelay = 0; | |
109 | } | |
110 | ||
111 | void CWalker::OnShootNotSuccessful() | |
112 | { | |
113 | if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; | |
114 | } | |
115 | ||
116 | ||
117 | /* ########################################### | |
118 | JUMPER CLASS EVENTS | |
119 | ############################################### */ | |
120 | ||
121 | ||
122 | CJumper::CJumper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) | |
123 | { | |
124 | inJump = 0; | |
125 | nextShootTime = 0; | |
126 | currentShootDelay = 0; | |
127 | lastShoot = 0; | |
128 | } | |
129 | ||
130 | CJumper::~CJumper() | |
131 | {} | |
132 | ||
133 | void CJumper::OnStart() | |
134 | { | |
135 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
136 | } | |
137 | ||
138 | void CJumper::OnCollision() | |
139 | { | |
140 | short elemx, elemy; | |
141 | short condition; | |
142 | ||
143 | // Is there only a step, so the jumper can jump onto the step (but only when the player | |
144 | // is in this direction) | |
145 | if (status == kMonsterForward) { | |
146 | elemx = (short)((xs + (xe - xs) * 0.5) / kElementSize) +1; | |
147 | condition = FindPlayerX() > 0 && elemx < kLevelWidth; | |
148 | }else{ | |
149 | elemx = (short)((xs + (xe - xs) * 0.5) / kElementSize) -1; | |
150 | condition = FindPlayerX() < 0 && elemx > 0; | |
151 | } | |
152 | elemy = (short)((ys + (ye - ys) * 0.5) / kElementSize) -1; | |
153 | ||
154 | if (condition && elemy >= 0 && gLevel->level[elemy][elemx]->background) | |
155 | Jump(); | |
156 | else if (!inJump) | |
157 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
158 | } | |
159 | ||
160 | void CJumper::OnAbyss() | |
161 | { | |
162 | short condition; | |
163 | ||
164 | // If there's an abyss, the jumper just jumps (only if the player is in the right direction) | |
165 | if (status == kMonsterForward) { | |
166 | condition = FindPlayerX() > 0; | |
167 | }else{ | |
168 | condition = FindPlayerX() < 0; | |
169 | } | |
170 | ||
171 | if (condition) | |
172 | Jump(); | |
173 | else | |
174 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
175 | } | |
176 | ||
177 | void CJumper::OnIdle() | |
178 | { | |
179 | double px = FindPlayerX(); | |
180 | short oldStatus = status; | |
181 | ||
182 | if (!noWeapon && lastTime > nextShootTime) { | |
183 | lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); | |
184 | if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { | |
185 | nextShootTime = lastTime + currentShootDelay; | |
186 | lastShoot = lastTime + kWalkerWaitAfterShooting; | |
187 | } | |
188 | ||
189 | ||
190 | } | |
191 | lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); | |
192 | ||
193 | if (lastTime > lastShoot && lastTime > lastBlessureTime) forceVectorX = speed * deltaTime * gConst->kVelocityUnit * (status == kMonsterForward ? 1.0 : -1.0); | |
194 | } | |
195 | ||
196 | ||
197 | void CJumper::OnTreatment(double directionx, double directiony) | |
198 | { | |
199 | if (ABS(directiony / directionx) > 1.0) { // the bullet comes vertical | |
200 | if (directiony > 0) { | |
201 | if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; | |
202 | } | |
203 | }else{ | |
204 | Jump(); | |
205 | } | |
206 | } | |
207 | ||
208 | void CJumper::OnLanding() | |
209 | { | |
210 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
211 | inJump = 0; | |
212 | } | |
213 | ||
214 | void CJumper::OnShootSuccessful() | |
215 | { | |
216 | currentShootDelay = 0; | |
217 | } | |
218 | ||
219 | void CJumper::OnShootNotSuccessful() | |
220 | { | |
221 | if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; | |
222 | } | |
223 | ||
224 | void CJumper::Jump() | |
225 | { | |
226 | if (!inJump) { | |
227 | forceVectorY = -gConst->kJumperJumpAcceleration * gConst->kVelocityUnit * deltaTime; | |
228 | inJump = 1; | |
229 | } | |
230 | } | |
231 | ||
232 | ||
233 | /* ########################################### | |
234 | FLYER CLASS EVENTS | |
235 | ############################################### */ | |
236 | ||
237 | CFlyer::CFlyer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) | |
238 | { | |
239 | weight = 10; | |
240 | rescueMeX = 0; | |
241 | rescueMeY = 0; | |
242 | weightless = 1; | |
243 | ||
244 | nextShootTime = 0; | |
245 | currentShootDelay = 0; | |
246 | lastShoot = 0; | |
247 | } | |
248 | ||
249 | CFlyer::~CFlyer() | |
250 | {} | |
251 | ||
252 | void CFlyer::OnIdle() | |
253 | { | |
254 | double px = FindPlayerX(); | |
255 | ||
256 | if (!noWeapon && lastTime > nextShootTime) { | |
257 | lookDirection = (FindPlayerX() < 0 ? kLookingLeft : kLookingRight); | |
258 | if (weapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { | |
259 | nextShootTime = lastTime + currentShootDelay; | |
260 | lastShoot = lastTime + kWalkerWaitAfterShooting; | |
261 | } | |
262 | } | |
263 | ||
264 | if (lastTime > lastShoot) { | |
265 | if (!rescueMeX && !rescueMeY) { | |
266 | forceVectorX = speed * deltaTime * gConst->kVelocityUnit * SIGN(FindPlayerX()); | |
267 | forceVectorY = speed * deltaTime * gConst->kVelocityUnit * SIGN(FindPlayerY()); | |
268 | }else{ | |
269 | forceVectorX = rescueMeX * deltaTime; | |
270 | forceVectorY = rescueMeY * deltaTime; | |
271 | rescueMeX = 0; | |
272 | rescueMeY = 0; | |
273 | } | |
274 | } | |
275 | lookDirection = SIGN(forceVectorX); | |
276 | } | |
277 | ||
278 | void CFlyer::OnTreatment(double directionx, double directiony) | |
279 | { | |
280 | double len = sqrt(directionx * directionx + directiony * directiony); | |
281 | ||
282 | rescueMeX = SIGN(directionx) * directiony * speed * gConst->kVelocityUnit / len * 2.0; | |
283 | rescueMeY = SIGN(directiony) * -1.0 * directionx * speed * gConst->kVelocityUnit / len * 2.0; | |
284 | } | |
285 | ||
286 | ||
287 | void CFlyer::OnShootSuccessful() | |
288 | { | |
289 | currentShootDelay = 0; | |
290 | } | |
291 | ||
292 | void CFlyer::OnShootNotSuccessful() | |
293 | { | |
294 | if (currentShootDelay < kMonsterMaxShootDelay) currentShootDelay += kMonsterMaxShootDelay / 4; | |
295 | } | |
296 | ||
297 | void CFlyer::OnKill() | |
298 | { | |
299 | weightless = 0; | |
300 | CMonster::OnKill(); | |
301 | } | |
302 | ||
303 | ||
304 | /* ########################################### | |
305 | WARG CLASS EVENTS | |
306 | ############################################### */ | |
307 | ||
308 | CWarg::CWarg(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : CMonster(initx, inity, width, height, number, monsterInfo) | |
309 | { | |
310 | inJump = 0; | |
311 | if (monsterInfo) OnAllocate(); | |
312 | deathTime = 0; | |
313 | ||
314 | nextShootTime = 0; | |
315 | currentShootDelay = 0; | |
316 | lastShoot = 0; | |
317 | speedup = 1; | |
318 | } | |
319 | ||
320 | void CWarg::OnAllocate() | |
321 | { | |
322 | farWeapon = CreateWeapon(info->weapon + 1); | |
323 | } | |
324 | ||
325 | CWarg::~CWarg() | |
326 | { | |
327 | if (farWeapon) delete farWeapon; | |
328 | } | |
329 | ||
330 | void CWarg::OnStart() | |
331 | { | |
332 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
333 | } | |
334 | ||
335 | void CWarg::OnCollision() | |
336 | { | |
337 | status = (lastCollisionCode & kCollisionOnRight ? kMonsterBackward : kMonsterForward); | |
338 | speedup = 1; | |
339 | } | |
340 | ||
341 | void CWarg::OnAbyss() | |
342 | { | |
343 | status = (status == kMonsterForward ? kMonsterBackward : kMonsterForward); | |
344 | speedup = 1.0; | |
345 | } | |
346 | ||
347 | void CWarg::OnIdle() | |
348 | { | |
349 | double px = FindPlayerX(); | |
350 | CWeapon *currentWeapon; | |
351 | ||
352 | if (!noWeapon && lastTime > nextShootTime) { | |
353 | lookDirection = (px < 0 ? kLookingLeft : kLookingRight); | |
354 | ||
355 | currentWeapon = (ABS(px) > gConst->kWargNearWeaponRadix ? farWeapon : weapon); | |
356 | ||
357 | if (currentWeapon->Shoot(px, FindPlayerY(), (px > 0 ? px + xs : px + xe))) { | |
358 | nextShootTime = lastTime + currentShootDelay; | |
359 | lastShoot = lastTime + kWalkerWaitAfterShooting; | |
360 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
361 | }; | |
362 | } | |
363 | ||
364 | lookDirection = (status == kMonsterBackward ? kLookingLeft : kLookingRight); | |
365 | ||
366 | if (lastTime > lastShoot) forceVectorX = speed * deltaTime * lookDirection * gConst->kVelocityUnit * speedup; | |
367 | } | |
368 | ||
369 | ||
370 | void CWarg::OnTreatment(double directionx, double directiony) | |
371 | { | |
372 | if (ABS(directiony / directionx) > 1.0) { // the bullet comes vertical | |
373 | if (directiony > 0) { | |
374 | if (directionx > 0) status = kMonsterForward; else status = kMonsterBackward; | |
375 | } | |
376 | }else{ | |
377 | Jump(); | |
378 | status = (FindPlayerX() < 0 ? kMonsterBackward : kMonsterForward); | |
379 | } | |
380 | } | |
381 | ||
382 | void CWarg::OnLanding() | |
383 | { | |
384 | inJump = 0; | |
385 | } | |
386 | ||
387 | void CWarg::Jump() | |
388 | { | |
389 | if (!inJump) { | |
390 | forceVectorY = -gConst->kWargJumpAcceleration; | |
391 | inJump = 1; | |
392 | } | |
393 | } | |
394 | ||
395 | // --------------------------------------------- | |
396 | void CWarg::OnDamage(short blessure) | |
397 | // Event occurs, when a monster is hit by something (bullet etc.) | |
398 | { | |
399 | if (dieFrame == -1 && lastBlessureTime < lastTime) { | |
400 | health -= blessure; | |
401 | if (health < 0) { | |
402 | OnKill(); | |
403 | deathTime = lastTime + gConst->kDelayAfterWargDeath; | |
404 | } else { | |
405 | lastBlessureTime = lastTime + gConst->kBlessureInvulnerabilityTime; | |
406 | speedup = gConst->kWargFastSpeedup; | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
411 | void CWarg::TestForDamage(double xb, double yb, short rad, short blessure) | |
412 | { | |
413 | CThing::TestForDamage(xb, yb, rad + dx / 2, blessure); | |
414 | } | |
415 | ||
416 | void CWarg::Render(short planeX, short planeY, tRect *clipRect) | |
417 | { | |
418 | CMonster::Render(planeX, planeY, clipRect); | |
419 | if (deathTime && deathTime < gSystem->GetTicks()) gApplication->command = kCmdNextLevel; | |
420 | } | |
421 | ||
422 | ||
423 | short CWalker::Write(FILE *f) | |
424 | { | |
425 | long size = 0; | |
426 | ||
427 | WRITEDATA(size); | |
428 | WRITEDATA(typeID); | |
429 | WRITEDATA(thingNumber); | |
430 | ||
431 | size += CMonster::Write(f); | |
432 | ||
433 | WRITEDATA(nextShootTime); | |
434 | WRITEDATA(currentShootDelay); | |
435 | WRITEDATA(lastShoot); | |
436 | ||
437 | FINISHWRITE; | |
438 | ||
439 | return size; | |
440 | } | |
441 | ||
442 | void CWalker::Read(FILE *f) | |
443 | { | |
444 | long size = 0; | |
445 | ||
446 | READDATA(size); | |
447 | READDATA(typeID); | |
448 | READDATA(thingNumber); | |
449 | ||
450 | CMonster::Read(f); | |
451 | ||
452 | READDATA(nextShootTime); | |
453 | READDATA(currentShootDelay); | |
454 | READDATA(lastShoot); | |
455 | } | |
456 | ||
457 | ||
458 | short CJumper::Write(FILE *f) | |
459 | { | |
460 | long size = 0; | |
461 | ||
462 | WRITEDATA(size); | |
463 | WRITEDATA(typeID); | |
464 | WRITEDATA(thingNumber); | |
465 | ||
466 | size += CMonster::Write(f); | |
467 | ||
468 | WRITEDATA(nextShootTime); | |
469 | WRITEDATA(currentShootDelay); | |
470 | WRITEDATA(lastShoot); | |
471 | WRITEDATA(inJump); | |
472 | ||
473 | FINISHWRITE; | |
474 | ||
475 | return size; | |
476 | } | |
477 | ||
478 | void CJumper::Read(FILE *f) | |
479 | { | |
480 | long size = 0; | |
481 | ||
482 | READDATA(size); | |
483 | READDATA(typeID); | |
484 | READDATA(thingNumber); | |
485 | ||
486 | CMonster::Read(f); | |
487 | ||
488 | READDATA(nextShootTime); | |
489 | READDATA(currentShootDelay); | |
490 | READDATA(lastShoot); | |
491 | READDATA(inJump); | |
492 | } | |
493 | ||
494 | short CFlyer::Write(FILE *f) | |
495 | { | |
496 | long size = 0; | |
497 | ||
498 | WRITEDATA(size); | |
499 | WRITEDATA(typeID); | |
500 | WRITEDATA(thingNumber); | |
501 | ||
502 | size += CMonster::Write(f); | |
503 | ||
504 | WRITEDATA(nextShootTime); | |
505 | WRITEDATA(currentShootDelay); | |
506 | WRITEDATA(lastShoot); | |
507 | WRITEDATA(rescueMeX); | |
508 | WRITEDATA(rescueMeY); | |
509 | ||
510 | FINISHWRITE; | |
511 | ||
512 | return size; | |
513 | } | |
514 | ||
515 | void CFlyer::Read(FILE *f) | |
516 | { | |
517 | long size = 0; | |
518 | ||
519 | READDATA(size); | |
520 | READDATA(typeID); | |
521 | READDATA(thingNumber); | |
522 | ||
523 | CMonster::Read(f); | |
524 | ||
525 | READDATA(nextShootTime); | |
526 | READDATA(currentShootDelay); | |
527 | READDATA(lastShoot); | |
528 | READDATA(rescueMeX); | |
529 | READDATA(rescueMeY); | |
530 | } | |
531 | ||
532 | ||
533 | short CWarg::Write(FILE *f) | |
534 | { | |
535 | long size = 0; | |
536 | ||
537 | WRITEDATA(size); | |
538 | WRITEDATA(typeID); | |
539 | WRITEDATA(thingNumber); | |
540 | ||
541 | size += CMonster::Write(f); | |
542 | if (farWeapon) size += farWeapon->Write(f); | |
543 | ||
544 | WRITEDATA(nextShootTime); | |
545 | WRITEDATA(currentShootDelay); | |
546 | WRITEDATA(lastShoot); | |
547 | WRITEDATA(inJump); | |
548 | WRITEDATA(speedup); | |
549 | ||
550 | FINISHWRITE; | |
551 | ||
552 | return size; | |
553 | } | |
554 | ||
555 | ||
556 | void CWarg::Read(FILE *f) | |
557 | { | |
558 | long size = 0; | |
559 | ||
560 | READDATA(size); | |
561 | READDATA(typeID); | |
562 | READDATA(thingNumber); | |
563 | ||
564 | CMonster::Read(f); | |
565 | ||
566 | OnAllocate(); | |
567 | ||
568 | if (farWeapon) farWeapon->Read(f); | |
569 | ||
570 | READDATA(nextShootTime); | |
571 | READDATA(currentShootDelay); | |
572 | READDATA(lastShoot); | |
573 | READDATA(inJump); | |
574 | READDATA(speedup); | |
575 | } |
0 | #ifndef __MONSTER_XTRAS__ | |
1 | #define __MONSTER_XTRAS__ | |
2 | ||
3 | #include "Monster.hpp" | |
4 | #include "ObjInfo.hpp" | |
5 | ||
6 | class CCreeper : public CMonster { | |
7 | protected: | |
8 | void OnStart(); | |
9 | void OnCollision(); | |
10 | void OnLanding(); | |
11 | void OnIdle(); | |
12 | void OnAbyss(); | |
13 | ||
14 | public: | |
15 | CCreeper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
16 | ~CCreeper(); | |
17 | }; | |
18 | ||
19 | class CWalker : public CMonster { | |
20 | protected: | |
21 | long nextShootTime; | |
22 | long currentShootDelay; | |
23 | long lastShoot; | |
24 | ||
25 | void OnStart(); | |
26 | void OnCollision(); | |
27 | void OnIdle(); | |
28 | void OnAbyss(); | |
29 | void OnTreatment(double dirx, double diry); | |
30 | ||
31 | public: | |
32 | CWalker(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
33 | ~CWalker(); | |
34 | ||
35 | void OnShootSuccessful(); | |
36 | void OnShootNotSuccessful(); | |
37 | ||
38 | short Write(FILE *f); | |
39 | void Read(FILE *f); | |
40 | }; | |
41 | ||
42 | class CJumper : public CMonster { | |
43 | protected: | |
44 | long nextShootTime; | |
45 | long currentShootDelay; | |
46 | long lastShoot; | |
47 | short inJump; | |
48 | ||
49 | void OnStart(); | |
50 | void OnCollision(); | |
51 | void OnIdle(); | |
52 | void OnAbyss(); | |
53 | void OnTreatment(double dirx, double diry); | |
54 | void OnLanding(); | |
55 | ||
56 | void Jump(); | |
57 | ||
58 | public: | |
59 | CJumper(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
60 | ~CJumper(); | |
61 | ||
62 | void OnShootSuccessful(); | |
63 | void OnShootNotSuccessful(); | |
64 | ||
65 | short Write(FILE *f); | |
66 | void Read(FILE *f); | |
67 | }; | |
68 | ||
69 | ||
70 | class CFlyer : public CMonster { | |
71 | protected: | |
72 | long nextShootTime; | |
73 | long currentShootDelay; | |
74 | long lastShoot; | |
75 | double rescueMeX, rescueMeY; | |
76 | ||
77 | void OnIdle(); | |
78 | void OnTreatment(double dirx, double diry); | |
79 | ||
80 | public: | |
81 | CFlyer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
82 | ~CFlyer(); | |
83 | ||
84 | void OnShootSuccessful(); | |
85 | void OnShootNotSuccessful(); | |
86 | void OnKill(); | |
87 | ||
88 | short Write(FILE *f); | |
89 | void Read(FILE *f); | |
90 | }; | |
91 | ||
92 | class CWarg : public CMonster { | |
93 | protected: | |
94 | CWeapon *farWeapon; | |
95 | long nextShootTime; | |
96 | long currentShootDelay; | |
97 | long lastShoot; | |
98 | short inJump; | |
99 | double speedup; | |
100 | long deathTime; | |
101 | ||
102 | void OnStart(); | |
103 | void OnCollision(); | |
104 | void OnIdle(); | |
105 | void OnAbyss(); | |
106 | void OnTreatment(double dirx, double diry); | |
107 | void OnLanding(); | |
108 | ||
109 | void Jump(); | |
110 | ||
111 | public: | |
112 | CWarg(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
113 | ~CWarg(); | |
114 | ||
115 | void OnAllocate(); | |
116 | ||
117 | void TestForDamage(double xb, double yb, short rad, short blessure); | |
118 | void OnDamage(short blessure); | |
119 | void Render(short planeX, short planeY, tRect *clipRect); | |
120 | ||
121 | short Write(FILE *f); | |
122 | void Read(FILE *f); | |
123 | }; | |
124 | ||
125 | #endif⏎ |
0 | #include "ObjInfo.hpp" | |
1 | #include "Monster.hpp" | |
2 | #include "Monstrxx.hpp" | |
3 | #include "Player.hpp" | |
4 | #include "Item.hpp" | |
5 | #include "ShapeDes.hpp" | |
6 | #include "Appl.hpp" | |
7 | #include "Pltform.hpp" | |
8 | #include "ConstVal.hpp" | |
9 | #include "System.hpp" | |
10 | #include <stdio.h> | |
11 | ||
12 | extern CApplication *gApplication; | |
13 | extern tConstValues *gConst; | |
14 | extern CSystem *gSystem; | |
15 | extern FILE *logFile; | |
16 | ||
17 | short *FindDescriptor(short id); | |
18 | ||
19 | CObjInfo::CObjInfo(short levelNumber) | |
20 | { | |
21 | MSG("LoadMonsters\n"); | |
22 | LoadMonsters(levelNumber); | |
23 | MSG("LoadItems\n"); | |
24 | LoadItems(levelNumber); | |
25 | MSG("LoadWeapons\n"); | |
26 | LoadWeapons(levelNumber); | |
27 | for (short n = 0; n < kNumPlatforms; n ++) platformInfo[n] = new tPlatformInfo; | |
28 | } | |
29 | ||
30 | CObjInfo::~CObjInfo() | |
31 | { | |
32 | short n; | |
33 | ||
34 | ||
35 | for (n = 0; n < kNumMonster; n ++) delete monsterInfo[n]; | |
36 | for (n = 0; n < kNumItems; n ++) delete itemInfo[n]; | |
37 | for (n = 0; n < kNumWeapons; n ++) delete weaponInfo[n]; | |
38 | for (n = 0; n < kNumPlatforms; n ++) delete platformInfo[n]; | |
39 | } | |
40 | ||
41 | ||
42 | void CObjInfo::LoadMonsters(short levelNumber) | |
43 | { | |
44 | if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileMonster))) gSystem->Error("Cannot find file kFileMonster or unable to open it", 0); // by LL | |
45 | SetFilePos(levelNumber * kNumMonster * sizeof(tMonsterInfo)); | |
46 | ||
47 | for (short n = 0; n < kNumMonster; n ++) { | |
48 | monsterInfo[n] = new tMonsterInfo; | |
49 | ReadData(monsterInfo[n], sizeof(tMonsterInfo)); | |
50 | ||
51 | TRANS_PUT_NUM(monsterInfo[n]->canExplode); | |
52 | for (short m = 0; m < 3; m ++) { | |
53 | TRANS_PUT_NUM(monsterInfo[n]->moveShapes[m]); | |
54 | TRANS_PUT_NUM(monsterInfo[n]->additionalData[m]); | |
55 | TRANS_PUT_NUM(monsterInfo[n]->deathShapes[m]); | |
56 | } | |
57 | TRANS_PUT_NUM(monsterInfo[n]->touchBlessure); | |
58 | TRANS_PUT_NUM(monsterInfo[n]->additionalData[0]); | |
59 | TRANS_PUT_NUM(monsterInfo[n]->additionalData[1]); | |
60 | //TRANS_PUT_NUM(monsterInfo[n]->jumpShape); | |
61 | TRANS_PUT_NUM(monsterInfo[n]->attackShape); | |
62 | TRANS_PUT_NUM(monsterInfo[n]->unused); | |
63 | TRANS_PUT_NUM(monsterInfo[n]->kind); | |
64 | TRANS_PUT_NUM(monsterInfo[n]->speed); | |
65 | TRANS_PUT_NUM(monsterInfo[n]->energy); | |
66 | TRANS_PUT_NUM(monsterInfo[n]->weapon); | |
67 | TRANS_PUT_NUM(monsterInfo[n]->aggression); | |
68 | TRANS_PUT_NUM(monsterInfo[n]->invisible); | |
69 | } | |
70 | ||
71 | CloseDataFile(); | |
72 | } | |
73 | ||
74 | ||
75 | void CObjInfo::LoadItems(short levelNumber) | |
76 | { | |
77 | if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileObjects))) gSystem->Error("Cannot find file kFileObjects or uable to open it", 0); // by LL | |
78 | SetFilePos(levelNumber * kNumItems * sizeof(tItemInfo)); | |
79 | ||
80 | for (short n = 0; n < kNumItems; n ++) { | |
81 | itemInfo[n] = new tItemInfo; | |
82 | ReadData(itemInfo[n], sizeof(tItemInfo)); | |
83 | ||
84 | TRANS_PUT_NUM(itemInfo[n]->iconID); | |
85 | TRANS_PUT_NUM(itemInfo[n]->data); | |
86 | TRANS_PUT_NUM(itemInfo[n]->flags); | |
87 | } | |
88 | ||
89 | CloseDataFile(); | |
90 | } | |
91 | ||
92 | void CObjInfo::LoadWeapons(short levelNumber) | |
93 | { | |
94 | if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFileWeapon))) gSystem->Error("Cannot find file kFileWeapon or unable to open it", 0); // by LL | |
95 | ||
96 | SetFilePos(levelNumber * kNumWeapons * sizeof(tWeaponInfo)); | |
97 | ||
98 | for (short n = 0; n < kNumWeapons; n ++) { | |
99 | weaponInfo[n] = new tWeaponInfo; | |
100 | ReadData(weaponInfo[n], sizeof(tWeaponInfo)); | |
101 | ||
102 | TRANS_PUT_NUM(weaponInfo[n]->art); | |
103 | TRANS_PUT_NUM(weaponInfo[n]->projectileShapes[0]); | |
104 | TRANS_PUT_NUM(weaponInfo[n]->projectileShapes[1]); | |
105 | for (short m = 0; m < 5; m ++) { | |
106 | TRANS_PUT_NUM(weaponInfo[n]->detonationShapes[m]); | |
107 | } | |
108 | TRANS_PUT_NUM(weaponInfo[n]->effect); | |
109 | TRANS_PUT_NUM(weaponInfo[n]->speed); | |
110 | TRANS_PUT_NUM(weaponInfo[n]->error); | |
111 | TRANS_PUT_NUM(weaponInfo[n]->repetition); | |
112 | TRANS_PUT_NUM(weaponInfo[n]->munition); | |
113 | TRANS_PUT_NUM(weaponInfo[n]->rad); | |
114 | TRANS_PUT_NUM(weaponInfo[n]->damage); | |
115 | } | |
116 | ||
117 | CloseDataFile(); | |
118 | } | |
119 | ||
120 | void CObjInfo::LoadPlatforms(short levelNumber) | |
121 | { | |
122 | if (!OpenDataFile(gSystem->QualifyDataDir(gConst->kFilePlatform))) gSystem->Error("Cannot find file kFilePlatform or unable to open it", 0); // by LL | |
123 | SetFilePos(levelNumber * kNumPlatforms * sizeof(tPlatformInfo)); | |
124 | ||
125 | for (short n = 0; n < kNumPlatforms; n ++) { | |
126 | ReadData(platformInfo[n], sizeof(tPlatformInfo)); | |
127 | ||
128 | TRANS_PUT_NUM2(platformInfo[n]->ID); | |
129 | TRANS_PUT_NUM2(platformInfo[n]->startx); | |
130 | TRANS_PUT_NUM2(platformInfo[n]->starty); | |
131 | TRANS_PUT_NUM2(platformInfo[n]->endx); | |
132 | TRANS_PUT_NUM2(platformInfo[n]->endy); | |
133 | TRANS_PUT_NUM2(platformInfo[n]->speed); | |
134 | TRANS_PUT_NUM2(platformInfo[n]->delay); | |
135 | TRANS_PUT_NUM2(platformInfo[n]->iconID); | |
136 | TRANS_PUT_NUM2(platformInfo[n]->refNum); | |
137 | ||
138 | //for (short m = 0; m < 8; m ++) TRANS_PUT_NUM2(platformInfo[n]->vars[m]); | |
139 | } | |
140 | } | |
141 | ||
142 | ||
143 | short *FindDescriptor(short id) | |
144 | { | |
145 | short n; | |
146 | for (n = 0; n < kNumShapes && id != kShapeDescriptor[n][0]; n++) {} | |
147 | if (n < kNumShapes) return kShapeDescriptor[n]; | |
148 | else{ | |
149 | for (n = 0; n < kNumTextures && id != kTextureDescriptor[n][0]; n++) {} | |
150 | if (n < kNumTextures) return kTextureDescriptor[n]; else return 0L; | |
151 | } | |
152 | } | |
153 | ||
154 | //----------------------------------------------------------------- | |
155 | CThing *CObjInfo::CreateMonster(short monsterNo, short j, short k) | |
156 | /* In: monsterNo: Number of monster in monster info table | |
157 | j, k: position in level elements | |
158 | Out: new monster object | |
159 | ||
160 | Creates a new monster object at position j, k (in level elements) | |
161 | */ | |
162 | { | |
163 | short *descriptor; | |
164 | ||
165 | if (monsterNo != -1) { | |
166 | descriptor = FindDescriptor(monsterInfo[monsterNo]->moveShapes[0]); | |
167 | ||
168 | switch (monsterInfo[monsterNo]->kind) { | |
169 | case kClassPlayer: return new CPlayer(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
170 | case kClassCreeper: return new CCreeper(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
171 | case kClassWalker: return new CWalker(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
172 | case kClassJumper: return new CJumper(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
173 | case kClassFlyer: return new CFlyer(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
174 | case kClassWarg: return new CWarg(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], monsterNo, monsterInfo[monsterNo]); break; | |
175 | } | |
176 | } | |
177 | return 0L; | |
178 | } | |
179 | ||
180 | //------------------------------------------------------------------ | |
181 | CThing *CObjInfo::CreateItem(short itemNo, short j, short k) | |
182 | /* In: itemNo: Number of item in item info record | |
183 | j, k: position in level elements | |
184 | Out: new item object | |
185 | */ | |
186 | { | |
187 | short *descriptor; | |
188 | ||
189 | if (itemNo >= 0 && itemNo < kNumItems) { | |
190 | descriptor = FindDescriptor(itemInfo[itemNo]->iconID); | |
191 | switch (itemInfo[itemNo]->flags & 3) { | |
192 | case kClassBackgroundItem: return new CBackgroundItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; | |
193 | case kClassUnpassableItem: return new CStaticItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; | |
194 | case kClassMovableItem: return new CMovableItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo]); break; | |
195 | case kClassPortableItem: return new CPortableItem(j * kElementSize + kElementSize / 2, k * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], itemNo, itemInfo[itemNo], itemNo); break; | |
196 | } | |
197 | } | |
198 | return 0L; | |
199 | } | |
200 | ||
201 | void CObjInfo::CreatePlatforms() | |
202 | { | |
203 | short *descriptor; | |
204 | CThing *temp; | |
205 | ||
206 | for (short n = 0; n < kNumPlatforms; n ++) { | |
207 | if (platformInfo[n]->exists) { | |
208 | descriptor = FindDescriptor(platformInfo[n]->iconID); | |
209 | temp = new CPlatform(platformInfo[n]->startx * kElementSize + kElementSize / 2, platformInfo[n]->starty * kElementSize + kElementSize / 2, descriptor[3], descriptor[4], n, platformInfo[n]); | |
210 | gApplication->platformTable[n] = (CPlatform *)temp; | |
211 | }else gApplication->platformTable[n] = 0L; | |
212 | } | |
213 | } | |
214 | ||
215 | short CObjInfo::GetMonsterType(short ref) | |
216 | { | |
217 | return (ref == -1 ? -1 : monsterInfo[ref]->kind); | |
218 | } | |
219 | ||
220 | tItemInfo *CObjInfo::GetItemInfo(short ref) | |
221 | { | |
222 | return (ref == -1 ? 0L : itemInfo[ref]); | |
223 | } | |
224 | ||
225 | tWeaponInfo *CObjInfo::FindWeapon(short ref) | |
226 | { | |
227 | return weaponInfo[ref]; | |
228 | } |
0 | #ifndef __AMP_THINGINFO__ | |
1 | #define __AMP_THINGINFO__ | |
2 | ||
3 | #include "File.hpp" | |
4 | #include "Thing.hpp" | |
5 | ||
6 | const short kNumMonster = 12; | |
7 | const short kNumItems = 42; | |
8 | const short kNumWeapons = 16; | |
9 | const short kNumPlatforms = 10; | |
10 | ||
11 | struct tMonsterInfo { | |
12 | Var2Bytes canExplode; | |
13 | Var2Bytes moveShapes[3]; | |
14 | Var2Bytes touchBlessure; | |
15 | Var2Bytes additionalData[2]; | |
16 | Var2Bytes jumpShape; | |
17 | Var2Bytes attackShape; | |
18 | Var1Byte unused; | |
19 | Var2Bytes deathShapes[3]; | |
20 | ||
21 | Var2Bytes kind; | |
22 | Var2Bytes speed; | |
23 | Var2Bytes energy; | |
24 | Var2Bytes weapon; | |
25 | Var2Bytes aggression; | |
26 | Var2Bytes invisible; | |
27 | }; | |
28 | ||
29 | struct tItemInfo { | |
30 | Var2Bytes iconID; | |
31 | Var2Bytes data; | |
32 | Var2Bytes flags; | |
33 | }; | |
34 | ||
35 | struct tWeaponInfo { | |
36 | Var2Bytes art; | |
37 | Var2Bytes projectileShapes[2]; | |
38 | Var2Bytes detonationShapes[5]; | |
39 | Var2Bytes effect; | |
40 | Var2Bytes speed; | |
41 | Var2Bytes error; | |
42 | Var2Bytes repetition; | |
43 | Var2Bytes munition; | |
44 | Var2Bytes rad; | |
45 | Var2Bytes damage; | |
46 | }; | |
47 | ||
48 | struct tPlatformInfo { | |
49 | Var1Byte exists; | |
50 | Var1Byte isElevator; | |
51 | Var2Bytes ID; | |
52 | Var2Bytes starty; | |
53 | Var2Bytes startx; | |
54 | Var2Bytes endy; | |
55 | Var2Bytes endx; | |
56 | Var2Bytes speed; | |
57 | Var2Bytes delay; | |
58 | Var2Bytes iconID; | |
59 | Var2Bytes refNum; | |
60 | Var1Byte playerControls; | |
61 | Var1Byte stopsAtStart; | |
62 | Var1Byte stopsAtEnd; | |
63 | Var1Byte delaysBeforeStart; | |
64 | Var1Byte hurts; | |
65 | Var1Byte returnsOnHit; | |
66 | Var1Byte activ; | |
67 | Var1Byte unused; | |
68 | }; | |
69 | ||
70 | ||
71 | class CObjInfo : public CFile { | |
72 | protected: | |
73 | void LoadMonsters(short levNum); | |
74 | void LoadItems(short levNum); | |
75 | void LoadWeapons(short levNum); | |
76 | ||
77 | public: | |
78 | ||
79 | tMonsterInfo* monsterInfo[kNumMonster]; | |
80 | tItemInfo* itemInfo[kNumItems]; | |
81 | tWeaponInfo* weaponInfo[kNumWeapons]; | |
82 | ||
83 | tPlatformInfo* platformInfo[kNumPlatforms]; | |
84 | ||
85 | CObjInfo(short levNum); | |
86 | ~CObjInfo(); | |
87 | ||
88 | void LoadPlatforms(short levNum); | |
89 | ||
90 | CThing *CreateMonster(short monsterNum, short j, short k); | |
91 | CThing *CreateItem(short itemNum, short j, short k); | |
92 | ||
93 | void CreatePlatforms(); | |
94 | short GetMonsterType(short ref); | |
95 | tItemInfo *GetItemInfo(short ref); | |
96 | tWeaponInfo *FindWeapon(short ref); | |
97 | }; | |
98 | ||
99 | #endif⏎ |
0 | #include "Object.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | ||
4 | #include <math.h> | |
5 | ||
6 | enum { | |
7 | kLeftTopCorner = 0, | |
8 | kLeftBottomCorner = 1, | |
9 | kRightTopCorner = 2, | |
10 | kRightBottomCorner = 3 | |
11 | }; | |
12 | ||
13 | const double kCollisionThingDetectError = 3.0; | |
14 | ||
15 | extern CApplication *gApplication; | |
16 | extern CSystem *gSystem; | |
17 | extern CLevel *gLevel; | |
18 | extern tConstValues *gConst; | |
19 | ||
20 | CObject::CObject(short initx, short inity, short width, short height) | |
21 | { | |
22 | typeID = 0; | |
23 | typeID |= kObject; | |
24 | ||
25 | xm = initx; | |
26 | ym = inity; | |
27 | xs = xm - width / 2; | |
28 | ys = ym - height / 2; | |
29 | xe = xs + width; | |
30 | ye = ys + height; | |
31 | ||
32 | ||
33 | forceVectorX = forceVectorY = 0; | |
34 | gravitation = 0; | |
35 | environmentForceX = environmentForceY = 0; | |
36 | lastTime = 0; | |
37 | ||
38 | // additinal initializations | |
39 | weight = 0; | |
40 | resForceX = resForceY = 0; | |
41 | deltaTime = 0; | |
42 | background = 0; | |
43 | } | |
44 | ||
45 | CObject::~CObject() | |
46 | {} | |
47 | ||
48 | ||
49 | short CObject::Think() | |
50 | { | |
51 | deltaTime = gApplication->deltaTime; | |
52 | lastTime = gApplication->time; | |
53 | pusher = 0L; | |
54 | environmentForceX = environmentForceY = 0; | |
55 | ||
56 | return kNoEvent; | |
57 | } | |
58 | ||
59 | short CObject::Forces() | |
60 | { | |
61 | resForceX = forceVectorX; | |
62 | resForceY = forceVectorY + gravitation; | |
63 | ||
64 | return kNoEvent; | |
65 | } | |
66 | ||
67 | ||
68 | void CalcSteps(double forcex, double forcey, double &sx, double &sy) | |
69 | { | |
70 | if (ABS(forcex) > ABS(forcey)) { | |
71 | sx += SIGN(forcex); | |
72 | sy += forcey / ABS(forcex); | |
73 | }else{ | |
74 | sy += SIGN(forcey); | |
75 | sx += forcex / ABS(forcey); | |
76 | } | |
77 | } | |
78 | ||
79 | short CObject::ExertForce(double &forcex, double &forcey, short &collisionObject, CObject **obstacle) | |
80 | { | |
81 | double sx = 0, sy = 0; | |
82 | short oldElem1x = -1, elem1x, oldElem1y = -1, elem1y; | |
83 | short oldElem2x = -1, elem2x, oldElem2y = -1, elem2y; | |
84 | short oldElem3x = -1, elem3x, oldElem3y = -1, elem3y; | |
85 | short oldElem4x = -1, elem4x, oldElem4y = -1, elem4y; | |
86 | short resultCode = 0, oldResultCode; | |
87 | double oldForcex = forcex, oldForcey = forcey; | |
88 | tThingList *currentEntry; | |
89 | double postForcex, postForcey; | |
90 | short tmpResultCode; | |
91 | ||
92 | if (obstacle) *obstacle = 0L; | |
93 | if (!forcex && !forcey) return kNoCollision; | |
94 | ||
95 | ||
96 | do { | |
97 | if (xs + sx <= 0) { | |
98 | resultCode |= kCollisionOnLeft; | |
99 | resultCode |= kCollisionWithLevelBorders; | |
100 | } | |
101 | if (xs + sx >= kLevelWidth * kElementSize -1) { | |
102 | resultCode |= kCollisionOnRight; | |
103 | resultCode |= kCollisionWithLevelBorders; | |
104 | } | |
105 | if (ys + sy <= 0) { | |
106 | resultCode |= kCollisionOnTop; | |
107 | resultCode |= kCollisionWithLevelBorders; | |
108 | } | |
109 | ||
110 | postForcex = (ABS(sx) > ABS(forcex) ? forcex : forcex - sx); | |
111 | postForcey = (ABS(sy) > ABS(forcey) ? forcey : forcey - sy); | |
112 | ||
113 | elem1x = (xs + sx) / kElementSize; | |
114 | elem1y = (ys + sy) / kElementSize; | |
115 | if ((elem1x != oldElem1x || elem1y != oldElem1y) && elem1x >= 0 && elem1y >= 0 && elem1x < kLevelWidth && elem1y < kLevelHeight) { | |
116 | resultCode |= gLevel->level[elem1y][elem1x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); | |
117 | oldElem1x = elem1x; | |
118 | oldElem1y = elem1y; | |
119 | } | |
120 | ||
121 | elem2x = (xe + sx) / kElementSize; | |
122 | elem2y = (ys + sy) / kElementSize; | |
123 | if ((elem2x != oldElem2x || elem2y != oldElem2y) && elem2x >= 0 && elem2y >= 0 && elem2x < kLevelWidth && elem2y < kLevelHeight) { | |
124 | resultCode |= gLevel->level[elem2y][elem2x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); | |
125 | oldElem2x = elem2x; | |
126 | oldElem2y = elem2y; | |
127 | } | |
128 | ||
129 | elem3x = (xs + sx) / kElementSize; | |
130 | elem3y = (ye + sy) / kElementSize; | |
131 | if ((elem3x != oldElem3x || elem3y != oldElem3y) && elem3x >= 0 && elem3y >= 0 && elem3x < kLevelWidth && elem3y < kLevelHeight) { | |
132 | resultCode |= gLevel->level[elem3y][elem3x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); | |
133 | oldElem3x = elem3x; | |
134 | oldElem3y = elem3y; | |
135 | } | |
136 | ||
137 | elem4x = (xe + sx) / kElementSize; | |
138 | elem4y = (ye + sy) / kElementSize; | |
139 | if ((elem4x != oldElem4x || elem4y != oldElem4y) && elem4x >= 0 && elem4y >= 0 && elem4x < kLevelWidth && elem4y < kLevelHeight) { | |
140 | resultCode |= gLevel->level[elem4y][elem4x]->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); | |
141 | oldElem4x = elem4x; | |
142 | oldElem4y = elem4y; | |
143 | } | |
144 | ||
145 | currentEntry = gApplication->collisionThingList; | |
146 | while (currentEntry) { | |
147 | oldResultCode = resultCode; | |
148 | tmpResultCode = 0; | |
149 | if (currentEntry->thing != this) tmpResultCode = currentEntry->thing->Collision(this, xs + sx, ys + sy, xe + sx, ye + sy, forcex, forcey, postForcex, postForcey, weight, collisionObject); | |
150 | if (obstacle && tmpResultCode) | |
151 | *obstacle = currentEntry->thing; | |
152 | resultCode |= tmpResultCode; | |
153 | currentEntry = currentEntry->next; | |
154 | } | |
155 | ||
156 | if ((resultCode & kCollisionOnTop) || (resultCode & kCollisionOnBottom)) { | |
157 | if ((resultCode & kCollisionOnLeft) || (resultCode & kCollisionOnRight)) forcex = forcey = 0; | |
158 | } | |
159 | ||
160 | CalcSteps(forcex, forcey, sx, sy); | |
161 | ||
162 | } while ((forcex || forcey) && (ABS(sx) < ABS(forcex) || !forcex) && (ABS(sy) < ABS(forcey) || !forcey)); | |
163 | ||
164 | if (ABS(forcex) > 1.0 && ((resultCode & kCollisionOnLeft) || (resultCode & kCollisionOnRight))) forcex = sx; | |
165 | if (ABS(forcey) > 1.0 && ((resultCode & kCollisionOnTop) || (resultCode & kCollisionOnBottom))) forcey = sy; | |
166 | ||
167 | if ((resultCode & kCollisionOnTop) && forcey < 0) forceVectorY = forcey = 0; | |
168 | if (resultCode & kCollisionOnBottom) forceVectorY = forcey = 0; | |
169 | ||
170 | return resultCode; | |
171 | } | |
172 | ||
173 | void CObject::OnTouch(CObject *touch) {} | |
174 | ||
175 | // Determines if the line a1-a2 intersects with the line b1-b2 where equality does not count | |
176 | short PointIntersection(double a1, double a2, double b1, double b2) | |
177 | { | |
178 | return !((a1 >= b1 && a2 >= b1 && a1 >= b2 && a2 >= b2) || (a1 <= b1 && a2 <= b1 && a1 <= b2 && a2 <= b2)); | |
179 | } | |
180 | ||
181 | // Determines if the line a1-a2 intersects with the line b1-b2 where equality does count | |
182 | short PointTouch(double a1, double a2, double b1, double b2) | |
183 | { | |
184 | return !((a1 > b1 && a2 > b1 && a1 > b2 && a2 > b2) || (a1 < b1 && a2 < b1 && a1 < b2 && a2 < b2)); | |
185 | } | |
186 | ||
187 | ||
188 | short CObject::CollisionPossible(double ptx, double pty) | |
189 | { | |
190 | return (!background && ptx >= xs && ptx < xe && pty >= ys && pty < ye); | |
191 | } | |
192 | ||
193 | short CObject::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double postForcex, double postForcey, short sourceWeight, short &collisionObject) | |
194 | { | |
195 | if (background || (!forcex && !forcey)) return kNoCollision; | |
196 | ||
197 | ||
198 | if (weight < sourceWeight) { | |
199 | short carryx = 0, carryy = 0, collCode = kCollisionWithPushing; | |
200 | double tmpForcex = forcex, tmpForcey = forcey; | |
201 | ||
202 | pusher = sender; | |
203 | sender->OnTouch(this); | |
204 | ||
205 | if (((short)left >= (short)xe - kCollisionThingDetectError && (short)(left + forcex) <= (short)xe) || | |
206 | ((short)right <= (short)xs + kCollisionThingDetectError && (short)(right + forcex + kCollisionThingDetectError) >= (short)xs)) { | |
207 | carryy = 1; forcey = 0; | |
208 | } | |
209 | if ((short)bottom <= (short)ys + kCollisionThingDetectError && (short)(bottom + forcey) >= (short)ys) { | |
210 | carryx = 1; forcex = 0; | |
211 | collCode |= kCollisionOnBottom; | |
212 | } | |
213 | collCode |= ExertForce(forcex, forcey, collisionObject, 0L); | |
214 | environmentForceX = forcex; | |
215 | environmentForceY = forcey; | |
216 | ||
217 | if (carryx) forcex = tmpForcex; | |
218 | if (carryy) forcey = tmpForcey; | |
219 | ||
220 | return collCode; | |
221 | ||
222 | } else { | |
223 | if ((short)right == (short)xs && (PointIntersection(floor(top), floor(bottom), floor(ys), floor(ye) -1) || | |
224 | ((short)top == (short)ys && (short)bottom == (short)ye))) { | |
225 | if (forcex > 0) { | |
226 | forcex = 0; | |
227 | //sender->OnTouch(this); | |
228 | collisionObject = typeID; | |
229 | return kCollisionOnRight; | |
230 | } | |
231 | } | |
232 | ||
233 | if ((short)left == (short)xe -1 && (PointIntersection(floor(top), floor(bottom), floor(ys), floor(ye) -1) || | |
234 | ((short)top == (short)ys && (short)bottom == (short)ye))) { | |
235 | if (forcex < 0) { | |
236 | forcex = 0; | |
237 | //sender->OnTouch(this); | |
238 | collisionObject = typeID; | |
239 | return kCollisionOnLeft; | |
240 | } | |
241 | } | |
242 | ||
243 | if (((short)bottom >= (short)ys && (short)bottom <= (short)ys + 3) && PointIntersection(floor(left), floor(right), floor(xs), floor(xe) -1)) { | |
244 | if (forcey > 0) { | |
245 | forcey = 0; | |
246 | //sender->OnTouch(this); | |
247 | collisionObject = typeID; | |
248 | return kCollisionOnBottom; | |
249 | } | |
250 | } | |
251 | ||
252 | if ((short)top == (short)ye -1 && PointIntersection(floor(left), floor(right), floor(xs), floor(xe) -1)) { | |
253 | if (forcey < 0) { | |
254 | forcey = 0; | |
255 | //sender->OnTouch(this); | |
256 | collisionObject = typeID; | |
257 | return kCollisionOnTop; | |
258 | } | |
259 | } | |
260 | ||
261 | return kNoCollision; | |
262 | } | |
263 | } | |
264 | ||
265 | void CObject::CollisionEvent(double friction, double externForce) | |
266 | { | |
267 | double theorForce; | |
268 | ||
269 | if (forceVectorX) { | |
270 | theorForce = forceVectorX - SIGN(forceVectorX) * friction * deltaTime; | |
271 | if (SIGN(theorForce) != SIGN(forceVectorX)) | |
272 | forceVectorX = 0; | |
273 | else forceVectorX = theorForce; | |
274 | } | |
275 | if (externForce) environmentForceX += externForce * deltaTime * gConst->kVelocityUnit; | |
276 | } | |
277 | ||
278 | ||
279 | ||
280 | short CObject::Write(FILE *f) | |
281 | { | |
282 | long size = 0; | |
283 | ||
284 | WRITEDATA(size); | |
285 | WRITEDATA(typeID); | |
286 | ||
287 | WRITEDATA(xs); | |
288 | WRITEDATA(ys); | |
289 | WRITEDATA(xe); | |
290 | WRITEDATA(ye); | |
291 | WRITEDATA(xm); | |
292 | WRITEDATA(ym); | |
293 | WRITEDATA(weight); | |
294 | WRITEDATA(forceVectorX); | |
295 | WRITEDATA(forceVectorY); | |
296 | WRITEDATA(environmentForceX); | |
297 | WRITEDATA(environmentForceY); | |
298 | WRITEDATA(gravitation); | |
299 | WRITEDATA(resForceX); | |
300 | WRITEDATA(resForceY); | |
301 | ||
302 | WRITEDATA(background); | |
303 | ||
304 | FINISHWRITE; | |
305 | ||
306 | return size; | |
307 | } | |
308 | ||
309 | void CObject::Read(FILE *f) | |
310 | { | |
311 | long size; | |
312 | ||
313 | READDATA(size); | |
314 | READDATA(typeID); | |
315 | ||
316 | READDATA(xs); | |
317 | READDATA(ys); | |
318 | READDATA(xe); | |
319 | READDATA(ye); | |
320 | READDATA(xm); | |
321 | READDATA(ym); | |
322 | READDATA(weight); | |
323 | READDATA(forceVectorX); | |
324 | READDATA(forceVectorY); | |
325 | READDATA(environmentForceX); | |
326 | READDATA(environmentForceY); | |
327 | READDATA(gravitation); | |
328 | READDATA(resForceX); | |
329 | READDATA(resForceY); | |
330 | READDATA(background); | |
331 | } |
0 | #ifndef __AMP_OBJECT__ | |
1 | #define __AMP_OBJECT__ | |
2 | ||
3 | #include "Shape.hpp" | |
4 | ||
5 | class CMonster; | |
6 | class CGuidedBullet; | |
7 | class CSoundSystem; | |
8 | ||
9 | class CObject { | |
10 | friend class CMonster; | |
11 | friend class CGuidedBullet; | |
12 | friend class CSoundSystem; | |
13 | ||
14 | protected: | |
15 | short weight; | |
16 | double forceVectorX, forceVectorY; | |
17 | double environmentForceX, environmentForceY; | |
18 | double gravitation; | |
19 | double resForceX, resForceY; | |
20 | long lastTime, deltaTime; | |
21 | CObject *pusher; | |
22 | ||
23 | public: | |
24 | unsigned long typeID; | |
25 | short background; | |
26 | double xs, ys, xe, ye, xm, ym; | |
27 | ||
28 | CObject(short initx, short inity, short width, short height); | |
29 | ~CObject(); | |
30 | ||
31 | short ExertForce(double &forcex, double &forcey, short &collisionObject, CObject **obstacle); | |
32 | virtual short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
33 | virtual void CollisionEvent(double friction, double externForce); | |
34 | virtual short CollisionPossible(double ptx, double pty); | |
35 | virtual short Think(); | |
36 | virtual short Forces(); | |
37 | ||
38 | virtual void OnTouch(CObject *touch); | |
39 | ||
40 | virtual short Write(FILE *f); | |
41 | virtual void Read(FILE *f); | |
42 | }; | |
43 | ||
44 | ||
45 | #define WRITEDATA(data) fwrite(&data, sizeof(data), 1, f); size += sizeof(data) | |
46 | #define READDATA(data) fread(&data, sizeof(data), 1, f); | |
47 | ||
48 | #define FINISHWRITE fseek(f, -size, SEEK_CUR); fwrite(&size, sizeof(size), 1, f); fseek(f, size - sizeof(size), SEEK_CUR); | |
49 | ||
50 | #endif |
0 | #include "Player.hpp" | |
1 | #include "ShapeDes.hpp" | |
2 | #include "Appl.hpp" | |
3 | #include "ConstVal.hpp" | |
4 | #include "Gui.hpp" | |
5 | #include "Item.hpp" | |
6 | #include "SndSys.hpp" | |
7 | ||
8 | extern CApplication *gApplication; | |
9 | extern CSystem *gSystem; | |
10 | extern CShapeManager *gShapeManager; | |
11 | extern CObjInfo *gObjInfo; | |
12 | extern CLevel *gLevel; | |
13 | extern tConstValues *gConst; | |
14 | extern CGUI *gGUI; | |
15 | extern tConfigData *gConfigData; | |
16 | extern CSoundSystem *gSoundSystem; | |
17 | ||
18 | CPlayer::CPlayer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo) : | |
19 | CMonster(initx, inity, width, height, number, monsterInfo) | |
20 | { | |
21 | short n; | |
22 | ||
23 | typeID |= kPlayer; | |
24 | ||
25 | xs += (dx - gConst->kPlayerWidth) / 2; | |
26 | xe -= (dx - gConst->kPlayerWidth) / 2; | |
27 | ys += 2; | |
28 | ||
29 | weight = 2; | |
30 | jumpTime = LONG_MAX; | |
31 | jumped = 0; | |
32 | ||
33 | for (short m = 0; m < 3; m ++) { | |
34 | playerMoveShapes[0][m] = moveShapes[m]; | |
35 | ||
36 | } | |
37 | attackShapes[0][0] = gShapeManager->FindShape(504, 0); | |
38 | attackShapes[0][1] = attackShapes[0][2] = 0L; | |
39 | jumpShapes[0] = jumpShape; | |
40 | ||
41 | for (n = 1; n < 8; n ++) { | |
42 | for (short m = 0; m < 3; m ++) { | |
43 | playerMoveShapes[n][m] = gShapeManager->FindShape(500 + n * 10 + m, 0); | |
44 | attackShapes[n][m] = gShapeManager->FindShape(504 + n * 10 + m, 0); | |
45 | } | |
46 | jumpShapes[n] = gShapeManager->FindShape(503 + n * 10, 0); | |
47 | } | |
48 | ||
49 | unused = weapon; | |
50 | weapons[0] = new CHandWeapon(this, gObjInfo->FindWeapon(0), attackShapes[0][0], attackShapes[0][1], attackShapes[0][2]); | |
51 | weapons[1] = new CWeapon(this, gObjInfo->FindWeapon(1), attackShapes[1][0]); | |
52 | weapons[2] = new CSorcery(this, gObjInfo->FindWeapon(2), attackShapes[2][0]); | |
53 | weapons[3] = new CWeapon(this, gObjInfo->FindWeapon(3), attackShapes[3][0]); | |
54 | weapons[4] = new CHandWeapon(this, gObjInfo->FindWeapon(4), attackShapes[4][0], attackShapes[4][1], attackShapes[4][2]); | |
55 | weapons[5] = new CMultiBulletWeapon(this, gObjInfo->FindWeapon(5), attackShapes[5][0], gConst->kFirehandAngle); | |
56 | weapons[6] = new CBomb(this, gObjInfo->FindWeapon(6), attackShapes[6][0], attackShapes[3][1]); | |
57 | weapons[7] = new CStaff(this, gObjInfo->FindWeapon(7), attackShapes[7][0], attackShapes[7][1]); | |
58 | weapon = weapons[0]; | |
59 | ||
60 | for (n = 0; n <= 7; n ++) weapons[n]->weaponNumber = n; | |
61 | ||
62 | teleportCounter = -1; | |
63 | lastOxygenDecTime = 0; | |
64 | ||
65 | lastWeaponChanging = 0; // by LL | |
66 | lastActionTime = 0; // by LL | |
67 | // teleportRefNum = 0; ? by LL | |
68 | lastOxygenDecTime = 0; // by LL | |
69 | ||
70 | lastPickupTime = 0; | |
71 | ||
72 | currentWeapon = 0; | |
73 | weapons[0]->weaponStatus = kWeaponReady; | |
74 | oxygen = gConst->kInitialOxygen; | |
75 | } | |
76 | ||
77 | ||
78 | CPlayer::~CPlayer() | |
79 | { | |
80 | for (short n = 1; n < 8; n ++) delete weapons[n]; | |
81 | } | |
82 | ||
83 | short CPlayer::Think() | |
84 | { | |
85 | CElement *element; | |
86 | short action; | |
87 | short liquid; | |
88 | double currentSpeed; | |
89 | ||
90 | CObject::Think(); | |
91 | if (gApplication->firstPlayRound) OnStart(); | |
92 | ||
93 | Gravitation(); | |
94 | ||
95 | element = gLevel->GetElement(xm, ym); | |
96 | if (element) liquid = element->GetElementLiquid(); else liquid = kShapemodusNormal; | |
97 | ||
98 | if (dieFrame == -1) { | |
99 | currentSpeed = (gSystem->KeyPressed(gConfigData->runKey) && lastCollisionCode & kCollisionOnBottom ? info->speed * gConst->kRunScaleFactor : info->speed) * gConst->kVelocityUnit * deltaTime; | |
100 | ||
101 | if (gSystem->KeyPressed(gConfigData->leftKey)) { | |
102 | if (forceVectorX > -currentSpeed) forceVectorX -= gConst->kPlayerAcceleration * deltaTime; | |
103 | lookDirection = kLookingLeft; | |
104 | } | |
105 | if (gSystem->KeyPressed(gConfigData->rightKey)) { | |
106 | if (forceVectorX < currentSpeed) forceVectorX += gConst->kPlayerAcceleration * deltaTime; | |
107 | lookDirection = kLookingRight; | |
108 | } | |
109 | if (gSystem->KeyPressed(gConfigData->jumpKey)) { | |
110 | if (liquid == kShapemodusWater || liquid == kShapemodusLava) { | |
111 | if (forceVectorY > -info->speed * gConst->kVelocityUnit * deltaTime) forceVectorY = -gConst->kPlayerLiquidAccel * deltaTime; | |
112 | if (!gSoundSystem->playerDive->isPlaying()) gSoundSystem->Play(gSoundSystem->playerDive, xm, ym); | |
113 | }else if (jumpTime > lastTime){ | |
114 | forceVectorY = -gConst->kJumpVelocity * gConst->kVelocityUnit * deltaTime; | |
115 | if (!jumped) gSoundSystem->Play(gSoundSystem->playerJump, xm, ym); | |
116 | jumped = 1; | |
117 | } | |
118 | }else jumpTime = 0; | |
119 | ||
120 | if (gSystem->KeyPressed(gConfigData->shootKey)) { | |
121 | weapons[currentWeapon]->Shoot(lookDirection == kLookingRight ? 1 : -1, 0, 0); | |
122 | gGUI->UpdateWeapon(); | |
123 | } | |
124 | if (gSystem->KeyPressed(gConfigData->prevWeaponKey) && lastTime > lastWeaponChanging) { | |
125 | do { | |
126 | currentWeapon ++; | |
127 | if (currentWeapon > 7) currentWeapon = 0; | |
128 | } while (weapons[currentWeapon]->weaponStatus != kWeaponReady); | |
129 | ||
130 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
131 | gGUI->UpdateWeapon(); | |
132 | } | |
133 | ||
134 | if (gSystem->KeyPressed(gConfigData->nextWeaponKey) && lastTime > lastWeaponChanging) { | |
135 | do { | |
136 | currentWeapon --; | |
137 | if (currentWeapon < 0) currentWeapon = 7; | |
138 | } while (weapons[currentWeapon]->weaponStatus != kWeaponReady); | |
139 | ||
140 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
141 | gGUI->UpdateWeapon(); | |
142 | } | |
143 | ||
144 | if (gSystem->KeyPressed(gConfigData->activateKey) && lastActionTime < lastTime) { | |
145 | PerformAction(); | |
146 | lastActionTime = lastTime + gConst->kActionDelayTime; | |
147 | } | |
148 | ||
149 | ||
150 | if (gSystem->KeyPressed(gConfigData->weapon1Key) && weapons[0]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
151 | currentWeapon = 0; | |
152 | gGUI->UpdateWeapon(); | |
153 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
154 | } | |
155 | if (gSystem->KeyPressed(gConfigData->weapon2Key) && weapons[1]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
156 | currentWeapon = 1; | |
157 | gGUI->UpdateWeapon(); | |
158 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
159 | } | |
160 | if (gSystem->KeyPressed(gConfigData->weapon3Key) && weapons[2]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
161 | currentWeapon = 2; | |
162 | gGUI->UpdateWeapon(); | |
163 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
164 | } | |
165 | if (gSystem->KeyPressed(gConfigData->weapon4Key) && weapons[3]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
166 | currentWeapon = 3; | |
167 | gGUI->UpdateWeapon(); | |
168 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
169 | } | |
170 | if (gSystem->KeyPressed(gConfigData->weapon5Key) && weapons[4]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
171 | currentWeapon = 4; | |
172 | gGUI->UpdateWeapon(); | |
173 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
174 | } | |
175 | if (gSystem->KeyPressed(gConfigData->weapon6Key) && weapons[5]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
176 | currentWeapon = 5; | |
177 | gGUI->UpdateWeapon(); | |
178 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
179 | } | |
180 | if (gSystem->KeyPressed(gConfigData->weapon7Key) && weapons[6]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
181 | currentWeapon = 6; | |
182 | gGUI->UpdateWeapon(); | |
183 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
184 | } | |
185 | if (gSystem->KeyPressed(gConfigData->weapon8Key) && weapons[7]->weaponStatus == kWeaponReady && lastTime > lastWeaponChanging) { | |
186 | currentWeapon = 7; | |
187 | gGUI->UpdateWeapon(); | |
188 | lastWeaponChanging = lastTime + gConst->kWeaponChangeTime; | |
189 | } | |
190 | ||
191 | if (liquid == kShapemodusWater || liquid == kShapemodusLava) { | |
192 | oxygen -= gConst->kOxygenDecrease * deltaTime; | |
193 | } | |
194 | if (liquid == kShapemodusLava) OnDamage(gConst->kLavaDamage); | |
195 | } | |
196 | ||
197 | if (liquid == kShapemodusWater || liquid == kShapemodusLava) { | |
198 | forceVectorX *= gConst->kLiquidFriction; | |
199 | forceVectorY *= gConst->kLiquidFriction; | |
200 | } | |
201 | ||
202 | if (element) element->PassiveAction(); | |
203 | ||
204 | return kNoEvent; | |
205 | } | |
206 | ||
207 | // ------------------------------------------------ | |
208 | void CPlayer::PerformAction() | |
209 | // Performs the action which is returned by CElement::Action | |
210 | { | |
211 | short action = 0; | |
212 | CElement *element = gLevel->GetElement(xm, ym); | |
213 | ||
214 | if (element) action = element->Action(); | |
215 | ||
216 | if (action & kTeleportMask) { // Player used a teleporter | |
217 | teleportCounter = 0; | |
218 | teleportRefNum = element->refNum; | |
219 | teleportDeltaTime = lastTime; | |
220 | currentJob = kJobTeleporting; | |
221 | } | |
222 | if (action & kExitMask) gApplication->command = kCmdNextLevel; | |
223 | } | |
224 | ||
225 | short CPlayer::Forces() | |
226 | { | |
227 | short collisionObject, collisionCode; | |
228 | ||
229 | CObject::Forces(); | |
230 | ||
231 | lastCollisionCode = ExertForce(resForceX, resForceY, collisionObject, 0L); | |
232 | if (lastCollisionCode & kCollisionOnBottom) { | |
233 | jumpTime = lastTime + gConst->kJumpAccelerationTime; | |
234 | jumped = 0; | |
235 | } | |
236 | if (lastCollisionCode & kCollisionOnTop) { | |
237 | jumpTime = 0; | |
238 | forceVectorY = 0; | |
239 | } | |
240 | ||
241 | if (lastCollisionCode & (kCollisionOnLeft | kCollisionOnRight)) forceVectorX = 0; | |
242 | ||
243 | return kNoEvent; | |
244 | } | |
245 | ||
246 | void CPlayer::Move() | |
247 | { | |
248 | moveShapes[0] = playerMoveShapes[currentWeapon][0]; | |
249 | moveShapes[1] = playerMoveShapes[currentWeapon][1]; | |
250 | moveShapes[2] = playerMoveShapes[currentWeapon][2]; | |
251 | jumpShape = jumpShapes[currentWeapon]; | |
252 | weapon = weapons[currentWeapon]; | |
253 | ||
254 | CMonster::Move(); | |
255 | } | |
256 | ||
257 | void CPlayer::OnStart() | |
258 | { | |
259 | gGUI->UpdateWeapon(); | |
260 | } | |
261 | ||
262 | // ------------------------------------ | |
263 | void CPlayer::OnTeleport() | |
264 | // Teleport event, sent by CMonster::Render | |
265 | { | |
266 | if (currentJob == kJobTeleporting) { | |
267 | CElement *element = gLevel->FindRefnum(teleportRefNum); | |
268 | ||
269 | if (element) { | |
270 | element->Teleport(xs, ys); | |
271 | xe = xs + dx; ye = ys + dy; | |
272 | } | |
273 | } | |
274 | } | |
275 | ||
276 | void CPlayer::GetItAll() | |
277 | // cheat | |
278 | { | |
279 | int i; | |
280 | ||
281 | for (i = 0; i < 7; ++i) { | |
282 | //if (weapons[i]->weaponStatus != kWeaponReady) currentWeapon = i; | |
283 | weapons[i]->weaponStatus = kWeaponReady; | |
284 | weapons[i]->AddMunition(100); | |
285 | ||
286 | oxygen += 100; | |
287 | oxygen = MIN(oxygen, gConst->kInitialOxygen); | |
288 | ||
289 | health += 100; | |
290 | health = MIN(health, info->energy); | |
291 | } | |
292 | } | |
293 | ||
294 | void CPlayer::OnTouch(CObject *touch) | |
295 | { | |
296 | short value; | |
297 | short what; | |
298 | ||
299 | if (touch->typeID & kPortableItem) { | |
300 | what = ((CPortableItem *)touch)->PickMeUp(value); | |
301 | gSoundSystem->Play(gSoundSystem->playerPickup, xm, ym); | |
302 | switch (what) { | |
303 | case kItemSword: | |
304 | if (weapons[0]->weaponStatus != kWeaponReady) currentWeapon = 0; | |
305 | weapons[0]->weaponStatus = kWeaponReady; | |
306 | weapons[0]->AddMunition(0); | |
307 | break; | |
308 | ||
309 | case kItemPhiol: | |
310 | if (weapons[1]->weaponStatus != kWeaponReady) currentWeapon = 1; | |
311 | weapons[1]->weaponStatus = kWeaponReady; | |
312 | weapons[1]->AddMunition(gObjInfo->GetItemInfo(kItemPhiolmun)->data); | |
313 | break; | |
314 | ||
315 | case kItemSorcery: | |
316 | if (weapons[2]->weaponStatus != kWeaponReady) currentWeapon = 2; | |
317 | weapons[2]->weaponStatus = kWeaponReady; | |
318 | weapons[2]->AddMunition(gObjInfo->GetItemInfo(kItemSorcerymun)->data); | |
319 | break; | |
320 | ||
321 | case kItemBow: | |
322 | if (weapons[3]->weaponStatus != kWeaponReady) currentWeapon = 3; | |
323 | weapons[3]->weaponStatus = kWeaponReady; | |
324 | weapons[3]->AddMunition(gObjInfo->GetItemInfo(kItemBowmun)->data); | |
325 | break; | |
326 | ||
327 | case kItemScie: | |
328 | if (weapons[4]->weaponStatus != kWeaponReady) currentWeapon = 4; | |
329 | weapons[4]->weaponStatus = kWeaponReady; | |
330 | weapons[4]->AddMunition(0); | |
331 | break; | |
332 | ||
333 | case kItemHands: | |
334 | if (weapons[5]->weaponStatus != kWeaponReady) currentWeapon = 5; | |
335 | weapons[5]->weaponStatus = kWeaponReady; | |
336 | weapons[5]->AddMunition(gObjInfo->GetItemInfo(kItemHandsmun)->data); | |
337 | break; | |
338 | ||
339 | case kItemBomb: | |
340 | if (weapons[6]->weaponStatus != kWeaponReady) currentWeapon = 6; | |
341 | weapons[6]->weaponStatus = kWeaponReady; | |
342 | weapons[6]->AddMunition(gObjInfo->GetItemInfo(kItemBombmun)->data); | |
343 | break; | |
344 | ||
345 | case kItemStaff: | |
346 | if (weapons[7]->weaponStatus != kWeaponReady) currentWeapon = 7; | |
347 | weapons[7]->weaponStatus = kWeaponReady; | |
348 | weapons[7]->AddMunition(gObjInfo->GetItemInfo(kItemStaffmun)->data); | |
349 | break; | |
350 | ||
351 | case kItemPhiolmun: | |
352 | weapons[1]->AddMunition(value); | |
353 | break; | |
354 | ||
355 | case kItemSorcerymun: | |
356 | weapons[2]->AddMunition(value); | |
357 | break; | |
358 | ||
359 | case kItemBowmun: | |
360 | weapons[3]->AddMunition(value); | |
361 | break; | |
362 | ||
363 | case kItemSciemun: | |
364 | weapons[4]->AddMunition(value); | |
365 | break; | |
366 | ||
367 | case kItemHandsmun: | |
368 | weapons[5]->AddMunition(value); | |
369 | break; | |
370 | ||
371 | case kItemBombmun: | |
372 | weapons[6]->AddMunition(value); | |
373 | break; | |
374 | ||
375 | case kItemStaffmun: | |
376 | weapons[7]->AddMunition(value); | |
377 | break; | |
378 | ||
379 | case kItemOxygen: | |
380 | oxygen += value; | |
381 | oxygen = MIN(oxygen, gConst->kInitialOxygen); | |
382 | break; | |
383 | ||
384 | case kItemHelppacket: | |
385 | health += value; | |
386 | health = MIN(health, info->energy); | |
387 | break; | |
388 | } | |
389 | lastPickupTime = lastTime + gConst->kPickupTime; | |
390 | gGUI->UpdateWeapon(); | |
391 | gGUI->OnPickUpSomething(what); | |
392 | } | |
393 | } | |
394 | ||
395 | void CPlayer::OnDamage(short blessure) | |
396 | { | |
397 | gSoundSystem->Play(gSoundSystem->firestoneDamage, xm, ym); | |
398 | CMonster::OnDamage(blessure); | |
399 | } | |
400 | ||
401 | void CPlayer::SaveDataToNextLevel(tPlayerData *playerData) | |
402 | { | |
403 | for (short n = 0; n <= 7; n ++) weapons[n]->SaveDataToNextLevel(&(playerData->munition[n]), &(playerData->weaponStatus[n])); | |
404 | ||
405 | playerData->currentWeapon = currentWeapon; | |
406 | playerData->health = health; | |
407 | playerData->oxygen = oxygen; | |
408 | } | |
409 | ||
410 | void CPlayer::RestoreDataFromNextLevel(tPlayerData *savedData) | |
411 | { | |
412 | currentWeapon = savedData->currentWeapon; | |
413 | oxygen = savedData->oxygen; | |
414 | health = savedData->health; | |
415 | for (short n = 0; n <= 7; n ++) { | |
416 | weapons[n]->RestoreDataFromPrevLevel(savedData->munition[n], savedData->weaponStatus[n]); | |
417 | } | |
418 | } | |
419 | ||
420 | CCamera::CCamera(short initx, short inity, short width, short height, short thingNumber) : CThing(initx, inity, width, height, thingNumber) | |
421 | { | |
422 | typeID |= kCamera; | |
423 | ||
424 | weightless = 1; | |
425 | ||
426 | gApplication->Enqueue(&gApplication->thingList, this); | |
427 | gApplication->Enqueue(&gApplication->renderQueue, this); | |
428 | } | |
429 | ||
430 | CCamera::~CCamera() | |
431 | { | |
432 | gApplication->Dequeue(&gApplication->thingList, this); | |
433 | gApplication->Dequeue(&gApplication->renderQueue, this); | |
434 | } | |
435 | ||
436 | short CCamera::Forces() | |
437 | { | |
438 | if (xm < kLevelWidth * kElementSize - kGamePlaneWidth / 2) | |
439 | forceVectorX = gConst->kCameraSpeed * deltaTime * gConst->kVelocityUnit; | |
440 | else forceVectorX = 0; | |
441 | ||
442 | return kNoEvent; | |
443 | } | |
444 | ||
445 | short CCamera::Think() | |
446 | { | |
447 | CElement *element; | |
448 | ||
449 | CObject::Think(); | |
450 | ||
451 | element = gLevel->GetElement(xm, ym); | |
452 | if (element && element->GetElementLiquid() == kShapemodusFog) { | |
453 | currentMessage = gConst->kMonsterNames[element->data -1]; | |
454 | msgY = kGamePlaneHeight; | |
455 | } | |
456 | ||
457 | msgY -= gConst->kMonsterNameSpeed * deltaTime * gConst->kVelocityUnit; | |
458 | ||
459 | return kNoEvent; | |
460 | } | |
461 | ||
462 | void CCamera::Move() | |
463 | { | |
464 | xm += forceVectorX; | |
465 | } | |
466 | ||
467 | void CCamera::Render(short planeX, short planeY, tRect *clipRect) | |
468 | { | |
469 | if (msgY > -kElementSize) gApplication->plane->DrawString(gConst->kMonsterNameX, (short)msgY, currentMessage, kShapemodusNormal); | |
470 | } | |
471 | ||
472 | short CPlayer::Write(FILE *f) | |
473 | { | |
474 | long size = 0; | |
475 | ||
476 | WRITEDATA(size); | |
477 | WRITEDATA(typeID); | |
478 | WRITEDATA(thingNumber); | |
479 | ||
480 | weapon = unused; | |
481 | size += CMonster::Write(f); | |
482 | weapon = unused; | |
483 | ||
484 | for (short n = 0; n < 8; n ++) { | |
485 | size += weapons[n]->Write(f); | |
486 | } | |
487 | ||
488 | WRITEDATA(jumpTime); | |
489 | WRITEDATA(currentWeapon); | |
490 | WRITEDATA(lastWeaponChanging); | |
491 | WRITEDATA(lastPickupTime); | |
492 | WRITEDATA(lastActionTime); | |
493 | WRITEDATA(teleportRefNum); | |
494 | WRITEDATA(currentJob); | |
495 | ||
496 | WRITEDATA(oxygen); | |
497 | WRITEDATA(lastOxygenDecTime); | |
498 | ||
499 | FINISHWRITE; | |
500 | ||
501 | return size; | |
502 | } | |
503 | ||
504 | void CPlayer::Read(FILE *f) | |
505 | { | |
506 | long size = 0; | |
507 | ||
508 | ||
509 | READDATA(size); | |
510 | READDATA(typeID); | |
511 | READDATA(thingNumber); | |
512 | ||
513 | CMonster::Read(f); | |
514 | ||
515 | for (short n = 0; n < 8; n ++) { | |
516 | weapons[n]->Read(f); | |
517 | } | |
518 | ||
519 | READDATA(jumpTime); | |
520 | READDATA(currentWeapon); | |
521 | READDATA(lastWeaponChanging); | |
522 | READDATA(lastPickupTime); | |
523 | READDATA(lastActionTime); | |
524 | READDATA(teleportRefNum); | |
525 | READDATA(currentJob); | |
526 | ||
527 | READDATA(oxygen); | |
528 | READDATA(lastOxygenDecTime); | |
529 | }⏎ |
0 | #ifndef __AMP_PLAYER__ | |
1 | #define __AMP_PLAYER__ | |
2 | ||
3 | #include "Monster.hpp" | |
4 | #include "SoundList.hpp" | |
5 | ||
6 | enum { | |
7 | kJobTeleporting, | |
8 | kJobExiting | |
9 | }; | |
10 | ||
11 | class CGUI; | |
12 | struct tPlayerData; | |
13 | ||
14 | class CPlayer : public CMonster { | |
15 | friend class CGUI; | |
16 | ||
17 | protected: | |
18 | CShape *playerMoveShapes[8][3]; | |
19 | CShape *jumpShapes[8]; | |
20 | CShape *attackShapes[8][3]; | |
21 | ||
22 | CWeapon *weapons[8]; | |
23 | CWeapon *unused; | |
24 | ||
25 | CSound *jumpSound; | |
26 | ||
27 | long jumpTime; | |
28 | short jumped; | |
29 | short currentWeapon; | |
30 | long lastWeaponChanging; | |
31 | long lastPickupTime; | |
32 | long lastActionTime; | |
33 | short teleportRefNum; | |
34 | short currentJob; | |
35 | ||
36 | void PerformAction(); | |
37 | void OnTeleport(); | |
38 | ||
39 | double oxygen; | |
40 | long lastOxygenDecTime; | |
41 | ||
42 | void OnStart(); | |
43 | ||
44 | public: | |
45 | CPlayer(short initx, short inity, short width, short height, short number, tMonsterInfo *monsterInfo); | |
46 | ~CPlayer(); | |
47 | ||
48 | short Forces(); | |
49 | void Move(); | |
50 | short Think(); | |
51 | ||
52 | void OnTouch(CObject *touch); | |
53 | void OnDamage(short blessure); | |
54 | ||
55 | void SaveDataToNextLevel(tPlayerData *); | |
56 | void RestoreDataFromNextLevel(tPlayerData *); | |
57 | ||
58 | short Write(FILE *f); | |
59 | void Read(FILE *f); | |
60 | ||
61 | // cheat | |
62 | void GetItAll(); | |
63 | ||
64 | }; | |
65 | ||
66 | ||
67 | class CCamera : public CThing { | |
68 | private: | |
69 | char *currentMessage; | |
70 | double msgY; | |
71 | ||
72 | public: | |
73 | CCamera(short initx, short inity, short width, short height, short number); | |
74 | ~CCamera(); | |
75 | ||
76 | short Forces(); | |
77 | void Move(); | |
78 | short Think(); | |
79 | void Render(short planeX, short planeY, tRect *clipRect); | |
80 | ||
81 | }; | |
82 | ||
83 | #endif⏎ |
0 | #include "Pltform.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "Player.hpp" | |
3 | #include "ConstVal.hpp" | |
4 | #include "SndSys.hpp" | |
5 | ||
6 | extern CApplication *gApplication; | |
7 | extern CShapeManager *gShapeManager; | |
8 | extern tConstValues *gConst; | |
9 | extern CLevel *gLevel; | |
10 | extern CSoundSystem *gSoundSystem; | |
11 | ||
12 | const short kPlatformCollisionHeight = 30; | |
13 | ||
14 | CPlatform::CPlatform(short initx, short inity, short width, short height, short number, tPlatformInfo *platformInfo) : | |
15 | CThing(initx, inity, width, height, number) | |
16 | { | |
17 | typeID |= kPlatform; | |
18 | LinkInLists(); | |
19 | ||
20 | if (platformInfo) { | |
21 | info = platformInfo; | |
22 | isLocal = 0; | |
23 | weight = SHRT_MAX; | |
24 | background = 0; | |
25 | ||
26 | origHeight = dy; | |
27 | ys = ym - kPlatformCollisionHeight / 2; | |
28 | ye = ym + kPlatformCollisionHeight / 2; | |
29 | dy = kPlatformCollisionHeight; | |
30 | dx -= 1; | |
31 | ye -= 1; | |
32 | ||
33 | OnAllocate(); | |
34 | ||
35 | startx = info->startx * kElementSize; | |
36 | starty = info->starty * kElementSize + (kElementSize - kPlatformCollisionHeight) / 2; | |
37 | endx = info->endx * kElementSize; | |
38 | endy = info->endy * kElementSize + (kElementSize - kPlatformCollisionHeight) / 2; | |
39 | ||
40 | maxDistance = sqrt((endx - startx) * (endx - startx) + (endy - starty) * (endy - starty)); | |
41 | ||
42 | if (info->activ) action = kRunsStartToEnd; else action = kStopsAtStart; | |
43 | }else info = 0L; | |
44 | } | |
45 | ||
46 | void CPlatform::OnAllocate() | |
47 | { | |
48 | shape = gShapeManager->FindShape(info->iconID, 0); | |
49 | } | |
50 | ||
51 | ||
52 | CPlatform::~CPlatform() | |
53 | { | |
54 | if (isLocal) delete info; | |
55 | } | |
56 | ||
57 | void CPlatform::LinkInLists() | |
58 | { | |
59 | gApplication->Enqueue(&gApplication->thingList, this); | |
60 | gApplication->Enqueue(&gApplication->collisionThingList, this); | |
61 | gApplication->Enqueue(&gApplication->renderQueue, this); | |
62 | } | |
63 | ||
64 | void CPlatform::UnlinkInLists() | |
65 | { | |
66 | gApplication->Dequeue(&gApplication->thingList, this); | |
67 | gApplication->Dequeue(&gApplication->collisionThingList, this); | |
68 | gApplication->Dequeue(&gApplication->renderQueue, this); | |
69 | } | |
70 | ||
71 | short CPlatform::Think() | |
72 | { | |
73 | double speedVector, distance; | |
74 | ||
75 | CObject::Think(); | |
76 | ||
77 | switch (action) { | |
78 | ||
79 | case kRunsStartToEnd: | |
80 | distance = sqrt((xs - startx) * (xs - startx) + (ys - starty) * (ys - starty)); | |
81 | ||
82 | if (distance >= maxDistance) { | |
83 | if (info->stopsAtEnd) action = kStopsAtEnd; else action = kDelaysAtEnd; | |
84 | xs = endx; ys = endy; | |
85 | xe = xs + kElementSize -1; ye = ys + kElementSize -1; | |
86 | delayTime = lastTime; | |
87 | gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); | |
88 | }else{ | |
89 | speedVector = info->speed * gConst->kVelocityUnit * deltaTime; | |
90 | forceVectorX = (endx - startx) * speedVector / maxDistance; | |
91 | forceVectorY = (endy - starty) * speedVector / maxDistance; | |
92 | } | |
93 | break; | |
94 | ||
95 | case kRunsEndToStart: | |
96 | distance = sqrt((xs - endx) * (xs - endx) + (ys - endy) * (ys - endy)); | |
97 | ||
98 | if (distance >= maxDistance) { | |
99 | if (info->stopsAtStart) action = kStopsAtStart; else action = kDelaysAtStart; | |
100 | xs = startx; ys = starty; | |
101 | xe = xs + kElementSize -1; ye = ys + kElementSize -1; | |
102 | delayTime = lastTime; | |
103 | gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); | |
104 | }else{ | |
105 | speedVector = info->speed * gConst->kVelocityUnit * deltaTime; | |
106 | forceVectorX = (startx - endx) * speedVector / maxDistance; | |
107 | forceVectorY = (starty - endy) * speedVector / maxDistance; | |
108 | } | |
109 | break; | |
110 | ||
111 | case kDelaysAtStart: | |
112 | if (lastTime - delayTime > info->delay * kTimeFactor) { | |
113 | action = kRunsStartToEnd; | |
114 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
115 | } | |
116 | forceVectorX = forceVectorY = 0; | |
117 | break; | |
118 | ||
119 | case kDelaysAtEnd: | |
120 | if (lastTime - delayTime > info->delay * kTimeFactor) { | |
121 | action = kRunsEndToStart; | |
122 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
123 | } | |
124 | forceVectorX = forceVectorY = 0; | |
125 | break; | |
126 | ||
127 | case kStopsAtStart: | |
128 | case kStopsAtEnd: | |
129 | forceVectorX = forceVectorY = 0; | |
130 | break; | |
131 | } | |
132 | ||
133 | return kNoEvent; | |
134 | } | |
135 | ||
136 | short CPlatform::Forces() | |
137 | { | |
138 | short collisionObject, collisionCode; | |
139 | CObject *collObj; | |
140 | ||
141 | CObject::Forces(); | |
142 | double oldfx = resForceX, oldfy = resForceY; | |
143 | ||
144 | collisionCode = ExertForce(resForceX, resForceY, collisionObject, &collObj); | |
145 | if (!(collisionCode & kCollisionWithPushing)) { | |
146 | if (collisionObject & (kElement | kItem | kPlatform)) { // Platforms can go through level elements | |
147 | resForceX = oldfx; resForceY = oldfy; | |
148 | } | |
149 | }else if (collisionCode & ~kCollisionWithPushing) { | |
150 | action = (action == kRunsStartToEnd ? kRunsEndToStart : kRunsStartToEnd); | |
151 | if (info->returnsOnHit && collObj->typeID & kThing) ((CThing *)collObj)->OnDamage(info->returnsOnHit); | |
152 | ||
153 | } | |
154 | return kNoEvent; | |
155 | } | |
156 | ||
157 | ||
158 | void CPlatform::Render(short planeX, short planeY, tRect *clipRect) | |
159 | { | |
160 | CElement *element = gLevel->GetElement(xm, ym); | |
161 | ||
162 | if (shape) shape->RenderShape(xs - planeX, ym - planeY - origHeight / 2, clipRect, | |
163 | modus, element ? element->brightness : 0, gApplication->plane); | |
164 | } | |
165 | ||
166 | short CPlatform::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
167 | { | |
168 | if (right + 2 < xs || left - 2 > xe || bottom + 2 < ys || top - 2 > ye) return kNoCollision; | |
169 | ||
170 | short returnValue; | |
171 | ||
172 | if ((returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject)) & kCollisionOnBottom) { | |
173 | sender->CollisionEvent(gConst->kNormalFriction, 0); | |
174 | if (info->hurts) ((CThing *)sender)->OnDamage(info->hurts); | |
175 | ||
176 | if ((sender->typeID & kPlayer) && info->playerControls) { | |
177 | if (action == kStopsAtStart) { | |
178 | action = kRunsStartToEnd; | |
179 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
180 | } | |
181 | if (action == kStopsAtEnd) { | |
182 | action = kRunsEndToStart; | |
183 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
184 | } | |
185 | } | |
186 | } | |
187 | return returnValue; | |
188 | } | |
189 | ||
190 | void CPlatform::OnTouch(CObject *touch) | |
191 | { | |
192 | if ((touch->typeID & kThing) && info->hurts) ((CThing *)touch)->OnDamage(info->hurts); | |
193 | } | |
194 | ||
195 | void CPlatform::Switch() | |
196 | { | |
197 | switch (action) { | |
198 | case kRunsStartToEnd: | |
199 | case kDelaysAtStart: | |
200 | action = kStopsAtStart; | |
201 | gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); | |
202 | break; | |
203 | case kRunsEndToStart: | |
204 | case kDelaysAtEnd: | |
205 | action = kStopsAtEnd; | |
206 | gSoundSystem->Play(gSoundSystem->platformStop, xm, ym); | |
207 | break; | |
208 | case kStopsAtStart: | |
209 | action = kRunsStartToEnd; | |
210 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
211 | if (info->refNum > 0) gApplication->platformTable[info->refNum]->Switch(); | |
212 | break; | |
213 | case kStopsAtEnd: | |
214 | action = kRunsEndToStart; | |
215 | gSoundSystem->Play(gSoundSystem->platformGo, xm, ym); | |
216 | if (info->refNum > 0) gApplication->platformTable[info->refNum]->Switch(); | |
217 | break; | |
218 | } | |
219 | } | |
220 | ||
221 | ||
222 | CShape *CPlatform::GetCurrentState(CShape *active, CShape *inactive) | |
223 | { | |
224 | if (action == kStopsAtStart || action == kStopsAtEnd) return inactive; else return active; | |
225 | } | |
226 | ||
227 | ||
228 | ||
229 | short CPlatform::Write(FILE *f) | |
230 | { | |
231 | long size = 0; | |
232 | ||
233 | WRITEDATA(size); | |
234 | WRITEDATA(typeID); | |
235 | WRITEDATA(thingNumber); | |
236 | ||
237 | size += CThing::Write(f); | |
238 | ||
239 | WRITEDATA(origHeight); | |
240 | WRITEDATA(action); | |
241 | WRITEDATA(startx); | |
242 | WRITEDATA(starty); | |
243 | WRITEDATA(endx); | |
244 | WRITEDATA(endy); | |
245 | WRITEDATA(maxDistance); | |
246 | WRITEDATA(delayTime); | |
247 | fwrite(info, sizeof(tPlatformInfo), 1, f); size += sizeof(tPlatformInfo); | |
248 | ||
249 | FINISHWRITE; | |
250 | ||
251 | return size; | |
252 | } | |
253 | ||
254 | void CPlatform::Read(FILE *f) | |
255 | { | |
256 | long size = 0; | |
257 | ||
258 | READDATA(size); | |
259 | READDATA(typeID); | |
260 | READDATA(thingNumber); | |
261 | ||
262 | CThing::Read(f); | |
263 | ||
264 | READDATA(origHeight); | |
265 | READDATA(action); | |
266 | READDATA(startx); | |
267 | READDATA(starty); | |
268 | READDATA(endx); | |
269 | READDATA(endy); | |
270 | READDATA(maxDistance); | |
271 | READDATA(delayTime); | |
272 | ||
273 | isLocal = 1; | |
274 | info = new tPlatformInfo; | |
275 | fread(info, sizeof(tPlatformInfo), 1, f); | |
276 | ||
277 | OnAllocate(); | |
278 | }⏎ |
0 | #ifndef __AMP_PLATTFORMS__ | |
1 | #define __AMP_PLATTFORMS__ | |
2 | ||
3 | #include "Thing.hpp" | |
4 | #include "ObjInfo.hpp" | |
5 | ||
6 | enum { | |
7 | kRunsStartToEnd = 0, | |
8 | kRunsEndToStart, | |
9 | kDelaysAtStart, | |
10 | kDelaysAtEnd, | |
11 | kStopsAtStart, // Platform stopped at start or while running start -> end | |
12 | kStopsAtEnd // Platform stopped at end or while running end -> start | |
13 | }; | |
14 | ||
15 | const short kTimeFactor = 100; | |
16 | ||
17 | class CPlatform : public CThing { | |
18 | protected: | |
19 | tPlatformInfo *info; | |
20 | short isLocal; // whether info is allocated by the platform itself (after loading) or by ObjInfo | |
21 | CShape *shape; | |
22 | ||
23 | short origHeight; | |
24 | ||
25 | short action; | |
26 | double startx, starty; | |
27 | double endx, endy; | |
28 | double maxDistance; | |
29 | long delayTime; | |
30 | ||
31 | public: | |
32 | CPlatform(short initx, short inity, short width, short height, short number, tPlatformInfo *platformInfo); | |
33 | ~CPlatform(); | |
34 | ||
35 | void OnAllocate(); | |
36 | ||
37 | void LinkInLists(); | |
38 | void UnlinkInLists(); | |
39 | short Think(); | |
40 | short Forces(); | |
41 | void Render(short planeX, short planeY, tRect *clipRect); | |
42 | short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
43 | ||
44 | void Switch(); | |
45 | CShape *GetCurrentState(CShape *active, CShape *inactive); | |
46 | void OnTouch(CObject *touch); | |
47 | ||
48 | short Write(FILE *f); | |
49 | void Read(FILE *f); | |
50 | }; | |
51 | ||
52 | #endif |
0 | #include "Shape.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "Clut.hpp" | |
3 | #include <string.h> | |
4 | #include <memory.h> | |
5 | ||
6 | extern CApplication *gApplication; | |
7 | extern CSystem *gSystem; | |
8 | extern CClutManager *gClutManager; | |
9 | extern tConstValues *gConst; | |
10 | extern tConfigData *gConfigData; | |
11 | ||
12 | ||
13 | CShape::CShape(unsigned char *bitmap, short descr[], long width) | |
14 | { | |
15 | this->id = descr[0]; | |
16 | this->dx = descr[3]; | |
17 | this->dy = descr[4]; | |
18 | } | |
19 | ||
20 | CShape::~CShape() | |
21 | { | |
22 | delete [] shapeForward; | |
23 | } | |
24 | ||
25 | unsigned char *CShape::AllowPixelAccess(short &ddx, short &ddy) | |
26 | { | |
27 | ddx = dx; ddy = dy; | |
28 | return shapeForward; | |
29 | } | |
30 | ||
31 | short CShape::RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface) | |
32 | { | |
33 | return dx; | |
34 | } | |
35 | ||
36 | ||
37 | #define kEndShapeToken 0L // the end of shape maker | |
38 | #define kLineStartToken 1L // the line start marker | |
39 | #define kDrawPixelsToken 2L // the draw run marker | |
40 | #define kSkipPixelsToken 3L // the skip pixels marker | |
41 | #define kClearColorIndex 0 // the index of the color defined as clear (in this case, white) | |
42 | #define kFalse 0 | |
43 | #define kTrue 1 | |
44 | ||
45 | CMaskedShape::CMaskedShape(unsigned char *bitmap, short descr[], long width) : CShape(bitmap, descr, width) | |
46 | { | |
47 | shapeForward = new unsigned char [ 8 * dy * dx + 4 * dy + 4 + 8]; | |
48 | Encode(shapeForward, bitmap, descr, width); | |
49 | ||
50 | shapeBackward = new unsigned char [ 8 * dy * dx + 4 * dy + 4 + 8]; | |
51 | Encode(shapeBackward, bitmap, descr, width); | |
52 | } | |
53 | ||
54 | /* Allow unaligned memory access if the architecture supports it (like IA-32) | |
55 | */ | |
56 | #ifdef __OPT_MEM_ACCESS__ | |
57 | ||
58 | #define GET_LONG(adr) *(unsigned long *)adr | |
59 | #define SET_LONG(adr, l) *(unsigned long *)adr = l | |
60 | ||
61 | #else | |
62 | ||
63 | #define GET_LONG(adr) ((long)((unsigned char *)(adr))[0] << 24) + ((long)((unsigned char *)(adr))[1] << 16) + ((long)((unsigned char *)(adr))[2] << 8) + ((long)((unsigned char *)(adr))[3]) | |
64 | #define SET_LONG(adr, l) ((unsigned char *)adr)[0] = (unsigned char)((l) >> 24); \ | |
65 | ((unsigned char *)adr)[1] = (unsigned char)((l) >> 16); \ | |
66 | ((unsigned char *)adr)[2] = (unsigned char)((l) >> 8); \ | |
67 | ((unsigned char *)adr)[3] = (unsigned char)(l) | |
68 | ||
69 | #endif | |
70 | ||
71 | ||
72 | void CMaskedShape::Encode(unsigned char *shape, unsigned char *bitmap, short descr[], long width) | |
73 | { | |
74 | unsigned short shapeHeight; // the height of the shape | |
75 | unsigned short shapeWidth; // the width of the shape | |
76 | unsigned char *destPtr; // the current position in the shape | |
77 | unsigned char *srcPtr; // the current position in the souce graphic data | |
78 | unsigned char *baseAddr; // the base address of the source pixmap | |
79 | unsigned long rowBytes; // the row bytes of the source pixmap | |
80 | unsigned char *rowStart; // the start of the current row in the pixmap | |
81 | unsigned long yCounter; // a counter to scan the shape vertically | |
82 | unsigned long xCounter; // a counter to scan the shape horizontally | |
83 | unsigned char drawRunFlag; // are we in a draw pixels run? | |
84 | unsigned char skipRunFlag; // are we in a skip pixels run? | |
85 | unsigned char *lineStartPtr; // where is the line start token for this line | |
86 | unsigned char *runTokenPtr; // where is the token for the current run | |
87 | unsigned long runCounter; // how long is the current run? | |
88 | long srcStep = (shape == shapeForward ? 1 : -1); | |
89 | ||
90 | // determine the width and height of the shape (we use these values a lot) | |
91 | shapeHeight = dy; | |
92 | shapeWidth = dx; | |
93 | ||
94 | // create a handle big enough for the worst case encoding | |
95 | // ( 8 bytes/pixel + 4 bytes/row + 4 bytes/shape (end token) + 8 bytes/shape (rect) ) | |
96 | ||
97 | ||
98 | // lock the handle and get the pointer | |
99 | destPtr = shape; | |
100 | ||
101 | // store the shape rect | |
102 | ((short *)destPtr)[0] = 0; | |
103 | ((short *)destPtr)[1] = 0; | |
104 | ((short *)destPtr)[2] = dx; | |
105 | ((short *)destPtr)[3] = dy; | |
106 | destPtr += 8; | |
107 | ||
108 | // get the location of the source data | |
109 | baseAddr = bitmap; | |
110 | rowBytes = width; | |
111 | rowStart = baseAddr + rowBytes * descr[2] + descr[1] + (shape == shapeForward ? 0 : dx); | |
112 | ||
113 | // scan the shape row by row | |
114 | for( yCounter = 0; yCounter < shapeHeight; yCounter++ ) | |
115 | { | |
116 | // store the location of this line start | |
117 | lineStartPtr = destPtr; | |
118 | destPtr += sizeof( unsigned long ); | |
119 | ||
120 | // at the beginning of each row we are not in any run | |
121 | drawRunFlag = kFalse; | |
122 | skipRunFlag = kFalse; | |
123 | ||
124 | // move to the start of the row | |
125 | srcPtr = rowStart; | |
126 | ||
127 | // scan each row of the shape | |
128 | for( xCounter = 0; xCounter < shapeWidth; xCounter++ ) { | |
129 | // is this pixel clear? | |
130 | if ( *srcPtr == kClearColorIndex ) { | |
131 | // are we in a draw run? | |
132 | if ( drawRunFlag ) { | |
133 | // end the draw run | |
134 | drawRunFlag = kFalse; | |
135 | ||
136 | // create the draw token | |
137 | SET_LONG(runTokenPtr, ( kDrawPixelsToken << 24 ) + runCounter); | |
138 | ||
139 | // pad to a mulitple of four | |
140 | SET_LONG(destPtr ,0L); | |
141 | destPtr += ( ( runCounter & 3L ) == 0 ) ? 0 : ( 4 - ( runCounter & 3L ) ); | |
142 | } | |
143 | ||
144 | // are we in a skip run | |
145 | if ( skipRunFlag ) { | |
146 | // continue it | |
147 | runCounter++; | |
148 | } else { | |
149 | // start one | |
150 | skipRunFlag = kTrue; | |
151 | runCounter = 1; | |
152 | } | |
153 | } else { | |
154 | // are we in a skip run | |
155 | if ( skipRunFlag ) { | |
156 | // end the skip run | |
157 | skipRunFlag = kFalse; | |
158 | ||
159 | // create the skip token | |
160 | //*( ( unsigned long * )destPtr ) = ( kSkipPixelsToken << 24 ) + runCounter; | |
161 | SET_LONG(destPtr, ( kSkipPixelsToken << 24 ) + runCounter); | |
162 | destPtr += sizeof( unsigned long ); | |
163 | } | |
164 | ||
165 | // are we in a draw run | |
166 | if ( drawRunFlag ) { | |
167 | // continue it | |
168 | runCounter++; | |
169 | ||
170 | // copy the pixel | |
171 | *destPtr = *srcPtr; | |
172 | ||
173 | destPtr++; | |
174 | } else { | |
175 | // start one | |
176 | drawRunFlag = kTrue; | |
177 | runCounter = 1; | |
178 | ||
179 | // save the location of the token (so we can fill it in later) | |
180 | runTokenPtr = destPtr; | |
181 | destPtr += sizeof( unsigned long ); | |
182 | ||
183 | // copy the pixel | |
184 | *destPtr = *srcPtr; | |
185 | ||
186 | destPtr++; | |
187 | } | |
188 | } | |
189 | ||
190 | // move to the next byte | |
191 | srcPtr += srcStep; | |
192 | } | |
193 | ||
194 | // are we in a draw run | |
195 | if( drawRunFlag ) | |
196 | { | |
197 | // end the draw run | |
198 | drawRunFlag = kFalse; | |
199 | ||
200 | // create the draw token | |
201 | SET_LONG(runTokenPtr, ( kDrawPixelsToken << 24 ) + runCounter); | |
202 | ||
203 | // pad to a mulitple of four | |
204 | SET_LONG(destPtr, 0L); | |
205 | destPtr += ( ( runCounter & 3L ) == 0 ) ? 0 : ( 4 - ( runCounter & 3L ) ); | |
206 | } | |
207 | ||
208 | // create the line start token | |
209 | SET_LONG(lineStartPtr, ( kLineStartToken << 24 ) + ( destPtr - ( lineStartPtr + 4 ) )); | |
210 | ||
211 | // move the row start to the next row | |
212 | rowStart += rowBytes; | |
213 | } | |
214 | ||
215 | // create the end of shape token | |
216 | SET_LONG(destPtr, kEndShapeToken << 24); | |
217 | destPtr += sizeof( unsigned long ); | |
218 | ||
219 | // Resize the handle to match the real size of the shape | |
220 | //SetHandleSize( shapeHandle, destPtr - ( unsigned char * )( *shapeHandle ) ); | |
221 | } | |
222 | ||
223 | ||
224 | ||
225 | CMaskedShape::~CMaskedShape() | |
226 | { | |
227 | delete [] shapeBackward; | |
228 | } | |
229 | ||
230 | short CMaskedShape::RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface) | |
231 | { | |
232 | if (clipRect->left > x || clipRect->top > y || clipRect->right < x + dx || clipRect->bottom < y + dy) | |
233 | RenderShapeClipped(x, y, clipRect, modus, percentage, surface); | |
234 | else RenderShapeUnclipped(x, y, modus, percentage, surface); | |
235 | ||
236 | return dx; | |
237 | } | |
238 | ||
239 | void CMaskedShape::RenderShapeClipped(short x, short y, tRect *sClipRect, short modus, short percentage, CGraphicSurface *surface) | |
240 | { | |
241 | tRect clipRect; // the rect that defines the clipped shape | |
242 | short pitch; | |
243 | unsigned char *rowStart; // the pointer to the start of this row | |
244 | unsigned char *srcPtr; // the current position in the sprite data | |
245 | unsigned char *destPtr; // the current position in the destination pixmap | |
246 | long miscCounter; // a counter for various purposes | |
247 | long extraCounter; // a counter for right clippling purposes ( how much extra was there? ) | |
248 | unsigned long tokenOp; // the op code from the token | |
249 | unsigned long tokenData; // the data from the token | |
250 | unsigned char exitFlag; // should we exit from the loop? | |
251 | long yCount; // how many lines down in the shape are we? | |
252 | long xCount; // where are we in this line? | |
253 | unsigned char *shape = (modus & kShapemodusBackwardFlag ? shapeBackward : shapeForward); | |
254 | ||
255 | modus &= ~kShapemodusBackwardFlag; // clearing the direction flag | |
256 | ||
257 | ||
258 | // create a clipped rect in the coordinates of the sprite | |
259 | clipRect.left = x < sClipRect->left ? sClipRect->left - x : 0; | |
260 | clipRect.right = x + dx > sClipRect->right ? sClipRect->right - x : dx; | |
261 | clipRect.top = y < sClipRect->top ? sClipRect->top - y : 0; | |
262 | clipRect.bottom = y + dy > sClipRect->bottom ? sClipRect->bottom - y : dy; | |
263 | ||
264 | // set up the counters | |
265 | yCount = 0; | |
266 | xCount = 0; | |
267 | // determine characteristics about the pixmap | |
268 | ||
269 | rowStart = surface->GetSurfacePtr(&pitch); | |
270 | rowStart += y * pitch + x; | |
271 | ||
272 | // move to the right place in the shape ( just past the size rect ) | |
273 | srcPtr = shape + 8; | |
274 | ||
275 | // loop until we are done | |
276 | exitFlag = kFalse; | |
277 | while( !exitFlag ) | |
278 | { | |
279 | // get a token | |
280 | tokenOp = GET_LONG(srcPtr ) >> 24; | |
281 | tokenData = GET_LONG(srcPtr ) & 0x00ffffff; | |
282 | srcPtr += sizeof( unsigned long ); | |
283 | ||
284 | // depending on the token | |
285 | switch( tokenOp ) | |
286 | { | |
287 | case kDrawPixelsToken: | |
288 | miscCounter = tokenData; | |
289 | extraCounter = 0; | |
290 | ||
291 | // if we need to, clip to the left | |
292 | if( xCount < clipRect.left ) | |
293 | { | |
294 | // if this run does not appear at all, don't draw it | |
295 | if ( miscCounter < clipRect.left - xCount ) | |
296 | { | |
297 | destPtr += miscCounter; | |
298 | srcPtr += miscCounter; | |
299 | srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); | |
300 | xCount += miscCounter; | |
301 | break; | |
302 | } | |
303 | else | |
304 | { | |
305 | // if it does, skip to where we can draw | |
306 | miscCounter -= clipRect.left - xCount; | |
307 | destPtr += (clipRect.left - xCount); | |
308 | srcPtr += (clipRect.left - xCount); | |
309 | xCount += clipRect.left - xCount; | |
310 | } | |
311 | } | |
312 | ||
313 | // if we need to, clip to the right | |
314 | if ( xCount + miscCounter > clipRect.right ) | |
315 | { | |
316 | // if this run does not appear at all, skip it | |
317 | if ( xCount > clipRect.right ) | |
318 | { | |
319 | destPtr += miscCounter; | |
320 | srcPtr += miscCounter; | |
321 | srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); | |
322 | xCount += miscCounter; | |
323 | break; | |
324 | } | |
325 | else | |
326 | { | |
327 | // if it does, setup to draw what we can | |
328 | extraCounter = miscCounter; | |
329 | miscCounter -= ( xCount + miscCounter ) - clipRect.right; | |
330 | extraCounter -= miscCounter; | |
331 | } | |
332 | } | |
333 | ||
334 | // adjust xCount for the run | |
335 | xCount += miscCounter; | |
336 | ||
337 | if (gConfigData->disableShapeModes) { | |
338 | while (miscCounter) | |
339 | { | |
340 | *(unsigned char *)destPtr = *(unsigned char *)srcPtr; | |
341 | destPtr += sizeof( unsigned char ); | |
342 | srcPtr += sizeof( unsigned char ); | |
343 | miscCounter -= sizeof( unsigned char ); | |
344 | } | |
345 | }else{ | |
346 | while (miscCounter) | |
347 | { | |
348 | gClutManager->SetPixel((unsigned char *)srcPtr, (unsigned char *)destPtr, modus, percentage); | |
349 | destPtr += sizeof( unsigned char ); | |
350 | srcPtr += sizeof( unsigned char ); | |
351 | miscCounter -= sizeof( unsigned char ); | |
352 | } | |
353 | } | |
354 | ||
355 | ||
356 | // adjust for right clipping | |
357 | destPtr += extraCounter; | |
358 | srcPtr += extraCounter; | |
359 | xCount += extraCounter; | |
360 | ||
361 | // adjust for the padding | |
362 | srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); | |
363 | break; | |
364 | ||
365 | case kSkipPixelsToken: | |
366 | destPtr += tokenData; | |
367 | xCount += tokenData; | |
368 | break; | |
369 | ||
370 | case kLineStartToken: | |
371 | // if this line is above the clip rect, skip to the next line | |
372 | if( yCount < clipRect.top ) | |
373 | { | |
374 | srcPtr += tokenData; | |
375 | } | |
376 | ||
377 | // set up the destination pointer | |
378 | destPtr = rowStart; | |
379 | rowStart += pitch; | |
380 | ||
381 | // move the yCounter | |
382 | yCount++; | |
383 | ||
384 | // reset the xCounter | |
385 | xCount = 0; | |
386 | ||
387 | // if we have hit the bottom clip, exit the loop | |
388 | if ( yCount > clipRect.bottom ) | |
389 | { | |
390 | exitFlag = kTrue; | |
391 | } | |
392 | break; | |
393 | ||
394 | case kEndShapeToken: | |
395 | // signal a loop exit | |
396 | exitFlag = kTrue; | |
397 | break; | |
398 | ||
399 | default: | |
400 | // we should never get here | |
401 | break; | |
402 | } | |
403 | } | |
404 | surface->ReleaseSurface(); | |
405 | } | |
406 | ||
407 | ||
408 | ||
409 | void CMaskedShape::RenderShapeUnclipped(short x, short y, short modus, short percentage, CGraphicSurface *surface) | |
410 | { | |
411 | short pitch; | |
412 | unsigned char *rowStart; // the pointer to the start of this row | |
413 | unsigned char *srcPtr; // the current position in the sprite data | |
414 | unsigned char *destPtr; // the current position in the destination pixmap | |
415 | long miscCounter; // a counter for various purposes | |
416 | unsigned long tokenOp; // the op code from the token | |
417 | unsigned long tokenData; // the data from the token | |
418 | unsigned char exitFlag; // should we exit from the loop? | |
419 | unsigned char *shape = (modus & kShapemodusBackwardFlag ? shapeBackward : shapeForward); | |
420 | ||
421 | modus &= ~kShapemodusBackwardFlag; // clearing the direction flag | |
422 | ||
423 | // determine characteristics about the pixmap | |
424 | rowStart = surface->GetSurfacePtr(&pitch); | |
425 | rowStart += y * pitch + x; | |
426 | ||
427 | // move to the right place in the shape ( just past the size rect ) | |
428 | srcPtr = shape + 8; | |
429 | ||
430 | // loop until we are done | |
431 | exitFlag = kFalse; | |
432 | while( !exitFlag ) | |
433 | { | |
434 | // get a token | |
435 | tokenOp = GET_LONG(srcPtr) >> 24; | |
436 | tokenData = GET_LONG(srcPtr) & 0x00ffffff; | |
437 | srcPtr += sizeof( unsigned long ); | |
438 | ||
439 | // depending on the token | |
440 | switch( tokenOp ) | |
441 | { | |
442 | case kDrawPixelsToken: | |
443 | miscCounter = tokenData; | |
444 | ||
445 | ||
446 | if (gConfigData->disableShapeModes) { | |
447 | while (miscCounter) | |
448 | { | |
449 | *(unsigned char *)destPtr = *(unsigned char *)srcPtr; | |
450 | destPtr += sizeof( unsigned char ); | |
451 | srcPtr += sizeof( unsigned char ); | |
452 | miscCounter -= sizeof( unsigned char ); | |
453 | } | |
454 | }else{ | |
455 | while (miscCounter) | |
456 | { | |
457 | gClutManager->SetPixel((unsigned char *)srcPtr, (unsigned char *)destPtr, modus, percentage); | |
458 | destPtr += sizeof( unsigned char ); | |
459 | srcPtr += sizeof( unsigned char ); | |
460 | miscCounter -= sizeof( unsigned char ); | |
461 | } | |
462 | } | |
463 | ||
464 | ||
465 | // adjust for the padding | |
466 | srcPtr += ( ( tokenData & 3L ) == 0 ) ? 0 : ( 4 - ( tokenData & 3L ) ); | |
467 | break; | |
468 | ||
469 | case kSkipPixelsToken: | |
470 | destPtr += tokenData; | |
471 | break; | |
472 | ||
473 | case kLineStartToken: | |
474 | // set up the destination pointer | |
475 | destPtr = rowStart; | |
476 | rowStart += pitch; | |
477 | break; | |
478 | ||
479 | case kEndShapeToken: | |
480 | // signal a loop exit | |
481 | exitFlag = kTrue; | |
482 | break; | |
483 | ||
484 | default: | |
485 | // we should never get here | |
486 | break; | |
487 | } | |
488 | } | |
489 | ||
490 | surface->ReleaseSurface(); | |
491 | } | |
492 | ||
493 | ||
494 | ||
495 | ||
496 | CTexture::CTexture(unsigned char *bitmap, short descr[], long width, short light) : CShape(bitmap, descr, width) | |
497 | { | |
498 | short j, k; | |
499 | unsigned char *shapePtr; | |
500 | short size = dx * dy; | |
501 | ||
502 | shapeForward = new unsigned char[size]; | |
503 | ||
504 | bitmap = (unsigned char *)((unsigned long)bitmap + descr[2] * width + descr[1]); | |
505 | shapePtr = shapeForward; | |
506 | ||
507 | for (j = 0; j < dy; j ++) { | |
508 | for (k = 0; k < dx; k ++) { | |
509 | gClutManager->SetPixel(&(bitmap[k]), &(shapePtr[k]), kShapemodusNormal, light); | |
510 | } | |
511 | bitmap += width; | |
512 | shapePtr += dx; | |
513 | } | |
514 | } | |
515 | ||
516 | ||
517 | CTexture::~CTexture() | |
518 | { | |
519 | } | |
520 | ||
521 | ||
522 | short CTexture::RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface) | |
523 | { | |
524 | unsigned char *startDestPtr, *startSourcePtr, *tmpSourcePtr, *tmpDestPtr; | |
525 | short pitch, startX, startY, clipWidth, clipHeight, tmpWidth; | |
526 | ||
527 | startDestPtr = surface->GetSurfacePtr(&pitch); | |
528 | startDestPtr += MAX(y, clipRect->top) * pitch + MAX(x, clipRect->left); | |
529 | ||
530 | startY = clipRect->top > y ? clipRect->top - y : 0; | |
531 | startX = clipRect->left > x ? clipRect->left - x : 0; | |
532 | startSourcePtr = shapeForward + startY * dx + startX; | |
533 | ||
534 | clipWidth = (clipRect->right < x + dx ? clipRect->right - x : dx) - startX; | |
535 | clipHeight = (clipRect->bottom < y + dy ? clipRect->bottom - y : dy) - startY; | |
536 | ||
537 | if (clipWidth > 0 && clipHeight > 0) { | |
538 | for (short j = 0; j < clipHeight; j ++) { | |
539 | memcpy(startDestPtr, startSourcePtr, clipWidth); | |
540 | startSourcePtr += dx; | |
541 | startDestPtr += pitch; | |
542 | } | |
543 | } | |
544 | surface->ReleaseSurface(); | |
545 | ||
546 | return dx; | |
547 | } | |
548 | ||
549 | ||
550 | CBackground::CBackground(unsigned char *bitmap, short descr[], long width) : CShape(bitmap, descr, width) | |
551 | { | |
552 | shapeForward = bitmap; | |
553 | ||
554 | // For background shapes, descr[1] and descr[2] are the width and height of the background picture | |
555 | shapeWidth = descr[1]; | |
556 | shapeHeight = descr[2]; | |
557 | } | |
558 | ||
559 | CBackground::~CBackground() | |
560 | {} | |
561 | ||
562 | short CBackground::RenderShape(short x, short y, tRect *clipRect, short bkgndCoordX, short unused2, CGraphicSurface *surface) | |
563 | { | |
564 | unsigned char *startDestPtr, *startSourcePtr, *tmpSourcePtr, *tmpDestPtr; | |
565 | short pitch, startX, startY, clipWidth, clipHeight, tmpWidth; | |
566 | short bkgndPictCoordX = bkgndCoordX % shapeWidth; | |
567 | short n; | |
568 | ||
569 | startDestPtr = surface->GetSurfacePtr(&pitch); | |
570 | startDestPtr += MAX(y, clipRect->top) * pitch + MAX(x, clipRect->left); | |
571 | ||
572 | startY = MAX(clipRect->top, y); | |
573 | startX = (bkgndPictCoordX + MAX(x, clipRect->left)) % shapeWidth; | |
574 | startSourcePtr = shapeForward + MAX(y, clipRect->top) * shapeWidth; | |
575 | ||
576 | clipWidth = (clipRect->right < x + dx ? clipRect->right : x + dx) - MAX(x, clipRect->left); | |
577 | clipHeight = (clipRect->bottom < y + dy ? clipRect->bottom : y + dy) - startY; | |
578 | ||
579 | for (short j = 0; j < clipHeight; j ++) { | |
580 | tmpWidth = clipWidth; | |
581 | tmpDestPtr = startDestPtr; | |
582 | ||
583 | if (startX + tmpWidth >= shapeWidth) { | |
584 | for (n = 0; n < tmpWidth; n ++) { | |
585 | startDestPtr[n] = startSourcePtr[(startX + n) % shapeWidth]; | |
586 | } | |
587 | }else{ | |
588 | tmpSourcePtr = startSourcePtr + startX; | |
589 | memcpy(tmpDestPtr, tmpSourcePtr, tmpWidth); | |
590 | } | |
591 | startSourcePtr += shapeWidth; | |
592 | startDestPtr += pitch; | |
593 | } | |
594 | ||
595 | surface->ReleaseSurface(); | |
596 | ||
597 | return dx; | |
598 | } |
0 | #ifndef __AMP_SHAPES__ | |
1 | #define __AMP_SHAPES__ | |
2 | ||
3 | #include "AmpHead.hpp" | |
4 | #include "Surface.hpp" | |
5 | ||
6 | class CShape { | |
7 | protected: | |
8 | short id; | |
9 | short dx, dy; | |
10 | unsigned char *shapeForward; | |
11 | ||
12 | public: | |
13 | long ID; | |
14 | long savedID; | |
15 | ||
16 | CShape(unsigned char *, short [], long); | |
17 | ~CShape(); | |
18 | ||
19 | virtual short RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); | |
20 | unsigned char *AllowPixelAccess(short &dx, short &dy); | |
21 | }; | |
22 | ||
23 | class CMaskedShape : public CShape { | |
24 | protected: | |
25 | unsigned char *shapeBackward; | |
26 | ||
27 | void Encode(unsigned char *, unsigned char *, short [], long); | |
28 | void RenderShapeClipped(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); | |
29 | void RenderShapeUnclipped(short x, short y, short modus, short percentage, CGraphicSurface *surface); | |
30 | ||
31 | public: | |
32 | CMaskedShape(unsigned char *, short [], long); | |
33 | ~CMaskedShape(); | |
34 | ||
35 | short RenderShape(short x, short y, tRect *clipRect, short modus, short percentage, CGraphicSurface *surface); | |
36 | }; | |
37 | ||
38 | class CTexture : public CShape { | |
39 | protected: | |
40 | ||
41 | public: | |
42 | CTexture(unsigned char *, short [], long, short light); | |
43 | ~CTexture(); | |
44 | ||
45 | short RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface); | |
46 | }; | |
47 | ||
48 | ||
49 | class CBackground : public CShape { | |
50 | protected: | |
51 | short shapeWidth, shapeHeight; | |
52 | ||
53 | public: | |
54 | CBackground(unsigned char *, short [], long); | |
55 | ~CBackground(); | |
56 | ||
57 | short RenderShape(short x, short y, tRect *clipRect, short unused, short unused2, CGraphicSurface *surface); | |
58 | }; | |
59 | ||
60 | #endif |
0 | #ifndef __AMP_SHAPEDESCRIPTOR__ | |
1 | #define __AMP_SHAPEDESCRIPTOR__ | |
2 | ||
3 | #include "ShapeLd.hpp" | |
4 | ||
5 | static short kShapeDescriptor[kNumShapes][5] = { // Items | |
6 | ||
7 | // ID x y dx dy | |
8 | //--------------------- | |
9 | {4100, 0, 576, 32, 32}, // Schwert | |
10 | {4101, 32, 576, 32, 32}, // Phiole | |
11 | {4102, 64, 576, 32, 32}, | |
12 | {4103, 96, 576, 32, 32}, | |
13 | {4104, 128, 576, 32, 32}, | |
14 | {4105, 160, 576, 32, 32}, | |
15 | {4106, 192, 576, 32, 32}, | |
16 | {4107, 224, 576, 32, 32}, | |
17 | {4110, 0, 608, 32, 32}, // Munition | |
18 | {4111, 32, 608, 32, 32}, | |
19 | {4112, 64, 608, 32, 32}, | |
20 | {4113, 96, 608, 32, 32}, | |
21 | {4114, 128, 608, 32, 32}, | |
22 | {4115, 160, 608, 32, 32}, | |
23 | {4120, 192, 608, 32, 32}, // Helppacket | |
24 | {4121, 224, 608, 32, 32}, // Sauerstoff | |
25 | {4122, 256, 608, 32, 32}, // Feuerstein | |
26 | {4000, 0, 512, 32, 32}, // Fenster 1 | |
27 | {4001, 32, 512, 32, 32}, // Fenster 2 | |
28 | {4002, 64, 512, 32, 32}, // Tor solid | |
29 | {4003, 96, 512, 32, 32}, // Gitter | |
30 | {4004, 128, 512, 32, 32}, // Dach l | |
31 | {4005, 160, 512, 32, 32}, // Dach R | |
32 | {4006, 192, 512, 32, 32}, // Busch 1 | |
33 | {4007, 224, 512, 32, 32}, // Busch 2 | |
34 | {4008, 256, 512, 32, 32}, // Tropfstein | |
35 | {4009, 288, 512, 32, 32}, | |
36 | {4010, 320, 512, 32, 32}, | |
37 | {4011, 352, 512, 32, 32}, | |
38 | {4012, 384, 512, 32, 32}, | |
39 | {4013, 416, 512, 32, 32}, | |
40 | {4014, 448, 512, 32, 32}, | |
41 | {4015, 0, 544, 32, 32}, | |
42 | {4016, 32, 544, 32, 32}, | |
43 | {4017, 64, 544, 32, 32}, | |
44 | {4018, 96, 544, 32, 32}, | |
45 | {4020, 128, 544, 32, 32}, | |
46 | {4019, 416, 544, 64, 64}, | |
47 | // Player | |
48 | {500, 0 * 32, 32, 32, 32}, // Sword | |
49 | {501, 1 * 32, 32, 32, 32}, | |
50 | {502, 2 * 32, 32, 32, 32}, | |
51 | {503, 3 * 32, 32, 32, 32}, | |
52 | {504, 4 * 32, 32, 32, 32}, | |
53 | {505, 5 * 32, 32, 32, 32}, | |
54 | {506, 6 * 32, 32, 32, 32}, | |
55 | {507, 7 * 32, 32, 32, 32}, | |
56 | {520, 0 * 32, 64, 32, 32}, // Phiole | |
57 | {521, 1 * 32, 64, 32, 32}, | |
58 | {522, 2 * 32, 64, 32, 32}, | |
59 | {523, 3 * 32, 64, 32, 32}, | |
60 | {524, 4 * 32, 64, 32, 32}, | |
61 | {510, 5 * 32, 64, 32, 32}, // Bacchetta | |
62 | {511, 6 * 32, 64, 32, 32}, | |
63 | {512, 7 * 32, 64, 32, 32}, | |
64 | {513, 8 * 32, 64, 32, 32}, | |
65 | {514, 9 * 32, 64, 32, 32}, | |
66 | {530, 10 * 32, 64, 32, 32}, // Bow | |
67 | {531, 11 * 32, 64, 32, 32}, | |
68 | {532, 12 * 32, 64, 32, 32}, | |
69 | {533, 13 * 32, 64, 32, 32}, | |
70 | {534, 14 * 32, 64, 32, 32}, | |
71 | {535, 15 * 32, 64, 32, 32}, | |
72 | {540, 0 * 32, 96, 32, 32}, // Scie | |
73 | {541, 1 * 32, 96, 32, 32}, | |
74 | {542, 2 * 32, 96, 32, 32}, | |
75 | {543, 3 * 32, 96, 32, 32}, | |
76 | {544, 4 * 32, 96, 32, 32}, | |
77 | {545, 5 * 32, 96, 32, 32}, | |
78 | {546, 6 * 32, 96, 32, 32}, | |
79 | {550, 7 * 32, 96, 32, 32}, // Hands | |
80 | {551, 8 * 32, 96, 32, 32}, | |
81 | {552, 9 * 32, 96, 32, 32}, | |
82 | {553, 10 * 32, 96, 32, 32}, | |
83 | {554, 11 * 32, 96, 32, 32}, | |
84 | {560, 0 * 32, 128, 32, 32}, // Bombs | |
85 | {561, 1 * 32, 128, 32, 32}, | |
86 | {562, 2 * 32, 128, 32, 32}, | |
87 | {563, 3 * 32, 128, 32, 32}, | |
88 | {564, 4 * 32, 128, 32, 32}, | |
89 | {570, 5 * 32, 128, 32, 32}, // Staff | |
90 | {571, 6 * 32, 128, 32, 32}, | |
91 | {572, 7 * 32, 128, 32, 32}, | |
92 | {573, 8 * 32, 128, 32, 32}, | |
93 | {574, 9 * 32, 128, 32, 32}, | |
94 | {575, 10 * 32, 128, 32, 32}, | |
95 | // Creeper | |
96 | {1000, 0 * 32, 160, 32, 32}, | |
97 | {1001, 1 * 32, 160, 32, 32}, | |
98 | {1002, 2 * 32, 160, 32, 32}, | |
99 | {1003, 3 * 32, 160, 32, 32}, | |
100 | {1004, 4 * 32, 160, 32, 32}, | |
101 | {1005, 5 * 32, 160, 32, 32}, | |
102 | {1006, 6 * 32, 160, 32, 32}, | |
103 | {1007, 7 * 32, 160, 32, 32}, | |
104 | // Saqqraq | |
105 | {1010, 8 * 32, 160, 32, 32}, | |
106 | {1011, 9 * 32, 160, 32, 32}, | |
107 | {1012, 10 * 32, 160, 32, 32}, | |
108 | {1013, 11 * 32, 160, 32, 32}, | |
109 | {1014, 12 * 32, 160, 32, 32}, | |
110 | {1015, 13 * 32, 160, 32, 32}, | |
111 | {1016, 14 * 32, 160, 32, 32}, | |
112 | {1017, 15 * 32, 160, 32, 32}, | |
113 | // Deadfish | |
114 | {1020, 0 * 32, 192, 32, 32}, | |
115 | {1021, 1 * 32, 192, 32, 32}, | |
116 | {1022, 2 * 32, 192, 32, 32}, | |
117 | {1023, 3 * 32, 192, 32, 32}, | |
118 | {1024, 4 * 32, 192, 32, 32}, | |
119 | {1025, 5 * 32, 192, 32, 32}, | |
120 | {1026, 6 * 32, 192, 32, 32}, | |
121 | {1027, 7 * 32, 192, 32, 32}, | |
122 | // Ork | |
123 | {1030, 8 * 32, 192, 32, 32}, | |
124 | {1031, 9 * 32, 192, 32, 32}, | |
125 | {1032, 10 * 32, 192, 32, 32}, | |
126 | {1033, 11 * 32, 192, 32, 32}, | |
127 | {1034, 12 * 32, 192, 32, 32}, | |
128 | {1035, 13 * 32, 192, 32, 32}, | |
129 | {1036, 14 * 32, 192, 32, 32}, | |
130 | {1037, 15 * 32, 192, 32, 32}, | |
131 | // Libelle | |
132 | {1050, 0 * 32, 224, 32, 32}, | |
133 | {1051, 1 * 32, 224, 32, 32}, | |
134 | {1052, 2 * 32, 224, 32, 32}, | |
135 | {1053, 3 * 32, 224, 32, 32}, | |
136 | {1054, 4 * 32, 224, 32, 32}, | |
137 | {1055, 5 * 32, 224, 32, 32}, | |
138 | {1056, 6 * 32, 224, 32, 32}, | |
139 | {1057, 7 * 32, 224, 32, 32}, | |
140 | // BlackOrk | |
141 | {1060, 8 * 32, 224, 32, 32}, | |
142 | {1061, 9 * 32, 224, 32, 32}, | |
143 | {1062, 10 * 32, 224, 32, 32}, | |
144 | {1063, 11 * 32, 224, 32, 32}, | |
145 | {1064, 12 * 32, 224, 32, 32}, | |
146 | {1065, 13 * 32, 224, 32, 32}, | |
147 | {1066, 14 * 32, 224, 32, 32}, | |
148 | {1067, 15 * 32, 224, 32, 32}, | |
149 | // Oger | |
150 | {1070, 0 * 32, 256, 32, 32}, | |
151 | {1071, 1 * 32, 256, 32, 32}, | |
152 | {1072, 2 * 32, 256, 32, 32}, | |
153 | {1073, 3 * 32, 256, 32, 32}, | |
154 | {1074, 4 * 32, 256, 32, 32}, | |
155 | {1075, 5 * 32, 256, 32, 32}, | |
156 | {1076, 6 * 32, 256, 32, 32}, | |
157 | {1077, 7 * 32, 256, 32, 32}, | |
158 | // Nazgul | |
159 | {1040, 8 * 32, 256, 32, 32}, | |
160 | {1041, 9 * 32, 256, 32, 32}, | |
161 | {1042, 10 * 32, 256, 32, 32}, | |
162 | {1043, 11 * 32, 256, 32, 32}, | |
163 | {1044, 12 * 32, 256, 32, 32}, | |
164 | {1045, 13 * 32, 256, 32, 32}, | |
165 | {1046, 14 * 32, 256, 32, 32}, | |
166 | {1047, 15 * 32, 256, 32, 32}, | |
167 | // Otyg | |
168 | {1080, 0 * 32, 288, 32, 32}, | |
169 | {1081, 1 * 32, 288, 32, 32}, | |
170 | {1082, 2 * 32, 288, 32, 32}, | |
171 | {1083, 3 * 32, 288, 32, 32}, | |
172 | {1084, 4 * 32, 288, 32, 32}, | |
173 | {1085, 5 * 32, 288, 32, 32}, | |
174 | {1086, 6 * 32, 288, 32, 32}, | |
175 | {1087, 7 * 32, 288, 32, 32}, | |
176 | // Grieg | |
177 | {1090, 8 * 32, 288, 32, 32}, | |
178 | {1091, 9 * 32, 288, 32, 32}, | |
179 | {1092, 10 * 32, 288, 32, 32}, | |
180 | {1093, 11 * 32, 288, 32, 32}, | |
181 | {1094, 12 * 32, 288, 32, 32}, | |
182 | {1095, 13 * 32, 288, 32, 32}, | |
183 | {1096, 14 * 32, 288, 32, 32}, | |
184 | {1097, 15 * 32, 288, 32, 32}, | |
185 | // Warg | |
186 | {1100, 0 * 64, 320, 64, 64}, | |
187 | {1101, 1 * 64, 320, 64, 64}, | |
188 | {1102, 2 * 64, 320, 64, 64}, | |
189 | {1103, 3 * 64, 320, 64, 64}, | |
190 | {1104, 4 * 64, 320, 64, 64}, | |
191 | {1105, 5 * 64, 320, 64, 64}, | |
192 | {1106, 6 * 64, 320, 64, 64}, | |
193 | {1107, 7 * 64, 320, 64, 64}, | |
194 | // Weapons | |
195 | {4803, 105, 649, 14, 14}, // Phiole | |
196 | {5100, 7 * 32, 672, 32, 32}, | |
197 | {5101, 8 * 32, 672, 32, 32}, | |
198 | {4804, 138, 650, 12, 12}, // Zauberstab | |
199 | {5110, 9 * 32, 672, 32, 32}, | |
200 | {5111, 10 * 32, 672, 32, 32}, | |
201 | {4802, 71, 650, 18, 10}, // Pfeilbogen | |
202 | {5000, 0 * 32, 672, 32, 32}, | |
203 | {5001, 1 * 32, 672, 32, 32}, | |
204 | {5002, 2 * 32, 672, 32, 32}, | |
205 | {5003, 3 * 32, 672, 32, 32}, | |
206 | {5004, 4 * 32, 672, 32, 32}, | |
207 | {4805, 167, 650, 16, 14}, // Hand | |
208 | {5120, 11 * 32, 672, 32, 32}, | |
209 | {5121, 12 * 32, 672, 32, 32}, | |
210 | {5122, 13 * 32, 672, 32, 32}, | |
211 | {5123, 14 * 32, 672, 32, 32}, | |
212 | {4806, 202, 652, 12, 12}, // Bombe | |
213 | {5160, 0 * 64, 800, 64, 64}, | |
214 | {5161, 1 * 64, 800, 64, 64}, | |
215 | {5162, 2 * 64, 800, 64, 64}, | |
216 | {5163, 3 * 64, 800, 64, 64}, | |
217 | {5164, 4 * 64, 800, 64, 64}, | |
218 | {4807, 7 * 32, 640, 32, 32}, // Staff | |
219 | {5126, 1 * 64, 704, 64, 64}, | |
220 | {5127, 2 * 64, 704, 64, 64}, | |
221 | {5128, 3 * 64, 704, 64, 64}, | |
222 | {5129, 4 * 64, 704, 64, 64}, | |
223 | {5130, 5 * 64, 704, 64, 64}, | |
224 | {4800, 9, 650, 14, 14}, // Unguided | |
225 | {4801, 38, 646, 18, 18}, // aimed | |
226 | {4810, 328, 649, 16, 16}, // guided | |
227 | {5180, 4, 741, 27, 28}, | |
228 | {5181, 33, 736, 31, 31}, | |
229 | {5182, 159, 769, 30, 30}, | |
230 | //{4811, 6 * 32, 672, 32, 32}, | |
231 | {5138, 7 * 32, 768, 32, 32}, | |
232 | {5139, 8 * 32, 768, 32, 32}, | |
233 | {5140, 9 * 32, 768, 32, 32}, | |
234 | {5141, 10 * 32, 768, 32, 32}, | |
235 | {5142, 11 * 32, 768, 32, 32}, | |
236 | {4808, 263, 651, 18, 18}, // Trollbombs | |
237 | {5124, 0 * 32, 704, 32, 32}, | |
238 | {5125, 1 * 32, 704, 32, 32}, | |
239 | {4809, 297, 650, 14, 12}, // Otyg | |
240 | {5131, 0 * 32, 768, 32, 32}, | |
241 | {5132, 1 * 32, 768, 32, 32}, | |
242 | {5133, 2 * 32, 768, 32, 32}, | |
243 | {5134, 3 * 32, 768, 32, 32}, | |
244 | {5135, 4 * 32, 768, 32, 32}, | |
245 | {4113, 327, 649, 18, 18}, // Violett | |
246 | {5120, 6 * 32, 736, 32, 32}, | |
247 | {5121, 7 * 32, 736, 32, 32}, | |
248 | {5122, 8 * 32, 736, 32, 32}, | |
249 | {5123, 9 * 32, 736, 32, 32}, | |
250 | {5124, 10 * 32, 736, 32, 32}, | |
251 | {4811, 356, 647, 25, 23}, // Warg 1 | |
252 | {5150, 12 * 32, 768, 32, 32}, | |
253 | {5151, 13 * 32, 768, 32, 32}, | |
254 | {4812, 384, 651, 34, 14}, // Warg 2 | |
255 | {2000, 0, 384, 32, 32}, // Türe | |
256 | {2001, 33, 384, 30, 32}, // Lift | |
257 | // Schalter etc. | |
258 | {200, 0 * 32, 0, 32, 32}, | |
259 | {201, 1 * 32, 0, 32, 32}, | |
260 | {202, 2 * 32, 0, 32, 32}, | |
261 | {203, 3 * 32, 0, 32, 32}, | |
262 | {204, 4 * 32, 0, 32, 32}, | |
263 | {205, 5 * 32, 0, 32, 32}, | |
264 | {206, 6 * 32, 0, 32, 32}, | |
265 | {207, 7 * 32, 0, 32, 32}, | |
266 | {208, 8 * 32, 0, 32, 32}, | |
267 | {209, 9 * 32, 0, 32, 32}, | |
268 | {210, 362, 0, 32, 37}, | |
269 | {211, 394, 0, 32, 37}, | |
270 | {300, 10 * 32, 0, 32, 32}, | |
271 | // Letters | |
272 | {65, 0, 864, 31, 24}, | |
273 | {66, 31, 864, 32, 24}, | |
274 | {67, 66, 864, 25, 24}, | |
275 | {68, 95, 864, 31, 24}, | |
276 | {69, 130, 864, 28, 24}, | |
277 | {70, 162, 864, 32, 24}, | |
278 | {71, 197, 864, 26, 24}, | |
279 | {72, 228, 864, 29, 24}, | |
280 | {73, 261, 864, 23, 24}, | |
281 | ||
282 | {74, 6, 888, 25, 25}, | |
283 | {75, 33, 888, 42, 25}, | |
284 | {76, 79, 888, 34, 25}, | |
285 | {77, 118, 888, 36, 25}, | |
286 | {78, 164, 888, 34, 25}, | |
287 | {79, 202, 888, 28, 25}, | |
288 | {80, 234, 888, 28, 25}, | |
289 | {81, 266, 888, 32, 25}, | |
290 | {82, 299, 888, 39, 25}, | |
291 | ||
292 | {83, 0, 914, 26, 25}, | |
293 | {84, 32, 914, 30, 25}, | |
294 | {85, 62, 914, 30, 25}, | |
295 | {86, 96, 914, 29, 25}, | |
296 | {87, 131, 914, 39, 25}, | |
297 | {88, 170, 914, 36, 25}, | |
298 | {89, 209, 914, 30, 25}, | |
299 | {90, 243, 914, 26, 25}, | |
300 | ||
301 | {33, 270, 914, 15, 25}, | |
302 | {63, 291, 914, 22, 25}, | |
303 | ||
304 | {49, 3, 939, 15, 21}, | |
305 | {50, 25, 939, 17, 21}, | |
306 | {51, 49, 939, 16, 21}, | |
307 | {52, 73, 939, 17, 21}, | |
308 | {53, 96, 939, 18, 21}, | |
309 | {54, 121, 939, 17, 21}, | |
310 | {55, 144, 939, 20, 21}, | |
311 | {56, 169, 939, 16, 21}, | |
312 | {57, 193, 939, 17, 21}, | |
313 | {48, 217, 939, 17, 21}, | |
314 | {46, 241, 939, 12, 21}, | |
315 | {44, 259, 939, 11, 21}, | |
316 | {45, 278, 939, 18, 21}, | |
317 | ||
318 | {10000, 317, 543, 94, 92}, | |
319 | {10001, 382, 806, 126, 126}, | |
320 | {10002, 322, 802, 40, 40} | |
321 | ||
322 | ||
323 | }; | |
324 | ||
325 | static short kTextureDescriptor[kNumTextures][5] = { | |
326 | // Texset 1 | |
327 | {3000, 0 * 32, 416, 32, 32}, | |
328 | {3001, 1 * 32, 416, 32, 32}, | |
329 | {3002, 2 * 32, 416, 32, 32}, | |
330 | {3003, 3 * 32, 416, 32, 32}, | |
331 | {3004, 4 * 32, 416, 32, 32}, | |
332 | {3005, 5 * 32, 416, 32, 32}, | |
333 | {3006, 6 * 32, 416, 32, 32}, | |
334 | {3007, 7 * 32, 416, 32, 32}, | |
335 | {3008, 8 * 32, 416, 32, 32}, | |
336 | {3009, 9 * 32, 416, 32, 32}, | |
337 | {3010, 10 * 32, 416, 32, 32}, | |
338 | {3011, 11 * 32, 416, 32, 32}, | |
339 | {3012, 12 * 32, 416, 32, 32}, | |
340 | {3013, 13 * 32, 416, 32, 32}, | |
341 | {3014, 14 * 32, 416, 32, 32}, | |
342 | // Texset 2 | |
343 | {3020, 0 * 32, 448, 32, 32}, | |
344 | {3021, 1 * 32, 448, 32, 32}, | |
345 | {3022, 2 * 32, 448, 32, 32}, | |
346 | {3023, 3 * 32, 448, 32, 32}, | |
347 | {3024, 4 * 32, 448, 32, 32}, | |
348 | {3025, 5 * 32, 448, 32, 32}, | |
349 | {3026, 6 * 32, 448, 32, 32}, | |
350 | {3027, 7 * 32, 448, 32, 32}, | |
351 | {3028, 8 * 32, 448, 32, 32}, | |
352 | {3029, 9 * 32, 448, 32, 32}, | |
353 | {3030, 10 * 32, 448, 32, 32}, | |
354 | {3031, 11 * 32, 448, 32, 32}, | |
355 | {3032, 12 * 32, 448, 32, 32}, | |
356 | {3033, 13 * 32, 448, 32, 32}, | |
357 | {3034, 14 * 32, 448, 32, 32}, | |
358 | // Texset 3 | |
359 | {3040, 0 * 32, 480, 32, 32}, | |
360 | {3041, 1 * 32, 480, 32, 32}, | |
361 | {3042, 2 * 32, 480, 32, 32}, | |
362 | {3043, 3 * 32, 480, 32, 32}, | |
363 | {3044, 4 * 32, 480, 32, 32}, | |
364 | {3045, 5 * 32, 480, 32, 32}, | |
365 | {3046, 6 * 32, 480, 32, 32}, | |
366 | {3047, 7 * 32, 480, 32, 32}, | |
367 | {3048, 8 * 32, 480, 32, 32}, | |
368 | {3049, 9 * 32, 480, 32, 32}, | |
369 | {3050, 10 * 32, 480, 32, 32}, | |
370 | {3051, 11 * 32, 480, 32, 32}, | |
371 | {3052, 12 * 32, 480, 32, 32}, | |
372 | {3053, 13 * 32, 480, 32, 32}, | |
373 | {3054, 14 * 32, 480, 32, 32} | |
374 | ||
375 | }; | |
376 | ||
377 | ||
378 | #endif⏎ |
0 | #include "ShapeLd.hpp" | |
1 | #include "Graphfil.hpp" | |
2 | #include "Appl.hpp" | |
3 | #include "Clut.hpp" | |
4 | #include "ShapeDes.hpp" | |
5 | #include "ConstVal.hpp" | |
6 | #include <stdio.h> | |
7 | ||
8 | extern CApplication *gApplication; | |
9 | extern CSystem *gSystem; | |
10 | extern CClutManager *gClutManager; | |
11 | extern tConstValues *gConst; | |
12 | extern CClutManager *gClutManager; | |
13 | extern FILE *logFile; | |
14 | ||
15 | CShapeManager::CShapeManager() | |
16 | { | |
17 | } | |
18 | ||
19 | CShapeManager::~CShapeManager() | |
20 | { | |
21 | } | |
22 | ||
23 | void CShapeManager::LoadShapes() | |
24 | { | |
25 | short n; | |
26 | Graphic_file *plane; | |
27 | ||
28 | MSG("Opening shape file\n"); | |
29 | plane = read_graphic_file(gSystem->QualifyDataDir(gConst->kFileShapes)); // by LL | |
30 | if (!plane) gSystem->Error("Cannot find kFileShapes or cannot open it. Perhaps lack of memory?", 0); | |
31 | ||
32 | MSG("Creating shapes and textures\n"); | |
33 | for (n = 0; n < kNumShapes; n ++) { | |
34 | shapes[n] = new CMaskedShape(plane->bitmap, &kShapeDescriptor[n][0], plane->width); | |
35 | } | |
36 | for (n = 0; n < kNumTextures; n ++) { | |
37 | for (short m = 0; m < 4; m ++) { | |
38 | textures[n][m] = new CTexture(plane->bitmap, &kTextureDescriptor[n][0], plane->width, m); | |
39 | } | |
40 | } | |
41 | ||
42 | gClutManager->CalculateCoronas(plane->bitmap, plane->width); | |
43 | ||
44 | free_graphic_file(plane); | |
45 | } | |
46 | ||
47 | void CShapeManager::UnloadShapes() | |
48 | { | |
49 | short n; | |
50 | ||
51 | for (n = 0; n < kNumShapes; n ++) { | |
52 | delete shapes[n]; | |
53 | } | |
54 | for (n = 0; n < kNumTextures; n ++) { | |
55 | for (short m = 0; m < 4; m ++) { | |
56 | delete textures[n][m]; | |
57 | } | |
58 | } | |
59 | } | |
60 | ||
61 | void CShapeManager::LoadBackground(char *background) | |
62 | { | |
63 | MSG("Opening background image\n"); | |
64 | backgroundPicture = read_graphic_file(gSystem->QualifyDataDir(background)); | |
65 | if (!backgroundPicture) gSystem->Error("Cannot open background file. Lack of memory?", 0); | |
66 | SwapBlackWhite(backgroundPicture); | |
67 | } | |
68 | ||
69 | void CShapeManager::UnloadBackground() | |
70 | { | |
71 | free_graphic_file(backgroundPicture); | |
72 | } | |
73 | ||
74 | CShape* CShapeManager::FindShape(short id, short light) | |
75 | { | |
76 | short n; | |
77 | if (id == -1) return NULL; else { | |
78 | if (id >= kTextureStart && id <= kTextureEnd) { | |
79 | for (n = 0; n < kNumTextures && kTextureDescriptor[n][0] != id; n ++) {} | |
80 | if (n != kNumTextures) return textures[n][light]; else return 0L; | |
81 | ||
82 | }else{ | |
83 | for (n = 0; n < kNumShapes && kShapeDescriptor[n][0] != id; n ++) {} | |
84 | if (n != kNumShapes) return shapes[n]; else return 0L; | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
89 | unsigned char *CShapeManager::GetBackground(short &width, short &height) | |
90 | { | |
91 | width = backgroundPicture->width; | |
92 | height = backgroundPicture->height; | |
93 | ||
94 | return backgroundPicture->bitmap; | |
95 | }⏎ |
0 | #ifndef __AMP_SHAPEMANAGER__ | |
1 | #define __AMP_SHAPEMANAGER__ | |
2 | ||
3 | ||
4 | #include "System.hpp" | |
5 | #include "Shape.hpp" | |
6 | #include "Graphfil.hpp" | |
7 | ||
8 | ||
9 | enum { | |
10 | kTotalShapes = 336, | |
11 | kTextureStart = 3000, | |
12 | kTextureEnd = 3054, | |
13 | kNumTextures = 45, | |
14 | kNumShapes = kTotalShapes - kNumTextures, | |
15 | kAddPlayerStart = 510, | |
16 | kAddPlayerEnd = 574 | |
17 | }; | |
18 | ||
19 | ||
20 | class CShapeManager { | |
21 | protected: | |
22 | CShape *shapes[kNumShapes]; | |
23 | CShape *textures[kNumTextures][4]; | |
24 | unsigned char *coronas; | |
25 | Graphic_file *backgroundPicture; | |
26 | ||
27 | public: | |
28 | CShapeManager(); | |
29 | ~CShapeManager(); | |
30 | ||
31 | void LoadShapes(); | |
32 | void LoadBackground(char *name); | |
33 | void UnloadShapes(); | |
34 | void UnloadBackground(); | |
35 | ||
36 | CShape *FindShape(short id, short light); | |
37 | unsigned char *GetBackground(short &width, short &height); | |
38 | }; | |
39 | ||
40 | #endif |
0 | #include "SndSys.hpp" | |
1 | #include "Level.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | ||
4 | extern CSoundSystem *gSoundSystem; | |
5 | extern CLevel *gLevel; | |
6 | extern tConstValues *gConst; | |
7 | extern tConfigData *gConfigData; | |
8 | ||
9 | const short kMaxUserSound = 10; | |
10 | ||
11 | void Mix_Audio(void *udata, Uint8 *stream, int len) | |
12 | { | |
13 | gSoundSystem->ProcessList(udata, stream, len); | |
14 | } | |
15 | ||
16 | int InitializeSoundSystem() | |
17 | { | |
18 | SDL_AudioSpec wanted, obtained; | |
19 | ||
20 | /* Set the audio format */ | |
21 | // Not all sounds are of the same sampling rate which is why | |
22 | // some of them sound a little crappy. Some conversion should be performed... | |
23 | wanted.freq = 11025; | |
24 | wanted.format = (AUDIO_U8); | |
25 | wanted.channels = 1; | |
26 | wanted.samples = 512; /* Good low-latency value for callback */ | |
27 | wanted.callback = Mix_Audio; | |
28 | wanted.userdata = NULL; | |
29 | ||
30 | /* Open the audio device, forcing the desired format */ | |
31 | if ( SDL_OpenAudio(&wanted, &obtained) < 0 ) { | |
32 | fprintf(stderr, "InitSoundSystem: Couldn't open audio: %s\n", SDL_GetError()); | |
33 | fprintf(stderr, "Sound was disabled. \n"); | |
34 | return(-1); | |
35 | } | |
36 | return(0); | |
37 | } | |
38 | ||
39 | CSoundSystem::CSoundSystem(int status) | |
40 | { | |
41 | state=status; | |
42 | ||
43 | for (short n = 0; n < kNumWeapons; n ++) { | |
44 | weaponLaunchSounds[n] = new CSound(kWeaponLaunchSounds[n]); | |
45 | weaponHitSounds[n] = new CSound(kWeaponHitSounds[n]); | |
46 | } | |
47 | ||
48 | platformGo = new CSound(kPlatformGoSound); | |
49 | platformStop = new CSound(kPlatformStopSound); | |
50 | lightOn = new CSound(kLightOnSound); | |
51 | lightOff = new CSound(kLightOffSound); | |
52 | ||
53 | firestoneDamage = new CSound(kFirestoneDamage); | |
54 | ||
55 | selMenu = new CSound(kSelMenuSound); | |
56 | entrMenu = new CSound(kEntrMenuSound); | |
57 | openMenu = new CSound(kOpenMenuSound); | |
58 | ||
59 | playerJump = new CSound(kPlayerJumpSound); | |
60 | playerDive = new CSound(kPlayerDiveSound); | |
61 | playerPickup = new CSound(kPlayerPickupSound); | |
62 | ||
63 | minDistance = gConst->kSoundMinDistance * gConst->kSoundMinDistance; | |
64 | maxDistance = gConst->kSoundMaxDistance * gConst->kSoundMaxDistance; | |
65 | ||
66 | playList = new CSoundList(); | |
67 | ||
68 | currentMaxSound = (SDL_MIX_MAXVOLUME) * gConfigData->soundVolume / kMaxUserSound; | |
69 | ||
70 | if (state) { | |
71 | SDL_PauseAudio(0); // turn the music on... | |
72 | } | |
73 | ||
74 | } | |
75 | ||
76 | CSoundSystem::~CSoundSystem() | |
77 | { | |
78 | if (state) { | |
79 | SDL_PauseAudio(1); | |
80 | SDL_CloseAudio(); | |
81 | } | |
82 | delete playList; | |
83 | for (short n = 0; n < kNumWeapons; n ++) { | |
84 | delete weaponLaunchSounds[n]; | |
85 | delete weaponHitSounds[n]; | |
86 | } | |
87 | ||
88 | delete platformGo; | |
89 | delete platformStop; | |
90 | delete lightOn; | |
91 | delete lightOff; | |
92 | ||
93 | delete playerJump; | |
94 | delete playerDive; | |
95 | delete playerPickup; | |
96 | } | |
97 | ||
98 | void CSoundSystem::Play(CSound *which, double x, double y) | |
99 | { | |
100 | if (!state) return; | |
101 | long distance = (long)((x - gLevel->focus->xm) * (x - gLevel->focus->xm) + (y - gLevel->focus->ym) * (y - gLevel->focus->ym)); | |
102 | double factor; | |
103 | ||
104 | SoundState *newstate = new SoundState; | |
105 | ||
106 | if (distance < minDistance) { | |
107 | which->SetVol(currentMaxSound); | |
108 | } else if (distance < maxDistance) { | |
109 | factor = double(distance - minDistance) / double(maxDistance - minDistance); | |
110 | which->SetVol(currentMaxSound - currentMaxSound * factor); | |
111 | } else return; | |
112 | ||
113 | which->Play(newstate); | |
114 | playList->Insert(newstate); | |
115 | ||
116 | } | |
117 | ||
118 | void CSoundSystem::ProcessList(void *udata, Uint8 *stream, int len) | |
119 | { | |
120 | SoundState *theSound; | |
121 | int mixlen; | |
122 | ||
123 | playList->Reset(); | |
124 | // traverse the list of sounds being played | |
125 | while (theSound = playList->GetNext()) { | |
126 | mixlen = MIN(len, (int) theSound->bytesleft); | |
127 | SDL_MixAudio(stream, theSound->soundpos, mixlen, theSound->volume); | |
128 | theSound->soundpos += mixlen; | |
129 | theSound->bytesleft -= mixlen; | |
130 | if (!theSound->bytesleft) { // sound finished playing | |
131 | playList->RemoveCurrent(); | |
132 | } | |
133 | } | |
134 | }⏎ |
0 | #ifndef _AMPH_SOUND_SYS_ | |
1 | ||
2 | #define _AMPH_SOUND_SYS_ | |
3 | ||
4 | #include "ObjInfo.hpp" | |
5 | #include "SoundList.hpp" | |
6 | ||
7 | const char kWeaponLaunchSounds[kNumWeapons][21] = { | |
8 | "sounds/swordl.wav", | |
9 | "sounds/phioll.wav", | |
10 | "sounds/sorceryl.wav", | |
11 | "sounds/bowl.wav", | |
12 | "sounds/sciel.wav", | |
13 | "sounds/handsl.wav", | |
14 | "sounds/bombl.wav", | |
15 | "sounds/staffl.wav", | |
16 | "sounds/borkl.wav", | |
17 | "sounds/aimedl.wav", | |
18 | "sounds/guidedl.wav", | |
19 | "sounds/trolll.wav", | |
20 | "sounds/otygl.wav", | |
21 | "sounds/nazgull.wav", | |
22 | "sounds/warg1l.wav", | |
23 | "sounds/warg2l.wav" | |
24 | }; | |
25 | ||
26 | const char kWeaponHitSounds[kNumWeapons][21] = { | |
27 | "sounds/swordh.wav", | |
28 | "sounds/phiolh.wav", | |
29 | "sounds/sorceryh.wav", | |
30 | "sounds/bowh.wav", | |
31 | "sounds/scieh.wav", | |
32 | "sounds/handsh.wav", | |
33 | "sounds/bombh.wav", | |
34 | "sounds/staffh.wav", | |
35 | "sounds/borkh.wav", | |
36 | "sounds/aimedh.wav", | |
37 | "sounds/guidedh.wav", | |
38 | "sounds/trollh.wav", | |
39 | "sounds/otygh.wav", | |
40 | "sounds/nazgulh.wav", | |
41 | "sounds/warg1h.wav", | |
42 | "sounds/warg2h.wav" | |
43 | }; | |
44 | ||
45 | ||
46 | ||
47 | const char kPlatformGoSound[21] = "sounds/platgo.wav"; | |
48 | const char kPlatformStopSound[21] = "sounds/platstop.wav"; | |
49 | const char kLightOnSound[21] = "sounds/lighton.wav"; | |
50 | const char kLightOffSound[21] = "sounds/lightoff.wav"; | |
51 | ||
52 | const char kSelMenuSound[21] = "sounds/selmenu.wav"; | |
53 | const char kEntrMenuSound[21] = "sounds/entrmenu.wav"; | |
54 | const char kOpenMenuSound[21] = "sounds/openmenu.wav"; | |
55 | ||
56 | const char kFirestoneDamage[21] = "sounds/stonedam.wav"; | |
57 | ||
58 | const char kPlayerJumpSound[21] = "sounds/jump.wav"; | |
59 | const char kPlayerDiveSound[21] = "sounds/dive.wav"; | |
60 | const char kPlayerPickupSound[21] = "sounds/pickup.wav"; | |
61 | ||
62 | class CSoundSystem { | |
63 | ||
64 | private: | |
65 | long maxDistance, minDistance; | |
66 | long currentMaxSound; | |
67 | // List of sounds being played | |
68 | CSoundList *playList; | |
69 | ||
70 | public: | |
71 | // Weapon sounds | |
72 | int state; | |
73 | CSound *weaponLaunchSounds[kNumWeapons]; | |
74 | CSound *weaponHitSounds[kNumWeapons]; | |
75 | ||
76 | // Platform and light sounds | |
77 | CSound *platformGo; | |
78 | CSound *platformStop; | |
79 | CSound *lightOn; | |
80 | CSound *lightOff; | |
81 | ||
82 | // Item sounds | |
83 | CSound *firestoneDamage; | |
84 | ||
85 | // GUI sounds | |
86 | CSound *selMenu; | |
87 | CSound *entrMenu; | |
88 | CSound *openMenu; | |
89 | CSound *playerJump; | |
90 | CSound *playerDive; | |
91 | CSound *playerPickup; | |
92 | ||
93 | CSoundSystem(int state); | |
94 | ~CSoundSystem(); | |
95 | ||
96 | void ProcessList(void*, Uint8*, int ); | |
97 | void Play(CSound *which, double x, double y); | |
98 | ||
99 | }; | |
100 | ||
101 | #endif⏎ |
0 | // SoundList.cpp: Implementierung der Klasse CSoundList. | |
1 | // | |
2 | ////////////////////////////////////////////////////////////////////// | |
3 | #include <stdlib.h> | |
4 | #include <stdarg.h> | |
5 | #include <math.h> | |
6 | #include <stdio.h> | |
7 | #include "SoundList.hpp" | |
8 | #include "System.hpp" | |
9 | ||
10 | extern CSystem *gSystem; | |
11 | ||
12 | ////////////////////////////////////////////////////////////////////// | |
13 | // Konstruktion/Destruktion | |
14 | ////////////////////////////////////////////////////////////////////// | |
15 | ||
16 | extern FILE *logFile; | |
17 | ||
18 | CSound::CSound(const char* wav) | |
19 | { | |
20 | if (wav) { | |
21 | // MSG("Loading "); | |
22 | // MSG(wav); | |
23 | if (!SDL_LoadWAV(gSystem->QualifyDataDir(wav),&specs, &data, &soundlen)) { | |
24 | // MSG(" failed"); | |
25 | } else { | |
26 | // MSG(" succeeded\n"); | |
27 | } | |
28 | state = 1; | |
29 | } | |
30 | Reset(); | |
31 | } | |
32 | ||
33 | void CSound::Reset() | |
34 | { | |
35 | playing = 0; | |
36 | } | |
37 | ||
38 | CSound::~CSound() | |
39 | { | |
40 | delete [] data; | |
41 | } | |
42 | ||
43 | void CSound::Play(SoundState *newstate) | |
44 | { | |
45 | newstate->sound=this; | |
46 | newstate->bytesleft=soundlen; | |
47 | newstate->volume=volume; | |
48 | newstate->soundpos=data; | |
49 | newstate->next=NULL; | |
50 | } | |
51 | ||
52 | bool CSound::isPlaying() | |
53 | { | |
54 | if (state) { | |
55 | return (bool)playing; | |
56 | }else return 0; | |
57 | } | |
58 | ||
59 | void CSound::SetVol(long vol) | |
60 | { | |
61 | volume=vol; | |
62 | } | |
63 | ||
64 | ||
65 | // -------------------------------------------------------- | |
66 | ||
67 | void CSoundList::Reset() { | |
68 | current = first; | |
69 | prev = first; | |
70 | } | |
71 | ||
72 | CSoundList::CSoundList() | |
73 | { | |
74 | first = new SoundState; | |
75 | first->sound=NULL; | |
76 | first->next=NULL; | |
77 | Reset(); | |
78 | } | |
79 | ||
80 | CSoundList::~CSoundList() | |
81 | { | |
82 | delete first; | |
83 | } | |
84 | ||
85 | SoundState *CSoundList::GetNext() | |
86 | { | |
87 | if (current) { | |
88 | prev = current; | |
89 | current = current->next; | |
90 | } | |
91 | return current; | |
92 | } | |
93 | ||
94 | void CSoundList::Insert(SoundState *s) | |
95 | { | |
96 | s->sound->playing ++; | |
97 | s->next=first->next; | |
98 | first->next=s; | |
99 | } | |
100 | ||
101 | void CSoundList::RemoveCurrent() | |
102 | { | |
103 | SoundState *tmp; | |
104 | ||
105 | tmp =current; | |
106 | ||
107 | if (current->sound) { | |
108 | current->sound->playing --; | |
109 | } | |
110 | prev->next = current->next; | |
111 | current = current->next; | |
112 | ||
113 | delete tmp; | |
114 | } |
0 | // SoundList.hpp: Schnittstelle für die Klasse CSoundList. | |
1 | // | |
2 | ////////////////////////////////////////////////////////////////////// | |
3 | ||
4 | #if !defined(_AMPH_SOUND_LIST_) | |
5 | #define _AMPH_SOUND_LIST_ | |
6 | ||
7 | extern "C" { | |
8 | #include <SDL/SDL.h> | |
9 | #include <SDL/SDL_audio.h> | |
10 | #include <SDL/SDL_types.h> | |
11 | } | |
12 | ||
13 | class CSound; | |
14 | ||
15 | struct SoundState { | |
16 | Uint8 *soundpos; | |
17 | Uint32 bytesleft; | |
18 | int volume; | |
19 | CSound *sound; | |
20 | SoundState *next; | |
21 | }; | |
22 | ||
23 | class CSound | |
24 | { | |
25 | private: | |
26 | short state; // 0 if sound doesn't exist, 1 if ok | |
27 | public: | |
28 | Uint8 *data; | |
29 | Uint32 soundlen, playing; | |
30 | int volume; | |
31 | ||
32 | SDL_AudioSpec specs; | |
33 | CSound(const char* wav); | |
34 | ~CSound(); | |
35 | void Play(SoundState *newstate); | |
36 | void Reset(); | |
37 | bool isPlaying(); | |
38 | void SetVol(long vol); | |
39 | }; | |
40 | ||
41 | ||
42 | class CSoundList | |
43 | { | |
44 | public: | |
45 | CSoundList(); | |
46 | ~CSoundList(); | |
47 | ||
48 | void Reset(); | |
49 | void Insert(SoundState *s); | |
50 | SoundState *GetNext(); | |
51 | void RemoveCurrent(); | |
52 | ||
53 | private: | |
54 | SoundState *first, *prev, *current; | |
55 | }; | |
56 | ||
57 | #endif ⏎ |
0 | #include "Surface.hpp" | |
1 | #include "Shape.hpp" | |
2 | #include "ShapeLd.hpp" | |
3 | #include "Clut.hpp" | |
4 | #include "ConstVal.hpp" | |
5 | #include <memory.h> | |
6 | ||
7 | const short kNoCharSpace = 20; | |
8 | const char kNoCharChar = '_'; | |
9 | ||
10 | extern CSystem *gSystem; | |
11 | extern CShapeManager *gShapeManager; | |
12 | extern CClutManager *gClutManager; | |
13 | extern tConstValues *gConst; | |
14 | ||
15 | CGraphicSurface::CGraphicSurface(short dx, short dy) | |
16 | { | |
17 | buffer = gSystem->AllocateBuffer(dx, dy); | |
18 | gSystem->SetBufferPalette(buffer); | |
19 | ||
20 | width = dx; | |
21 | height = dy; | |
22 | ||
23 | numGraphics = 0; | |
24 | } | |
25 | ||
26 | CGraphicSurface::~CGraphicSurface() | |
27 | { | |
28 | for (short n = 0; n < numGraphics; n ++) { | |
29 | if (graphicTypes[n] == kGraphicEmbedded) free_graphic_file(graphics[n]); | |
30 | } | |
31 | gSystem->DisposeBuffer(buffer); | |
32 | } | |
33 | ||
34 | unsigned char *CGraphicSurface::GetSurfacePtr(short *pitch) | |
35 | { | |
36 | unsigned char *tmp = gSystem->GetBufferPtr(buffer, pitch); | |
37 | ||
38 | return tmp; | |
39 | } | |
40 | ||
41 | void CGraphicSurface::ReleaseSurface() | |
42 | { | |
43 | gSystem->ReleaseBufferPtr(buffer); | |
44 | } | |
45 | ||
46 | void CGraphicSurface::InsertGraphic(char *filename, Graphic_file *graphic, tRect *position) | |
47 | { | |
48 | if (filename) { | |
49 | graphics[numGraphics] = read_graphic_file(filename); | |
50 | ||
51 | SwapBlackWhite(graphics[numGraphics]); | |
52 | ||
53 | graphicsPositions[numGraphics].left = 0; | |
54 | graphicsPositions[numGraphics].top = 0; | |
55 | graphicsPositions[numGraphics].right = graphics[numGraphics]->width; | |
56 | graphicsPositions[numGraphics].bottom = graphics[numGraphics]->height; | |
57 | graphicTypes[numGraphics] = kGraphicEmbedded; | |
58 | ||
59 | numGraphics ++; | |
60 | } | |
61 | if (graphic && position) { | |
62 | graphics[numGraphics] = graphic; | |
63 | ||
64 | graphicsPositions[numGraphics].left = position->left; | |
65 | graphicsPositions[numGraphics].top = position->top; | |
66 | graphicsPositions[numGraphics].right = position->right; | |
67 | graphicsPositions[numGraphics].bottom = position->bottom; | |
68 | graphicTypes[numGraphics] = kGraphicReferenced; | |
69 | ||
70 | numGraphics ++; | |
71 | } | |
72 | } | |
73 | ||
74 | void CGraphicSurface::PaintGraphic(short num, short left, short top, short modus) | |
75 | { | |
76 | short j, k; | |
77 | short bottom, right; | |
78 | unsigned char *baseAddr, *linePtr, *sourcePtr, *sourceLinePtr; | |
79 | short pitch; | |
80 | ||
81 | baseAddr = gSystem->GetBufferPtr(buffer, &pitch); | |
82 | ||
83 | // Luke hat hier das -1 entfernt | |
84 | bottom = MIN(top + graphicsPositions[num].bottom - graphicsPositions[num].top, height); | |
85 | right = MIN(left + graphicsPositions[num].right - graphicsPositions[num].left, pitch); | |
86 | ||
87 | baseAddr += top * pitch + left; | |
88 | sourcePtr = graphics[num]->bitmap + graphicsPositions[num].top * graphics[num]->width + graphicsPositions[num].left; | |
89 | ||
90 | for (j = top; j < bottom; j ++) { | |
91 | k = right - left; | |
92 | ||
93 | sourceLinePtr = sourcePtr; | |
94 | linePtr = baseAddr; | |
95 | ||
96 | if (modus == kShapemodusNormal) { | |
97 | memcpy(linePtr, sourcePtr, k); | |
98 | } else { | |
99 | while (k) { | |
100 | gClutManager->SetPixel((unsigned char *)sourceLinePtr, (unsigned char *)linePtr, modus, 0); | |
101 | linePtr++; | |
102 | sourceLinePtr++; | |
103 | k--; | |
104 | } | |
105 | } | |
106 | baseAddr += pitch; | |
107 | sourcePtr += graphics[num]->width; | |
108 | } | |
109 | ||
110 | gSystem->ReleaseBufferPtr(buffer); | |
111 | } | |
112 | ||
113 | ||
114 | ||
115 | #define INT_TO_FIXED(i) ((i) << 16) | |
116 | #define FIXED_TO_INT(f) ((f) >> 16) | |
117 | #define FIXED_TO_FLOAT(f) (((double) (f)) * 1.52587890625e-5) | |
118 | #define FLOAT_TO_FIXED(f) ((long) ((f) * 65536.0)) | |
119 | ||
120 | ||
121 | void CGraphicSurface::DrawAntialiasedLine(short x1, short y1, short x2, short y2, unsigned char color, short modus) | |
122 | { | |
123 | unsigned char *baseAddr; | |
124 | short pitch; | |
125 | ||
126 | baseAddr = gSystem->GetBufferPtr(buffer, &pitch); | |
127 | ||
128 | x1 = MAX(0, x1); | |
129 | x1 = MIN(pitch, x1); | |
130 | x2 = MAX(0, x2); | |
131 | x2 = MIN(pitch, x2); | |
132 | y1 = MAX(0, y1); | |
133 | y1 = MIN(height -1, y1); | |
134 | y2 = MAX(0, y2); | |
135 | y2 = MIN(height -1, y2); | |
136 | ||
137 | short dx = x2 - x1, dy = y2 - y1, dmax; | |
138 | long ex, ey, curx = 0, cury = 0; | |
139 | long lastx, lasty; | |
140 | short counter; | |
141 | ||
142 | if (abs(dx) > abs(dy)) { | |
143 | ex = FLOAT_TO_FIXED(SIGN(dx) * 1.0); | |
144 | ey = FLOAT_TO_FIXED((double)dy / (double)abs(dx)); | |
145 | counter = SIGN(dx) * dx; | |
146 | }else{ | |
147 | ex = FLOAT_TO_FIXED((double)dx / (double)abs(dy)); | |
148 | ey = FLOAT_TO_FIXED(SIGN(dy) * 1.0); | |
149 | counter = SIGN(dy) * dy; | |
150 | } | |
151 | curx = INT_TO_FIXED(x1); | |
152 | cury = INT_TO_FIXED(y1); | |
153 | ||
154 | lastx = INT_TO_FIXED(x1); | |
155 | lasty = INT_TO_FIXED(y1); | |
156 | ||
157 | ||
158 | ||
159 | baseAddr += (FIXED_TO_INT(lasty) * pitch + FIXED_TO_INT(lastx)); | |
160 | ||
161 | while (counter) { | |
162 | gClutManager->SetPixel((unsigned char *)&color, baseAddr, modus, 0); | |
163 | ||
164 | curx += ex; | |
165 | cury += ey; | |
166 | counter --; | |
167 | ||
168 | if (lasty >> 16 != cury >> 16) { | |
169 | baseAddr += (SIGN(cury - lasty)) * pitch; | |
170 | lasty = cury; | |
171 | } | |
172 | if (lastx >> 16 != curx >> 16) { | |
173 | baseAddr += SIGN(curx - lastx); | |
174 | lastx = curx; | |
175 | } | |
176 | } | |
177 | gSystem->ReleaseBufferPtr(buffer); | |
178 | } | |
179 | ||
180 | ||
181 | void CGraphicSurface::PaintRect(short left, short top, short right, short bottom, unsigned char color, short modus) | |
182 | { | |
183 | short j, k; | |
184 | unsigned char *baseAddr; | |
185 | short pitch; | |
186 | ||
187 | baseAddr = gSystem->GetBufferPtr(buffer, &pitch); | |
188 | ||
189 | left = MAX(0, left); | |
190 | top = MAX(0, top); | |
191 | left = MIN(pitch, left); | |
192 | top = MIN(height, top); | |
193 | ||
194 | right = MAX(0, right); | |
195 | bottom = MAX(0, bottom); | |
196 | right = MIN(pitch, right); | |
197 | bottom = MIN(height, bottom); | |
198 | ||
199 | ||
200 | baseAddr += top * pitch; | |
201 | ||
202 | for (j = top; j < bottom; j ++) { | |
203 | for (k = left; k < right; k ++) { | |
204 | gClutManager->SetPixel((unsigned char *)&color, baseAddr + k, modus, 0); | |
205 | } | |
206 | baseAddr += pitch; | |
207 | } | |
208 | ||
209 | gSystem->ReleaseBufferPtr(buffer); | |
210 | } | |
211 | ||
212 | void CGraphicSurface::DrawString(short left, short top, char *text, short modus) | |
213 | { | |
214 | short n = 0, x, startWord, startShapePos; | |
215 | short shapePos = left; | |
216 | short dx, unused; | |
217 | CShape *shape; | |
218 | unsigned char *unused2; | |
219 | ||
220 | tRect clipRect; | |
221 | ||
222 | clipRect.left = clipRect.top = 0; | |
223 | clipRect.right = width; clipRect.bottom = height; | |
224 | ||
225 | while (text && text[n] != '\0') { | |
226 | startWord = n; | |
227 | startShapePos = shapePos; | |
228 | x = n; | |
229 | while (text[x] != kNoCharChar && text[x] != '\0') { | |
230 | shape = gShapeManager->FindShape((short)text[x], 0); | |
231 | if (shape) unused2 = shape->AllowPixelAccess(dx, unused); else dx = 0; | |
232 | shapePos += dx; | |
233 | x ++; | |
234 | } | |
235 | if (shapePos >= width) { | |
236 | top += gConst->kTextYDistance; | |
237 | shapePos = left; | |
238 | }else shapePos = startShapePos; | |
239 | ||
240 | x = startWord; | |
241 | while (text[x] != kNoCharChar && text[x] != '\0') { | |
242 | shape = gShapeManager->FindShape((short)text[x], 0); | |
243 | if (shape) shapePos += shape->RenderShape(shapePos, top, &clipRect, modus, 0, this); | |
244 | x ++; | |
245 | } | |
246 | ||
247 | if (text[x] == kNoCharChar) { | |
248 | shapePos += kNoCharSpace; | |
249 | x ++; | |
250 | } | |
251 | n = x; | |
252 | } | |
253 | } | |
254 | ||
255 | void CGraphicSurface::FlipToScreen(short left, short top) | |
256 | { | |
257 | gSystem->FlipSurfaces(buffer, width, height, left, top); | |
258 | } |
0 | #ifndef __AMP_GRAPHSURFACE__ | |
1 | #define __AMP_GRAPHSURFACE__ | |
2 | ||
3 | #include "System.hpp" | |
4 | #include "Graphfil.hpp" | |
5 | ||
6 | const short kMaxGraphics = 32; | |
7 | const short kNumChars = 40; | |
8 | ||
9 | enum { | |
10 | kGraphicEmbedded, | |
11 | kGraphicReferenced | |
12 | }; // graphicType | |
13 | ||
14 | class CShape; | |
15 | ||
16 | class CGraphicSurface { | |
17 | protected: | |
18 | tGraphicBuffer *buffer; | |
19 | ||
20 | Graphic_file *graphics[kMaxGraphics]; | |
21 | short graphicTypes[kMaxGraphics]; | |
22 | short numGraphics; | |
23 | tRect graphicsPositions[kMaxGraphics]; | |
24 | ||
25 | public: | |
26 | short width, height; | |
27 | ||
28 | CGraphicSurface(short dx, short dy); | |
29 | ~CGraphicSurface(); | |
30 | ||
31 | void InsertGraphic(char *filename, Graphic_file *graphic, tRect *position); | |
32 | void PaintGraphic(short num, short left, short top, short modus); | |
33 | void DrawAntialiasedLine(short x1, short y1, short x2, short y2, unsigned char color, short modus); | |
34 | void PaintRect(short left, short top, short right, short bottom, unsigned char color, short modus); | |
35 | void DrawString(short left, short top, char *text, short modus); | |
36 | ||
37 | void FlipToScreen(short left, short top); | |
38 | unsigned char *GetSurfacePtr(short *pitch); | |
39 | void ReleaseSurface(); | |
40 | }; | |
41 | ||
42 | #endif |
0 | /************************************* | |
1 | System.cpp | |
2 | ||
3 | (c) 1999 Jonas Spillmann | |
4 | ||
5 | Contains system-depending routines such as creating windows and video buffers | |
6 | **************************************/ | |
7 | ||
8 | #include "System.hpp" | |
9 | #include "Graphfil.hpp" | |
10 | #include <sys/time.h> | |
11 | #include <string.h> | |
12 | #include <sys/types.h> | |
13 | #include <sys/stat.h> | |
14 | #include <fcntl.h> | |
15 | #include <unistd.h> | |
16 | #include "Appl.hpp" | |
17 | #include "Level.hpp" | |
18 | #include "Player.hpp" | |
19 | ||
20 | #ifdef _USE_LIB_XPM | |
21 | extern "C" { | |
22 | #include <X11/xpm.h> | |
23 | } | |
24 | #endif | |
25 | ||
26 | extern FILE *logFile; | |
27 | extern CSystem *gSystem; | |
28 | extern CApplication *gApplication; | |
29 | extern CLevel *gLevel; | |
30 | extern tConfigData *gConfigData; | |
31 | ||
32 | int InitializeSoundSystem(); | |
33 | ||
34 | /* Loads the icon to a surface */ | |
35 | ||
36 | inline static unsigned char Hex2Dec(char digit) | |
37 | { | |
38 | if (digit > 64) | |
39 | return (digit - 55); | |
40 | else | |
41 | return (digit - 48); | |
42 | } | |
43 | ||
44 | static void ExtractColors(char *gstring, Uint8 *red, Uint8 *green, Uint8 *blue) { | |
45 | ||
46 | *red = Hex2Dec(gstring[1])*16+Hex2Dec(gstring[2]); | |
47 | *green = Hex2Dec(gstring[3])*16+Hex2Dec(gstring[4]); | |
48 | *blue = Hex2Dec(gstring[5])*16+Hex2Dec(gstring[6]); | |
49 | } | |
50 | ||
51 | #ifdef _USE_LIB_XPM | |
52 | ||
53 | SDL_Surface *CSystem::XPM2Surface(char *filename) | |
54 | { | |
55 | int x, ret; | |
56 | unsigned int i, y; | |
57 | unsigned char *buffer; | |
58 | unsigned int *data; | |
59 | short pitch; | |
60 | SDL_Surface *icon; | |
61 | XpmImage xpmimage; | |
62 | SDL_Color *palette; | |
63 | ||
64 | ret = XpmReadFileToXpmImage(filename, &xpmimage, NULL); | |
65 | ||
66 | if (ret != XpmSuccess || xpmimage.cpp > 1) { // only 8bit pixmaps will work | |
67 | return NULL; | |
68 | } | |
69 | ||
70 | icon = AllocateBuffer(xpmimage.width,xpmimage.height); | |
71 | palette = new SDL_Color[xpmimage.ncolors]; | |
72 | ||
73 | // Get color palette | |
74 | for (i=0; i < xpmimage.ncolors; ++i) { | |
75 | ExtractColors(xpmimage.colorTable[i].c_color, &(palette[i].r),&(palette[i].g),&(palette[i].b)); | |
76 | } | |
77 | ||
78 | buffer = GetBufferPtr(icon, &pitch); | |
79 | data = xpmimage.data; | |
80 | ||
81 | // Copy data | |
82 | for (y = 0; y < xpmimage.width; y++ ) { | |
83 | for (x = 0; x < xpmimage.height; x++) { | |
84 | *buffer = (unsigned char)*data; | |
85 | buffer++; data++; | |
86 | } | |
87 | } | |
88 | ||
89 | ReleaseBufferPtr(icon); | |
90 | SDL_SetColors(icon, palette, 0, xpmimage.ncolors); | |
91 | ||
92 | return icon; | |
93 | } | |
94 | ||
95 | #endif | |
96 | ||
97 | /* This function may run in a separate event thread */ | |
98 | static int FilterEvents(const SDL_Event *event) { | |
99 | ||
100 | /* This quit event signals the closing of the window */ | |
101 | if ( (event->type == SDL_QUIT) ) { | |
102 | exit(0); | |
103 | return(0); | |
104 | } | |
105 | if ( event->type == SDL_KEYDOWN ) { | |
106 | if (event->key.keysym.mod == KMOD_RALT || event->key.keysym.mod == KMOD_LALT){ | |
107 | switch (event->key.keysym.sym) { | |
108 | case (SDLK_s): | |
109 | gSystem->ScreenShot(); | |
110 | break; | |
111 | case (SDLK_n): | |
112 | gApplication->command = kCmdNextLevel; | |
113 | break; | |
114 | case (SDLK_p): | |
115 | gApplication->command = kCmdPrevLevel; | |
116 | break; | |
117 | case (SDLK_w): | |
118 | ((CPlayer *)gLevel->player)->GetItAll(); | |
119 | break; | |
120 | default: | |
121 | break; | |
122 | } | |
123 | return(0); | |
124 | } | |
125 | } | |
126 | return(1); | |
127 | } | |
128 | ||
129 | char *CSystem::QualifyHomeDir(const char *fname) | |
130 | { | |
131 | char *tmp = new char[strlen(homeDir)+strlen(fname)+2]; | |
132 | sprintf(tmp, "%s/%s", homeDir, fname); | |
133 | ||
134 | return tmp; | |
135 | } | |
136 | ||
137 | char *CSystem::QualifyDataDir(const char *fname) | |
138 | { | |
139 | char *tmp = new char[strlen(dataDir)+strlen(fname)+2]; | |
140 | sprintf(tmp, "%s/%s", dataDir, fname); | |
141 | ||
142 | return tmp; | |
143 | } | |
144 | ||
145 | void CSystem::GetHomeDir() | |
146 | { | |
147 | char *tmp; | |
148 | int rcode; | |
149 | ||
150 | if (tmp = getenv("HOME")) { | |
151 | homeDir = new char[strlen(tmp)+strlen(kHomeName)+2]; | |
152 | sprintf(homeDir, "%s/%s", tmp, kHomeName); | |
153 | } else { | |
154 | homeDir = strdup("."); | |
155 | } | |
156 | rcode = mkdir(homeDir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); | |
157 | } | |
158 | ||
159 | //--------------------------------------------------------- | |
160 | CSystem::CSystem(char *theName) | |
161 | /* In: theName: Name of the application | |
162 | ||
163 | Register the application class and allocates space for the palette | |
164 | ||
165 | WP: - | |
166 | */ | |
167 | { | |
168 | GetHomeDir(); | |
169 | dataDir = new char[strlen(INSTALL_DIR)+1]; | |
170 | strcpy(dataDir, INSTALL_DIR); | |
171 | ||
172 | char *logFileName = QualifyHomeDir(kLogFileName); | |
173 | ||
174 | logFile = fopen(logFileName, "w"); // by LL | |
175 | ||
176 | strcpy(name, theName); | |
177 | ||
178 | /* Initialize SDL */ | |
179 | if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) { | |
180 | MSG("SDL_Init_Failed."); | |
181 | MSG(SDL_GetError()); | |
182 | ||
183 | exit(1); | |
184 | } | |
185 | atexit(SDL_Quit); | |
186 | ||
187 | // Ignore most events | |
188 | SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); | |
189 | SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE); | |
190 | SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE); | |
191 | SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); | |
192 | SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); | |
193 | SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); | |
194 | /* Filter quit and mouse motion events */ | |
195 | SDL_SetEventFilter(FilterEvents); | |
196 | ||
197 | #ifdef _USE_LIB_XPM | |
198 | ||
199 | SDL_Surface *icon; | |
200 | icon = XPM2Surface(QualifyDataDir("amph.xpm")); | |
201 | if (icon) { | |
202 | SDL_WM_SetIcon(icon, 0); | |
203 | DisposeBuffer(icon); | |
204 | } | |
205 | ||
206 | #endif | |
207 | ||
208 | textout = false; | |
209 | ||
210 | palColors = new RGBcolor[256]; | |
211 | palette = new SDL_Color[256]; | |
212 | startTicks = 0; | |
213 | ||
214 | } | |
215 | ||
216 | ||
217 | //------------------------------------ | |
218 | CSystem::~CSystem() | |
219 | /* | |
220 | Releases SDL | |
221 | */ | |
222 | { | |
223 | ||
224 | } | |
225 | ||
226 | //----------------------------------------------------------------------------- | |
227 | void CSystem::NewWindow(short left, short top, short width, short height) | |
228 | /* In: left, top, width, height: position and size of windows being created | |
229 | Usually left and top are set to 0 and width, height are equal to the screen size | |
230 | ||
231 | Creates a new window | |
232 | Initializes DirectX | |
233 | Calls sound initialization | |
234 | ||
235 | WP: * Application class registered | |
236 | */ | |
237 | { | |
238 | MSG("InitializeSoundSystem\n"); | |
239 | workingSound = gConfigData->haveSound && !(InitializeSoundSystem()); | |
240 | } | |
241 | ||
242 | ||
243 | //---------------------------------------------------------- | |
244 | void CSystem::DisposeWindow() | |
245 | /* | |
246 | Destroys window | |
247 | */ | |
248 | { | |
249 | SDL_Quit(); | |
250 | } | |
251 | ||
252 | ||
253 | //----------------------------------------------------------------------- | |
254 | void CSystem::AllocateScreen(short rx, short ry, short depth) | |
255 | /* In: rx, ry: Width and height of the videobuffer being allocated | |
256 | depth: Pixeldepth of video buffer. Must be set to 8 | |
257 | ||
258 | Out: - | |
259 | ||
260 | Locks the screen | |
261 | Sets the screen resolution to rx x ry | |
262 | Creates the primary video surface (which is actually the visible screen) | |
263 | ||
264 | WP: * DirectDraw - object allocated (done in NewWindow) | |
265 | * Window created | |
266 | */ | |
267 | { | |
268 | Uint32 sdl_vid_options; | |
269 | ||
270 | MSG("Allocating screens\n"); | |
271 | sdl_vid_options = SDL_INIT_TIMER | SDL_HWSURFACE|SDL_HWPALETTE; | |
272 | if (gConfigData->tryFullScreen) { | |
273 | sdl_vid_options = sdl_vid_options | SDL_FULLSCREEN; | |
274 | } | |
275 | ||
276 | screenPort=SDL_SetVideoMode(640, 480, 8, sdl_vid_options); | |
277 | if (!screenPort) { | |
278 | fprintf(stderr, "Opening a window failed: %s \n", SDL_GetError()); | |
279 | exit(1); | |
280 | } | |
281 | PaintString(name,0,0,0); | |
282 | SDL_ShowCursor(0); | |
283 | } | |
284 | ||
285 | ||
286 | // ------------------------------------------------- | |
287 | tGraphicBuffer *CSystem::AllocateBuffer(short rx, short ry) | |
288 | /* In: rx, ry: Size of buffer being allocated | |
289 | Out: Reference to new graphic buffer | |
290 | ||
291 | Allocates a new graphics buffer. The buffer is allocated in main memory | |
292 | because read access is faster on main memory than on video memory (perhaps not | |
293 | true for AGP video cards) | |
294 | ||
295 | WP: * Directdraw object created | |
296 | */ | |
297 | { | |
298 | tGraphicBuffer *port; | |
299 | ||
300 | MSG("Allocate a buffer\n"); | |
301 | port = SDL_CreateRGBSurface(SDL_SWSURFACE,rx,ry,kScreenDepth,0,0,0,0); | |
302 | if (port == NULL) Error("Error while creating an SDL Surface", 0); | |
303 | ||
304 | return port; | |
305 | } | |
306 | ||
307 | //------------------------------------------------------- | |
308 | void CSystem::DisposeScreen() | |
309 | /* Disposes the screen buffer | |
310 | */ | |
311 | { | |
312 | if (screenPort) SDL_FreeSurface(screenPort); | |
313 | } | |
314 | ||
315 | //------------------------------------------------------ | |
316 | void CSystem::DisposeBuffer(tGraphicBuffer *buffer) | |
317 | /* In: buffer: buffer being disposed | |
318 | ||
319 | Disposes the indicated graphic buffer | |
320 | ||
321 | WP: * buffer exists and is not locked | |
322 | */ | |
323 | { | |
324 | if (buffer) SDL_FreeSurface(buffer); | |
325 | } | |
326 | ||
327 | ||
328 | // -------------------------------------------------------- | |
329 | void CSystem::LoadPalette(char *name) | |
330 | /* In: name: Name of palette file. The palette file must be a *.gif image file | |
331 | with a saved palette. The image itself is ignored | |
332 | ||
333 | Reads the palette file and stores the color information in the allocated palette array | |
334 | Transforms the palette to a DirectDraw - palette and loads it | |
335 | Make this palette active for the screen buffer | |
336 | ||
337 | WP: * directDraw - object allocated | |
338 | * palette allocated (in CSystem::CSystem) | |
339 | * The file name must exist | |
340 | */ | |
341 | { | |
342 | Graphic_file *gf = read_graphic_file(QualifyDataDir(name)); | |
343 | if (!gf) Error("Cannot find or open the palette file (*.pal)", 0); | |
344 | ||
345 | for (short n = 0; n < 256; n ++) { | |
346 | palColors[n].red = gf->palette[n].red; | |
347 | palColors[n].green = gf->palette[n].green; | |
348 | palColors[n].blue = gf->palette[n].blue; | |
349 | } | |
350 | ||
351 | free_graphic_file(gf); | |
352 | ||
353 | // Alle Farben der Reihe nach aus dem File lesen | |
354 | for (short i=0; i<256; i++) { | |
355 | palette[i].r = palColors[i].red; | |
356 | palette[i].g = palColors[i].green; | |
357 | palette[i].b = palColors[i].blue; | |
358 | } | |
359 | ||
360 | // Perform funny color switch | |
361 | palette[0].r = 0; | |
362 | palette[0].g = 0; | |
363 | palette[0].b = 0; | |
364 | palette[255].r = 255; | |
365 | palette[255].g = 255; | |
366 | palette[255].b = 255; | |
367 | ||
368 | SDL_SetColors(screenPort, palette, 0, 256); | |
369 | } | |
370 | ||
371 | // -------------------------------------------------------- | |
372 | void CSystem::SetBufferPalette(tGraphicBuffer *buffer) | |
373 | /* In: buffer: The buffer the palette should be made active | |
374 | ||
375 | Makes the palette active for the indicated buffer. For each buffer this routine | |
376 | must be called | |
377 | ||
378 | WP: * buffer exists | |
379 | * The palette is loaded (done in LoadPalette) | |
380 | */ | |
381 | { | |
382 | SDL_SetColors(buffer, palette, 0, 256); | |
383 | } | |
384 | ||
385 | // ------------------------------------------------------------------------- | |
386 | unsigned char *CSystem::GetBufferPtr(tGraphicBuffer *buffer, short *width) | |
387 | // In: buffer: The buffer being locked for pixel access | |
388 | // | |
389 | // Out: width: Actual width of pixel plane of this buffer | |
390 | // | |
391 | // Prepares the graphic buffer indicated for drawing and returns the actual width | |
392 | // and the adress of the plane | |
393 | // if buffer = 0L, then the standard screen buffer will be locked | |
394 | // | |
395 | // WP: * buffer exists | |
396 | // * width points to a valid container | |
397 | { | |
398 | if ( SDL_MUSTLOCK(buffer) ) { | |
399 | if ( SDL_LockSurface(buffer) < 0 ) | |
400 | return NULL; | |
401 | } | |
402 | ||
403 | *width = buffer->pitch; | |
404 | ||
405 | return (unsigned char *)buffer->pixels; | |
406 | } | |
407 | ||
408 | // ----------------------------------------------------------- | |
409 | void CSystem::ReleaseBufferPtr(tGraphicBuffer *buffer) | |
410 | // Unlocks the graphic buffer indicated. If buffer = 0L, then the standard | |
411 | // screen buffer will be unlocked | |
412 | { | |
413 | if ( SDL_MUSTLOCK(buffer) ) { | |
414 | SDL_UnlockSurface(buffer); | |
415 | } | |
416 | } | |
417 | ||
418 | // ---------------------------------------------------------------- | |
419 | void CSystem::FlipSurfaces(tGraphicBuffer *buffer, short width, short height, short posx, short posy) | |
420 | /* In: buffer: The buffer being flipped to screen | |
421 | width, height: Width and height of the plane being flipped. Usually equal to | |
422 | the size of the buffer | |
423 | posx, posy: Position of the lefttop corner of the flipped plane on the screen | |
424 | */ | |
425 | // Blittes the content of buffer to the screen, assuming the buffer to have width X height, | |
426 | // and blitting it on the screen to position posx / posy | |
427 | // If buffer = 0L, then the standard screen buffer will be blitted using standard coordinates | |
428 | ||
429 | // WP: * The screenPort is allocated (in AllocateScreen) | |
430 | // * buffer exists | |
431 | { | |
432 | int hRet; | |
433 | SDL_Rect rcRect, destRect; | |
434 | ||
435 | if (buffer) { | |
436 | rcRect.x = 0; | |
437 | rcRect.y = 0; | |
438 | rcRect.w = width; | |
439 | rcRect.h = height; | |
440 | ||
441 | destRect.x = posx; | |
442 | destRect.y = posy; | |
443 | destRect.w = width; | |
444 | destRect.h = height; | |
445 | ||
446 | hRet = SDL_BlitSurface( buffer, &rcRect, screenPort,&destRect); | |
447 | SDL_UpdateRects(screenPort, 1, &destRect); | |
448 | } | |
449 | } | |
450 | ||
451 | void CSystem::ProcessEvents() | |
452 | { | |
453 | SDL_Event event; | |
454 | while (SDL_PollEvent(&event)) { | |
455 | ||
456 | } // Luke | |
457 | } | |
458 | ||
459 | ||
460 | //---------------------------------------------- | |
461 | boolVar CSystem::KeyPressed(short key) | |
462 | // In: key: Virtual key code of the tested key | |
463 | // Out: True if the key is being pressed | |
464 | // | |
465 | // WP: - | |
466 | { | |
467 | Uint8 *keyboard_state; | |
468 | ||
469 | ProcessEvents(); | |
470 | keyboard_state = SDL_GetKeyState(0); | |
471 | return (boolVar)(keyboard_state[key] == SDL_PRESSED); | |
472 | } | |
473 | ||
474 | //-------------------------------------------------------- | |
475 | void CSystem::Error(char *message, short errorNo) | |
476 | /* In: message: Error text | |
477 | errorNo: Error number | |
478 | ||
479 | Writes the message followed by the error number in the log file | |
480 | ||
481 | WP: * logFile exists | |
482 | */ | |
483 | { | |
484 | MSG(message); fprintf(logFile, " %d\n", errorNo); fflush(logFile); | |
485 | } | |
486 | ||
487 | ||
488 | long CSystem::GetTickCount() | |
489 | { | |
490 | // Unused | |
491 | struct timeval now; | |
492 | long ticks; | |
493 | ||
494 | gettimeofday(&now, NULL); | |
495 | ticks=now.tv_sec*1000+now.tv_usec/1000; | |
496 | return ticks; | |
497 | } | |
498 | ||
499 | //--------------------------------------------- | |
500 | long CSystem::GetTicks() | |
501 | /* Out: Ticks | |
502 | ||
503 | WP: startTicks is valid (done in ResetTicks) | |
504 | */ | |
505 | { | |
506 | return (SDL_GetTicks() + startTicks); | |
507 | } | |
508 | ||
509 | //--------------------------------------------------- | |
510 | void CSystem::ResetTicks(long startTickOffset) | |
511 | /* In: startTickOffset: Reset value for ticks | |
512 | ||
513 | */ | |
514 | { | |
515 | startTicks = -SDL_GetTicks() + startTickOffset; | |
516 | } | |
517 | ||
518 | //----------------------------------------------------------------------------------- | |
519 | void CSystem::PaintString(char *text, short x, short y, unsigned long foreColor) | |
520 | /* In: text: Text being drawn | |
521 | x, y: Position on screen | |
522 | foreColor: color of text | |
523 | ||
524 | Draws the text on the screen. Usually you do not call this routine | |
525 | ||
526 | WP: * screenPort is allocated | |
527 | */ | |
528 | { | |
529 | SDL_WM_SetCaption(text,NULL); | |
530 | } | |
531 | ||
532 | void CSystem::ScreenShot() | |
533 | { | |
534 | if (screenPort) { | |
535 | char *fileName = QualifyHomeDir("screenshot.bmp"); | |
536 | SDL_SaveBMP(screenPort, fileName); | |
537 | delete [] fileName; | |
538 | } | |
539 | } | |
540 | ||
541 | FILE *CSystem::FindFile(const char *fname) | |
542 | { | |
543 | FILE *tmp; | |
544 | ||
545 | if (tmp=fopen(gSystem->QualifyHomeDir(fname), "r")) | |
546 | return tmp; // check home directory | |
547 | else | |
548 | delete [] tmp; | |
549 | ||
550 | if (tmp=fopen(gSystem->QualifyDataDir(fname), "r")) | |
551 | return tmp; // check data directory | |
552 | else | |
553 | delete [] tmp; | |
554 | ||
555 | return NULL; // failed | |
556 | }⏎ |
0 | #ifndef __AMP_SYSTEM__ | |
1 | #define __AMP_SYSTEM__ | |
2 | ||
3 | ||
4 | #include <stdlib.h> | |
5 | #include <stdarg.h> | |
6 | #include <math.h> | |
7 | #include <stdio.h> | |
8 | #include "AmpHead.hpp" | |
9 | ||
10 | extern "C" { | |
11 | #include <SDL/SDL.h> | |
12 | } | |
13 | ||
14 | #ifndef INSTALL_DIR | |
15 | #define INSTALL_DIR "/usr/local/games/amph" | |
16 | #endif | |
17 | ||
18 | #if SDL_BYTEORDER == SDL_LIL_ENDIAN | |
19 | #undef __BIG_ENDIAN__ | |
20 | #else | |
21 | #define __BIG_ENDIAN__ 1 | |
22 | #endif | |
23 | ||
24 | typedef bool boolVar; | |
25 | ||
26 | const char kHomeName[] = ".amph"; | |
27 | ||
28 | enum { | |
29 | kKeyLeft = SDLK_LEFT, | |
30 | kKeyRight = SDLK_RIGHT, | |
31 | kKeyUp = SDLK_UP, | |
32 | kKeyDown = SDLK_DOWN, | |
33 | kKeyD = SDLK_d, | |
34 | kKeyC = SDLK_c, | |
35 | kKeyY = SDLK_y, | |
36 | kKeyX = SDLK_x, | |
37 | kKeyScrLock = SDLK_SCROLLOCK, | |
38 | kKeyPrscreen = SDLK_NUMLOCK, | |
39 | kKeyEscape = SDLK_ESCAPE, | |
40 | kKeyTab = SDLK_TAB, | |
41 | kKeyPlus = SDLK_KP_PLUS, | |
42 | kKeyMinus = SDLK_KP_MINUS, | |
43 | kKeyControl = SDLK_LCTRL, | |
44 | kKeyReturn = SDLK_RETURN, | |
45 | kKeySpace = SDLK_SPACE | |
46 | }; | |
47 | ||
48 | const unsigned char kASCIISpace = 32; | |
49 | const unsigned char kASCIIEqual = 61; | |
50 | ||
51 | const long kTicksPerSecond = 1000; | |
52 | // Windows can't change the color indexes for black and white | |
53 | const unsigned char kWhiteColor = 255; | |
54 | const unsigned char kBlackColor = 0; | |
55 | ||
56 | typedef SDL_Surface tGraphicBuffer; | |
57 | ||
58 | //************************* class CSystem ******************** | |
59 | ||
60 | class CSystem { | |
61 | protected: | |
62 | //"""""""""""""""" Misc stuff | |
63 | char name[16]; | |
64 | long startTicks; | |
65 | bool textout; | |
66 | ||
67 | //"""""""""""""""" Graphics stuff | |
68 | tGraphicBuffer *screenPort; | |
69 | SDL_Color *palette; | |
70 | #ifdef _USE_LIB_XPM | |
71 | SDL_Surface *XPM2Surface(char *pixmap); | |
72 | #endif | |
73 | ||
74 | public: | |
75 | RGBcolor *palColors; | |
76 | char *homeDir; | |
77 | char *dataDir; | |
78 | int workingSound; | |
79 | ||
80 | //"""""""""""""""" System Stuff | |
81 | CSystem(char *); | |
82 | ~CSystem(); | |
83 | ||
84 | void NewWindow(short, short, short, short); | |
85 | void DisposeWindow(); | |
86 | ||
87 | //"""""""""""""""" SDL Stuff | |
88 | void AllocateScreen(short rx, short ry, short depth); | |
89 | tGraphicBuffer *AllocateBuffer(short rx, short ry); | |
90 | void DisposeBuffer(tGraphicBuffer *); | |
91 | void DisposeScreen(); | |
92 | void LoadPalette(char *name); | |
93 | void SetBufferPalette(tGraphicBuffer *); | |
94 | unsigned char *GetBufferPtr(tGraphicBuffer *, short *width); | |
95 | void ReleaseBufferPtr(tGraphicBuffer *); | |
96 | void FlipSurfaces(tGraphicBuffer *, short width, short height, short posx, short posy); | |
97 | ||
98 | //"""""""""""""""" User stuff | |
99 | void Error(char *message, short errorNo); | |
100 | boolVar KeyPressed(short key); | |
101 | long GetTicks(); | |
102 | long GetTickCount(); | |
103 | void ResetTicks(long startTickOffset); | |
104 | void PaintString(char *, short x, short y, unsigned long color); | |
105 | void ProcessEvents(); | |
106 | void GetHomeDir(); | |
107 | char *QualifyDataDir(const char *fname); | |
108 | char *QualifyHomeDir(const char *fname); | |
109 | void ScreenShot(); | |
110 | FILE *FindFile(const char *fname); | |
111 | }; | |
112 | ||
113 | #endif |
0 | #include "Thing.hpp" | |
1 | #include "Appl.hpp" | |
2 | #include "ConstVal.hpp" | |
3 | ||
4 | extern CApplication *gApplication; | |
5 | extern tConstValues *gConst; | |
6 | extern CLevel *gLevel; | |
7 | ||
8 | ||
9 | CThing::CThing(short initx, short inity, short width, short height, short number) : CObject(initx, inity, width, height) | |
10 | { | |
11 | typeID |= kThing; | |
12 | ||
13 | dx = xe - xs; | |
14 | dy = ye - ys; | |
15 | ||
16 | weight = 10; | |
17 | next = prev = nextCollisionThing = prevCollisionThing = 0L; | |
18 | lookDirection = kLookingRight; | |
19 | weightless = 0; | |
20 | thingNumber = number; | |
21 | ||
22 | // additinal initializations | |
23 | modus = 0; | |
24 | } | |
25 | ||
26 | CThing::~CThing() | |
27 | {} | |
28 | ||
29 | void CThing::Gravitation() | |
30 | { | |
31 | if (weight && !weightless && forceVectorY < gConst->kMaxFallingSpeed * deltaTime * gConst->kVelocityUnit) forceVectorY += gConst->kGravitation * deltaTime; | |
32 | } | |
33 | ||
34 | ||
35 | void CThing::LinkInLists() | |
36 | { | |
37 | gApplication->Enqueue(&gApplication->thingList, this); | |
38 | } | |
39 | ||
40 | void CThing::UnlinkInLists() | |
41 | { | |
42 | gApplication->Dequeue(&gApplication->thingList, this); | |
43 | } | |
44 | ||
45 | ||
46 | void CThing::Render(short planeX, short planeY, tRect *clipRect) | |
47 | {} | |
48 | ||
49 | void CThing::PostRender(short planeX, short planeY, tRect *clipRect) | |
50 | {} | |
51 | ||
52 | short CThing::Forces() | |
53 | { | |
54 | short collisionObject; | |
55 | ||
56 | Gravitation(); | |
57 | ||
58 | CObject::Forces(); | |
59 | ExertForce(resForceX, resForceY, collisionObject, 0L); | |
60 | ||
61 | return kNoEvent; | |
62 | } | |
63 | ||
64 | void CThing::Move() | |
65 | { | |
66 | CElement *element; | |
67 | ||
68 | //CObject::Forces(); | |
69 | ||
70 | if (ys < kLevelHeight * kElementSize) { | |
71 | xs += resForceX + environmentForceX; | |
72 | xe += resForceX + environmentForceX; | |
73 | ys += resForceY + environmentForceY; | |
74 | ye += resForceY + environmentForceY; | |
75 | xm = xs + (xe - xs) * 0.5; | |
76 | ym = ys + (ye - ys) * 0.5; | |
77 | } | |
78 | element = gLevel->GetElement(xm, ym); | |
79 | modus = (element ? element->GetElementLiquid() : kShapemodusNormal); | |
80 | } | |
81 | ||
82 | void CThing::CalcPlaneOffsets(short &planex, short &planey) | |
83 | { | |
84 | short midx = xm; | |
85 | short midy = ym; | |
86 | ||
87 | if (midx <= kGamePlaneWidth / 2) planex = 0; | |
88 | else if (midx >= kLevelWidth * kElementSize - kGamePlaneWidth / 2) planex = kLevelWidth * kElementSize - kGamePlaneWidth; | |
89 | else planex = midx - kGamePlaneWidth / 2; | |
90 | ||
91 | if (midy <= kGamePlaneHeight / 2) planey = 0; | |
92 | else if (midy >= kLevelHeight * kElementSize - kGamePlaneHeight / 2) planey = kLevelHeight * kElementSize - kGamePlaneHeight; | |
93 | else planey = midy - kGamePlaneHeight / 2; | |
94 | } | |
95 | ||
96 | short CThing::Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject) | |
97 | { | |
98 | if (right + forcex < xs || left + forcex > xe || | |
99 | bottom + forcey < ys || top + forcey > ye) return kNoCollision; | |
100 | ||
101 | short returnValue = CObject::Collision(sender, left, top, right, bottom, forcex, forcey, pfx, pfy, sourceWeight, collisionObject); | |
102 | ||
103 | if (returnValue & (kCollisionOnBottom | kCollisionWithPushing)) { | |
104 | sender->CollisionEvent(gConst->kNormalFriction, 0); | |
105 | } | |
106 | return returnValue; | |
107 | } | |
108 | ||
109 | // ------------------------------------------------------------------------------ | |
110 | void CThing::TestForDamage(double xb, double yb, short rad, short blessure) | |
111 | // Sending a damage event to the thing if the distance to the bullet is less than rad | |
112 | { | |
113 | if ((xm - xb) * (xm - xb) + (ym - yb) * (ym - yb) <= rad * rad) OnDamage(blessure); | |
114 | } | |
115 | ||
116 | ||
117 | void CThing::OnDamage(short blessure) | |
118 | { | |
119 | } | |
120 | ||
121 | ||
122 | short CThing::Write(FILE *f) | |
123 | { | |
124 | long size = 0; | |
125 | ||
126 | WRITEDATA(size); | |
127 | WRITEDATA(typeID); | |
128 | WRITEDATA(thingNumber); | |
129 | ||
130 | size += CObject::Write(f); | |
131 | ||
132 | WRITEDATA(lookDirection); | |
133 | WRITEDATA(weightless); | |
134 | WRITEDATA(dx); | |
135 | WRITEDATA(dy); | |
136 | WRITEDATA(modus); | |
137 | ||
138 | FINISHWRITE; | |
139 | ||
140 | return size; | |
141 | } | |
142 | ||
143 | void CThing::Read(FILE *f) | |
144 | { | |
145 | long size = 0; | |
146 | ||
147 | READDATA(size); | |
148 | READDATA(typeID); | |
149 | READDATA(thingNumber); | |
150 | ||
151 | CObject::Read(f); | |
152 | ||
153 | READDATA(lookDirection); | |
154 | READDATA(weightless); | |
155 | READDATA(dx); | |
156 | READDATA(dy); | |
157 | READDATA(modus); | |
158 | } |
0 | #ifndef __AMP_THING__ | |
1 | #define __AMP_THING__ | |
2 | ||
3 | #include "Object.hpp" | |
4 | ||
5 | class CWeapon; | |
6 | class CHandWeapon; | |
7 | class CSorcery; | |
8 | class CBomb; | |
9 | class CMultiBulletWeapon; | |
10 | class CStaff; | |
11 | class CSineWeapon; | |
12 | class CGuided; | |
13 | ||
14 | enum { // Looking values | |
15 | kLookingRight = 1, | |
16 | kLookingLeft = -1 | |
17 | }; | |
18 | ||
19 | class CThing : public CObject { | |
20 | friend class CWeapon; | |
21 | friend class CHandWeapon; | |
22 | friend class CSorcery; | |
23 | friend class CBomb; | |
24 | friend class CMultiBulletWeapon; | |
25 | friend class CStaff; | |
26 | friend class CSineWeapon; | |
27 | friend class CGuided; | |
28 | ||
29 | protected: | |
30 | short lookDirection; // in which direction the thing looks | |
31 | short weightless; | |
32 | short dx, dy; | |
33 | short modus; | |
34 | short thingNumber; | |
35 | ||
36 | public: | |
37 | CThing *next, *prev, *nextCollisionThing, *prevCollisionThing; | |
38 | CThing *nextPreRenderThing, *prevPreRenderThing; | |
39 | CThing *nextPostRenderThing, *prevPostRenderThing; | |
40 | ||
41 | ||
42 | CThing(short initx, short inity, short width, short height, short number); | |
43 | ~CThing(); | |
44 | ||
45 | void Gravitation(); | |
46 | virtual void LinkInLists(); | |
47 | virtual void UnlinkInLists(); | |
48 | ||
49 | virtual void Render(short planeX, short planeY, tRect *clipRect); | |
50 | virtual void PostRender(short planeX, short planeY, tRect *clipRect); | |
51 | virtual void Move(); | |
52 | virtual short Forces(); | |
53 | void CalcPlaneOffsets(short &planex, short &planey); | |
54 | short Collision(CObject *sender, double left, double top, double right, double bottom, double &forcex, double &forcey, double pfx, double pfy, short sourceWeight, short &collisionObject); | |
55 | virtual void TestForDamage(double xb, double yb, short rad, short blessure); | |
56 | ||
57 | virtual void OnDamage(short blessure); | |
58 | ||
59 | virtual short Write(FILE *f); | |
60 | virtual void Read(FILE *f); | |
61 | ||
62 | ||
63 | ||
64 | }; | |
65 | ||
66 | #endif⏎ |
0 | #include "Weapon.hpp" | |
1 | #include "System.hpp" | |
2 | #include "Bullet.hpp" | |
3 | #include "Appl.hpp" | |
4 | #include "Thing.hpp" | |
5 | #include "ConstVal.hpp" | |
6 | #include "SndSys.hpp" | |
7 | ||
8 | extern CSystem *gSystem; | |
9 | extern CApplication *gApplication; | |
10 | extern tConstValues *gConst; | |
11 | extern CLevel *gLevel; | |
12 | extern CSoundSystem *gSoundSystem; | |
13 | ||
14 | short *FindDescriptor(short id); | |
15 | ||
16 | ||
17 | CWeapon::CWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) | |
18 | { | |
19 | owner = own; | |
20 | info = weaponInfo; | |
21 | attackShape = attack; | |
22 | lastShoot = 0; | |
23 | lastShootFrame = 0; // by LL | |
24 | weaponStatus = kWeaponDoesntExist; | |
25 | munition = 0; | |
26 | repetition = (owner->typeID & kPlayer) ? info->repetition : info->repetition * gApplication->currentWeaponSF; | |
27 | } | |
28 | ||
29 | CWeapon::~CWeapon() | |
30 | {} | |
31 | ||
32 | void CWeapon::AddMunition(short mun) | |
33 | { | |
34 | munition += mun; | |
35 | munition = MIN(munition, info->munition); | |
36 | if (weaponStatus == kWeaponOutOfMunition) weaponStatus = kWeaponReady; | |
37 | } | |
38 | ||
39 | short CWeapon::Shoot(double directionx, double directiony, double targetpos) | |
40 | { | |
41 | CBullet *temp; | |
42 | short *descr; | |
43 | ||
44 | if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { | |
45 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
46 | lastShoot = gSystem->GetTicks() + repetition; | |
47 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
48 | descr = FindDescriptor(info->projectileShapes[0]); | |
49 | temp = new CBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos); | |
50 | ||
51 | munition --; | |
52 | if (!munition) weaponStatus = kWeaponOutOfMunition; | |
53 | ||
54 | return 1; | |
55 | }else return 0; | |
56 | } | |
57 | ||
58 | short CWeapon::ShootAnimation(CShape **currentShape) | |
59 | { | |
60 | if (owner->lastTime < lastShootFrame) { | |
61 | *currentShape = attackShape; | |
62 | return 0; | |
63 | }else return 1; | |
64 | } | |
65 | ||
66 | ||
67 | void CWeapon::SaveDataToNextLevel(short *mun, short *stat) | |
68 | { | |
69 | *mun = munition; | |
70 | *stat = weaponStatus; | |
71 | } | |
72 | ||
73 | void CWeapon::RestoreDataFromPrevLevel(short mun, short stat) | |
74 | { | |
75 | munition = mun; | |
76 | weaponStatus = stat; | |
77 | } | |
78 | ||
79 | CHandWeapon::CHandWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack1, CShape *attack2, CShape *attack3) : CWeapon(own, weaponInfo, attack1) | |
80 | { | |
81 | numAnimFrames = 1; | |
82 | attackShape2 = attack2; if (attackShape2) numAnimFrames = 2; | |
83 | attackShape3 = attack3; if (attackShape3) numAnimFrames = 3; | |
84 | ||
85 | animationFrame = 4; | |
86 | shootFrameTime = gConst->kShootFrameTime * (4 - numAnimFrames); | |
87 | } | |
88 | ||
89 | CHandWeapon::~CHandWeapon() {} | |
90 | ||
91 | short CHandWeapon::Shoot(double directionx, double unused, double unused2) | |
92 | { | |
93 | if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { | |
94 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
95 | lastShoot = gSystem->GetTicks() + repetition; | |
96 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
97 | animationFrame = 0; | |
98 | ||
99 | return 1; | |
100 | }else return 0; | |
101 | } | |
102 | ||
103 | short CHandWeapon::ShootAnimation(CShape **currentShape) | |
104 | { | |
105 | if (animationFrame < numAnimFrames) { | |
106 | switch (animationFrame) { | |
107 | case 0: *currentShape = attackShape; break; | |
108 | case 1: *currentShape = attackShape2; break; | |
109 | case 2: *currentShape = attackShape3; break; | |
110 | } | |
111 | if (owner->lastTime > lastShootFrame) { | |
112 | animationFrame ++; | |
113 | lastShootFrame = owner->lastTime + shootFrameTime; | |
114 | } | |
115 | return 0; | |
116 | }else if (animationFrame == numAnimFrames) { | |
117 | ||
118 | tThingList *currentEntry = gApplication->collisionThingList; | |
119 | ||
120 | while (currentEntry) { | |
121 | if (currentEntry->thing != owner) currentEntry->thing->TestForDamage(owner->lookDirection == kLookingRight ? owner->xe : owner->xs, owner->ye - gConst->kWeaponCarryHeight, info->rad, info->damage); | |
122 | currentEntry = currentEntry->next; | |
123 | } | |
124 | animationFrame = SHRT_MAX; | |
125 | } | |
126 | return 1; | |
127 | } | |
128 | ||
129 | CSorcery::CSorcery(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) : CWeapon(own, weaponInfo, attack) | |
130 | {} | |
131 | ||
132 | CSorcery::~CSorcery() {} | |
133 | ||
134 | short CSorcery::Shoot(double directionx, double directiony, double unused) | |
135 | { | |
136 | CBullet *temp; | |
137 | short *descr; | |
138 | ||
139 | if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { | |
140 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
141 | lastShoot = gSystem->GetTicks() + repetition; | |
142 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
143 | descr = FindDescriptor(info->projectileShapes[0]); | |
144 | temp = new CSorceryBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, ABS(directionx), owner, 0); | |
145 | ||
146 | munition --; | |
147 | if (!munition) weaponStatus = kWeaponOutOfMunition; | |
148 | ||
149 | return 1; | |
150 | }else return 0; | |
151 | } | |
152 | ||
153 | CBomb::CBomb(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, CShape *det) : CWeapon(own, weaponInfo, attack) | |
154 | { | |
155 | status = kReady; | |
156 | detonator = det; | |
157 | } | |
158 | ||
159 | CBomb::~CBomb() {} | |
160 | ||
161 | short CBomb::Shoot(double directionx, double directiony, double unused) | |
162 | { | |
163 | CBombBullet *temp; | |
164 | short *descr; | |
165 | ||
166 | if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { | |
167 | lastShoot = gSystem->GetTicks() + repetition; | |
168 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
169 | ||
170 | if (status == kReady) { | |
171 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
172 | status = kDetonation; | |
173 | descr = FindDescriptor(info->projectileShapes[0]); | |
174 | temp = new CBombBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, 0); | |
175 | bomb = temp; | |
176 | ||
177 | munition --; | |
178 | }else{ | |
179 | gSoundSystem->Play(gSoundSystem->weaponHitSounds[weaponNumber], bomb->xm, bomb->ym); | |
180 | if (bomb) ((CBombBullet *)bomb)->detonate = 1; | |
181 | bomb = 0L; | |
182 | status = kReady; | |
183 | if (!munition) weaponStatus = kWeaponOutOfMunition; | |
184 | } | |
185 | return 1; | |
186 | }else return 0; | |
187 | } | |
188 | ||
189 | short CBomb::ShootAnimation(CShape **currentShape) | |
190 | { | |
191 | if (status == kDetonation) *currentShape = detonator; | |
192 | if (owner->lastTime < lastShootFrame && status == kDetonation) *currentShape = attackShape; | |
193 | return 1; | |
194 | } | |
195 | ||
196 | ||
197 | CMultiBulletWeapon::CMultiBulletWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, double angle) : CWeapon(own, weaponInfo, attack) | |
198 | { | |
199 | numOfBullets = weaponInfo->error; | |
200 | alpha = angle; | |
201 | initAlpha = (double)(numOfBullets - 1) / 2.0 * alpha; | |
202 | } | |
203 | ||
204 | CMultiBulletWeapon::~CMultiBulletWeapon() {} | |
205 | ||
206 | ||
207 | short CMultiBulletWeapon::Shoot(double directionx, double directiony, double targetpos) | |
208 | { | |
209 | CBullet *temp; | |
210 | short *descr; | |
211 | double dx, dy, tmp; | |
212 | ||
213 | if (weaponStatus == kWeaponReady && lastShoot <= gSystem->GetTicks()) { | |
214 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
215 | lastShoot = gSystem->GetTicks() + repetition; | |
216 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
217 | descr = FindDescriptor(info->projectileShapes[0]); | |
218 | ||
219 | dx = directionx * cos(initAlpha) - directiony * sin(initAlpha); | |
220 | dy = directionx * sin(initAlpha) + directiony * cos(initAlpha); | |
221 | for (short n = 0; n < numOfBullets && weaponStatus == kWeaponReady; n ++) { | |
222 | temp = new CBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, dx, dy, owner, targetpos); | |
223 | ||
224 | munition --; | |
225 | if (!munition) weaponStatus = kWeaponOutOfMunition; | |
226 | ||
227 | tmp = dx * cos(alpha) + dy * sin(alpha); | |
228 | dy = -dx * sin(alpha) + dy * cos(alpha); | |
229 | dx = tmp; | |
230 | } | |
231 | ||
232 | return 1; | |
233 | }else return 0; | |
234 | } | |
235 | ||
236 | ||
237 | CStaff::CStaff(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, CShape *load) : CWeapon(own, weaponInfo, attack) | |
238 | { | |
239 | loaded = load; | |
240 | inLoad = 0; | |
241 | lastLoad = 0; | |
242 | } | |
243 | ||
244 | CStaff::~CStaff() | |
245 | {} | |
246 | ||
247 | ||
248 | short CStaff::Shoot(double directionx, double directiony, double targetpos) | |
249 | { | |
250 | long time = gSystem->GetTicks(); | |
251 | ||
252 | dx = directionx; | |
253 | dy = directiony; | |
254 | ||
255 | if (time - lastLoad < 100) { | |
256 | lastLoad = time; | |
257 | if (time - staffLoadTime >= gConst->kStaffLoadTime) inLoad = 1; | |
258 | }else if (lastShoot <= time && weaponStatus == kWeaponReady) { | |
259 | lastLoad = time; | |
260 | staffLoadTime = time; | |
261 | } | |
262 | ||
263 | return 0; | |
264 | } | |
265 | ||
266 | ||
267 | short CStaff::ShootAnimation(CShape **currentShape) | |
268 | { | |
269 | long time = gSystem->GetTicks(); | |
270 | ||
271 | if (time - lastLoad < 100) { // Weapon is in load | |
272 | if (time - staffLoadTime < gConst->kStaffLoadTime) | |
273 | *currentShape = attackShape; | |
274 | else *currentShape = loaded; | |
275 | return 0; | |
276 | }else if (inLoad) { // Weapon is released | |
277 | CBullet *temp; | |
278 | short *descr; | |
279 | ||
280 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
281 | lastShoot = gSystem->GetTicks() + repetition; | |
282 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
283 | descr = FindDescriptor(info->projectileShapes[0]); | |
284 | temp = new CSineBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, dx, 0, owner, 0, gConst->kSineWeaponRad, info->error); | |
285 | ||
286 | munition --; | |
287 | if (!munition) weaponStatus = kWeaponOutOfMunition; | |
288 | ||
289 | inLoad = 0; | |
290 | } | |
291 | ||
292 | if (time < lastShootFrame) { | |
293 | *currentShape = loaded; | |
294 | return 0; | |
295 | } | |
296 | return 1; | |
297 | } | |
298 | ||
299 | ||
300 | CSineWeapon::CSineWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack, short rad) : CWeapon(own, weaponInfo, attack) | |
301 | { | |
302 | radius = rad; | |
303 | } | |
304 | ||
305 | CSineWeapon::~CSineWeapon() | |
306 | {} | |
307 | ||
308 | short CSineWeapon::Shoot(double directionx, double directiony, double targetpos) | |
309 | { | |
310 | CBullet *temp; | |
311 | short *descr; | |
312 | ||
313 | if (lastShoot <= gSystem->GetTicks()) { | |
314 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
315 | lastShoot = gSystem->GetTicks() + repetition; | |
316 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
317 | descr = FindDescriptor(info->projectileShapes[0]); | |
318 | temp = new CSineBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos, radius, info->error); | |
319 | return 1; | |
320 | }else return 0; | |
321 | } | |
322 | ||
323 | CGuided::CGuided(CThing *own, tWeaponInfo *weaponInfo, CShape *attack) : CWeapon(own, weaponInfo, attack) | |
324 | { | |
325 | } | |
326 | ||
327 | CGuided::~CGuided() | |
328 | {} | |
329 | ||
330 | short CGuided::Shoot(double directionx, double directiony, double targetpos) | |
331 | { | |
332 | CBullet *temp; | |
333 | short *descr; | |
334 | ||
335 | if (lastShoot <= gSystem->GetTicks()) { | |
336 | gSoundSystem->Play(gSoundSystem->weaponLaunchSounds[weaponNumber], owner->xm, owner->ym); | |
337 | lastShoot = gSystem->GetTicks() + repetition; | |
338 | lastShootFrame = gSystem->GetTicks() + gConst->kShootFrameTime; | |
339 | descr = FindDescriptor(info->projectileShapes[0]); | |
340 | temp = new CGuidedBullet((owner->lookDirection == kLookingRight ? owner->xe - descr[3] / 2 - kWeaponBodyOffset : owner->xs + kWeaponBodyOffset + descr[3] / 2), owner->ye - gConst->kWeaponCarryHeight, descr[3], descr[4], weaponNumber, info, directionx, directiony, owner, targetpos, gLevel->player); | |
341 | ||
342 | return 1; | |
343 | }else return 0; | |
344 | } | |
345 | ||
346 | ||
347 | ||
348 | short CWeapon::Write(FILE *f) | |
349 | { | |
350 | long size = 0; | |
351 | ||
352 | WRITEDATA(size); | |
353 | ||
354 | WRITEDATA(munition); | |
355 | WRITEDATA(lastShoot); | |
356 | WRITEDATA(lastShootFrame); | |
357 | WRITEDATA(weaponStatus); | |
358 | WRITEDATA(repetition); | |
359 | ||
360 | FINISHWRITE; | |
361 | ||
362 | return size; | |
363 | } | |
364 | ||
365 | void CWeapon::Read(FILE *f) | |
366 | { | |
367 | long size = 0; | |
368 | ||
369 | READDATA(size); | |
370 | ||
371 | READDATA(munition); | |
372 | READDATA(lastShoot); | |
373 | READDATA(lastShootFrame); | |
374 | READDATA(weaponStatus); | |
375 | READDATA(repetition); | |
376 | } | |
377 | ||
378 | short CHandWeapon::Write(FILE *f) | |
379 | { | |
380 | long size = 0; | |
381 | ||
382 | WRITEDATA(size); | |
383 | ||
384 | size += CWeapon::Write(f); | |
385 | ||
386 | WRITEDATA(animationFrame); | |
387 | WRITEDATA(numAnimFrames); | |
388 | WRITEDATA(shootFrameTime); | |
389 | ||
390 | FINISHWRITE; | |
391 | ||
392 | return size; | |
393 | } | |
394 | ||
395 | void CHandWeapon::Read(FILE *f) | |
396 | { | |
397 | long size = 0; | |
398 | ||
399 | READDATA(size); | |
400 | ||
401 | CWeapon::Read(f); | |
402 | ||
403 | READDATA(animationFrame); | |
404 | READDATA(numAnimFrames); | |
405 | READDATA(shootFrameTime); | |
406 | ||
407 | } | |
408 | ||
409 | short CBomb::Write(FILE *f) | |
410 | { | |
411 | long size = 0; | |
412 | ||
413 | WRITEDATA(size); | |
414 | ||
415 | size += CWeapon::Write(f); | |
416 | ||
417 | WRITEDATA(status); | |
418 | ||
419 | FINISHWRITE; | |
420 | ||
421 | return size; | |
422 | } | |
423 | ||
424 | void CBomb::Read(FILE *f) | |
425 | { | |
426 | long size = 0; | |
427 | ||
428 | READDATA(size); | |
429 | ||
430 | CWeapon::Read(f); | |
431 | ||
432 | READDATA(status); | |
433 | } | |
434 | ||
435 | ||
436 | short CStaff::Write(FILE *f) | |
437 | { | |
438 | long size = 0; | |
439 | ||
440 | WRITEDATA(size); | |
441 | ||
442 | size += CWeapon::Write(f); | |
443 | ||
444 | WRITEDATA(staffLoadTime); | |
445 | WRITEDATA(lastLoad); | |
446 | WRITEDATA(inLoad); | |
447 | WRITEDATA(dx); | |
448 | WRITEDATA(dy); | |
449 | ||
450 | FINISHWRITE; | |
451 | ||
452 | return size; | |
453 | } | |
454 | ||
455 | void CStaff::Read(FILE *f) | |
456 | { | |
457 | long size = 0; | |
458 | ||
459 | READDATA(size); | |
460 | ||
461 | CWeapon::Read(f); | |
462 | ||
463 | READDATA(staffLoadTime); | |
464 | READDATA(lastLoad); | |
465 | READDATA(inLoad); | |
466 | READDATA(dx); | |
467 | READDATA(dy); | |
468 | ||
469 | }⏎ |
0 | #ifndef __AMP_WEAPON__ | |
1 | #define __AMP_WEAPON__ | |
2 | ||
3 | #include "ObjInfo.hpp" | |
4 | #include "Thing.hpp" | |
5 | #include "SoundList.hpp" | |
6 | ||
7 | const short kWeaponBodyOffset = 3; // At which direction of the body the shooted bullet is placed | |
8 | ||
9 | class CGUI; | |
10 | ||
11 | class CWeapon { | |
12 | friend class CGUI; | |
13 | ||
14 | protected: | |
15 | CThing *owner; | |
16 | tWeaponInfo *info; | |
17 | CShape *attackShape; | |
18 | short munition; | |
19 | ||
20 | long lastShoot, lastShootFrame; | |
21 | short repetition; | |
22 | ||
23 | CSound *launchSound, *hitSound; | |
24 | ||
25 | ||
26 | public: | |
27 | long ID; | |
28 | long savedID; | |
29 | short weaponStatus; | |
30 | short weaponNumber; | |
31 | ||
32 | CWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack); | |
33 | ~CWeapon(); | |
34 | ||
35 | void SetID(long); | |
36 | ||
37 | void AddMunition(short munition); | |
38 | virtual short Shoot(double directionx, double directiony, double targetpos); | |
39 | virtual short ShootAnimation(CShape **); | |
40 | ||
41 | void SaveDataToNextLevel(short *, short *); | |
42 | void RestoreDataFromPrevLevel(short, short); | |
43 | ||
44 | virtual short Write(FILE *f); | |
45 | virtual void Read(FILE *f); | |
46 | }; | |
47 | ||
48 | ||
49 | class CHandWeapon : public CWeapon { | |
50 | protected: | |
51 | CShape *attackShape2, *attackShape3; | |
52 | short animationFrame; | |
53 | short numAnimFrames; | |
54 | long shootFrameTime; | |
55 | ||
56 | public: | |
57 | CHandWeapon(CThing *own, tWeaponInfo *weaponInfo, CShape *attack1, CShape *attack2, CShape *attack3); | |
58 | ~CHandWeapon(); | |
59 | ||
60 | short Shoot(double directionx, double directiony, double targetpos); | |
61 | short ShootAnimation(CShape **); | |
62 | ||
63 | short Write(FILE *f); | |
64 | void Read(FILE *f); | |
65 | }; | |
66 | ||
67 | ||
68 | class CSorcery : public CWeapon { | |
69 | protected: | |
70 | ||
71 | public: | |
72 | CSorcery(CThing *own, tWeaponInfo *weaponInfo, CShape *attack); | |
73 | ~CSorcery(); | |
74 | ||
75 | short Shoot(double directionx, double directiony, double unused); | |
76 | }; | |
77 | ||
78 | enum { // stati | |
79 | kReady, | |
80 | kDetonation | |
81 | }; | |
82 | ||
83 | class CBomb : public CWeapon { | |
84 | protected: | |
85 | short status; | |
86 | CThing *bomb; | |
87 | CShape *detonator; | |
88 | ||
89 | public: | |
90 | CBomb(CThing *own, tWeaponInfo *info, CShape *attack, CShape *det); | |
91 | ~CBomb(); | |
92 | ||
93 | short Shoot(double directionx, double directiony, double unused); | |
94 | short ShootAnimation(CShape **); | |
95 | ||
96 | short Write(FILE *f); | |
97 | void Read(FILE *f); | |
98 | }; | |
99 | ||
100 | class CMultiBulletWeapon : public CWeapon { | |
101 | protected: | |
102 | short numOfBullets; | |
103 | double alpha, initAlpha; | |
104 | ||
105 | public: | |
106 | CMultiBulletWeapon(CThing *own, tWeaponInfo *info, CShape *attack, double angle); | |
107 | ~CMultiBulletWeapon(); | |
108 | ||
109 | short Shoot(double directionx, double directiony, double targetpos); | |
110 | }; | |
111 | ||
112 | ||
113 | class CStaff : public CWeapon { | |
114 | protected: | |
115 | long staffLoadTime; | |
116 | long lastLoad; | |
117 | short inLoad; | |
118 | CShape *loaded; | |
119 | double dx, dy; | |
120 | ||
121 | public: | |
122 | CStaff(CThing *own, tWeaponInfo *info, CShape *attack, CShape *load); | |
123 | ~CStaff(); | |
124 | ||
125 | short Shoot(double directionx, double directiony, double unused); | |
126 | short ShootAnimation(CShape **); | |
127 | ||
128 | short Write(FILE *f); | |
129 | void Read(FILE *f); | |
130 | }; | |
131 | ||
132 | ||
133 | class CSineWeapon : public CWeapon { | |
134 | protected: | |
135 | short radius; | |
136 | ||
137 | public: | |
138 | CSineWeapon(CThing *own, tWeaponInfo *info, CShape *attack, short rad); | |
139 | ~CSineWeapon(); | |
140 | ||
141 | short Shoot(double directionx, double directiony, double targetpos); | |
142 | }; | |
143 | ||
144 | ||
145 | class CGuided : public CWeapon | |
146 | { | |
147 | public: | |
148 | CGuided(CThing *own, tWeaponInfo *info, CShape *attack); | |
149 | ~CGuided(); | |
150 | ||
151 | short Shoot(double directionx, double directiony, double targetpos); | |
152 | }; | |
153 | ||
154 | #endif⏎ |