Squashed 'external/pure_doom/PureDOOM/' content from commit 5694fa4
git-subtree-dir: external/pure_doom/PureDOOM git-subtree-split: 5694fa42089714cb3c9edc1c8e10e4e6b6e9adb9
This commit is contained in:
commit
0132cbcf33
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
build/
|
||||
*.wad
|
||||
.doomrc
|
||||
references/
|
||||
.DS_Store
|
||||
.vscode
|
||||
*.DLL
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "thirdparty/SDL"]
|
||||
path = thirdparty/SDL
|
||||
url = https://github.com/SDL-mirror/SDL.git
|
||||
[submodule "thirdparty/SFML"]
|
||||
path = thirdparty/SFML
|
||||
url = https://github.com/SFML/SFML.git
|
5
CMakeLists.txt
Normal file
5
CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(PureDOOM)
|
||||
|
||||
add_subdirectory(examples/SDL)
|
339
LICENSE
Normal file
339
LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
48583
PureDOOM.h
Normal file
48583
PureDOOM.h
Normal file
File diff suppressed because it is too large
Load Diff
266
README.md
Normal file
266
README.md
Normal file
@ -0,0 +1,266 @@
|
||||
![](images/PureDOOM.png)
|
||||
|
||||
# Pure DOOM
|
||||
Header only, no dependencies DOOM source port. Designed to run on any devices.
|
||||
|
||||
Primarily of interest to people that want to "run DOOM on their microwave".
|
||||
|
||||
## LICENSE
|
||||
See end of file for license information.
|
||||
|
||||
## Main Features:
|
||||
- Single header
|
||||
- Pure-C, No includes dependencies: no stdlib, stdio, etc.
|
||||
- Supports 32 bits and 64 bits
|
||||
|
||||
## Other Features:
|
||||
- Menu option to disable mouse move Forward/Backward
|
||||
- Crosshair option
|
||||
- Always-Run option
|
||||
|
||||
## TODOs
|
||||
- Custom resolution
|
||||
- Remove exit and have update return 0 on quit. Add doom_get_exit_code()
|
||||
- Implement Sockets and Multiplayer
|
||||
- Print message when discovered a secret
|
||||
|
||||
## Cool TODOs to have
|
||||
- Rebindable keys
|
||||
- Unlocked FPS
|
||||
- Release mouse in menus and use it for clicking
|
||||
- Wipe screen freezes menu
|
||||
- Use floats instead of fixed_t
|
||||
- French and german
|
||||
- Full color mode (Don't use COLORMAPS, use full 24 bits RGB)
|
||||
|
||||
## Usage
|
||||
Call `doom_init()`, then call `doom_update()` every frame, or as often as you can. This will run DOOM, without any video, inputs, sounds or music.
|
||||
|
||||
```c
|
||||
#define DOOM_IMPLEMENTATION
|
||||
#include "PureDOOM.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
doom_init(argc, argv, 0);
|
||||
while (true)
|
||||
{
|
||||
doom_update();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Enable features
|
||||
Most standard headers are available on most platforms. Define these preprocessors to toggle these features.
|
||||
|
||||
- `DOOM_IMPLEMENT_PRINT`. Allows printf, requires `<stdio.h>`
|
||||
- `DOOM_IMPLEMENT_MALLOC`. Allows malloc/free, requires `<stdlib.h>`
|
||||
- `DOOM_IMPLEMENT_FILE_IO`. Allows FILE, requires `<stdio.h>`
|
||||
- `DOOM_IMPLEMENT_GETTIME`. Requires `<sys/time.h>` or `<winsock.h>`
|
||||
- `DOOM_IMPLEMENT_EXIT`. Allows exit(), requires `<stdlib.h>`
|
||||
- `DOOM_IMPLEMENT_GETENV`. Requires `<stdlib.h>`
|
||||
|
||||
If your microwave doesn't have these headers, you can override their default implementations:
|
||||
|
||||
```c
|
||||
void doom_set_print(doom_print_fn print_fn);
|
||||
void doom_set_malloc(doom_malloc_fn malloc_fn, doom_free_fn free_fn);
|
||||
void doom_set_file_io(doom_open_fn open_fn,
|
||||
doom_close_fn close_fn,
|
||||
doom_read_fn read_fn,
|
||||
doom_write_fn write_fn,
|
||||
doom_seek_fn seek_fn,
|
||||
doom_tell_fn tell_fn,
|
||||
doom_eof_fn eof_fn);
|
||||
void doom_set_gettime(doom_gettime_fn gettime_fn);
|
||||
void doom_set_exit(doom_exit_fn exit_fn);
|
||||
void doom_set_getenv(doom_getenv_fn getenv_fn);
|
||||
```
|
||||
|
||||
## Video
|
||||
Every frame, after having called `doom_update()`, you can get the screen pixels with `doom_get_framebuffer` and display it as you please.
|
||||
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
doom_update();
|
||||
uint8_t* framebuffer = doom_get_framebuffer(4 /* RGBA */);
|
||||
// ... Display framebuffer
|
||||
}
|
||||
```
|
||||
|
||||
## Inputs
|
||||
When you receive input events from your microwave touch pad, simply call one of the DOOM input events:
|
||||
|
||||
```c
|
||||
void doom_key_down(doom_key_t key);
|
||||
void doom_key_up(doom_key_t key);
|
||||
void doom_button_down(doom_button_t button);
|
||||
void doom_button_up(doom_button_t button);
|
||||
void doom_mouse_move(int delta_x, int delta_y);
|
||||
```
|
||||
|
||||
## Sounds
|
||||
Create a sound thread that outputs at 11025hz (`DOOM_SAMPLERATE`), 512 samples, 16 bits, stereo. Then in your sound callback, call `doom_get_sound_buffer` to update and get the current DOOM's sound output. Make sure to add synchronization primitives around this and `doom_update` if your sound loop is in a thread.
|
||||
|
||||
Here is a quick example using SDL audio callback:
|
||||
```c
|
||||
void sdl_audio_callback(void* userdata, Uint8* stream, int len)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
int16_t* buffer = doom_get_sound_buffer(len);
|
||||
SDL_UnlockAudio();
|
||||
|
||||
memcpy(stream, buffer, len);
|
||||
}
|
||||
```
|
||||
|
||||
You can use different bitrate, but make sure to resample because DOOM will always be 11025hz, 512 samples, 16 bits, 2 channels. For a total for 2048 bytes per buffer.
|
||||
|
||||
## Music
|
||||
Set a timer in your application that runs at 140hz. In the timer's callback, tick DOOM's music as long as there are MIDI messages to send.
|
||||
|
||||
Here is an example using Window's MultiMedia to play MIDI events, using an SDL timer.
|
||||
```c
|
||||
Uint32 tick_music(Uint32 interval, void *param)
|
||||
{
|
||||
uint32_t midi_msg;
|
||||
|
||||
SDL_LockAudio();
|
||||
|
||||
while (midi_msg = doom_tick_midi())
|
||||
midiOutShortMsg(midi_out_handle, midi_msg);
|
||||
|
||||
SDL_UnlockAudio();
|
||||
|
||||
return 1000 / DOOM_MIDI_RATE /* 140 */;
|
||||
}
|
||||
```
|
||||
|
||||
## Change default settings
|
||||
Default input setup in DOOM's source is not modern. It uses Arrows to move and `','` / `'.'` to strafe. You can call `doom_set_default_int` and `doom_set_default_str` to change them:
|
||||
|
||||
```c
|
||||
// Change default bindings to modern mapping
|
||||
doom_set_default_int("key_up", DOOM_KEY_W);
|
||||
doom_set_default_int("key_down", DOOM_KEY_S);
|
||||
doom_set_default_int("key_strafeleft", DOOM_KEY_A);
|
||||
doom_set_default_int("key_straferight", DOOM_KEY_D);
|
||||
doom_set_default_int("key_use", DOOM_KEY_E);
|
||||
doom_set_default_int("mouse_move", 0); // Mouse will not move forward
|
||||
```
|
||||
|
||||
Refer to the defaults in `m_misc.cpp` for the complete list.
|
||||
|
||||
## Working SDL Example
|
||||
See the file `src/sdl_example.c` for a complete SDL example.
|
||||
|
||||
# DOOM LICENSE
|
||||
```
|
||||
LIMITED USE SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
This Limited Use Software License Agreement (the "Agreement")
|
||||
is a legal agreement between you, the end-user, and Id Software, Inc.
|
||||
("ID"). By downloading or purchasing the software material, which
|
||||
includes source code (the "Source Code"), artwork data, music and
|
||||
software tools (collectively, the "Software"), you are agreeing to
|
||||
be bound by the terms of this Agreement. If you do not agree to the
|
||||
terms of this Agreement, promptly destroy the Software you may have
|
||||
downloaded or copied.
|
||||
|
||||
ID SOFTWARE LICENSE
|
||||
|
||||
1. Grant of License. ID grants to you the right to use the
|
||||
Software. You have no ownership or proprietary rights in or to the
|
||||
Software, or the Trademark. For purposes of this section, "use" means
|
||||
loading the Software into RAM, as well as installation on a hard disk
|
||||
or other storage device. The Software, together with any archive copy
|
||||
thereof, shall be destroyed when no longer used in accordance with
|
||||
this Agreement, or when the right to use the Software is terminated.
|
||||
You agree that the Software will not be shipped, transferred or
|
||||
exported into any country in violation of the U.S. Export
|
||||
Administration Act (or any other law governing such matters) and that
|
||||
you will not utilize, in any other manner, the Software in violation
|
||||
of any applicable law.
|
||||
|
||||
2. Permitted Uses. For educational purposes only, you, the
|
||||
end-user, may use portions of the Source Code, such as particular
|
||||
routines, to develop your own software, but may not duplicate the
|
||||
Source Code, except as noted in paragraph 4. The limited right
|
||||
referenced in the preceding sentence is hereinafter referred to as
|
||||
"Educational Use." By so exercising the Educational Use right you
|
||||
shall not obtain any ownership, copyright, proprietary or other
|
||||
interest in or to the Source Code, or any portion of the Source
|
||||
Code. You may dispose of your own software in your sole discretion.
|
||||
With the exception of the Educational Use right, you may not
|
||||
otherwise use the Software, or an portion of the Software, which
|
||||
includes the Source Code, for commercial gain.
|
||||
|
||||
3. Prohibited Uses: Under no circumstances shall you, the
|
||||
end-user, be permitted, allowed or authorized to commercially exploit
|
||||
the Software. Neither you nor anyone at your direction shall do any
|
||||
of the following acts with regard to the Software, or any portion
|
||||
thereof:
|
||||
|
||||
Rent;
|
||||
|
||||
Sell;
|
||||
|
||||
Lease;
|
||||
|
||||
Offer on a pay-per-play basis;
|
||||
|
||||
Distribute for money or any other consideration; or
|
||||
|
||||
In any other manner and through any medium whatsoever
|
||||
commercially exploit or use for any commercial purpose.
|
||||
|
||||
Notwithstanding the foregoing prohibitions, you may commercially
|
||||
exploit the software you develop by exercising the Educational Use
|
||||
right, referenced in paragraph 2. hereinabove.
|
||||
|
||||
4. Copyright. The Software and all copyrights related thereto
|
||||
(including all characters and other images generated by the Software
|
||||
or depicted in the Software) are owned by ID and is protected by
|
||||
United States copyright laws and international treaty provisions.
|
||||
Id shall retain exclusive ownership and copyright in and to the
|
||||
Software and all portions of the Software and you shall have no
|
||||
ownership or other proprietary interest in such materials. You must
|
||||
treat the Software like any other copyrighted material. You may not
|
||||
otherwise reproduce, copy or disclose to others, in whole or in any
|
||||
part, the Software. You may not copy the written materials
|
||||
accompanying the Software. You agree to use your best efforts to
|
||||
see that any user of the Software licensed hereunder complies with
|
||||
this Agreement.
|
||||
|
||||
5. NO WARRANTIES. ID DISCLAIMS ALL WARRANTIES, BOTH EXPRESS
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT
|
||||
TO THE SOFTWARE. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||
RIGHTS. YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
|
||||
JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE
|
||||
WILL BE UNINTERRUPTED, ERROR FREE OR MEET YOUR SPECIFIC REQUIREMENTS.
|
||||
THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
|
||||
WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
|
||||
DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
|
||||
MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
|
||||
OF ID.
|
||||
|
||||
Exclusive Remedies. The Software is being offered to you
|
||||
free of any charge. You agree that you have no remedy against ID, its
|
||||
affiliates, contractors, suppliers, and agents for loss or damage
|
||||
caused by any defect or failure in the Software regardless of the form
|
||||
of action, whether in contract, tort, includinegligence, strict
|
||||
liability or otherwise, with regard to the Software. This Agreement
|
||||
shall be construed in accordance with and governed by the laws of the
|
||||
State of Texas. Copyright and other proprietary matters will be
|
||||
governed by United States laws and international treaties. IN ANY
|
||||
CASE, ID SHALL NOT BE LIABLE FOR LOSS OF DATA, LOSS OF PROFITS, LOST
|
||||
SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER
|
||||
SIMILAR DAMAGES ARISING FROM BREACH OF WARRANTY, BREACH OF CONTRACT,
|
||||
NEGLIGENCE, OR OTHER LEGAL THEORY EVEN IF ID OR ITS AGENT HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
|
||||
OTHER PARTY. Some jurisdictions do not allow the exclusion or
|
||||
limitation of incidental or consequential damages, so the above
|
||||
limitation or exclusion may not apply to you.
|
||||
```
|
49
examples/SDL/CMakeLists.txt
Normal file
49
examples/SDL/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
# Project
|
||||
project(pd_sdl_example)
|
||||
|
||||
# add_definitions(-DDOOM_FAST_TICK)
|
||||
add_definitions(
|
||||
-DDOOM_IMPLEMENT_PRINT
|
||||
-DDOOM_IMPLEMENT_MALLOC
|
||||
-DDOOM_IMPLEMENT_FILE_IO
|
||||
-DDOOM_IMPLEMENT_SOCKETS
|
||||
-DDOOM_IMPLEMENT_GETTIME
|
||||
-DDOOM_IMPLEMENT_EXIT
|
||||
-DDOOM_IMPLEMENT_GETENV
|
||||
)
|
||||
|
||||
# Sources
|
||||
file(GLOB dpsdl_src_files sdl_example.c)
|
||||
file(GLOB dpsdl_doom_src_files ../../src/DOOM/*.*)
|
||||
list(APPEND dpsdl_includes PUBLIC ../../src/)
|
||||
|
||||
# SDL
|
||||
add_definitions(-DSDL_MAIN_HANDLED)
|
||||
set(HAVE_LIBC ON)
|
||||
add_subdirectory(../../thirdparty/SDL/ ./thirdparty/SDL/)
|
||||
list(APPEND dpsdl_libs SDL2-static)
|
||||
list(APPEND dpsdl_includes PUBLIC ../../thirdparty/SDL/include/)
|
||||
|
||||
# Source groups
|
||||
source_group("Example" FILES ${dpsdl_src_files})
|
||||
source_group("DOOM" FILES ${dpsdl_doom_src_files})
|
||||
|
||||
# Executable
|
||||
add_executable(${PROJECT_NAME} ${dpsdl_src_files})
|
||||
|
||||
# Work dir
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||
|
||||
# For midi output on mac
|
||||
if (APPLE)
|
||||
list(APPEND dpsdl_libs "-framework CoreFoundation")
|
||||
list(APPEND dpsdl_libs "-framework AudioToolbox")
|
||||
list(APPEND dpsdl_libs "-framework CoreMIDI")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks")
|
||||
endif()
|
||||
|
||||
# Lib/Headers
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${dpsdl_includes})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${dpsdl_libs})
|
514
examples/SDL/sdl_example.c
Normal file
514
examples/SDL/sdl_example.c
Normal file
@ -0,0 +1,514 @@
|
||||
#if defined(WIN32)
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#include <Windows.h>
|
||||
#include <mmeapi.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
#include <SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#if 1 // Use the PureDOOM.h single header
|
||||
#define DOOM_IMPLEMENTATION
|
||||
#include "../../PureDOOM.h"
|
||||
#else
|
||||
#include "DOOM/DOOM.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Palette experiments
|
||||
//#define PICO8 1
|
||||
//#define CGA 1
|
||||
//#define GAME_BOY 1
|
||||
|
||||
|
||||
// Resolution DOOM renders at
|
||||
#define WIDTH 320
|
||||
#define HEIGHT 200
|
||||
#define SCALE 4
|
||||
|
||||
// Resolution of the SDL window
|
||||
#define FULL_WIDTH (WIDTH * SCALE)
|
||||
#define FULL_HEIGHT (int)(HEIGHT * 1.2 * SCALE) // 1.2x higher than DOOM's height. Original game was designed stretched
|
||||
|
||||
|
||||
doom_key_t sdl_scancode_to_doom_key(SDL_Scancode scancode)
|
||||
{
|
||||
switch (scancode)
|
||||
{
|
||||
case SDL_SCANCODE_TAB: return DOOM_KEY_TAB;
|
||||
case SDL_SCANCODE_RETURN: return DOOM_KEY_ENTER;
|
||||
case SDL_SCANCODE_ESCAPE: return DOOM_KEY_ESCAPE;
|
||||
case SDL_SCANCODE_SPACE: return DOOM_KEY_SPACE;
|
||||
case SDL_SCANCODE_APOSTROPHE: return DOOM_KEY_APOSTROPHE;
|
||||
case SDL_SCANCODE_KP_MULTIPLY: return DOOM_KEY_MULTIPLY;
|
||||
case SDL_SCANCODE_COMMA: return DOOM_KEY_COMMA;
|
||||
case SDL_SCANCODE_MINUS: return DOOM_KEY_MINUS;
|
||||
case SDL_SCANCODE_PERIOD: return DOOM_KEY_PERIOD;
|
||||
case SDL_SCANCODE_SLASH: return DOOM_KEY_SLASH;
|
||||
case SDL_SCANCODE_0: return DOOM_KEY_0;
|
||||
case SDL_SCANCODE_1: return DOOM_KEY_1;
|
||||
case SDL_SCANCODE_2: return DOOM_KEY_2;
|
||||
case SDL_SCANCODE_3: return DOOM_KEY_3;
|
||||
case SDL_SCANCODE_4: return DOOM_KEY_4;
|
||||
case SDL_SCANCODE_5: return DOOM_KEY_5;
|
||||
case SDL_SCANCODE_6: return DOOM_KEY_6;
|
||||
case SDL_SCANCODE_7: return DOOM_KEY_7;
|
||||
case SDL_SCANCODE_8: return DOOM_KEY_8;
|
||||
case SDL_SCANCODE_9: return DOOM_KEY_9;
|
||||
case SDL_SCANCODE_SEMICOLON: return DOOM_KEY_SEMICOLON;
|
||||
case SDL_SCANCODE_EQUALS: return DOOM_KEY_EQUALS;
|
||||
case SDL_SCANCODE_LEFTBRACKET: return DOOM_KEY_LEFT_BRACKET;
|
||||
case SDL_SCANCODE_RIGHTBRACKET: return DOOM_KEY_RIGHT_BRACKET;
|
||||
case SDL_SCANCODE_A: return DOOM_KEY_A;
|
||||
case SDL_SCANCODE_B: return DOOM_KEY_B;
|
||||
case SDL_SCANCODE_C: return DOOM_KEY_C;
|
||||
case SDL_SCANCODE_D: return DOOM_KEY_D;
|
||||
case SDL_SCANCODE_E: return DOOM_KEY_E;
|
||||
case SDL_SCANCODE_F: return DOOM_KEY_F;
|
||||
case SDL_SCANCODE_G: return DOOM_KEY_G;
|
||||
case SDL_SCANCODE_H: return DOOM_KEY_H;
|
||||
case SDL_SCANCODE_I: return DOOM_KEY_I;
|
||||
case SDL_SCANCODE_J: return DOOM_KEY_J;
|
||||
case SDL_SCANCODE_K: return DOOM_KEY_K;
|
||||
case SDL_SCANCODE_L: return DOOM_KEY_L;
|
||||
case SDL_SCANCODE_M: return DOOM_KEY_M;
|
||||
case SDL_SCANCODE_N: return DOOM_KEY_N;
|
||||
case SDL_SCANCODE_O: return DOOM_KEY_O;
|
||||
case SDL_SCANCODE_P: return DOOM_KEY_P;
|
||||
case SDL_SCANCODE_Q: return DOOM_KEY_Q;
|
||||
case SDL_SCANCODE_R: return DOOM_KEY_R;
|
||||
case SDL_SCANCODE_S: return DOOM_KEY_S;
|
||||
case SDL_SCANCODE_T: return DOOM_KEY_T;
|
||||
case SDL_SCANCODE_U: return DOOM_KEY_U;
|
||||
case SDL_SCANCODE_V: return DOOM_KEY_V;
|
||||
case SDL_SCANCODE_W: return DOOM_KEY_W;
|
||||
case SDL_SCANCODE_X: return DOOM_KEY_X;
|
||||
case SDL_SCANCODE_Y: return DOOM_KEY_Y;
|
||||
case SDL_SCANCODE_Z: return DOOM_KEY_Z;
|
||||
case SDL_SCANCODE_BACKSPACE: return DOOM_KEY_BACKSPACE;
|
||||
case SDL_SCANCODE_LCTRL:
|
||||
case SDL_SCANCODE_RCTRL: return DOOM_KEY_CTRL;
|
||||
case SDL_SCANCODE_LEFT: return DOOM_KEY_LEFT_ARROW;
|
||||
case SDL_SCANCODE_UP: return DOOM_KEY_UP_ARROW;
|
||||
case SDL_SCANCODE_RIGHT: return DOOM_KEY_RIGHT_ARROW;
|
||||
case SDL_SCANCODE_DOWN: return DOOM_KEY_DOWN_ARROW;
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
case SDL_SCANCODE_RSHIFT: return DOOM_KEY_SHIFT;
|
||||
case SDL_SCANCODE_LALT:
|
||||
case SDL_SCANCODE_RALT: return DOOM_KEY_ALT;
|
||||
case SDL_SCANCODE_F1: return DOOM_KEY_F1;
|
||||
case SDL_SCANCODE_F2: return DOOM_KEY_F2;
|
||||
case SDL_SCANCODE_F3: return DOOM_KEY_F3;
|
||||
case SDL_SCANCODE_F4: return DOOM_KEY_F4;
|
||||
case SDL_SCANCODE_F5: return DOOM_KEY_F5;
|
||||
case SDL_SCANCODE_F6: return DOOM_KEY_F6;
|
||||
case SDL_SCANCODE_F7: return DOOM_KEY_F7;
|
||||
case SDL_SCANCODE_F8: return DOOM_KEY_F8;
|
||||
case SDL_SCANCODE_F9: return DOOM_KEY_F9;
|
||||
case SDL_SCANCODE_F10: return DOOM_KEY_F10;
|
||||
case SDL_SCANCODE_F11: return DOOM_KEY_F11;
|
||||
case SDL_SCANCODE_F12: return DOOM_KEY_F12;
|
||||
case SDL_SCANCODE_PAUSE: return DOOM_KEY_PAUSE;
|
||||
default: return DOOM_KEY_UNKNOWN;
|
||||
}
|
||||
return DOOM_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
doom_button_t sdl_button_to_doom_button(Uint8 sdl_button)
|
||||
{
|
||||
switch (sdl_button)
|
||||
{
|
||||
case SDL_BUTTON_LEFT: return DOOM_LEFT_BUTTON;
|
||||
case SDL_BUTTON_RIGHT: return DOOM_RIGHT_BUTTON;
|
||||
case SDL_BUTTON_MIDDLE: return DOOM_MIDDLE_BUTTON;
|
||||
}
|
||||
return (doom_button_t)0;
|
||||
}
|
||||
|
||||
|
||||
void audio_callback(void* userdata, Uint8* stream, int len)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
int16_t* buffer = doom_get_sound_buffer();
|
||||
SDL_UnlockAudio();
|
||||
|
||||
memcpy(stream, buffer, len);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
static HMIDIOUT midi_out_handle = 0;
|
||||
void send_midi_msg(uint32_t midi_msg)
|
||||
{
|
||||
if (midi_out_handle)
|
||||
{
|
||||
midiOutShortMsg(midi_out_handle, midi_msg);
|
||||
}
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
AudioUnit audio_unit = 0;
|
||||
void send_midi_msg(uint32_t midi_msg)
|
||||
{
|
||||
if (audio_unit)
|
||||
{
|
||||
MusicDeviceMIDIEvent(audio_unit,
|
||||
(midi_msg) & 0xFF,
|
||||
(midi_msg >> 8) & 0xFF,
|
||||
(midi_msg >> 16) & 0xFF,
|
||||
0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void send_midi_msg(uint32_t midi_msg) {}
|
||||
#endif
|
||||
|
||||
|
||||
SDL_TimerID midi_timer = 0;
|
||||
Uint32 tick_midi(Uint32 interval, void *param)
|
||||
{
|
||||
uint32_t midi_msg;
|
||||
|
||||
SDL_LockAudio();
|
||||
while ((midi_msg = doom_tick_midi()) != 0) send_midi_msg(midi_msg);
|
||||
SDL_UnlockAudio();
|
||||
|
||||
#if defined(__APPLE__)
|
||||
return 1000 / DOOM_MIDI_RATE - 1; // Weirdly, on Apple music is too slow
|
||||
#else
|
||||
return 1000 / DOOM_MIDI_RATE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Init SDL
|
||||
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
SDL_Window* window = SDL_CreateWindow("Pure DOOM - SDL Example",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
FULL_WIDTH, FULL_HEIGHT,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
|
||||
// SDL Renderer
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
|
||||
SDL_Texture* render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
|
||||
|
||||
// SDL Audio thread
|
||||
SDL_AudioSpec audio_spec;
|
||||
memset(&audio_spec, 0, sizeof(audio_spec));
|
||||
audio_spec.freq = DOOM_SAMPLERATE;
|
||||
audio_spec.format = AUDIO_S16;
|
||||
audio_spec.channels = 2;
|
||||
audio_spec.samples = 512;
|
||||
audio_spec.callback = audio_callback;
|
||||
|
||||
if (SDL_OpenAudio(&audio_spec, NULL) < 0)
|
||||
{
|
||||
printf("Failed to SDL_OpenAudio\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Capture mouse
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Setup DOOM
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
// Change default bindings to modern
|
||||
doom_set_default_int("key_up", DOOM_KEY_W);
|
||||
doom_set_default_int("key_down", DOOM_KEY_S);
|
||||
doom_set_default_int("key_strafeleft", DOOM_KEY_A);
|
||||
doom_set_default_int("key_straferight", DOOM_KEY_D);
|
||||
doom_set_default_int("key_use", DOOM_KEY_E);
|
||||
doom_set_default_int("mouse_move", 0); // Mouse will not move forward
|
||||
|
||||
// Setup resolution
|
||||
doom_set_resolution(WIDTH, HEIGHT);
|
||||
|
||||
// Setup MIDI for songs
|
||||
#if defined(WIN32)
|
||||
if (midiOutGetNumDevs() != 0)
|
||||
midiOutOpen(&midi_out_handle, 0, 0, 0, 0);
|
||||
#elif defined(__APPLE__)
|
||||
// I don't really understand this part, but it works.
|
||||
AUGraph graph;
|
||||
AUNode outputNode, mixerNode, dlsNode;
|
||||
NewAUGraph(&graph);
|
||||
AudioComponentDescription output = {'auou','ahal','appl',0,0};
|
||||
AUGraphAddNode(graph, &output, &outputNode);
|
||||
AUGraphOpen(graph);
|
||||
AUGraphInitialize(graph);
|
||||
AUGraphStart(graph);
|
||||
AudioComponentDescription dls = {'aumu','dls ','appl',0,0};
|
||||
AUGraphAddNode(graph, &dls, &dlsNode);
|
||||
AUGraphNodeInfo(graph, dlsNode, NULL, &audio_unit);
|
||||
AudioComponentDescription mixer = {'aumx','smxr','appl',0,0};
|
||||
AUGraphAddNode(graph, &mixer, &mixerNode);
|
||||
AUGraphConnectNodeInput(graph,mixerNode,0,outputNode,0);
|
||||
AUGraphConnectNodeInput(graph,dlsNode,0,mixerNode,0);
|
||||
AUGraphUpdate(graph,NULL);
|
||||
#endif
|
||||
midi_timer = SDL_AddTimer(0, tick_midi, 0);
|
||||
|
||||
// Initialize doom
|
||||
doom_init(argc, argv, DOOM_FLAG_MENU_DARKEN_BG);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
// Main loop
|
||||
SDL_PauseAudio(0);
|
||||
int done = 0;
|
||||
int active_mouse = 1; // Dev allow us to take mouse out of window
|
||||
while (!done)
|
||||
{
|
||||
SDL_Event e;
|
||||
Sint32 mouse_motion_x = 0;
|
||||
Sint32 mouse_motion_y = 0;
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
switch (e.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_END)
|
||||
{
|
||||
active_mouse = !active_mouse;
|
||||
SDL_SetRelativeMouseMode(active_mouse ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
if (!e.key.repeat)
|
||||
doom_key_down(sdl_scancode_to_doom_key(e.key.keysym.scancode));
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
if (!e.key.repeat)
|
||||
doom_key_up(sdl_scancode_to_doom_key(e.key.keysym.scancode));
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (active_mouse) doom_button_down(sdl_button_to_doom_button(e.button.button));
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (active_mouse) doom_button_up(sdl_button_to_doom_button(e.button.button));
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
if (active_mouse)
|
||||
{
|
||||
mouse_motion_x += e.motion.xrel;
|
||||
mouse_motion_y += e.motion.yrel;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (done) break;
|
||||
}
|
||||
if (done) break;
|
||||
|
||||
if (mouse_motion_x || mouse_motion_y)
|
||||
doom_mouse_move(mouse_motion_x * 4, mouse_motion_y * 4);
|
||||
|
||||
SDL_LockAudio();
|
||||
doom_update();
|
||||
SDL_UnlockAudio();
|
||||
|
||||
// Blit DOOM's framebuffer onto our SDL texture
|
||||
#if GAME_BOY
|
||||
void* dst;
|
||||
const unsigned char* src = doom_get_framebuffer(3);
|
||||
int src_pitch = WIDTH * 3;
|
||||
int dst_pitch;
|
||||
const int palette_size = 4;
|
||||
const int pico8_palette[4 * 3] = {
|
||||
0x0f, 0x3, 0x80f,
|
||||
0x30, 0x62, 0x30,
|
||||
0x8b, 0xac, 0x0f,
|
||||
0x9b, 0xbc, 0x0f
|
||||
};
|
||||
if (!SDL_LockTexture(render_target, NULL, &dst, &dst_pitch))
|
||||
{
|
||||
unsigned char* dst8 = (unsigned char*)dst;
|
||||
for (int y = 0; y < HEIGHT; ++y)
|
||||
{
|
||||
for (int x = 0; x < WIDTH; ++x)
|
||||
{
|
||||
int dstk = y * dst_pitch + x * 4;
|
||||
int srck = y * src_pitch + x * 3;
|
||||
|
||||
int r = src[srck + 0];
|
||||
int g = src[srck + 1];
|
||||
int b = src[srck + 2];
|
||||
|
||||
int best = 0;
|
||||
int best_score = (r * r + g * g + b * b) * 2;
|
||||
for (int p = 0; p < palette_size * 3; p += 3)
|
||||
{
|
||||
const int* pico8_color = pico8_palette + p;
|
||||
if (pico8_color[0] == r &&
|
||||
pico8_color[1] == g &&
|
||||
pico8_color[2] == b)
|
||||
{
|
||||
// Perfect match
|
||||
best = p;
|
||||
break;
|
||||
}
|
||||
int ri = pico8_color[0] - r;
|
||||
int gi = pico8_color[1] - g;
|
||||
int bi = pico8_color[2] - b;
|
||||
int score = ri * ri + gi * gi + bi * bi;
|
||||
if (score < best_score)
|
||||
{
|
||||
best_score = score;
|
||||
best = p;
|
||||
}
|
||||
}
|
||||
|
||||
dst8[dstk + 0] = pico8_palette[best + 0];
|
||||
dst8[dstk + 1] = pico8_palette[best + 1];
|
||||
dst8[dstk + 2] = pico8_palette[best + 2];
|
||||
dst8[dstk + 3] = 255;
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(render_target);
|
||||
}
|
||||
#elif PICO8 || CGA
|
||||
void* dst;
|
||||
const unsigned char* src = doom_get_framebuffer(3);
|
||||
int src_pitch = WIDTH * 3;
|
||||
int dst_pitch;
|
||||
#if CGA
|
||||
const int palette_size = 16;
|
||||
const int pico8_palette[16 * 3] = {
|
||||
0, 0, 0,
|
||||
0, 0, 0xAA,
|
||||
0, 0xAA, 0,
|
||||
0, 0xAA, 0xAA,
|
||||
0xAA, 0, 0,
|
||||
0xAA, 0, 0xAA,
|
||||
0xAA, 0x55, 0,
|
||||
0xAA, 0xAA, 0xAA,
|
||||
0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0xFF,
|
||||
0x55, 0xFF, 0x55,
|
||||
0x55, 0xFF, 0xFF,
|
||||
0xFF, 0x55, 0x55,
|
||||
0xFF, 0x55, 0xFF,
|
||||
0xFF, 0xFF, 0x55,
|
||||
0xFF, 0xFF, 0xFF
|
||||
};
|
||||
#elif PICO8
|
||||
const int palette_size = 16;
|
||||
const int pico8_palette[16 * 3] = {
|
||||
0, 0, 0,
|
||||
29, 43, 83,
|
||||
126, 37, 83,
|
||||
0, 135, 81,
|
||||
171, 82, 54,
|
||||
95, 87, 79,
|
||||
194, 195, 199,
|
||||
255, 241, 232,
|
||||
255, 0, 77,
|
||||
255, 163, 0,
|
||||
255, 236, 39,
|
||||
0, 228, 54,
|
||||
41, 173, 255,
|
||||
131, 118, 156,
|
||||
255, 119, 168,
|
||||
255, 204, 170
|
||||
};
|
||||
#endif
|
||||
if (!SDL_LockTexture(render_target, NULL, &dst, &dst_pitch))
|
||||
{
|
||||
unsigned char* dst8 = (unsigned char*)dst;
|
||||
for (int y = 0; y < HEIGHT; ++y)
|
||||
{
|
||||
for (int x = 0; x < WIDTH; ++x)
|
||||
{
|
||||
int dstk = y * dst_pitch + x * 4;
|
||||
int srck = y * src_pitch + x * 3;
|
||||
|
||||
int r = src[srck + 0];
|
||||
int g = src[srck + 1];
|
||||
int b = src[srck + 2];
|
||||
|
||||
int best = 0;
|
||||
int best_score = (r * r + g * g + b * b) * 2;
|
||||
for (int p = 0; p < palette_size * 3; p += 3)
|
||||
{
|
||||
const int* pico8_color = pico8_palette + p;
|
||||
if (pico8_color[0] == r &&
|
||||
pico8_color[1] == g &&
|
||||
pico8_color[2] == b)
|
||||
{
|
||||
// Perfect match
|
||||
best = p;
|
||||
break;
|
||||
}
|
||||
int ri = pico8_color[0] - r;
|
||||
int gi = pico8_color[1] - g;
|
||||
int bi = pico8_color[2] - b;
|
||||
int score = ri * ri + gi * gi + bi * bi;
|
||||
if (score < best_score)
|
||||
{
|
||||
best_score = score;
|
||||
best = p;
|
||||
}
|
||||
}
|
||||
|
||||
dst8[dstk + 0] = pico8_palette[best + 0];
|
||||
dst8[dstk + 1] = pico8_palette[best + 1];
|
||||
dst8[dstk + 2] = pico8_palette[best + 2];
|
||||
dst8[dstk + 3] = 255;
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(render_target);
|
||||
}
|
||||
#else
|
||||
void* dst;
|
||||
const unsigned char* src = doom_get_framebuffer(4);
|
||||
int src_pitch = WIDTH * 4;
|
||||
int dst_pitch;
|
||||
if (!SDL_LockTexture(render_target, NULL, &dst, &dst_pitch))
|
||||
{
|
||||
for (int y = 0; y < HEIGHT; ++y)
|
||||
{
|
||||
memcpy(dst, src, src_pitch);
|
||||
dst = (unsigned char*)dst + dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
SDL_UnlockTexture(render_target);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Stretch our texture on the screen
|
||||
SDL_Rect src_rect = {0, 0, WIDTH, HEIGHT };
|
||||
SDL_Rect dst_rect = {0, 0, FULL_WIDTH, FULL_HEIGHT};
|
||||
SDL_RenderCopy(renderer, render_target, &src_rect, &dst_rect);
|
||||
|
||||
// Swap
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
if (midi_timer) SDL_RemoveTimer(midi_timer);
|
||||
#if defined(WIN32)
|
||||
if (midi_out_handle) midiOutClose(midi_out_handle);
|
||||
#endif
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_CloseAudio();
|
||||
SDL_DestroyTexture(render_target);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
BIN
images/PureDOOM.png
Normal file
BIN
images/PureDOOM.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
739
src/DOOM/DOOM.c
Normal file
739
src/DOOM/DOOM.c
Normal file
@ -0,0 +1,739 @@
|
||||
#if defined(WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include "DOOM.h"
|
||||
|
||||
#include "d_main.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
|
||||
extern byte* screens[5];
|
||||
extern unsigned char screen_palette[256 * 3];
|
||||
extern doom_boolean is_wiping_screen;
|
||||
extern default_t defaults[];
|
||||
extern int numdefaults;
|
||||
extern signed short mixbuffer[2048];
|
||||
|
||||
|
||||
static unsigned char* screen_buffer = 0;
|
||||
static unsigned char* final_screen_buffer = 0;
|
||||
static int last_update_time = 0;
|
||||
static int button_states[3] = { 0 };
|
||||
static char itoa_buf[20];
|
||||
|
||||
|
||||
char error_buf[260];
|
||||
int doom_flags = 0;
|
||||
doom_print_fn doom_print = 0;
|
||||
doom_malloc_fn doom_malloc = 0;
|
||||
doom_free_fn doom_free = 0;
|
||||
doom_open_fn doom_open = 0;
|
||||
doom_close_fn doom_close = 0;
|
||||
doom_read_fn doom_read = 0;
|
||||
doom_write_fn doom_write = 0;
|
||||
doom_seek_fn doom_seek = 0;
|
||||
doom_tell_fn doom_tell = 0;
|
||||
doom_eof_fn doom_eof = 0;
|
||||
doom_gettime_fn doom_gettime = 0;
|
||||
doom_exit_fn doom_exit = 0;
|
||||
doom_getenv_fn doom_getenv = 0;
|
||||
|
||||
|
||||
void D_DoomLoop(void);
|
||||
void D_UpdateWipe(void);
|
||||
void I_UpdateSound();
|
||||
unsigned long I_TickSong();
|
||||
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_PRINT)
|
||||
#include <stdio.h>
|
||||
static void doom_print_impl(const char* str)
|
||||
{
|
||||
printf("%s", str);
|
||||
}
|
||||
#else
|
||||
static void doom_print_impl(const char* str) {}
|
||||
#endif
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_MALLOC)
|
||||
#include <stdlib.h>
|
||||
static void* doom_malloc_impl(int size)
|
||||
{
|
||||
return malloc((size_t)size);
|
||||
}
|
||||
static void doom_free_impl(void* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#else
|
||||
static void* doom_malloc_impl(int size) { return 0; }
|
||||
static void doom_free_impl(void* ptr) {}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_FILE_IO)
|
||||
#include <stdio.h>
|
||||
void* doom_open_impl(const char* filename, const char* mode)
|
||||
{
|
||||
return fopen(filename, mode);
|
||||
}
|
||||
void doom_close_impl(void* handle)
|
||||
{
|
||||
fclose(handle);
|
||||
}
|
||||
int doom_read_impl(void* handle, void *buf, int count)
|
||||
{
|
||||
return (int)fread(buf, 1, count, handle);
|
||||
}
|
||||
int doom_write_impl(void* handle, const void *buf, int count)
|
||||
{
|
||||
return (int)fwrite(buf, 1, count, handle);
|
||||
}
|
||||
int doom_seek_impl(void* handle, int offset, doom_seek_t origin)
|
||||
{
|
||||
return fseek(handle, offset, origin);
|
||||
}
|
||||
int doom_tell_impl(void* handle)
|
||||
{
|
||||
return (int)ftell(handle);
|
||||
}
|
||||
int doom_eof_impl(void* handle)
|
||||
{
|
||||
return feof(handle);
|
||||
}
|
||||
#else
|
||||
void* doom_open_impl(const char* filename, const char* mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void doom_close_impl(void* handle) {}
|
||||
int doom_read_impl(void* handle, void *buf, int count)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int doom_write_impl(void* handle, const void *buf, int count)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int doom_seek_impl(void* handle, int offset, doom_seek_t origin)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int doom_tell_impl(void* handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int doom_eof_impl(void* handle)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_GETTIME)
|
||||
#if defined(WIN32)
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
void doom_gettime_impl(int* sec, int* usec)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
static const unsigned long long EPOCH = ((unsigned long long)116444736000000000ULL);
|
||||
SYSTEMTIME system_time;
|
||||
FILETIME file_time;
|
||||
unsigned long long time;
|
||||
GetSystemTime(&system_time);
|
||||
SystemTimeToFileTime(&system_time, &file_time);
|
||||
time = ((unsigned long long)file_time.dwLowDateTime);
|
||||
time += ((unsigned long long)file_time.dwHighDateTime) << 32;
|
||||
*sec = (int)((time - EPOCH) / 10000000L);
|
||||
*usec = (int)(system_time.wMilliseconds * 1000);
|
||||
#else
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
gettimeofday(&tp, &tzp);
|
||||
*sec = tp.tv_sec;
|
||||
*usec = tp.tv_usec;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void doom_gettime_impl(int* sec, int* usec)
|
||||
{
|
||||
*sec = 0;
|
||||
*usec = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_EXIT)
|
||||
#include <stdlib.h>
|
||||
void doom_exit_impl(int code)
|
||||
{
|
||||
exit(code);
|
||||
}
|
||||
#else
|
||||
void doom_exit_impl(int code) {}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(DOOM_IMPLEMENT_GETENV)
|
||||
#include <stdlib.h>
|
||||
char* doom_getenv_impl(const char* var)
|
||||
{
|
||||
return getenv(var);
|
||||
}
|
||||
#else
|
||||
char* doom_getenv_impl(const char* var) { return 0; }
|
||||
#endif
|
||||
|
||||
|
||||
void doom_memset(void* ptr, int value, int num)
|
||||
{
|
||||
unsigned char* p = ptr;
|
||||
for (int i = 0; i < num; ++i, ++p)
|
||||
{
|
||||
*p = (unsigned char)value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void* doom_memcpy(void* destination, const void* source, int num)
|
||||
{
|
||||
unsigned char* dst = destination;
|
||||
const unsigned char* src = source;
|
||||
|
||||
for (int i = 0; i < num; ++i, ++dst, ++src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
||||
int doom_strlen(const char* str)
|
||||
{
|
||||
int len = 0;
|
||||
while (*str++) ++len;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
char* doom_concat(char* dst, const char* src)
|
||||
{
|
||||
char* ret = dst;
|
||||
dst += doom_strlen(dst);
|
||||
|
||||
while (*src) *dst++ = *src++;
|
||||
*dst = *src; // \0
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char* doom_strcpy(char* dst, const char* src)
|
||||
{
|
||||
char* ret = dst;
|
||||
|
||||
while (*src) *dst++ = *src++;
|
||||
*dst = *src; // \0
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char* doom_strncpy(char* dst, const char* src, int num)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (; i < num; ++i)
|
||||
{
|
||||
if (!src[i]) break;
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
while (i < num) dst[i++] = '\0';
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
int doom_strcmp(const char* str1, const char* str2)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (!(ret = *(unsigned char*)str1 - *(unsigned char*) str2) && *str1)
|
||||
++str1, ++str2;
|
||||
|
||||
if (ret < 0)
|
||||
ret = -1;
|
||||
else if (ret > 0)
|
||||
ret = 1;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
int doom_strncmp(const char* str1, const char* str2, int n)
|
||||
{
|
||||
int ret = 0;
|
||||
int count = 1;
|
||||
|
||||
while (!(ret = *(unsigned char*)str1 - *(unsigned char*) str2) && *str1 && count++ < n)
|
||||
++str1, ++str2;
|
||||
|
||||
if (ret < 0)
|
||||
ret = -1;
|
||||
else if (ret > 0)
|
||||
ret = 1;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
int doom_toupper(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z') return c - 'a' + 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
int doom_strcasecmp(const char* str1, const char* str2)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (!(ret = doom_toupper(*(unsigned char*)str1) - doom_toupper(*(unsigned char*)str2)) && *str1)
|
||||
++str1, ++str2;
|
||||
|
||||
if (ret < 0)
|
||||
ret = -1;
|
||||
else if (ret > 0)
|
||||
ret = 1;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
int doom_strncasecmp(const char* str1, const char* str2, int n)
|
||||
{
|
||||
int ret = 0;
|
||||
int count = 1;
|
||||
|
||||
while (!(ret = doom_toupper(*(unsigned char*)str1) - doom_toupper(*(unsigned char*)str2)) && *str1 && count++ < n)
|
||||
++str1, ++str2;
|
||||
|
||||
if (ret < 0)
|
||||
ret = -1;
|
||||
else if (ret > 0)
|
||||
ret = 1;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
int doom_atoi(const char* str)
|
||||
{
|
||||
int i = 0;
|
||||
int c;
|
||||
|
||||
while ((c = *str++) != 0)
|
||||
{
|
||||
i *= 10;
|
||||
i += c - '0';
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int doom_atox(const char* str)
|
||||
{
|
||||
int i = 0;
|
||||
int c;
|
||||
|
||||
while ((c = *str++) != 0)
|
||||
{
|
||||
i *= 16;
|
||||
if (c >= '0' && c <= '9')
|
||||
i += c - '0';
|
||||
else
|
||||
i += c - 'A' + 10;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
const char* doom_itoa(int k, int radix)
|
||||
{
|
||||
int i = k < 0 ? -k : k;
|
||||
if (i == 0)
|
||||
{
|
||||
itoa_buf[0] = '0';
|
||||
itoa_buf[1] = '\0';
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
int idx = k < 0 ? 1 : 0;
|
||||
int j = i;
|
||||
while (j)
|
||||
{
|
||||
j /= radix;
|
||||
idx++;
|
||||
}
|
||||
itoa_buf[idx] = '\0';
|
||||
|
||||
if (radix == 10)
|
||||
{
|
||||
while (i)
|
||||
{
|
||||
itoa_buf[--idx] = '0' + (i % 10);
|
||||
i /= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i)
|
||||
{
|
||||
int k = (i & 0xF);
|
||||
if (k >= 10)
|
||||
itoa_buf[--idx] = 'A' + ((i & 0xF) - 10);
|
||||
else
|
||||
itoa_buf[--idx] = '0' + (i & 0xF);
|
||||
i >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (k < 0) itoa_buf[0] = '-';
|
||||
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
|
||||
const char* doom_ctoa(char c)
|
||||
{
|
||||
itoa_buf[0] = c;
|
||||
itoa_buf[1] = '\0';
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
|
||||
const char* doom_ptoa(void* p)
|
||||
{
|
||||
int idx = 0;
|
||||
unsigned long long i = (unsigned long long)p;
|
||||
|
||||
itoa_buf[idx++] = '0';
|
||||
itoa_buf[idx++] = 'x';
|
||||
|
||||
while (i)
|
||||
{
|
||||
int k = (i & 0xF);
|
||||
if (k >= 10)
|
||||
itoa_buf[idx++] = 'A' + ((i & 0xF) - 10);
|
||||
else
|
||||
itoa_buf[idx++] = '0' + (i & 0xF);
|
||||
i >>= 4;
|
||||
}
|
||||
|
||||
itoa_buf[idx] = '\0';
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
|
||||
int doom_fprint(void* handle, const char* str)
|
||||
{
|
||||
return doom_write(handle, str, doom_strlen(str));
|
||||
}
|
||||
|
||||
|
||||
static default_t* get_default(const char* name)
|
||||
{
|
||||
for (int i = 0; i < numdefaults; ++i)
|
||||
{
|
||||
if (doom_strcmp(defaults[i].name, name) == 0) return &defaults[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_resolution(int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0) return;
|
||||
// SCREENWIDTH = width;
|
||||
// SCREENHEIGHT = height;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_default_int(const char* name, int value)
|
||||
{
|
||||
default_t* def = get_default(name);
|
||||
if (!def) return;
|
||||
def->defaultvalue = value;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_default_string(const char* name, const char* value)
|
||||
{
|
||||
default_t* def = get_default(name);
|
||||
if (!def) return;
|
||||
def->default_text_value = (char*)value;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_print(doom_print_fn print_fn)
|
||||
{
|
||||
doom_print = print_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_malloc(doom_malloc_fn malloc_fn, doom_free_fn free_fn)
|
||||
{
|
||||
doom_malloc = malloc_fn;
|
||||
doom_free = free_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_file_io(doom_open_fn open_fn,
|
||||
doom_close_fn close_fn,
|
||||
doom_read_fn read_fn,
|
||||
doom_write_fn write_fn,
|
||||
doom_seek_fn seek_fn,
|
||||
doom_tell_fn tell_fn,
|
||||
doom_eof_fn eof_fn)
|
||||
{
|
||||
doom_open = open_fn;
|
||||
doom_close = close_fn;
|
||||
doom_read = read_fn;
|
||||
doom_write = write_fn;
|
||||
doom_seek = seek_fn;
|
||||
doom_tell = tell_fn;
|
||||
doom_eof = eof_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_gettime(doom_gettime_fn gettime_fn)
|
||||
{
|
||||
doom_gettime = gettime_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_exit(doom_exit_fn exit_fn)
|
||||
{
|
||||
doom_exit = exit_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_set_getenv(doom_getenv_fn getenv_fn)
|
||||
{
|
||||
doom_getenv = getenv_fn;
|
||||
}
|
||||
|
||||
|
||||
void doom_init(int argc, char** argv, int flags)
|
||||
{
|
||||
if (!doom_print) doom_print = doom_print_impl;
|
||||
if (!doom_malloc) doom_malloc = doom_malloc_impl;
|
||||
if (!doom_free) doom_free = doom_free_impl;
|
||||
if (!doom_open) doom_open = doom_open_impl;
|
||||
if (!doom_close) doom_close = doom_close_impl;
|
||||
if (!doom_read) doom_read = doom_read_impl;
|
||||
if (!doom_write) doom_write = doom_write_impl;
|
||||
if (!doom_seek) doom_seek = doom_seek_impl;
|
||||
if (!doom_tell) doom_tell = doom_tell_impl;
|
||||
if (!doom_eof) doom_eof = doom_eof_impl;
|
||||
if (!doom_gettime) doom_gettime = doom_gettime_impl;
|
||||
if (!doom_exit) doom_exit = doom_exit_impl;
|
||||
if (!doom_getenv) doom_getenv = doom_getenv_impl;
|
||||
|
||||
screen_buffer = doom_malloc(SCREENWIDTH * SCREENHEIGHT);
|
||||
final_screen_buffer = doom_malloc(SCREENWIDTH * SCREENHEIGHT * 4);
|
||||
last_update_time = I_GetTime();
|
||||
|
||||
myargc = argc;
|
||||
myargv = argv;
|
||||
doom_flags = flags;
|
||||
|
||||
D_DoomMain();
|
||||
}
|
||||
|
||||
|
||||
void doom_update()
|
||||
{
|
||||
int now = I_GetTime();
|
||||
int delta_time = now - last_update_time;
|
||||
|
||||
while (delta_time-- > 0)
|
||||
{
|
||||
if (is_wiping_screen)
|
||||
D_UpdateWipe();
|
||||
else
|
||||
D_DoomLoop();
|
||||
}
|
||||
|
||||
last_update_time = now;
|
||||
}
|
||||
|
||||
|
||||
const unsigned char* doom_get_framebuffer(int channels)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
doom_memcpy(screen_buffer, screens[0], SCREENWIDTH * SCREENHEIGHT);
|
||||
|
||||
extern doom_boolean menuactive;
|
||||
extern gamestate_t gamestate;
|
||||
extern doom_boolean automapactive;
|
||||
extern int crosshair;
|
||||
|
||||
// Draw crosshair
|
||||
if (crosshair &&
|
||||
!menuactive &&
|
||||
gamestate == GS_LEVEL &&
|
||||
!automapactive)
|
||||
{
|
||||
int y;
|
||||
extern int setblocks;
|
||||
if (setblocks == 11) y = SCREENHEIGHT / 2 + 8;
|
||||
else y = SCREENHEIGHT / 2 - 8;
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
screen_buffer[SCREENWIDTH / 2 - 2 - i + y * SCREENWIDTH] = 4;
|
||||
screen_buffer[SCREENWIDTH / 2 + 2 + i + y * SCREENWIDTH] = 4;
|
||||
}
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
screen_buffer[SCREENWIDTH / 2 + (y - 2 - i) * SCREENWIDTH] = 4;
|
||||
screen_buffer[SCREENWIDTH / 2 + (y + 2 + i) * SCREENWIDTH] = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (channels == 1)
|
||||
{
|
||||
return screen_buffer;
|
||||
}
|
||||
else if (channels == 3)
|
||||
{
|
||||
for (i = 0, len = SCREENWIDTH * SCREENHEIGHT; i < len; ++i)
|
||||
{
|
||||
int k = i * 3;
|
||||
int kpal = screen_buffer[i] * 3;
|
||||
final_screen_buffer[k + 0] = screen_palette[kpal + 0];
|
||||
final_screen_buffer[k + 1] = screen_palette[kpal + 1];
|
||||
final_screen_buffer[k + 2] = screen_palette[kpal + 2];
|
||||
}
|
||||
return final_screen_buffer;
|
||||
}
|
||||
else if (channels == 4)
|
||||
{
|
||||
for (i = 0, len = SCREENWIDTH * SCREENHEIGHT; i < len; ++i)
|
||||
{
|
||||
int k = i * 4;
|
||||
int kpal = screen_buffer[i] * 3;
|
||||
final_screen_buffer[k + 0] = screen_palette[kpal + 0];
|
||||
final_screen_buffer[k + 1] = screen_palette[kpal + 1];
|
||||
final_screen_buffer[k + 2] = screen_palette[kpal + 2];
|
||||
final_screen_buffer[k + 3] = 255;
|
||||
}
|
||||
return final_screen_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long doom_tick_midi()
|
||||
{
|
||||
return I_TickSong();
|
||||
}
|
||||
|
||||
|
||||
short* doom_get_sound_buffer()
|
||||
{
|
||||
I_UpdateSound();
|
||||
return mixbuffer;
|
||||
}
|
||||
|
||||
|
||||
void doom_key_down(doom_key_t key)
|
||||
{
|
||||
event_t event;
|
||||
event.type = ev_keydown;
|
||||
event.data1 = (int)key;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
||||
void doom_key_up(doom_key_t key)
|
||||
{
|
||||
event_t event;
|
||||
event.type = ev_keyup;
|
||||
event.data1 = (int)key;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
||||
void doom_button_down(doom_button_t button)
|
||||
{
|
||||
button_states[button] = 1;
|
||||
|
||||
event_t event;
|
||||
event.type = ev_mouse;
|
||||
event.data1 =
|
||||
(button_states[0]) |
|
||||
(button_states[1] ? 2 : 0) |
|
||||
(button_states[2] ? 4 : 0);
|
||||
event.data2 = event.data3 = 0;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
||||
void doom_button_up(doom_button_t button)
|
||||
{
|
||||
button_states[button] = 0;
|
||||
|
||||
event_t event;
|
||||
event.type = ev_mouse;
|
||||
event.data1 =
|
||||
(button_states[0]) |
|
||||
(button_states[1] ? 2 : 0) |
|
||||
(button_states[2] ? 4 : 0);
|
||||
|
||||
event.data1 =
|
||||
event.data1
|
||||
^ (button_states[0] ? 1 : 0)
|
||||
^ (button_states[1] ? 2 : 0)
|
||||
^ (button_states[2] ? 4 : 0);
|
||||
|
||||
event.data2 = event.data3 = 0;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
||||
void doom_mouse_move(int delta_x, int delta_y)
|
||||
{
|
||||
event_t event;
|
||||
|
||||
event.type = ev_mouse;
|
||||
event.data1 =
|
||||
(button_states[0]) |
|
||||
(button_states[1] ? 2 : 0) |
|
||||
(button_states[2] ? 4 : 0);
|
||||
event.data2 = delta_x;
|
||||
event.data3 = -delta_y;
|
||||
|
||||
if (event.data2 || event.data3)
|
||||
{
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
}
|
216
src/DOOM/DOOM.h
Normal file
216
src/DOOM/DOOM.h
Normal file
@ -0,0 +1,216 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
/* Pure DOOM usage
|
||||
|
||||
Do this:
|
||||
#define DOOM_IMPLEMENTATION
|
||||
before you include this file in *one* C or C++ file to create the implementation.
|
||||
|
||||
// i.e. it should look like this:
|
||||
#include ...
|
||||
#include ...
|
||||
#include ...
|
||||
#define DOOM_IMPLEMENTATION
|
||||
#include "PureDOOM.h"
|
||||
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __DOOM_H__
|
||||
#define __DOOM_H__
|
||||
|
||||
|
||||
// Sample rate of sound samples from doom
|
||||
#define DOOM_SAMPLERATE 11025
|
||||
|
||||
// MIDI tick needs to be called 140 times per seconds
|
||||
#define DOOM_MIDI_RATE 140
|
||||
|
||||
// Hide menu options. If for say your platform doesn't support mouse or
|
||||
// MIDI playback, you can hide these settings from the menu.
|
||||
#define DOOM_FLAG_HIDE_MOUSE_OPTIONS 1 // Remove mouse options from menu
|
||||
#define DOOM_FLAG_HIDE_SOUND_OPTIONS 2 // Remove sound options from menu
|
||||
#define DOOM_FLAG_HIDE_MUSIC_OPTIONS 4 // Remove music options from menu
|
||||
|
||||
// Darken background when menu is open, making it more readable. This
|
||||
// uses a bit more CPU and redraws the HUD every frame
|
||||
#define DOOM_FLAG_MENU_DARKEN_BG 8
|
||||
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DOOM_SEEK_CUR = 1,
|
||||
DOOM_SEEK_END = 2,
|
||||
DOOM_SEEK_SET = 0
|
||||
} doom_seek_t;
|
||||
|
||||
|
||||
typedef void(*doom_print_fn)(const char* str);
|
||||
typedef void*(*doom_malloc_fn)(int size);
|
||||
typedef void(*doom_free_fn)(void* ptr);
|
||||
typedef void*(*doom_open_fn)(const char* filename, const char* mode);
|
||||
typedef void(*doom_close_fn)(void* handle);
|
||||
typedef int(*doom_read_fn)(void* handle, void *buf, int count);
|
||||
typedef int(*doom_write_fn)(void* handle, const void *buf, int count);
|
||||
typedef int(*doom_seek_fn)(void* handle, int offset, doom_seek_t origin);
|
||||
typedef int(*doom_tell_fn)(void* handle);
|
||||
typedef int(*doom_eof_fn)(void* handle);
|
||||
typedef void(*doom_gettime_fn)(int* sec, int* usec);
|
||||
typedef void(*doom_exit_fn)(int code);
|
||||
typedef char*(*doom_getenv_fn)(const char* var);
|
||||
|
||||
|
||||
// Doom key mapping
|
||||
typedef enum
|
||||
{
|
||||
DOOM_KEY_UNKNOWN = -1,
|
||||
DOOM_KEY_TAB = 9,
|
||||
DOOM_KEY_ENTER = 13,
|
||||
DOOM_KEY_ESCAPE = 27,
|
||||
DOOM_KEY_SPACE = 32,
|
||||
DOOM_KEY_APOSTROPHE = '\'',
|
||||
DOOM_KEY_MULTIPLY = '*',
|
||||
DOOM_KEY_COMMA = ',',
|
||||
DOOM_KEY_MINUS = 0x2d,
|
||||
DOOM_KEY_PERIOD = '.',
|
||||
DOOM_KEY_SLASH = '/',
|
||||
DOOM_KEY_0 = '0',
|
||||
DOOM_KEY_1 = '1',
|
||||
DOOM_KEY_2 = '2',
|
||||
DOOM_KEY_3 = '3',
|
||||
DOOM_KEY_4 = '4',
|
||||
DOOM_KEY_5 = '5',
|
||||
DOOM_KEY_6 = '6',
|
||||
DOOM_KEY_7 = '7',
|
||||
DOOM_KEY_8 = '8',
|
||||
DOOM_KEY_9 = '9',
|
||||
DOOM_KEY_SEMICOLON = ';',
|
||||
DOOM_KEY_EQUALS = 0x3d,
|
||||
DOOM_KEY_LEFT_BRACKET = '[',
|
||||
DOOM_KEY_RIGHT_BRACKET = ']',
|
||||
DOOM_KEY_A = 'a',
|
||||
DOOM_KEY_B = 'b',
|
||||
DOOM_KEY_C = 'c',
|
||||
DOOM_KEY_D = 'd',
|
||||
DOOM_KEY_E = 'e',
|
||||
DOOM_KEY_F = 'f',
|
||||
DOOM_KEY_G = 'g',
|
||||
DOOM_KEY_H = 'h',
|
||||
DOOM_KEY_I = 'i',
|
||||
DOOM_KEY_J = 'j',
|
||||
DOOM_KEY_K = 'k',
|
||||
DOOM_KEY_L = 'l',
|
||||
DOOM_KEY_M = 'm',
|
||||
DOOM_KEY_N = 'n',
|
||||
DOOM_KEY_O = 'o',
|
||||
DOOM_KEY_P = 'p',
|
||||
DOOM_KEY_Q = 'q',
|
||||
DOOM_KEY_R = 'r',
|
||||
DOOM_KEY_S = 's',
|
||||
DOOM_KEY_T = 't',
|
||||
DOOM_KEY_U = 'u',
|
||||
DOOM_KEY_V = 'v',
|
||||
DOOM_KEY_W = 'w',
|
||||
DOOM_KEY_X = 'x',
|
||||
DOOM_KEY_Y = 'y',
|
||||
DOOM_KEY_Z = 'z',
|
||||
DOOM_KEY_BACKSPACE = 127,
|
||||
DOOM_KEY_CTRL = (0x80 + 0x1d), // Both left and right
|
||||
DOOM_KEY_LEFT_ARROW = 0xac,
|
||||
DOOM_KEY_UP_ARROW = 0xad,
|
||||
DOOM_KEY_RIGHT_ARROW = 0xae,
|
||||
DOOM_KEY_DOWN_ARROW = 0xaf,
|
||||
DOOM_KEY_SHIFT = (0x80 + 0x36), // Both left and right
|
||||
DOOM_KEY_ALT = (0x80 + 0x38), // Both left and right
|
||||
DOOM_KEY_F1 = (0x80 + 0x3b),
|
||||
DOOM_KEY_F2 = (0x80 + 0x3c),
|
||||
DOOM_KEY_F3 = (0x80 + 0x3d),
|
||||
DOOM_KEY_F4 = (0x80 + 0x3e),
|
||||
DOOM_KEY_F5 = (0x80 + 0x3f),
|
||||
DOOM_KEY_F6 = (0x80 + 0x40),
|
||||
DOOM_KEY_F7 = (0x80 + 0x41),
|
||||
DOOM_KEY_F8 = (0x80 + 0x42),
|
||||
DOOM_KEY_F9 = (0x80 + 0x43),
|
||||
DOOM_KEY_F10 = (0x80 + 0x44),
|
||||
DOOM_KEY_F11 = (0x80 + 0x57),
|
||||
DOOM_KEY_F12 = (0x80 + 0x58),
|
||||
DOOM_KEY_PAUSE = 0xff
|
||||
} doom_key_t;
|
||||
|
||||
|
||||
// Mouse button mapping
|
||||
typedef enum
|
||||
{
|
||||
DOOM_LEFT_BUTTON = 0,
|
||||
DOOM_RIGHT_BUTTON = 1,
|
||||
DOOM_MIDDLE_BUTTON = 2
|
||||
} doom_button_t;
|
||||
|
||||
|
||||
// For the software renderer. Default is 320x200
|
||||
void doom_set_resolution(int width, int height);
|
||||
|
||||
// Set default configurations. Lets say, changing arrows to WASD as default controls
|
||||
void doom_set_default_int(const char* name, int value);
|
||||
void doom_set_default_string(const char* name, const char* value);
|
||||
|
||||
// set callbacks
|
||||
void doom_set_print(doom_print_fn print_fn);
|
||||
void doom_set_malloc(doom_malloc_fn malloc_fn, doom_free_fn free_fn);
|
||||
void doom_set_file_io(doom_open_fn open_fn,
|
||||
doom_close_fn close_fn,
|
||||
doom_read_fn read_fn,
|
||||
doom_write_fn write_fn,
|
||||
doom_seek_fn seek_fn,
|
||||
doom_tell_fn tell_fn,
|
||||
doom_eof_fn eof_fn);
|
||||
void doom_set_gettime(doom_gettime_fn gettime_fn);
|
||||
void doom_set_exit(doom_exit_fn exit_fn);
|
||||
void doom_set_getenv(doom_getenv_fn getenv_fn);
|
||||
|
||||
// Initializes DOOM and start things up. Call only call one
|
||||
void doom_init(int argc, char** argv, int flags);
|
||||
|
||||
// Call this every frame
|
||||
void doom_update();
|
||||
|
||||
// Channels: 1 = indexed, 3 = RGB, 4 = RGBA
|
||||
const unsigned char* doom_get_framebuffer(int channels);
|
||||
|
||||
// It is always 2048 bytes in size
|
||||
short* doom_get_sound_buffer();
|
||||
|
||||
// Call this 140 times per second. Or about every 7ms.
|
||||
// Returns midi message. Keep calling it until it returns 0.
|
||||
unsigned long doom_tick_midi();
|
||||
|
||||
// Events
|
||||
void doom_key_down(doom_key_t key);
|
||||
void doom_key_up(doom_key_t key);
|
||||
void doom_button_down(doom_button_t button);
|
||||
void doom_button_up(doom_button_t button);
|
||||
void doom_mouse_move(int delta_x, int delta_y);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
112
src/DOOM/DOOMLIC.TXT
Normal file
112
src/DOOM/DOOMLIC.TXT
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
|
||||
LIMITED USE SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
This Limited Use Software License Agreement (the "Agreement")
|
||||
is a legal agreement between you, the end-user, and Id Software, Inc.
|
||||
("ID"). By downloading or purchasing the software material, which
|
||||
includes source code (the "Source Code"), artwork data, music and
|
||||
software tools (collectively, the "Software"), you are agreeing to
|
||||
be bound by the terms of this Agreement. If you do not agree to the
|
||||
terms of this Agreement, promptly destroy the Software you may have
|
||||
downloaded or copied.
|
||||
|
||||
ID SOFTWARE LICENSE
|
||||
|
||||
1. Grant of License. ID grants to you the right to use the
|
||||
Software. You have no ownership or proprietary rights in or to the
|
||||
Software, or the Trademark. For purposes of this section, "use" means
|
||||
loading the Software into RAM, as well as installation on a hard disk
|
||||
or other storage device. The Software, together with any archive copy
|
||||
thereof, shall be destroyed when no longer used in accordance with
|
||||
this Agreement, or when the right to use the Software is terminated.
|
||||
You agree that the Software will not be shipped, transferred or
|
||||
exported into any country in violation of the U.S. Export
|
||||
Administration Act (or any other law governing such matters) and that
|
||||
you will not utilize, in any other manner, the Software in violation
|
||||
of any applicable law.
|
||||
|
||||
2. Permitted Uses. For educational purposes only, you, the
|
||||
end-user, may use portions of the Source Code, such as particular
|
||||
routines, to develop your own software, but may not duplicate the
|
||||
Source Code, except as noted in paragraph 4. The limited right
|
||||
referenced in the preceding sentence is hereinafter referred to as
|
||||
"Educational Use." By so exercising the Educational Use right you
|
||||
shall not obtain any ownership, copyright, proprietary or other
|
||||
interest in or to the Source Code, or any portion of the Source
|
||||
Code. You may dispose of your own software in your sole discretion.
|
||||
With the exception of the Educational Use right, you may not
|
||||
otherwise use the Software, or an portion of the Software, which
|
||||
includes the Source Code, for commercial gain.
|
||||
|
||||
3. Prohibited Uses: Under no circumstances shall you, the
|
||||
end-user, be permitted, allowed or authorized to commercially exploit
|
||||
the Software. Neither you nor anyone at your direction shall do any
|
||||
of the following acts with regard to the Software, or any portion
|
||||
thereof:
|
||||
|
||||
Rent;
|
||||
|
||||
Sell;
|
||||
|
||||
Lease;
|
||||
|
||||
Offer on a pay-per-play basis;
|
||||
|
||||
Distribute for money or any other consideration; or
|
||||
|
||||
In any other manner and through any medium whatsoever
|
||||
commercially exploit or use for any commercial purpose.
|
||||
|
||||
Notwithstanding the foregoing prohibitions, you may commercially
|
||||
exploit the software you develop by exercising the Educational Use
|
||||
right, referenced in paragraph 2. hereinabove.
|
||||
|
||||
4. Copyright. The Software and all copyrights related thereto
|
||||
(including all characters and other images generated by the Software
|
||||
or depicted in the Software) are owned by ID and is protected by
|
||||
United States copyright laws and international treaty provisions.
|
||||
Id shall retain exclusive ownership and copyright in and to the
|
||||
Software and all portions of the Software and you shall have no
|
||||
ownership or other proprietary interest in such materials. You must
|
||||
treat the Software like any other copyrighted material. You may not
|
||||
otherwise reproduce, copy or disclose to others, in whole or in any
|
||||
part, the Software. You may not copy the written materials
|
||||
accompanying the Software. You agree to use your best efforts to
|
||||
see that any user of the Software licensed hereunder complies with
|
||||
this Agreement.
|
||||
|
||||
5. NO WARRANTIES. ID DISCLAIMS ALL WARRANTIES, BOTH EXPRESS
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT
|
||||
TO THE SOFTWARE. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||
RIGHTS. YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
|
||||
JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE
|
||||
WILL BE UNINTERRUPTED, ERROR FREE OR MEET YOUR SPECIFIC REQUIREMENTS.
|
||||
THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
|
||||
WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
|
||||
DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
|
||||
MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
|
||||
OF ID.
|
||||
|
||||
Exclusive Remedies. The Software is being offered to you
|
||||
free of any charge. You agree that you have no remedy against ID, its
|
||||
affiliates, contractors, suppliers, and agents for loss or damage
|
||||
caused by any defect or failure in the Software regardless of the form
|
||||
of action, whether in contract, tort, includinegligence, strict
|
||||
liability or otherwise, with regard to the Software. This Agreement
|
||||
shall be construed in accordance with and governed by the laws of the
|
||||
State of Texas. Copyright and other proprietary matters will be
|
||||
governed by United States laws and international treaties. IN ANY
|
||||
CASE, ID SHALL NOT BE LIABLE FOR LOSS OF DATA, LOSS OF PROFITS, LOST
|
||||
SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER
|
||||
SIMILAR DAMAGES ARISING FROM BREACH OF WARRANTY, BREACH OF CONTRACT,
|
||||
NEGLIGENCE, OR OTHER LEGAL THEORY EVEN IF ID OR ITS AGENT HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
|
||||
OTHER PARTY. Some jurisdictions do not allow the exclusion or
|
||||
limitation of incidental or consequential damages, so the above
|
||||
limitation or exclusion may not apply to you.
|
||||
|
||||
|
||||
|
||||
|
1319
src/DOOM/am_map.c
Normal file
1319
src/DOOM/am_map.c
Normal file
File diff suppressed because it is too large
Load Diff
56
src/DOOM/am_map.h
Normal file
56
src/DOOM/am_map.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// AutoMap module.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __AMMAP_H__
|
||||
#define __AMMAP_H__
|
||||
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
// Used by ST StatusBar stuff.
|
||||
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
|
||||
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
|
||||
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
|
||||
|
||||
|
||||
// Called by main loop.
|
||||
doom_boolean AM_Responder(event_t* ev);
|
||||
|
||||
// Called by main loop.
|
||||
void AM_Ticker(void);
|
||||
|
||||
// Called by main loop,
|
||||
// called instead of view drawer if automap active.
|
||||
void AM_Drawer(void);
|
||||
|
||||
// Called to force the automap to quit
|
||||
// if the level is completed while it is up.
|
||||
void AM_Stop(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
699
src/DOOM/d_englsh.h
Normal file
699
src/DOOM/d_englsh.h
Normal file
@ -0,0 +1,699 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Printed strings for translation.
|
||||
// English language support (default).
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_ENGLSH__
|
||||
#define __D_ENGLSH__
|
||||
|
||||
|
||||
//
|
||||
// Printed strings for translation
|
||||
//
|
||||
|
||||
//
|
||||
// D_Main.C
|
||||
//
|
||||
#define D_DEVSTR "Development mode ON.\n"
|
||||
#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n"
|
||||
|
||||
//
|
||||
// M_Menu.C
|
||||
//
|
||||
#define PRESSKEY "press a key."
|
||||
#define PRESSYN "press y or n."
|
||||
#define QUITMSG "are you sure you want to\nquit this great game?"
|
||||
#define LOADNET "you can't do load while in a net game!\n\n" PRESSKEY
|
||||
#define QLOADNET "you can't quickload during a netgame!\n\n" PRESSKEY
|
||||
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n" PRESSKEY
|
||||
#define SAVEDEAD "you can't save if you aren't playing!\n\n" PRESSKEY
|
||||
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n" PRESSYN
|
||||
#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n" PRESSYN
|
||||
|
||||
#define QSPROMPT_1 "quicksave over your game named\n\n'"
|
||||
#define QSPROMPT_2 "'?\n\n" PRESSYN
|
||||
#define QLPROMPT_1 "do you want to quickload the game named\n\n'%s"
|
||||
#define QLPROMPT_2 "'?\n\n" PRESSYN
|
||||
|
||||
#define NEWGAME \
|
||||
"you can't start a new game\n"\
|
||||
"while in a network game.\n\n" PRESSKEY
|
||||
|
||||
#define NIGHTMARE \
|
||||
"are you sure? this skill level\n"\
|
||||
"isn't even remotely fair.\n\n" PRESSYN
|
||||
|
||||
#define SWSTRING \
|
||||
"this is the shareware version of doom.\n\n"\
|
||||
"you need to order the entire trilogy.\n\n" PRESSKEY
|
||||
|
||||
#define MSGOFF "Messages OFF"
|
||||
#define MSGON "Messages ON"
|
||||
#define CROSSOFF "Crosshair OFF"
|
||||
#define CROSSON "Crosshair ON"
|
||||
#define ALWAYSRUNOFF "Always run OFF"
|
||||
#define ALWAYSRUNON "Always run ON"
|
||||
#define NETEND "you can't end a netgame!\n\n" PRESSKEY
|
||||
#define ENDGAME "are you sure you want to end the game?\n\n" PRESSYN
|
||||
|
||||
#define DOSY "(press y to quit)"
|
||||
|
||||
#define DETAILHI "High detail"
|
||||
#define DETAILLO "Low detail"
|
||||
#define GAMMALVL0 "Gamma correction OFF"
|
||||
#define GAMMALVL1 "Gamma correction level 1"
|
||||
#define GAMMALVL2 "Gamma correction level 2"
|
||||
#define GAMMALVL3 "Gamma correction level 3"
|
||||
#define GAMMALVL4 "Gamma correction level 4"
|
||||
#define EMPTYSTRING "empty slot"
|
||||
|
||||
//
|
||||
// P_inter.C
|
||||
//
|
||||
#define GOTARMOR "Picked up the armor."
|
||||
#define GOTMEGA "Picked up the MegaArmor!"
|
||||
#define GOTHTHBONUS "Picked up a health bonus."
|
||||
#define GOTARMBONUS "Picked up an armor bonus."
|
||||
#define GOTSTIM "Picked up a stimpack."
|
||||
#define GOTMEDINEED "Picked up a medikit that you REALLY need!"
|
||||
#define GOTMEDIKIT "Picked up a medikit."
|
||||
#define GOTSUPER "Supercharge!"
|
||||
|
||||
#define GOTBLUECARD "Picked up a blue keycard."
|
||||
#define GOTYELWCARD "Picked up a yellow keycard."
|
||||
#define GOTREDCARD "Picked up a red keycard."
|
||||
#define GOTBLUESKUL "Picked up a blue skull key."
|
||||
#define GOTYELWSKUL "Picked up a yellow skull key."
|
||||
#define GOTREDSKULL "Picked up a red skull key."
|
||||
|
||||
#define GOTINVUL "Invulnerability!"
|
||||
#define GOTBERSERK "Berserk!"
|
||||
#define GOTINVIS "Partial Invisibility"
|
||||
#define GOTSUIT "Radiation Shielding Suit"
|
||||
#define GOTMAP "Computer Area Map"
|
||||
#define GOTVISOR "Light Amplification Visor"
|
||||
#define GOTMSPHERE "MegaSphere!"
|
||||
|
||||
#define GOTCLIP "Picked up a clip."
|
||||
#define GOTCLIPBOX "Picked up a box of bullets."
|
||||
#define GOTROCKET "Picked up a rocket."
|
||||
#define GOTROCKBOX "Picked up a box of rockets."
|
||||
#define GOTCELL "Picked up an energy cell."
|
||||
#define GOTCELLBOX "Picked up an energy cell pack."
|
||||
#define GOTSHELLS "Picked up 4 shotgun shells."
|
||||
#define GOTSHELLBOX "Picked up a box of shotgun shells."
|
||||
#define GOTBACKPACK "Picked up a backpack full of ammo!"
|
||||
|
||||
#define GOTBFG9000 "You got the BFG9000! Oh, yes."
|
||||
#define GOTCHAINGUN "You got the chaingun!"
|
||||
#define GOTCHAINSAW "A chainsaw! Find some meat!"
|
||||
#define GOTLAUNCHER "You got the rocket launcher!"
|
||||
#define GOTPLASMA "You got the plasma gun!"
|
||||
#define GOTSHOTGUN "You got the shotgun!"
|
||||
#define GOTSHOTGUN2 "You got the super shotgun!"
|
||||
|
||||
//
|
||||
// P_Doors.C
|
||||
//
|
||||
#define PD_BLUEO "You need a blue key to activate this object"
|
||||
#define PD_REDO "You need a red key to activate this object"
|
||||
#define PD_YELLOWO "You need a yellow key to activate this object"
|
||||
#define PD_BLUEK "You need a blue key to open this door"
|
||||
#define PD_REDK "You need a red key to open this door"
|
||||
#define PD_YELLOWK "You need a yellow key to open this door"
|
||||
|
||||
//
|
||||
// G_game.C
|
||||
//
|
||||
#define GGSAVED "game saved."
|
||||
|
||||
//
|
||||
// HU_stuff.C
|
||||
//
|
||||
#define HUSTR_MSGU "[Message unsent]"
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: Hangar"
|
||||
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
|
||||
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
|
||||
#define HUSTR_E1M4 "E1M4: Command Control"
|
||||
#define HUSTR_E1M5 "E1M5: Phobos Lab"
|
||||
#define HUSTR_E1M6 "E1M6: Central Processing"
|
||||
#define HUSTR_E1M7 "E1M7: Computer Station"
|
||||
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
|
||||
#define HUSTR_E1M9 "E1M9: Military Base"
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
|
||||
#define HUSTR_E2M2 "E2M2: Containment Area"
|
||||
#define HUSTR_E2M3 "E2M3: Refinery"
|
||||
#define HUSTR_E2M4 "E2M4: Deimos Lab"
|
||||
#define HUSTR_E2M5 "E2M5: Command Center"
|
||||
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
|
||||
#define HUSTR_E2M7 "E2M7: Spawning Vats"
|
||||
#define HUSTR_E2M8 "E2M8: Tower of Babel"
|
||||
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: Hell Keep"
|
||||
#define HUSTR_E3M2 "E3M2: Slough of Despair"
|
||||
#define HUSTR_E3M3 "E3M3: Pandemonium"
|
||||
#define HUSTR_E3M4 "E3M4: House of Pain"
|
||||
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
|
||||
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
|
||||
#define HUSTR_E3M7 "E3M7: Limbo"
|
||||
#define HUSTR_E3M8 "E3M8: Dis"
|
||||
#define HUSTR_E3M9 "E3M9: Warrens"
|
||||
|
||||
#define HUSTR_E4M1 "E4M1: Hell Beneath"
|
||||
#define HUSTR_E4M2 "E4M2: Perfect Hatred"
|
||||
#define HUSTR_E4M3 "E4M3: Sever The Wicked"
|
||||
#define HUSTR_E4M4 "E4M4: Unruly Evil"
|
||||
#define HUSTR_E4M5 "E4M5: They Will Repent"
|
||||
#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
|
||||
#define HUSTR_E4M7 "E4M7: And Hell Followed"
|
||||
#define HUSTR_E4M8 "E4M8: Unto The Cruel"
|
||||
#define HUSTR_E4M9 "E4M9: Fear"
|
||||
|
||||
#define HUSTR_1 "level 1: entryway"
|
||||
#define HUSTR_2 "level 2: underhalls"
|
||||
#define HUSTR_3 "level 3: the gantlet"
|
||||
#define HUSTR_4 "level 4: the focus"
|
||||
#define HUSTR_5 "level 5: the waste tunnels"
|
||||
#define HUSTR_6 "level 6: the crusher"
|
||||
#define HUSTR_7 "level 7: dead simple"
|
||||
#define HUSTR_8 "level 8: tricks and traps"
|
||||
#define HUSTR_9 "level 9: the pit"
|
||||
#define HUSTR_10 "level 10: refueling base"
|
||||
#define HUSTR_11 "level 11: 'o' of destruction!"
|
||||
|
||||
#define HUSTR_12 "level 12: the factory"
|
||||
#define HUSTR_13 "level 13: downtown"
|
||||
#define HUSTR_14 "level 14: the inmost dens"
|
||||
#define HUSTR_15 "level 15: industrial zone"
|
||||
#define HUSTR_16 "level 16: suburbs"
|
||||
#define HUSTR_17 "level 17: tenements"
|
||||
#define HUSTR_18 "level 18: the courtyard"
|
||||
#define HUSTR_19 "level 19: the citadel"
|
||||
#define HUSTR_20 "level 20: gotcha!"
|
||||
|
||||
#define HUSTR_21 "level 21: nirvana"
|
||||
#define HUSTR_22 "level 22: the catacombs"
|
||||
#define HUSTR_23 "level 23: barrels o' fun"
|
||||
#define HUSTR_24 "level 24: the chasm"
|
||||
#define HUSTR_25 "level 25: bloodfalls"
|
||||
#define HUSTR_26 "level 26: the abandoned mines"
|
||||
#define HUSTR_27 "level 27: monster condo"
|
||||
#define HUSTR_28 "level 28: the spirit world"
|
||||
#define HUSTR_29 "level 29: the living end"
|
||||
#define HUSTR_30 "level 30: icon of sin"
|
||||
|
||||
#define HUSTR_31 "level 31: wolfenstein"
|
||||
#define HUSTR_32 "level 32: grosse"
|
||||
|
||||
#define PHUSTR_1 "level 1: congo"
|
||||
#define PHUSTR_2 "level 2: well of souls"
|
||||
#define PHUSTR_3 "level 3: aztec"
|
||||
#define PHUSTR_4 "level 4: caged"
|
||||
#define PHUSTR_5 "level 5: ghost town"
|
||||
#define PHUSTR_6 "level 6: baron's lair"
|
||||
#define PHUSTR_7 "level 7: caughtyard"
|
||||
#define PHUSTR_8 "level 8: realm"
|
||||
#define PHUSTR_9 "level 9: abattoire"
|
||||
#define PHUSTR_10 "level 10: onslaught"
|
||||
#define PHUSTR_11 "level 11: hunted"
|
||||
|
||||
#define PHUSTR_12 "level 12: speed"
|
||||
#define PHUSTR_13 "level 13: the crypt"
|
||||
#define PHUSTR_14 "level 14: genesis"
|
||||
#define PHUSTR_15 "level 15: the twilight"
|
||||
#define PHUSTR_16 "level 16: the omen"
|
||||
#define PHUSTR_17 "level 17: compound"
|
||||
#define PHUSTR_18 "level 18: neurosphere"
|
||||
#define PHUSTR_19 "level 19: nme"
|
||||
#define PHUSTR_20 "level 20: the death domain"
|
||||
|
||||
#define PHUSTR_21 "level 21: slayer"
|
||||
#define PHUSTR_22 "level 22: impossible mission"
|
||||
#define PHUSTR_23 "level 23: tombstone"
|
||||
#define PHUSTR_24 "level 24: the final frontier"
|
||||
#define PHUSTR_25 "level 25: the temple of darkness"
|
||||
#define PHUSTR_26 "level 26: bunker"
|
||||
#define PHUSTR_27 "level 27: anti-christ"
|
||||
#define PHUSTR_28 "level 28: the sewers"
|
||||
#define PHUSTR_29 "level 29: odyssey of noises"
|
||||
#define PHUSTR_30 "level 30: the gateway of hell"
|
||||
|
||||
#define PHUSTR_31 "level 31: cyberden"
|
||||
#define PHUSTR_32 "level 32: go 2 it"
|
||||
|
||||
#define THUSTR_1 "level 1: system control"
|
||||
#define THUSTR_2 "level 2: human bbq"
|
||||
#define THUSTR_3 "level 3: power control"
|
||||
#define THUSTR_4 "level 4: wormhole"
|
||||
#define THUSTR_5 "level 5: hanger"
|
||||
#define THUSTR_6 "level 6: open season"
|
||||
#define THUSTR_7 "level 7: prison"
|
||||
#define THUSTR_8 "level 8: metal"
|
||||
#define THUSTR_9 "level 9: stronghold"
|
||||
#define THUSTR_10 "level 10: redemption"
|
||||
#define THUSTR_11 "level 11: storage facility"
|
||||
|
||||
#define THUSTR_12 "level 12: crater"
|
||||
#define THUSTR_13 "level 13: nukage processing"
|
||||
#define THUSTR_14 "level 14: steel works"
|
||||
#define THUSTR_15 "level 15: dead zone"
|
||||
#define THUSTR_16 "level 16: deepest reaches"
|
||||
#define THUSTR_17 "level 17: processing area"
|
||||
#define THUSTR_18 "level 18: mill"
|
||||
#define THUSTR_19 "level 19: shipping/respawning"
|
||||
#define THUSTR_20 "level 20: central processing"
|
||||
|
||||
#define THUSTR_21 "level 21: administration center"
|
||||
#define THUSTR_22 "level 22: habitat"
|
||||
#define THUSTR_23 "level 23: lunar mining project"
|
||||
#define THUSTR_24 "level 24: quarry"
|
||||
#define THUSTR_25 "level 25: baron's den"
|
||||
#define THUSTR_26 "level 26: ballistyx"
|
||||
#define THUSTR_27 "level 27: mount pain"
|
||||
#define THUSTR_28 "level 28: heck"
|
||||
#define THUSTR_29 "level 29: river styx"
|
||||
#define THUSTR_30 "level 30: last call"
|
||||
|
||||
#define THUSTR_31 "level 31: pharaoh"
|
||||
#define THUSTR_32 "level 32: caribbean"
|
||||
|
||||
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
|
||||
#define HUSTR_CHATMACRO2 "I'm OK."
|
||||
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
|
||||
#define HUSTR_CHATMACRO4 "Help!"
|
||||
#define HUSTR_CHATMACRO5 "You suck!"
|
||||
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
|
||||
#define HUSTR_CHATMACRO7 "Come here!"
|
||||
#define HUSTR_CHATMACRO8 "I'll take care of it."
|
||||
#define HUSTR_CHATMACRO9 "Yes"
|
||||
#define HUSTR_CHATMACRO0 "No"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
|
||||
#define HUSTR_TALKTOSELF2 "Who's there?"
|
||||
#define HUSTR_TALKTOSELF3 "You scare yourself"
|
||||
#define HUSTR_TALKTOSELF4 "You start to rave"
|
||||
#define HUSTR_TALKTOSELF5 "You've lost it..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[Message Sent]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "Green: "
|
||||
#define HUSTR_PLRINDIGO "Indigo: "
|
||||
#define HUSTR_PLRBROWN "Brown: "
|
||||
#define HUSTR_PLRRED "Red: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g'
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//
|
||||
// AM_map.C
|
||||
//
|
||||
|
||||
#define AMSTR_FOLLOWON "Follow Mode ON"
|
||||
#define AMSTR_FOLLOWOFF "Follow Mode OFF"
|
||||
|
||||
#define AMSTR_GRIDON "Grid ON"
|
||||
#define AMSTR_GRIDOFF "Grid OFF"
|
||||
|
||||
#define AMSTR_MARKEDSPOT "Marked Spot"
|
||||
#define AMSTR_MARKSCLEARED "All Marks Cleared"
|
||||
|
||||
//
|
||||
// ST_stuff.C
|
||||
//
|
||||
|
||||
#define STSTR_MUS "Music Change"
|
||||
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
|
||||
#define STSTR_DQDON "Degreelessness Mode On"
|
||||
#define STSTR_DQDOFF "Degreelessness Mode Off"
|
||||
|
||||
#define STSTR_KFAADDED "Very Happy Ammo Added"
|
||||
#define STSTR_FAADDED "Ammo (no keys) Added"
|
||||
|
||||
#define STSTR_NCON "No Clipping Mode ON"
|
||||
#define STSTR_NCOFF "No Clipping Mode OFF"
|
||||
|
||||
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "Power-up Toggled"
|
||||
|
||||
#define STSTR_CHOPPERS "... doesn't suck - GM"
|
||||
#define STSTR_CLEV "Changing Level..."
|
||||
|
||||
//
|
||||
// F_Finale.C
|
||||
//
|
||||
#define E1TEXT \
|
||||
"Once you beat the big badasses and\n"\
|
||||
"clean out the moon base you're supposed\n"\
|
||||
"to win, aren't you? Aren't you? Where's\n"\
|
||||
"your fat reward and ticket home? What\n"\
|
||||
"the hell is this? It's not supposed to\n"\
|
||||
"end this way!\n"\
|
||||
"\n" \
|
||||
"It stinks like rotten meat, but looks\n"\
|
||||
"like the lost Deimos base. Looks like\n"\
|
||||
"you're stuck on The Shores of Hell.\n"\
|
||||
"The only way out is through.\n"\
|
||||
"\n"\
|
||||
"To continue the DOOM experience, play\n"\
|
||||
"The Shores of Hell and its amazing\n"\
|
||||
"sequel, Inferno!\n"
|
||||
|
||||
|
||||
#define E2TEXT \
|
||||
"You've done it! The hideous cyber-\n"\
|
||||
"demon lord that ruled the lost Deimos\n"\
|
||||
"moon base has been slain and you\n"\
|
||||
"are triumphant! But ... where are\n"\
|
||||
"you? You clamber to the edge of the\n"\
|
||||
"moon and look down to see the awful\n"\
|
||||
"truth.\n" \
|
||||
"\n"\
|
||||
"Deimos floats above Hell itself!\n"\
|
||||
"You've never heard of anyone escaping\n"\
|
||||
"from Hell, but you'll make the bastards\n"\
|
||||
"sorry they ever heard of you! Quickly,\n"\
|
||||
"you rappel down to the surface of\n"\
|
||||
"Hell.\n"\
|
||||
"\n" \
|
||||
"Now, it's on to the final chapter of\n"\
|
||||
"DOOM! -- Inferno."
|
||||
|
||||
|
||||
#define E3TEXT \
|
||||
"The loathsome spiderdemon that\n"\
|
||||
"masterminded the invasion of the moon\n"\
|
||||
"bases and caused so much death has had\n"\
|
||||
"its ass kicked for all time.\n"\
|
||||
"\n"\
|
||||
"A hidden doorway opens and you enter.\n"\
|
||||
"You've proven too tough for Hell to\n"\
|
||||
"contain, and now Hell at last plays\n"\
|
||||
"fair -- for you emerge from the door\n"\
|
||||
"to see the green fields of Earth!\n"\
|
||||
"Home at last.\n" \
|
||||
"\n"\
|
||||
"You wonder what's been happening on\n"\
|
||||
"Earth while you were battling evil\n"\
|
||||
"unleashed. It's good that no Hell-\n"\
|
||||
"spawn could have come through that\n"\
|
||||
"door with you ..."
|
||||
|
||||
|
||||
#define E4TEXT \
|
||||
"the spider mastermind must have sent forth\n"\
|
||||
"its legions of hellspawn before your\n"\
|
||||
"final confrontation with that terrible\n"\
|
||||
"beast from hell. but you stepped forward\n"\
|
||||
"and brought forth eternal damnation and\n"\
|
||||
"suffering upon the horde as a true hero\n"\
|
||||
"would in the face of something so evil.\n"\
|
||||
"\n"\
|
||||
"besides, someone was gonna pay for what\n"\
|
||||
"happened to daisy, your pet rabbit.\n"\
|
||||
"\n"\
|
||||
"but now, you see spread before you more\n"\
|
||||
"potential pain and gibbitude as a nation\n"\
|
||||
"of demons run amok among our cities.\n"\
|
||||
"\n"\
|
||||
"next stop, hell on earth!"
|
||||
|
||||
|
||||
// after level 6, put this:
|
||||
#define C1TEXT \
|
||||
"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
|
||||
"STARPORT. BUT SOMETHING IS WRONG. THE\n" \
|
||||
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
|
||||
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
|
||||
"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \
|
||||
"\n"\
|
||||
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \
|
||||
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \
|
||||
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \
|
||||
"OF THE STARBASE AND FIND THE CONTROLLING\n" \
|
||||
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
|
||||
"HOSTAGE."
|
||||
|
||||
// After level 11, put this:
|
||||
#define C2TEXT \
|
||||
"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
|
||||
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
|
||||
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
|
||||
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
|
||||
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\
|
||||
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\
|
||||
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\
|
||||
"THAT YOU HAVE SAVED YOUR SPECIES.\n"\
|
||||
"\n"\
|
||||
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\
|
||||
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\
|
||||
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\
|
||||
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\
|
||||
"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\
|
||||
"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\
|
||||
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
|
||||
"UP AND RETURN TO THE FRAY."
|
||||
|
||||
|
||||
// After level 20, put this:
|
||||
#define C3TEXT \
|
||||
"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
|
||||
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
|
||||
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
|
||||
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
|
||||
"TEETH AND PLUNGE THROUGH IT.\n"\
|
||||
"\n"\
|
||||
"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\
|
||||
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
|
||||
"GOT TO GO THROUGH HELL TO GET TO IT?"
|
||||
|
||||
|
||||
// After level 29, put this:
|
||||
#define C4TEXT \
|
||||
"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
|
||||
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
|
||||
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
|
||||
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
|
||||
"UP AND DIES, ITS THRASHING LIMBS\n"\
|
||||
"DEVASTATING UNTOLD MILES OF HELL'S\n"\
|
||||
"SURFACE.\n"\
|
||||
"\n"\
|
||||
"YOU'VE DONE IT. THE INVASION IS OVER.\n"\
|
||||
"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\
|
||||
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\
|
||||
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\
|
||||
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\
|
||||
"HOME. REBUILDING EARTH OUGHT TO BE A\n"\
|
||||
"LOT MORE FUN THAN RUINING IT WAS.\n"
|
||||
|
||||
|
||||
|
||||
// Before level 31, put this:
|
||||
#define C5TEXT \
|
||||
"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
|
||||
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
|
||||
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
|
||||
"WHO THE INMATES OF THIS CORNER OF HELL\n"\
|
||||
"WILL BE."
|
||||
|
||||
|
||||
// Before level 32, put this:
|
||||
#define C6TEXT \
|
||||
"CONGRATULATIONS, YOU'VE FOUND THE\n"\
|
||||
"SUPER SECRET LEVEL! YOU'D BETTER\n"\
|
||||
"BLAZE THROUGH THIS ONE!\n"
|
||||
|
||||
|
||||
// after map 06
|
||||
#define P1TEXT \
|
||||
"You gloat over the steaming carcass of the\n"\
|
||||
"Guardian. With its death, you've wrested\n"\
|
||||
"the Accelerator from the stinking claws\n"\
|
||||
"of Hell. You relax and glance around the\n"\
|
||||
"room. Damn! There was supposed to be at\n"\
|
||||
"least one working prototype, but you can't\n"\
|
||||
"see it. The demons must have taken it.\n"\
|
||||
"\n"\
|
||||
"You must find the prototype, or all your\n"\
|
||||
"struggles will have been wasted. Keep\n"\
|
||||
"moving, keep fighting, keep killing.\n"\
|
||||
"Oh yes, keep living, too."
|
||||
|
||||
|
||||
// after map 11
|
||||
#define P2TEXT \
|
||||
"Even the deadly Arch-Vile labyrinth could\n"\
|
||||
"not stop you, and you've gotten to the\n"\
|
||||
"prototype Accelerator which is soon\n"\
|
||||
"efficiently and permanently deactivated.\n"\
|
||||
"\n"\
|
||||
"You're good at that kind of thing."
|
||||
|
||||
|
||||
// after map 20
|
||||
#define P3TEXT \
|
||||
"You've bashed and battered your way into\n"\
|
||||
"the heart of the devil-hive. Time for a\n"\
|
||||
"Search-and-Destroy mission, aimed at the\n"\
|
||||
"Gatekeeper, whose foul offspring is\n"\
|
||||
"cascading to Earth. Yeah, he's bad. But\n"\
|
||||
"you know who's worse!\n"\
|
||||
"\n"\
|
||||
"Grinning evilly, you check your gear, and\n"\
|
||||
"get ready to give the bastard a little Hell\n"\
|
||||
"of your own making!"
|
||||
|
||||
// after map 30
|
||||
#define P4TEXT \
|
||||
"The Gatekeeper's evil face is splattered\n"\
|
||||
"all over the place. As its tattered corpse\n"\
|
||||
"collapses, an inverted Gate forms and\n"\
|
||||
"sucks down the shards of the last\n"\
|
||||
"prototype Accelerator, not to mention the\n"\
|
||||
"few remaining demons. You're done. Hell\n"\
|
||||
"has gone back to pounding bad dead folks \n"\
|
||||
"instead of good live ones. Remember to\n"\
|
||||
"tell your grandkids to put a rocket\n"\
|
||||
"launcher in your coffin. If you go to Hell\n"\
|
||||
"when you die, you'll need it for some\n"\
|
||||
"final cleaning-up ..."
|
||||
|
||||
// before map 31
|
||||
#define P5TEXT \
|
||||
"You've found the second-hardest level we\n"\
|
||||
"got. Hope you have a saved game a level or\n"\
|
||||
"two previous. If not, be prepared to die\n"\
|
||||
"aplenty. For master marines only."
|
||||
|
||||
// before map 32
|
||||
#define P6TEXT \
|
||||
"Betcha wondered just what WAS the hardest\n"\
|
||||
"level we had ready for ya? Now you know.\n"\
|
||||
"No one gets out alive."
|
||||
|
||||
|
||||
#define T1TEXT \
|
||||
"You've fought your way out of the infested\n"\
|
||||
"experimental labs. It seems that UAC has\n"\
|
||||
"once again gulped it down. With their\n"\
|
||||
"high turnover, it must be hard for poor\n"\
|
||||
"old UAC to buy corporate health insurance\n"\
|
||||
"nowadays..\n"\
|
||||
"\n"\
|
||||
"Ahead lies the military complex, now\n"\
|
||||
"swarming with diseased horrors hot to get\n"\
|
||||
"their teeth into you. With luck, the\n"\
|
||||
"complex still has some warlike ordnance\n"\
|
||||
"laying around."
|
||||
|
||||
|
||||
#define T2TEXT \
|
||||
"You hear the grinding of heavy machinery\n"\
|
||||
"ahead. You sure hope they're not stamping\n"\
|
||||
"out new hellspawn, but you're ready to\n"\
|
||||
"ream out a whole herd if you have to.\n"\
|
||||
"They might be planning a blood feast, but\n"\
|
||||
"you feel about as mean as two thousand\n"\
|
||||
"maniacs packed into one mad killer.\n"\
|
||||
"\n"\
|
||||
"You don't plan to go down easy."
|
||||
|
||||
|
||||
#define T3TEXT \
|
||||
"The vista opening ahead looks real damn\n"\
|
||||
"familiar. Smells familiar, too -- like\n"\
|
||||
"fried excrement. You didn't like this\n"\
|
||||
"place before, and you sure as hell ain't\n"\
|
||||
"planning to like it now. The more you\n"\
|
||||
"brood on it, the madder you get.\n"\
|
||||
"Hefting your gun, an evil grin trickles\n"\
|
||||
"onto your face. Time to take some names."
|
||||
|
||||
#define T4TEXT \
|
||||
"Suddenly, all is silent, from one horizon\n"\
|
||||
"to the other. The agonizing echo of Hell\n"\
|
||||
"fades away, the nightmare sky turns to\n"\
|
||||
"blue, the heaps of monster corpses start \n"\
|
||||
"to evaporate along with the evil stench \n"\
|
||||
"that filled the air. Jeeze, maybe you've\n"\
|
||||
"done it. Have you really won?\n"\
|
||||
"\n"\
|
||||
"Something rumbles in the distance.\n"\
|
||||
"A blue light begins to glow inside the\n"\
|
||||
"ruined skull of the demon-spitter."
|
||||
|
||||
|
||||
#define T5TEXT \
|
||||
"What now? Looks totally different. Kind\n"\
|
||||
"of like King Tut's condo. Well,\n"\
|
||||
"whatever's here can't be any worse\n"\
|
||||
"than usual. Can it? Or maybe it's best\n"\
|
||||
"to let sleeping gods lie.."
|
||||
|
||||
|
||||
#define T6TEXT \
|
||||
"Time for a vacation. You've burst the\n"\
|
||||
"bowels of hell and by golly you're ready\n"\
|
||||
"for a break. You mutter to yourself,\n"\
|
||||
"Maybe someone else can kick Hell's ass\n"\
|
||||
"next time around. Ahead lies a quiet town,\n"\
|
||||
"with peaceful flowing water, quaint\n"\
|
||||
"buildings, and presumably no Hellspawn.\n"\
|
||||
"\n"\
|
||||
"As you step off the transport, you hear\n"\
|
||||
"the stomp of a cyberdemon's iron shoe."
|
||||
|
||||
|
||||
//
|
||||
// Character cast strings F_FINALE.C
|
||||
//
|
||||
#define CC_ZOMBIE "ZOMBIEMAN"
|
||||
#define CC_SHOTGUN "SHOTGUN GUY"
|
||||
#define CC_HEAVY "HEAVY WEAPON DUDE"
|
||||
#define CC_IMP "IMP"
|
||||
#define CC_DEMON "DEMON"
|
||||
#define CC_LOST "LOST SOUL"
|
||||
#define CC_CACO "CACODEMON"
|
||||
#define CC_HELL "HELL KNIGHT"
|
||||
#define CC_BARON "BARON OF HELL"
|
||||
#define CC_ARACH "ARACHNOTRON"
|
||||
#define CC_PAIN "PAIN ELEMENTAL"
|
||||
#define CC_REVEN "REVENANT"
|
||||
#define CC_MANCU "MANCUBUS"
|
||||
#define CC_ARCH "ARCH-VILE"
|
||||
#define CC_SPIDER "THE SPIDER MASTERMIND"
|
||||
#define CC_CYBER "THE CYBERDEMON"
|
||||
#define CC_HERO "OUR HERO"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
119
src/DOOM/d_event.h
Normal file
119
src/DOOM/d_event.h
Normal file
@ -0,0 +1,119 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_EVENT__
|
||||
#define __D_EVENT__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
//
|
||||
// Event handling.
|
||||
//
|
||||
|
||||
// Input event types.
|
||||
typedef enum
|
||||
{
|
||||
ev_keydown,
|
||||
ev_keyup,
|
||||
ev_mouse,
|
||||
ev_joystick
|
||||
} evtype_t;
|
||||
|
||||
|
||||
// Event structure.
|
||||
typedef struct
|
||||
{
|
||||
evtype_t type;
|
||||
int data1; // keys / mouse/joystick buttons
|
||||
int data2; // mouse/joystick x move
|
||||
int data3; // mouse/joystick y move
|
||||
} event_t;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ga_nothing,
|
||||
ga_loadlevel,
|
||||
ga_newgame,
|
||||
ga_loadgame,
|
||||
ga_savegame,
|
||||
ga_playdemo,
|
||||
ga_completed,
|
||||
ga_victory,
|
||||
ga_worlddone,
|
||||
ga_screenshot
|
||||
} gameaction_t;
|
||||
|
||||
|
||||
//
|
||||
// Button/action code definitions.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Press "Fire".
|
||||
BT_ATTACK = 1,
|
||||
// Use button, to open doors, activate switches.
|
||||
BT_USE = 2,
|
||||
|
||||
// Flag: game events, not really buttons.
|
||||
BT_SPECIAL = 128,
|
||||
BT_SPECIALMASK = 3,
|
||||
|
||||
// Flag, weapon change pending.
|
||||
// If true, the next 3 bits hold weapon num.
|
||||
BT_CHANGE = 4,
|
||||
// The 3bit weapon mask and shift, convenience.
|
||||
BT_WEAPONMASK = (8 + 16 + 32),
|
||||
BT_WEAPONSHIFT = 3,
|
||||
|
||||
// Pause the game.
|
||||
BTS_PAUSE = 1,
|
||||
// Save the game at each console.
|
||||
BTS_SAVEGAME = 2,
|
||||
|
||||
// Savegame slot numbers
|
||||
// occupy the second byte of buttons.
|
||||
BTS_SAVEMASK = (4 + 8 + 16),
|
||||
BTS_SAVESHIFT = 2,
|
||||
} buttoncode_t;
|
||||
|
||||
|
||||
//
|
||||
// GLOBAL VARIABLES
|
||||
//
|
||||
#define MAXEVENTS (64 * 64) // [pd] Crank up the number because we pump them faster
|
||||
|
||||
extern event_t events[MAXEVENTS];
|
||||
extern int eventhead;
|
||||
extern int eventtail;
|
||||
|
||||
extern gameaction_t gameaction;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
433
src/DOOM/d_french.h
Normal file
433
src/DOOM/d_french.h
Normal file
@ -0,0 +1,433 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Printed strings, french translation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __D_FRENCH__
|
||||
#define __D_FRENCH__
|
||||
|
||||
//
|
||||
// D_Main.C
|
||||
//
|
||||
#define D_DEVSTR "MODE DEVELOPPEMENT ON.\n"
|
||||
#define D_CDROM "VERSION CD-ROM: DEFAULT.CFG DANS C:\\DOOMDATA\n"
|
||||
|
||||
//
|
||||
// M_Menu.C
|
||||
//
|
||||
#define PRESSKEY "APPUYEZ SUR UNE TOUCHE."
|
||||
#define PRESSYN "APPUYEZ SUR Y OU N"
|
||||
#define QUITMSG "VOUS VOULEZ VRAIMENT\nQUITTER CE SUPER JEU?"
|
||||
#define LOADNET "VOUS NE POUVEZ PAS CHARGER\nUN JEU EN RESEAU!\n\n"PRESSKEY
|
||||
#define QLOADNET "CHARGEMENT RAPIDE INTERDIT EN RESEAU!\n\n"PRESSKEY
|
||||
#define QSAVESPOT "VOUS N'AVEZ PAS CHOISI UN EMPLACEMENT!\n\n"PRESSKEY
|
||||
#define SAVEDEAD "VOUS NE POUVEZ PAS SAUVER SI VOUS NE JOUEZ "\
|
||||
"PAS!\n\n"PRESSKEY
|
||||
#define QSPROMPT "SAUVEGARDE RAPIDE DANS LE FICHIER \n\n'%s'?\n\n"PRESSYN
|
||||
#define QLPROMPT "VOULEZ-VOUS CHARGER LA SAUVEGARDE"\
|
||||
"\n\n'%s'?\n\n"PRESSYN
|
||||
#define NEWGAME "VOUS NE POUVEZ PAS LANCER\n"\
|
||||
"UN NOUVEAU JEU SUR RESEAU.\n\n"PRESSKEY
|
||||
#define NIGHTMARE "VOUS CONFIRMEZ? CE NIVEAU EST\n"\
|
||||
"VRAIMENT IMPITOYABLE!n"PRESSYN
|
||||
#define SWSTRING "CECI EST UNE VERSION SHAREWARE DE DOOM.\n\n"\
|
||||
"VOUS DEVRIEZ COMMANDER LA TRILOGIE COMPLETE.\n\n"PRESSKEY
|
||||
#define MSGOFF "MESSAGES OFF"
|
||||
#define MSGON "MESSAGES ON"
|
||||
#define NETEND "VOUS NE POUVEZ PAS METTRE FIN A UN JEU SUR "\
|
||||
"RESEAU!\n\n"PRESSKEY
|
||||
#define ENDGAME "VOUS VOULEZ VRAIMENT METTRE FIN AU JEU?\n\n"PRESSYN
|
||||
|
||||
#define DOSY "(APPUYEZ SUR Y POUR REVENIR AU OS.)"
|
||||
|
||||
#define DETAILHI "GRAPHISMES MAXIMUM "
|
||||
#define DETAILLO "GRAPHISMES MINIMUM "
|
||||
#define GAMMALVL0 "CORRECTION GAMMA OFF"
|
||||
#define GAMMALVL1 "CORRECTION GAMMA NIVEAU 1"
|
||||
#define GAMMALVL2 "CORRECTION GAMMA NIVEAU 2"
|
||||
#define GAMMALVL3 "CORRECTION GAMMA NIVEAU 3"
|
||||
#define GAMMALVL4 "CORRECTION GAMMA NIVEAU 4"
|
||||
#define EMPTYSTRING "EMPLACEMENT VIDE"
|
||||
|
||||
//
|
||||
// P_inter.C
|
||||
//
|
||||
#define GOTARMOR "ARMURE RECUPEREE."
|
||||
#define GOTMEGA "MEGA-ARMURE RECUPEREE!"
|
||||
#define GOTHTHBONUS "BONUS DE SANTE RECUPERE."
|
||||
#define GOTARMBONUS "BONUS D'ARMURE RECUPERE."
|
||||
#define GOTSTIM "STIMPACK RECUPERE."
|
||||
#define GOTMEDINEED "MEDIKIT RECUPERE. VOUS EN AVEZ VRAIMENT BESOIN!"
|
||||
#define GOTMEDIKIT "MEDIKIT RECUPERE."
|
||||
#define GOTSUPER "SUPERCHARGE!"
|
||||
|
||||
#define GOTBLUECARD "CARTE MAGNETIQUE BLEUE RECUPEREE."
|
||||
#define GOTYELWCARD "CARTE MAGNETIQUE JAUNE RECUPEREE."
|
||||
#define GOTREDCARD "CARTE MAGNETIQUE ROUGE RECUPEREE."
|
||||
#define GOTBLUESKUL "CLEF CRANE BLEUE RECUPEREE."
|
||||
#define GOTYELWSKUL "CLEF CRANE JAUNE RECUPEREE."
|
||||
#define GOTREDSKULL "CLEF CRANE ROUGE RECUPEREE."
|
||||
|
||||
#define GOTINVUL "INVULNERABILITE!"
|
||||
#define GOTBERSERK "BERSERK!"
|
||||
#define GOTINVIS "INVISIBILITE PARTIELLE "
|
||||
#define GOTSUIT "COMBINAISON ANTI-RADIATIONS "
|
||||
#define GOTMAP "CARTE INFORMATIQUE "
|
||||
#define GOTVISOR "VISEUR A AMPLIFICATION DE LUMIERE "
|
||||
#define GOTMSPHERE "MEGASPHERE!"
|
||||
|
||||
#define GOTCLIP "CHARGEUR RECUPERE."
|
||||
#define GOTCLIPBOX "BOITE DE BALLES RECUPEREE."
|
||||
#define GOTROCKET "ROQUETTE RECUPEREE."
|
||||
#define GOTROCKBOX "CAISSE DE ROQUETTES RECUPEREE."
|
||||
#define GOTCELL "CELLULE D'ENERGIE RECUPEREE."
|
||||
#define GOTCELLBOX "PACK DE CELLULES D'ENERGIE RECUPERE."
|
||||
#define GOTSHELLS "4 CARTOUCHES RECUPEREES."
|
||||
#define GOTSHELLBOX "BOITE DE CARTOUCHES RECUPEREE."
|
||||
#define GOTBACKPACK "SAC PLEIN DE MUNITIONS RECUPERE!"
|
||||
|
||||
#define GOTBFG9000 "VOUS AVEZ UN BFG9000! OH, OUI!"
|
||||
#define GOTCHAINGUN "VOUS AVEZ LA MITRAILLEUSE!"
|
||||
#define GOTCHAINSAW "UNE TRONCONNEUSE!"
|
||||
#define GOTLAUNCHER "VOUS AVEZ UN LANCE-ROQUETTES!"
|
||||
#define GOTPLASMA "VOUS AVEZ UN FUSIL A PLASMA!"
|
||||
#define GOTSHOTGUN "VOUS AVEZ UN FUSIL!"
|
||||
#define GOTSHOTGUN2 "VOUS AVEZ UN SUPER FUSIL!"
|
||||
|
||||
//
|
||||
// P_Doors.C
|
||||
//
|
||||
#define PD_BLUEO "IL VOUS FAUT UNE CLEF BLEUE"
|
||||
#define PD_REDO "IL VOUS FAUT UNE CLEF ROUGE"
|
||||
#define PD_YELLOWO "IL VOUS FAUT UNE CLEF JAUNE"
|
||||
#define PD_BLUEK PD_BLUEO
|
||||
#define PD_REDK PD_REDO
|
||||
#define PD_YELLOWK PD_YELLOWO
|
||||
|
||||
//
|
||||
// G_game.C
|
||||
//
|
||||
#define GGSAVED "JEU SAUVEGARDE."
|
||||
|
||||
//
|
||||
// HU_stuff.C
|
||||
//
|
||||
#define HUSTR_MSGU "[MESSAGE NON ENVOYE]"
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: HANGAR"
|
||||
#define HUSTR_E1M2 "E1M2: USINE NUCLEAIRE "
|
||||
#define HUSTR_E1M3 "E1M3: RAFFINERIE DE TOXINES "
|
||||
#define HUSTR_E1M4 "E1M4: CENTRE DE CONTROLE "
|
||||
#define HUSTR_E1M5 "E1M5: LABORATOIRE PHOBOS "
|
||||
#define HUSTR_E1M6 "E1M6: TRAITEMENT CENTRAL "
|
||||
#define HUSTR_E1M7 "E1M7: CENTRE INFORMATIQUE "
|
||||
#define HUSTR_E1M8 "E1M8: ANOMALIE PHOBOS "
|
||||
#define HUSTR_E1M9 "E1M9: BASE MILITAIRE "
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: ANOMALIE DEIMOS "
|
||||
#define HUSTR_E2M2 "E2M2: ZONE DE CONFINEMENT "
|
||||
#define HUSTR_E2M3 "E2M3: RAFFINERIE"
|
||||
#define HUSTR_E2M4 "E2M4: LABORATOIRE DEIMOS "
|
||||
#define HUSTR_E2M5 "E2M5: CENTRE DE CONTROLE "
|
||||
#define HUSTR_E2M6 "E2M6: HALLS DES DAMNES "
|
||||
#define HUSTR_E2M7 "E2M7: CUVES DE REPRODUCTION "
|
||||
#define HUSTR_E2M8 "E2M8: TOUR DE BABEL "
|
||||
#define HUSTR_E2M9 "E2M9: FORTERESSE DU MYSTERE "
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: DONJON DE L'ENFER "
|
||||
#define HUSTR_E3M2 "E3M2: BOURBIER DU DESESPOIR "
|
||||
#define HUSTR_E3M3 "E3M3: PANDEMONIUM"
|
||||
#define HUSTR_E3M4 "E3M4: MAISON DE LA DOULEUR "
|
||||
#define HUSTR_E3M5 "E3M5: CATHEDRALE PROFANE "
|
||||
#define HUSTR_E3M6 "E3M6: MONT EREBUS"
|
||||
#define HUSTR_E3M7 "E3M7: LIMBES"
|
||||
#define HUSTR_E3M8 "E3M8: DIS"
|
||||
#define HUSTR_E3M9 "E3M9: CLAPIERS"
|
||||
|
||||
#define HUSTR_1 "NIVEAU 1: ENTREE "
|
||||
#define HUSTR_2 "NIVEAU 2: HALLS SOUTERRAINS "
|
||||
#define HUSTR_3 "NIVEAU 3: LE FEU NOURRI "
|
||||
#define HUSTR_4 "NIVEAU 4: LE FOYER "
|
||||
#define HUSTR_5 "NIVEAU 5: LES EGOUTS "
|
||||
#define HUSTR_6 "NIVEAU 6: LE BROYEUR "
|
||||
#define HUSTR_7 "NIVEAU 7: L'HERBE DE LA MORT"
|
||||
#define HUSTR_8 "NIVEAU 8: RUSES ET PIEGES "
|
||||
#define HUSTR_9 "NIVEAU 9: LE PUITS "
|
||||
#define HUSTR_10 "NIVEAU 10: BASE DE RAVITAILLEMENT "
|
||||
#define HUSTR_11 "NIVEAU 11: LE CERCLE DE LA MORT!"
|
||||
|
||||
#define HUSTR_12 "NIVEAU 12: L'USINE "
|
||||
#define HUSTR_13 "NIVEAU 13: LE CENTRE VILLE"
|
||||
#define HUSTR_14 "NIVEAU 14: LES ANTRES PROFONDES "
|
||||
#define HUSTR_15 "NIVEAU 15: LA ZONE INDUSTRIELLE "
|
||||
#define HUSTR_16 "NIVEAU 16: LA BANLIEUE"
|
||||
#define HUSTR_17 "NIVEAU 17: LES IMMEUBLES"
|
||||
#define HUSTR_18 "NIVEAU 18: LA COUR "
|
||||
#define HUSTR_19 "NIVEAU 19: LA CITADELLE "
|
||||
#define HUSTR_20 "NIVEAU 20: JE T'AI EU!"
|
||||
|
||||
#define HUSTR_21 "NIVEAU 21: LE NIRVANA"
|
||||
#define HUSTR_22 "NIVEAU 22: LES CATACOMBES "
|
||||
#define HUSTR_23 "NIVEAU 23: LA GRANDE FETE "
|
||||
#define HUSTR_24 "NIVEAU 24: LE GOUFFRE "
|
||||
#define HUSTR_25 "NIVEAU 25: LES CHUTES DE SANG"
|
||||
#define HUSTR_26 "NIVEAU 26: LES MINES ABANDONNEES "
|
||||
#define HUSTR_27 "NIVEAU 27: CHEZ LES MONSTRES "
|
||||
#define HUSTR_28 "NIVEAU 28: LE MONDE DE L'ESPRIT "
|
||||
#define HUSTR_29 "NIVEAU 29: LA LIMITE "
|
||||
#define HUSTR_30 "NIVEAU 30: L'ICONE DU PECHE "
|
||||
|
||||
#define HUSTR_31 "NIVEAU 31: WOLFENSTEIN"
|
||||
#define HUSTR_32 "NIVEAU 32: LE MASSACRE"
|
||||
|
||||
|
||||
#define HUSTR_CHATMACRO1 "JE SUIS PRET A LEUR EN FAIRE BAVER!"
|
||||
#define HUSTR_CHATMACRO2 "JE VAIS BIEN."
|
||||
#define HUSTR_CHATMACRO3 "JE N'AI PAS L'AIR EN FORME!"
|
||||
#define HUSTR_CHATMACRO4 "AU SECOURS!"
|
||||
#define HUSTR_CHATMACRO5 "TU CRAINS!"
|
||||
#define HUSTR_CHATMACRO6 "LA PROCHAINE FOIS, MINABLE..."
|
||||
#define HUSTR_CHATMACRO7 "VIENS ICI!"
|
||||
#define HUSTR_CHATMACRO8 "JE VAIS M'EN OCCUPER."
|
||||
#define HUSTR_CHATMACRO9 "OUI"
|
||||
#define HUSTR_CHATMACRO0 "NON"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "VOUS PARLEZ TOUT SEUL "
|
||||
#define HUSTR_TALKTOSELF2 "QUI EST LA?"
|
||||
#define HUSTR_TALKTOSELF3 "VOUS VOUS FAITES PEUR "
|
||||
#define HUSTR_TALKTOSELF4 "VOUS COMMENCEZ A DELIRER "
|
||||
#define HUSTR_TALKTOSELF5 "VOUS ETES LARGUE..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[MESSAGE ENVOYE]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "VERT: "
|
||||
#define HUSTR_PLRINDIGO "INDIGO: "
|
||||
#define HUSTR_PLRBROWN "BRUN: "
|
||||
#define HUSTR_PLRRED "ROUGE: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g' // french key should be "V"
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//
|
||||
// AM_map.C
|
||||
//
|
||||
|
||||
#define AMSTR_FOLLOWON "MODE POURSUITE ON"
|
||||
#define AMSTR_FOLLOWOFF "MODE POURSUITE OFF"
|
||||
|
||||
#define AMSTR_GRIDON "GRILLE ON"
|
||||
#define AMSTR_GRIDOFF "GRILLE OFF"
|
||||
|
||||
#define AMSTR_MARKEDSPOT "REPERE MARQUE "
|
||||
#define AMSTR_MARKSCLEARED "REPERES EFFACES "
|
||||
|
||||
//
|
||||
// ST_stuff.C
|
||||
//
|
||||
|
||||
#define STSTR_MUS "CHANGEMENT DE MUSIQUE "
|
||||
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
|
||||
#define STSTR_DQDON "INVULNERABILITE ON "
|
||||
#define STSTR_DQDOFF "INVULNERABILITE OFF"
|
||||
|
||||
#define STSTR_KFAADDED "ARMEMENT MAXIMUM! "
|
||||
#define STSTR_FAADDED "ARMES (SAUF CLEFS) AJOUTEES"
|
||||
|
||||
#define STSTR_NCON "BARRIERES ON"
|
||||
#define STSTR_NCOFF "BARRIERES OFF"
|
||||
|
||||
#define STSTR_BEHOLD " inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "AMELIORATION ACTIVEE"
|
||||
|
||||
#define STSTR_CHOPPERS "... DOESN'T SUCK - GM"
|
||||
#define STSTR_CLEV "CHANGEMENT DE NIVEAU..."
|
||||
|
||||
//
|
||||
// F_Finale.C
|
||||
//
|
||||
#define E1TEXT "APRES AVOIR VAINCU LES GROS MECHANTS\n"\
|
||||
"ET NETTOYE LA BASE LUNAIRE, VOUS AVEZ\n"\
|
||||
"GAGNE, NON? PAS VRAI? OU EST DONC VOTRE\n"\
|
||||
" RECOMPENSE ET VOTRE BILLET DE\n"\
|
||||
"RETOUR? QU'EST-QUE CA VEUT DIRE?CE"\
|
||||
"N'EST PAS LA FIN ESPEREE!\n"\
|
||||
"\n" \
|
||||
"CA SENT LA VIANDE PUTREFIEE, MAIS\n"\
|
||||
"ON DIRAIT LA BASE DEIMOS. VOUS ETES\n"\
|
||||
"APPAREMMENT BLOQUE AUX PORTES DE L'ENFER.\n"\
|
||||
"LA SEULE ISSUE EST DE L'AUTRE COTE.\n"\
|
||||
"\n"\
|
||||
"POUR VIVRE LA SUITE DE DOOM, JOUEZ\n"\
|
||||
"A 'AUX PORTES DE L'ENFER' ET A\n"\
|
||||
"L'EPISODE SUIVANT, 'L'ENFER'!\n"
|
||||
|
||||
#define E2TEXT "VOUS AVEZ REUSSI. L'INFAME DEMON\n"\
|
||||
"QUI CONTROLAIT LA BASE LUNAIRE DE\n"\
|
||||
"DEIMOS EST MORT, ET VOUS AVEZ\n"\
|
||||
"TRIOMPHE! MAIS... OU ETES-VOUS?\n"\
|
||||
"VOUS GRIMPEZ JUSQU'AU BORD DE LA\n"\
|
||||
"LUNE ET VOUS DECOUVREZ L'ATROCE\n"\
|
||||
"VERITE.\n" \
|
||||
"\n"\
|
||||
"DEIMOS EST AU-DESSUS DE L'ENFER!\n"\
|
||||
"VOUS SAVEZ QUE PERSONNE NE S'EN\n"\
|
||||
"EST JAMAIS ECHAPPE, MAIS CES FUMIERS\n"\
|
||||
"VONT REGRETTER DE VOUS AVOIR CONNU!\n"\
|
||||
"VOUS REDESCENDEZ RAPIDEMENT VERS\n"\
|
||||
"LA SURFACE DE L'ENFER.\n"\
|
||||
"\n" \
|
||||
"VOICI MAINTENANT LE CHAPITRE FINAL DE\n"\
|
||||
"DOOM! -- L'ENFER."
|
||||
|
||||
#define E3TEXT "LE DEMON ARACHNEEN ET REPUGNANT\n"\
|
||||
"QUI A DIRIGE L'INVASION DES BASES\n"\
|
||||
"LUNAIRES ET SEME LA MORT VIENT DE SE\n"\
|
||||
"FAIRE PULVERISER UNE FOIS POUR TOUTES.\n"\
|
||||
"\n"\
|
||||
"UNE PORTE SECRETE S'OUVRE. VOUS ENTREZ.\n"\
|
||||
"VOUS AVEZ PROUVE QUE VOUS POUVIEZ\n"\
|
||||
"RESISTER AUX HORREURS DE L'ENFER.\n"\
|
||||
"IL SAIT ETRE BEAU JOUEUR, ET LORSQUE\n"\
|
||||
"VOUS SORTEZ, VOUS REVOYEZ LES VERTES\n"\
|
||||
"PRAIRIES DE LA TERRE, VOTRE PLANETE.\n"\
|
||||
"\n"\
|
||||
"VOUS VOUS DEMANDEZ CE QUI S'EST PASSE\n"\
|
||||
"SUR TERRE PENDANT QUE VOUS AVEZ\n"\
|
||||
"COMBATTU LE DEMON. HEUREUSEMENT,\n"\
|
||||
"AUCUN GERME DU MAL N'A FRANCHI\n"\
|
||||
"CETTE PORTE AVEC VOUS..."
|
||||
|
||||
|
||||
|
||||
// after level 6, put this:
|
||||
|
||||
#define C1TEXT "VOUS ETES AU PLUS PROFOND DE L'ASTROPORT\n" \
|
||||
"INFESTE DE MONSTRES, MAIS QUELQUE CHOSE\n" \
|
||||
"NE VA PAS. ILS ONT APPORTE LEUR PROPRE\n" \
|
||||
"REALITE, ET LA TECHNOLOGIE DE L'ASTROPORT\n" \
|
||||
"EST AFFECTEE PAR LEUR PRESENCE.\n" \
|
||||
"\n"\
|
||||
"DEVANT VOUS, VOUS VOYEZ UN POSTE AVANCE\n" \
|
||||
"DE L'ENFER, UNE ZONE FORTIFIEE. SI VOUS\n" \
|
||||
"POUVEZ PASSER, VOUS POURREZ PENETRER AU\n" \
|
||||
"COEUR DE LA BASE HANTEE ET TROUVER \n" \
|
||||
"L'INTERRUPTEUR DE CONTROLE QUI GARDE LA \n" \
|
||||
"POPULATION DE LA TERRE EN OTAGE."
|
||||
|
||||
// After level 11, put this:
|
||||
|
||||
#define C2TEXT "VOUS AVEZ GAGNE! VOTRE VICTOIRE A PERMIS\n" \
|
||||
"A L'HUMANITE D'EVACUER LA TERRE ET \n"\
|
||||
"D'ECHAPPER AU CAUCHEMAR. VOUS ETES \n"\
|
||||
"MAINTENANT LE DERNIER HUMAIN A LA SURFACE \n"\
|
||||
"DE LA PLANETE. VOUS ETES ENTOURE DE \n"\
|
||||
"MUTANTS CANNIBALES, D'EXTRATERRESTRES \n"\
|
||||
"CARNIVORES ET D'ESPRITS DU MAL. VOUS \n"\
|
||||
"ATTENDEZ CALMEMENT LA MORT, HEUREUX \n"\
|
||||
"D'AVOIR PU SAUVER VOTRE RACE.\n"\
|
||||
"MAIS UN MESSAGE VOUS PARVIENT SOUDAIN\n"\
|
||||
"DE L'ESPACE: \"NOS CAPTEURS ONT LOCALISE\n"\
|
||||
"LA SOURCE DE L'INVASION EXTRATERRESTRE.\n"\
|
||||
"SI VOUS Y ALLEZ, VOUS POURREZ PEUT-ETRE\n"\
|
||||
"LES ARRETER. LEUR BASE EST SITUEE AU COEUR\n"\
|
||||
"DE VOTRE VILLE NATALE, PRES DE L'ASTROPORT.\n"\
|
||||
"VOUS VOUS RELEVEZ LENTEMENT ET PENIBLEMENT\n"\
|
||||
"ET VOUS REPARTEZ POUR LE FRONT."
|
||||
|
||||
// After level 20, put this:
|
||||
|
||||
#define C3TEXT "VOUS ETES AU COEUR DE LA CITE CORROMPUE,\n"\
|
||||
"ENTOURE PAR LES CADAVRES DE VOS ENNEMIS.\n"\
|
||||
"VOUS NE VOYEZ PAS COMMENT DETRUIRE LA PORTE\n"\
|
||||
"DES CREATURES DE CE COTE. VOUS SERREZ\n"\
|
||||
"LES DENTS ET PLONGEZ DANS L'OUVERTURE.\n"\
|
||||
"\n"\
|
||||
"IL DOIT Y AVOIR UN MOYEN DE LA FERMER\n"\
|
||||
"DE L'AUTRE COTE. VOUS ACCEPTEZ DE\n"\
|
||||
"TRAVERSER L'ENFER POUR LE FAIRE?"
|
||||
|
||||
// After level 29, put this:
|
||||
|
||||
#define C4TEXT "LE VISAGE HORRIBLE D'UN DEMON D'UNE\n"\
|
||||
"TAILLE INCROYABLE S'EFFONDRE DEVANT\n"\
|
||||
"VOUS LORSQUE VOUS TIREZ UNE SALVE DE\n"\
|
||||
"ROQUETTES DANS SON CERVEAU. LE MONSTRE\n"\
|
||||
"SE RATATINE, SES MEMBRES DECHIQUETES\n"\
|
||||
"SE REPANDANT SUR DES CENTAINES DE\n"\
|
||||
"KILOMETRES A LA SURFACE DE L'ENFER.\n"\
|
||||
"\n"\
|
||||
"VOUS AVEZ REUSSI. L'INVASION N'AURA.\n"\
|
||||
"PAS LIEU. LA TERRE EST SAUVEE. L'ENFER\n"\
|
||||
"EST ANEANTI. EN VOUS DEMANDANT OU IRONT\n"\
|
||||
"MAINTENANT LES DAMNES, VOUS ESSUYEZ\n"\
|
||||
"VOTRE FRONT COUVERT DE SUEUR ET REPARTEZ\n"\
|
||||
"VERS LA TERRE. SA RECONSTRUCTION SERA\n"\
|
||||
"BEAUCOUP PLUS DROLE QUE SA DESTRUCTION.\n"
|
||||
|
||||
// Before level 31, put this:
|
||||
|
||||
#define C5TEXT "FELICITATIONS! VOUS AVEZ TROUVE LE\n"\
|
||||
"NIVEAU SECRET! IL SEMBLE AVOIR ETE\n"\
|
||||
"CONSTRUIT PAR LES HUMAINS. VOUS VOUS\n"\
|
||||
"DEMANDEZ QUELS PEUVENT ETRE LES\n"\
|
||||
"HABITANTS DE CE COIN PERDU DE L'ENFER."
|
||||
|
||||
// Before level 32, put this:
|
||||
|
||||
#define C6TEXT "FELICITATIONS! VOUS AVEZ DECOUVERT\n"\
|
||||
"LE NIVEAU SUPER SECRET! VOUS FERIEZ\n"\
|
||||
"MIEUX DE FONCER DANS CELUI-LA!\n"
|
||||
|
||||
//
|
||||
// Character cast strings F_FINALE.C
|
||||
//
|
||||
#define CC_ZOMBIE "ZOMBIE"
|
||||
#define CC_SHOTGUN "TYPE AU FUSIL"
|
||||
#define CC_HEAVY "MEC SUPER-ARME"
|
||||
#define CC_IMP "DIABLOTIN"
|
||||
#define CC_DEMON "DEMON"
|
||||
#define CC_LOST "AME PERDUE"
|
||||
#define CC_CACO "CACODEMON"
|
||||
#define CC_HELL "CHEVALIER DE L'ENFER"
|
||||
#define CC_BARON "BARON DE L'ENFER"
|
||||
#define CC_ARACH "ARACHNOTRON"
|
||||
#define CC_PAIN "ELEMENTAIRE DE LA DOULEUR"
|
||||
#define CC_REVEN "REVENANT"
|
||||
#define CC_MANCU "MANCUBUS"
|
||||
#define CC_ARCH "ARCHI-INFAME"
|
||||
#define CC_SPIDER "L'ARAIGNEE CERVEAU"
|
||||
#define CC_CYBER "LE CYBERDEMON"
|
||||
#define CC_HERO "NOTRE HEROS"
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
125
src/DOOM/d_items.c
Normal file
125
src/DOOM/d_items.c
Normal file
@ -0,0 +1,125 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "info.h" // We are referring to sprite numbers.
|
||||
#include "d_items.h"
|
||||
|
||||
|
||||
//
|
||||
// PSPRITE ACTIONS for waepons.
|
||||
// This struct controls the weapon animations.
|
||||
//
|
||||
// Each entry is:
|
||||
// ammo/amunition type
|
||||
// upstate
|
||||
// downstate
|
||||
// readystate
|
||||
// atkstate, i.e. attack/fire/hit frame
|
||||
// flashstate, muzzle flash
|
||||
//
|
||||
weaponinfo_t weaponinfo[NUMWEAPONS] =
|
||||
{
|
||||
{
|
||||
// fist
|
||||
am_noammo,
|
||||
S_PUNCHUP,
|
||||
S_PUNCHDOWN,
|
||||
S_PUNCH,
|
||||
S_PUNCH1,
|
||||
S_NULL
|
||||
},
|
||||
{
|
||||
// pistol
|
||||
am_clip,
|
||||
S_PISTOLUP,
|
||||
S_PISTOLDOWN,
|
||||
S_PISTOL,
|
||||
S_PISTOL1,
|
||||
S_PISTOLFLASH
|
||||
},
|
||||
{
|
||||
// shotgun
|
||||
am_shell,
|
||||
S_SGUNUP,
|
||||
S_SGUNDOWN,
|
||||
S_SGUN,
|
||||
S_SGUN1,
|
||||
S_SGUNFLASH1
|
||||
},
|
||||
{
|
||||
// chaingun
|
||||
am_clip,
|
||||
S_CHAINUP,
|
||||
S_CHAINDOWN,
|
||||
S_CHAIN,
|
||||
S_CHAIN1,
|
||||
S_CHAINFLASH1
|
||||
},
|
||||
{
|
||||
// missile launcher
|
||||
am_misl,
|
||||
S_MISSILEUP,
|
||||
S_MISSILEDOWN,
|
||||
S_MISSILE,
|
||||
S_MISSILE1,
|
||||
S_MISSILEFLASH1
|
||||
},
|
||||
{
|
||||
// plasma rifle
|
||||
am_cell,
|
||||
S_PLASMAUP,
|
||||
S_PLASMADOWN,
|
||||
S_PLASMA,
|
||||
S_PLASMA1,
|
||||
S_PLASMAFLASH1
|
||||
},
|
||||
{
|
||||
// bfg 9000
|
||||
am_cell,
|
||||
S_BFGUP,
|
||||
S_BFGDOWN,
|
||||
S_BFG,
|
||||
S_BFG1,
|
||||
S_BFGFLASH1
|
||||
},
|
||||
{
|
||||
// chainsaw
|
||||
am_noammo,
|
||||
S_SAWUP,
|
||||
S_SAWDOWN,
|
||||
S_SAW,
|
||||
S_SAW1,
|
||||
S_NULL
|
||||
},
|
||||
{
|
||||
// super shotgun
|
||||
am_shell,
|
||||
S_DSGUNUP,
|
||||
S_DSGUNDOWN,
|
||||
S_DSGUN,
|
||||
S_DSGUN1,
|
||||
S_DSGUNFLASH1
|
||||
},
|
||||
};
|
50
src/DOOM/d_items.h
Normal file
50
src/DOOM/d_items.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Items: key cards, artifacts, weapon, ammunition.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_ITEMS__
|
||||
#define __D_ITEMS__
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
|
||||
// Weapon info: sprite frames, ammunition use.
|
||||
typedef struct
|
||||
{
|
||||
ammotype_t ammo;
|
||||
int upstate;
|
||||
int downstate;
|
||||
int readystate;
|
||||
int atkstate;
|
||||
int flashstate;
|
||||
} weaponinfo_t;
|
||||
|
||||
|
||||
extern weaponinfo_t weaponinfo[NUMWEAPONS];
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
1258
src/DOOM/d_main.c
Normal file
1258
src/DOOM/d_main.c
Normal file
File diff suppressed because it is too large
Load Diff
59
src/DOOM/d_main.h
Normal file
59
src/DOOM/d_main.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_MAIN__
|
||||
#define __D_MAIN__
|
||||
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
#define MAXWADFILES 20
|
||||
|
||||
|
||||
extern char* wadfiles[MAXWADFILES];
|
||||
|
||||
|
||||
void D_AddFile(char* file);
|
||||
|
||||
//
|
||||
// D_DoomMain()
|
||||
// Not a globally visible function, just included for source reference,
|
||||
// calls all startup code, parses command line options.
|
||||
// If not overrided by user input, calls N_AdvanceDemo.
|
||||
//
|
||||
void D_DoomMain(void);
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent(event_t* ev);
|
||||
|
||||
//
|
||||
// BASE LEVEL
|
||||
//
|
||||
void D_PageTicker(void);
|
||||
void D_PageDrawer(void);
|
||||
void D_AdvanceDemo(void);
|
||||
void D_StartTitle(void);
|
||||
|
||||
|
||||
#endif
|
856
src/DOOM/d_net.c
Normal file
856
src/DOOM/d_net.c
Normal file
@ -0,0 +1,856 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM Network game communication and protocol,
|
||||
// all OS independend parts.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "m_menu.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "i_net.h"
|
||||
#include "g_game.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
//
|
||||
// gametic is the tic about to (or currently being) run
|
||||
// maketic is the tick that hasn't had control made for it yet
|
||||
// nettics[] has the maketics for all players
|
||||
//
|
||||
// a gametic cannot be run until nettics[] > gametic for all players
|
||||
//
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_KILL 0x10000000 // kill game
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
|
||||
doomcom_t* doomcom;
|
||||
doomdata_t* netbuffer; // points inside doomcom
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
doom_boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
doom_boolean remoteresend[MAXNETNODES]; // set when local needs tics
|
||||
int resendto[MAXNETNODES]; // set when remote needs tics
|
||||
int resendcount[MAXNETNODES];
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
int maketic;
|
||||
int lastnettic;
|
||||
int skiptics;
|
||||
int ticdup;
|
||||
int maxsend; // BACKUPTICS/(2*ticdup)-1
|
||||
|
||||
doom_boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
char exitmsg[80];
|
||||
int gametime;
|
||||
int frametics[4];
|
||||
int frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
|
||||
|
||||
extern int viewangleoffset;
|
||||
extern doom_boolean advancedemo;
|
||||
|
||||
|
||||
void D_ProcessEvents(void);
|
||||
void G_BuildTiccmd(ticcmd_t* cmd);
|
||||
void D_DoAdvanceDemo(void);
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
int NetbufferSize(void)
|
||||
{
|
||||
return (int)(long long)&(((doomdata_t*)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Checksum
|
||||
//
|
||||
unsigned NetbufferChecksum(void)
|
||||
{
|
||||
unsigned c;
|
||||
int i, l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
// FIXME -endianess?
|
||||
// #ifdef NORMALUNIX
|
||||
return 0; // byte order problems
|
||||
// #endif
|
||||
|
||||
l = (NetbufferSize() - (int)(long long)&(((doomdata_t*)0)->retransmitfrom)) / 4;
|
||||
for (i = 0; i < l; i++)
|
||||
c += ((unsigned*)&netbuffer->retransmitfrom)[i] * (i + 1);
|
||||
|
||||
return c & NCMD_CHECKSUM;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
int ExpandTics(int low)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = low - (maketic & 0xff);
|
||||
|
||||
if (delta >= -64 && delta <= 64)
|
||||
return (maketic & ~0xff) + low;
|
||||
if (delta > 64)
|
||||
return (maketic & ~0xff) - 256 + low;
|
||||
if (delta < -64)
|
||||
return (maketic & ~0xff) + 256 + low;
|
||||
|
||||
//I_Error("Error: ExpandTics: strange value %i at maketic %i", low, maketic);
|
||||
doom_strcpy(error_buf, "Error: ExpandTics: strange value ");
|
||||
doom_concat(error_buf, doom_itoa(low, 10));
|
||||
doom_concat(error_buf, " at maketic ");
|
||||
doom_concat(error_buf, doom_itoa(maketic, 10));
|
||||
I_Error(error_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HSendPacket
|
||||
//
|
||||
void HSendPacket(int node, int flags)
|
||||
{
|
||||
netbuffer->checksum = NetbufferChecksum() | flags;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
reboundstore = *netbuffer;
|
||||
reboundpacket = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
if (!netgame)
|
||||
I_Error("Error: Tried to transmit to another node");
|
||||
|
||||
doomcom->command = CMD_SEND;
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = NetbufferSize();
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int i;
|
||||
int realretrans;
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics(netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
|
||||
{
|
||||
//fprintf(debugfile, "send (%i + %i, R %i) [%i] ",
|
||||
// ExpandTics(netbuffer->starttic),
|
||||
// netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
doom_fprint(debugfile, "send (");
|
||||
doom_fprint(debugfile, doom_itoa(ExpandTics(netbuffer->starttic), 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ", R ");
|
||||
doom_fprint(debugfile, doom_itoa(realretrans, 10));
|
||||
doom_fprint(debugfile, ") [");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "] ");
|
||||
}
|
||||
|
||||
for (i = 0; i < doomcom->datalength; i++)
|
||||
{
|
||||
//fprintf(debugfile, "%i ", ((byte*)netbuffer)[i]);
|
||||
doom_fprint(debugfile, doom_itoa(((byte*)netbuffer)[i], 10));
|
||||
doom_fprint(debugfile, " ");
|
||||
}
|
||||
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
|
||||
I_NetCmd();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HGetPacket
|
||||
// Returns false if no packet is waiting
|
||||
//
|
||||
doom_boolean HGetPacket(void)
|
||||
{
|
||||
if (reboundpacket)
|
||||
{
|
||||
*netbuffer = reboundstore;
|
||||
doomcom->remotenode = 0;
|
||||
reboundpacket = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
return false;
|
||||
|
||||
if (demoplayback)
|
||||
return false;
|
||||
|
||||
doomcom->command = CMD_GET;
|
||||
I_NetCmd();
|
||||
|
||||
if (doomcom->remotenode == -1)
|
||||
return false;
|
||||
|
||||
if (doomcom->datalength != NetbufferSize())
|
||||
{
|
||||
if (debugfile)
|
||||
{
|
||||
//fprintf(debugfile, "bad packet length %i\n", doomcom->datalength);
|
||||
doom_fprint(debugfile, "bad packet length ");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum() != (netbuffer->checksum & NCMD_CHECKSUM))
|
||||
{
|
||||
if (debugfile)
|
||||
{
|
||||
doom_fprint(debugfile, "bad packet checksum\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
doom_fprint(debugfile, "setup packet\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics(netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
|
||||
{
|
||||
//fprintf(debugfile, "get %i = (%i + %i, R %i)[%i] ",
|
||||
// doomcom->remotenode,
|
||||
// ExpandTics(netbuffer->starttic),
|
||||
// netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
doom_fprint(debugfile, "get ");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->remotenode, 10));
|
||||
doom_fprint(debugfile, " = (");
|
||||
doom_fprint(debugfile, doom_itoa(ExpandTics(netbuffer->starttic), 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ", R ");
|
||||
doom_fprint(debugfile, doom_itoa(realretrans, 10));
|
||||
doom_fprint(debugfile, ")[");
|
||||
doom_fprint(debugfile, doom_itoa(doomcom->datalength, 10));
|
||||
doom_fprint(debugfile, "] ");
|
||||
}
|
||||
|
||||
for (i = 0; i < doomcom->datalength; i++)
|
||||
{
|
||||
//fprintf(debugfile, "%i ", ((byte*)netbuffer)[i]);
|
||||
doom_fprint(debugfile, doom_itoa(((byte*)netbuffer)[i], 10));
|
||||
doom_fprint(debugfile, " ");
|
||||
}
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPackets
|
||||
//
|
||||
void GetPackets(void)
|
||||
{
|
||||
int netconsole;
|
||||
int netnode;
|
||||
ticcmd_t* src, *dest;
|
||||
int realend;
|
||||
int realstart;
|
||||
|
||||
while (HGetPacket())
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
continue; // extra setup packet
|
||||
|
||||
netconsole = netbuffer->player & ~PL_DRONE;
|
||||
netnode = doomcom->remotenode;
|
||||
|
||||
// to save bytes, only the low byte of tic numbers are sent
|
||||
// Figure out what the rest of the bytes are
|
||||
realstart = ExpandTics(netbuffer->starttic);
|
||||
realend = (realstart + netbuffer->numtics);
|
||||
|
||||
// check for exiting the game
|
||||
if (netbuffer->checksum & NCMD_EXIT)
|
||||
{
|
||||
if (!nodeingame[netnode])
|
||||
continue;
|
||||
nodeingame[netnode] = false;
|
||||
playeringame[netconsole] = false;
|
||||
doom_strcpy(exitmsg, "Player 1 left the game");
|
||||
exitmsg[7] += netconsole;
|
||||
players[consoleplayer].message = exitmsg;
|
||||
if (demorecording)
|
||||
G_CheckDemoStatus();
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for a remote game kill
|
||||
if (netbuffer->checksum & NCMD_KILL)
|
||||
I_Error("Error: Killed by network driver");
|
||||
|
||||
nodeforplayer[netconsole] = netnode;
|
||||
|
||||
// check for retransmit request
|
||||
if (resendcount[netnode] <= 0
|
||||
&& (netbuffer->checksum & NCMD_RETRANSMIT))
|
||||
{
|
||||
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
|
||||
if (debugfile)
|
||||
{
|
||||
//fprintf(debugfile, "retransmit from %i\n", resendto[netnode]);
|
||||
doom_fprint(debugfile, "retransmit from ");
|
||||
doom_fprint(debugfile, doom_itoa(resendto[netnode], 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
resendcount[netnode] = RESENDCOUNT;
|
||||
}
|
||||
else
|
||||
resendcount[netnode]--;
|
||||
|
||||
// check for out of order / duplicated packet
|
||||
if (realend == nettics[netnode])
|
||||
continue;
|
||||
|
||||
if (realend < nettics[netnode])
|
||||
{
|
||||
if (debugfile)
|
||||
{
|
||||
//fprintf(debugfile,
|
||||
// "out of order packet (%i + %i)\n",
|
||||
// realstart, netbuffer->numtics);
|
||||
doom_fprint(debugfile, "out of order packet (");
|
||||
doom_fprint(debugfile, doom_itoa(realstart, 10));
|
||||
doom_fprint(debugfile, " + ");
|
||||
doom_fprint(debugfile, doom_itoa(netbuffer->numtics, 10));
|
||||
doom_fprint(debugfile, ")\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for a missed packet
|
||||
if (realstart > nettics[netnode])
|
||||
{
|
||||
// stop processing until the other system resends the missed tics
|
||||
if (debugfile)
|
||||
{
|
||||
//fprintf(debugfile,
|
||||
// "missed tics from %i (%i - %i)\n",
|
||||
// netnode, realstart, nettics[netnode]);
|
||||
doom_fprint(debugfile, "missed tics from ");
|
||||
doom_fprint(debugfile, doom_itoa(netnode, 10));
|
||||
doom_fprint(debugfile, " (");
|
||||
doom_fprint(debugfile, doom_itoa(realstart, 10));
|
||||
doom_fprint(debugfile, " - ");
|
||||
doom_fprint(debugfile, doom_itoa(nettics[netnode], 10));
|
||||
doom_fprint(debugfile, ")\n");
|
||||
}
|
||||
remoteresend[netnode] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// update command store from the packet
|
||||
{
|
||||
int start;
|
||||
|
||||
remoteresend[netnode] = false;
|
||||
|
||||
start = nettics[netnode] - realstart;
|
||||
src = &netbuffer->cmds[start];
|
||||
|
||||
while (nettics[netnode] < realend)
|
||||
{
|
||||
dest = &netcmds[netconsole][nettics[netnode] % BACKUPTICS];
|
||||
nettics[netnode]++;
|
||||
*dest = *src;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// NetUpdate
|
||||
// Builds ticcmds for console player,
|
||||
// sends out a packet
|
||||
//
|
||||
void NetUpdate(void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i, j;
|
||||
int realstart;
|
||||
int gameticdiv;
|
||||
|
||||
// check time
|
||||
nowtime = I_GetTime() / ticdup;
|
||||
newtics = nowtime - gametime;
|
||||
gametime = nowtime;
|
||||
|
||||
if (newtics <= 0) // nothing new to update
|
||||
goto listen;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
netbuffer->player = consoleplayer;
|
||||
|
||||
// build new ticcmds for console player
|
||||
gameticdiv = gametic / ticdup;
|
||||
for (i = 0; i < newtics; i++)
|
||||
{
|
||||
I_StartTic();
|
||||
D_ProcessEvents();
|
||||
if (maketic - gameticdiv >= BACKUPTICS / 2 - 1)
|
||||
break; // can't hold any more
|
||||
|
||||
//doom_print ("mk:%i ",maketic);
|
||||
G_BuildTiccmd(&localcmds[maketic % BACKUPTICS]);
|
||||
maketic++;
|
||||
}
|
||||
|
||||
|
||||
if (singletics)
|
||||
return; // singletic update is syncronous
|
||||
|
||||
// send the packet to the other nodes
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
netbuffer->starttic = realstart = resendto[i];
|
||||
netbuffer->numtics = maketic - realstart;
|
||||
if (netbuffer->numtics > BACKUPTICS)
|
||||
I_Error("Error: NetUpdate: netbuffer->numtics > BACKUPTICS");
|
||||
|
||||
resendto[i] = maketic - doomcom->extratics;
|
||||
|
||||
for (j = 0; j < netbuffer->numtics; j++)
|
||||
netbuffer->cmds[j] =
|
||||
localcmds[(realstart + j) % BACKUPTICS];
|
||||
|
||||
if (remoteresend[i])
|
||||
{
|
||||
netbuffer->retransmitfrom = nettics[i];
|
||||
HSendPacket(i, NCMD_RETRANSMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->retransmitfrom = 0;
|
||||
HSendPacket(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// listen for other packets
|
||||
listen:
|
||||
GetPackets();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CheckAbort
|
||||
//
|
||||
void CheckAbort(void)
|
||||
{
|
||||
event_t* ev;
|
||||
int stoptic;
|
||||
|
||||
stoptic = I_GetTime() + 2;
|
||||
while (I_GetTime() < stoptic)
|
||||
I_StartTic();
|
||||
|
||||
I_StartTic();
|
||||
for (; eventtail != eventhead
|
||||
; )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error("Error: Network game synchronization aborted.");
|
||||
}
|
||||
|
||||
eventtail++;
|
||||
eventtail = (eventtail) & (MAXEVENTS - 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_ArbitrateNetStart
|
||||
//
|
||||
void D_ArbitrateNetStart(void)
|
||||
{
|
||||
int i;
|
||||
doom_boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
doom_memset(gotinfo, 0, sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{
|
||||
// listen for setup info from key player
|
||||
doom_print("listening for network start info...\n");
|
||||
while (1)
|
||||
{
|
||||
CheckAbort();
|
||||
if (!HGetPacket())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error("Error: Different DOOM versions cannot play a net game!");
|
||||
startskill = netbuffer->retransmitfrom & 15;
|
||||
deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
|
||||
nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
|
||||
respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
|
||||
startmap = netbuffer->starttic & 0x3f;
|
||||
startepisode = netbuffer->starttic >> 6;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// key player, send the setup info
|
||||
doom_print("sending network start info...\n");
|
||||
do
|
||||
{
|
||||
CheckAbort();
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
{
|
||||
netbuffer->retransmitfrom = startskill;
|
||||
if (deathmatch)
|
||||
netbuffer->retransmitfrom |= (deathmatch << 6);
|
||||
if (nomonsters)
|
||||
netbuffer->retransmitfrom |= 0x20;
|
||||
if (respawnparm)
|
||||
netbuffer->retransmitfrom |= 0x10;
|
||||
netbuffer->starttic = startepisode * 64 + startmap;
|
||||
netbuffer->player = VERSION;
|
||||
netbuffer->numtics = 0;
|
||||
HSendPacket(i, NCMD_SETUP);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for (i = 10; i && HGetPacket(); --i)
|
||||
{
|
||||
if ((netbuffer->player & 0x7f) < MAXNETNODES)
|
||||
gotinfo[netbuffer->player & 0x7f] = true;
|
||||
}
|
||||
#else
|
||||
while (HGetPacket())
|
||||
{
|
||||
gotinfo[netbuffer->player & 0x7f] = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 1; i < doomcom->numnodes; i++)
|
||||
if (!gotinfo[i])
|
||||
break;
|
||||
} while (i < doomcom->numnodes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_CheckNetGame
|
||||
// Works out player numbers among the net participants
|
||||
//
|
||||
void D_CheckNetGame(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXNETNODES; i++)
|
||||
{
|
||||
nodeingame[i] = false;
|
||||
nettics[i] = 0;
|
||||
remoteresend[i] = false; // set when local needs tics
|
||||
resendto[i] = 0; // which tic to start sending
|
||||
}
|
||||
|
||||
// I_InitNetwork sets doomcom and netgame
|
||||
I_InitNetwork();
|
||||
if (doomcom->id != DOOMCOM_ID)
|
||||
I_Error("Error: Doomcom buffer invalid!");
|
||||
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart();
|
||||
|
||||
//doom_print("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
|
||||
// startskill, deathmatch, startmap, startepisode);
|
||||
doom_print("startskill ");
|
||||
doom_print(doom_itoa(startskill, 10));
|
||||
doom_print(" deathmatch: ");
|
||||
doom_print(doom_itoa(deathmatch, 10));
|
||||
doom_print(" startmap: ");
|
||||
doom_print(doom_itoa(startmap, 10));
|
||||
doom_print(" startepisode: ");
|
||||
doom_print(doom_itoa(startepisode, 10));
|
||||
doom_print("\n");
|
||||
|
||||
// read values out of doomcom
|
||||
ticdup = doomcom->ticdup;
|
||||
maxsend = BACKUPTICS / (2 * ticdup) - 1;
|
||||
if (maxsend < 1)
|
||||
maxsend = 1;
|
||||
|
||||
for (i = 0; i < doomcom->numplayers; i++)
|
||||
playeringame[i] = true;
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
//doom_print("player %i of %i (%i nodes)\n",
|
||||
// consoleplayer + 1, doomcom->numplayers, doomcom->numnodes);
|
||||
doom_print("player ");
|
||||
doom_print(doom_itoa(consoleplayer + 1, 10));
|
||||
doom_print(" of ");
|
||||
doom_print(doom_itoa(doomcom->numplayers, 10));
|
||||
doom_print(" (");
|
||||
doom_print(doom_itoa(doomcom->numnodes, 10));
|
||||
doom_print(" nodes)\n");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// D_QuitNetGame
|
||||
// Called before quitting to leave a net game
|
||||
// without hanging the other players
|
||||
//
|
||||
void D_QuitNetGame(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
doom_close(debugfile);
|
||||
|
||||
if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
|
||||
return;
|
||||
|
||||
// send a bunch of packets for security
|
||||
netbuffer->player = consoleplayer;
|
||||
netbuffer->numtics = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 1; j < doomcom->numnodes; j++)
|
||||
if (nodeingame[j])
|
||||
HSendPacket(j, NCMD_EXIT);
|
||||
I_WaitVBL(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// TryRunTics
|
||||
//
|
||||
void TryRunTics(void)
|
||||
{
|
||||
int i;
|
||||
int lowtic;
|
||||
int entertic;
|
||||
static int oldentertics;
|
||||
int realtics;
|
||||
int availabletics;
|
||||
int counts;
|
||||
int numplaying;
|
||||
|
||||
// get real tics
|
||||
entertic = I_GetTime() / ticdup;
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
// get available tics
|
||||
NetUpdate();
|
||||
|
||||
lowtic = DOOM_MAXINT;
|
||||
numplaying = 0;
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
{
|
||||
if (nodeingame[i])
|
||||
{
|
||||
numplaying++;
|
||||
if (nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
}
|
||||
}
|
||||
availabletics = lowtic - gametic / ticdup;
|
||||
|
||||
// decide how many tics to run
|
||||
if (realtics < availabletics - 1)
|
||||
counts = realtics + 1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
frameon++;
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
//fprintf(debugfile,
|
||||
// "=======real: %i avail: %i game: %i\n",
|
||||
// realtics, availabletics, counts);
|
||||
doom_fprint(debugfile, "=======real: ");
|
||||
doom_fprint(debugfile, doom_itoa(realtics, 10));
|
||||
doom_fprint(debugfile, " avail: ");
|
||||
doom_fprint(debugfile, doom_itoa(availabletics, 10));
|
||||
doom_fprint(debugfile, " game: ");
|
||||
doom_fprint(debugfile, doom_itoa(counts, 10));
|
||||
doom_fprint(debugfile, "\n");
|
||||
}
|
||||
|
||||
if (!demoplayback)
|
||||
{
|
||||
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
break;
|
||||
if (consoleplayer == i)
|
||||
{
|
||||
// the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nettics[0] <= nettics[nodeforplayer[i]])
|
||||
{
|
||||
gametime--;
|
||||
// doom_print ("-");
|
||||
}
|
||||
frameskip[frameon & 3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// doom_print ("+");
|
||||
}
|
||||
}
|
||||
}// demoplayback
|
||||
|
||||
// wait for new tics if needed
|
||||
while (lowtic < gametic / ticdup + counts)
|
||||
{
|
||||
NetUpdate();
|
||||
lowtic = DOOM_MAXINT;
|
||||
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic / ticdup)
|
||||
I_Error("Error: TryRunTics: lowtic < gametic");
|
||||
|
||||
// don't stay in here forever -- give the menu a chance to work
|
||||
if (I_GetTime() / ticdup - entertic >= 20)
|
||||
{
|
||||
M_Ticker();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run the count * ticdup dics
|
||||
while (counts--)
|
||||
{
|
||||
for (i = 0; i < ticdup; i++)
|
||||
{
|
||||
if (gametic / ticdup > lowtic)
|
||||
I_Error("Error: gametic>lowtic");
|
||||
if (advancedemo)
|
||||
D_DoAdvanceDemo();
|
||||
M_Ticker();
|
||||
G_Ticker();
|
||||
gametic++;
|
||||
|
||||
// modify command for duplicated tics
|
||||
if (i != ticdup - 1)
|
||||
{
|
||||
ticcmd_t* cmd;
|
||||
int buf;
|
||||
int j;
|
||||
|
||||
buf = (gametic / ticdup) % BACKUPTICS;
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
cmd = &netcmds[j][buf];
|
||||
cmd->chatchar = 0;
|
||||
if (cmd->buttons & BT_SPECIAL)
|
||||
cmd->buttons = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
NetUpdate(); // check for new console commands
|
||||
}
|
||||
}
|
137
src/DOOM/d_net.h
Normal file
137
src/DOOM/d_net.h
Normal file
@ -0,0 +1,137 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Networking stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_NET__
|
||||
#define __D_NET__
|
||||
|
||||
|
||||
#include "d_player.h"
|
||||
|
||||
|
||||
//
|
||||
// Network play related stuff.
|
||||
// There is a data struct that stores network
|
||||
// communication related stuff, and another
|
||||
// one that defines the actual packets to
|
||||
// be transmitted.
|
||||
//
|
||||
|
||||
#define DOOMCOM_ID 0x12345678l
|
||||
|
||||
// Max computers/players in a game.
|
||||
#define MAXNETNODES 8
|
||||
|
||||
// Networking and tick handling related.
|
||||
#define BACKUPTICS 12
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CMD_SEND = 1,
|
||||
CMD_GET = 2
|
||||
} command_t;
|
||||
|
||||
|
||||
//
|
||||
// Network packet data.
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
// High bit is retransmit request.
|
||||
unsigned checksum;
|
||||
// Only valid if NCMD_RETRANSMIT.
|
||||
byte retransmitfrom;
|
||||
|
||||
byte starttic;
|
||||
byte player;
|
||||
byte numtics;
|
||||
ticcmd_t cmds[BACKUPTICS];
|
||||
} doomdata_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Supposed to be DOOMCOM_ID?
|
||||
long id;
|
||||
|
||||
// DOOM executes an int to execute commands.
|
||||
short intnum;
|
||||
// Communication between DOOM and the driver.
|
||||
// Is CMD_SEND or CMD_GET.
|
||||
short command;
|
||||
// Is dest for send, set by get (-1 = no packet).
|
||||
short remotenode;
|
||||
|
||||
// Number of bytes in doomdata to be sent
|
||||
short datalength;
|
||||
|
||||
// Info common to all nodes.
|
||||
// Console is allways node 0.
|
||||
short numnodes;
|
||||
// Flag: 1 = no duplication, 2-5 = dup for slow nets.
|
||||
short ticdup;
|
||||
// Flag: 1 = send a backup tic in every packet.
|
||||
short extratics;
|
||||
// Flag: 1 = deathmatch.
|
||||
short deathmatch;
|
||||
// Flag: -1 = new game, 0-5 = load savegame
|
||||
short savegame;
|
||||
short episode; // 1-3
|
||||
short map; // 1-9
|
||||
short skill; // 1-5
|
||||
|
||||
// Info specific to this node.
|
||||
short consoleplayer;
|
||||
short numplayers;
|
||||
|
||||
// These are related to the 3-display mode,
|
||||
// in which two drones looking left and right
|
||||
// were used to render two additional views
|
||||
// on two additional computers.
|
||||
// Probably not operational anymore.
|
||||
// 1 = left, 0 = center, -1 = right
|
||||
short angleoffset;
|
||||
// 1 = drone
|
||||
short drone;
|
||||
|
||||
// The packet data to be sent.
|
||||
doomdata_t data;
|
||||
} doomcom_t;
|
||||
|
||||
|
||||
// Create any new ticcmds and broadcast to other players.
|
||||
void NetUpdate(void);
|
||||
|
||||
// Broadcasts special packets to other players
|
||||
// to notify of game exit
|
||||
void D_QuitNetGame(void);
|
||||
|
||||
//? how many ticks to run?
|
||||
void TryRunTics(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
209
src/DOOM/d_player.h
Normal file
209
src/DOOM/d_player.h
Normal file
@ -0,0 +1,209 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_PLAYER__
|
||||
#define __D_PLAYER__
|
||||
|
||||
|
||||
// The player data structure depends on a number
|
||||
// of other structs: items (internal inventory),
|
||||
// animation states (closely tied to the sprites
|
||||
// used to represent them, unfortunately).
|
||||
#include "d_items.h"
|
||||
#include "p_pspr.h"
|
||||
|
||||
// In addition, the player is just a special
|
||||
// case of the generic moving object/actor.
|
||||
#include "p_mobj.h"
|
||||
|
||||
// Finally, for odd reasons, the player input
|
||||
// is buffered within the player data struct,
|
||||
// as commands per game tick.
|
||||
#include "d_ticcmd.h"
|
||||
|
||||
|
||||
//
|
||||
// Player states.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Playing or camping.
|
||||
PST_LIVE,
|
||||
// Dead on the ground, view follows killer.
|
||||
PST_DEAD,
|
||||
// Ready to restart/respawn???
|
||||
PST_REBORN
|
||||
} playerstate_t;
|
||||
|
||||
|
||||
//
|
||||
// Player internal flags, for cheats and debug.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// No clipping, walk through barriers.
|
||||
CF_NOCLIP = 1,
|
||||
// No damage, no health loss.
|
||||
CF_GODMODE = 2,
|
||||
// Not really a cheat, just a debug aid.
|
||||
CF_NOMOMENTUM = 4
|
||||
} cheat_t;
|
||||
|
||||
|
||||
//
|
||||
// Extended player object info: player_t
|
||||
//
|
||||
typedef struct player_s
|
||||
{
|
||||
mobj_t* mo;
|
||||
playerstate_t playerstate;
|
||||
ticcmd_t cmd;
|
||||
|
||||
// Determine POV,
|
||||
// including viewpoint bobbing during movement.
|
||||
// Focal origin above r.z
|
||||
fixed_t viewz;
|
||||
// Base height above floor for viewz.
|
||||
fixed_t viewheight;
|
||||
// Bob/squat speed.
|
||||
fixed_t deltaviewheight;
|
||||
// bounded/scaled total momentum.
|
||||
fixed_t bob;
|
||||
|
||||
// This is only used between levels,
|
||||
// mo->health is used during levels.
|
||||
int health;
|
||||
int armorpoints;
|
||||
// Armor type is 0-2.
|
||||
int armortype;
|
||||
|
||||
// Power ups. invinc and invis are tic counters.
|
||||
int powers[NUMPOWERS];
|
||||
doom_boolean cards[NUMCARDS];
|
||||
doom_boolean backpack;
|
||||
|
||||
// Frags, kills of other players.
|
||||
int frags[MAXPLAYERS];
|
||||
weapontype_t readyweapon;
|
||||
|
||||
// Is wp_nochange if not changing.
|
||||
weapontype_t pendingweapon;
|
||||
|
||||
doom_boolean weaponowned[NUMWEAPONS];
|
||||
int ammo[NUMAMMO];
|
||||
int maxammo[NUMAMMO];
|
||||
|
||||
// True if button down last tic.
|
||||
int attackdown;
|
||||
int usedown;
|
||||
|
||||
// Bit flags, for cheats and debug.
|
||||
// See cheat_t, above.
|
||||
int cheats;
|
||||
|
||||
// Refired shots are less accurate.
|
||||
int refire;
|
||||
|
||||
// For intermission stats.
|
||||
int killcount;
|
||||
int itemcount;
|
||||
int secretcount;
|
||||
|
||||
// Hint messages.
|
||||
char* message;
|
||||
|
||||
// For screen flashing (red or bright).
|
||||
int damagecount;
|
||||
int bonuscount;
|
||||
|
||||
// Who did damage (0 for floors/ceilings).
|
||||
mobj_t* attacker;
|
||||
|
||||
// So gun flashes light up areas.
|
||||
int extralight;
|
||||
|
||||
// Current PLAYPAL, ???
|
||||
// can be set to REDCOLORMAP for pain, etc.
|
||||
int fixedcolormap;
|
||||
|
||||
// Player skin colorshift,
|
||||
// 0-3 for which color to draw player.
|
||||
int colormap;
|
||||
|
||||
// Overlay view sprites (gun, etc).
|
||||
pspdef_t psprites[NUMPSPRITES];
|
||||
|
||||
// True if secret level has been done.
|
||||
doom_boolean didsecret;
|
||||
} player_t;
|
||||
|
||||
|
||||
//
|
||||
// INTERMISSION
|
||||
// Structure passed e.g. to WI_Start(wb)
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
doom_boolean in; // whether the player is in game
|
||||
|
||||
// Player stats, kills, collected items etc.
|
||||
int skills;
|
||||
int sitems;
|
||||
int ssecret;
|
||||
int stime;
|
||||
int frags[4];
|
||||
int score; // current score on entry, modified on return
|
||||
} wbplayerstruct_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int epsd; // episode # (0-2)
|
||||
|
||||
// if true, splash the secret level
|
||||
doom_boolean didsecret;
|
||||
|
||||
// previous and next levels, origin 0
|
||||
int last;
|
||||
int next;
|
||||
|
||||
int maxkills;
|
||||
int maxitems;
|
||||
int maxsecret;
|
||||
int maxfrags;
|
||||
|
||||
// the par time
|
||||
int partime;
|
||||
|
||||
// index of this player in game
|
||||
int pnum;
|
||||
|
||||
wbplayerstruct_t plyr[MAXPLAYERS];
|
||||
} wbstartstruct_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
48
src/DOOM/d_textur.h
Normal file
48
src/DOOM/d_textur.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Typedefs related to to textures etc.,
|
||||
// isolated here to make it easier separating modules.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_TEXTUR__
|
||||
#define __D_TEXTUR__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
//
|
||||
// Flats?
|
||||
//
|
||||
// a pic is an unmasked block of pixels
|
||||
typedef struct
|
||||
{
|
||||
byte width;
|
||||
byte height;
|
||||
byte data;
|
||||
} pic_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
67
src/DOOM/d_think.h
Normal file
67
src/DOOM/d_think.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// MapObj data. Map Objects or mobjs are actors, entities,
|
||||
// thinker, take-your-pick... anything that moves, acts, or
|
||||
// suffers state changes of more or less violent nature.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_THINK__
|
||||
#define __D_THINK__
|
||||
|
||||
|
||||
//
|
||||
// Experimental stuff.
|
||||
// To compile this as "ANSI C with classes"
|
||||
// we will need to handle the various
|
||||
// action functions cleanly.
|
||||
//
|
||||
typedef void (*actionf_v)();
|
||||
typedef void (*actionf_p1)(void*);
|
||||
typedef void (*actionf_p2)(void*, void*);
|
||||
|
||||
typedef union
|
||||
{
|
||||
actionf_p1 acp1;
|
||||
actionf_v acv;
|
||||
actionf_p2 acp2;
|
||||
} actionf_t;
|
||||
|
||||
|
||||
// Historically, "think_t" is yet another
|
||||
// function pointer to a routine to handle
|
||||
// an actor.
|
||||
typedef actionf_t think_t;
|
||||
|
||||
|
||||
// Doubly linked list of actors.
|
||||
typedef struct thinker_s
|
||||
{
|
||||
struct thinker_s* prev;
|
||||
struct thinker_s* next;
|
||||
think_t function;
|
||||
} thinker_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
50
src/DOOM/d_ticcmd.h
Normal file
50
src/DOOM/d_ticcmd.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_TICCMD__
|
||||
#define __D_TICCMD__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
// The data sampled per tick (single player)
|
||||
// and transmitted to other peers (multiplayer).
|
||||
// Mainly movements/button commands per game tick,
|
||||
// plus a checksum for internal state consistency.
|
||||
typedef struct
|
||||
{
|
||||
char forwardmove; // *2048 for move
|
||||
char sidemove; // *2048 for move
|
||||
short angleturn; // <<16 for angle delta
|
||||
short consistancy; // checks for net game
|
||||
byte chatchar;
|
||||
byte buttons;
|
||||
} ticcmd_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
56
src/DOOM/doom_config.h
Normal file
56
src/DOOM/doom_config.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef __DOOM_CONFIG_H__
|
||||
#define __DOOM_CONFIG_H__
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
#define DOOM_WIN32
|
||||
#elif defined(__APPLE__)
|
||||
#define DOOM_APPLE
|
||||
#else
|
||||
#define DOOM_LINUX
|
||||
#endif
|
||||
|
||||
|
||||
#include "DOOM.h"
|
||||
|
||||
|
||||
#define doom_abs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
|
||||
extern char error_buf[260];
|
||||
extern int doom_flags;
|
||||
extern doom_print_fn doom_print;
|
||||
extern doom_malloc_fn doom_malloc;
|
||||
extern doom_free_fn doom_free;
|
||||
extern doom_open_fn doom_open;
|
||||
extern doom_close_fn doom_close;
|
||||
extern doom_read_fn doom_read;
|
||||
extern doom_write_fn doom_write;
|
||||
extern doom_seek_fn doom_seek;
|
||||
extern doom_tell_fn doom_tell;
|
||||
extern doom_eof_fn doom_eof;
|
||||
extern doom_gettime_fn doom_gettime;
|
||||
extern doom_exit_fn doom_exit;
|
||||
extern doom_getenv_fn doom_getenv;
|
||||
|
||||
|
||||
const char* doom_itoa(int i, int radix);
|
||||
const char* doom_ctoa(char c);
|
||||
const char* doom_ptoa(void* p);
|
||||
void doom_memset(void* ptr, int value, int num);
|
||||
void* doom_memcpy(void* destination, const void* source, int num);
|
||||
int doom_fprint(void* handle, const char* str);
|
||||
int doom_strlen(const char* str);
|
||||
char* doom_concat(char* dst, const char* src);
|
||||
char* doom_strcpy(char* destination, const char* source);
|
||||
char* doom_strncpy(char* destination, const char* source, int num);
|
||||
int doom_strcmp(const char* str1, const char* str2);
|
||||
int doom_strncmp(const char* str1, const char* str2, int n);
|
||||
int doom_strcasecmp(const char* str1, const char* str2);
|
||||
int doom_strncasecmp(const char* str1, const char* str2, int n);
|
||||
int doom_atoi(const char* str);
|
||||
int doom_atox(const char* str);
|
||||
int doom_toupper(int c);
|
||||
|
||||
|
||||
#endif
|
215
src/DOOM/doomdata.h
Normal file
215
src/DOOM/doomdata.h
Normal file
@ -0,0 +1,215 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// all external data is defined here
|
||||
// most of the data is loaded into different structures at run time
|
||||
// some internal structures shared by many modules are here
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DOOMDATA__
|
||||
#define __DOOMDATA__
|
||||
|
||||
|
||||
// The most basic types we use, portability.
|
||||
#include "doomtype.h"
|
||||
|
||||
// Some global defines, that configure the game.
|
||||
#include "doomdef.h"
|
||||
|
||||
|
||||
//
|
||||
// Map level types.
|
||||
// The following data structures define the persistent format
|
||||
// used in the lumps of the WAD files.
|
||||
//
|
||||
|
||||
// Lump order in a map WAD: each map needs a couple of lumps
|
||||
// to provide a complete scene geometry description.
|
||||
enum
|
||||
{
|
||||
ML_LABEL, // A separator, name, ExMx or MAPxx
|
||||
ML_THINGS, // Monsters, items..
|
||||
ML_LINEDEFS, // LineDefs, from editing
|
||||
ML_SIDEDEFS, // SideDefs, from editing
|
||||
ML_VERTEXES, // Vertices, edited and BSP splits generated
|
||||
ML_SEGS, // LineSegs, from LineDefs split by BSP
|
||||
ML_SSECTORS, // SubSectors, list of LineSegs
|
||||
ML_NODES, // BSP nodes
|
||||
ML_SECTORS, // Sectors, from editing
|
||||
ML_REJECT, // LUT, sector-sector visibility
|
||||
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
|
||||
};
|
||||
|
||||
|
||||
// A single Vertex.
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
} mapvertex_t;
|
||||
|
||||
|
||||
// A SideDef, defining the visual appearance of a wall,
|
||||
// by setting textures and offsets.
|
||||
typedef struct
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
// Front sector, towards viewer.
|
||||
short sector;
|
||||
} mapsidedef_t;
|
||||
|
||||
|
||||
// A LineDef, as used for editing, and as input
|
||||
// to the BSP builder.
|
||||
typedef struct
|
||||
{
|
||||
short v1;
|
||||
short v2;
|
||||
short flags;
|
||||
short special;
|
||||
short tag;
|
||||
// sidenum[1] will be -1 if one sided
|
||||
short sidenum[2];
|
||||
} maplinedef_t;
|
||||
|
||||
|
||||
//
|
||||
// LineDef attributes.
|
||||
//
|
||||
|
||||
// Solid, is an obstacle.
|
||||
#define ML_BLOCKING 1
|
||||
|
||||
// Blocks monsters only.
|
||||
#define ML_BLOCKMONSTERS 2
|
||||
|
||||
// Backside will not be present at all
|
||||
// if not two sided.
|
||||
#define ML_TWOSIDED 4
|
||||
|
||||
// If a texture is pegged, the texture will have
|
||||
// the end exposed to air held constant at the
|
||||
// top or bottom of the texture (stairs or pulled
|
||||
// down things) and will move with a height change
|
||||
// of one of the neighbor sectors.
|
||||
// Unpegged textures allways have the first row of
|
||||
// the texture at the top pixel of the line for both
|
||||
// top and bottom textures (use next to windows).
|
||||
|
||||
// upper texture unpegged
|
||||
#define ML_DONTPEGTOP 8
|
||||
|
||||
// lower texture unpegged
|
||||
#define ML_DONTPEGBOTTOM 16
|
||||
|
||||
// In AutoMap: don't map as two sided: IT'S A SECRET!
|
||||
#define ML_SECRET 32
|
||||
|
||||
// Sound rendering: don't let sound cross two of these.
|
||||
#define ML_SOUNDBLOCK 64
|
||||
|
||||
// Don't draw on the automap at all.
|
||||
#define ML_DONTDRAW 128
|
||||
|
||||
// Set if already seen, thus drawn in automap.
|
||||
#define ML_MAPPED 256
|
||||
|
||||
|
||||
// Sector definition, from editing.
|
||||
typedef struct
|
||||
{
|
||||
short floorheight;
|
||||
short ceilingheight;
|
||||
char floorpic[8];
|
||||
char ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special;
|
||||
short tag;
|
||||
} mapsector_t;
|
||||
|
||||
|
||||
// SubSector, as generated by BSP.
|
||||
typedef struct
|
||||
{
|
||||
short numsegs;
|
||||
// Index of first one, segs are stored sequentially.
|
||||
short firstseg;
|
||||
} mapsubsector_t;
|
||||
|
||||
|
||||
// LineSeg, generated by splitting LineDefs
|
||||
// using partition lines selected by BSP builder.
|
||||
typedef struct
|
||||
{
|
||||
short v1;
|
||||
short v2;
|
||||
short angle;
|
||||
short linedef;
|
||||
short side;
|
||||
short offset;
|
||||
} mapseg_t;
|
||||
|
||||
|
||||
//
|
||||
// BSP node structure.
|
||||
//
|
||||
|
||||
// Indicate a leaf.
|
||||
#define NF_SUBSECTOR 0x8000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Partition line from (x,y) to x+dx,y+dy)
|
||||
short x;
|
||||
short y;
|
||||
short dx;
|
||||
short dy;
|
||||
|
||||
// Bounding box for each child,
|
||||
// clip against view frustum.
|
||||
short bbox[2][4];
|
||||
|
||||
// If NF_SUBSECTOR its a subsector,
|
||||
// else it's a node of another subtree.
|
||||
unsigned short children[2];
|
||||
} mapnode_t;
|
||||
|
||||
|
||||
// Thing definition, position, orientation and type,
|
||||
// plus skill/visibility flags and attributes.
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
short angle;
|
||||
short type;
|
||||
short options;
|
||||
} mapthing_t;
|
||||
|
||||
|
||||
#endif // __DOOMDATA__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
27
src/DOOM/doomdef.c
Normal file
27
src/DOOM/doomdef.c
Normal file
@ -0,0 +1,27 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DoomDef - basic defines for DOOM, e.g. Version, game mode
|
||||
// and skill level, and display parameters.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
264
src/DOOM/doomdef.h
Normal file
264
src/DOOM/doomdef.h
Normal file
@ -0,0 +1,264 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Internally used data structures for virtually everything,
|
||||
// key definitions, lots of other stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DOOMDEF__
|
||||
#define __DOOMDEF__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Global parameters/defines.
|
||||
//
|
||||
// DOOM version
|
||||
enum
|
||||
{
|
||||
VERSION = 110
|
||||
};
|
||||
|
||||
|
||||
// Game mode handling - identify IWAD version
|
||||
// to handle IWAD dependend animations etc.
|
||||
typedef enum
|
||||
{
|
||||
shareware, // DOOM 1 shareware, E1, M9
|
||||
registered, // DOOM 1 registered, E3, M27
|
||||
commercial, // DOOM 2 retail, E1 M34
|
||||
// DOOM 2 german edition not handled
|
||||
retail, // DOOM 1 retail, E4, M36
|
||||
indetermined // Well, no IWAD found.
|
||||
} GameMode_t;
|
||||
|
||||
|
||||
// Mission packs - might be useful for TC stuff?
|
||||
typedef enum
|
||||
{
|
||||
doom, // DOOM 1
|
||||
doom2, // DOOM 2
|
||||
pack_tnt, // TNT mission pack
|
||||
pack_plut, // Plutonia pack
|
||||
none
|
||||
} GameMission_t;
|
||||
|
||||
|
||||
// Identify language to use, software localization.
|
||||
typedef enum
|
||||
{
|
||||
english,
|
||||
french,
|
||||
german,
|
||||
unknown
|
||||
} Language_t;
|
||||
|
||||
|
||||
// If rangecheck is undefined,
|
||||
// most parameter validation debugging code will not be compiled
|
||||
#define RANGECHECK
|
||||
|
||||
//
|
||||
// For resize of screen, at start of game.
|
||||
// It will not work dynamically, see visplanes.
|
||||
//
|
||||
#define BASE_WIDTH 320
|
||||
|
||||
// It is educational but futile to change this
|
||||
// scaling e.g. to 2. Drawing of status bar,
|
||||
// menues etc. is tied to the scale implied
|
||||
// by the graphics.
|
||||
#define SCREEN_MUL 1
|
||||
#define INV_ASPECT_RATIO 0.625 // 0.75, ideally
|
||||
|
||||
// Defines suck. C sucks.
|
||||
// C++ might sucks for OOP, but it sure is a better C.
|
||||
// So there.
|
||||
// extern int SCREENWIDTH;
|
||||
#define SCREENWIDTH 320
|
||||
#define SCREENHEIGHT 200
|
||||
|
||||
// The maximum number of players, multiplayer/networking.
|
||||
#define MAXPLAYERS 4
|
||||
|
||||
// State updates, number of tics / second.
|
||||
#if defined(DOOM_FAST_TICK)
|
||||
#define TICKMUL 2
|
||||
#else
|
||||
#define TICKMUL 1
|
||||
#endif
|
||||
#define TICRATE (35 * TICKMUL)
|
||||
|
||||
|
||||
// The current state of the game: whether we are
|
||||
// playing, gazing at the intermission screen,
|
||||
// the game final animation, or a demo.
|
||||
typedef enum
|
||||
{
|
||||
GS_LEVEL,
|
||||
GS_INTERMISSION,
|
||||
GS_FINALE,
|
||||
GS_DEMOSCREEN
|
||||
} gamestate_t;
|
||||
|
||||
|
||||
//
|
||||
// Difficulty/skill settings/filters.
|
||||
//
|
||||
|
||||
// Skill flags.
|
||||
#define MTF_EASY 1
|
||||
#define MTF_NORMAL 2
|
||||
#define MTF_HARD 4
|
||||
|
||||
// Deaf monsters/do not react to sound.
|
||||
#define MTF_AMBUSH 8
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sk_baby,
|
||||
sk_easy,
|
||||
sk_medium,
|
||||
sk_hard,
|
||||
sk_nightmare
|
||||
} skill_t;
|
||||
|
||||
|
||||
//
|
||||
// Key cards.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
it_bluecard,
|
||||
it_yellowcard,
|
||||
it_redcard,
|
||||
it_blueskull,
|
||||
it_yellowskull,
|
||||
it_redskull,
|
||||
NUMCARDS
|
||||
} card_t;
|
||||
|
||||
|
||||
// The defined weapons,
|
||||
// including a marker indicating
|
||||
// user has not changed weapon.
|
||||
typedef enum
|
||||
{
|
||||
wp_fist,
|
||||
wp_pistol,
|
||||
wp_shotgun,
|
||||
wp_chaingun,
|
||||
wp_missile,
|
||||
wp_plasma,
|
||||
wp_bfg,
|
||||
wp_chainsaw,
|
||||
wp_supershotgun,
|
||||
NUMWEAPONS,
|
||||
// No pending weapon change.
|
||||
wp_nochange
|
||||
} weapontype_t;
|
||||
|
||||
|
||||
// Ammunition types defined.
|
||||
typedef enum
|
||||
{
|
||||
am_clip, // Pistol / chaingun ammo.
|
||||
am_shell, // Shotgun / double barreled shotgun.
|
||||
am_cell, // Plasma rifle, BFG.
|
||||
am_misl, // Missile launcher.
|
||||
NUMAMMO,
|
||||
am_noammo // Unlimited for chainsaw / fist.
|
||||
} ammotype_t;
|
||||
|
||||
|
||||
// Power up artifacts.
|
||||
typedef enum
|
||||
{
|
||||
pw_invulnerability,
|
||||
pw_strength,
|
||||
pw_invisibility,
|
||||
pw_ironfeet,
|
||||
pw_allmap,
|
||||
pw_infrared,
|
||||
NUMPOWERS
|
||||
} powertype_t;
|
||||
|
||||
|
||||
//
|
||||
// Power up durations,
|
||||
// how many seconds till expiration,
|
||||
// assuming TICRATE is 35 ticks/second.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
INVULNTICS = (30 * TICRATE),
|
||||
INVISTICS = (60 * TICRATE),
|
||||
INFRATICS = (120 * TICRATE),
|
||||
IRONTICS = (60 * TICRATE)
|
||||
} powerduration_t;
|
||||
|
||||
|
||||
//
|
||||
// DOOM keyboard definition.
|
||||
// This is the stuff configured by Setup.Exe.
|
||||
// Most key data are simple ascii (uppercased).
|
||||
//
|
||||
#define KEY_RIGHTARROW 0xae
|
||||
#define KEY_LEFTARROW 0xac
|
||||
#define KEY_UPARROW 0xad
|
||||
#define KEY_DOWNARROW 0xaf
|
||||
#define KEY_ESCAPE 27
|
||||
#define KEY_ENTER 13
|
||||
#define KEY_TAB 9
|
||||
#define KEY_F1 (0x80+0x3b)
|
||||
#define KEY_F2 (0x80+0x3c)
|
||||
#define KEY_F3 (0x80+0x3d)
|
||||
#define KEY_F4 (0x80+0x3e)
|
||||
#define KEY_F5 (0x80+0x3f)
|
||||
#define KEY_F6 (0x80+0x40)
|
||||
#define KEY_F7 (0x80+0x41)
|
||||
#define KEY_F8 (0x80+0x42)
|
||||
#define KEY_F9 (0x80+0x43)
|
||||
#define KEY_F10 (0x80+0x44)
|
||||
#define KEY_F11 (0x80+0x57)
|
||||
#define KEY_F12 (0x80+0x58)
|
||||
|
||||
#define KEY_BACKSPACE 127
|
||||
#define KEY_PAUSE 0xff
|
||||
|
||||
#define KEY_EQUALS 0x3d
|
||||
#define KEY_MINUS 0x2d
|
||||
|
||||
#define KEY_RSHIFT (0x80+0x36)
|
||||
#define KEY_RCTRL (0x80+0x1d)
|
||||
#define KEY_RALT (0x80+0x38)
|
||||
|
||||
#define KEY_LALT KEY_RALT
|
||||
|
||||
|
||||
#endif // __DOOMDEF__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
37
src/DOOM/doomstat.c
Normal file
37
src/DOOM/doomstat.c
Normal file
@ -0,0 +1,37 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Put all global tate variables here.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
// Game Mode - identify IWAD as shareware, retail etc.
|
||||
GameMode_t gamemode = indetermined;
|
||||
GameMission_t gamemission = doom;
|
||||
|
||||
// Language.
|
||||
Language_t language = english;
|
||||
|
||||
// Set if homebrew PWAD stuff has been added.
|
||||
doom_boolean modifiedgame;
|
268
src/DOOM/doomstat.h
Normal file
268
src/DOOM/doomstat.h
Normal file
@ -0,0 +1,268 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// All the global variables that store the internal state.
|
||||
// Theoretically speaking, the internal state of the engine
|
||||
// should be found by looking at the variables collected
|
||||
// here, and every relevant module will have to include
|
||||
// this header file.
|
||||
// In practice, things are a bit messy.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __D_STATE__
|
||||
#define __D_STATE__
|
||||
|
||||
|
||||
// We need globally shared data structures,
|
||||
// for defining the global state variables.
|
||||
#include "doomdata.h"
|
||||
#include "d_net.h"
|
||||
|
||||
// We need the playr data structure as well.
|
||||
#include "d_player.h"
|
||||
|
||||
|
||||
// ------------------------
|
||||
// Command line parameters.
|
||||
//
|
||||
extern doom_boolean nomonsters; // checkparm of -nomonsters
|
||||
extern doom_boolean respawnparm; // checkparm of -respawn
|
||||
extern doom_boolean fastparm; // checkparm of -fast
|
||||
extern doom_boolean devparm; // DEBUG: launched with -devparm
|
||||
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Game Mode - identify IWAD as shareware, retail etc.
|
||||
//
|
||||
extern GameMode_t gamemode;
|
||||
extern GameMission_t gamemission;
|
||||
|
||||
// Set if homebrew PWAD stuff has been added.
|
||||
extern doom_boolean modifiedgame;
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
// Language.
|
||||
extern Language_t language;
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
// Selected skill type, map etc.
|
||||
//
|
||||
|
||||
// Defaults for menu, methinks.
|
||||
extern skill_t startskill;
|
||||
extern int startepisode;
|
||||
extern int startmap;
|
||||
|
||||
extern doom_boolean autostart;
|
||||
|
||||
// Selected by user.
|
||||
extern skill_t gameskill;
|
||||
extern int gameepisode;
|
||||
extern int gamemap;
|
||||
|
||||
// Nightmare mode flag, single player.
|
||||
extern doom_boolean respawnmonsters;
|
||||
|
||||
// Netgame? Only true if >1 player.
|
||||
extern doom_boolean netgame;
|
||||
|
||||
// Flag: true only if started as net deathmatch.
|
||||
// An enum might handle altdeath/cooperative better.
|
||||
extern doom_boolean deathmatch;
|
||||
|
||||
// -------------------------
|
||||
// Internal parameters for sound rendering.
|
||||
// These have been taken from the DOS version,
|
||||
// but are not (yet) supported with Linux
|
||||
// (e.g. no sound volume adjustment with menu.
|
||||
|
||||
// These are not used, but should be (menu).
|
||||
// From m_menu.c:
|
||||
// Sound FX volume has default, 0 - 15
|
||||
// Music volume has default, 0 - 15
|
||||
// These are multiplied by 8.
|
||||
extern int snd_SfxVolume; // maximum volume for sound
|
||||
extern int snd_MusicVolume; // maximum volume for music
|
||||
|
||||
// Current music/sfx card - index useless
|
||||
// w/o a reference LUT in a sound module.
|
||||
// Ideally, this would use indices found
|
||||
// in: /usr/include/linux/soundcard.h
|
||||
extern int snd_MusicDevice;
|
||||
extern int snd_SfxDevice;
|
||||
|
||||
// Config file? Same disclaimer as above.
|
||||
extern int snd_DesiredMusicDevice;
|
||||
extern int snd_DesiredSfxDevice;
|
||||
|
||||
|
||||
// -------------------------
|
||||
// Status flags for refresh.
|
||||
//
|
||||
|
||||
// Depending on view size - no status bar?
|
||||
// Note that there is no way to disable the
|
||||
// status bar explicitely.
|
||||
extern doom_boolean statusbaractive;
|
||||
|
||||
extern doom_boolean automapactive; // In AutoMap mode?
|
||||
extern doom_boolean menuactive; // Menu overlayed?
|
||||
extern doom_boolean paused; // Game Pause?
|
||||
|
||||
extern doom_boolean viewactive;
|
||||
|
||||
extern doom_boolean nodrawers;
|
||||
extern doom_boolean noblit;
|
||||
|
||||
extern int viewwindowx;
|
||||
extern int viewwindowy;
|
||||
extern int viewheight;
|
||||
extern int viewwidth;
|
||||
extern int scaledviewwidth;
|
||||
|
||||
|
||||
// This one is related to the 3-screen display mode.
|
||||
// ANG90 = left side, ANG270 = right
|
||||
extern int viewangleoffset;
|
||||
|
||||
// Player taking events, and displaying.
|
||||
extern int consoleplayer;
|
||||
extern int displayplayer;
|
||||
|
||||
|
||||
// -------------------------------------
|
||||
// Scores, rating.
|
||||
// Statistics on a given map, for intermission.
|
||||
//
|
||||
extern int totalkills;
|
||||
extern int totalitems;
|
||||
extern int totalsecret;
|
||||
|
||||
// Timer, for scores.
|
||||
extern int levelstarttic; // gametic at level start
|
||||
extern int leveltime; // tics in game play for par
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
// DEMO playback/recording related stuff.
|
||||
// No demo, there is a human player in charge?
|
||||
// Disable save/end game?
|
||||
extern doom_boolean usergame;
|
||||
|
||||
//?
|
||||
extern doom_boolean demoplayback;
|
||||
extern doom_boolean demorecording;
|
||||
|
||||
// Quit after playing a demo from cmdline.
|
||||
extern doom_boolean singledemo;
|
||||
|
||||
//?
|
||||
extern gamestate_t gamestate;
|
||||
|
||||
|
||||
//-----------------------------
|
||||
// Internal parameters, fixed.
|
||||
// These are set by the engine, and not changed
|
||||
// according to user inputs. Partly load from
|
||||
// WAD, partly set at startup time.
|
||||
|
||||
extern int gametic;
|
||||
|
||||
|
||||
// Bookkeeping on players - state.
|
||||
extern player_t players[MAXPLAYERS];
|
||||
|
||||
// Alive? Disconnected?
|
||||
extern doom_boolean playeringame[MAXPLAYERS];
|
||||
|
||||
|
||||
// Player spawn spots for deathmatch.
|
||||
#define MAX_DM_STARTS 10
|
||||
extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
|
||||
extern mapthing_t* deathmatch_p;
|
||||
|
||||
// Player spawn spots.
|
||||
extern mapthing_t playerstarts[MAXPLAYERS];
|
||||
|
||||
// Intermission stats.
|
||||
// Parameters for world map / intermission.
|
||||
extern wbstartstruct_t wminfo;
|
||||
|
||||
|
||||
// LUT of ammunition limits for each kind.
|
||||
// This doubles with BackPack powerup item.
|
||||
extern int maxammo[NUMAMMO];
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Internal parameters, used for engine.
|
||||
//
|
||||
|
||||
// File handling stuff.
|
||||
extern char basedefault[1024];
|
||||
extern void* debugfile;
|
||||
|
||||
// if true, load all graphics at level load
|
||||
extern doom_boolean precache;
|
||||
|
||||
// wipegamestate can be set to -1
|
||||
// to force a wipe on the next draw
|
||||
extern gamestate_t wipegamestate;
|
||||
|
||||
extern int mouseSensitivity;
|
||||
//?
|
||||
// debug flag to cancel adaptiveness
|
||||
extern doom_boolean singletics;
|
||||
|
||||
extern int bodyqueslot;
|
||||
|
||||
|
||||
// Needed to store the number of the dummy sky flat.
|
||||
// Used for rendering,
|
||||
// as well as tracking projectiles etc.
|
||||
extern int skyflatnum;
|
||||
|
||||
|
||||
// Netgame stuff (buffers and pointers, i.e. indices).
|
||||
|
||||
// This is ???
|
||||
extern doomcom_t* doomcom;
|
||||
|
||||
// This points inside doomcom.
|
||||
extern doomdata_t* netbuffer;
|
||||
|
||||
|
||||
extern ticcmd_t localcmds[BACKUPTICS];
|
||||
extern int rndindex;
|
||||
|
||||
extern int maketic;
|
||||
extern int nettics[MAXNETNODES];
|
||||
|
||||
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
extern int ticdup;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
65
src/DOOM/doomtype.h
Normal file
65
src/DOOM/doomtype.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Simple basic typedefs, isolated here to make it easier
|
||||
// separating modules.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DOOMTYPE__
|
||||
#define __DOOMTYPE__
|
||||
|
||||
|
||||
// Fixed to use builtin bool type with C++.
|
||||
#ifdef __cplusplus
|
||||
typedef bool doom_boolean;
|
||||
#else
|
||||
#if !defined(false) && !defined(true)
|
||||
typedef enum
|
||||
{
|
||||
false, true
|
||||
} doom_boolean;
|
||||
#else
|
||||
typedef int doom_boolean;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
|
||||
#define DOOM_MAXCHAR ((char)0x7f)
|
||||
#define DOOM_MAXSHORT ((short)0x7fff)
|
||||
|
||||
// Max pos 32-bit int.
|
||||
#define DOOM_MAXINT ((int)0x7fffffff)
|
||||
#define DOOM_MAXLONG ((long)0x7fffffff)
|
||||
#define DOOM_MINCHAR ((char)0x80)
|
||||
#define DOOM_MINSHORT ((short)0x8000)
|
||||
|
||||
// Max negative 32-bit integer.
|
||||
#define DOOM_MININT ((int)0x80000000)
|
||||
#define DOOM_MINLONG ((long)0x80000000)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
61
src/DOOM/dstrings.c
Normal file
61
src/DOOM/dstrings.c
Normal file
@ -0,0 +1,61 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Globally defined strings.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
#include "dstrings.h"
|
||||
|
||||
|
||||
char* endmsg[NUM_QUITMESSAGES + 1] =
|
||||
{
|
||||
// DOOM1
|
||||
QUITMSG,
|
||||
"please don't leave, there's more\ndemons to toast!",
|
||||
"let's beat it -- this is turning\ninto a bloodbath!",
|
||||
"i wouldn't leave if i were you.\ndos is much worse.",
|
||||
"you're trying to say you like dos\nbetter than me, right?",
|
||||
"don't leave yet -- there's a\ndemon around that corner!",
|
||||
"ya know, next time you come in here\ni'm gonna toast ya.",
|
||||
"go ahead and leave. see if i care.",
|
||||
|
||||
// QuitDOOM II messages
|
||||
"you want to quit?\nthen, thou hast lost an eighth!",
|
||||
"don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
|
||||
"get outta here and go back\nto your boring programs.",
|
||||
"if i were your boss, i'd \n deathmatch ya in a minute!",
|
||||
"look, bud. you leave now\nand you forfeit your body count!",
|
||||
"just leave. when you come\nback, i'll be waiting with a bat.",
|
||||
"you're lucky i don't smack\nyou for thinking about leaving.",
|
||||
|
||||
// FinalDOOM?
|
||||
"fuck you, pussy!\nget the fuck out!",
|
||||
"you quit and i'll jizz\nin your cystholes!",
|
||||
"if you leave, i'll make\nthe lord drink my jizz.",
|
||||
"hey, ron! can we say\n'fuck' in the game?",
|
||||
"i'd leave: this is just\nmore monsters and levels.\nwhat a load.",
|
||||
"suck it down, asshole!\nyou're a fucking wimp!",
|
||||
"don't quit now! we're \nstill spending your money!",
|
||||
|
||||
// Internal debug. Different style, too.
|
||||
"THIS IS NO MESSAGE!\nPage intentionally left blank."
|
||||
};
|
66
src/DOOM/dstrings.h
Normal file
66
src/DOOM/dstrings.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM strings, by language.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DSTRINGS__
|
||||
#define __DSTRINGS__
|
||||
|
||||
|
||||
// All important printed strings.
|
||||
// Language selection (message strings).
|
||||
// Use -DFRENCH etc.
|
||||
|
||||
#ifdef FRENCH
|
||||
#include "d_french.h" // Leave the extra space there, to throw off regex in PureDOOM.h creation
|
||||
#else
|
||||
#include "d_englsh.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Misc. other strings.
|
||||
#define SAVEGAMENAME "doomsav"
|
||||
|
||||
//
|
||||
// File locations,
|
||||
// relative to current position.
|
||||
// Path names are OS-sensitive.
|
||||
//
|
||||
#define DEVMAPS "devmaps"
|
||||
#define DEVDATA "devdata"
|
||||
|
||||
// Not done in french?
|
||||
|
||||
// QuitDOOM messages
|
||||
#define NUM_QUITMESSAGES 22
|
||||
|
||||
|
||||
extern char* endmsg[];
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
718
src/DOOM/f_finale.c
Normal file
718
src/DOOM/f_finale.c
Normal file
@ -0,0 +1,718 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Game completion, final screen animation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "i_system.h" // Functions.
|
||||
#include "m_swap.h" // Functions.
|
||||
#include "z_zone.h" // Functions.
|
||||
#include "v_video.h" // Functions.
|
||||
#include "w_wad.h" // Functions.
|
||||
#include "s_sound.h" // Functions.
|
||||
#include "dstrings.h" // Data.
|
||||
#include "sounds.h" // Data.
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
#include "hu_stuff.h"
|
||||
|
||||
|
||||
#define TEXTSPEED 3
|
||||
#define TEXTWAIT 250
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* name;
|
||||
mobjtype_t type;
|
||||
} castinfo_t;
|
||||
|
||||
|
||||
// Stage of animation:
|
||||
// 0 = text, 1 = art screen, 2 = character cast
|
||||
int finalestage;
|
||||
|
||||
int finalecount;
|
||||
|
||||
char* e1text = E1TEXT;
|
||||
char* e2text = E2TEXT;
|
||||
char* e3text = E3TEXT;
|
||||
char* e4text = E4TEXT;
|
||||
|
||||
char* c1text = C1TEXT;
|
||||
char* c2text = C2TEXT;
|
||||
char* c3text = C3TEXT;
|
||||
char* c4text = C4TEXT;
|
||||
char* c5text = C5TEXT;
|
||||
char* c6text = C6TEXT;
|
||||
|
||||
char* p1text = P1TEXT;
|
||||
char* p2text = P2TEXT;
|
||||
char* p3text = P3TEXT;
|
||||
char* p4text = P4TEXT;
|
||||
char* p5text = P5TEXT;
|
||||
char* p6text = P6TEXT;
|
||||
|
||||
char* t1text = T1TEXT;
|
||||
char* t2text = T2TEXT;
|
||||
char* t3text = T3TEXT;
|
||||
char* t4text = T4TEXT;
|
||||
char* t5text = T5TEXT;
|
||||
char* t6text = T6TEXT;
|
||||
|
||||
char* finaletext;
|
||||
char* finaleflat;
|
||||
|
||||
castinfo_t castorder[] = {
|
||||
{CC_ZOMBIE, MT_POSSESSED},
|
||||
{CC_SHOTGUN, MT_SHOTGUY},
|
||||
{CC_HEAVY, MT_CHAINGUY},
|
||||
{CC_IMP, MT_TROOP},
|
||||
{CC_DEMON, MT_SERGEANT},
|
||||
{CC_LOST, MT_SKULL},
|
||||
{CC_CACO, MT_HEAD},
|
||||
{CC_HELL, MT_KNIGHT},
|
||||
{CC_BARON, MT_BRUISER},
|
||||
{CC_ARACH, MT_BABY},
|
||||
{CC_PAIN, MT_PAIN},
|
||||
{CC_REVEN, MT_UNDEAD},
|
||||
{CC_MANCU, MT_FATSO},
|
||||
{CC_ARCH, MT_VILE},
|
||||
{CC_SPIDER, MT_SPIDER},
|
||||
{CC_CYBER, MT_CYBORG},
|
||||
{CC_HERO, MT_PLAYER},
|
||||
|
||||
{0,0}
|
||||
};
|
||||
|
||||
int castnum;
|
||||
int casttics;
|
||||
state_t* caststate;
|
||||
doom_boolean castdeath;
|
||||
int castframes;
|
||||
int castonmelee;
|
||||
doom_boolean castattacking;
|
||||
|
||||
|
||||
//
|
||||
// F_StartCast
|
||||
//
|
||||
extern gamestate_t wipegamestate;
|
||||
extern patch_t* hu_font[HU_FONTSIZE];
|
||||
|
||||
|
||||
void F_StartCast(void);
|
||||
void F_CastTicker(void);
|
||||
doom_boolean F_CastResponder(event_t* ev);
|
||||
void F_CastDrawer(void);
|
||||
void V_DrawPatchFlipped(int x, int y, int scrn, patch_t* patch);
|
||||
|
||||
|
||||
//
|
||||
// F_StartFinale
|
||||
//
|
||||
void F_StartFinale(void)
|
||||
{
|
||||
gameaction = ga_nothing;
|
||||
gamestate = GS_FINALE;
|
||||
viewactive = false;
|
||||
automapactive = false;
|
||||
|
||||
// Okay - IWAD dependend stuff.
|
||||
// This has been changed severly, and
|
||||
// some stuff might have changed in the process.
|
||||
switch (gamemode)
|
||||
{
|
||||
|
||||
// DOOM 1 - E1, E3 or E4, but each nine missions
|
||||
case shareware:
|
||||
case registered:
|
||||
case retail:
|
||||
{
|
||||
S_ChangeMusic(mus_victor, true);
|
||||
|
||||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
finaleflat = "FLOOR4_8";
|
||||
finaletext = e1text;
|
||||
break;
|
||||
case 2:
|
||||
finaleflat = "SFLR6_1";
|
||||
finaletext = e2text;
|
||||
break;
|
||||
case 3:
|
||||
finaleflat = "MFLR8_4";
|
||||
finaletext = e3text;
|
||||
break;
|
||||
case 4:
|
||||
finaleflat = "MFLR8_3";
|
||||
finaletext = e4text;
|
||||
break;
|
||||
default:
|
||||
// Ouch.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// DOOM II and missions packs with E1, M34
|
||||
case commercial:
|
||||
{
|
||||
S_ChangeMusic(mus_read_m, true);
|
||||
|
||||
switch (gamemap)
|
||||
{
|
||||
case 6:
|
||||
finaleflat = "SLIME16";
|
||||
finaletext = c1text;
|
||||
break;
|
||||
case 11:
|
||||
finaleflat = "RROCK14";
|
||||
finaletext = c2text;
|
||||
break;
|
||||
case 20:
|
||||
finaleflat = "RROCK07";
|
||||
finaletext = c3text;
|
||||
break;
|
||||
case 30:
|
||||
finaleflat = "RROCK17";
|
||||
finaletext = c4text;
|
||||
break;
|
||||
case 15:
|
||||
finaleflat = "RROCK13";
|
||||
finaletext = c5text;
|
||||
break;
|
||||
case 31:
|
||||
finaleflat = "RROCK19";
|
||||
finaletext = c6text;
|
||||
break;
|
||||
default:
|
||||
// Ouch.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Indeterminate.
|
||||
default:
|
||||
S_ChangeMusic(mus_read_m, true);
|
||||
finaleflat = "F_SKY1"; // Not used anywhere else.
|
||||
finaletext = c1text; // FIXME - other text, music?
|
||||
break;
|
||||
}
|
||||
|
||||
finalestage = 0;
|
||||
finalecount = 0;
|
||||
}
|
||||
|
||||
|
||||
doom_boolean F_Responder(event_t* event)
|
||||
{
|
||||
if (finalestage == 2)
|
||||
return F_CastResponder(event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_Ticker
|
||||
//
|
||||
void F_Ticker(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// check for skipping
|
||||
if ((gamemode == commercial)
|
||||
&& (finalecount > 50))
|
||||
{
|
||||
// go on to the next level
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (players[i].cmd.buttons)
|
||||
break;
|
||||
|
||||
if (i < MAXPLAYERS)
|
||||
{
|
||||
if (gamemap == 30)
|
||||
F_StartCast();
|
||||
else
|
||||
gameaction = ga_worlddone;
|
||||
}
|
||||
}
|
||||
|
||||
// advance animation
|
||||
finalecount++;
|
||||
|
||||
if (finalestage == 2)
|
||||
{
|
||||
F_CastTicker();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gamemode == commercial)
|
||||
return;
|
||||
|
||||
if (!finalestage && finalecount > doom_strlen(finaletext) * TEXTSPEED + TEXTWAIT)
|
||||
{
|
||||
finalecount = 0;
|
||||
finalestage = 1;
|
||||
wipegamestate = -1; // force a wipe
|
||||
if (gameepisode == 3)
|
||||
S_StartMusic(mus_bunny);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_TextWrite
|
||||
//
|
||||
void F_TextWrite(void)
|
||||
{
|
||||
byte* src;
|
||||
byte* dest;
|
||||
|
||||
int x, y, w;
|
||||
int count;
|
||||
char* ch;
|
||||
int c;
|
||||
int cx;
|
||||
int cy;
|
||||
|
||||
// erase the entire screen to a tiled background
|
||||
src = W_CacheLumpName(finaleflat, PU_CACHE);
|
||||
dest = screens[0];
|
||||
|
||||
for (y = 0; y < SCREENHEIGHT; y++)
|
||||
{
|
||||
for (x = 0; x < SCREENWIDTH / 64; x++)
|
||||
{
|
||||
doom_memcpy(dest, src + ((y & 63) << 6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH & 63)
|
||||
{
|
||||
doom_memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
|
||||
dest += (SCREENWIDTH & 63);
|
||||
}
|
||||
}
|
||||
|
||||
V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
// draw some of the text onto the screen
|
||||
cx = 10;
|
||||
cy = 10;
|
||||
ch = finaletext;
|
||||
|
||||
count = (finalecount - 10) / TEXTSPEED;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
for (; count; count--)
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
if (c == '\n')
|
||||
{
|
||||
cx = 10;
|
||||
cy += 11;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = doom_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
cx += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT(hu_font[c]->width);
|
||||
if (cx + w > SCREENWIDTH)
|
||||
break;
|
||||
V_DrawPatch(cx, cy, 0, hu_font[c]);
|
||||
cx += w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Final DOOM 2 animation
|
||||
// Casting by id Software.
|
||||
// in order of appearance
|
||||
//
|
||||
void F_StartCast(void)
|
||||
{
|
||||
wipegamestate = -1; // force a screen wipe
|
||||
castnum = 0;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
casttics = caststate->tics;
|
||||
castdeath = false;
|
||||
finalestage = 2;
|
||||
castframes = 0;
|
||||
castonmelee = 0;
|
||||
castattacking = false;
|
||||
S_ChangeMusic(mus_evil, true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastTicker
|
||||
//
|
||||
void F_CastTicker(void)
|
||||
{
|
||||
int st;
|
||||
int sfx;
|
||||
|
||||
if (--casttics > 0)
|
||||
return; // not time to change state yet
|
||||
|
||||
if (caststate->tics == -1 || caststate->nextstate == S_NULL)
|
||||
{
|
||||
// switch from deathstate to next monster
|
||||
castnum++;
|
||||
castdeath = false;
|
||||
if (castorder[castnum].name == 0)
|
||||
castnum = 0;
|
||||
if (mobjinfo[castorder[castnum].type].seesound)
|
||||
S_StartSound(0, mobjinfo[castorder[castnum].type].seesound);
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
castframes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just advance to next state in animation
|
||||
if (caststate == &states[S_PLAY_ATK1])
|
||||
goto stopattack; // Oh, gross hack!
|
||||
st = caststate->nextstate;
|
||||
caststate = &states[st];
|
||||
castframes++;
|
||||
|
||||
// sound hacks....
|
||||
switch (st)
|
||||
{
|
||||
case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
|
||||
case S_POSS_ATK2: sfx = sfx_pistol; break;
|
||||
case S_SPOS_ATK2: sfx = sfx_shotgn; break;
|
||||
case S_VILE_ATK2: sfx = sfx_vilatk; break;
|
||||
case S_SKEL_FIST2: sfx = sfx_skeswg; break;
|
||||
case S_SKEL_FIST4: sfx = sfx_skepch; break;
|
||||
case S_SKEL_MISS2: sfx = sfx_skeatk; break;
|
||||
case S_FATT_ATK8:
|
||||
case S_FATT_ATK5:
|
||||
case S_FATT_ATK2: sfx = sfx_firsht; break;
|
||||
case S_CPOS_ATK2:
|
||||
case S_CPOS_ATK3:
|
||||
case S_CPOS_ATK4: sfx = sfx_shotgn; break;
|
||||
case S_TROO_ATK3: sfx = sfx_claw; break;
|
||||
case S_SARG_ATK2: sfx = sfx_sgtatk; break;
|
||||
case S_BOSS_ATK2:
|
||||
case S_BOS2_ATK2:
|
||||
case S_HEAD_ATK2: sfx = sfx_firsht; break;
|
||||
case S_SKULL_ATK2: sfx = sfx_sklatk; break;
|
||||
case S_SPID_ATK2:
|
||||
case S_SPID_ATK3: sfx = sfx_shotgn; break;
|
||||
case S_BSPI_ATK2: sfx = sfx_plasma; break;
|
||||
case S_CYBER_ATK2:
|
||||
case S_CYBER_ATK4:
|
||||
case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
|
||||
case S_PAIN_ATK3: sfx = sfx_sklatk; break;
|
||||
default: sfx = 0; break;
|
||||
}
|
||||
|
||||
if (sfx)
|
||||
S_StartSound(0, sfx);
|
||||
}
|
||||
|
||||
if (castframes == 12)
|
||||
{
|
||||
// go into attack frame
|
||||
castattacking = true;
|
||||
if (castonmelee)
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].meleestate];
|
||||
else
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].missilestate];
|
||||
castonmelee ^= 1;
|
||||
if (caststate == &states[S_NULL])
|
||||
{
|
||||
if (castonmelee)
|
||||
caststate =
|
||||
&states[mobjinfo[castorder[castnum].type].meleestate];
|
||||
else
|
||||
caststate =
|
||||
&states[mobjinfo[castorder[castnum].type].missilestate];
|
||||
}
|
||||
}
|
||||
|
||||
if (castattacking)
|
||||
{
|
||||
if (castframes == 24
|
||||
|| caststate == &states[mobjinfo[castorder[castnum].type].seestate])
|
||||
{
|
||||
stopattack:
|
||||
castattacking = false;
|
||||
castframes = 0;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
|
||||
}
|
||||
}
|
||||
|
||||
casttics = caststate->tics;
|
||||
if (casttics == -1)
|
||||
casttics = 15;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastResponder
|
||||
//
|
||||
doom_boolean F_CastResponder(event_t* ev)
|
||||
{
|
||||
if (ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
if (castdeath)
|
||||
return true; // already in dying frames
|
||||
|
||||
// go into death frame
|
||||
castdeath = true;
|
||||
caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
|
||||
casttics = caststate->tics;
|
||||
castframes = 0;
|
||||
castattacking = false;
|
||||
if (mobjinfo[castorder[castnum].type].deathsound)
|
||||
S_StartSound(0, mobjinfo[castorder[castnum].type].deathsound);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void F_CastPrint(char* text)
|
||||
{
|
||||
char* ch;
|
||||
int c;
|
||||
int cx;
|
||||
int w;
|
||||
int width;
|
||||
|
||||
// find width
|
||||
ch = text;
|
||||
width = 0;
|
||||
|
||||
while (ch)
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
c = doom_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
width += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT(hu_font[c]->width);
|
||||
width += w;
|
||||
}
|
||||
|
||||
// draw it
|
||||
cx = 160 - width / 2;
|
||||
ch = text;
|
||||
while (ch)
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
c = doom_toupper(c) - HU_FONTSTART;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
cx += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT(hu_font[c]->width);
|
||||
V_DrawPatch(cx, 180, 0, hu_font[c]);
|
||||
cx += w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_CastDrawer
|
||||
//
|
||||
void F_CastDrawer(void)
|
||||
{
|
||||
spritedef_t* sprdef;
|
||||
spriteframe_t* sprframe;
|
||||
int lump;
|
||||
doom_boolean flip;
|
||||
patch_t* patch;
|
||||
|
||||
// erase the entire screen to a background
|
||||
V_DrawPatch(0, 0, 0, W_CacheLumpName("BOSSBACK", PU_CACHE));
|
||||
|
||||
F_CastPrint(castorder[castnum].name);
|
||||
|
||||
// draw the current frame in the middle of the screen
|
||||
sprdef = &sprites[caststate->sprite];
|
||||
sprframe = &sprdef->spriteframes[caststate->frame & FF_FRAMEMASK];
|
||||
lump = sprframe->lump[0];
|
||||
flip = (doom_boolean)sprframe->flip[0];
|
||||
|
||||
patch = W_CacheLumpNum(lump + firstspritelump, PU_CACHE);
|
||||
if (flip)
|
||||
V_DrawPatchFlipped(160, 170, 0, patch);
|
||||
else
|
||||
V_DrawPatch(160, 170, 0, patch);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_DrawPatchCol
|
||||
//
|
||||
void F_DrawPatchCol(int x, patch_t* patch, int col)
|
||||
{
|
||||
column_t* column;
|
||||
byte* source;
|
||||
byte* dest;
|
||||
byte* desttop;
|
||||
int count;
|
||||
|
||||
column = (column_t*)((byte*)patch + LONG(patch->columnofs[col]));
|
||||
desttop = screens[0] + x;
|
||||
|
||||
// step through the posts in a column
|
||||
while (column->topdelta != 0xff)
|
||||
{
|
||||
source = (byte*)column + 3;
|
||||
dest = desttop + column->topdelta * SCREENWIDTH;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = *source++;
|
||||
dest += SCREENWIDTH;
|
||||
}
|
||||
column = (column_t*)((byte*)column + column->length + 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_BunnyScroll
|
||||
//
|
||||
void F_BunnyScroll(void)
|
||||
{
|
||||
int scrolled;
|
||||
int x;
|
||||
patch_t* p1;
|
||||
patch_t* p2;
|
||||
char name[10];
|
||||
int stage;
|
||||
static int laststage;
|
||||
|
||||
p1 = W_CacheLumpName("PFUB2", PU_LEVEL);
|
||||
p2 = W_CacheLumpName("PFUB1", PU_LEVEL);
|
||||
|
||||
V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
scrolled = 320 - (finalecount - 230) / 2;
|
||||
if (scrolled > 320)
|
||||
scrolled = 320;
|
||||
if (scrolled < 0)
|
||||
scrolled = 0;
|
||||
|
||||
for (x = 0; x < SCREENWIDTH; x++)
|
||||
{
|
||||
if (x + scrolled < 320)
|
||||
F_DrawPatchCol(x, p1, x + scrolled);
|
||||
else
|
||||
F_DrawPatchCol(x, p2, x + scrolled - 320);
|
||||
}
|
||||
|
||||
if (finalecount < 1130)
|
||||
return;
|
||||
if (finalecount < 1180)
|
||||
{
|
||||
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
|
||||
(SCREENHEIGHT - 8 * 8) / 2, 0, W_CacheLumpName("END0", PU_CACHE));
|
||||
laststage = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
stage = (finalecount - 1180) / 5;
|
||||
if (stage > 6)
|
||||
stage = 6;
|
||||
if (stage > laststage)
|
||||
{
|
||||
S_StartSound(0, sfx_pistol);
|
||||
laststage = stage;
|
||||
}
|
||||
|
||||
//doom_sprintf(name, "END%i", stage);
|
||||
doom_strcpy(name, "END");
|
||||
doom_concat(name, doom_itoa(stage, 10));
|
||||
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, 0, W_CacheLumpName(name, PU_CACHE));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// F_Drawer
|
||||
//
|
||||
void F_Drawer(void)
|
||||
{
|
||||
if (finalestage == 2)
|
||||
{
|
||||
F_CastDrawer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!finalestage)
|
||||
F_TextWrite();
|
||||
else
|
||||
{
|
||||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
if (gamemode == retail)
|
||||
V_DrawPatch(0, 0, 0,
|
||||
W_CacheLumpName("CREDIT", PU_CACHE));
|
||||
else
|
||||
V_DrawPatch(0, 0, 0,
|
||||
W_CacheLumpName("HELP2", PU_CACHE));
|
||||
break;
|
||||
case 2:
|
||||
V_DrawPatch(0, 0, 0,
|
||||
W_CacheLumpName("VICTORY2", PU_CACHE));
|
||||
break;
|
||||
case 3:
|
||||
F_BunnyScroll();
|
||||
break;
|
||||
case 4:
|
||||
V_DrawPatch(0, 0, 0,
|
||||
W_CacheLumpName("ENDPIC", PU_CACHE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
52
src/DOOM/f_finale.h
Normal file
52
src/DOOM/f_finale.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __F_FINALE__
|
||||
#define __F_FINALE__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
//
|
||||
// FINALE
|
||||
//
|
||||
|
||||
// Called by main loop.
|
||||
doom_boolean F_Responder(event_t* ev);
|
||||
|
||||
// Called by main loop.
|
||||
void F_Ticker(void);
|
||||
|
||||
// Called by main loop.
|
||||
void F_Drawer(void);
|
||||
|
||||
void F_StartFinale(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
258
src/DOOM/f_wipe.c
Normal file
258
src/DOOM/f_wipe.c
Normal file
@ -0,0 +1,258 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Mission begin melt/wipe screen special effect.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "m_random.h"
|
||||
#include "doomdef.h"
|
||||
#include "f_wipe.h"
|
||||
|
||||
|
||||
//
|
||||
// SCREEN WIPE PACKAGE
|
||||
//
|
||||
|
||||
// when zero, stop the wipe
|
||||
static doom_boolean go = 0;
|
||||
|
||||
static byte* wipe_scr_start;
|
||||
static byte* wipe_scr_end;
|
||||
static byte* wipe_scr;
|
||||
|
||||
static int* y;
|
||||
|
||||
|
||||
void wipe_shittyColMajorXform(short* array, int width, int height)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
short* dest;
|
||||
|
||||
dest = (short*)Z_Malloc(width * height * sizeof(short), PU_STATIC, 0);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
dest[x * height + y] = array[y * width + x];
|
||||
|
||||
doom_memcpy(array, dest, width * height * 2);
|
||||
|
||||
Z_Free(dest);
|
||||
}
|
||||
|
||||
|
||||
int wipe_initColorXForm(int width, int height, int ticks)
|
||||
{
|
||||
doom_memcpy(wipe_scr, wipe_scr_start, width * height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_doColorXForm(int width, int height, int ticks)
|
||||
{
|
||||
doom_boolean changed;
|
||||
byte* w;
|
||||
byte* e;
|
||||
int newval;
|
||||
|
||||
changed = false;
|
||||
w = wipe_scr;
|
||||
e = wipe_scr_end;
|
||||
|
||||
while (w != wipe_scr + width * height)
|
||||
{
|
||||
if (*w != *e)
|
||||
{
|
||||
if (*w > *e)
|
||||
{
|
||||
newval = *w - ticks;
|
||||
if (newval < *e)
|
||||
*w = *e;
|
||||
else
|
||||
*w = newval;
|
||||
changed = true;
|
||||
}
|
||||
else if (*w < *e)
|
||||
{
|
||||
newval = *w + ticks;
|
||||
if (newval > *e)
|
||||
*w = *e;
|
||||
else
|
||||
*w = newval;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
w++;
|
||||
e++;
|
||||
}
|
||||
|
||||
return !changed;
|
||||
}
|
||||
|
||||
|
||||
int wipe_exitColorXForm(int width, int height, int ticks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_initMelt(int width, int height, int ticks)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
// copy start screen to main screen
|
||||
doom_memcpy(wipe_scr, wipe_scr_start, width * height);
|
||||
|
||||
// makes this wipe faster (in theory)
|
||||
// to have stuff in column-major format
|
||||
wipe_shittyColMajorXform((short*)wipe_scr_start, width / 2, height);
|
||||
wipe_shittyColMajorXform((short*)wipe_scr_end, width / 2, height);
|
||||
|
||||
// setup initial column positions
|
||||
// (y<0 => not ready to scroll yet)
|
||||
y = (int*)Z_Malloc(width * sizeof(int), PU_STATIC, 0);
|
||||
y[0] = -(M_Random() % 16);
|
||||
for (i = 1; i < width; i++)
|
||||
{
|
||||
r = (M_Random() % 3) - 1;
|
||||
y[i] = y[i - 1] + r;
|
||||
if (y[i] > 0) y[i] = 0;
|
||||
else if (y[i] == -16) y[i] = -15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_doMelt(int width, int height, int ticks)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int dy;
|
||||
int idx;
|
||||
|
||||
short* s;
|
||||
short* d;
|
||||
doom_boolean done = true;
|
||||
|
||||
width /= 2;
|
||||
|
||||
while (ticks--)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
{
|
||||
y[i]++; done = false;
|
||||
}
|
||||
else if (y[i] < height)
|
||||
{
|
||||
dy = (y[i] < 16) ? y[i] + 1 : 8;
|
||||
if (y[i] + dy >= height) dy = height - y[i];
|
||||
s = &((short*)wipe_scr_end)[i * height + y[i]];
|
||||
d = &((short*)wipe_scr)[y[i] * width + i];
|
||||
idx = 0;
|
||||
for (j = dy; j; j--)
|
||||
{
|
||||
d[idx] = *(s++);
|
||||
idx += width;
|
||||
}
|
||||
y[i] += dy;
|
||||
s = &((short*)wipe_scr_start)[i * height];
|
||||
d = &((short*)wipe_scr)[y[i] * width + i];
|
||||
idx = 0;
|
||||
for (j = height - y[i]; j; j--)
|
||||
{
|
||||
d[idx] = *(s++);
|
||||
idx += width;
|
||||
}
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
int wipe_exitMelt(int width, int height, int ticks)
|
||||
{
|
||||
Z_Free(y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_StartScreen(int x, int y, int width, int height)
|
||||
{
|
||||
wipe_scr_start = screens[2];
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_EndScreen(int x, int y, int width, int height)
|
||||
{
|
||||
wipe_scr_end = screens[3];
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
V_DrawBlock(x, y, 0, width, height, wipe_scr_start); // restore start scr.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wipe_ScreenWipe(int wipeno, int x, int y, int width, int height, int ticks)
|
||||
{
|
||||
int rc;
|
||||
static int (*wipes[])(int, int, int) =
|
||||
{
|
||||
wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm,
|
||||
wipe_initMelt, wipe_doMelt, wipe_exitMelt
|
||||
};
|
||||
|
||||
void V_MarkRect(int, int, int, int);
|
||||
|
||||
// initial stuff
|
||||
if (!go)
|
||||
{
|
||||
go = 1;
|
||||
// wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG
|
||||
wipe_scr = screens[0];
|
||||
(*wipes[wipeno * 3])(width, height, ticks);
|
||||
}
|
||||
|
||||
// do a piece of wipe-in
|
||||
V_MarkRect(0, 0, width, height);
|
||||
rc = (*wipes[wipeno * 3 + 1])(width, height, ticks);
|
||||
// V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG
|
||||
|
||||
// final stuff
|
||||
if (rc)
|
||||
{
|
||||
go = 0;
|
||||
(*wipes[wipeno * 3 + 2])(width, height, ticks);
|
||||
}
|
||||
|
||||
return !go;
|
||||
}
|
53
src/DOOM/f_wipe.h
Normal file
53
src/DOOM/f_wipe.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Mission start screen wipe/melt, special effects.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __F_WIPE_H__
|
||||
#define __F_WIPE_H__
|
||||
|
||||
|
||||
//
|
||||
// SCREEN WIPE PACKAGE
|
||||
//
|
||||
|
||||
enum
|
||||
{
|
||||
// simple gradual pixel change for 8-bit only
|
||||
wipe_ColorXForm,
|
||||
|
||||
// weird screen melt
|
||||
wipe_Melt,
|
||||
|
||||
wipe_NUMWIPES
|
||||
};
|
||||
|
||||
|
||||
int wipe_StartScreen(int x, int y, int width, int height);
|
||||
int wipe_EndScreen(int x, int y, int width, int height);
|
||||
int wipe_ScreenWipe(int wipeno, int x, int y, int width, int height, int ticks);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
1678
src/DOOM/g_game.c
Normal file
1678
src/DOOM/g_game.c
Normal file
File diff suppressed because it is too large
Load Diff
78
src/DOOM/g_game.h
Normal file
78
src/DOOM/g_game.h
Normal file
@ -0,0 +1,78 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Duh.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __G_GAME__
|
||||
#define __G_GAME__
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
//
|
||||
// GAME
|
||||
//
|
||||
void G_DeathMatchSpawnPlayer(int playernum);
|
||||
|
||||
void G_InitNew(skill_t skill, int episode, int map);
|
||||
|
||||
// Can be called by the startup code or M_Responder.
|
||||
// A normal game starts at map 1,
|
||||
// but a warp test can start elsewhere
|
||||
void G_DeferedInitNew(skill_t skill, int episode, int map);
|
||||
|
||||
void G_DeferedPlayDemo(char* demo);
|
||||
|
||||
// Can be called by the startup code or M_Responder,
|
||||
// calls P_SetupLevel or W_EnterWorld.
|
||||
void G_LoadGame(char* name);
|
||||
|
||||
void G_DoLoadGame(void);
|
||||
|
||||
// Called by M_Responder.
|
||||
void G_SaveGame(int slot, char* description);
|
||||
|
||||
// Only called by startup code.
|
||||
void G_RecordDemo(char* name);
|
||||
|
||||
void G_BeginRecording(void);
|
||||
|
||||
void G_TimeDemo(char* name);
|
||||
doom_boolean G_CheckDemoStatus(void);
|
||||
|
||||
void G_ExitLevel(void);
|
||||
void G_SecretExitLevel(void);
|
||||
|
||||
void G_WorldDone(void);
|
||||
|
||||
void G_Ticker(void);
|
||||
doom_boolean G_Responder(event_t* ev);
|
||||
|
||||
void G_ScreenShot(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
329
src/DOOM/hu_lib.c
Normal file
329
src/DOOM/hu_lib.c
Normal file
@ -0,0 +1,329 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION: heads-up text and input code
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "v_video.h"
|
||||
#include "m_swap.h"
|
||||
#include "hu_lib.h"
|
||||
#include "r_local.h"
|
||||
#include "r_draw.h"
|
||||
|
||||
|
||||
// doom_boolean : whether the screen is always erased
|
||||
#define noterased viewwindowx
|
||||
|
||||
|
||||
extern doom_boolean automapactive; // in AM_map.c
|
||||
|
||||
|
||||
void HUlib_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void HUlib_clearTextLine(hu_textline_t* t)
|
||||
{
|
||||
t->len = 0;
|
||||
t->l[0] = 0;
|
||||
t->needsupdate = true;
|
||||
}
|
||||
|
||||
|
||||
void HUlib_initTextLine(hu_textline_t* t, int x, int y, patch_t** f, int sc)
|
||||
{
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
t->f = f;
|
||||
t->sc = sc;
|
||||
HUlib_clearTextLine(t);
|
||||
}
|
||||
|
||||
|
||||
doom_boolean HUlib_addCharToTextLine(hu_textline_t* t, char ch)
|
||||
{
|
||||
if (t->len == HU_MAXLINELENGTH)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
t->l[t->len++] = ch;
|
||||
t->l[t->len] = 0;
|
||||
t->needsupdate = 4;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doom_boolean HUlib_delCharFromTextLine(hu_textline_t* t)
|
||||
{
|
||||
if (!t->len) return false;
|
||||
else
|
||||
{
|
||||
t->l[--t->len] = 0;
|
||||
t->needsupdate = 4;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HUlib_drawTextLine(hu_textline_t* l, doom_boolean drawcursor)
|
||||
{
|
||||
int i;
|
||||
int w;
|
||||
int x;
|
||||
unsigned char c;
|
||||
|
||||
// draw the new stuff
|
||||
x = l->x;
|
||||
for (i = 0; i < l->len; i++)
|
||||
{
|
||||
c = doom_toupper(l->l[i]);
|
||||
if (c != ' '
|
||||
&& c >= l->sc
|
||||
&& c <= '_')
|
||||
{
|
||||
w = SHORT(l->f[c - l->sc]->width);
|
||||
if (x + w > SCREENWIDTH)
|
||||
break;
|
||||
V_DrawPatchDirect(x, l->y, FG, l->f[c - l->sc]);
|
||||
x += w;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += 4;
|
||||
if (x >= SCREENWIDTH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the cursor if requested
|
||||
if (drawcursor
|
||||
&& x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH)
|
||||
{
|
||||
V_DrawPatchDirect(x, l->y, FG, l->f['_' - l->sc]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sorta called by HU_Erase and just better darn get things straight
|
||||
void HUlib_eraseTextLine(hu_textline_t* l)
|
||||
{
|
||||
int lh;
|
||||
int y;
|
||||
int yoffset;
|
||||
static doom_boolean lastautomapactive = true;
|
||||
|
||||
// Only erases when NOT in automap and the screen is reduced,
|
||||
// and the text must either need updating or refreshing
|
||||
// (because of a recent change back from the automap)
|
||||
|
||||
if (!automapactive &&
|
||||
viewwindowx && l->needsupdate)
|
||||
{
|
||||
lh = SHORT(l->f[0]->height) + 1;
|
||||
for (y = l->y, yoffset = y * SCREENWIDTH; y < l->y + lh; y++, yoffset += SCREENWIDTH)
|
||||
{
|
||||
if (y < viewwindowy || y >= viewwindowy + viewheight)
|
||||
R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
|
||||
else
|
||||
{
|
||||
R_VideoErase(yoffset, viewwindowx); // erase left border
|
||||
R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
|
||||
// erase right border
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastautomapactive = automapactive;
|
||||
if (l->needsupdate) l->needsupdate--;
|
||||
}
|
||||
|
||||
|
||||
void HUlib_initSText(hu_stext_t* s,
|
||||
int x,
|
||||
int y,
|
||||
int h,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
doom_boolean* on)
|
||||
{
|
||||
int i;
|
||||
|
||||
s->h = h;
|
||||
s->on = on;
|
||||
s->laston = true;
|
||||
s->cl = 0;
|
||||
for (i = 0; i < h; i++)
|
||||
HUlib_initTextLine(&s->l[i],
|
||||
x, y - i * (SHORT(font[0]->height) + 1),
|
||||
font, startchar);
|
||||
}
|
||||
|
||||
|
||||
void HUlib_addLineToSText(hu_stext_t* s)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// add a clear line
|
||||
if (++s->cl == s->h)
|
||||
s->cl = 0;
|
||||
HUlib_clearTextLine(&s->l[s->cl]);
|
||||
|
||||
// everything needs updating
|
||||
for (i = 0; i < s->h; i++)
|
||||
s->l[i].needsupdate = 4;
|
||||
}
|
||||
|
||||
|
||||
void HUlib_addMessageToSText(hu_stext_t* s, char* prefix, char* msg)
|
||||
{
|
||||
HUlib_addLineToSText(s);
|
||||
if (prefix)
|
||||
while (*prefix)
|
||||
HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
|
||||
|
||||
while (*msg)
|
||||
HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
|
||||
}
|
||||
|
||||
|
||||
void HUlib_drawSText(hu_stext_t* s)
|
||||
{
|
||||
int i, idx;
|
||||
hu_textline_t* l;
|
||||
|
||||
if (!*s->on)
|
||||
return; // if not on, don't draw
|
||||
|
||||
// draw everything
|
||||
for (i = 0; i < s->h; i++)
|
||||
{
|
||||
idx = s->cl - i;
|
||||
if (idx < 0)
|
||||
idx += s->h; // handle queue of lines
|
||||
|
||||
l = &s->l[idx];
|
||||
|
||||
// need a decision made here on whether to skip the draw
|
||||
HUlib_drawTextLine(l, false); // no cursor, please
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HUlib_eraseSText(hu_stext_t* s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->h; i++)
|
||||
{
|
||||
if (s->laston && !*s->on)
|
||||
s->l[i].needsupdate = 4;
|
||||
HUlib_eraseTextLine(&s->l[i]);
|
||||
}
|
||||
s->laston = *s->on;
|
||||
}
|
||||
|
||||
|
||||
void HUlib_initIText(hu_itext_t* it,
|
||||
int x,
|
||||
int y,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
doom_boolean* on)
|
||||
{
|
||||
it->lm = 0; // default left margin is start of text
|
||||
it->on = on;
|
||||
it->laston = true;
|
||||
HUlib_initTextLine(&it->l, x, y, font, startchar);
|
||||
}
|
||||
|
||||
|
||||
// The following deletion routines adhere to the left margin restriction
|
||||
void HUlib_delCharFromIText(hu_itext_t* it)
|
||||
{
|
||||
if (it->l.len != it->lm)
|
||||
HUlib_delCharFromTextLine(&it->l);
|
||||
}
|
||||
|
||||
|
||||
void HUlib_eraseLineFromIText(hu_itext_t* it)
|
||||
{
|
||||
while (it->lm != it->l.len)
|
||||
HUlib_delCharFromTextLine(&it->l);
|
||||
}
|
||||
|
||||
|
||||
// Resets left margin as well
|
||||
void HUlib_resetIText(hu_itext_t* it)
|
||||
{
|
||||
it->lm = 0;
|
||||
HUlib_clearTextLine(&it->l);
|
||||
}
|
||||
|
||||
|
||||
void HUlib_addPrefixToIText(hu_itext_t* it, char* str)
|
||||
{
|
||||
while (*str)
|
||||
HUlib_addCharToTextLine(&it->l, *(str++));
|
||||
it->lm = it->l.len;
|
||||
}
|
||||
|
||||
|
||||
// wrapper function for handling general keyed input.
|
||||
// returns true if it ate the key
|
||||
doom_boolean HUlib_keyInIText(hu_itext_t* it, unsigned char ch)
|
||||
{
|
||||
if (ch >= ' ' && ch <= '_')
|
||||
HUlib_addCharToTextLine(&it->l, (char)ch);
|
||||
else
|
||||
if (ch == KEY_BACKSPACE)
|
||||
HUlib_delCharFromIText(it);
|
||||
else
|
||||
if (ch != KEY_ENTER)
|
||||
return false; // did not eat key
|
||||
|
||||
return true; // ate the key
|
||||
}
|
||||
|
||||
|
||||
void HUlib_drawIText(hu_itext_t* it)
|
||||
{
|
||||
hu_textline_t* l = &it->l;
|
||||
|
||||
if (!*it->on)
|
||||
return;
|
||||
HUlib_drawTextLine(l, true); // draw the line w/ cursor
|
||||
}
|
||||
|
||||
|
||||
void HUlib_eraseIText(hu_itext_t* it)
|
||||
{
|
||||
if (it->laston && !*it->on)
|
||||
it->l.needsupdate = 4;
|
||||
HUlib_eraseTextLine(&it->l);
|
||||
it->laston = *it->on;
|
||||
}
|
181
src/DOOM/hu_lib.h
Normal file
181
src/DOOM/hu_lib.h
Normal file
@ -0,0 +1,181 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION: none
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __HULIB__
|
||||
#define __HULIB__
|
||||
|
||||
|
||||
// We are referring to patches.
|
||||
#include "r_defs.h"
|
||||
|
||||
|
||||
// background and foreground screen numbers
|
||||
// different from other modules.
|
||||
#define BG 1
|
||||
#define FG 0
|
||||
|
||||
// font stuff
|
||||
#define HU_CHARERASE KEY_BACKSPACE
|
||||
|
||||
#define HU_MAXLINES 4
|
||||
#define HU_MAXLINELENGTH 80
|
||||
|
||||
|
||||
//
|
||||
// Typedefs of widgets
|
||||
//
|
||||
|
||||
// Text Line widget
|
||||
// (parent of Scrolling Text and Input Text widgets)
|
||||
typedef struct
|
||||
{
|
||||
// left-justified position of scrolling text window
|
||||
int x;
|
||||
int y;
|
||||
|
||||
patch_t** f; // font
|
||||
int sc; // start character
|
||||
char l[HU_MAXLINELENGTH + 1]; // line of text
|
||||
int len; // current line length
|
||||
|
||||
// whether this line needs to be udpated
|
||||
int needsupdate;
|
||||
} hu_textline_t;
|
||||
|
||||
|
||||
// Scrolling Text window widget
|
||||
// (child of Text Line widget)
|
||||
typedef struct
|
||||
{
|
||||
hu_textline_t l[HU_MAXLINES]; // text lines to draw
|
||||
int h; // height in lines
|
||||
int cl; // current line number
|
||||
|
||||
// pointer to doom_boolean stating whether to update window
|
||||
doom_boolean* on;
|
||||
doom_boolean laston; // last value of *->on.
|
||||
} hu_stext_t;
|
||||
|
||||
|
||||
// Input Text Line widget
|
||||
// (child of Text Line widget)
|
||||
typedef struct
|
||||
{
|
||||
hu_textline_t l; // text line to input on
|
||||
|
||||
// left margin past which I am not to delete characters
|
||||
int lm;
|
||||
|
||||
// pointer to doom_boolean stating whether to update window
|
||||
doom_boolean* on;
|
||||
doom_boolean laston; // last value of *->on;
|
||||
} hu_itext_t;
|
||||
|
||||
|
||||
//
|
||||
// Widget creation, access, and update routines
|
||||
//
|
||||
|
||||
// initializes heads-up widget library
|
||||
void HUlib_init(void);
|
||||
|
||||
//
|
||||
// textline code
|
||||
//
|
||||
|
||||
// clear a line of text
|
||||
void HUlib_clearTextLine(hu_textline_t* t);
|
||||
|
||||
void HUlib_initTextLine(hu_textline_t* t, int x, int y, patch_t** f, int sc);
|
||||
|
||||
// returns success
|
||||
doom_boolean HUlib_addCharToTextLine(hu_textline_t* t, char ch);
|
||||
|
||||
// returns success
|
||||
doom_boolean HUlib_delCharFromTextLine(hu_textline_t* t);
|
||||
|
||||
// draws tline
|
||||
void HUlib_drawTextLine(hu_textline_t* l, doom_boolean drawcursor);
|
||||
|
||||
// erases text line
|
||||
void HUlib_eraseTextLine(hu_textline_t* l);
|
||||
|
||||
|
||||
//
|
||||
// Scrolling Text window widget routines
|
||||
//
|
||||
|
||||
// ?
|
||||
void HUlib_initSText(hu_stext_t* s,
|
||||
int x,
|
||||
int y,
|
||||
int h,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
doom_boolean* on);
|
||||
|
||||
// add a new line
|
||||
void HUlib_addLineToSText(hu_stext_t* s);
|
||||
|
||||
// ?
|
||||
void HUlib_addMessageToSText(hu_stext_t* s, char* prefix, char* msg);
|
||||
|
||||
// draws stext
|
||||
void HUlib_drawSText(hu_stext_t* s);
|
||||
|
||||
// erases all stext lines
|
||||
void HUlib_eraseSText(hu_stext_t* s);
|
||||
|
||||
// Input Text Line widget routines
|
||||
void HUlib_initIText(hu_itext_t* it,
|
||||
int x,
|
||||
int y,
|
||||
patch_t** font,
|
||||
int startchar,
|
||||
doom_boolean* on);
|
||||
|
||||
// enforces left margin
|
||||
void HUlib_delCharFromIText(hu_itext_t* it);
|
||||
|
||||
// enforces left margin
|
||||
void HUlib_eraseLineFromIText(hu_itext_t* it);
|
||||
|
||||
// resets line and left margin
|
||||
void HUlib_resetIText(hu_itext_t* it);
|
||||
|
||||
// left of left-margin
|
||||
void HUlib_addPrefixToIText(hu_itext_t* it, char* str);
|
||||
|
||||
// whether eaten
|
||||
doom_boolean HUlib_keyInIText(hu_itext_t* it, unsigned char ch);
|
||||
|
||||
void HUlib_drawIText(hu_itext_t* it);
|
||||
|
||||
// erases all itext lines
|
||||
void HUlib_eraseIText(hu_itext_t* it);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
733
src/DOOM/hu_stuff.c
Normal file
733
src/DOOM/hu_stuff.c
Normal file
@ -0,0 +1,733 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION: Heads-up displays
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_swap.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "hu_lib.h"
|
||||
#include "w_wad.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h"
|
||||
#include "dstrings.h" // Data.
|
||||
#include "sounds.h"
|
||||
|
||||
|
||||
//
|
||||
// Locally used constants, shortcuts.
|
||||
//
|
||||
#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
|
||||
#define HU_TITLE2 (mapnames2[gamemap-1])
|
||||
#define HU_TITLEP (mapnamesp[gamemap-1])
|
||||
#define HU_TITLET (mapnamest[gamemap-1])
|
||||
#define HU_TITLEHEIGHT 1
|
||||
#define HU_TITLEX 0
|
||||
#define HU_TITLEY (167 - SHORT(hu_font[0]->height))
|
||||
#define HU_INPUTTOGGLE 't'
|
||||
#define HU_INPUTX HU_MSGX
|
||||
#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1))
|
||||
#define HU_INPUTWIDTH 64
|
||||
#define HU_INPUTHEIGHT 1
|
||||
#define QUEUESIZE 128
|
||||
|
||||
|
||||
static player_t* plr;
|
||||
static hu_textline_t w_title;
|
||||
static hu_itext_t w_chat;
|
||||
static doom_boolean always_off = false;
|
||||
static char chat_dest[MAXPLAYERS];
|
||||
static hu_itext_t w_inputbuffer[MAXPLAYERS];
|
||||
static doom_boolean message_on;
|
||||
static doom_boolean message_nottobefuckedwith;
|
||||
static hu_stext_t w_message;
|
||||
static int message_counter;
|
||||
static doom_boolean headsupactive = false;
|
||||
static char chatchars[QUEUESIZE];
|
||||
static int head = 0;
|
||||
static int tail = 0;
|
||||
|
||||
char* chat_macros[] =
|
||||
{
|
||||
HUSTR_CHATMACRO0,
|
||||
HUSTR_CHATMACRO1,
|
||||
HUSTR_CHATMACRO2,
|
||||
HUSTR_CHATMACRO3,
|
||||
HUSTR_CHATMACRO4,
|
||||
HUSTR_CHATMACRO5,
|
||||
HUSTR_CHATMACRO6,
|
||||
HUSTR_CHATMACRO7,
|
||||
HUSTR_CHATMACRO8,
|
||||
HUSTR_CHATMACRO9
|
||||
};
|
||||
|
||||
char* player_names[] =
|
||||
{
|
||||
HUSTR_PLRGREEN,
|
||||
HUSTR_PLRINDIGO,
|
||||
HUSTR_PLRBROWN,
|
||||
HUSTR_PLRRED
|
||||
};
|
||||
|
||||
const char* shiftxform;
|
||||
|
||||
const char french_shiftxform[] =
|
||||
{
|
||||
0,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31,
|
||||
' ', '!', '"', '#', '$', '%', '&',
|
||||
'"', // shift-'
|
||||
'(', ')', '*', '+',
|
||||
'?', // shift-,
|
||||
'_', // shift--
|
||||
'>', // shift-.
|
||||
'?', // shift-/
|
||||
'0', // shift-0
|
||||
'1', // shift-1
|
||||
'2', // shift-2
|
||||
'3', // shift-3
|
||||
'4', // shift-4
|
||||
'5', // shift-5
|
||||
'6', // shift-6
|
||||
'7', // shift-7
|
||||
'8', // shift-8
|
||||
'9', // shift-9
|
||||
'/',
|
||||
'.', // shift-;
|
||||
'<',
|
||||
'+', // shift-=
|
||||
'>', '?', '@',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'[', // shift-[
|
||||
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
|
||||
']', // shift-]
|
||||
'"', '_',
|
||||
'\'', // shift-`
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'{', '|', '}', '~', 127
|
||||
|
||||
};
|
||||
|
||||
const char english_shiftxform[] =
|
||||
{
|
||||
0,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31,
|
||||
' ', '!', '"', '#', '$', '%', '&',
|
||||
'"', // shift-'
|
||||
'(', ')', '*', '+',
|
||||
'<', // shift-,
|
||||
'_', // shift--
|
||||
'>', // shift-.
|
||||
'?', // shift-/
|
||||
')', // shift-0
|
||||
'!', // shift-1
|
||||
'@', // shift-2
|
||||
'#', // shift-3
|
||||
'$', // shift-4
|
||||
'%', // shift-5
|
||||
'^', // shift-6
|
||||
'&', // shift-7
|
||||
'*', // shift-8
|
||||
'(', // shift-9
|
||||
':',
|
||||
':', // shift-;
|
||||
'<',
|
||||
'+', // shift-=
|
||||
'>', '?', '@',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'[', // shift-[
|
||||
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
|
||||
']', // shift-]
|
||||
'"', '_',
|
||||
'\'', // shift-`
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'{', '|', '}', '~', 127
|
||||
};
|
||||
|
||||
char frenchKeyMap[128] =
|
||||
{
|
||||
0,
|
||||
1,2,3,4,5,6,7,8,9,10,
|
||||
11,12,13,14,15,16,17,18,19,20,
|
||||
21,22,23,24,25,26,27,28,29,30,
|
||||
31,
|
||||
' ','!','"','#','$','%','&','%','(',')','*','+',';','-',':','!',
|
||||
'0','1','2','3','4','5','6','7','8','9',':','M','<','=','>','?',
|
||||
'@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
|
||||
'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^','_',
|
||||
'@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
|
||||
'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^',127
|
||||
};
|
||||
|
||||
char chat_char; // remove later.
|
||||
patch_t* hu_font[HU_FONTSIZE];
|
||||
doom_boolean chat_on;
|
||||
doom_boolean message_dontfuckwithme;
|
||||
|
||||
extern int showMessages;
|
||||
extern doom_boolean automapactive;
|
||||
|
||||
|
||||
//
|
||||
// Builtin map names.
|
||||
// The actual names can be found in DStrings.h.
|
||||
//
|
||||
|
||||
char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
|
||||
{
|
||||
|
||||
HUSTR_E1M1,
|
||||
HUSTR_E1M2,
|
||||
HUSTR_E1M3,
|
||||
HUSTR_E1M4,
|
||||
HUSTR_E1M5,
|
||||
HUSTR_E1M6,
|
||||
HUSTR_E1M7,
|
||||
HUSTR_E1M8,
|
||||
HUSTR_E1M9,
|
||||
|
||||
HUSTR_E2M1,
|
||||
HUSTR_E2M2,
|
||||
HUSTR_E2M3,
|
||||
HUSTR_E2M4,
|
||||
HUSTR_E2M5,
|
||||
HUSTR_E2M6,
|
||||
HUSTR_E2M7,
|
||||
HUSTR_E2M8,
|
||||
HUSTR_E2M9,
|
||||
|
||||
HUSTR_E3M1,
|
||||
HUSTR_E3M2,
|
||||
HUSTR_E3M3,
|
||||
HUSTR_E3M4,
|
||||
HUSTR_E3M5,
|
||||
HUSTR_E3M6,
|
||||
HUSTR_E3M7,
|
||||
HUSTR_E3M8,
|
||||
HUSTR_E3M9,
|
||||
|
||||
HUSTR_E4M1,
|
||||
HUSTR_E4M2,
|
||||
HUSTR_E4M3,
|
||||
HUSTR_E4M4,
|
||||
HUSTR_E4M5,
|
||||
HUSTR_E4M6,
|
||||
HUSTR_E4M7,
|
||||
HUSTR_E4M8,
|
||||
HUSTR_E4M9,
|
||||
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL",
|
||||
"NEWLEVEL"
|
||||
};
|
||||
|
||||
char* mapnames2[] = // DOOM 2 map names.
|
||||
{
|
||||
HUSTR_1,
|
||||
HUSTR_2,
|
||||
HUSTR_3,
|
||||
HUSTR_4,
|
||||
HUSTR_5,
|
||||
HUSTR_6,
|
||||
HUSTR_7,
|
||||
HUSTR_8,
|
||||
HUSTR_9,
|
||||
HUSTR_10,
|
||||
HUSTR_11,
|
||||
|
||||
HUSTR_12,
|
||||
HUSTR_13,
|
||||
HUSTR_14,
|
||||
HUSTR_15,
|
||||
HUSTR_16,
|
||||
HUSTR_17,
|
||||
HUSTR_18,
|
||||
HUSTR_19,
|
||||
HUSTR_20,
|
||||
|
||||
HUSTR_21,
|
||||
HUSTR_22,
|
||||
HUSTR_23,
|
||||
HUSTR_24,
|
||||
HUSTR_25,
|
||||
HUSTR_26,
|
||||
HUSTR_27,
|
||||
HUSTR_28,
|
||||
HUSTR_29,
|
||||
HUSTR_30,
|
||||
HUSTR_31,
|
||||
HUSTR_32
|
||||
};
|
||||
|
||||
|
||||
char* mapnamesp[] = // Plutonia WAD map names.
|
||||
{
|
||||
PHUSTR_1,
|
||||
PHUSTR_2,
|
||||
PHUSTR_3,
|
||||
PHUSTR_4,
|
||||
PHUSTR_5,
|
||||
PHUSTR_6,
|
||||
PHUSTR_7,
|
||||
PHUSTR_8,
|
||||
PHUSTR_9,
|
||||
PHUSTR_10,
|
||||
PHUSTR_11,
|
||||
|
||||
PHUSTR_12,
|
||||
PHUSTR_13,
|
||||
PHUSTR_14,
|
||||
PHUSTR_15,
|
||||
PHUSTR_16,
|
||||
PHUSTR_17,
|
||||
PHUSTR_18,
|
||||
PHUSTR_19,
|
||||
PHUSTR_20,
|
||||
|
||||
PHUSTR_21,
|
||||
PHUSTR_22,
|
||||
PHUSTR_23,
|
||||
PHUSTR_24,
|
||||
PHUSTR_25,
|
||||
PHUSTR_26,
|
||||
PHUSTR_27,
|
||||
PHUSTR_28,
|
||||
PHUSTR_29,
|
||||
PHUSTR_30,
|
||||
PHUSTR_31,
|
||||
PHUSTR_32
|
||||
};
|
||||
|
||||
|
||||
char* mapnamest[] = // TNT WAD map names.
|
||||
{
|
||||
THUSTR_1,
|
||||
THUSTR_2,
|
||||
THUSTR_3,
|
||||
THUSTR_4,
|
||||
THUSTR_5,
|
||||
THUSTR_6,
|
||||
THUSTR_7,
|
||||
THUSTR_8,
|
||||
THUSTR_9,
|
||||
THUSTR_10,
|
||||
THUSTR_11,
|
||||
|
||||
THUSTR_12,
|
||||
THUSTR_13,
|
||||
THUSTR_14,
|
||||
THUSTR_15,
|
||||
THUSTR_16,
|
||||
THUSTR_17,
|
||||
THUSTR_18,
|
||||
THUSTR_19,
|
||||
THUSTR_20,
|
||||
|
||||
THUSTR_21,
|
||||
THUSTR_22,
|
||||
THUSTR_23,
|
||||
THUSTR_24,
|
||||
THUSTR_25,
|
||||
THUSTR_26,
|
||||
THUSTR_27,
|
||||
THUSTR_28,
|
||||
THUSTR_29,
|
||||
THUSTR_30,
|
||||
THUSTR_31,
|
||||
THUSTR_32
|
||||
};
|
||||
|
||||
char ForeignTranslation(unsigned char ch)
|
||||
{
|
||||
return ch < 128 ? frenchKeyMap[ch] : ch;
|
||||
}
|
||||
|
||||
void HU_Init(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
int j;
|
||||
char buffer[9];
|
||||
|
||||
if (french)
|
||||
shiftxform = french_shiftxform;
|
||||
else
|
||||
shiftxform = english_shiftxform;
|
||||
|
||||
// load the heads-up font
|
||||
j = HU_FONTSTART;
|
||||
for (i = 0; i < HU_FONTSIZE; i++)
|
||||
{
|
||||
//if (j == 40) __debugbreak();
|
||||
//doom_sprintf(buffer, "STCFN%.3d", j++);
|
||||
doom_strcpy(buffer, "STCFN");
|
||||
if (j < 100) doom_concat(buffer, "0");
|
||||
if (j < 10) doom_concat(buffer, "0");
|
||||
doom_concat(buffer, doom_itoa(j++, 10));
|
||||
hu_font[i] = (patch_t*)W_CacheLumpName(buffer, PU_STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
void HU_Stop(void)
|
||||
{
|
||||
headsupactive = false;
|
||||
}
|
||||
|
||||
void HU_Start(void)
|
||||
{
|
||||
int i;
|
||||
char* s;
|
||||
|
||||
if (headsupactive)
|
||||
HU_Stop();
|
||||
|
||||
plr = &players[consoleplayer];
|
||||
message_on = false;
|
||||
message_dontfuckwithme = false;
|
||||
message_nottobefuckedwith = false;
|
||||
chat_on = false;
|
||||
|
||||
// create the message widget
|
||||
HUlib_initSText(&w_message,
|
||||
HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
|
||||
hu_font,
|
||||
HU_FONTSTART, &message_on);
|
||||
|
||||
// create the map title widget
|
||||
HUlib_initTextLine(&w_title,
|
||||
HU_TITLEX, HU_TITLEY,
|
||||
hu_font,
|
||||
HU_FONTSTART);
|
||||
|
||||
switch (gamemode)
|
||||
{
|
||||
case shareware:
|
||||
case registered:
|
||||
case retail:
|
||||
s = HU_TITLE;
|
||||
break;
|
||||
|
||||
/* FIXME
|
||||
case pack_plut:
|
||||
s = HU_TITLEP;
|
||||
break;
|
||||
case pack_tnt:
|
||||
s = HU_TITLET;
|
||||
break;
|
||||
*/
|
||||
|
||||
case commercial:
|
||||
default:
|
||||
s = HU_TITLE2;
|
||||
break;
|
||||
}
|
||||
|
||||
while (*s)
|
||||
HUlib_addCharToTextLine(&w_title, *(s++));
|
||||
|
||||
// create the chat widget
|
||||
HUlib_initIText(&w_chat,
|
||||
HU_INPUTX, HU_INPUTY,
|
||||
hu_font,
|
||||
HU_FONTSTART, &chat_on);
|
||||
|
||||
// create the inputbuffer widgets
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
|
||||
|
||||
headsupactive = true;
|
||||
}
|
||||
|
||||
void HU_Drawer(void)
|
||||
{
|
||||
HUlib_drawSText(&w_message);
|
||||
HUlib_drawIText(&w_chat);
|
||||
if (automapactive)
|
||||
HUlib_drawTextLine(&w_title, false);
|
||||
}
|
||||
|
||||
void HU_Erase(void)
|
||||
{
|
||||
HUlib_eraseSText(&w_message);
|
||||
HUlib_eraseIText(&w_chat);
|
||||
HUlib_eraseTextLine(&w_title);
|
||||
}
|
||||
|
||||
void HU_Ticker(void)
|
||||
{
|
||||
int i, rc;
|
||||
char c;
|
||||
|
||||
// tick down message counter if message is up
|
||||
if (message_counter && !--message_counter)
|
||||
{
|
||||
message_on = false;
|
||||
message_nottobefuckedwith = false;
|
||||
}
|
||||
|
||||
if (showMessages || message_dontfuckwithme)
|
||||
{
|
||||
|
||||
// display message if necessary
|
||||
if ((plr->message && !message_nottobefuckedwith)
|
||||
|| (plr->message && message_dontfuckwithme))
|
||||
{
|
||||
HUlib_addMessageToSText(&w_message, 0, plr->message);
|
||||
plr->message = 0;
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
message_nottobefuckedwith = message_dontfuckwithme;
|
||||
message_dontfuckwithme = 0;
|
||||
}
|
||||
|
||||
} // else message_on = false;
|
||||
|
||||
// check for incoming chat characters
|
||||
if (netgame)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (i != consoleplayer
|
||||
&& (c = players[i].cmd.chatchar))
|
||||
{
|
||||
if (c <= HU_BROADCAST)
|
||||
chat_dest[i] = c;
|
||||
else
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
c = (char)shiftxform[(unsigned char)c];
|
||||
rc = HUlib_keyInIText(&w_inputbuffer[i], c);
|
||||
if (rc && c == KEY_ENTER)
|
||||
{
|
||||
if (w_inputbuffer[i].l.len
|
||||
&& (chat_dest[i] == consoleplayer + 1
|
||||
|| chat_dest[i] == HU_BROADCAST))
|
||||
{
|
||||
HUlib_addMessageToSText(&w_message,
|
||||
player_names[i],
|
||||
w_inputbuffer[i].l.l);
|
||||
|
||||
message_nottobefuckedwith = true;
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
if (gamemode == commercial)
|
||||
S_StartSound(0, sfx_radio);
|
||||
else
|
||||
S_StartSound(0, sfx_tink);
|
||||
}
|
||||
HUlib_resetIText(&w_inputbuffer[i]);
|
||||
}
|
||||
}
|
||||
players[i].cmd.chatchar = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HU_queueChatChar(char c)
|
||||
{
|
||||
if (((head + 1) & (QUEUESIZE - 1)) == tail)
|
||||
{
|
||||
plr->message = HUSTR_MSGU;
|
||||
}
|
||||
else
|
||||
{
|
||||
chatchars[head] = c;
|
||||
head = (head + 1) & (QUEUESIZE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
char HU_dequeueChatChar(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (head != tail)
|
||||
{
|
||||
c = chatchars[tail];
|
||||
tail = (tail + 1) & (QUEUESIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
doom_boolean HU_Responder(event_t* ev)
|
||||
{
|
||||
|
||||
static char lastmessage[HU_MAXLINELENGTH + 1];
|
||||
char* macromessage;
|
||||
doom_boolean eatkey = false;
|
||||
static doom_boolean shiftdown = false;
|
||||
static doom_boolean altdown = false;
|
||||
unsigned char c;
|
||||
int i;
|
||||
int numplayers;
|
||||
|
||||
static char destination_keys[MAXPLAYERS] =
|
||||
{
|
||||
HUSTR_KEYGREEN,
|
||||
HUSTR_KEYINDIGO,
|
||||
HUSTR_KEYBROWN,
|
||||
HUSTR_KEYRED
|
||||
};
|
||||
|
||||
static int num_nobrainers = 0;
|
||||
|
||||
numplayers = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
numplayers += playeringame[i];
|
||||
|
||||
if (ev->data1 == KEY_RSHIFT)
|
||||
{
|
||||
shiftdown = ev->type == ev_keydown;
|
||||
return false;
|
||||
}
|
||||
else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
|
||||
{
|
||||
altdown = ev->type == ev_keydown;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ev->type != ev_keydown)
|
||||
return false;
|
||||
|
||||
if (!chat_on)
|
||||
{
|
||||
if (ev->data1 == HU_MSGREFRESH)
|
||||
{
|
||||
message_on = true;
|
||||
message_counter = HU_MSGTIMEOUT;
|
||||
eatkey = true;
|
||||
}
|
||||
else if (netgame && ev->data1 == HU_INPUTTOGGLE)
|
||||
{
|
||||
eatkey = chat_on = true;
|
||||
HUlib_resetIText(&w_chat);
|
||||
HU_queueChatChar(HU_BROADCAST);
|
||||
}
|
||||
else if (netgame && numplayers > 2)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (ev->data1 == destination_keys[i])
|
||||
{
|
||||
if (playeringame[i] && i != consoleplayer)
|
||||
{
|
||||
eatkey = chat_on = true;
|
||||
HUlib_resetIText(&w_chat);
|
||||
HU_queueChatChar(i + 1);
|
||||
break;
|
||||
}
|
||||
else if (i == consoleplayer)
|
||||
{
|
||||
num_nobrainers++;
|
||||
if (num_nobrainers < 3)
|
||||
plr->message = HUSTR_TALKTOSELF1;
|
||||
else if (num_nobrainers < 6)
|
||||
plr->message = HUSTR_TALKTOSELF2;
|
||||
else if (num_nobrainers < 9)
|
||||
plr->message = HUSTR_TALKTOSELF3;
|
||||
else if (num_nobrainers < 32)
|
||||
plr->message = HUSTR_TALKTOSELF4;
|
||||
else
|
||||
plr->message = HUSTR_TALKTOSELF5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = ev->data1;
|
||||
// send a macro
|
||||
if (altdown)
|
||||
{
|
||||
c = c - '0';
|
||||
if (c > 9)
|
||||
return false;
|
||||
macromessage = chat_macros[c];
|
||||
|
||||
// kill last message with a '\n'
|
||||
HU_queueChatChar(KEY_ENTER); // DEBUG!!!
|
||||
|
||||
// send the macro message
|
||||
while (*macromessage)
|
||||
HU_queueChatChar(*macromessage++);
|
||||
HU_queueChatChar(KEY_ENTER);
|
||||
|
||||
// leave chat mode and notify that it was sent
|
||||
chat_on = false;
|
||||
doom_strcpy(lastmessage, chat_macros[c]);
|
||||
plr->message = lastmessage;
|
||||
eatkey = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (french)
|
||||
c = ForeignTranslation(c);
|
||||
if (shiftdown || (c >= 'a' && c <= 'z'))
|
||||
c = shiftxform[c];
|
||||
eatkey = HUlib_keyInIText(&w_chat, c);
|
||||
if (eatkey)
|
||||
{
|
||||
HU_queueChatChar(c);
|
||||
}
|
||||
if (c == KEY_ENTER)
|
||||
{
|
||||
chat_on = false;
|
||||
if (w_chat.l.len)
|
||||
{
|
||||
doom_strcpy(lastmessage, w_chat.l.l);
|
||||
plr->message = lastmessage;
|
||||
}
|
||||
}
|
||||
else if (c == KEY_ESCAPE)
|
||||
chat_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
return eatkey;
|
||||
}
|
67
src/DOOM/hu_stuff.h
Normal file
67
src/DOOM/hu_stuff.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION: Head up display
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __HU_STUFF_H__
|
||||
#define __HU_STUFF_H__
|
||||
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
//
|
||||
// Globally visible constants.
|
||||
//
|
||||
#define HU_FONTSTART '!' // the first font characters
|
||||
#define HU_FONTEND '_' // the last font characters
|
||||
|
||||
// Calculate # of glyphs in font.
|
||||
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
|
||||
|
||||
#define HU_BROADCAST 5
|
||||
|
||||
#define HU_MSGREFRESH KEY_ENTER
|
||||
#define HU_MSGX 0
|
||||
#define HU_MSGY 0
|
||||
#define HU_MSGWIDTH 64 // in characters
|
||||
#define HU_MSGHEIGHT 1 // in lines
|
||||
|
||||
#define HU_MSGTIMEOUT (4*TICRATE)
|
||||
|
||||
|
||||
//
|
||||
// HEADS UP TEXT
|
||||
//
|
||||
|
||||
void HU_Init(void);
|
||||
void HU_Start(void);
|
||||
doom_boolean HU_Responder(event_t* ev);
|
||||
void HU_Ticker(void);
|
||||
void HU_Drawer(void);
|
||||
char HU_dequeueChatChar(void);
|
||||
void HU_Erase(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
457
src/DOOM/i_net.c
Normal file
457
src/DOOM/i_net.c
Normal file
@ -0,0 +1,457 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//#define I_NET_ENABLED
|
||||
|
||||
#if defined(I_NET_ENABLED)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#endif
|
||||
#include "doom_config.h"
|
||||
|
||||
#if defined(I_NET_ENABLED)
|
||||
#if defined(DOOM_WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#include <WinSock2.h>
|
||||
#include <winsock.h>
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/ioctl.h>
|
||||
#define SOCKET int
|
||||
#endif
|
||||
#else
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#endif
|
||||
|
||||
#include "i_system.h"
|
||||
#include "d_event.h"
|
||||
#include "d_net.h"
|
||||
#include "m_argv.h"
|
||||
#include "doomstat.h"
|
||||
#include "i_net.h"
|
||||
|
||||
|
||||
// For some odd reason...
|
||||
#if !defined(DOOM_APPLE) // It doesn't complain on Win32? O_o
|
||||
#define ntohl(x) \
|
||||
((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
|
||||
(((unsigned long int)(x) & 0x0000ff00U) << 8) | \
|
||||
(((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
|
||||
(((unsigned long int)(x) & 0xff000000U) >> 24)))
|
||||
|
||||
#define ntohs(x) \
|
||||
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
|
||||
(((unsigned short int)(x) & 0xff00) >> 8))) \
|
||||
|
||||
#define htonl(x) ntohl(x)
|
||||
#define htons(x) ntohs(x)
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
//
|
||||
|
||||
int DOOMPORT = (IPPORT_USERRESERVED + 0x1d);
|
||||
int DOOMPORT_SEND = (IPPORT_USERRESERVED + 0x1e);
|
||||
|
||||
#if defined(I_NET_ENABLED)
|
||||
SOCKET sendsocket;
|
||||
SOCKET insocket;
|
||||
|
||||
struct sockaddr_in sendaddress[MAXNETNODES];
|
||||
#endif
|
||||
|
||||
void (*netget) (void);
|
||||
void (*netsend) (void);
|
||||
|
||||
|
||||
void NetSend(void);
|
||||
doom_boolean NetListen(void);
|
||||
|
||||
|
||||
//
|
||||
// UDPsocket
|
||||
//
|
||||
#if defined(I_NET_ENABLED)
|
||||
SOCKET UDPsocket(void)
|
||||
{
|
||||
SOCKET s;
|
||||
|
||||
// allocate a socket
|
||||
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (s < 0)
|
||||
{
|
||||
//I_Error("Error: can't create socket: %s", strerror(errno));
|
||||
|
||||
doom_strcpy(error_buf, "Error: can't create socket: ");
|
||||
doom_concat(error_buf, strerror(errno));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// BindToLocalPort
|
||||
//
|
||||
#if defined(I_NET_ENABLED)
|
||||
void BindToLocalPort(SOCKET s, int port)
|
||||
{
|
||||
int v;
|
||||
struct sockaddr_in address;
|
||||
|
||||
doom_memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = port;
|
||||
|
||||
v = bind(s, (void*)&address, sizeof(address));
|
||||
if (v == -1)
|
||||
{
|
||||
//I_Error("Error: BindToPort: bind: %s", strerror(errno));
|
||||
|
||||
doom_strcpy(error_buf, "Error: BindToPort: bind: ");
|
||||
doom_concat(error_buf, strerror(errno));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// PacketSend
|
||||
//
|
||||
void PacketSend(void)
|
||||
{
|
||||
#if defined(I_NET_ENABLED)
|
||||
int c;
|
||||
doomdata_t sw;
|
||||
|
||||
// byte swap
|
||||
sw.checksum = htonl(netbuffer->checksum);
|
||||
sw.player = netbuffer->player;
|
||||
sw.retransmitfrom = netbuffer->retransmitfrom;
|
||||
sw.starttic = netbuffer->starttic;
|
||||
sw.numtics = netbuffer->numtics;
|
||||
for (c = 0; c < netbuffer->numtics; c++)
|
||||
{
|
||||
sw.cmds[c].forwardmove = netbuffer->cmds[c].forwardmove;
|
||||
sw.cmds[c].sidemove = netbuffer->cmds[c].sidemove;
|
||||
sw.cmds[c].angleturn = htons(netbuffer->cmds[c].angleturn);
|
||||
sw.cmds[c].consistancy = htons(netbuffer->cmds[c].consistancy);
|
||||
sw.cmds[c].chatchar = netbuffer->cmds[c].chatchar;
|
||||
sw.cmds[c].buttons = netbuffer->cmds[c].buttons;
|
||||
}
|
||||
|
||||
//doom_print ("sending %i\n",gametic);
|
||||
c = sendto(sendsocket, (const char*)&sw, doomcom->datalength
|
||||
, 0, (void*)&sendaddress[doomcom->remotenode]
|
||||
, sizeof(sendaddress[doomcom->remotenode]));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// PacketGet
|
||||
//
|
||||
void PacketGet(void)
|
||||
{
|
||||
#if defined(I_NET_ENABLED)
|
||||
int i;
|
||||
int c;
|
||||
struct sockaddr_in fromaddress;
|
||||
#if defined(__APPLE__)
|
||||
socklen_t fromlen;
|
||||
#else
|
||||
int fromlen;
|
||||
#endif
|
||||
doomdata_t sw;
|
||||
|
||||
fromlen = sizeof(fromaddress);
|
||||
c = recvfrom(insocket, (char*)&sw, sizeof(sw), 0
|
||||
, (struct sockaddr*)&fromaddress, &fromlen);
|
||||
if (c == -1)
|
||||
{
|
||||
#if defined(DOOM_WIN32)
|
||||
int r = WSAGetLastError();
|
||||
if (r != WSAEWOULDBLOCK)
|
||||
{
|
||||
//I_Error("Error: GetPacket: %i", r);
|
||||
|
||||
doom_strcpy(error_buf, "Error: GetPacket: ");
|
||||
doom_concat(error_buf, doom_itoa(r, 10));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
#else
|
||||
if (errno != EWOULDBLOCK)
|
||||
{
|
||||
//I_Error("Error: GetPacket: %s", strerror(errno));
|
||||
|
||||
doom_strcpy(error_buf, "Error: GetPacket: ");
|
||||
doom_concat(error_buf, strerror(errno));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
#endif
|
||||
doomcom->remotenode = -1; // no packet
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
static int first = 1;
|
||||
if (first)
|
||||
{
|
||||
//doom_print("len=%d:p=[0x%x 0x%x] \n", c, *(int*)&sw, *((int*)&sw + 1));
|
||||
doom_print("len=");
|
||||
doom_print(doom_itoa(c, 10));
|
||||
doom_print(":p=[0x");
|
||||
doom_print(doom_itoa(*(int*)&sw, 16));
|
||||
doom_print(" 0x");
|
||||
doom_print(doom_itoa(*((int*)&sw + 1), 16));
|
||||
doom_print("] \n");
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
|
||||
// find remote node number
|
||||
for (i = 0; i < doomcom->numnodes; i++)
|
||||
if (fromaddress.sin_addr.s_addr == sendaddress[i].sin_addr.s_addr)
|
||||
break;
|
||||
|
||||
if (i == doomcom->numnodes)
|
||||
{
|
||||
// packet is not from one of the players (new game broadcast)
|
||||
doomcom->remotenode = -1; // no packet
|
||||
return;
|
||||
}
|
||||
|
||||
doomcom->remotenode = i; // good packet from a game player
|
||||
doomcom->datalength = c;
|
||||
|
||||
// byte swap
|
||||
netbuffer->checksum = ntohl(sw.checksum);
|
||||
netbuffer->player = sw.player;
|
||||
netbuffer->retransmitfrom = sw.retransmitfrom;
|
||||
netbuffer->starttic = sw.starttic;
|
||||
netbuffer->numtics = sw.numtics;
|
||||
|
||||
for (c = 0; c < netbuffer->numtics; c++)
|
||||
{
|
||||
netbuffer->cmds[c].forwardmove = sw.cmds[c].forwardmove;
|
||||
netbuffer->cmds[c].sidemove = sw.cmds[c].sidemove;
|
||||
netbuffer->cmds[c].angleturn = ntohs(sw.cmds[c].angleturn);
|
||||
netbuffer->cmds[c].consistancy = ntohs(sw.cmds[c].consistancy);
|
||||
netbuffer->cmds[c].chatchar = sw.cmds[c].chatchar;
|
||||
netbuffer->cmds[c].buttons = sw.cmds[c].buttons;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int GetLocalAddress(void)
|
||||
{
|
||||
#if defined(I_NET_ENABLED)
|
||||
char hostname[1024];
|
||||
struct hostent* hostentry; // host information entry
|
||||
int v;
|
||||
|
||||
// get local address
|
||||
v = gethostname(hostname, sizeof(hostname));
|
||||
if (v == -1)
|
||||
{
|
||||
//I_Error("Error: GetLocalAddress : gethostname: errno %d", errno);
|
||||
|
||||
doom_strcpy(error_buf, "Error: GetLocalAddress : gethostname: errno ");
|
||||
doom_concat(error_buf, strerror(errno));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
|
||||
hostentry = gethostbyname(hostname);
|
||||
if (!hostentry)
|
||||
{
|
||||
I_Error("Error: GetLocalAddress : gethostbyname: couldn't get local host");
|
||||
}
|
||||
|
||||
return *(int*)hostentry->h_addr_list[0];
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_InitNetwork
|
||||
//
|
||||
void I_InitNetwork(void)
|
||||
{
|
||||
#if defined(I_NET_ENABLED)
|
||||
#if defined(DOOM_WIN32)
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
|
||||
u_long trueval = 1;
|
||||
#else
|
||||
doom_boolean trueval = true;
|
||||
#endif
|
||||
#endif
|
||||
int i;
|
||||
int p;
|
||||
struct hostent* hostentry; // host information entry
|
||||
|
||||
doomcom = doom_malloc(sizeof(*doomcom));
|
||||
doom_memset(doomcom, 0, sizeof(*doomcom));
|
||||
|
||||
// set up for network
|
||||
i = M_CheckParm("-dup");
|
||||
if (i && i < myargc - 1)
|
||||
{
|
||||
doomcom->ticdup = myargv[i + 1][0] - '0';
|
||||
if (doomcom->ticdup < 1)
|
||||
doomcom->ticdup = 1;
|
||||
if (doomcom->ticdup > 9)
|
||||
doomcom->ticdup = 9;
|
||||
}
|
||||
else
|
||||
doomcom->ticdup = 1;
|
||||
|
||||
if (M_CheckParm("-extratic"))
|
||||
doomcom->extratics = 1;
|
||||
else
|
||||
doomcom->extratics = 0;
|
||||
|
||||
p = M_CheckParm("-port");
|
||||
if (p && p < myargc - 1)
|
||||
{
|
||||
DOOMPORT = doom_atoi(myargv[p + 1]);
|
||||
//doom_print("using alternate port %i\n", DOOMPORT);
|
||||
doom_print("using alternate port ");
|
||||
doom_print(doom_itoa(DOOMPORT, 10));
|
||||
doom_print("\n");
|
||||
}
|
||||
|
||||
p = M_CheckParm("-sendport");
|
||||
if (p && p < myargc - 1)
|
||||
{
|
||||
DOOMPORT_SEND = doom_atoi(myargv[p + 1]);
|
||||
//doom_print("using alternate send port %i\n", DOOMPORT_SEND);
|
||||
doom_print("using alternate send port ");
|
||||
doom_print(doom_itoa(DOOMPORT_SEND, 10));
|
||||
doom_print("\n");
|
||||
}
|
||||
|
||||
// parse network game options,
|
||||
// -net <consoleplayer> <host> <host> ...
|
||||
i = M_CheckParm("-net");
|
||||
if (!i)
|
||||
{
|
||||
// single player game
|
||||
netgame = false;
|
||||
doomcom->id = DOOMCOM_ID;
|
||||
doomcom->numplayers = doomcom->numnodes = 1;
|
||||
doomcom->deathmatch = false;
|
||||
doomcom->consoleplayer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(I_NET_ENABLED)
|
||||
netsend = PacketSend;
|
||||
netget = PacketGet;
|
||||
netgame = true;
|
||||
|
||||
// parse player number and host list
|
||||
doomcom->consoleplayer = myargv[i + 1][0] - '1';
|
||||
|
||||
doomcom->numnodes = 1; // this node for sure
|
||||
|
||||
i++;
|
||||
while (++i < myargc && myargv[i][0] != '-')
|
||||
{
|
||||
sendaddress[doomcom->numnodes].sin_family = AF_INET;
|
||||
sendaddress[doomcom->numnodes].sin_port = htons(DOOMPORT);
|
||||
if (myargv[i][0] == '.')
|
||||
{
|
||||
sendaddress[doomcom->numnodes].sin_addr.s_addr
|
||||
= inet_addr(myargv[i] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hostentry = gethostbyname(myargv[i]);
|
||||
if (!hostentry)
|
||||
{
|
||||
//I_Error("Error: gethostbyname: couldn't find %s", myargv[i]);
|
||||
|
||||
doom_strcpy(error_buf, "Error: gethostbyname: couldn't find ");
|
||||
doom_concat(error_buf, myargv[i]);
|
||||
I_Error(error_buf);
|
||||
}
|
||||
sendaddress[doomcom->numnodes].sin_addr.s_addr
|
||||
= *(int*)hostentry->h_addr_list[0];
|
||||
}
|
||||
doomcom->numnodes++;
|
||||
}
|
||||
|
||||
doomcom->id = DOOMCOM_ID;
|
||||
doomcom->numplayers = doomcom->numnodes;
|
||||
|
||||
// build message to receive
|
||||
insocket = UDPsocket();
|
||||
BindToLocalPort(insocket, htons(DOOMPORT));
|
||||
#if defined(DOOM_WIN32)
|
||||
ioctlsocket(insocket, FIONBIO, &trueval);
|
||||
#else
|
||||
ioctl(insocket, FIONBIO, &trueval);
|
||||
#endif
|
||||
|
||||
sendsocket = UDPsocket();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void I_NetCmd(void)
|
||||
{
|
||||
#if defined(I_NET_ENABLED)
|
||||
if (doomcom->command == CMD_SEND)
|
||||
{
|
||||
netsend();
|
||||
}
|
||||
else if (doomcom->command == CMD_GET)
|
||||
{
|
||||
netget();
|
||||
}
|
||||
else
|
||||
{
|
||||
//I_Error("Error: Bad net cmd: %i\n", doomcom->command);
|
||||
|
||||
doom_strcpy(error_buf, "Error: Bad net cmd: ");
|
||||
doom_concat(error_buf, doom_itoa(doomcom->command, 10));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
#endif
|
||||
}
|
38
src/DOOM/i_net.h
Normal file
38
src/DOOM/i_net.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific network interface stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __I_NET__
|
||||
#define __I_NET__
|
||||
|
||||
|
||||
// Called by D_DoomMain.
|
||||
|
||||
void I_InitNetwork (void);
|
||||
void I_NetCmd (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
1168
src/DOOM/i_sound.c
Normal file
1168
src/DOOM/i_sound.c
Normal file
File diff suppressed because it is too large
Load Diff
110
src/DOOM/i_sound.h
Normal file
110
src/DOOM/i_sound.h
Normal file
@ -0,0 +1,110 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System interface, sound.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __I_SOUND__
|
||||
#define __I_SOUND__
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "sounds.h"
|
||||
|
||||
|
||||
// Init at program start...
|
||||
void I_InitSound();
|
||||
|
||||
// ... update sound buffer and audio device at runtime...
|
||||
void I_UpdateSound(void);
|
||||
void I_SubmitSound(void);
|
||||
|
||||
// ... shut down and relase at program termination.
|
||||
void I_ShutdownSound(void);
|
||||
|
||||
|
||||
//
|
||||
// SFX I/O
|
||||
//
|
||||
|
||||
// Initialize channels?
|
||||
void I_SetChannels();
|
||||
|
||||
// Get raw data lump index for sound descriptor.
|
||||
int I_GetSfxLumpNum(sfxinfo_t* sfxinfo);
|
||||
|
||||
// Starts a sound in a particular sound channel.
|
||||
int I_StartSound(int id, int vol, int sep, int pitch, int priority);
|
||||
|
||||
// Stops a sound channel.
|
||||
void I_StopSound(int handle);
|
||||
|
||||
// Called by S_*() functions
|
||||
// to see if a channel is still playing.
|
||||
// Returns 0 if no longer playing, 1 if playing.
|
||||
int I_SoundIsPlaying(int handle);
|
||||
|
||||
// Updates the volume, separation,
|
||||
// and pitch of a sound channel.
|
||||
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch);
|
||||
|
||||
|
||||
//
|
||||
// MUSIC I/O
|
||||
//
|
||||
void I_InitMusic(void);
|
||||
void I_ShutdownMusic(void);
|
||||
|
||||
// Volume.
|
||||
void I_SetMusicVolume(int volume);
|
||||
|
||||
// PAUSE game handling.
|
||||
void I_PauseSong(int handle);
|
||||
void I_ResumeSong(int handle);
|
||||
|
||||
// Registers a song handle to song data.
|
||||
int I_RegisterSong(void* data);
|
||||
|
||||
// Called by anything that wishes to start music.
|
||||
// plays a song, and when the song is done,
|
||||
// starts playing it again in an endless loop.
|
||||
// Horrible thing to do, considering.
|
||||
void I_PlaySong(int handle, int looping);
|
||||
|
||||
// Stops a song over 3 seconds.
|
||||
void I_StopSong(int handle);
|
||||
|
||||
// See above (register), then think backwards
|
||||
void I_UnRegisterSong(int handle);
|
||||
|
||||
// Get next MIDI message
|
||||
unsigned long I_TickSong();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
160
src/DOOM/i_system.c
Normal file
160
src/DOOM/i_system.c
Normal file
@ -0,0 +1,160 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "m_misc.h"
|
||||
#include "i_video.h"
|
||||
#include "i_sound.h"
|
||||
#include "d_net.h"
|
||||
#include "g_game.h"
|
||||
#include "i_system.h"
|
||||
|
||||
|
||||
int mb_used = 6 * (sizeof(void*) / 4);
|
||||
ticcmd_t emptycmd;
|
||||
|
||||
|
||||
extern doom_boolean demorecording;
|
||||
|
||||
|
||||
void I_Tactile(int on, int off, int total)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ticcmd_t* I_BaseTiccmd(void)
|
||||
{
|
||||
return &emptycmd;
|
||||
}
|
||||
|
||||
|
||||
int I_GetHeapSize(void)
|
||||
{
|
||||
return mb_used * 1024 * 1024;
|
||||
}
|
||||
|
||||
|
||||
byte* I_ZoneBase(int* size)
|
||||
{
|
||||
*size = mb_used * 1024 * 1024;
|
||||
return (byte*)doom_malloc(*size);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_GetTime
|
||||
// returns time in 1/70th second tics
|
||||
//
|
||||
int I_GetTime(void)
|
||||
{
|
||||
int sec, usec;
|
||||
int newtics;
|
||||
static int basetime = 0;
|
||||
|
||||
doom_gettime(&sec, &usec);
|
||||
if (!basetime)
|
||||
basetime = sec;
|
||||
newtics = (sec - basetime) * TICRATE + usec * TICRATE / 1000000;
|
||||
return newtics;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_Init
|
||||
//
|
||||
void I_Init(void)
|
||||
{
|
||||
I_InitSound();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_Quit
|
||||
//
|
||||
void I_Quit(void)
|
||||
{
|
||||
D_QuitNetGame();
|
||||
I_ShutdownSound();
|
||||
I_ShutdownMusic();
|
||||
M_SaveDefaults();
|
||||
I_ShutdownGraphics();
|
||||
doom_exit(0);
|
||||
}
|
||||
|
||||
|
||||
void I_WaitVBL(int count)
|
||||
{
|
||||
#if 0 // [pd] Never sleep in main thread
|
||||
#ifdef SGI
|
||||
sginap(1);
|
||||
#else
|
||||
#ifdef SUN
|
||||
sleep(0);
|
||||
#else
|
||||
usleep(count * (1000000 / 70));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void I_BeginRead(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void I_EndRead(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
byte* I_AllocLow(int length)
|
||||
{
|
||||
byte* mem;
|
||||
|
||||
mem = (byte*)doom_malloc(length);
|
||||
doom_memset(mem, 0, length);
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_Error
|
||||
//
|
||||
void I_Error(char* error)
|
||||
{
|
||||
// Message first.
|
||||
if (error) doom_print(error);
|
||||
doom_print("\n");
|
||||
|
||||
// Shutdown. Here might be other errors.
|
||||
if (demorecording)
|
||||
G_CheckDemoStatus();
|
||||
|
||||
D_QuitNetGame();
|
||||
I_ShutdownGraphics();
|
||||
|
||||
doom_exit(-1);
|
||||
}
|
85
src/DOOM/i_system.h
Normal file
85
src/DOOM/i_system.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __I_SYSTEM__
|
||||
#define __I_SYSTEM__
|
||||
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
// Called by DoomMain.
|
||||
void I_Init(void);
|
||||
|
||||
// Called by startup code
|
||||
// to get the ammount of memory to malloc
|
||||
// for the zone management.
|
||||
byte* I_ZoneBase(int* size);
|
||||
|
||||
// Called by D_DoomLoop,
|
||||
// returns current time in tics.
|
||||
int I_GetTime(void);
|
||||
|
||||
// Called by D_DoomLoop,
|
||||
// called before processing any tics in a frame
|
||||
// (just after displaying a frame).
|
||||
// Time consuming syncronous operations
|
||||
// are performed here (joystick reading).
|
||||
// Can call D_PostEvent.
|
||||
void I_StartFrame(void);
|
||||
|
||||
// Called by D_DoomLoop,
|
||||
// called before processing each tic in a frame.
|
||||
// Quick syncronous operations are performed here.
|
||||
// Can call D_PostEvent.
|
||||
void I_StartTic(void);
|
||||
|
||||
// Asynchronous interrupt functions should maintain private queues
|
||||
// that are read by the synchronous functions
|
||||
// to be converted into events.
|
||||
|
||||
// Either returns a null ticcmd,
|
||||
// or calls a loadable driver to build it.
|
||||
// This ticcmd will then be modified by the gameloop
|
||||
// for normal input.
|
||||
ticcmd_t* I_BaseTiccmd(void);
|
||||
|
||||
// Called by M_Responder when quit is selected.
|
||||
// Clean exit, displays sell blurb.
|
||||
void I_Quit(void);
|
||||
|
||||
// Allocates from low memory under dos,
|
||||
// just mallocs under unix
|
||||
byte* I_AllocLow(int length);
|
||||
|
||||
void I_Tactile(int on, int off, int total);
|
||||
|
||||
void I_Error(char* error);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
143
src/DOOM/i_video.c
Normal file
143
src/DOOM/i_video.c
Normal file
@ -0,0 +1,143 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// DOOM graphics stuff for X11, UNIX.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "i_system.h"
|
||||
#include "v_video.h"
|
||||
#include "m_argv.h"
|
||||
#include "d_main.h"
|
||||
#include "doomdef.h"
|
||||
|
||||
|
||||
#define POINTER_WARP_COUNTDOWN 1
|
||||
|
||||
|
||||
// Fake mouse handling.
|
||||
// This cannot work properly w/o DGA.
|
||||
// Needs an invisible mouse cursor at least.
|
||||
doom_boolean grabMouse;
|
||||
int doPointerWarp = POINTER_WARP_COUNTDOWN;
|
||||
|
||||
unsigned char screen_palette[256 * 3];
|
||||
|
||||
doom_boolean mousemoved = false;
|
||||
doom_boolean shmFinished;
|
||||
|
||||
|
||||
// Blocky mode,
|
||||
// replace each 320x200 pixel with multiply*multiply pixels.
|
||||
// According to Dave Taylor, it still is a bonehead thing
|
||||
// to use ....
|
||||
static int multiply = 1;
|
||||
static int lastmousex = 0;
|
||||
static int lastmousey = 0;
|
||||
|
||||
|
||||
void I_ShutdownGraphics(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_StartFrame
|
||||
//
|
||||
void I_StartFrame(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void I_GetEvent(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_StartTic
|
||||
//
|
||||
void I_StartTic(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_UpdateNoBlit
|
||||
//
|
||||
void I_UpdateNoBlit(void)
|
||||
{
|
||||
// what is this?
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_FinishUpdate
|
||||
//
|
||||
void I_FinishUpdate(void)
|
||||
{
|
||||
static int lasttic;
|
||||
int tics;
|
||||
int i;
|
||||
|
||||
// draws little dots on the bottom of the screen
|
||||
if (devparm)
|
||||
{
|
||||
i = I_GetTime();
|
||||
tics = i - lasttic;
|
||||
lasttic = i;
|
||||
if (tics > 20) tics = 20;
|
||||
|
||||
for (i = 0; i < tics * 2; i += 2)
|
||||
screens[0][(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0xff;
|
||||
for (; i < 20 * 2; i += 2)
|
||||
screens[0][(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0x0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_ReadScreen
|
||||
//
|
||||
void I_ReadScreen(byte* scr)
|
||||
{
|
||||
doom_memcpy(scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// I_SetPalette
|
||||
//
|
||||
void I_SetPalette(byte* palette)
|
||||
{
|
||||
doom_memcpy(screen_palette, palette, 256 * 3);
|
||||
}
|
||||
|
||||
|
||||
void I_InitGraphics(void)
|
||||
{
|
||||
screens[0] = (unsigned char*)doom_malloc(SCREENWIDTH * SCREENHEIGHT);
|
||||
}
|
57
src/DOOM/i_video.h
Normal file
57
src/DOOM/i_video.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// System specific interface stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __I_VIDEO__
|
||||
#define __I_VIDEO__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
// Called by D_DoomMain,
|
||||
// determines the hardware configuration
|
||||
// and sets up the video mode
|
||||
void I_InitGraphics(void);
|
||||
|
||||
void I_ShutdownGraphics(void);
|
||||
|
||||
// Takes full 8 bit values.
|
||||
void I_SetPalette(byte* palette);
|
||||
|
||||
void I_UpdateNoBlit(void);
|
||||
void I_FinishUpdate(void);
|
||||
|
||||
// Wait for vertical retrace or pause a bit.
|
||||
void I_WaitVBL(int count);
|
||||
|
||||
void I_ReadScreen(byte* scr);
|
||||
|
||||
void I_BeginRead(void);
|
||||
void I_EndRead(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
4663
src/DOOM/info.c
Normal file
4663
src/DOOM/info.c
Normal file
File diff suppressed because it is too large
Load Diff
1344
src/DOOM/info.h
Normal file
1344
src/DOOM/info.h
Normal file
File diff suppressed because it is too large
Load Diff
53
src/DOOM/m_argv.c
Normal file
53
src/DOOM/m_argv.c
Normal file
@ -0,0 +1,53 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
// #if defined(DOOM_WIN32)
|
||||
// #define strcasecmp stricmp
|
||||
// #endif
|
||||
|
||||
|
||||
int myargc;
|
||||
char** myargv;
|
||||
|
||||
|
||||
//
|
||||
// M_CheckParm
|
||||
// Checks for the given parameter
|
||||
// in the program's command line arguments.
|
||||
// Returns the argument number (1 to argc-1)
|
||||
// or 0 if not present
|
||||
int M_CheckParm(char* check)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < myargc; i++)
|
||||
{
|
||||
if (!doom_strcasecmp(check, myargv[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
43
src/DOOM/m_argv.h
Normal file
43
src/DOOM/m_argv.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Nil.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_ARGV__
|
||||
#define __M_ARGV__
|
||||
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
extern int myargc;
|
||||
extern char** myargv;
|
||||
|
||||
// Returns the position of the given parameter
|
||||
// in the arg list (0 if not found).
|
||||
int M_CheckParm(char* check);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
50
src/DOOM/m_bbox.c
Normal file
50
src/DOOM/m_bbox.c
Normal file
@ -0,0 +1,50 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Main loop menu stuff.
|
||||
// Random number LUT.
|
||||
// Default Config File.
|
||||
// PCX Screenshots.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "m_bbox.h"
|
||||
|
||||
|
||||
void M_ClearBox(fixed_t* box)
|
||||
{
|
||||
box[BOXTOP] = box[BOXRIGHT] = DOOM_MININT;
|
||||
box[BOXBOTTOM] = box[BOXLEFT] = DOOM_MAXINT;
|
||||
}
|
||||
|
||||
|
||||
void M_AddToBox(fixed_t* box, fixed_t x, fixed_t y)
|
||||
{
|
||||
if (x < box[BOXLEFT])
|
||||
box[BOXLEFT] = x;
|
||||
else if (x > box[BOXRIGHT])
|
||||
box[BOXRIGHT] = x;
|
||||
if (y < box[BOXBOTTOM])
|
||||
box[BOXBOTTOM] = y;
|
||||
else if (y > box[BOXTOP])
|
||||
box[BOXTOP] = y;
|
||||
}
|
51
src/DOOM/m_bbox.h
Normal file
51
src/DOOM/m_bbox.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Nil.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_BBOX__
|
||||
#define __M_BBOX__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
|
||||
// Bounding box coordinate storage.
|
||||
enum
|
||||
{
|
||||
BOXTOP,
|
||||
BOXBOTTOM,
|
||||
BOXLEFT,
|
||||
BOXRIGHT
|
||||
}; // bbox coordinates
|
||||
|
||||
|
||||
// Bounding box functions.
|
||||
void M_ClearBox(fixed_t* box);
|
||||
void M_AddToBox(fixed_t* box, fixed_t x, fixed_t y);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
91
src/DOOM/m_cheat.c
Normal file
91
src/DOOM/m_cheat.c
Normal file
@ -0,0 +1,91 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Cheat sequence checking.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "m_cheat.h"
|
||||
|
||||
|
||||
//
|
||||
// CHEAT SEQUENCE PACKAGE
|
||||
//
|
||||
|
||||
static int firsttime = 1;
|
||||
static unsigned char cheat_xlate_table[256];
|
||||
|
||||
|
||||
//
|
||||
// Called in st_stuff module, which handles the input.
|
||||
// Returns a 1 if the cheat was successful, 0 if failed.
|
||||
//
|
||||
int cht_CheckCheat(cheatseq_t* cht, char key)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
if (firsttime)
|
||||
{
|
||||
firsttime = 0;
|
||||
for (i = 0; i < 256; i++) cheat_xlate_table[i] = SCRAMBLE(i);
|
||||
}
|
||||
|
||||
if (!cht->p)
|
||||
cht->p = cht->sequence; // initialize if first time
|
||||
|
||||
if (*cht->p == 0)
|
||||
*(cht->p++) = key;
|
||||
else if
|
||||
(cheat_xlate_table[(unsigned char)key] == *cht->p) cht->p++;
|
||||
else
|
||||
cht->p = cht->sequence;
|
||||
|
||||
if (*cht->p == 1)
|
||||
cht->p++;
|
||||
else if (*cht->p == 0xff) // end of sequence character
|
||||
{
|
||||
cht->p = cht->sequence;
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void cht_GetParam(cheatseq_t* cht, char* buffer)
|
||||
{
|
||||
unsigned char* p, c;
|
||||
|
||||
p = cht->sequence;
|
||||
while (*(p++) != 1);
|
||||
|
||||
do
|
||||
{
|
||||
c = *p;
|
||||
*(buffer++) = c;
|
||||
*(p++) = 0;
|
||||
} while (c && *p != 0xff);
|
||||
|
||||
if (*p == 0xff)
|
||||
*buffer = 0;
|
||||
}
|
52
src/DOOM/m_cheat.h
Normal file
52
src/DOOM/m_cheat.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Cheat code checking.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_CHEAT__
|
||||
#define __M_CHEAT__
|
||||
|
||||
|
||||
//
|
||||
// CHEAT SEQUENCE PACKAGE
|
||||
//
|
||||
|
||||
#define SCRAMBLE(a) \
|
||||
((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
|
||||
+ (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char* sequence;
|
||||
unsigned char* p;
|
||||
} cheatseq_t;
|
||||
|
||||
|
||||
int cht_CheckCheat(cheatseq_t* cht, char key);
|
||||
void cht_GetParam(cheatseq_t* cht, char* buffer);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
59
src/DOOM/m_fixed.c
Normal file
59
src/DOOM/m_fixed.c
Normal file
@ -0,0 +1,59 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Fixed point implementation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
|
||||
fixed_t FixedMul(fixed_t a, fixed_t b)
|
||||
{
|
||||
return ((long long)a * (long long)b) >> FRACBITS;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// FixedDiv, C version.
|
||||
//
|
||||
fixed_t FixedDiv(fixed_t a, fixed_t b)
|
||||
{
|
||||
if ((doom_abs(a) >> 14) >= doom_abs(b))
|
||||
return (a ^ b) < 0 ? DOOM_MININT : DOOM_MAXINT;
|
||||
return FixedDiv2(a, b);
|
||||
}
|
||||
|
||||
|
||||
fixed_t FixedDiv2(fixed_t a, fixed_t b)
|
||||
{
|
||||
double c;
|
||||
|
||||
c = ((double)a) / ((double)b) * FRACUNIT;
|
||||
|
||||
if (c >= 2147483648.0 || c < -2147483648.0)
|
||||
I_Error("Error: FixedDiv: divide by zero");
|
||||
return (fixed_t)c;
|
||||
}
|
47
src/DOOM/m_fixed.h
Normal file
47
src/DOOM/m_fixed.h
Normal file
@ -0,0 +1,47 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Fixed point arithemtics, implementation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_FIXED__
|
||||
#define __M_FIXED__
|
||||
|
||||
|
||||
//
|
||||
// Fixed point, 32bit as 16.16.
|
||||
//
|
||||
#define FRACBITS 16
|
||||
#define FRACUNIT (1<<FRACBITS)
|
||||
|
||||
|
||||
typedef int fixed_t;
|
||||
|
||||
|
||||
fixed_t FixedMul(fixed_t a, fixed_t b);
|
||||
fixed_t FixedDiv(fixed_t a, fixed_t b);
|
||||
fixed_t FixedDiv2(fixed_t a, fixed_t b);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
2263
src/DOOM/m_menu.c
Normal file
2263
src/DOOM/m_menu.c
Normal file
File diff suppressed because it is too large
Load Diff
63
src/DOOM/m_menu.h
Normal file
63
src/DOOM/m_menu.h
Normal file
@ -0,0 +1,63 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Menu widget stuff, episode selection and such.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_MENU__
|
||||
#define __M_MENU__
|
||||
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
|
||||
//
|
||||
// MENUS
|
||||
//
|
||||
|
||||
// Called by main loop,
|
||||
// saves config file and calls I_Quit when user exits.
|
||||
// Even when the menu is not displayed,
|
||||
// this can resize the view and change game parameters.
|
||||
// Does all the real work of the menu interaction.
|
||||
doom_boolean M_Responder(event_t* ev);
|
||||
|
||||
// Called by main loop,
|
||||
// only used for menu (skull cursor) animation.
|
||||
void M_Ticker(void);
|
||||
|
||||
// Called by main loop,
|
||||
// draws the menus directly into the screen buffer.
|
||||
void M_Drawer(void);
|
||||
|
||||
// Called by D_DoomMain,
|
||||
// loads the config file.
|
||||
void M_Init(void);
|
||||
|
||||
// Called by intro code to force menu up upon a keypress,
|
||||
// does nothing if menu is already up.
|
||||
void M_StartControlPanel(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
542
src/DOOM/m_misc.c
Normal file
542
src/DOOM/m_misc.c
Normal file
@ -0,0 +1,542 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Main loop menu stuff.
|
||||
// Default Config File.
|
||||
// PCX Screenshots.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_swap.h"
|
||||
#include "m_argv.h"
|
||||
#include "w_wad.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "dstrings.h" // Data.
|
||||
#include "m_misc.h"
|
||||
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#define STRING_VALUE 0xFFFF
|
||||
|
||||
|
||||
//
|
||||
// SCREEN SHOTS
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
|
||||
unsigned short xmin;
|
||||
unsigned short ymin;
|
||||
unsigned short xmax;
|
||||
unsigned short ymax;
|
||||
|
||||
unsigned short hres;
|
||||
unsigned short vres;
|
||||
|
||||
unsigned char palette[48];
|
||||
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
|
||||
char filler[58];
|
||||
unsigned char data; // unbounded
|
||||
} pcx_t;
|
||||
|
||||
|
||||
//
|
||||
// M_DrawText
|
||||
// Returns the final X coordinate
|
||||
// HU_Init must have been called to init the font
|
||||
//
|
||||
extern patch_t* hu_font[HU_FONTSIZE];
|
||||
|
||||
|
||||
//
|
||||
// DEFAULTS
|
||||
//
|
||||
extern int key_right;
|
||||
extern int key_left;
|
||||
extern int key_up;
|
||||
extern int key_down;
|
||||
|
||||
extern int key_strafeleft;
|
||||
extern int key_straferight;
|
||||
|
||||
extern int key_fire;
|
||||
extern int key_use;
|
||||
extern int key_strafe;
|
||||
extern int key_speed;
|
||||
|
||||
extern int mousebfire;
|
||||
extern int mousebstrafe;
|
||||
extern int mousebforward;
|
||||
extern int mousemove;
|
||||
|
||||
extern int joybfire;
|
||||
extern int joybstrafe;
|
||||
extern int joybuse;
|
||||
extern int joybspeed;
|
||||
|
||||
extern int viewwidth;
|
||||
extern int viewheight;
|
||||
|
||||
extern int mouseSensitivity;
|
||||
extern int showMessages;
|
||||
|
||||
extern int detailLevel;
|
||||
|
||||
extern int screenblocks;
|
||||
|
||||
extern int showMessages;
|
||||
|
||||
// machine-independent sound params
|
||||
extern int numChannels;
|
||||
|
||||
extern char* chat_macros[];
|
||||
|
||||
extern byte scantokey[128];
|
||||
|
||||
|
||||
int usemouse;
|
||||
int usejoystick;
|
||||
int crosshair;
|
||||
int always_run;
|
||||
|
||||
|
||||
default_t defaults[] =
|
||||
{
|
||||
{"mouse_sensitivity",&mouseSensitivity, 5},
|
||||
{"sfx_volume",&snd_SfxVolume, 8},
|
||||
{"music_volume",&snd_MusicVolume, 8},
|
||||
{"show_messages",&showMessages, 1},
|
||||
|
||||
{"key_right",&key_right, KEY_RIGHTARROW},
|
||||
{"key_left",&key_left, KEY_LEFTARROW},
|
||||
{"key_up",&key_up, KEY_UPARROW},
|
||||
{"key_down",&key_down, KEY_DOWNARROW},
|
||||
{"key_strafeleft",&key_strafeleft, ','},
|
||||
{"key_straferight",&key_straferight, '.'},
|
||||
|
||||
{"key_fire",&key_fire, KEY_RCTRL},
|
||||
{"key_use",&key_use, ' '},
|
||||
{"key_strafe",&key_strafe, KEY_RALT},
|
||||
{"key_speed",&key_speed, KEY_RSHIFT},
|
||||
|
||||
{"use_mouse",&usemouse, 1},
|
||||
{"mouseb_fire",&mousebfire,0},
|
||||
{"mouseb_strafe",&mousebstrafe,1},
|
||||
{"mouseb_forward",&mousebforward,2},
|
||||
{"mouse_move",&mousemove,0},
|
||||
|
||||
{"use_joystick",&usejoystick, 0},
|
||||
{"joyb_fire",&joybfire,0},
|
||||
{"joyb_strafe",&joybstrafe,1},
|
||||
{"joyb_use",&joybuse,3},
|
||||
{"joyb_speed",&joybspeed,2},
|
||||
|
||||
{"screenblocks",&screenblocks, 9},
|
||||
{"detaillevel",&detailLevel, 0},
|
||||
{"crosshair",&crosshair, 0},
|
||||
{"always_run",&always_run, 0},
|
||||
|
||||
{"snd_channels",&numChannels, 3},
|
||||
|
||||
{"usegamma",&usegamma, 0},
|
||||
|
||||
{"chatmacro0", 0, STRING_VALUE, 0, 0, &chat_macros[0], HUSTR_CHATMACRO0 },
|
||||
{"chatmacro1", 0, STRING_VALUE, 0, 0, &chat_macros[1], HUSTR_CHATMACRO1 },
|
||||
{"chatmacro2", 0, STRING_VALUE, 0, 0, &chat_macros[2], HUSTR_CHATMACRO2 },
|
||||
{"chatmacro3", 0, STRING_VALUE, 0, 0, &chat_macros[3], HUSTR_CHATMACRO3 },
|
||||
{"chatmacro4", 0, STRING_VALUE, 0, 0, &chat_macros[4], HUSTR_CHATMACRO4 },
|
||||
{"chatmacro5", 0, STRING_VALUE, 0, 0, &chat_macros[5], HUSTR_CHATMACRO5 },
|
||||
{"chatmacro6", 0, STRING_VALUE, 0, 0, &chat_macros[6], HUSTR_CHATMACRO6 },
|
||||
{"chatmacro7", 0, STRING_VALUE, 0, 0, &chat_macros[7], HUSTR_CHATMACRO7 },
|
||||
{"chatmacro8", 0, STRING_VALUE, 0, 0, &chat_macros[8], HUSTR_CHATMACRO8 },
|
||||
{"chatmacro9", 0, STRING_VALUE, 0, 0, &chat_macros[9], HUSTR_CHATMACRO9 }
|
||||
};
|
||||
|
||||
|
||||
int numdefaults = sizeof(defaults) / sizeof(default_t);;
|
||||
char* defaultfile;
|
||||
|
||||
|
||||
int M_DrawText(int x, int y, doom_boolean direct, char* string)
|
||||
{
|
||||
int c;
|
||||
int w;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
c = doom_toupper(*string) - HU_FONTSTART;
|
||||
string++;
|
||||
if (c < 0 || c> HU_FONTSIZE)
|
||||
{
|
||||
x += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = SHORT(hu_font[c]->width);
|
||||
if (x + w > SCREENWIDTH)
|
||||
break;
|
||||
if (direct)
|
||||
V_DrawPatchDirect(x, y, 0, hu_font[c]);
|
||||
else
|
||||
V_DrawPatch(x, y, 0, hu_font[c]);
|
||||
x += w;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_WriteFile
|
||||
//
|
||||
doom_boolean M_WriteFile(char const* name, void* source, int length)
|
||||
{
|
||||
void* handle;
|
||||
int count;
|
||||
|
||||
handle = doom_open(name, "wb");
|
||||
|
||||
if (handle == 0)
|
||||
return false;
|
||||
|
||||
count = doom_write(handle, source, length);
|
||||
doom_close(handle);
|
||||
|
||||
if (count < length)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_ReadFile
|
||||
//
|
||||
int M_ReadFile(char const* name, byte** buffer)
|
||||
{
|
||||
void* handle;
|
||||
int count, length;
|
||||
byte* buf;
|
||||
|
||||
handle = doom_open(name, "rb");
|
||||
if (handle == 0)
|
||||
{
|
||||
//I_Error("Error: Couldn't read file %s", name);
|
||||
|
||||
doom_strcpy(error_buf, "Error: Couldn't read file ");
|
||||
doom_concat(error_buf, name);
|
||||
I_Error(error_buf);
|
||||
}
|
||||
doom_seek(handle, 0, DOOM_SEEK_END);
|
||||
length = doom_tell(handle);
|
||||
doom_seek(handle, 0, DOOM_SEEK_SET);
|
||||
buf = Z_Malloc(length, PU_STATIC, 0);
|
||||
count = doom_read(handle, buf, length);
|
||||
doom_close(handle);
|
||||
|
||||
if (count < length)
|
||||
{
|
||||
//I_Error("Error: Couldn't read file %s", name);
|
||||
|
||||
doom_strcpy(error_buf, "Error: Couldn't read file ");
|
||||
doom_concat(error_buf, name);
|
||||
I_Error(error_buf);
|
||||
}
|
||||
|
||||
*buffer = buf;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_SaveDefaults
|
||||
//
|
||||
void M_SaveDefaults(void)
|
||||
{
|
||||
int i;
|
||||
int v;
|
||||
void* f;
|
||||
|
||||
f = doom_open(defaultfile, "w");
|
||||
if (!f)
|
||||
return; // can't write the file, but don't complain
|
||||
|
||||
for (i = 0; i < numdefaults; i++)
|
||||
{
|
||||
if (defaults[i].defaultvalue > -0xfff
|
||||
&& defaults[i].defaultvalue < 0xfff)
|
||||
{
|
||||
v = *defaults[i].location;
|
||||
//fprintf(f, "%s\t\t%i\n", defaults[i].name, v);
|
||||
doom_fprint(f, defaults[i].name);
|
||||
doom_fprint(f, "\t\t");
|
||||
doom_fprint(f, doom_itoa(v, 10));
|
||||
doom_fprint(f, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(f, "%s\t\t\"%s\"\n", defaults[i].name,
|
||||
// *(char**)(defaults[i].text_location));
|
||||
doom_fprint(f, defaults[i].name);
|
||||
doom_fprint(f, "\t\t\"");
|
||||
doom_fprint(f, *(char**)(defaults[i].text_location));
|
||||
doom_fprint(f, "\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
doom_close(f);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_LoadDefaults
|
||||
//
|
||||
void M_LoadDefaults(void)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
void* f;
|
||||
char def[80];
|
||||
char strparm[100];
|
||||
char* newstring;
|
||||
int parm;
|
||||
doom_boolean isstring;
|
||||
|
||||
// set everything to base values
|
||||
// numdefaults = sizeof(defaults)/sizeof(defaults[0]);
|
||||
for (i = 0; i < numdefaults; i++)
|
||||
{
|
||||
if (defaults[i].defaultvalue == 0xFFFF)
|
||||
*defaults[i].text_location = defaults[i].default_text_value;
|
||||
else
|
||||
*defaults[i].location = (int)defaults[i].defaultvalue;
|
||||
}
|
||||
|
||||
// check for a custom default file
|
||||
i = M_CheckParm("-config");
|
||||
if (i && i < myargc - 1)
|
||||
{
|
||||
defaultfile = myargv[i + 1];
|
||||
//doom_print(" default file: %s\n", defaultfile);
|
||||
doom_print(" default file: ");
|
||||
doom_print(defaultfile);
|
||||
doom_print("\n");
|
||||
}
|
||||
else
|
||||
defaultfile = basedefault;
|
||||
|
||||
// read the file in, overriding any set defaults
|
||||
f = doom_open(defaultfile, "r");
|
||||
if (f)
|
||||
{
|
||||
while (!doom_eof(f))
|
||||
{
|
||||
// def
|
||||
int arg_read = 0;
|
||||
char c;
|
||||
for (i = 0; i < 79; ++i)
|
||||
{
|
||||
doom_read(f, &c, 1);
|
||||
if (c == ' ' || c == '\n' || c == '\t')
|
||||
{
|
||||
if (i > 0) arg_read++;
|
||||
break;
|
||||
}
|
||||
def[i] = c;
|
||||
}
|
||||
def[i] = '\0';
|
||||
|
||||
// Ignore spaces
|
||||
if (c != '\n')
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
doom_read(f, &c, 1);
|
||||
if (c != ' ' && c != '\t') break;
|
||||
}
|
||||
|
||||
// strparam
|
||||
i = 0;
|
||||
if (c != '\n')
|
||||
{
|
||||
for (; i < 260;)
|
||||
{
|
||||
strparm[i++] = c;
|
||||
doom_read(f, &c, 1);
|
||||
if (c == '\n')
|
||||
{
|
||||
if (i > 0) arg_read++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
strparm[i] = '\0';
|
||||
}
|
||||
|
||||
isstring = false;
|
||||
//if (fscanf(f, "%79s %[^\n]\n", def, strparm) == 2)
|
||||
if (arg_read == 2)
|
||||
{
|
||||
if (strparm[0] == '"')
|
||||
{
|
||||
// get a string default
|
||||
isstring = true;
|
||||
len = (int)doom_strlen(strparm);
|
||||
newstring = (char*)doom_malloc(len);
|
||||
strparm[len - 1] = 0;
|
||||
doom_strcpy(newstring, strparm + 1);
|
||||
}
|
||||
else if (strparm[0] == '0' && strparm[1] == 'x')
|
||||
{
|
||||
//sscanf(strparm + 2, "%x", &parm);
|
||||
parm = doom_atox(strparm + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sscanf(strparm, "%i", &parm);
|
||||
parm = doom_atoi(strparm);
|
||||
}
|
||||
for (i = 0; i < numdefaults; i++)
|
||||
if (!doom_strcmp(def, defaults[i].name))
|
||||
{
|
||||
if (!isstring)
|
||||
*defaults[i].location = parm;
|
||||
else
|
||||
*defaults[i].text_location = newstring;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doom_close(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// WritePCXfile
|
||||
//
|
||||
void WritePCXfile(char* filename, byte* data, int width, int height, byte* palette)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
pcx_t* pcx;
|
||||
byte* pack;
|
||||
|
||||
pcx = Z_Malloc(width * height * 2 + 1000, PU_STATIC, 0);
|
||||
|
||||
pcx->manufacturer = 0x0a; // PCX id
|
||||
pcx->version = 5; // 256 color
|
||||
pcx->encoding = 1; // uncompressed
|
||||
pcx->bits_per_pixel = 8; // 256 color
|
||||
pcx->xmin = 0;
|
||||
pcx->ymin = 0;
|
||||
pcx->xmax = SHORT(width - 1);
|
||||
pcx->ymax = SHORT(height - 1);
|
||||
pcx->hres = SHORT(width);
|
||||
pcx->vres = SHORT(height);
|
||||
doom_memset(pcx->palette, 0, sizeof(pcx->palette));
|
||||
pcx->color_planes = 1; // chunky image
|
||||
pcx->bytes_per_line = SHORT(width);
|
||||
pcx->palette_type = SHORT(2); // not a grey scale
|
||||
doom_memset(pcx->filler, 0, sizeof(pcx->filler));
|
||||
|
||||
// pack the image
|
||||
pack = &pcx->data;
|
||||
|
||||
for (i = 0; i < width * height; i++)
|
||||
{
|
||||
if ((*data & 0xc0) != 0xc0)
|
||||
*pack++ = *data++;
|
||||
else
|
||||
{
|
||||
*pack++ = 0xc1;
|
||||
*pack++ = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
// write the palette
|
||||
*pack++ = 0x0c; // palette ID byte
|
||||
for (i = 0; i < 768; i++)
|
||||
*pack++ = *palette++;
|
||||
|
||||
// write output file
|
||||
length = (int)(pack - (byte*)pcx);
|
||||
M_WriteFile(filename, pcx, length);
|
||||
|
||||
Z_Free(pcx);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// M_ScreenShot
|
||||
//
|
||||
void M_ScreenShot(void)
|
||||
{
|
||||
int i;
|
||||
byte* linear;
|
||||
char lbmname[12];
|
||||
void* f;
|
||||
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
I_ReadScreen(linear);
|
||||
|
||||
// find a file name to save it to
|
||||
doom_strcpy(lbmname, "DOOM00.pcx");
|
||||
|
||||
for (i = 0; i <= 99; i++)
|
||||
{
|
||||
lbmname[4] = i / 10 + '0';
|
||||
lbmname[5] = i % 10 + '0';
|
||||
if ((f = doom_open(lbmname, "wb")) == 0)
|
||||
break; // file doesn't exist
|
||||
doom_close(f);
|
||||
}
|
||||
if (i == 100)
|
||||
I_Error("Error: M_ScreenShot: Couldn't create a PCX");
|
||||
|
||||
// save the pcx file
|
||||
WritePCXfile(lbmname, linear,
|
||||
SCREENWIDTH, SCREENHEIGHT,
|
||||
W_CacheLumpName("PLAYPAL", PU_CACHE));
|
||||
|
||||
players[consoleplayer].message = "screen shot";
|
||||
}
|
58
src/DOOM/m_misc.h
Normal file
58
src/DOOM/m_misc.h
Normal file
@ -0,0 +1,58 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_MISC__
|
||||
#define __M_MISC__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
char* name;
|
||||
int* location;
|
||||
int defaultvalue;
|
||||
int scantranslate; // PC scan code hack
|
||||
int untranslated; // lousy hack
|
||||
char** text_location; // [pd] int* location was used to store text pointer. Can't change to intptr_t unless we change all settings type
|
||||
char* default_text_value; // [pd] So we don't change defaultvalue behavior for int to intptr_t
|
||||
} default_t;
|
||||
|
||||
|
||||
doom_boolean M_WriteFile(char const* name, void* source, int length);
|
||||
int M_ReadFile(char const* name, byte** buffer);
|
||||
void M_ScreenShot(void);
|
||||
void M_LoadDefaults(void);
|
||||
void M_SaveDefaults(void);
|
||||
int M_DrawText(int x, int y, doom_boolean direct, char* string);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
77
src/DOOM/m_random.c
Normal file
77
src/DOOM/m_random.c
Normal file
@ -0,0 +1,77 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Random number LUT.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
//
|
||||
// M_Random
|
||||
// Returns a 0-255 number
|
||||
//
|
||||
unsigned char rndtable[256] = {
|
||||
0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 ,
|
||||
74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 ,
|
||||
95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 ,
|
||||
52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 ,
|
||||
149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 ,
|
||||
145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 ,
|
||||
175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 ,
|
||||
25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 ,
|
||||
94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 ,
|
||||
136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 ,
|
||||
135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 ,
|
||||
80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 ,
|
||||
24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 ,
|
||||
145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 ,
|
||||
28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 ,
|
||||
71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 ,
|
||||
17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 ,
|
||||
197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 ,
|
||||
120, 163, 236, 249
|
||||
};
|
||||
|
||||
|
||||
int rndindex = 0;
|
||||
int prndindex = 0;
|
||||
|
||||
|
||||
// Which one is deterministic?
|
||||
int P_Random(void)
|
||||
{
|
||||
prndindex = (prndindex + 1) & 0xff;
|
||||
return rndtable[prndindex];
|
||||
}
|
||||
|
||||
|
||||
int M_Random(void)
|
||||
{
|
||||
rndindex = (rndindex + 1) & 0xff;
|
||||
return rndtable[rndindex];
|
||||
}
|
||||
|
||||
|
||||
void M_ClearRandom(void)
|
||||
{
|
||||
rndindex = prndindex = 0;
|
||||
}
|
46
src/DOOM/m_random.h
Normal file
46
src/DOOM/m_random.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_RANDOM__
|
||||
#define __M_RANDOM__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
// Returns a number from 0 to 255,
|
||||
// from a lookup table.
|
||||
int M_Random(void);
|
||||
|
||||
// As M_Random, but used only by the play simulation.
|
||||
int P_Random(void);
|
||||
|
||||
// Fix randoms for demos.
|
||||
void M_ClearRandom(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
53
src/DOOM/m_swap.c
Normal file
53
src/DOOM/m_swap.c
Normal file
@ -0,0 +1,53 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Endianess handling, swapping 16bit and 32bit.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "m_swap.h"
|
||||
|
||||
|
||||
// Not needed with big endian.
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
|
||||
// Swap 16bit, that is, MSB and LSB byte.
|
||||
unsigned short SwapSHORT(unsigned short x)
|
||||
{
|
||||
// No masking with 0xFF should be necessary.
|
||||
return (x >> 8) | (x << 8);
|
||||
}
|
||||
|
||||
|
||||
// Swapping 32bit.
|
||||
unsigned long SwapLONG(unsigned long x)
|
||||
{
|
||||
return
|
||||
(x >> 24)
|
||||
| ((x >> 8) & 0xff00)
|
||||
| ((x << 8) & 0xff0000)
|
||||
| (x << 24);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
45
src/DOOM/m_swap.h
Normal file
45
src/DOOM/m_swap.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Endianess handling, swapping 16bit and 32bit.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __M_SWAP__
|
||||
#define __M_SWAP__
|
||||
|
||||
|
||||
// Endianess handling.
|
||||
// WAD files are stored little endian.
|
||||
#ifdef __BIG_ENDIAN__
|
||||
unsigned short SwapSHORT(unsigned short);
|
||||
unsigned long SwapLONG(unsigned long);
|
||||
#define SHORT(x) ((short)SwapSHORT((unsigned short) (x)))
|
||||
#define LONG(x) ((long)SwapLONG((unsigned long) (x)))
|
||||
#else
|
||||
#define SHORT(x) (x)
|
||||
#define LONG(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
322
src/DOOM/p_ceilng.c
Normal file
322
src/DOOM/p_ceilng.c
Normal file
@ -0,0 +1,322 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
#include "sounds.h" // Data.
|
||||
|
||||
|
||||
//
|
||||
// CEILINGS
|
||||
//
|
||||
|
||||
ceiling_t* activeceilings[MAXCEILINGS];
|
||||
|
||||
|
||||
//
|
||||
// T_MoveCeiling
|
||||
//
|
||||
void T_MoveCeiling(ceiling_t* ceiling)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch (ceiling->direction)
|
||||
{
|
||||
case 0:
|
||||
// IN STASIS
|
||||
break;
|
||||
case 1:
|
||||
// UP
|
||||
res = T_MovePlane(ceiling->sector,
|
||||
ceiling->speed,
|
||||
ceiling->topheight,
|
||||
false, 1, ceiling->direction);
|
||||
|
||||
if (!(leveltime & 7))
|
||||
{
|
||||
switch (ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
break;
|
||||
default:
|
||||
S_StartSound((mobj_t*)&ceiling->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
// ?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch (ceiling->type)
|
||||
{
|
||||
case raiseToHighest:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
case silentCrushAndRaise:
|
||||
S_StartSound((mobj_t*)&ceiling->sector->soundorg,
|
||||
sfx_pstop);
|
||||
case fastCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
ceiling->direction = -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
// DOWN
|
||||
res = T_MovePlane(ceiling->sector,
|
||||
ceiling->speed,
|
||||
ceiling->bottomheight,
|
||||
ceiling->crush, 1, ceiling->direction);
|
||||
|
||||
if (!(leveltime & 7))
|
||||
{
|
||||
switch (ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise: break;
|
||||
default:
|
||||
S_StartSound((mobj_t*)&ceiling->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch (ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
S_StartSound((mobj_t*)&ceiling->sector->soundorg,
|
||||
sfx_pstop);
|
||||
case crushAndRaise:
|
||||
ceiling->speed = CEILSPEED;
|
||||
case fastCrushAndRaise:
|
||||
ceiling->direction = 1;
|
||||
break;
|
||||
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // ( res != pastdest )
|
||||
{
|
||||
if (res == crushed)
|
||||
{
|
||||
switch (ceiling->type)
|
||||
{
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
case lowerAndCrush:
|
||||
ceiling->speed = CEILSPEED / 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_DoCeiling
|
||||
// Move a ceiling up/down and all around!
|
||||
//
|
||||
int EV_DoCeiling(line_t* line, ceiling_e type)
|
||||
{
|
||||
int secnum;
|
||||
int rtn;
|
||||
sector_t* sec;
|
||||
ceiling_t* ceiling;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
// Reactivate in-stasis ceilings...for certain types.
|
||||
switch (type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
P_ActivateInStasisCeiling(line);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
sec->specialdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
||||
ceiling->sector = sec;
|
||||
ceiling->crush = false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT);
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED * 2;
|
||||
break;
|
||||
|
||||
case silentCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
ceiling->bottomheight = sec->floorheight;
|
||||
if (type != lowerToFloor)
|
||||
ceiling->bottomheight += 8 * FRACUNIT;
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
|
||||
case raiseToHighest:
|
||||
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
||||
ceiling->direction = 1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
}
|
||||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
P_AddActiveCeiling(ceiling);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Add an active ceiling
|
||||
//
|
||||
void P_AddActiveCeiling(ceiling_t* c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXCEILINGS; i++)
|
||||
{
|
||||
if (activeceilings[i] == 0)
|
||||
{
|
||||
activeceilings[i] = c;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Remove a ceiling's thinker
|
||||
//
|
||||
void P_RemoveActiveCeiling(ceiling_t* c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXCEILINGS; i++)
|
||||
{
|
||||
if (activeceilings[i] == c)
|
||||
{
|
||||
activeceilings[i]->sector->specialdata = 0;
|
||||
P_RemoveThinker(&activeceilings[i]->thinker);
|
||||
activeceilings[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Restart a ceiling that's in-stasis
|
||||
//
|
||||
void P_ActivateInStasisCeiling(line_t* line)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXCEILINGS; i++)
|
||||
{
|
||||
if (activeceilings[i]
|
||||
&& (activeceilings[i]->tag == line->tag)
|
||||
&& (activeceilings[i]->direction == 0))
|
||||
{
|
||||
activeceilings[i]->direction = activeceilings[i]->olddirection;
|
||||
activeceilings[i]->thinker.function.acp1
|
||||
= (actionf_p1)T_MoveCeiling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_CeilingCrushStop
|
||||
// Stop a ceiling from crushing!
|
||||
//
|
||||
int EV_CeilingCrushStop(line_t* line)
|
||||
{
|
||||
int i;
|
||||
int rtn;
|
||||
|
||||
rtn = 0;
|
||||
for (i = 0; i < MAXCEILINGS; i++)
|
||||
{
|
||||
if (activeceilings[i]
|
||||
&& (activeceilings[i]->tag == line->tag)
|
||||
&& (activeceilings[i]->direction != 0))
|
||||
{
|
||||
activeceilings[i]->olddirection = activeceilings[i]->direction;
|
||||
activeceilings[i]->thinker.function.acv = (actionf_v)0;
|
||||
activeceilings[i]->direction = 0; // in-stasis
|
||||
rtn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
517
src/DOOM/p_doors.c
Normal file
517
src/DOOM/p_doors.c
Normal file
@ -0,0 +1,517 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION: Door animation code (opening/closing)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
#include "dstrings.h" // Data.
|
||||
#include "sounds.h" // Data.
|
||||
|
||||
|
||||
//
|
||||
// VERTICAL DOORS
|
||||
//
|
||||
|
||||
//
|
||||
// T_VerticalDoor
|
||||
//
|
||||
void T_VerticalDoor(vldoor_t* door)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch (door->direction)
|
||||
{
|
||||
case 0:
|
||||
// WAITING
|
||||
if (!--door->topcountdown)
|
||||
{
|
||||
switch (door->type)
|
||||
{
|
||||
case blazeRaise:
|
||||
door->direction = -1; // time to go back down
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_bdcls);
|
||||
break;
|
||||
|
||||
case door_normal:
|
||||
door->direction = -1; // time to go back down
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_dorcls);
|
||||
break;
|
||||
|
||||
case close30ThenOpen:
|
||||
door->direction = 1;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// INITIAL WAIT
|
||||
if (!--door->topcountdown)
|
||||
{
|
||||
switch (door->type)
|
||||
{
|
||||
case raiseIn5Mins:
|
||||
door->direction = 1;
|
||||
door->type = door_normal;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
// DOWN
|
||||
res = T_MovePlane(door->sector,
|
||||
door->speed,
|
||||
door->sector->floorheight,
|
||||
false, 1, door->direction);
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch (door->type)
|
||||
{
|
||||
case blazeRaise:
|
||||
case blazeClose:
|
||||
door->sector->specialdata = 0;
|
||||
P_RemoveThinker(&door->thinker); // unlink and free
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_bdcls);
|
||||
break;
|
||||
|
||||
case door_normal:
|
||||
case door_close:
|
||||
door->sector->specialdata = 0;
|
||||
P_RemoveThinker(&door->thinker); // unlink and free
|
||||
break;
|
||||
|
||||
case close30ThenOpen:
|
||||
door->direction = 0;
|
||||
door->topcountdown = 35 * 30;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (res == crushed)
|
||||
{
|
||||
switch (door->type)
|
||||
{
|
||||
case blazeClose:
|
||||
case door_close: // DO NOT GO BACK UP!
|
||||
break;
|
||||
|
||||
default:
|
||||
door->direction = 1;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_doropn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
res = T_MovePlane(door->sector,
|
||||
door->speed,
|
||||
door->topheight,
|
||||
false, 1, door->direction);
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
switch (door->type)
|
||||
{
|
||||
case blazeRaise:
|
||||
case door_normal:
|
||||
door->direction = 0; // wait at top
|
||||
door->topcountdown = door->topwait;
|
||||
break;
|
||||
|
||||
case close30ThenOpen:
|
||||
case blazeOpen:
|
||||
case door_open:
|
||||
door->sector->specialdata = 0;
|
||||
P_RemoveThinker(&door->thinker); // unlink and free
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_DoLockedDoor
|
||||
// Move a locked door up/down
|
||||
//
|
||||
int EV_DoLockedDoor(line_t* line, vldoor_e type, mobj_t* thing)
|
||||
{
|
||||
player_t* p;
|
||||
|
||||
p = thing->player;
|
||||
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
switch (line->special)
|
||||
{
|
||||
case 99: // Blue Lock
|
||||
case 133:
|
||||
if (!p)
|
||||
return 0;
|
||||
if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
|
||||
{
|
||||
p->message = PD_BLUEO;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 134: // Red Lock
|
||||
case 135:
|
||||
if (!p)
|
||||
return 0;
|
||||
if (!p->cards[it_redcard] && !p->cards[it_redskull])
|
||||
{
|
||||
p->message = PD_REDO;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 136: // Yellow Lock
|
||||
case 137:
|
||||
if (!p)
|
||||
return 0;
|
||||
if (!p->cards[it_yellowcard] &&
|
||||
!p->cards[it_yellowskull])
|
||||
{
|
||||
p->message = PD_YELLOWO;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return EV_DoDoor(line, type);
|
||||
}
|
||||
|
||||
|
||||
int EV_DoDoor(line_t* line, vldoor_e type)
|
||||
{
|
||||
int secnum, rtn;
|
||||
sector_t* sec;
|
||||
vldoor_t* door;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
|
||||
// new door thinker
|
||||
rtn = 1;
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->type = type;
|
||||
door->topwait = VDOORWAIT;
|
||||
door->speed = VDOORSPEED;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case blazeClose:
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
door->direction = -1;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_bdcls);
|
||||
break;
|
||||
|
||||
case door_close:
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
door->direction = -1;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_dorcls);
|
||||
break;
|
||||
|
||||
case close30ThenOpen:
|
||||
door->topheight = sec->ceilingheight;
|
||||
door->direction = -1;
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_dorcls);
|
||||
break;
|
||||
|
||||
case blazeRaise:
|
||||
case blazeOpen:
|
||||
door->direction = 1;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
if (door->topheight != sec->ceilingheight)
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_bdopn);
|
||||
break;
|
||||
|
||||
case door_normal:
|
||||
case door_open:
|
||||
door->direction = 1;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
if (door->topheight != sec->ceilingheight)
|
||||
S_StartSound((mobj_t*)&door->sector->soundorg,
|
||||
sfx_doropn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// EV_VerticalDoor : open a door manually, no tag value
|
||||
//
|
||||
void EV_VerticalDoor(line_t* line, mobj_t* thing)
|
||||
{
|
||||
player_t* player;
|
||||
int secnum;
|
||||
sector_t* sec;
|
||||
vldoor_t* door;
|
||||
int side;
|
||||
|
||||
side = 0; // only front sides can be used
|
||||
|
||||
// Check for locks
|
||||
player = thing->player;
|
||||
|
||||
switch (line->special)
|
||||
{
|
||||
case 26: // Blue Lock
|
||||
case 32:
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
|
||||
{
|
||||
player->message = PD_BLUEK;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 27: // Yellow Lock
|
||||
case 34:
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!player->cards[it_yellowcard] &&
|
||||
!player->cards[it_yellowskull])
|
||||
{
|
||||
player->message = PD_YELLOWK;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 28: // Red Lock
|
||||
case 33:
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (!player->cards[it_redcard] && !player->cards[it_redskull])
|
||||
{
|
||||
player->message = PD_REDK;
|
||||
S_StartSound(0, sfx_oof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if the sector has an active thinker, use it
|
||||
sec = sides[line->sidenum[side ^ 1]].sector;
|
||||
secnum = (int)(sec - sectors);
|
||||
|
||||
if (sec->specialdata)
|
||||
{
|
||||
door = sec->specialdata;
|
||||
switch (line->special)
|
||||
{
|
||||
case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 117:
|
||||
if (door->direction == -1)
|
||||
door->direction = 1; // go back up
|
||||
else
|
||||
{
|
||||
if (!thing->player)
|
||||
return; // JDC: bad guys never close doors
|
||||
|
||||
door->direction = -1; // start going down immediately
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// for proper sound
|
||||
switch (line->special)
|
||||
{
|
||||
case 117: // BLAZING DOOR RAISE
|
||||
case 118: // BLAZING DOOR OPEN
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_bdopn);
|
||||
break;
|
||||
|
||||
case 1: // NORMAL DOOR SOUND
|
||||
case 31:
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_doropn);
|
||||
break;
|
||||
|
||||
default: // LOCKED DOOR SOUND
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_doropn);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// new door thinker
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 1;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topwait = VDOORWAIT;
|
||||
|
||||
switch (line->special)
|
||||
{
|
||||
case 1:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
door->type = door_normal;
|
||||
break;
|
||||
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
door->type = door_open;
|
||||
line->special = 0;
|
||||
break;
|
||||
|
||||
case 117: // blazing door raise
|
||||
door->type = blazeRaise;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
break;
|
||||
case 118: // blazing door open
|
||||
door->type = blazeOpen;
|
||||
line->special = 0;
|
||||
door->speed = VDOORSPEED * 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// find the top and bottom of the movement range
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Spawn a door that closes after 30 seconds
|
||||
//
|
||||
void P_SpawnDoorCloseIn30(sector_t* sec)
|
||||
{
|
||||
vldoor_t* door;
|
||||
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&door->thinker);
|
||||
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 0;
|
||||
door->type = door_normal;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topcountdown = 30 * 35;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Spawn a door that opens after 5 minutes
|
||||
//
|
||||
void P_SpawnDoorRaiseIn5Mins(sector_t* sec, int secnum)
|
||||
{
|
||||
vldoor_t* door;
|
||||
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&door->thinker);
|
||||
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 2;
|
||||
door->type = raiseIn5Mins;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4 * FRACUNIT;
|
||||
door->topwait = VDOORWAIT;
|
||||
door->topcountdown = 5 * 60 * 35;
|
||||
}
|
1957
src/DOOM/p_enemy.c
Normal file
1957
src/DOOM/p_enemy.c
Normal file
File diff suppressed because it is too large
Load Diff
541
src/DOOM/p_floor.c
Normal file
541
src/DOOM/p_floor.c
Normal file
@ -0,0 +1,541 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Floor animation: raising stairs.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
#include "sounds.h" // Data.
|
||||
|
||||
|
||||
//
|
||||
// FLOORS
|
||||
//
|
||||
|
||||
//
|
||||
// Move a plane (floor or ceiling) and check for crushing
|
||||
//
|
||||
result_e T_MovePlane(sector_t* sector,
|
||||
fixed_t speed,
|
||||
fixed_t dest,
|
||||
doom_boolean crush,
|
||||
int floorOrCeiling,
|
||||
int direction)
|
||||
{
|
||||
doom_boolean flag;
|
||||
fixed_t lastpos;
|
||||
|
||||
switch (floorOrCeiling)
|
||||
{
|
||||
case 0:
|
||||
// FLOOR
|
||||
switch (direction)
|
||||
{
|
||||
case -1:
|
||||
// DOWN
|
||||
if (sector->floorheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight -= speed;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
if (sector->floorheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// COULD GET CRUSHED
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight += speed;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// CEILING
|
||||
switch (direction)
|
||||
{
|
||||
case -1:
|
||||
// DOWN
|
||||
if (sector->ceilingheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// COULD GET CRUSHED
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight -= speed;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
if (sector->ceilingheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight += speed;
|
||||
flag = P_ChangeSector(sector, crush);
|
||||
// UNUSED
|
||||
#if 0
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector, crush);
|
||||
return crushed;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
|
||||
//
|
||||
void T_MoveFloor(floormove_t* floor)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
res = T_MovePlane(floor->sector,
|
||||
floor->speed,
|
||||
floor->floordestheight,
|
||||
floor->crush, 0, floor->direction);
|
||||
|
||||
if (!(leveltime & 7))
|
||||
S_StartSound((mobj_t*)&floor->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
floor->sector->specialdata = 0;
|
||||
|
||||
if (floor->direction == 1)
|
||||
{
|
||||
switch (floor->type)
|
||||
{
|
||||
case donutRaise:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (floor->direction == -1)
|
||||
{
|
||||
switch (floor->type)
|
||||
{
|
||||
case lowerAndChange:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
P_RemoveThinker(&floor->thinker);
|
||||
|
||||
S_StartSound((mobj_t*)&floor->sector->soundorg,
|
||||
sfx_pstop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// HANDLE FLOOR TYPES
|
||||
//
|
||||
int EV_DoFloor(line_t* line, floor_e floortype)
|
||||
{
|
||||
int secnum;
|
||||
int rtn;
|
||||
int i;
|
||||
sector_t* sec;
|
||||
floormove_t* floor;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new floor thinker
|
||||
rtn = 1;
|
||||
floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
|
||||
floor->type = floortype;
|
||||
floor->crush = false;
|
||||
|
||||
switch (floortype)
|
||||
{
|
||||
case lowerFloor:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
break;
|
||||
|
||||
case lowerFloorToLowest:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
break;
|
||||
|
||||
case turboLower:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED * 4;
|
||||
floor->floordestheight =
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
if (floor->floordestheight != sec->floorheight)
|
||||
floor->floordestheight += 8 * FRACUNIT;
|
||||
break;
|
||||
|
||||
case raiseFloorCrush:
|
||||
floor->crush = true;
|
||||
case raiseFloor:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestCeilingSurrounding(sec);
|
||||
if (floor->floordestheight > sec->ceilingheight)
|
||||
floor->floordestheight = sec->ceilingheight;
|
||||
floor->floordestheight -= (8 * FRACUNIT) *
|
||||
(floortype == raiseFloorCrush);
|
||||
break;
|
||||
|
||||
case raiseFloorTurbo:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED * 4;
|
||||
floor->floordestheight =
|
||||
P_FindNextHighestFloor(sec, sec->floorheight);
|
||||
break;
|
||||
|
||||
case raiseFloorToNearest:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindNextHighestFloor(sec, sec->floorheight);
|
||||
break;
|
||||
|
||||
case raiseFloor24:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
break;
|
||||
case raiseFloor512:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
512 * FRACUNIT;
|
||||
break;
|
||||
|
||||
case raiseFloor24AndChange:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
sec->floorpic = line->frontsector->floorpic;
|
||||
sec->special = line->frontsector->special;
|
||||
break;
|
||||
|
||||
case raiseToTexture:
|
||||
{
|
||||
int minsize = DOOM_MAXINT;
|
||||
side_t* side;
|
||||
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
if (twoSided(secnum, i))
|
||||
{
|
||||
side = getSide(secnum, i, 0);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
side = getSide(secnum, i, 1);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
}
|
||||
}
|
||||
floor->floordestheight =
|
||||
floor->sector->floorheight + minsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case lowerAndChange:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
floor->texture = sec->floorpic;
|
||||
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
if (twoSided(secnum, i))
|
||||
{
|
||||
if (getSide(secnum, i, 0)->sector - sectors == secnum)
|
||||
{
|
||||
sec = getSector(secnum, i, 1);
|
||||
|
||||
if (sec->floorheight == floor->floordestheight)
|
||||
{
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = getSector(secnum, i, 0);
|
||||
|
||||
if (sec->floorheight == floor->floordestheight)
|
||||
{
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// BUILD A STAIRCASE!
|
||||
//
|
||||
int EV_BuildStairs(line_t* line, stair_e type)
|
||||
{
|
||||
int secnum;
|
||||
int height;
|
||||
int i;
|
||||
int newsecnum;
|
||||
int texture;
|
||||
int ok;
|
||||
int rtn;
|
||||
|
||||
sector_t* sec;
|
||||
sector_t* tsec;
|
||||
|
||||
floormove_t* floor;
|
||||
|
||||
fixed_t stairsize;
|
||||
fixed_t speed;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// new floor thinker
|
||||
rtn = 1;
|
||||
floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
switch (type)
|
||||
{
|
||||
case build8:
|
||||
speed = FLOORSPEED / 4;
|
||||
stairsize = 8 * FRACUNIT;
|
||||
break;
|
||||
case turbo16:
|
||||
speed = FLOORSPEED * 4;
|
||||
stairsize = 16 * FRACUNIT;
|
||||
break;
|
||||
}
|
||||
floor->speed = speed;
|
||||
height = sec->floorheight + stairsize;
|
||||
floor->floordestheight = height;
|
||||
|
||||
texture = sec->floorpic;
|
||||
|
||||
// Find next sector to raise
|
||||
// 1. Find 2-sided line with same sector side[0]
|
||||
// 2. Other side is the next sector to raise
|
||||
do
|
||||
{
|
||||
ok = 0;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
if (!((sec->lines[i])->flags & ML_TWOSIDED))
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->frontsector;
|
||||
newsecnum = (int)(tsec - sectors);
|
||||
|
||||
if (secnum != newsecnum)
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->backsector;
|
||||
newsecnum = (int)(tsec - sectors);
|
||||
|
||||
if (tsec->floorpic != texture)
|
||||
continue;
|
||||
|
||||
height += stairsize;
|
||||
|
||||
if (tsec->specialdata)
|
||||
continue;
|
||||
|
||||
sec = tsec;
|
||||
secnum = newsecnum;
|
||||
floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&floor->thinker);
|
||||
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = speed;
|
||||
floor->floordestheight = height;
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
} while (ok);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
924
src/DOOM/p_inter.c
Normal file
924
src/DOOM/p_inter.c
Normal file
@ -0,0 +1,924 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Handling interactions (i.e., collisions).
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
|
||||
// Data.
|
||||
#include "doomdef.h"
|
||||
#include "dstrings.h"
|
||||
#include "sounds.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
#include "m_random.h"
|
||||
#include "i_system.h"
|
||||
|
||||
#include "am_map.h"
|
||||
|
||||
#include "p_local.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "p_inter.h"
|
||||
#endif
|
||||
#include "p_inter.h"
|
||||
|
||||
|
||||
#define BONUSADD 6
|
||||
|
||||
|
||||
|
||||
|
||||
// a weapon is found with two clip loads,
|
||||
// a big item has five clip loads
|
||||
int maxammo[NUMAMMO] = {200, 50, 300, 50};
|
||||
int clipammo[NUMAMMO] = {10, 4, 20, 1};
|
||||
|
||||
|
||||
//
|
||||
// GET STUFF
|
||||
//
|
||||
|
||||
//
|
||||
// P_GiveAmmo
|
||||
// Num is the number of clip loads,
|
||||
// not the individual count (0= 1/2 clip).
|
||||
// Returns false if the ammo can't be picked up at all
|
||||
//
|
||||
|
||||
doom_boolean
|
||||
P_GiveAmmo
|
||||
( player_t* player,
|
||||
ammotype_t ammo,
|
||||
int num )
|
||||
{
|
||||
int oldammo;
|
||||
|
||||
if (ammo == am_noammo)
|
||||
return false;
|
||||
|
||||
if (ammo < 0 || ammo > NUMAMMO)
|
||||
{
|
||||
//I_Error ("P_GiveAmmo: bad type %i", ammo);
|
||||
|
||||
doom_strcpy(error_buf, "P_GiveAmmo: bad type ");
|
||||
doom_concat(error_buf, doom_itoa(ammo, 10));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
|
||||
if ( player->ammo[ammo] == player->maxammo[ammo] )
|
||||
return false;
|
||||
|
||||
if (num)
|
||||
num *= clipammo[ammo];
|
||||
else
|
||||
num = clipammo[ammo]/2;
|
||||
|
||||
if (gameskill == sk_baby
|
||||
|| gameskill == sk_nightmare)
|
||||
{
|
||||
// give double ammo in trainer mode,
|
||||
// you'll need in nightmare
|
||||
num <<= 1;
|
||||
}
|
||||
|
||||
|
||||
oldammo = player->ammo[ammo];
|
||||
player->ammo[ammo] += num;
|
||||
|
||||
if (player->ammo[ammo] > player->maxammo[ammo])
|
||||
player->ammo[ammo] = player->maxammo[ammo];
|
||||
|
||||
// If non zero ammo,
|
||||
// don't change up weapons,
|
||||
// player was lower on purpose.
|
||||
if (oldammo)
|
||||
return true;
|
||||
|
||||
// We were down to zero,
|
||||
// so select a new weapon.
|
||||
// Preferences are not user selectable.
|
||||
switch (ammo)
|
||||
{
|
||||
case am_clip:
|
||||
if (player->readyweapon == wp_fist)
|
||||
{
|
||||
if (player->weaponowned[wp_chaingun])
|
||||
player->pendingweapon = wp_chaingun;
|
||||
else
|
||||
player->pendingweapon = wp_pistol;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_shell:
|
||||
if (player->readyweapon == wp_fist
|
||||
|| player->readyweapon == wp_pistol)
|
||||
{
|
||||
if (player->weaponowned[wp_shotgun])
|
||||
player->pendingweapon = wp_shotgun;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_cell:
|
||||
if (player->readyweapon == wp_fist
|
||||
|| player->readyweapon == wp_pistol)
|
||||
{
|
||||
if (player->weaponowned[wp_plasma])
|
||||
player->pendingweapon = wp_plasma;
|
||||
}
|
||||
break;
|
||||
|
||||
case am_misl:
|
||||
if (player->readyweapon == wp_fist)
|
||||
{
|
||||
if (player->weaponowned[wp_missile])
|
||||
player->pendingweapon = wp_missile;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GiveWeapon
|
||||
// The weapon name may have a MF_DROPPED flag ored in.
|
||||
//
|
||||
doom_boolean
|
||||
P_GiveWeapon
|
||||
( player_t* player,
|
||||
weapontype_t weapon,
|
||||
doom_boolean dropped )
|
||||
{
|
||||
doom_boolean gaveammo;
|
||||
doom_boolean gaveweapon;
|
||||
|
||||
if (netgame
|
||||
&& (deathmatch!=2)
|
||||
&& !dropped )
|
||||
{
|
||||
// leave placed weapons forever on net games
|
||||
if (player->weaponowned[weapon])
|
||||
return false;
|
||||
|
||||
player->bonuscount += BONUSADD;
|
||||
player->weaponowned[weapon] = true;
|
||||
|
||||
if (deathmatch)
|
||||
P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
|
||||
else
|
||||
P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
||||
player->pendingweapon = weapon;
|
||||
|
||||
if (player == &players[consoleplayer])
|
||||
S_StartSound (0, sfx_wpnup);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (weaponinfo[weapon].ammo != am_noammo)
|
||||
{
|
||||
// give one clip with a dropped weapon,
|
||||
// two clips with a found weapon
|
||||
if (dropped)
|
||||
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
|
||||
else
|
||||
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
|
||||
}
|
||||
else
|
||||
gaveammo = false;
|
||||
|
||||
if (player->weaponowned[weapon])
|
||||
gaveweapon = false;
|
||||
else
|
||||
{
|
||||
gaveweapon = true;
|
||||
player->weaponowned[weapon] = true;
|
||||
player->pendingweapon = weapon;
|
||||
}
|
||||
|
||||
return (gaveweapon || gaveammo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveBody
|
||||
// Returns false if the body isn't needed at all
|
||||
//
|
||||
doom_boolean
|
||||
P_GiveBody
|
||||
( player_t* player,
|
||||
int num )
|
||||
{
|
||||
if (player->health >= MAXHEALTH)
|
||||
return false;
|
||||
|
||||
player->health += num;
|
||||
if (player->health > MAXHEALTH)
|
||||
player->health = MAXHEALTH;
|
||||
player->mo->health = player->health;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveArmor
|
||||
// Returns false if the armor is worse
|
||||
// than the current armor.
|
||||
//
|
||||
doom_boolean
|
||||
P_GiveArmor
|
||||
( player_t* player,
|
||||
int armortype )
|
||||
{
|
||||
int hits;
|
||||
|
||||
hits = armortype*100;
|
||||
if (player->armorpoints >= hits)
|
||||
return false; // don't pick up
|
||||
|
||||
player->armortype = armortype;
|
||||
player->armorpoints = hits;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_GiveCard
|
||||
//
|
||||
void
|
||||
P_GiveCard
|
||||
( player_t* player,
|
||||
card_t card )
|
||||
{
|
||||
if (player->cards[card])
|
||||
return;
|
||||
|
||||
player->bonuscount = BONUSADD;
|
||||
player->cards[card] = 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GivePower
|
||||
//
|
||||
doom_boolean
|
||||
P_GivePower
|
||||
( player_t* player,
|
||||
int /*powertype_t*/ power )
|
||||
{
|
||||
if (power == pw_invulnerability)
|
||||
{
|
||||
player->powers[power] = INVULNTICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_invisibility)
|
||||
{
|
||||
player->powers[power] = INVISTICS;
|
||||
player->mo->flags |= MF_SHADOW;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_infrared)
|
||||
{
|
||||
player->powers[power] = INFRATICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_ironfeet)
|
||||
{
|
||||
player->powers[power] = IRONTICS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (power == pw_strength)
|
||||
{
|
||||
P_GiveBody (player, 100);
|
||||
player->powers[power] = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player->powers[power])
|
||||
return false; // already got it
|
||||
|
||||
player->powers[power] = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_TouchSpecialThing
|
||||
//
|
||||
void
|
||||
P_TouchSpecialThing
|
||||
( mobj_t* special,
|
||||
mobj_t* toucher )
|
||||
{
|
||||
player_t* player;
|
||||
int i;
|
||||
fixed_t delta;
|
||||
int sound;
|
||||
|
||||
delta = special->z - toucher->z;
|
||||
|
||||
if (delta > toucher->height
|
||||
|| delta < -8*FRACUNIT)
|
||||
{
|
||||
// out of reach
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sound = sfx_itemup;
|
||||
player = toucher->player;
|
||||
|
||||
// Dead thing touching.
|
||||
// Can happen with a sliding player corpse.
|
||||
if (toucher->health <= 0)
|
||||
return;
|
||||
|
||||
// Identify by sprite.
|
||||
switch (special->sprite)
|
||||
{
|
||||
// armor
|
||||
case SPR_ARM1:
|
||||
if (!P_GiveArmor (player, 1))
|
||||
return;
|
||||
player->message = GOTARMOR;
|
||||
break;
|
||||
|
||||
case SPR_ARM2:
|
||||
if (!P_GiveArmor (player, 2))
|
||||
return;
|
||||
player->message = GOTMEGA;
|
||||
break;
|
||||
|
||||
// bonus items
|
||||
case SPR_BON1:
|
||||
player->health++; // can go over 100%
|
||||
if (player->health > 200)
|
||||
player->health = 200;
|
||||
player->mo->health = player->health;
|
||||
player->message = GOTHTHBONUS;
|
||||
break;
|
||||
|
||||
case SPR_BON2:
|
||||
player->armorpoints++; // can go over 100%
|
||||
if (player->armorpoints > 200)
|
||||
player->armorpoints = 200;
|
||||
if (!player->armortype)
|
||||
player->armortype = 1;
|
||||
player->message = GOTARMBONUS;
|
||||
break;
|
||||
|
||||
case SPR_SOUL:
|
||||
player->health += 100;
|
||||
if (player->health > 200)
|
||||
player->health = 200;
|
||||
player->mo->health = player->health;
|
||||
player->message = GOTSUPER;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_MEGA:
|
||||
if (gamemode != commercial)
|
||||
return;
|
||||
player->health = 200;
|
||||
player->mo->health = player->health;
|
||||
P_GiveArmor (player,2);
|
||||
player->message = GOTMSPHERE;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
// cards
|
||||
// leave cards for everyone
|
||||
case SPR_BKEY:
|
||||
if (!player->cards[it_bluecard])
|
||||
player->message = GOTBLUECARD;
|
||||
P_GiveCard (player, it_bluecard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_YKEY:
|
||||
if (!player->cards[it_yellowcard])
|
||||
player->message = GOTYELWCARD;
|
||||
P_GiveCard (player, it_yellowcard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_RKEY:
|
||||
if (!player->cards[it_redcard])
|
||||
player->message = GOTREDCARD;
|
||||
P_GiveCard (player, it_redcard);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_BSKU:
|
||||
if (!player->cards[it_blueskull])
|
||||
player->message = GOTBLUESKUL;
|
||||
P_GiveCard (player, it_blueskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_YSKU:
|
||||
if (!player->cards[it_yellowskull])
|
||||
player->message = GOTYELWSKUL;
|
||||
P_GiveCard (player, it_yellowskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
case SPR_RSKU:
|
||||
if (!player->cards[it_redskull])
|
||||
player->message = GOTREDSKULL;
|
||||
P_GiveCard (player, it_redskull);
|
||||
if (!netgame)
|
||||
break;
|
||||
return;
|
||||
|
||||
// medikits, heals
|
||||
case SPR_STIM:
|
||||
if (!P_GiveBody (player, 10))
|
||||
return;
|
||||
player->message = GOTSTIM;
|
||||
break;
|
||||
|
||||
case SPR_MEDI:
|
||||
if (!P_GiveBody (player, 25))
|
||||
return;
|
||||
|
||||
if (player->health < 25)
|
||||
player->message = GOTMEDINEED;
|
||||
else
|
||||
player->message = GOTMEDIKIT;
|
||||
break;
|
||||
|
||||
|
||||
// power ups
|
||||
case SPR_PINV:
|
||||
if (!P_GivePower (player, pw_invulnerability))
|
||||
return;
|
||||
player->message = GOTINVUL;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PSTR:
|
||||
if (!P_GivePower (player, pw_strength))
|
||||
return;
|
||||
player->message = GOTBERSERK;
|
||||
if (player->readyweapon != wp_fist)
|
||||
player->pendingweapon = wp_fist;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PINS:
|
||||
if (!P_GivePower (player, pw_invisibility))
|
||||
return;
|
||||
player->message = GOTINVIS;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_SUIT:
|
||||
if (!P_GivePower (player, pw_ironfeet))
|
||||
return;
|
||||
player->message = GOTSUIT;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PMAP:
|
||||
if (!P_GivePower (player, pw_allmap))
|
||||
return;
|
||||
player->message = GOTMAP;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
case SPR_PVIS:
|
||||
if (!P_GivePower (player, pw_infrared))
|
||||
return;
|
||||
player->message = GOTVISOR;
|
||||
sound = sfx_getpow;
|
||||
break;
|
||||
|
||||
// ammo
|
||||
case SPR_CLIP:
|
||||
if (special->flags & MF_DROPPED)
|
||||
{
|
||||
if (!P_GiveAmmo (player,am_clip,0))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!P_GiveAmmo (player,am_clip,1))
|
||||
return;
|
||||
}
|
||||
player->message = GOTCLIP;
|
||||
break;
|
||||
|
||||
case SPR_AMMO:
|
||||
if (!P_GiveAmmo (player, am_clip,5))
|
||||
return;
|
||||
player->message = GOTCLIPBOX;
|
||||
break;
|
||||
|
||||
case SPR_ROCK:
|
||||
if (!P_GiveAmmo (player, am_misl,1))
|
||||
return;
|
||||
player->message = GOTROCKET;
|
||||
break;
|
||||
|
||||
case SPR_BROK:
|
||||
if (!P_GiveAmmo (player, am_misl,5))
|
||||
return;
|
||||
player->message = GOTROCKBOX;
|
||||
break;
|
||||
|
||||
case SPR_CELL:
|
||||
if (!P_GiveAmmo (player, am_cell,1))
|
||||
return;
|
||||
player->message = GOTCELL;
|
||||
break;
|
||||
|
||||
case SPR_CELP:
|
||||
if (!P_GiveAmmo (player, am_cell,5))
|
||||
return;
|
||||
player->message = GOTCELLBOX;
|
||||
break;
|
||||
|
||||
case SPR_SHEL:
|
||||
if (!P_GiveAmmo (player, am_shell,1))
|
||||
return;
|
||||
player->message = GOTSHELLS;
|
||||
break;
|
||||
|
||||
case SPR_SBOX:
|
||||
if (!P_GiveAmmo (player, am_shell,5))
|
||||
return;
|
||||
player->message = GOTSHELLBOX;
|
||||
break;
|
||||
|
||||
case SPR_BPAK:
|
||||
if (!player->backpack)
|
||||
{
|
||||
for (i=0 ; i<NUMAMMO ; i++)
|
||||
player->maxammo[i] *= 2;
|
||||
player->backpack = true;
|
||||
}
|
||||
for (i=0 ; i<NUMAMMO ; i++)
|
||||
P_GiveAmmo (player, i, 1);
|
||||
player->message = GOTBACKPACK;
|
||||
break;
|
||||
|
||||
// weapons
|
||||
case SPR_BFUG:
|
||||
if (!P_GiveWeapon (player, wp_bfg, false) )
|
||||
return;
|
||||
player->message = GOTBFG9000;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_MGUN:
|
||||
if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
|
||||
return;
|
||||
player->message = GOTCHAINGUN;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_CSAW:
|
||||
if (!P_GiveWeapon (player, wp_chainsaw, false) )
|
||||
return;
|
||||
player->message = GOTCHAINSAW;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_LAUN:
|
||||
if (!P_GiveWeapon (player, wp_missile, false) )
|
||||
return;
|
||||
player->message = GOTLAUNCHER;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_PLAS:
|
||||
if (!P_GiveWeapon (player, wp_plasma, false) )
|
||||
return;
|
||||
player->message = GOTPLASMA;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_SHOT:
|
||||
if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
|
||||
return;
|
||||
player->message = GOTSHOTGUN;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
case SPR_SGN2:
|
||||
if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
|
||||
return;
|
||||
player->message = GOTSHOTGUN2;
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error ("P_SpecialThing: Unknown gettable thing");
|
||||
}
|
||||
|
||||
if (special->flags & MF_COUNTITEM)
|
||||
player->itemcount++;
|
||||
P_RemoveMobj (special);
|
||||
player->bonuscount += BONUSADD;
|
||||
if (player == &players[consoleplayer])
|
||||
S_StartSound (0, sound);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// KillMobj
|
||||
//
|
||||
void
|
||||
P_KillMobj
|
||||
( mobj_t* source,
|
||||
mobj_t* target )
|
||||
{
|
||||
mobjtype_t item;
|
||||
mobj_t* mo;
|
||||
|
||||
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
|
||||
|
||||
if (target->type != MT_SKULL)
|
||||
target->flags &= ~MF_NOGRAVITY;
|
||||
|
||||
target->flags |= MF_CORPSE|MF_DROPOFF;
|
||||
target->height >>= 2;
|
||||
|
||||
if (source && source->player)
|
||||
{
|
||||
// count for intermission
|
||||
if (target->flags & MF_COUNTKILL)
|
||||
source->player->killcount++;
|
||||
|
||||
if (target->player)
|
||||
source->player->frags[target->player-players]++;
|
||||
}
|
||||
else if (!netgame && (target->flags & MF_COUNTKILL) )
|
||||
{
|
||||
// count all monster deaths,
|
||||
// even those caused by other monsters
|
||||
players[0].killcount++;
|
||||
}
|
||||
|
||||
if (target->player)
|
||||
{
|
||||
// count environment kills against you
|
||||
if (!source)
|
||||
target->player->frags[target->player-players]++;
|
||||
|
||||
target->flags &= ~MF_SOLID;
|
||||
target->player->playerstate = PST_DEAD;
|
||||
P_DropWeapon (target->player);
|
||||
|
||||
if (target->player == &players[consoleplayer]
|
||||
&& automapactive)
|
||||
{
|
||||
// don't die in auto map,
|
||||
// switch view prior to dying
|
||||
AM_Stop ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (target->health < -target->info->spawnhealth
|
||||
&& target->info->xdeathstate)
|
||||
{
|
||||
P_SetMobjState (target, target->info->xdeathstate);
|
||||
}
|
||||
else
|
||||
P_SetMobjState (target, target->info->deathstate);
|
||||
target->tics -= P_Random()&3;
|
||||
|
||||
if (target->tics < 1)
|
||||
target->tics = 1;
|
||||
|
||||
// I_StartSound (&actor->r, actor->info->deathsound);
|
||||
|
||||
|
||||
// Drop stuff.
|
||||
// This determines the kind of object spawned
|
||||
// during the death frame of a thing.
|
||||
switch (target->type)
|
||||
{
|
||||
case MT_WOLFSS:
|
||||
case MT_POSSESSED:
|
||||
item = MT_CLIP;
|
||||
break;
|
||||
|
||||
case MT_SHOTGUY:
|
||||
item = MT_SHOTGUN;
|
||||
break;
|
||||
|
||||
case MT_CHAINGUY:
|
||||
item = MT_CHAINGUN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
|
||||
mo->flags |= MF_DROPPED; // special versions of items
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_DamageMobj
|
||||
// Damages both enemies and players
|
||||
// "inflictor" is the thing that caused the damage
|
||||
// creature or missile, can be 0 (slime, etc)
|
||||
// "source" is the thing to target after taking damage
|
||||
// creature or 0
|
||||
// Source and inflictor are the same for melee attacks.
|
||||
// Source can be 0 for slime, barrel explosions
|
||||
// and other environmental stuff.
|
||||
//
|
||||
void
|
||||
P_DamageMobj
|
||||
( mobj_t* target,
|
||||
mobj_t* inflictor,
|
||||
mobj_t* source,
|
||||
int damage )
|
||||
{
|
||||
unsigned ang;
|
||||
int saved;
|
||||
player_t* player;
|
||||
fixed_t thrust;
|
||||
int temp;
|
||||
|
||||
if ( !(target->flags & MF_SHOOTABLE) )
|
||||
return; // shouldn't happen...
|
||||
|
||||
if (target->health <= 0)
|
||||
return;
|
||||
|
||||
if ( target->flags & MF_SKULLFLY )
|
||||
{
|
||||
target->momx = target->momy = target->momz = 0;
|
||||
}
|
||||
|
||||
player = target->player;
|
||||
if (player && gameskill == sk_baby)
|
||||
damage >>= 1; // take half damage in trainer mode
|
||||
|
||||
|
||||
// Some close combat weapons should not
|
||||
// inflict thrust and push the victim out of reach,
|
||||
// thus kick away unless using the chainsaw.
|
||||
if (inflictor
|
||||
&& !(target->flags & MF_NOCLIP)
|
||||
&& (!source
|
||||
|| !source->player
|
||||
|| source->player->readyweapon != wp_chainsaw))
|
||||
{
|
||||
ang = R_PointToAngle2 ( inflictor->x,
|
||||
inflictor->y,
|
||||
target->x,
|
||||
target->y);
|
||||
|
||||
thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
|
||||
|
||||
// make fall forwards sometimes
|
||||
if ( damage < 40
|
||||
&& damage > target->health
|
||||
&& target->z - inflictor->z > 64*FRACUNIT
|
||||
&& (P_Random ()&1) )
|
||||
{
|
||||
ang += ANG180;
|
||||
thrust *= 4;
|
||||
}
|
||||
|
||||
ang >>= ANGLETOFINESHIFT;
|
||||
target->momx += FixedMul (thrust, finecosine[ang]);
|
||||
target->momy += FixedMul (thrust, finesine[ang]);
|
||||
}
|
||||
|
||||
// player specific
|
||||
if (player)
|
||||
{
|
||||
// end of game hell hack
|
||||
if (target->subsector->sector->special == 11
|
||||
&& damage >= target->health)
|
||||
{
|
||||
damage = target->health - 1;
|
||||
}
|
||||
|
||||
|
||||
// Below certain threshold,
|
||||
// ignore damage in GOD mode, or with INVUL power.
|
||||
if ( damage < 1000
|
||||
&& ( (player->cheats&CF_GODMODE)
|
||||
|| player->powers[pw_invulnerability] ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->armortype)
|
||||
{
|
||||
if (player->armortype == 1)
|
||||
saved = damage/3;
|
||||
else
|
||||
saved = damage/2;
|
||||
|
||||
if (player->armorpoints <= saved)
|
||||
{
|
||||
// armor is used up
|
||||
saved = player->armorpoints;
|
||||
player->armortype = 0;
|
||||
}
|
||||
player->armorpoints -= saved;
|
||||
damage -= saved;
|
||||
}
|
||||
player->health -= damage; // mirror mobj health here for Dave
|
||||
if (player->health < 0)
|
||||
player->health = 0;
|
||||
|
||||
player->attacker = source;
|
||||
player->damagecount += damage; // add damage after armor / invuln
|
||||
|
||||
if (player->damagecount > 100)
|
||||
player->damagecount = 100; // teleport stomp does 10k points...
|
||||
|
||||
temp = damage < 100 ? damage : 100;
|
||||
|
||||
if (player == &players[consoleplayer])
|
||||
I_Tactile (40,10,40+temp*2);
|
||||
}
|
||||
|
||||
// do the damage
|
||||
target->health -= damage;
|
||||
if (target->health <= 0)
|
||||
{
|
||||
P_KillMobj (source, target);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (P_Random () < target->info->painchance)
|
||||
&& !(target->flags&MF_SKULLFLY) )
|
||||
{
|
||||
target->flags |= MF_JUSTHIT; // fight back!
|
||||
|
||||
P_SetMobjState (target, target->info->painstate);
|
||||
}
|
||||
|
||||
target->reactiontime = 0; // we're awake now...
|
||||
|
||||
if ( (!target->threshold || target->type == MT_VILE)
|
||||
&& source && source != target
|
||||
&& source->type != MT_VILE)
|
||||
{
|
||||
// if not intent on another player,
|
||||
// chase after this one
|
||||
target->target = source;
|
||||
target->threshold = BASETHRESHOLD;
|
||||
if (target->state == &states[target->info->spawnstate]
|
||||
&& target->info->seestate != S_NULL)
|
||||
P_SetMobjState (target, target->info->seestate);
|
||||
}
|
||||
|
||||
}
|
||||
|
38
src/DOOM/p_inter.h
Normal file
38
src/DOOM/p_inter.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_INTER__
|
||||
#define __P_INTER__
|
||||
|
||||
|
||||
#include "d_player.h"
|
||||
|
||||
|
||||
doom_boolean P_GivePower(player_t*, int);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
333
src/DOOM/p_lights.c
Normal file
333
src/DOOM/p_lights.c
Normal file
@ -0,0 +1,333 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Handle Sector base lighting effects.
|
||||
// Muzzle flash?
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "m_random.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
//
|
||||
// FIRELIGHT FLICKER
|
||||
//
|
||||
|
||||
//
|
||||
// T_FireFlicker
|
||||
//
|
||||
void T_FireFlicker(fireflicker_t* flick)
|
||||
{
|
||||
int amount;
|
||||
|
||||
if (--flick->count)
|
||||
return;
|
||||
|
||||
amount = (P_Random() & 3) * 16;
|
||||
|
||||
if (flick->sector->lightlevel - amount < flick->minlight)
|
||||
flick->sector->lightlevel = flick->minlight;
|
||||
else
|
||||
flick->sector->lightlevel = flick->maxlight - amount;
|
||||
|
||||
flick->count = 4;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnFireFlicker
|
||||
//
|
||||
void P_SpawnFireFlicker(sector_t* sector)
|
||||
{
|
||||
fireflicker_t* flick;
|
||||
|
||||
// Note that we are resetting sector attributes.
|
||||
// Nothing special about it during gameplay.
|
||||
sector->special = 0;
|
||||
|
||||
flick = Z_Malloc(sizeof(*flick), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&flick->thinker);
|
||||
|
||||
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
|
||||
flick->sector = sector;
|
||||
flick->maxlight = sector->lightlevel;
|
||||
flick->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel) + 16;
|
||||
flick->count = 4;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// BROKEN LIGHT FLASHING
|
||||
//
|
||||
|
||||
//
|
||||
// T_LightFlash
|
||||
// Do flashing lights.
|
||||
//
|
||||
void T_LightFlash(lightflash_t* flash)
|
||||
{
|
||||
if (--flash->count)
|
||||
return;
|
||||
|
||||
if (flash->sector->lightlevel == flash->maxlight)
|
||||
{
|
||||
flash->sector->lightlevel = flash->minlight;
|
||||
flash->count = (P_Random() & flash->mintime) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash->sector->lightlevel = flash->maxlight;
|
||||
flash->count = (P_Random() & flash->maxtime) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnLightFlash
|
||||
// After the map has been loaded, scan each sector
|
||||
// for specials that spawn thinkers
|
||||
//
|
||||
void P_SpawnLightFlash(sector_t* sector)
|
||||
{
|
||||
lightflash_t* flash;
|
||||
|
||||
// nothing special about it during gameplay
|
||||
sector->special = 0;
|
||||
|
||||
flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
|
||||
flash->sector = sector;
|
||||
flash->maxlight = sector->lightlevel;
|
||||
|
||||
flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
|
||||
flash->maxtime = 64;
|
||||
flash->mintime = 7;
|
||||
flash->count = (P_Random() & flash->maxtime) + 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// STROBE LIGHT FLASHING
|
||||
//
|
||||
|
||||
//
|
||||
// T_StrobeFlash
|
||||
//
|
||||
void T_StrobeFlash(strobe_t* flash)
|
||||
{
|
||||
if (--flash->count)
|
||||
return;
|
||||
|
||||
if (flash->sector->lightlevel == flash->minlight)
|
||||
{
|
||||
flash->sector->lightlevel = flash->maxlight;
|
||||
flash->count = flash->brighttime;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash->sector->lightlevel = flash->minlight;
|
||||
flash->count = flash->darktime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnStrobeFlash
|
||||
// After the map has been loaded, scan each sector
|
||||
// for specials that spawn thinkers
|
||||
//
|
||||
void P_SpawnStrobeFlash(sector_t* sector, int fastOrSlow, int inSync)
|
||||
{
|
||||
strobe_t* flash;
|
||||
|
||||
flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
|
||||
flash->sector = sector;
|
||||
flash->darktime = fastOrSlow;
|
||||
flash->brighttime = STROBEBRIGHT;
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
|
||||
flash->maxlight = sector->lightlevel;
|
||||
flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
|
||||
|
||||
if (flash->minlight == flash->maxlight)
|
||||
flash->minlight = 0;
|
||||
|
||||
// nothing special about it during gameplay
|
||||
sector->special = 0;
|
||||
|
||||
if (!inSync)
|
||||
flash->count = (P_Random() & 7) + 1;
|
||||
else
|
||||
flash->count = 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Start strobing lights (usually from a trigger)
|
||||
//
|
||||
void EV_StartLightStrobing(line_t* line)
|
||||
{
|
||||
int secnum;
|
||||
sector_t* sec;
|
||||
|
||||
secnum = -1;
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
P_SpawnStrobeFlash(sec, SLOWDARK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// TURN LINE'S TAG LIGHTS OFF
|
||||
//
|
||||
void EV_TurnTagLightsOff(line_t* line)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int min;
|
||||
sector_t* sector;
|
||||
sector_t* tsec;
|
||||
line_t* templine;
|
||||
|
||||
sector = sectors;
|
||||
|
||||
for (j = 0; j < numsectors; j++, sector++)
|
||||
{
|
||||
if (sector->tag == line->tag)
|
||||
{
|
||||
min = sector->lightlevel;
|
||||
for (i = 0; i < sector->linecount; i++)
|
||||
{
|
||||
templine = sector->lines[i];
|
||||
tsec = getNextSector(templine, sector);
|
||||
if (!tsec)
|
||||
continue;
|
||||
if (tsec->lightlevel < min)
|
||||
min = tsec->lightlevel;
|
||||
}
|
||||
sector->lightlevel = min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// TURN LINE'S TAG LIGHTS ON
|
||||
//
|
||||
void EV_LightTurnOn(line_t* line, int bright)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sector_t* sector;
|
||||
sector_t* temp;
|
||||
line_t* templine;
|
||||
|
||||
sector = sectors;
|
||||
|
||||
for (i = 0; i < numsectors; i++, sector++)
|
||||
{
|
||||
if (sector->tag == line->tag)
|
||||
{
|
||||
// bright = 0 means to search
|
||||
// for highest light level
|
||||
// surrounding sector
|
||||
if (!bright)
|
||||
{
|
||||
for (j = 0; j < sector->linecount; j++)
|
||||
{
|
||||
templine = sector->lines[j];
|
||||
temp = getNextSector(templine, sector);
|
||||
|
||||
if (!temp)
|
||||
continue;
|
||||
|
||||
if (temp->lightlevel > bright)
|
||||
bright = temp->lightlevel;
|
||||
}
|
||||
}
|
||||
sector->lightlevel = bright;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Spawn glowing light
|
||||
//
|
||||
void T_Glow(glow_t* g)
|
||||
{
|
||||
switch (g->direction)
|
||||
{
|
||||
case -1:
|
||||
// DOWN
|
||||
g->sector->lightlevel -= GLOWSPEED;
|
||||
if (g->sector->lightlevel <= g->minlight)
|
||||
{
|
||||
g->sector->lightlevel += GLOWSPEED;
|
||||
g->direction = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// UP
|
||||
g->sector->lightlevel += GLOWSPEED;
|
||||
if (g->sector->lightlevel >= g->maxlight)
|
||||
{
|
||||
g->sector->lightlevel -= GLOWSPEED;
|
||||
g->direction = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void P_SpawnGlowingLight(sector_t* sector)
|
||||
{
|
||||
glow_t* g;
|
||||
|
||||
g = Z_Malloc(sizeof(*g), PU_LEVSPEC, 0);
|
||||
|
||||
P_AddThinker(&g->thinker);
|
||||
|
||||
g->sector = sector;
|
||||
g->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
|
||||
g->maxlight = sector->lightlevel;
|
||||
g->thinker.function.acp1 = (actionf_p1)T_Glow;
|
||||
g->direction = -1;
|
||||
|
||||
sector->special = 0;
|
||||
}
|
256
src/DOOM/p_local.h
Normal file
256
src/DOOM/p_local.h
Normal file
@ -0,0 +1,256 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Play functions, animation, global header.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_LOCAL__
|
||||
#define __P_LOCAL__
|
||||
|
||||
|
||||
#ifndef __R_LOCAL__
|
||||
#include "r_local.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define FLOATSPEED (FRACUNIT*4)
|
||||
|
||||
#define MAXHEALTH 100
|
||||
#define VIEWHEIGHT (41*FRACUNIT)
|
||||
|
||||
// mapblocks are used to check movement
|
||||
// against lines and things
|
||||
#define MAPBLOCKUNITS 128
|
||||
#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT)
|
||||
#define MAPBLOCKSHIFT (FRACBITS+7)
|
||||
#define MAPBMASK (MAPBLOCKSIZE-1)
|
||||
#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS)
|
||||
|
||||
|
||||
// player radius for movement checking
|
||||
#define PLAYERRADIUS 16*FRACUNIT
|
||||
|
||||
// MAXRADIUS is for precalculated sector block boxes
|
||||
// the spider demon is larger,
|
||||
// but we do not have any moving sectors nearby
|
||||
#define MAXRADIUS 32*FRACUNIT
|
||||
|
||||
#define GRAVITY FRACUNIT
|
||||
#define MAXMOVE (30*FRACUNIT)
|
||||
|
||||
#define USERANGE (64*FRACUNIT)
|
||||
#define MELEERANGE (64*FRACUNIT)
|
||||
#define MISSILERANGE (32*64*FRACUNIT)
|
||||
|
||||
// follow a player exlusively for 3 seconds
|
||||
#define BASETHRESHOLD 100
|
||||
|
||||
|
||||
//
|
||||
// P_TICK
|
||||
//
|
||||
|
||||
// both the head and tail of the thinker list
|
||||
extern thinker_t thinkercap;
|
||||
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_AddThinker(thinker_t* thinker);
|
||||
void P_RemoveThinker(thinker_t* thinker);
|
||||
|
||||
|
||||
//
|
||||
// P_PSPR
|
||||
//
|
||||
void P_SetupPsprites(player_t* curplayer);
|
||||
void P_MovePsprites(player_t* curplayer);
|
||||
void P_DropWeapon(player_t* player);
|
||||
|
||||
|
||||
//
|
||||
// P_USER
|
||||
//
|
||||
void P_PlayerThink(player_t* player);
|
||||
|
||||
|
||||
//
|
||||
// P_MOBJ
|
||||
//
|
||||
#define ONFLOORZ DOOM_MININT
|
||||
#define ONCEILINGZ DOOM_MAXINT
|
||||
|
||||
// Time interval for item respawning.
|
||||
#define ITEMQUESIZE 128
|
||||
|
||||
|
||||
extern mapthing_t itemrespawnque[ITEMQUESIZE];
|
||||
extern int itemrespawntime[ITEMQUESIZE];
|
||||
extern int iquehead;
|
||||
extern int iquetail;
|
||||
|
||||
|
||||
void P_RespawnSpecials(void);
|
||||
mobj_t* P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
|
||||
void P_RemoveMobj(mobj_t* th);
|
||||
doom_boolean P_SetMobjState(mobj_t* mobj, statenum_t state);
|
||||
void P_MobjThinker(mobj_t* mobj);
|
||||
void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z);
|
||||
void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage);
|
||||
mobj_t* P_SpawnMissile(mobj_t* source, mobj_t* dest, mobjtype_t type);
|
||||
void P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type);
|
||||
|
||||
|
||||
//
|
||||
// P_ENEMY
|
||||
//
|
||||
void P_NoiseAlert(mobj_t* target, mobj_t* emmiter);
|
||||
|
||||
|
||||
//
|
||||
// P_MAPUTL
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
} divline_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t frac; // along trace line
|
||||
doom_boolean isaline;
|
||||
union
|
||||
{
|
||||
mobj_t* thing;
|
||||
line_t* line;
|
||||
} d;
|
||||
} intercept_t;
|
||||
|
||||
|
||||
#define MAXINTERCEPTS 128
|
||||
extern intercept_t intercepts[MAXINTERCEPTS];
|
||||
extern intercept_t* intercept_p;
|
||||
|
||||
|
||||
typedef doom_boolean(*traverser_t) (intercept_t* in);
|
||||
|
||||
|
||||
fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
|
||||
int P_PointOnLineSide(fixed_t x, fixed_t y, line_t* line);
|
||||
int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t* line);
|
||||
void P_MakeDivline(line_t* li, divline_t* dl);
|
||||
fixed_t P_InterceptVector(divline_t* v2, divline_t* v1);
|
||||
int P_BoxOnLineSide(fixed_t* tmbox, line_t* ld);
|
||||
|
||||
|
||||
extern fixed_t opentop;
|
||||
extern fixed_t openbottom;
|
||||
extern fixed_t openrange;
|
||||
extern fixed_t lowfloor;
|
||||
|
||||
|
||||
void P_LineOpening(line_t* linedef);
|
||||
|
||||
|
||||
doom_boolean P_BlockLinesIterator(int x, int y, doom_boolean(*func)(line_t*));
|
||||
doom_boolean P_BlockThingsIterator(int x, int y, doom_boolean(*func)(mobj_t*));
|
||||
|
||||
|
||||
#define PT_ADDLINES 1
|
||||
#define PT_ADDTHINGS 2
|
||||
#define PT_EARLYOUT 4
|
||||
|
||||
|
||||
extern divline_t trace;
|
||||
|
||||
|
||||
doom_boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, doom_boolean(*trav) (intercept_t*));
|
||||
void P_UnsetThingPosition(mobj_t* thing);
|
||||
void P_SetThingPosition(mobj_t* thing);
|
||||
|
||||
|
||||
//
|
||||
// P_MAP
|
||||
//
|
||||
|
||||
// If "floatok" true, move would be ok
|
||||
// if within "tmfloorz - tmceilingz".
|
||||
extern doom_boolean floatok;
|
||||
extern fixed_t tmfloorz;
|
||||
extern fixed_t tmceilingz;
|
||||
|
||||
extern line_t* ceilingline;
|
||||
|
||||
|
||||
doom_boolean P_CheckPosition(mobj_t* thing, fixed_t x, fixed_t y);
|
||||
doom_boolean P_TryMove(mobj_t* thing, fixed_t x, fixed_t y);
|
||||
doom_boolean P_TeleportMove(mobj_t* thing, fixed_t x, fixed_t y);
|
||||
void P_SlideMove(mobj_t* mo);
|
||||
doom_boolean P_CheckSight(mobj_t* t1, mobj_t* t2);
|
||||
void P_UseLines(player_t* player);
|
||||
doom_boolean P_ChangeSector(sector_t* sector, doom_boolean crunch);
|
||||
|
||||
|
||||
extern mobj_t* linetarget; // who got hit (or 0)
|
||||
|
||||
|
||||
fixed_t P_AimLineAttack(mobj_t* t1, angle_t angle, fixed_t distance);
|
||||
void P_LineAttack(mobj_t* t1, angle_t angle, fixed_t distance, fixed_t slope, int damage);
|
||||
void P_RadiusAttack(mobj_t* spot, mobj_t* source, int damage);
|
||||
|
||||
|
||||
//
|
||||
// P_SETUP
|
||||
//
|
||||
extern byte* rejectmatrix; // for fast sight rejection
|
||||
extern short* blockmaplump; // offsets in blockmap are from here
|
||||
extern short* blockmap;
|
||||
extern int bmapwidth;
|
||||
extern int bmapheight; // in mapblocks
|
||||
extern fixed_t bmaporgx;
|
||||
extern fixed_t bmaporgy; // origin of block map
|
||||
extern mobj_t** blocklinks; // for thing chains
|
||||
|
||||
|
||||
//
|
||||
// P_INTER
|
||||
//
|
||||
extern int maxammo[NUMAMMO];
|
||||
extern int clipammo[NUMAMMO];
|
||||
|
||||
|
||||
void P_TouchSpecialThing(mobj_t* special, mobj_t* toucher);
|
||||
void P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage);
|
||||
|
||||
|
||||
//
|
||||
// P_SPEC
|
||||
//
|
||||
#include "p_spec.h"
|
||||
|
||||
|
||||
#endif // __P_LOCAL__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
1291
src/DOOM/p_map.c
Normal file
1291
src/DOOM/p_map.c
Normal file
File diff suppressed because it is too large
Load Diff
788
src/DOOM/p_maputl.c
Normal file
788
src/DOOM/p_maputl.c
Normal file
@ -0,0 +1,788 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Movement/collision utility functions,
|
||||
// as used by function in p_map.c.
|
||||
// BLOCKMAP Iterator functions,
|
||||
// and some PIT_* functions to use for iteration.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "m_bbox.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
fixed_t opentop;
|
||||
fixed_t openbottom;
|
||||
fixed_t openrange;
|
||||
fixed_t lowfloor;
|
||||
intercept_t intercepts[MAXINTERCEPTS];
|
||||
intercept_t* intercept_p;
|
||||
divline_t trace;
|
||||
doom_boolean earlyout;
|
||||
int ptflags;
|
||||
|
||||
|
||||
//
|
||||
// P_AproxDistance
|
||||
// Gives an estimation of distance (not exact)
|
||||
//
|
||||
fixed_t P_AproxDistance(fixed_t dx, fixed_t dy)
|
||||
{
|
||||
dx = doom_abs(dx);
|
||||
dy = doom_abs(dy);
|
||||
if (dx < dy)
|
||||
return dx + dy - (dx >> 1);
|
||||
return dx + dy - (dy >> 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_PointOnLineSide
|
||||
// Returns 0 or 1
|
||||
//
|
||||
int P_PointOnLineSide(fixed_t x, fixed_t y, line_t* line)
|
||||
{
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
fixed_t left;
|
||||
fixed_t right;
|
||||
|
||||
if (!line->dx)
|
||||
{
|
||||
if (x <= line->v1->x)
|
||||
return line->dy > 0;
|
||||
|
||||
return line->dy < 0;
|
||||
}
|
||||
if (!line->dy)
|
||||
{
|
||||
if (y <= line->v1->y)
|
||||
return line->dx < 0;
|
||||
|
||||
return line->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - line->v1->x);
|
||||
dy = (y - line->v1->y);
|
||||
|
||||
left = FixedMul(line->dy >> FRACBITS, dx);
|
||||
right = FixedMul(dy, line->dx >> FRACBITS);
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_BoxOnLineSide
|
||||
// Considers the line to be infinite
|
||||
// Returns side 0 or 1, -1 if box crosses the line.
|
||||
//
|
||||
int P_BoxOnLineSide(fixed_t* tmbox, line_t* ld)
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
|
||||
switch (ld->slopetype)
|
||||
{
|
||||
case ST_HORIZONTAL:
|
||||
p1 = tmbox[BOXTOP] > ld->v1->y;
|
||||
p2 = tmbox[BOXBOTTOM] > ld->v1->y;
|
||||
if (ld->dx < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_VERTICAL:
|
||||
p1 = tmbox[BOXRIGHT] < ld->v1->x;
|
||||
p2 = tmbox[BOXLEFT] < ld->v1->x;
|
||||
if (ld->dy < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_POSITIVE:
|
||||
p1 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
|
||||
case ST_NEGATIVE:
|
||||
p1 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
}
|
||||
|
||||
if (p1 == p2)
|
||||
return p1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_PointOnDivlineSide
|
||||
// Returns 0 or 1.
|
||||
//
|
||||
int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t* line)
|
||||
{
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
fixed_t left;
|
||||
fixed_t right;
|
||||
|
||||
if (!line->dx)
|
||||
{
|
||||
if (x <= line->x)
|
||||
return line->dy > 0;
|
||||
|
||||
return line->dy < 0;
|
||||
}
|
||||
if (!line->dy)
|
||||
{
|
||||
if (y <= line->y)
|
||||
return line->dx < 0;
|
||||
|
||||
return line->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - line->x);
|
||||
dy = (y - line->y);
|
||||
|
||||
// try to quickly decide by looking at sign bits
|
||||
if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000)
|
||||
{
|
||||
if ((line->dy ^ dx) & 0x80000000)
|
||||
return 1; // (left is negative)
|
||||
return 0;
|
||||
}
|
||||
|
||||
left = FixedMul(line->dy >> 8, dx >> 8);
|
||||
right = FixedMul(dy >> 8, line->dx >> 8);
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_MakeDivline
|
||||
//
|
||||
void P_MakeDivline(line_t* li, divline_t* dl)
|
||||
{
|
||||
dl->x = li->v1->x;
|
||||
dl->y = li->v1->y;
|
||||
dl->dx = li->dx;
|
||||
dl->dy = li->dy;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_InterceptVector
|
||||
// Returns the fractional intercept point
|
||||
// along the first divline.
|
||||
// This is only called by the addthings
|
||||
// and addlines traversers.
|
||||
//
|
||||
fixed_t P_InterceptVector(divline_t* v2, divline_t* v1)
|
||||
{
|
||||
fixed_t frac;
|
||||
fixed_t num;
|
||||
fixed_t den;
|
||||
|
||||
den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy);
|
||||
|
||||
if (den == 0)
|
||||
return 0;
|
||||
// I_Error ("P_InterceptVector: parallel");
|
||||
|
||||
num =
|
||||
FixedMul((v1->x - v2->x) >> 8, v1->dy)
|
||||
+ FixedMul((v2->y - v1->y) >> 8, v1->dx);
|
||||
|
||||
frac = FixedDiv(num, den);
|
||||
|
||||
return frac;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LineOpening
|
||||
// Sets opentop and openbottom to the window
|
||||
// through a two sided line.
|
||||
// OPTIMIZE: keep this precalculated
|
||||
//
|
||||
void P_LineOpening(line_t* linedef)
|
||||
{
|
||||
sector_t* front;
|
||||
sector_t* back;
|
||||
|
||||
if (linedef->sidenum[1] == -1)
|
||||
{
|
||||
// single sided line
|
||||
openrange = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
front = linedef->frontsector;
|
||||
back = linedef->backsector;
|
||||
|
||||
if (front->ceilingheight < back->ceilingheight)
|
||||
opentop = front->ceilingheight;
|
||||
else
|
||||
opentop = back->ceilingheight;
|
||||
|
||||
if (front->floorheight > back->floorheight)
|
||||
{
|
||||
openbottom = front->floorheight;
|
||||
lowfloor = back->floorheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
openbottom = back->floorheight;
|
||||
lowfloor = front->floorheight;
|
||||
}
|
||||
|
||||
openrange = opentop - openbottom;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// THING POSITION SETTING
|
||||
//
|
||||
|
||||
//
|
||||
// P_UnsetThingPosition
|
||||
// Unlinks a thing from block map and sectors.
|
||||
// On each position change, BLOCKMAP and other
|
||||
// lookups maintaining lists ot things inside
|
||||
// these structures need to be updated.
|
||||
//
|
||||
void P_UnsetThingPosition(mobj_t* thing)
|
||||
{
|
||||
int blockx;
|
||||
int blocky;
|
||||
|
||||
if (!(thing->flags & MF_NOSECTOR))
|
||||
{
|
||||
// inert things don't need to be in blockmap?
|
||||
// unlink from subsector
|
||||
if (thing->snext)
|
||||
thing->snext->sprev = thing->sprev;
|
||||
|
||||
if (thing->sprev)
|
||||
thing->sprev->snext = thing->snext;
|
||||
else
|
||||
thing->subsector->sector->thinglist = thing->snext;
|
||||
}
|
||||
|
||||
if (!(thing->flags & MF_NOBLOCKMAP))
|
||||
{
|
||||
// inert things don't need to be in blockmap
|
||||
// unlink from block map
|
||||
if (thing->bnext)
|
||||
thing->bnext->bprev = thing->bprev;
|
||||
|
||||
if (thing->bprev)
|
||||
thing->bprev->bnext = thing->bnext;
|
||||
else
|
||||
{
|
||||
blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT;
|
||||
blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
|
||||
if (blockx >= 0 && blockx < bmapwidth
|
||||
&& blocky >= 0 && blocky < bmapheight)
|
||||
{
|
||||
blocklinks[blocky * bmapwidth + blockx] = thing->bnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SetThingPosition
|
||||
// Links a thing into both a block and a subsector
|
||||
// based on it's x y.
|
||||
// Sets thing->subsector properly
|
||||
//
|
||||
void P_SetThingPosition(mobj_t* thing)
|
||||
{
|
||||
subsector_t* ss;
|
||||
sector_t* sec;
|
||||
int blockx;
|
||||
int blocky;
|
||||
mobj_t** link;
|
||||
|
||||
|
||||
// link into subsector
|
||||
ss = R_PointInSubsector(thing->x, thing->y);
|
||||
thing->subsector = ss;
|
||||
|
||||
if (!(thing->flags & MF_NOSECTOR))
|
||||
{
|
||||
// invisible things don't go into the sector links
|
||||
sec = ss->sector;
|
||||
|
||||
thing->sprev = 0;
|
||||
thing->snext = sec->thinglist;
|
||||
|
||||
if (sec->thinglist)
|
||||
sec->thinglist->sprev = thing;
|
||||
|
||||
sec->thinglist = thing;
|
||||
}
|
||||
|
||||
// link into blockmap
|
||||
if (!(thing->flags & MF_NOBLOCKMAP))
|
||||
{
|
||||
// inert things don't need to be in blockmap
|
||||
blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT;
|
||||
blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
|
||||
if (blockx >= 0
|
||||
&& blockx < bmapwidth
|
||||
&& blocky >= 0
|
||||
&& blocky < bmapheight)
|
||||
{
|
||||
link = &blocklinks[blocky * bmapwidth + blockx];
|
||||
thing->bprev = 0;
|
||||
thing->bnext = *link;
|
||||
if (*link)
|
||||
(*link)->bprev = thing;
|
||||
|
||||
*link = thing;
|
||||
}
|
||||
else
|
||||
{
|
||||
// thing is off the map
|
||||
thing->bnext = thing->bprev = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// BLOCK MAP ITERATORS
|
||||
// For each line/thing in the given mapblock,
|
||||
// call the passed PIT_* function.
|
||||
// If the function returns false,
|
||||
// exit with false without checking anything else.
|
||||
//
|
||||
|
||||
//
|
||||
// P_BlockLinesIterator
|
||||
// The validcount flags are used to avoid checking lines
|
||||
// that are marked in multiple mapblocks,
|
||||
// so increment validcount before the first call
|
||||
// to P_BlockLinesIterator, then make one or more calls
|
||||
// to it.
|
||||
//
|
||||
doom_boolean P_BlockLinesIterator(int x, int y, doom_boolean(*func)(line_t*))
|
||||
{
|
||||
int offset;
|
||||
short* list;
|
||||
line_t* ld;
|
||||
|
||||
if (x < 0
|
||||
|| y < 0
|
||||
|| x >= bmapwidth
|
||||
|| y >= bmapheight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
offset = y * bmapwidth + x;
|
||||
|
||||
offset = *(blockmap + offset);
|
||||
|
||||
for (list = blockmaplump + offset; *list != -1; list++)
|
||||
{
|
||||
ld = &lines[*list];
|
||||
|
||||
if (ld->validcount == validcount)
|
||||
continue; // line has already been checked
|
||||
|
||||
ld->validcount = validcount;
|
||||
|
||||
if (!func(ld))
|
||||
return false;
|
||||
}
|
||||
return true; // everything was checked
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_BlockThingsIterator
|
||||
//
|
||||
doom_boolean P_BlockThingsIterator(int x, int y, doom_boolean(*func)(mobj_t*))
|
||||
{
|
||||
mobj_t* mobj;
|
||||
|
||||
if (x < 0
|
||||
|| y < 0
|
||||
|| x >= bmapwidth
|
||||
|| y >= bmapheight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
for (mobj = blocklinks[y * bmapwidth + x];
|
||||
mobj;
|
||||
mobj = mobj->bnext)
|
||||
{
|
||||
if (!func(mobj))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// INTERCEPT ROUTINES
|
||||
//
|
||||
|
||||
//
|
||||
// PIT_AddLineIntercepts.
|
||||
// Looks for lines in the given block
|
||||
// that intercept the given trace
|
||||
// to add to the intercepts list.
|
||||
//
|
||||
// A line is crossed if its endpoints
|
||||
// are on opposite sides of the trace.
|
||||
// Returns true if earlyout and a solid line hit.
|
||||
//
|
||||
doom_boolean PIT_AddLineIntercepts(line_t* ld)
|
||||
{
|
||||
int s1;
|
||||
int s2;
|
||||
fixed_t frac;
|
||||
divline_t dl;
|
||||
|
||||
// avoid precision problems with two routines
|
||||
if (trace.dx > FRACUNIT * 16
|
||||
|| trace.dy > FRACUNIT * 16
|
||||
|| trace.dx < -FRACUNIT * 16
|
||||
|| trace.dy < -FRACUNIT * 16)
|
||||
{
|
||||
s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace);
|
||||
s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = P_PointOnLineSide(trace.x, trace.y, ld);
|
||||
s2 = P_PointOnLineSide(trace.x + trace.dx, trace.y + trace.dy, ld);
|
||||
}
|
||||
|
||||
if (s1 == s2)
|
||||
return true; // line isn't crossed
|
||||
|
||||
// hit the line
|
||||
P_MakeDivline(ld, &dl);
|
||||
frac = P_InterceptVector(&trace, &dl);
|
||||
|
||||
if (frac < 0)
|
||||
return true; // behind source
|
||||
|
||||
// try to early out the check
|
||||
if (earlyout
|
||||
&& frac < FRACUNIT
|
||||
&& !ld->backsector)
|
||||
{
|
||||
return false; // stop checking
|
||||
}
|
||||
|
||||
intercept_p->frac = frac;
|
||||
intercept_p->isaline = true;
|
||||
intercept_p->d.line = ld;
|
||||
intercept_p++;
|
||||
|
||||
return true; // continue
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// PIT_AddThingIntercepts
|
||||
//
|
||||
doom_boolean PIT_AddThingIntercepts(mobj_t* thing)
|
||||
{
|
||||
fixed_t x1;
|
||||
fixed_t y1;
|
||||
fixed_t x2;
|
||||
fixed_t y2;
|
||||
|
||||
int s1;
|
||||
int s2;
|
||||
|
||||
doom_boolean tracepositive;
|
||||
|
||||
divline_t dl;
|
||||
|
||||
fixed_t frac;
|
||||
|
||||
tracepositive = (trace.dx ^ trace.dy) > 0;
|
||||
|
||||
// check a corner to corner crossection for hit
|
||||
if (tracepositive)
|
||||
{
|
||||
x1 = thing->x - thing->radius;
|
||||
y1 = thing->y + thing->radius;
|
||||
|
||||
x2 = thing->x + thing->radius;
|
||||
y2 = thing->y - thing->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = thing->x - thing->radius;
|
||||
y1 = thing->y - thing->radius;
|
||||
|
||||
x2 = thing->x + thing->radius;
|
||||
y2 = thing->y + thing->radius;
|
||||
}
|
||||
|
||||
s1 = P_PointOnDivlineSide(x1, y1, &trace);
|
||||
s2 = P_PointOnDivlineSide(x2, y2, &trace);
|
||||
|
||||
if (s1 == s2)
|
||||
return true; // line isn't crossed
|
||||
|
||||
dl.x = x1;
|
||||
dl.y = y1;
|
||||
dl.dx = x2 - x1;
|
||||
dl.dy = y2 - y1;
|
||||
|
||||
frac = P_InterceptVector(&trace, &dl);
|
||||
|
||||
if (frac < 0)
|
||||
return true; // behind source
|
||||
|
||||
intercept_p->frac = frac;
|
||||
intercept_p->isaline = false;
|
||||
intercept_p->d.thing = thing;
|
||||
intercept_p++;
|
||||
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_TraverseIntercepts
|
||||
// Returns true if the traverser function returns true
|
||||
// for all lines.
|
||||
//
|
||||
doom_boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac)
|
||||
{
|
||||
int count;
|
||||
fixed_t dist;
|
||||
intercept_t* scan;
|
||||
intercept_t* in;
|
||||
|
||||
count = (int)(intercept_p - intercepts);
|
||||
|
||||
in = 0; // shut up compiler warning
|
||||
|
||||
while (count--)
|
||||
{
|
||||
dist = DOOM_MAXINT;
|
||||
for (scan = intercepts; scan < intercept_p; scan++)
|
||||
{
|
||||
if (scan->frac < dist)
|
||||
{
|
||||
dist = scan->frac;
|
||||
in = scan;
|
||||
}
|
||||
}
|
||||
|
||||
if (dist > maxfrac)
|
||||
return true; // checked everything in range
|
||||
|
||||
#if 0 // UNUSED
|
||||
{
|
||||
// don't check these yet, there may be others inserted
|
||||
in = scan = intercepts;
|
||||
for (scan = intercepts; scan < intercept_p; scan++)
|
||||
if (scan->frac > maxfrac)
|
||||
*in++ = *scan;
|
||||
intercept_p = in;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!func(in))
|
||||
return false; // don't bother going farther
|
||||
|
||||
in->frac = DOOM_MAXINT;
|
||||
}
|
||||
|
||||
return true; // everything was traversed
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_PathTraverse
|
||||
// Traces a line from x1,y1 to x2,y2,
|
||||
// calling the traverser function for each.
|
||||
// Returns true if the traverser function returns true
|
||||
// for all lines.
|
||||
//
|
||||
doom_boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, doom_boolean(*trav) (intercept_t*))
|
||||
{
|
||||
fixed_t xt1;
|
||||
fixed_t yt1;
|
||||
fixed_t xt2;
|
||||
fixed_t yt2;
|
||||
|
||||
fixed_t xstep;
|
||||
fixed_t ystep;
|
||||
|
||||
fixed_t partial;
|
||||
|
||||
fixed_t xintercept;
|
||||
fixed_t yintercept;
|
||||
|
||||
int mapx;
|
||||
int mapy;
|
||||
|
||||
int mapxstep;
|
||||
int mapystep;
|
||||
|
||||
int count;
|
||||
|
||||
earlyout = flags & PT_EARLYOUT;
|
||||
|
||||
validcount++;
|
||||
intercept_p = intercepts;
|
||||
|
||||
if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0)
|
||||
y1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
trace.x = x1;
|
||||
trace.y = y1;
|
||||
trace.dx = x2 - x1;
|
||||
trace.dy = y2 - y1;
|
||||
|
||||
x1 -= bmaporgx;
|
||||
y1 -= bmaporgy;
|
||||
xt1 = x1 >> MAPBLOCKSHIFT;
|
||||
yt1 = y1 >> MAPBLOCKSHIFT;
|
||||
|
||||
x2 -= bmaporgx;
|
||||
y2 -= bmaporgy;
|
||||
xt2 = x2 >> MAPBLOCKSHIFT;
|
||||
yt2 = y2 >> MAPBLOCKSHIFT;
|
||||
|
||||
if (xt2 > xt1)
|
||||
{
|
||||
mapxstep = 1;
|
||||
partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1));
|
||||
ystep = FixedDiv(y2 - y1, doom_abs(x2 - x1));
|
||||
}
|
||||
else if (xt2 < xt1)
|
||||
{
|
||||
mapxstep = -1;
|
||||
partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1);
|
||||
ystep = FixedDiv(y2 - y1, doom_abs(x2 - x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapxstep = 0;
|
||||
partial = FRACUNIT;
|
||||
ystep = 256 * FRACUNIT;
|
||||
}
|
||||
|
||||
yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep);
|
||||
|
||||
|
||||
if (yt2 > yt1)
|
||||
{
|
||||
mapystep = 1;
|
||||
partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1));
|
||||
xstep = FixedDiv(x2 - x1, doom_abs(y2 - y1));
|
||||
}
|
||||
else if (yt2 < yt1)
|
||||
{
|
||||
mapystep = -1;
|
||||
partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1);
|
||||
xstep = FixedDiv(x2 - x1, doom_abs(y2 - y1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapystep = 0;
|
||||
partial = FRACUNIT;
|
||||
xstep = 256 * FRACUNIT;
|
||||
}
|
||||
xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep);
|
||||
|
||||
// Step through map blocks.
|
||||
// Count is present to prevent a round off error
|
||||
// from skipping the break.
|
||||
mapx = xt1;
|
||||
mapy = yt1;
|
||||
|
||||
for (count = 0; count < 64; count++)
|
||||
{
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts))
|
||||
return false; // early out
|
||||
}
|
||||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts))
|
||||
return false; // early out
|
||||
}
|
||||
|
||||
if (mapx == xt2
|
||||
&& mapy == yt2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((yintercept >> FRACBITS) == mapy)
|
||||
{
|
||||
yintercept += ystep;
|
||||
mapx += mapxstep;
|
||||
}
|
||||
else if ((xintercept >> FRACBITS) == mapx)
|
||||
{
|
||||
xintercept += xstep;
|
||||
mapy += mapystep;
|
||||
}
|
||||
}
|
||||
|
||||
// go through the sorted list
|
||||
return P_TraverseIntercepts(trav, FRACUNIT);
|
||||
}
|
961
src/DOOM/p_mobj.c
Normal file
961
src/DOOM/p_mobj.c
Normal file
@ -0,0 +1,961 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Moving object handling. Spawn functions.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_random.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "sounds.h"
|
||||
#include "st_stuff.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
#define STOPSPEED 0x1000
|
||||
#define FRICTION 0xe800
|
||||
|
||||
|
||||
//
|
||||
// P_SetMobjState
|
||||
// Returns true if the mobj is still present.
|
||||
//
|
||||
mapthing_t itemrespawnque[ITEMQUESIZE];
|
||||
int itemrespawntime[ITEMQUESIZE];
|
||||
int iquehead;
|
||||
int iquetail;
|
||||
|
||||
|
||||
extern fixed_t attackrange;
|
||||
|
||||
|
||||
void G_PlayerReborn(int player);
|
||||
void P_SpawnMapThing(mapthing_t* mthing);
|
||||
|
||||
|
||||
doom_boolean P_SetMobjState(mobj_t* mobj, statenum_t state)
|
||||
{
|
||||
state_t* st;
|
||||
|
||||
do
|
||||
{
|
||||
if (state == S_NULL)
|
||||
{
|
||||
mobj->state = (state_t*)S_NULL;
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
|
||||
st = &states[state];
|
||||
mobj->state = st;
|
||||
mobj->tics = st->tics;
|
||||
mobj->sprite = st->sprite;
|
||||
mobj->frame = st->frame;
|
||||
|
||||
// Modified handling.
|
||||
// Call action functions when the state is set
|
||||
if (st->action.acp1)
|
||||
st->action.acp1(mobj);
|
||||
|
||||
state = st->nextstate;
|
||||
} while (!mobj->tics);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_ExplodeMissile
|
||||
//
|
||||
void P_ExplodeMissile(mobj_t* mo)
|
||||
{
|
||||
mo->momx = mo->momy = mo->momz = 0;
|
||||
|
||||
P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
|
||||
|
||||
mo->tics -= P_Random() & 3;
|
||||
|
||||
if (mo->tics < 1)
|
||||
mo->tics = 1;
|
||||
|
||||
mo->flags &= ~MF_MISSILE;
|
||||
|
||||
if (mo->info->deathsound)
|
||||
S_StartSound(mo, mo->info->deathsound);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_XYMovement
|
||||
//
|
||||
void P_XYMovement(mobj_t* mo)
|
||||
{
|
||||
fixed_t ptryx;
|
||||
fixed_t ptryy;
|
||||
player_t* player;
|
||||
fixed_t xmove;
|
||||
fixed_t ymove;
|
||||
|
||||
if (!mo->momx && !mo->momy)
|
||||
{
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{
|
||||
// the skull slammed into something
|
||||
mo->flags &= ~MF_SKULLFLY;
|
||||
mo->momx = mo->momy = mo->momz = 0;
|
||||
|
||||
P_SetMobjState(mo, mo->info->spawnstate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
player = mo->player;
|
||||
|
||||
if (mo->momx > MAXMOVE)
|
||||
mo->momx = MAXMOVE;
|
||||
else if (mo->momx < -MAXMOVE)
|
||||
mo->momx = -MAXMOVE;
|
||||
|
||||
if (mo->momy > MAXMOVE)
|
||||
mo->momy = MAXMOVE;
|
||||
else if (mo->momy < -MAXMOVE)
|
||||
mo->momy = -MAXMOVE;
|
||||
|
||||
xmove = mo->momx;
|
||||
ymove = mo->momy;
|
||||
|
||||
do
|
||||
{
|
||||
if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2)
|
||||
{
|
||||
ptryx = mo->x + xmove / 2;
|
||||
ptryy = mo->y + ymove / 2;
|
||||
xmove >>= 1;
|
||||
ymove >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptryx = mo->x + xmove;
|
||||
ptryy = mo->y + ymove;
|
||||
xmove = ymove = 0;
|
||||
}
|
||||
|
||||
if (!P_TryMove(mo, ptryx, ptryy))
|
||||
{
|
||||
// blocked move
|
||||
if (mo->player)
|
||||
{ // try to slide along it
|
||||
P_SlideMove(mo);
|
||||
}
|
||||
else if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
// explode a missile
|
||||
if (ceilingline &&
|
||||
ceilingline->backsector &&
|
||||
ceilingline->backsector->ceilingpic == skyflatnum)
|
||||
{
|
||||
// Hack to prevent missiles exploding
|
||||
// against the sky.
|
||||
// Does not handle sky floors.
|
||||
P_RemoveMobj(mo);
|
||||
return;
|
||||
}
|
||||
P_ExplodeMissile(mo);
|
||||
}
|
||||
else
|
||||
mo->momx = mo->momy = 0;
|
||||
}
|
||||
} while (xmove || ymove);
|
||||
|
||||
// slow down
|
||||
if (player && player->cheats & CF_NOMOMENTUM)
|
||||
{
|
||||
// debug option for no sliding at all
|
||||
mo->momx = mo->momy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mo->flags & (MF_MISSILE | MF_SKULLFLY))
|
||||
return; // no friction for missiles ever
|
||||
|
||||
if (mo->z > mo->floorz)
|
||||
return; // no friction when airborne
|
||||
|
||||
if (mo->flags & MF_CORPSE)
|
||||
{
|
||||
// do not stop sliding
|
||||
// if halfway off a step with some momentum
|
||||
if (mo->momx > FRACUNIT / 4
|
||||
|| mo->momx < -FRACUNIT / 4
|
||||
|| mo->momy > FRACUNIT / 4
|
||||
|| mo->momy < -FRACUNIT / 4)
|
||||
{
|
||||
if (mo->floorz != mo->subsector->sector->floorheight)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mo->momx > -STOPSPEED
|
||||
&& mo->momx < STOPSPEED
|
||||
&& mo->momy > -STOPSPEED
|
||||
&& mo->momy < STOPSPEED
|
||||
&& (!player
|
||||
|| (player->cmd.forwardmove == 0
|
||||
&& player->cmd.sidemove == 0)))
|
||||
{
|
||||
// if in a walking frame, stop moving
|
||||
if (player && (unsigned)((player->mo->state - states) - S_PLAY_RUN1) < 4)
|
||||
P_SetMobjState(player->mo, S_PLAY);
|
||||
|
||||
mo->momx = 0;
|
||||
mo->momy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->momx = FixedMul(mo->momx, FRICTION);
|
||||
mo->momy = FixedMul(mo->momy, FRICTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_ZMovement
|
||||
//
|
||||
void P_ZMovement(mobj_t* mo)
|
||||
{
|
||||
fixed_t dist;
|
||||
fixed_t delta;
|
||||
|
||||
// check for smooth step up
|
||||
if (mo->player && mo->z < mo->floorz)
|
||||
{
|
||||
mo->player->viewheight -= mo->floorz - mo->z;
|
||||
|
||||
mo->player->deltaviewheight
|
||||
= (VIEWHEIGHT - mo->player->viewheight) >> 3;
|
||||
}
|
||||
|
||||
// adjust height
|
||||
mo->z += mo->momz;
|
||||
|
||||
if (mo->flags & MF_FLOAT
|
||||
&& mo->target)
|
||||
{
|
||||
// float down towards target if too close
|
||||
if (!(mo->flags & MF_SKULLFLY)
|
||||
&& !(mo->flags & MF_INFLOAT))
|
||||
{
|
||||
dist = P_AproxDistance(mo->x - mo->target->x,
|
||||
mo->y - mo->target->y);
|
||||
|
||||
delta = (mo->target->z + (mo->height >> 1)) - mo->z;
|
||||
|
||||
if (delta < 0 && dist < -(delta * 3))
|
||||
mo->z -= FLOATSPEED;
|
||||
else if (delta > 0 && dist < (delta * 3))
|
||||
mo->z += FLOATSPEED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clip movement
|
||||
if (mo->z <= mo->floorz)
|
||||
{
|
||||
// hit the floor
|
||||
|
||||
// Note (id):
|
||||
// somebody left this after the setting momz to 0,
|
||||
// kinda useless there.
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{
|
||||
// the skull slammed into something
|
||||
mo->momz = -mo->momz;
|
||||
}
|
||||
|
||||
if (mo->momz < 0)
|
||||
{
|
||||
if (mo->player
|
||||
&& mo->momz < -GRAVITY * 8)
|
||||
{
|
||||
// Squat down.
|
||||
// Decrease viewheight for a moment
|
||||
// after hitting the ground (hard),
|
||||
// and utter appropriate sound.
|
||||
mo->player->deltaviewheight = mo->momz >> 3;
|
||||
S_StartSound(mo, sfx_oof);
|
||||
}
|
||||
mo->momz = 0;
|
||||
}
|
||||
mo->z = mo->floorz;
|
||||
|
||||
if ((mo->flags & MF_MISSILE)
|
||||
&& !(mo->flags & MF_NOCLIP))
|
||||
{
|
||||
P_ExplodeMissile(mo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!(mo->flags & MF_NOGRAVITY))
|
||||
{
|
||||
if (mo->momz == 0)
|
||||
mo->momz = -GRAVITY * 2;
|
||||
else
|
||||
mo->momz -= GRAVITY;
|
||||
}
|
||||
|
||||
if (mo->z + mo->height > mo->ceilingz)
|
||||
{
|
||||
// hit the ceiling
|
||||
if (mo->momz > 0)
|
||||
mo->momz = 0;
|
||||
{
|
||||
mo->z = mo->ceilingz - mo->height;
|
||||
}
|
||||
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{ // the skull slammed into something
|
||||
mo->momz = -mo->momz;
|
||||
}
|
||||
|
||||
if ((mo->flags & MF_MISSILE)
|
||||
&& !(mo->flags & MF_NOCLIP))
|
||||
{
|
||||
P_ExplodeMissile(mo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_NightmareRespawn
|
||||
//
|
||||
void P_NightmareRespawn(mobj_t* mobj)
|
||||
{
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
subsector_t* ss;
|
||||
mobj_t* mo;
|
||||
mapthing_t* mthing;
|
||||
|
||||
x = mobj->spawnpoint.x << FRACBITS;
|
||||
y = mobj->spawnpoint.y << FRACBITS;
|
||||
|
||||
// somthing is occupying it's position?
|
||||
if (!P_CheckPosition(mobj, x, y))
|
||||
return; // no respwan
|
||||
|
||||
// spawn a teleport fog at old spot
|
||||
// because of removal of the body?
|
||||
mo = P_SpawnMobj(mobj->x,
|
||||
mobj->y,
|
||||
mobj->subsector->sector->floorheight, MT_TFOG);
|
||||
// initiate teleport sound
|
||||
S_StartSound(mo, sfx_telept);
|
||||
|
||||
// spawn a teleport fog at the new spot
|
||||
ss = R_PointInSubsector(x, y);
|
||||
|
||||
mo = P_SpawnMobj(x, y, ss->sector->floorheight, MT_TFOG);
|
||||
|
||||
S_StartSound(mo, sfx_telept);
|
||||
|
||||
// spawn the new monster
|
||||
mthing = &mobj->spawnpoint;
|
||||
|
||||
// spawn it
|
||||
if (mobj->info->flags & MF_SPAWNCEILING)
|
||||
z = ONCEILINGZ;
|
||||
else
|
||||
z = ONFLOORZ;
|
||||
|
||||
// inherit attributes from deceased one
|
||||
mo = P_SpawnMobj(x, y, z, mobj->type);
|
||||
mo->spawnpoint = mobj->spawnpoint;
|
||||
mo->angle = ANG45 * (mthing->angle / 45);
|
||||
|
||||
if (mthing->options & MTF_AMBUSH)
|
||||
mo->flags |= MF_AMBUSH;
|
||||
|
||||
mo->reactiontime = 18;
|
||||
|
||||
// remove the old monster,
|
||||
P_RemoveMobj(mobj);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_MobjThinker
|
||||
//
|
||||
void P_MobjThinker(mobj_t* mobj)
|
||||
{
|
||||
// momentum movement
|
||||
if (mobj->momx
|
||||
|| mobj->momy
|
||||
|| (mobj->flags & MF_SKULLFLY))
|
||||
{
|
||||
P_XYMovement(mobj);
|
||||
|
||||
// FIXME: decent NOP/0/Nil function pointer please.
|
||||
if (mobj->thinker.function.acv == (actionf_v)(-1))
|
||||
return; // mobj was removed
|
||||
}
|
||||
if ((mobj->z != mobj->floorz)
|
||||
|| mobj->momz)
|
||||
{
|
||||
P_ZMovement(mobj);
|
||||
|
||||
// FIXME: decent NOP/0/Nil function pointer please.
|
||||
if (mobj->thinker.function.acv == (actionf_v)(-1))
|
||||
return; // mobj was removed
|
||||
}
|
||||
|
||||
|
||||
// cycle through states,
|
||||
// calling action functions at transitions
|
||||
if (mobj->tics != -1)
|
||||
{
|
||||
mobj->tics--;
|
||||
|
||||
// you can cycle through multiple states in a tic
|
||||
if (!mobj->tics)
|
||||
if (!P_SetMobjState(mobj, mobj->state->nextstate))
|
||||
return; // freed itself
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for nightmare respawn
|
||||
if (!(mobj->flags & MF_COUNTKILL))
|
||||
return;
|
||||
|
||||
if (!respawnmonsters)
|
||||
return;
|
||||
|
||||
mobj->movecount++;
|
||||
|
||||
if (mobj->movecount < 12 * 35)
|
||||
return;
|
||||
|
||||
if (leveltime & 31)
|
||||
return;
|
||||
|
||||
if (P_Random() > 4)
|
||||
return;
|
||||
|
||||
P_NightmareRespawn(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnMobj
|
||||
//
|
||||
mobj_t* P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||
{
|
||||
mobj_t* mobj;
|
||||
state_t* st;
|
||||
mobjinfo_t* info;
|
||||
|
||||
mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, 0);
|
||||
doom_memset(mobj, 0, sizeof(*mobj));
|
||||
info = &mobjinfo[type];
|
||||
|
||||
mobj->type = type;
|
||||
mobj->info = info;
|
||||
mobj->x = x;
|
||||
mobj->y = y;
|
||||
mobj->radius = info->radius;
|
||||
mobj->height = info->height;
|
||||
mobj->flags = info->flags;
|
||||
mobj->health = info->spawnhealth;
|
||||
|
||||
if (gameskill != sk_nightmare)
|
||||
mobj->reactiontime = info->reactiontime;
|
||||
|
||||
mobj->lastlook = P_Random() % MAXPLAYERS;
|
||||
// do not set the state with P_SetMobjState,
|
||||
// because action routines can not be called yet
|
||||
st = &states[info->spawnstate];
|
||||
|
||||
mobj->state = st;
|
||||
mobj->tics = st->tics;
|
||||
mobj->sprite = st->sprite;
|
||||
mobj->frame = st->frame;
|
||||
|
||||
// set subsector and/or block links
|
||||
P_SetThingPosition(mobj);
|
||||
|
||||
mobj->floorz = mobj->subsector->sector->floorheight;
|
||||
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
||||
|
||||
if (z == ONFLOORZ)
|
||||
mobj->z = mobj->floorz;
|
||||
else if (z == ONCEILINGZ)
|
||||
mobj->z = mobj->ceilingz - mobj->info->height;
|
||||
else
|
||||
mobj->z = z;
|
||||
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
||||
|
||||
P_AddThinker(&mobj->thinker);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_RemoveMobj
|
||||
//
|
||||
void P_RemoveMobj(mobj_t* mobj)
|
||||
{
|
||||
if ((mobj->flags & MF_SPECIAL)
|
||||
&& !(mobj->flags & MF_DROPPED)
|
||||
&& (mobj->type != MT_INV)
|
||||
&& (mobj->type != MT_INS))
|
||||
{
|
||||
itemrespawnque[iquehead] = mobj->spawnpoint;
|
||||
itemrespawntime[iquehead] = leveltime;
|
||||
iquehead = (iquehead + 1) & (ITEMQUESIZE - 1);
|
||||
|
||||
// lose one off the end?
|
||||
if (iquehead == iquetail)
|
||||
iquetail = (iquetail + 1) & (ITEMQUESIZE - 1);
|
||||
}
|
||||
|
||||
// unlink from sector and block lists
|
||||
P_UnsetThingPosition(mobj);
|
||||
|
||||
// stop any playing sound
|
||||
S_StopSound(mobj);
|
||||
|
||||
// free block
|
||||
P_RemoveThinker((thinker_t*)mobj);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_RespawnSpecials
|
||||
//
|
||||
void P_RespawnSpecials(void)
|
||||
{
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
|
||||
subsector_t* ss;
|
||||
mobj_t* mo;
|
||||
mapthing_t* mthing;
|
||||
|
||||
int i;
|
||||
|
||||
// only respawn items in deathmatch
|
||||
if (deathmatch != 2)
|
||||
return; //
|
||||
|
||||
// nothing left to respawn?
|
||||
if (iquehead == iquetail)
|
||||
return;
|
||||
|
||||
// wait at least 30 seconds
|
||||
if (leveltime - itemrespawntime[iquetail] < 30 * 35)
|
||||
return;
|
||||
|
||||
mthing = &itemrespawnque[iquetail];
|
||||
|
||||
x = mthing->x << FRACBITS;
|
||||
y = mthing->y << FRACBITS;
|
||||
|
||||
// spawn a teleport fog at the new spot
|
||||
ss = R_PointInSubsector(x, y);
|
||||
mo = P_SpawnMobj(x, y, ss->sector->floorheight, MT_IFOG);
|
||||
S_StartSound(mo, sfx_itmbk);
|
||||
|
||||
// find which type to spawn
|
||||
for (i = 0; i < NUMMOBJTYPES; i++)
|
||||
{
|
||||
if (mthing->type == mobjinfo[i].doomednum)
|
||||
break;
|
||||
}
|
||||
|
||||
// spawn it
|
||||
if (mobjinfo[i].flags & MF_SPAWNCEILING)
|
||||
z = ONCEILINGZ;
|
||||
else
|
||||
z = ONFLOORZ;
|
||||
|
||||
mo = P_SpawnMobj(x, y, z, i);
|
||||
mo->spawnpoint = *mthing;
|
||||
mo->angle = ANG45 * (mthing->angle / 45);
|
||||
|
||||
// pull it from the que
|
||||
iquetail = (iquetail + 1) & (ITEMQUESIZE - 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnPlayer
|
||||
// Called when a player is spawned on the level.
|
||||
// Most of the player structure stays unchanged
|
||||
// between levels.
|
||||
//
|
||||
void P_SpawnPlayer(mapthing_t* mthing)
|
||||
{
|
||||
player_t* p;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
|
||||
mobj_t* mobj;
|
||||
|
||||
int i;
|
||||
|
||||
// not playing?
|
||||
if (!playeringame[mthing->type - 1])
|
||||
return;
|
||||
|
||||
p = &players[mthing->type - 1];
|
||||
|
||||
if (p->playerstate == PST_REBORN)
|
||||
G_PlayerReborn(mthing->type - 1);
|
||||
|
||||
x = mthing->x << FRACBITS;
|
||||
y = mthing->y << FRACBITS;
|
||||
z = ONFLOORZ;
|
||||
mobj = P_SpawnMobj(x, y, z, MT_PLAYER);
|
||||
|
||||
// set color translations for player sprites
|
||||
if (mthing->type > 1)
|
||||
mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT;
|
||||
|
||||
mobj->angle = ANG45 * (mthing->angle / 45);
|
||||
mobj->player = p;
|
||||
mobj->health = p->health;
|
||||
|
||||
p->mo = mobj;
|
||||
p->playerstate = PST_LIVE;
|
||||
p->refire = 0;
|
||||
p->message = 0;
|
||||
p->damagecount = 0;
|
||||
p->bonuscount = 0;
|
||||
p->extralight = 0;
|
||||
p->fixedcolormap = 0;
|
||||
p->viewheight = VIEWHEIGHT;
|
||||
|
||||
// setup gun psprite
|
||||
P_SetupPsprites(p);
|
||||
|
||||
// give all cards in death match mode
|
||||
if (deathmatch)
|
||||
for (i = 0; i < NUMCARDS; i++)
|
||||
p->cards[i] = true;
|
||||
|
||||
if (mthing->type - 1 == consoleplayer)
|
||||
{
|
||||
// wake up the status bar
|
||||
ST_Start();
|
||||
// wake up the heads up text
|
||||
HU_Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnMapThing
|
||||
// The fields of the mapthing should
|
||||
// already be in host byte order.
|
||||
//
|
||||
void P_SpawnMapThing(mapthing_t* mthing)
|
||||
{
|
||||
int i;
|
||||
int bit;
|
||||
mobj_t* mobj;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
|
||||
// count deathmatch start positions
|
||||
if (mthing->type == 11)
|
||||
{
|
||||
if (deathmatch_p < &deathmatchstarts[10])
|
||||
{
|
||||
doom_memcpy(deathmatch_p, mthing, sizeof(*mthing));
|
||||
deathmatch_p++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// check for players specially
|
||||
if (mthing->type <= 4)
|
||||
{
|
||||
// save spots for respawning in network games
|
||||
playerstarts[mthing->type - 1] = *mthing;
|
||||
if (!deathmatch)
|
||||
P_SpawnPlayer(mthing);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// check for apropriate skill level
|
||||
if (!netgame && (mthing->options & 16))
|
||||
return;
|
||||
|
||||
if (gameskill == sk_baby)
|
||||
bit = 1;
|
||||
else if (gameskill == sk_nightmare)
|
||||
bit = 4;
|
||||
else
|
||||
bit = 1 << (gameskill - 1);
|
||||
|
||||
if (!(mthing->options & bit))
|
||||
return;
|
||||
|
||||
// find which type to spawn
|
||||
for (i = 0; i < NUMMOBJTYPES; i++)
|
||||
if (mthing->type == mobjinfo[i].doomednum)
|
||||
break;
|
||||
|
||||
if (i == NUMMOBJTYPES)
|
||||
{
|
||||
//I_Error("Error: P_SpawnMapThing: Unknown type %i at (%i, %i)",
|
||||
// mthing->type,
|
||||
// mthing->x, mthing->y);
|
||||
|
||||
|
||||
doom_strcpy(error_buf, "Error: P_SpawnMapThing: Unknown type ");
|
||||
doom_concat(error_buf, doom_itoa(mthing->type, 10));
|
||||
doom_concat(error_buf, " at (");
|
||||
doom_concat(error_buf, doom_itoa(mthing->x, 10));
|
||||
doom_concat(error_buf, ", ");
|
||||
doom_concat(error_buf, doom_itoa(mthing->y, 10));
|
||||
doom_concat(error_buf, ")");
|
||||
I_Error(error_buf);
|
||||
}
|
||||
|
||||
// don't spawn keycards and players in deathmatch
|
||||
if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
|
||||
return;
|
||||
|
||||
// don't spawn any monsters if -nomonsters
|
||||
if (nomonsters
|
||||
&& (i == MT_SKULL
|
||||
|| (mobjinfo[i].flags & MF_COUNTKILL)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// spawn it
|
||||
x = mthing->x << FRACBITS;
|
||||
y = mthing->y << FRACBITS;
|
||||
|
||||
if (mobjinfo[i].flags & MF_SPAWNCEILING)
|
||||
z = ONCEILINGZ;
|
||||
else
|
||||
z = ONFLOORZ;
|
||||
|
||||
mobj = P_SpawnMobj(x, y, z, i);
|
||||
mobj->spawnpoint = *mthing;
|
||||
|
||||
if (mobj->tics > 0)
|
||||
mobj->tics = 1 + (P_Random() % mobj->tics);
|
||||
if (mobj->flags & MF_COUNTKILL)
|
||||
totalkills++;
|
||||
if (mobj->flags & MF_COUNTITEM)
|
||||
totalitems++;
|
||||
|
||||
mobj->angle = ANG45 * (mthing->angle / 45);
|
||||
if (mthing->options & MTF_AMBUSH)
|
||||
mobj->flags |= MF_AMBUSH;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GAME SPAWN FUNCTIONS
|
||||
//
|
||||
|
||||
//
|
||||
// P_SpawnPuff
|
||||
//
|
||||
void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
mobj_t* th;
|
||||
|
||||
z += ((P_Random() - P_Random()) << 10);
|
||||
|
||||
th = P_SpawnMobj(x, y, z, MT_PUFF);
|
||||
th->momz = FRACUNIT;
|
||||
th->tics -= P_Random() & 3;
|
||||
|
||||
if (th->tics < 1)
|
||||
th->tics = 1;
|
||||
|
||||
// don't make punches spark on the wall
|
||||
if (attackrange == MELEERANGE)
|
||||
P_SetMobjState(th, S_PUFF3);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnBlood
|
||||
//
|
||||
void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage)
|
||||
{
|
||||
mobj_t* th;
|
||||
|
||||
z += ((P_Random() - P_Random()) << 10);
|
||||
th = P_SpawnMobj(x, y, z, MT_BLOOD);
|
||||
th->momz = FRACUNIT * 2;
|
||||
th->tics -= P_Random() & 3;
|
||||
|
||||
if (th->tics < 1)
|
||||
th->tics = 1;
|
||||
|
||||
if (damage <= 12 && damage >= 9)
|
||||
P_SetMobjState(th, S_BLOOD2);
|
||||
else if (damage < 9)
|
||||
P_SetMobjState(th, S_BLOOD3);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CheckMissileSpawn
|
||||
// Moves the missile forward a bit
|
||||
// and possibly explodes it right there.
|
||||
//
|
||||
void P_CheckMissileSpawn(mobj_t* th)
|
||||
{
|
||||
th->tics -= P_Random() & 3;
|
||||
if (th->tics < 1)
|
||||
th->tics = 1;
|
||||
|
||||
// move a little forward so an angle can
|
||||
// be computed if it immediately explodes
|
||||
th->x += (th->momx >> 1);
|
||||
th->y += (th->momy >> 1);
|
||||
th->z += (th->momz >> 1);
|
||||
|
||||
if (!P_TryMove(th, th->x, th->y))
|
||||
P_ExplodeMissile(th);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnMissile
|
||||
//
|
||||
mobj_t* P_SpawnMissile(mobj_t* source, mobj_t* dest, mobjtype_t type)
|
||||
{
|
||||
mobj_t* th;
|
||||
angle_t an;
|
||||
int dist;
|
||||
|
||||
th = P_SpawnMobj(source->x,
|
||||
source->y,
|
||||
source->z + 4 * 8 * FRACUNIT, type);
|
||||
|
||||
if (th->info->seesound)
|
||||
S_StartSound(th, th->info->seesound);
|
||||
|
||||
th->target = source; // where it came from
|
||||
an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
|
||||
|
||||
// fuzzy player
|
||||
if (dest->flags & MF_SHADOW)
|
||||
an += (P_Random() - P_Random()) << 20;
|
||||
|
||||
th->angle = an;
|
||||
an >>= ANGLETOFINESHIFT;
|
||||
th->momx = FixedMul(th->info->speed, finecosine[an]);
|
||||
th->momy = FixedMul(th->info->speed, finesine[an]);
|
||||
|
||||
dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
|
||||
dist = dist / th->info->speed;
|
||||
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
th->momz = (dest->z - source->z) / dist;
|
||||
P_CheckMissileSpawn(th);
|
||||
|
||||
return th;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnPlayerMissile
|
||||
// Tries to aim at a nearby monster
|
||||
//
|
||||
void P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type)
|
||||
{
|
||||
mobj_t* th;
|
||||
angle_t an;
|
||||
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
fixed_t slope;
|
||||
|
||||
// see which target is to be aimed at
|
||||
an = source->angle;
|
||||
slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
an += 1 << 26;
|
||||
slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
an -= 2 << 26;
|
||||
slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT);
|
||||
}
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
an = source->angle;
|
||||
slope = 0;
|
||||
}
|
||||
}
|
||||
|
||||
x = source->x;
|
||||
y = source->y;
|
||||
z = source->z + 4 * 8 * FRACUNIT;
|
||||
|
||||
th = P_SpawnMobj(x, y, z, type);
|
||||
|
||||
if (th->info->seesound)
|
||||
S_StartSound(th, th->info->seesound);
|
||||
|
||||
th->target = source;
|
||||
th->angle = an;
|
||||
th->momx = FixedMul(th->info->speed,
|
||||
finecosine[an >> ANGLETOFINESHIFT]);
|
||||
th->momy = FixedMul(th->info->speed,
|
||||
finesine[an >> ANGLETOFINESHIFT]);
|
||||
th->momz = FixedMul(th->info->speed, slope);
|
||||
|
||||
P_CheckMissileSpawn(th);
|
||||
}
|
286
src/DOOM/p_mobj.h
Normal file
286
src/DOOM/p_mobj.h
Normal file
@ -0,0 +1,286 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Map Objects, MObj, definition and handling.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_MOBJ__
|
||||
#define __P_MOBJ__
|
||||
|
||||
|
||||
// Basics.
|
||||
#include "tables.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
// We need the thinker_t stuff.
|
||||
#include "d_think.h"
|
||||
|
||||
// We need the WAD data structure for Map things,
|
||||
// from the THINGS lump.
|
||||
#include "doomdata.h"
|
||||
|
||||
// States are tied to finite states are
|
||||
// tied to animation frames.
|
||||
// Needs precompiled tables/data structures.
|
||||
#include "info.h"
|
||||
|
||||
|
||||
//
|
||||
// NOTES: mobj_t
|
||||
//
|
||||
// mobj_ts are used to tell the refresh where to draw an image,
|
||||
// tell the world simulation when objects are contacted,
|
||||
// and tell the sound driver how to position a sound.
|
||||
//
|
||||
// The refresh uses the next and prev links to follow
|
||||
// lists of things in sectors as they are being drawn.
|
||||
// The sprite, frame, and angle elements determine which patch_t
|
||||
// is used to draw the sprite if it is visible.
|
||||
// The sprite and frame values are allmost allways set
|
||||
// from state_t structures.
|
||||
// The statescr.exe utility generates the states.h and states.c
|
||||
// files that contain the sprite/frame numbers from the
|
||||
// statescr.txt source file.
|
||||
// The xyz origin point represents a point at the bottom middle
|
||||
// of the sprite (between the feet of a biped).
|
||||
// This is the default origin position for patch_ts grabbed
|
||||
// with lumpy.exe.
|
||||
// A walking creature will have its z equal to the floor
|
||||
// it is standing on.
|
||||
//
|
||||
// The sound code uses the x,y, and subsector fields
|
||||
// to do stereo positioning of any sound effited by the mobj_t.
|
||||
//
|
||||
// The play simulation uses the blocklinks, x,y,z, radius, height
|
||||
// to determine when mobj_ts are touching each other,
|
||||
// touching lines in the map, or hit by trace lines (gunshots,
|
||||
// lines of sight, etc).
|
||||
// The mobj_t->flags element has various bit flags
|
||||
// used by the simulation.
|
||||
//
|
||||
// Every mobj_t is linked into a single sector
|
||||
// based on its origin coordinates.
|
||||
// The subsector_t is found with R_PointInSubsector(x,y),
|
||||
// and the sector_t can be found with subsector->sector.
|
||||
// The sector links are only used by the rendering code,
|
||||
// the play simulation does not care about them at all.
|
||||
//
|
||||
// Any mobj_t that needs to be acted upon by something else
|
||||
// in the play world (block movement, be shot, etc) will also
|
||||
// need to be linked into the blockmap.
|
||||
// If the thing has the MF_NOBLOCK flag set, it will not use
|
||||
// the block links. It can still interact with other things,
|
||||
// but only as the instigator (missiles will run into other
|
||||
// things, but nothing can run into a missile).
|
||||
// Each block in the grid is 128*128 units, and knows about
|
||||
// every line_t that it contains a piece of, and every
|
||||
// interactable mobj_t that has its origin contained.
|
||||
//
|
||||
// A valid mobj_t is a mobj_t that has the proper subsector_t
|
||||
// filled in for its xy coordinates and is linked into the
|
||||
// sector from which the subsector was made, or has the
|
||||
// MF_NOSECTOR flag set (the subsector_t needs to be valid
|
||||
// even if MF_NOSECTOR is set), and is linked into a blockmap
|
||||
// block or has the MF_NOBLOCKMAP flag set.
|
||||
// Links should only be modified by the P_[Un]SetThingPosition()
|
||||
// functions.
|
||||
// Do not change the MF_NO? flags while a thing is valid.
|
||||
//
|
||||
// Any questions?
|
||||
//
|
||||
|
||||
//
|
||||
// Misc. mobj flags
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Call P_SpecialThing when touched.
|
||||
MF_SPECIAL = 1,
|
||||
// Blocks.
|
||||
MF_SOLID = 2,
|
||||
// Can be hit.
|
||||
MF_SHOOTABLE = 4,
|
||||
// Don't use the sector links (invisible but touchable).
|
||||
MF_NOSECTOR = 8,
|
||||
// Don't use the blocklinks (inert but displayable)
|
||||
MF_NOBLOCKMAP = 16,
|
||||
|
||||
// Not to be activated by sound, deaf monster.
|
||||
MF_AMBUSH = 32,
|
||||
// Will try to attack right back.
|
||||
MF_JUSTHIT = 64,
|
||||
// Will take at least one step before attacking.
|
||||
MF_JUSTATTACKED = 128,
|
||||
// On level spawning (initial position),
|
||||
// hang from ceiling instead of stand on floor.
|
||||
MF_SPAWNCEILING = 256,
|
||||
// Don't apply gravity (every tic),
|
||||
// that is, object will float, keeping current height
|
||||
// or changing it actively.
|
||||
MF_NOGRAVITY = 512,
|
||||
|
||||
// Movement flags.
|
||||
// This allows jumps from high places.
|
||||
MF_DROPOFF = 0x400,
|
||||
// For players, will pick up items.
|
||||
MF_PICKUP = 0x800,
|
||||
// Player cheat. ???
|
||||
MF_NOCLIP = 0x1000,
|
||||
// Player: keep info about sliding along walls.
|
||||
MF_SLIDE = 0x2000,
|
||||
// Allow moves to any height, no gravity.
|
||||
// For active floaters, e.g. cacodemons, pain elementals.
|
||||
MF_FLOAT = 0x4000,
|
||||
// Don't cross lines
|
||||
// ??? or look at heights on teleport.
|
||||
MF_TELEPORT = 0x8000,
|
||||
// Don't hit same species, explode on block.
|
||||
// Player missiles as well as fireballs of various kinds.
|
||||
MF_MISSILE = 0x10000,
|
||||
// Dropped by a demon, not level spawned.
|
||||
// E.g. ammo clips dropped by dying former humans.
|
||||
MF_DROPPED = 0x20000,
|
||||
// Use fuzzy draw (shadow demons or spectres),
|
||||
// temporary player invisibility powerup.
|
||||
MF_SHADOW = 0x40000,
|
||||
// Flag: don't bleed when shot (use puff),
|
||||
// barrels and shootable furniture shall not bleed.
|
||||
MF_NOBLOOD = 0x80000,
|
||||
// Don't stop moving halfway off a step,
|
||||
// that is, have dead bodies slide down all the way.
|
||||
MF_CORPSE = 0x100000,
|
||||
// Floating to a height for a move, ???
|
||||
// don't auto float to target's height.
|
||||
MF_INFLOAT = 0x200000,
|
||||
|
||||
// On kill, count this enemy object
|
||||
// towards intermission kill total.
|
||||
// Happy gathering.
|
||||
MF_COUNTKILL = 0x400000,
|
||||
|
||||
// On picking up, count this item object
|
||||
// towards intermission item total.
|
||||
MF_COUNTITEM = 0x800000,
|
||||
|
||||
// Special handling: skull in flight.
|
||||
// Neither a cacodemon nor a missile.
|
||||
MF_SKULLFLY = 0x1000000,
|
||||
|
||||
// Don't spawn this object
|
||||
// in death match mode (e.g. key cards).
|
||||
MF_NOTDMATCH = 0x2000000,
|
||||
|
||||
// Player sprites in multiplayer modes are modified
|
||||
// using an internal color lookup table for re-indexing.
|
||||
// If 0x4 0x8 or 0xc,
|
||||
// use a translation table for player colormaps
|
||||
MF_TRANSLATION = 0xc000000,
|
||||
// Hmm ???.
|
||||
MF_TRANSSHIFT = 26
|
||||
} mobjflag_t;
|
||||
|
||||
|
||||
// Map Object definition.
|
||||
typedef struct mobj_s
|
||||
{
|
||||
// List: thinker links.
|
||||
thinker_t thinker;
|
||||
|
||||
// Info for drawing: position.
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
|
||||
// More list: links in sector (if needed)
|
||||
struct mobj_s* snext;
|
||||
struct mobj_s* sprev;
|
||||
|
||||
//More drawing info: to determine current sprite.
|
||||
angle_t angle; // orientation
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
int frame; // might be ORed with FF_FULLBRIGHT
|
||||
|
||||
// Interaction info, by BLOCKMAP.
|
||||
// Links in blocks (if needed).
|
||||
struct mobj_s* bnext;
|
||||
struct mobj_s* bprev;
|
||||
|
||||
struct subsector_s* subsector;
|
||||
|
||||
// The closest interval over all contacted Sectors.
|
||||
fixed_t floorz;
|
||||
fixed_t ceilingz;
|
||||
|
||||
// For movement checking.
|
||||
fixed_t radius;
|
||||
fixed_t height;
|
||||
|
||||
// Momentums, used to update position.
|
||||
fixed_t momx;
|
||||
fixed_t momy;
|
||||
fixed_t momz;
|
||||
|
||||
// If == validcount, already checked.
|
||||
int validcount;
|
||||
|
||||
mobjtype_t type;
|
||||
mobjinfo_t* info; // &mobjinfo[mobj->type]
|
||||
|
||||
int tics; // state tic counter
|
||||
state_t* state;
|
||||
int flags;
|
||||
int health;
|
||||
|
||||
// Movement direction, movement generation (zig-zagging).
|
||||
int movedir; // 0-7
|
||||
int movecount; // when 0, select a new dir
|
||||
|
||||
// Thing being chased/attacked (or 0),
|
||||
// also the originator for missiles.
|
||||
struct mobj_s* target;
|
||||
|
||||
// Reaction time: if non 0, don't attack yet.
|
||||
// Used by player to freeze a bit after teleporting.
|
||||
int reactiontime;
|
||||
|
||||
// If >0, the target will be chased
|
||||
// no matter what (even if shot)
|
||||
int threshold;
|
||||
|
||||
// Additional info record for player avatars only.
|
||||
// Only valid if type == MT_PLAYER
|
||||
struct player_s* player;
|
||||
|
||||
// Player number last looked for.
|
||||
int lastlook;
|
||||
|
||||
// For nightmare respawn.
|
||||
mapthing_t spawnpoint;
|
||||
|
||||
// Thing being chased/attacked for tracers.
|
||||
struct mobj_s* tracer;
|
||||
} mobj_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
298
src/DOOM/p_plats.c
Normal file
298
src/DOOM/p_plats.c
Normal file
@ -0,0 +1,298 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Plats (i.e. elevator platforms) code, raising/lowering.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_random.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
#include "sounds.h" // Data.
|
||||
|
||||
|
||||
plat_t* activeplats[MAXPLATS];
|
||||
|
||||
|
||||
//
|
||||
// Move a plat up and down
|
||||
//
|
||||
void T_PlatRaise(plat_t* plat)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch (plat->status)
|
||||
{
|
||||
case up:
|
||||
res = T_MovePlane(plat->sector,
|
||||
plat->speed,
|
||||
plat->high,
|
||||
plat->crush, 0, 1);
|
||||
|
||||
if (plat->type == raiseAndChange
|
||||
|| plat->type == raiseToNearestAndChange)
|
||||
{
|
||||
if (!(leveltime & 7))
|
||||
S_StartSound((mobj_t*)&plat->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
}
|
||||
|
||||
if (res == crushed && (!plat->crush))
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t*)&plat->sector->soundorg,
|
||||
sfx_pstart);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res == pastdest)
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = waiting;
|
||||
S_StartSound((mobj_t*)&plat->sector->soundorg,
|
||||
sfx_pstop);
|
||||
|
||||
switch (plat->type)
|
||||
{
|
||||
case blazeDWUS:
|
||||
case downWaitUpStay:
|
||||
P_RemoveActivePlat(plat);
|
||||
break;
|
||||
|
||||
case raiseAndChange:
|
||||
case raiseToNearestAndChange:
|
||||
P_RemoveActivePlat(plat);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case down:
|
||||
res = T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1);
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = waiting;
|
||||
S_StartSound((mobj_t*)&plat->sector->soundorg, sfx_pstop);
|
||||
}
|
||||
break;
|
||||
|
||||
case waiting:
|
||||
if (!--plat->count)
|
||||
{
|
||||
if (plat->sector->floorheight == plat->low)
|
||||
plat->status = up;
|
||||
else
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t*)&plat->sector->soundorg, sfx_pstart);
|
||||
}
|
||||
|
||||
case in_stasis:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Do Platforms
|
||||
// "amount" is only used for SOME platforms.
|
||||
//
|
||||
int EV_DoPlat(line_t* line, plattype_e type, int amount)
|
||||
{
|
||||
plat_t* plat;
|
||||
int secnum;
|
||||
int rtn;
|
||||
sector_t* sec;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
// Activate all <type> plats that are in_stasis
|
||||
switch (type)
|
||||
{
|
||||
case perpetualRaise:
|
||||
P_ActivateInStasis(line->tag);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
// Find lowest & highest floors around sector
|
||||
rtn = 1;
|
||||
plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&plat->thinker);
|
||||
|
||||
plat->type = type;
|
||||
plat->sector = sec;
|
||||
plat->sector->specialdata = plat;
|
||||
plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
|
||||
plat->crush = false;
|
||||
plat->tag = line->tag;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case raiseToNearestAndChange:
|
||||
plat->speed = PLATSPEED / 2;
|
||||
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
|
||||
plat->high = P_FindNextHighestFloor(sec, sec->floorheight);
|
||||
plat->wait = 0;
|
||||
plat->status = up;
|
||||
// NO MORE DAMAGE, IF APPLICABLE
|
||||
sec->special = 0;
|
||||
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_stnmov);
|
||||
break;
|
||||
|
||||
case raiseAndChange:
|
||||
plat->speed = PLATSPEED / 2;
|
||||
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
|
||||
plat->high = sec->floorheight + amount * FRACUNIT;
|
||||
plat->wait = 0;
|
||||
plat->status = up;
|
||||
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_stnmov);
|
||||
break;
|
||||
|
||||
case downWaitUpStay:
|
||||
plat->speed = PLATSPEED * 4;
|
||||
plat->low = P_FindLowestFloorSurrounding(sec);
|
||||
|
||||
if (plat->low > sec->floorheight)
|
||||
plat->low = sec->floorheight;
|
||||
|
||||
plat->high = sec->floorheight;
|
||||
plat->wait = 35 * PLATWAIT;
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_pstart);
|
||||
break;
|
||||
|
||||
case blazeDWUS:
|
||||
plat->speed = PLATSPEED * 8;
|
||||
plat->low = P_FindLowestFloorSurrounding(sec);
|
||||
|
||||
if (plat->low > sec->floorheight)
|
||||
plat->low = sec->floorheight;
|
||||
|
||||
plat->high = sec->floorheight;
|
||||
plat->wait = 35 * PLATWAIT;
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_pstart);
|
||||
break;
|
||||
|
||||
case perpetualRaise:
|
||||
plat->speed = PLATSPEED;
|
||||
plat->low = P_FindLowestFloorSurrounding(sec);
|
||||
|
||||
if (plat->low > sec->floorheight)
|
||||
plat->low = sec->floorheight;
|
||||
|
||||
plat->high = P_FindHighestFloorSurrounding(sec);
|
||||
|
||||
if (plat->high < sec->floorheight)
|
||||
plat->high = sec->floorheight;
|
||||
|
||||
plat->wait = 35 * PLATWAIT;
|
||||
plat->status = P_Random() & 1;
|
||||
|
||||
S_StartSound((mobj_t*)&sec->soundorg, sfx_pstart);
|
||||
break;
|
||||
}
|
||||
P_AddActivePlat(plat);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void P_ActivateInStasis(int tag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXPLATS; i++)
|
||||
if (activeplats[i]
|
||||
&& (activeplats[i])->tag == tag
|
||||
&& (activeplats[i])->status == in_stasis)
|
||||
{
|
||||
(activeplats[i])->status = (activeplats[i])->oldstatus;
|
||||
(activeplats[i])->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
|
||||
}
|
||||
}
|
||||
|
||||
void EV_StopPlat(line_t* line)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < MAXPLATS; j++)
|
||||
if (activeplats[j]
|
||||
&& ((activeplats[j])->status != in_stasis)
|
||||
&& ((activeplats[j])->tag == line->tag))
|
||||
{
|
||||
(activeplats[j])->oldstatus = (activeplats[j])->status;
|
||||
(activeplats[j])->status = in_stasis;
|
||||
(activeplats[j])->thinker.function.acv = (actionf_v)0;
|
||||
}
|
||||
}
|
||||
|
||||
void P_AddActivePlat(plat_t* plat)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXPLATS; i++)
|
||||
if (activeplats[i] == 0)
|
||||
{
|
||||
activeplats[i] = plat;
|
||||
return;
|
||||
}
|
||||
I_Error("Error: P_AddActivePlat: no more plats!");
|
||||
}
|
||||
|
||||
void P_RemoveActivePlat(plat_t* plat)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAXPLATS; i++)
|
||||
if (plat == activeplats[i])
|
||||
{
|
||||
(activeplats[i])->sector->specialdata = 0;
|
||||
P_RemoveThinker(&(activeplats[i])->thinker);
|
||||
activeplats[i] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
I_Error("Error: P_RemoveActivePlat: can't find plat!");
|
||||
}
|
778
src/DOOM/p_pspr.c
Normal file
778
src/DOOM/p_pspr.c
Normal file
@ -0,0 +1,778 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Weapon sprite animation, weapon objects.
|
||||
// Action functions for weapons.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_event.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "sounds.h" // Data.
|
||||
#include "p_pspr.h"
|
||||
|
||||
|
||||
#define LOWERSPEED (FRACUNIT*6)
|
||||
#define RAISESPEED (FRACUNIT*6)
|
||||
|
||||
#define WEAPONBOTTOM (128*FRACUNIT)
|
||||
#define WEAPONTOP (32*FRACUNIT)
|
||||
|
||||
// plasma cells for a bfg attack
|
||||
#define BFGCELLS 40
|
||||
|
||||
|
||||
fixed_t swingx;
|
||||
fixed_t swingy;
|
||||
fixed_t bulletslope;
|
||||
|
||||
|
||||
//
|
||||
// P_SetPsprite
|
||||
//
|
||||
void P_SetPsprite(player_t* player, int position, statenum_t stnum)
|
||||
{
|
||||
pspdef_t* psp;
|
||||
state_t* state;
|
||||
|
||||
psp = &player->psprites[position];
|
||||
|
||||
do
|
||||
{
|
||||
if (!stnum)
|
||||
{
|
||||
// object removed itself
|
||||
psp->state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
state = &states[stnum];
|
||||
psp->state = state;
|
||||
psp->tics = state->tics; // could be 0
|
||||
|
||||
if (state->misc1)
|
||||
{
|
||||
// coordinate set
|
||||
psp->sx = state->misc1 << FRACBITS;
|
||||
psp->sy = state->misc2 << FRACBITS;
|
||||
}
|
||||
|
||||
// Call action routine.
|
||||
// Modified handling.
|
||||
if (state->action.acp2)
|
||||
{
|
||||
state->action.acp2(player, psp);
|
||||
if (!psp->state)
|
||||
break;
|
||||
}
|
||||
|
||||
stnum = psp->state->nextstate;
|
||||
|
||||
} while (!psp->tics);
|
||||
// an initial state of 0 could cycle through
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_BringUpWeapon
|
||||
// Starts bringing the pending weapon up
|
||||
// from the bottom of the screen.
|
||||
// Uses player
|
||||
//
|
||||
void P_BringUpWeapon(player_t* player)
|
||||
{
|
||||
statenum_t newstate;
|
||||
|
||||
if (player->pendingweapon == wp_nochange)
|
||||
player->pendingweapon = player->readyweapon;
|
||||
|
||||
if (player->pendingweapon == wp_chainsaw)
|
||||
S_StartSound(player->mo, sfx_sawup);
|
||||
|
||||
newstate = weaponinfo[player->pendingweapon].upstate;
|
||||
|
||||
player->pendingweapon = wp_nochange;
|
||||
player->psprites[ps_weapon].sy = WEAPONBOTTOM;
|
||||
|
||||
P_SetPsprite(player, ps_weapon, newstate);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CheckAmmo
|
||||
// Returns true if there is enough ammo to shoot.
|
||||
// If not, selects the next weapon to use.
|
||||
//
|
||||
doom_boolean P_CheckAmmo(player_t* player)
|
||||
{
|
||||
ammotype_t ammo;
|
||||
int count;
|
||||
|
||||
ammo = weaponinfo[player->readyweapon].ammo;
|
||||
|
||||
// Minimal amount for one shot varies.
|
||||
if (player->readyweapon == wp_bfg)
|
||||
count = BFGCELLS;
|
||||
else if (player->readyweapon == wp_supershotgun)
|
||||
count = 2; // Double barrel.
|
||||
else
|
||||
count = 1; // Regular.
|
||||
|
||||
// Some do not need ammunition anyway.
|
||||
// Return if current ammunition sufficient.
|
||||
if (ammo == am_noammo || player->ammo[ammo] >= count)
|
||||
return true;
|
||||
|
||||
// Out of ammo, pick a weapon to change to.
|
||||
// Preferences are set here.
|
||||
do
|
||||
{
|
||||
if (player->weaponowned[wp_plasma]
|
||||
&& player->ammo[am_cell]
|
||||
&& (gamemode != shareware))
|
||||
{
|
||||
player->pendingweapon = wp_plasma;
|
||||
}
|
||||
else if (player->weaponowned[wp_supershotgun]
|
||||
&& player->ammo[am_shell] > 2
|
||||
&& (gamemode == commercial))
|
||||
{
|
||||
player->pendingweapon = wp_supershotgun;
|
||||
}
|
||||
else if (player->weaponowned[wp_chaingun]
|
||||
&& player->ammo[am_clip])
|
||||
{
|
||||
player->pendingweapon = wp_chaingun;
|
||||
}
|
||||
else if (player->weaponowned[wp_shotgun]
|
||||
&& player->ammo[am_shell])
|
||||
{
|
||||
player->pendingweapon = wp_shotgun;
|
||||
}
|
||||
else if (player->ammo[am_clip])
|
||||
{
|
||||
player->pendingweapon = wp_pistol;
|
||||
}
|
||||
else if (player->weaponowned[wp_chainsaw])
|
||||
{
|
||||
player->pendingweapon = wp_chainsaw;
|
||||
}
|
||||
else if (player->weaponowned[wp_missile]
|
||||
&& player->ammo[am_misl])
|
||||
{
|
||||
player->pendingweapon = wp_missile;
|
||||
}
|
||||
else if (player->weaponowned[wp_bfg]
|
||||
&& player->ammo[am_cell] > 40
|
||||
&& (gamemode != shareware))
|
||||
{
|
||||
player->pendingweapon = wp_bfg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If everything fails.
|
||||
player->pendingweapon = wp_fist;
|
||||
}
|
||||
|
||||
} while (player->pendingweapon == wp_nochange);
|
||||
|
||||
// Now set appropriate weapon overlay.
|
||||
P_SetPsprite(player,
|
||||
ps_weapon,
|
||||
weaponinfo[player->readyweapon].downstate);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_FireWeapon.
|
||||
//
|
||||
void P_FireWeapon(player_t* player)
|
||||
{
|
||||
statenum_t newstate;
|
||||
|
||||
if (!P_CheckAmmo(player))
|
||||
return;
|
||||
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK1);
|
||||
newstate = weaponinfo[player->readyweapon].atkstate;
|
||||
P_SetPsprite(player, ps_weapon, newstate);
|
||||
P_NoiseAlert(player->mo, player->mo);
|
||||
|
||||
// [pd] Stop gun bobbing when shooting
|
||||
pspdef_t* psp;
|
||||
psp = &player->psprites[ps_weapon];
|
||||
psp->sx = FRACUNIT;
|
||||
psp->sy = WEAPONTOP;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_DropWeapon
|
||||
// Player died, so put the weapon away.
|
||||
//
|
||||
void P_DropWeapon(player_t* player)
|
||||
{
|
||||
P_SetPsprite(player,
|
||||
ps_weapon,
|
||||
weaponinfo[player->readyweapon].downstate);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_WeaponReady
|
||||
// The player can fire the weapon
|
||||
// or change to another weapon at this time.
|
||||
// Follows after getting weapon up,
|
||||
// or after previous attack/fire sequence.
|
||||
//
|
||||
void A_WeaponReady(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
statenum_t newstate;
|
||||
int angle;
|
||||
|
||||
// get out of attack state
|
||||
if (player->mo->state == &states[S_PLAY_ATK1]
|
||||
|| player->mo->state == &states[S_PLAY_ATK2])
|
||||
{
|
||||
P_SetMobjState(player->mo, S_PLAY);
|
||||
}
|
||||
|
||||
if (player->readyweapon == wp_chainsaw
|
||||
&& psp->state == &states[S_SAW])
|
||||
{
|
||||
S_StartSound(player->mo, sfx_sawidl);
|
||||
}
|
||||
|
||||
// check for change
|
||||
// if player is dead, put the weapon away
|
||||
if (player->pendingweapon != wp_nochange || !player->health)
|
||||
{
|
||||
// change weapon
|
||||
// (pending weapon should allready be validated)
|
||||
newstate = weaponinfo[player->readyweapon].downstate;
|
||||
P_SetPsprite(player, ps_weapon, newstate);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for fire
|
||||
// the missile launcher and bfg do not auto fire
|
||||
if (player->cmd.buttons & BT_ATTACK)
|
||||
{
|
||||
if (!player->attackdown
|
||||
|| (player->readyweapon != wp_missile
|
||||
&& player->readyweapon != wp_bfg))
|
||||
{
|
||||
player->attackdown = true;
|
||||
P_FireWeapon(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
player->attackdown = false;
|
||||
|
||||
// bob the weapon based on movement speed
|
||||
angle = (128 * leveltime) & FINEMASK;
|
||||
psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]);
|
||||
angle &= FINEANGLES / 2 - 1;
|
||||
psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_ReFire
|
||||
// The player can re-fire the weapon
|
||||
// without lowering it entirely.
|
||||
//
|
||||
void A_ReFire(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
// check for fire
|
||||
// (if a weaponchange is pending, let it go through instead)
|
||||
if ((player->cmd.buttons & BT_ATTACK)
|
||||
&& player->pendingweapon == wp_nochange
|
||||
&& player->health)
|
||||
{
|
||||
player->refire++;
|
||||
P_FireWeapon(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->refire = 0;
|
||||
P_CheckAmmo(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void A_CheckReload(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
P_CheckAmmo(player);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_Lower
|
||||
// Lowers current weapon,
|
||||
// and changes weapon at bottom.
|
||||
//
|
||||
void A_Lower(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
psp->sy += LOWERSPEED;
|
||||
|
||||
// Is already down.
|
||||
if (psp->sy < WEAPONBOTTOM)
|
||||
return;
|
||||
|
||||
// Player is dead.
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
psp->sy = WEAPONBOTTOM;
|
||||
|
||||
// don't bring weapon back up
|
||||
return;
|
||||
}
|
||||
|
||||
// The old weapon has been lowered off the screen,
|
||||
// so change the weapon and start raising it
|
||||
if (!player->health)
|
||||
{
|
||||
// Player is dead, so keep the weapon off screen.
|
||||
P_SetPsprite(player, ps_weapon, S_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
player->readyweapon = player->pendingweapon;
|
||||
|
||||
P_BringUpWeapon(player);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_Raise
|
||||
//
|
||||
void A_Raise(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
statenum_t newstate;
|
||||
|
||||
psp->sy -= RAISESPEED;
|
||||
|
||||
if (psp->sy > WEAPONTOP)
|
||||
return;
|
||||
|
||||
psp->sy = WEAPONTOP;
|
||||
|
||||
// The weapon has been raised all the way,
|
||||
// so change to the ready state.
|
||||
newstate = weaponinfo[player->readyweapon].readystate;
|
||||
|
||||
P_SetPsprite(player, ps_weapon, newstate);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_GunFlash
|
||||
//
|
||||
void A_GunFlash(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK2);
|
||||
P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// WEAPON ATTACKS
|
||||
//
|
||||
|
||||
//
|
||||
// A_Punch
|
||||
//
|
||||
void A_Punch(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
angle_t angle;
|
||||
int damage;
|
||||
int slope;
|
||||
|
||||
damage = (P_Random() % 10 + 1) << 1;
|
||||
|
||||
if (player->powers[pw_strength])
|
||||
damage *= 10;
|
||||
|
||||
angle = player->mo->angle;
|
||||
angle += (P_Random() - P_Random()) << 18;
|
||||
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
|
||||
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_punch);
|
||||
player->mo->angle = R_PointToAngle2(player->mo->x,
|
||||
player->mo->y,
|
||||
linetarget->x,
|
||||
linetarget->y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_Saw
|
||||
//
|
||||
void A_Saw(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
angle_t angle;
|
||||
int damage;
|
||||
int slope;
|
||||
|
||||
damage = 2 * (P_Random() % 10 + 1);
|
||||
angle = player->mo->angle;
|
||||
angle += (P_Random() - P_Random()) << 18;
|
||||
|
||||
// use meleerange + 1 se the puff doesn't skip the flash
|
||||
slope = P_AimLineAttack(player->mo, angle, MELEERANGE + 1);
|
||||
P_LineAttack(player->mo, angle, MELEERANGE + 1, slope, damage);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_sawful);
|
||||
return;
|
||||
}
|
||||
S_StartSound(player->mo, sfx_sawhit);
|
||||
|
||||
// turn to face target
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y,
|
||||
linetarget->x, linetarget->y);
|
||||
if (angle - player->mo->angle > ANG180)
|
||||
{
|
||||
if (angle - player->mo->angle < -ANG90 / 20)
|
||||
player->mo->angle = angle + ANG90 / 21;
|
||||
else
|
||||
player->mo->angle -= ANG90 / 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (angle - player->mo->angle > ANG90 / 20)
|
||||
player->mo->angle = angle - ANG90 / 21;
|
||||
else
|
||||
player->mo->angle += ANG90 / 20;
|
||||
}
|
||||
player->mo->flags |= MF_JUSTATTACKED;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FireMissile
|
||||
//
|
||||
void A_FireMissile(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo]--;
|
||||
P_SpawnPlayerMissile(player->mo, MT_ROCKET);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FireBFG
|
||||
//
|
||||
void A_FireBFG(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS;
|
||||
P_SpawnPlayerMissile(player->mo, MT_BFG);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FirePlasma
|
||||
//
|
||||
void A_FirePlasma(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo]--;
|
||||
|
||||
P_SetPsprite(player,
|
||||
ps_flash,
|
||||
weaponinfo[player->readyweapon].flashstate + (P_Random() & 1));
|
||||
|
||||
P_SpawnPlayerMissile(player->mo, MT_PLASMA);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_BulletSlope
|
||||
// Sets a slope so a near miss is at aproximately
|
||||
// the height of the intended target
|
||||
//
|
||||
void P_BulletSlope(mobj_t* mo)
|
||||
{
|
||||
angle_t an;
|
||||
|
||||
// see which target is to be aimed at
|
||||
an = mo->angle;
|
||||
bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
an += 1 << 26;
|
||||
bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT);
|
||||
if (!linetarget)
|
||||
{
|
||||
an -= 2 << 26;
|
||||
bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GunShot
|
||||
//
|
||||
void P_GunShot(mobj_t* mo, doom_boolean accurate)
|
||||
{
|
||||
angle_t angle;
|
||||
int damage;
|
||||
|
||||
damage = 5 * (P_Random() % 3 + 1);
|
||||
angle = mo->angle;
|
||||
|
||||
if (!accurate)
|
||||
angle += (P_Random() - P_Random()) << 18;
|
||||
|
||||
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FirePistol
|
||||
//
|
||||
void A_FirePistol(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_pistol);
|
||||
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK2);
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo]--;
|
||||
|
||||
P_SetPsprite(player,
|
||||
ps_flash,
|
||||
weaponinfo[player->readyweapon].flashstate);
|
||||
|
||||
P_BulletSlope(player->mo);
|
||||
P_GunShot(player->mo, !player->refire);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FireShotgun
|
||||
//
|
||||
void A_FireShotgun(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
int i;
|
||||
|
||||
S_StartSound(player->mo, sfx_shotgn);
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK2);
|
||||
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo]--;
|
||||
|
||||
P_SetPsprite(player,
|
||||
ps_flash,
|
||||
weaponinfo[player->readyweapon].flashstate);
|
||||
|
||||
P_BulletSlope(player->mo);
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
P_GunShot(player->mo, false);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FireShotgun2
|
||||
//
|
||||
void A_FireShotgun2(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
int i;
|
||||
angle_t angle;
|
||||
int damage;
|
||||
|
||||
|
||||
S_StartSound(player->mo, sfx_dshtgn);
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK2);
|
||||
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo] -= 2;
|
||||
|
||||
P_SetPsprite(player,
|
||||
ps_flash,
|
||||
weaponinfo[player->readyweapon].flashstate);
|
||||
|
||||
P_BulletSlope(player->mo);
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
damage = 5 * (P_Random() % 3 + 1);
|
||||
angle = player->mo->angle;
|
||||
angle += (P_Random() - P_Random()) << 19;
|
||||
P_LineAttack(player->mo,
|
||||
angle,
|
||||
MISSILERANGE,
|
||||
bulletslope + ((P_Random() - P_Random()) << 5), damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_FireCGun
|
||||
//
|
||||
void A_FireCGun(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_pistol);
|
||||
|
||||
if (!player->ammo[weaponinfo[player->readyweapon].ammo])
|
||||
return;
|
||||
|
||||
P_SetMobjState(player->mo, S_PLAY_ATK2);
|
||||
player->ammo[weaponinfo[player->readyweapon].ammo]--;
|
||||
|
||||
P_SetPsprite(player,
|
||||
ps_flash,
|
||||
weaponinfo[player->readyweapon].flashstate
|
||||
+ psp->state
|
||||
- &states[S_CHAIN1]);
|
||||
|
||||
P_BulletSlope(player->mo);
|
||||
|
||||
P_GunShot(player->mo, !player->refire);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ?
|
||||
//
|
||||
void A_Light0(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->extralight = 0;
|
||||
}
|
||||
|
||||
void A_Light1(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->extralight = 1;
|
||||
}
|
||||
|
||||
void A_Light2(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
player->extralight = 2;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_BFGSpray
|
||||
// Spawn a BFG explosion on every monster in view
|
||||
//
|
||||
void A_BFGSpray(mobj_t* mo)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int damage;
|
||||
angle_t an;
|
||||
|
||||
// offset angles from its attack angle
|
||||
for (i = 0; i < 40; i++)
|
||||
{
|
||||
an = mo->angle - ANG90 / 2 + ANG90 / 40 * i;
|
||||
|
||||
// mo->target is the originator (player)
|
||||
// of the missile
|
||||
P_AimLineAttack(mo->target, an, 16 * 64 * FRACUNIT);
|
||||
|
||||
if (!linetarget)
|
||||
continue;
|
||||
|
||||
P_SpawnMobj(linetarget->x,
|
||||
linetarget->y,
|
||||
linetarget->z + (linetarget->height >> 2),
|
||||
MT_EXTRABFG);
|
||||
|
||||
damage = 0;
|
||||
for (j = 0; j < 15; j++)
|
||||
damage += (P_Random() & 7) + 1;
|
||||
|
||||
P_DamageMobj(linetarget, mo->target, mo->target, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_BFGsound
|
||||
//
|
||||
void A_BFGsound(player_t* player, pspdef_t* psp)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_bfg);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SetupPsprites
|
||||
// Called at start of level for each player.
|
||||
//
|
||||
void P_SetupPsprites(player_t* player)
|
||||
{
|
||||
int i;
|
||||
|
||||
// remove all psprites
|
||||
for (i = 0; i < NUMPSPRITES; i++)
|
||||
player->psprites[i].state = 0;
|
||||
|
||||
// spawn the gun
|
||||
player->pendingweapon = player->readyweapon;
|
||||
P_BringUpWeapon(player);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_MovePsprites
|
||||
// Called every tic by player thinking routine.
|
||||
//
|
||||
void P_MovePsprites(player_t* player)
|
||||
{
|
||||
int i;
|
||||
pspdef_t* psp;
|
||||
state_t* state;
|
||||
|
||||
psp = &player->psprites[0];
|
||||
for (i = 0; i < NUMPSPRITES; i++, psp++)
|
||||
{
|
||||
// a null state means not active
|
||||
if ((state = psp->state))
|
||||
{
|
||||
// drop tic count and possibly change state
|
||||
|
||||
// a -1 tic count never changes
|
||||
if (psp->tics != -1)
|
||||
{
|
||||
psp->tics--;
|
||||
if (!psp->tics)
|
||||
P_SetPsprite(player, i, psp->state->nextstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
|
||||
player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
|
||||
}
|
75
src/DOOM/p_pspr.h
Normal file
75
src/DOOM/p_pspr.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Sprite animation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __P_PSPR__
|
||||
#define __P_PSPR__
|
||||
|
||||
// Basic data types.
|
||||
// Needs fixed point, and BAM angles.
|
||||
#include "m_fixed.h"
|
||||
#include "tables.h"
|
||||
|
||||
// Needs to include the precompiled
|
||||
// sprite animation tables.
|
||||
// Header generated by multigen utility.
|
||||
// This includes all the data for thing animation,
|
||||
// i.e. the Thing Atrributes table
|
||||
// and the Frame Sequence table.
|
||||
#include "info.h"
|
||||
|
||||
//
|
||||
// Frame flags:
|
||||
// handles maximum brightness (torches, muzzle flare, light sources)
|
||||
//
|
||||
#define FF_FULLBRIGHT 0x8000 // flag in thing->frame
|
||||
#define FF_FRAMEMASK 0x7fff
|
||||
|
||||
|
||||
//
|
||||
// Overlay psprites are scaled shapes
|
||||
// drawn directly on the view screen,
|
||||
// coordinates are given for a 320*200 view screen.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
ps_weapon,
|
||||
ps_flash,
|
||||
NUMPSPRITES
|
||||
} psprnum_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
state_t* state; // a 0 state means not active
|
||||
int tics;
|
||||
fixed_t sx;
|
||||
fixed_t sy;
|
||||
} pspdef_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
584
src/DOOM/p_saveg.c
Normal file
584
src/DOOM/p_saveg.c
Normal file
@ -0,0 +1,584 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Archiving: SaveGame I/O.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "z_zone.h"
|
||||
#include "p_local.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
// Pads save_p to a 4-byte boundary
|
||||
// so that the load/save works on SGI&Gecko.
|
||||
#define PADSAVEP() save_p += (4 - ((long long)save_p & 3)) & 3
|
||||
|
||||
|
||||
byte* save_p;
|
||||
|
||||
|
||||
// TODO: [pd] We are loading/saving raw pointers. It will not work with saves from 32bits system. We need to rewrite those functions.
|
||||
//
|
||||
// P_ArchivePlayers
|
||||
//
|
||||
void P_ArchivePlayers(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
player_t* dest;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
PADSAVEP();
|
||||
|
||||
dest = (player_t*)save_p;
|
||||
doom_memcpy(dest, &players[i], sizeof(player_t));
|
||||
save_p += sizeof(player_t);
|
||||
for (j = 0; j < NUMPSPRITES; j++)
|
||||
{
|
||||
if (dest->psprites[j].state)
|
||||
{
|
||||
dest->psprites[j].state
|
||||
= (state_t*)(dest->psprites[j].state - states);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_UnArchivePlayers
|
||||
//
|
||||
void P_UnArchivePlayers(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
PADSAVEP();
|
||||
|
||||
doom_memcpy(&players[i], save_p, sizeof(player_t));
|
||||
save_p += sizeof(player_t);
|
||||
|
||||
// will be set when unarc thinker
|
||||
players[i].mo = 0;
|
||||
players[i].message = 0;
|
||||
players[i].attacker = 0;
|
||||
|
||||
for (j = 0; j < NUMPSPRITES; j++)
|
||||
{
|
||||
if (players[i].psprites[j].state)
|
||||
{
|
||||
players[i].psprites[j].state
|
||||
= &states[(long long)players[i].psprites[j].state];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_ArchiveWorld
|
||||
//
|
||||
void P_ArchiveWorld(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sector_t* sec;
|
||||
line_t* li;
|
||||
side_t* si;
|
||||
short* put;
|
||||
|
||||
put = (short*)save_p;
|
||||
|
||||
// do sectors
|
||||
for (i = 0, sec = sectors; i < numsectors; i++, sec++)
|
||||
{
|
||||
*put++ = sec->floorheight >> FRACBITS;
|
||||
*put++ = sec->ceilingheight >> FRACBITS;
|
||||
*put++ = sec->floorpic;
|
||||
*put++ = sec->ceilingpic;
|
||||
*put++ = sec->lightlevel;
|
||||
*put++ = sec->special; // needed?
|
||||
*put++ = sec->tag; // needed?
|
||||
}
|
||||
|
||||
|
||||
// do lines
|
||||
for (i = 0, li = lines; i < numlines; i++, li++)
|
||||
{
|
||||
*put++ = li->flags;
|
||||
*put++ = li->special;
|
||||
*put++ = li->tag;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (li->sidenum[j] == -1)
|
||||
continue;
|
||||
|
||||
si = &sides[li->sidenum[j]];
|
||||
|
||||
*put++ = si->textureoffset >> FRACBITS;
|
||||
*put++ = si->rowoffset >> FRACBITS;
|
||||
*put++ = si->toptexture;
|
||||
*put++ = si->bottomtexture;
|
||||
*put++ = si->midtexture;
|
||||
}
|
||||
}
|
||||
|
||||
save_p = (byte*)put;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_UnArchiveWorld
|
||||
//
|
||||
void P_UnArchiveWorld(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sector_t* sec;
|
||||
line_t* li;
|
||||
side_t* si;
|
||||
short* get;
|
||||
|
||||
get = (short*)save_p;
|
||||
|
||||
// do sectors
|
||||
for (i = 0, sec = sectors; i < numsectors; i++, sec++)
|
||||
{
|
||||
sec->floorheight = *get++ << FRACBITS;
|
||||
sec->ceilingheight = *get++ << FRACBITS;
|
||||
sec->floorpic = *get++;
|
||||
sec->ceilingpic = *get++;
|
||||
sec->lightlevel = *get++;
|
||||
sec->special = *get++; // needed?
|
||||
sec->tag = *get++; // needed?
|
||||
sec->specialdata = 0;
|
||||
sec->soundtarget = 0;
|
||||
}
|
||||
|
||||
// do lines
|
||||
for (i = 0, li = lines; i < numlines; i++, li++)
|
||||
{
|
||||
li->flags = *get++;
|
||||
li->special = *get++;
|
||||
li->tag = *get++;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (li->sidenum[j] == -1)
|
||||
continue;
|
||||
si = &sides[li->sidenum[j]];
|
||||
si->textureoffset = *get++ << FRACBITS;
|
||||
si->rowoffset = *get++ << FRACBITS;
|
||||
si->toptexture = *get++;
|
||||
si->bottomtexture = *get++;
|
||||
si->midtexture = *get++;
|
||||
}
|
||||
}
|
||||
|
||||
save_p = (byte*)get;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Thinkers
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
tc_end,
|
||||
tc_mobj
|
||||
} thinkerclass_t;
|
||||
|
||||
|
||||
//
|
||||
// P_ArchiveThinkers
|
||||
//
|
||||
void P_ArchiveThinkers(void)
|
||||
{
|
||||
thinker_t* th;
|
||||
mobj_t* mobj;
|
||||
|
||||
// save off the current thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
{
|
||||
*save_p++ = tc_mobj;
|
||||
PADSAVEP();
|
||||
mobj = (mobj_t*)save_p;
|
||||
doom_memcpy(mobj, th, sizeof(*mobj));
|
||||
save_p += sizeof(*mobj);
|
||||
mobj->state = (state_t*)(mobj->state - states);
|
||||
|
||||
if (mobj->player)
|
||||
mobj->player = (player_t*)((mobj->player - players) + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// I_Error ("P_ArchiveThinkers: Unknown thinker function");
|
||||
}
|
||||
|
||||
// add a terminating marker
|
||||
*save_p++ = tc_end;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_UnArchiveThinkers
|
||||
//
|
||||
void P_UnArchiveThinkers(void)
|
||||
{
|
||||
byte tclass;
|
||||
thinker_t* currentthinker;
|
||||
thinker_t* next;
|
||||
mobj_t* mobj;
|
||||
|
||||
// remove all the current thinkers
|
||||
currentthinker = thinkercap.next;
|
||||
while (currentthinker != &thinkercap)
|
||||
{
|
||||
next = currentthinker->next;
|
||||
|
||||
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
P_RemoveMobj((mobj_t*)currentthinker);
|
||||
else
|
||||
Z_Free(currentthinker);
|
||||
|
||||
currentthinker = next;
|
||||
}
|
||||
P_InitThinkers();
|
||||
|
||||
// read in saved thinkers
|
||||
while (1)
|
||||
{
|
||||
tclass = *save_p++;
|
||||
switch (tclass)
|
||||
{
|
||||
case tc_end:
|
||||
return; // end of list
|
||||
|
||||
case tc_mobj:
|
||||
PADSAVEP();
|
||||
mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, 0);
|
||||
doom_memcpy(mobj, save_p, sizeof(*mobj));
|
||||
save_p += sizeof(*mobj);
|
||||
mobj->state = &states[(long long)mobj->state];
|
||||
mobj->target = 0;
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->player = &players[(long long)mobj->player - 1];
|
||||
mobj->player->mo = mobj;
|
||||
}
|
||||
P_SetThingPosition(mobj);
|
||||
mobj->info = &mobjinfo[mobj->type];
|
||||
mobj->floorz = mobj->subsector->sector->floorheight;
|
||||
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
||||
P_AddThinker(&mobj->thinker);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
//I_Error("Error: Unknown tclass %i in savegame", tclass);
|
||||
|
||||
doom_strcpy(error_buf, "Error: Unknown tclass ");
|
||||
doom_concat(error_buf, doom_itoa(tclass, 10));
|
||||
doom_concat(error_buf, " in savegame");
|
||||
I_Error(error_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_ArchiveSpecials
|
||||
//
|
||||
enum
|
||||
{
|
||||
tc_ceiling,
|
||||
tc_door,
|
||||
tc_floor,
|
||||
tc_plat,
|
||||
tc_flash,
|
||||
tc_strobe,
|
||||
tc_glow,
|
||||
tc_endspecials
|
||||
} specials_e;
|
||||
|
||||
|
||||
//
|
||||
// Things to handle:
|
||||
//
|
||||
// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
|
||||
// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
|
||||
// T_MoveFloor, (floormove_t: sector_t * swizzle),
|
||||
// T_LightFlash, (lightflash_t: sector_t * swizzle),
|
||||
// T_StrobeFlash, (strobe_t: sector_t *),
|
||||
// T_Glow, (glow_t: sector_t *),
|
||||
// T_PlatRaise, (plat_t: sector_t *), - active list
|
||||
//
|
||||
void P_ArchiveSpecials(void)
|
||||
{
|
||||
thinker_t* th;
|
||||
ceiling_t* ceiling;
|
||||
vldoor_t* door;
|
||||
floormove_t* floor;
|
||||
plat_t* plat;
|
||||
lightflash_t* flash;
|
||||
strobe_t* strobe;
|
||||
glow_t* glow;
|
||||
int i;
|
||||
|
||||
// save off the current thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acv == (actionf_v)0)
|
||||
{
|
||||
for (i = 0; i < MAXCEILINGS; i++)
|
||||
if (activeceilings[i] == (ceiling_t*)th)
|
||||
break;
|
||||
|
||||
if (i < MAXCEILINGS)
|
||||
{
|
||||
*save_p++ = tc_ceiling;
|
||||
PADSAVEP();
|
||||
ceiling = (ceiling_t*)save_p;
|
||||
doom_memcpy(ceiling, th, sizeof(*ceiling));
|
||||
save_p += sizeof(*ceiling);
|
||||
ceiling->sector = (sector_t*)(ceiling->sector - sectors);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
|
||||
{
|
||||
*save_p++ = tc_ceiling;
|
||||
PADSAVEP();
|
||||
ceiling = (ceiling_t*)save_p;
|
||||
doom_memcpy(ceiling, th, sizeof(*ceiling));
|
||||
save_p += sizeof(*ceiling);
|
||||
ceiling->sector = (sector_t*)(ceiling->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
|
||||
{
|
||||
*save_p++ = tc_door;
|
||||
PADSAVEP();
|
||||
door = (vldoor_t*)save_p;
|
||||
doom_memcpy(door, th, sizeof(*door));
|
||||
save_p += sizeof(*door);
|
||||
door->sector = (sector_t*)(door->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_MoveFloor)
|
||||
{
|
||||
*save_p++ = tc_floor;
|
||||
PADSAVEP();
|
||||
floor = (floormove_t*)save_p;
|
||||
doom_memcpy(floor, th, sizeof(*floor));
|
||||
save_p += sizeof(*floor);
|
||||
floor->sector = (sector_t*)(floor->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_PlatRaise)
|
||||
{
|
||||
*save_p++ = tc_plat;
|
||||
PADSAVEP();
|
||||
plat = (plat_t*)save_p;
|
||||
doom_memcpy(plat, th, sizeof(*plat));
|
||||
save_p += sizeof(*plat);
|
||||
plat->sector = (sector_t*)(plat->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_LightFlash)
|
||||
{
|
||||
*save_p++ = tc_flash;
|
||||
PADSAVEP();
|
||||
flash = (lightflash_t*)save_p;
|
||||
doom_memcpy(flash, th, sizeof(*flash));
|
||||
save_p += sizeof(*flash);
|
||||
flash->sector = (sector_t*)(flash->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
|
||||
{
|
||||
*save_p++ = tc_strobe;
|
||||
PADSAVEP();
|
||||
strobe = (strobe_t*)save_p;
|
||||
doom_memcpy(strobe, th, sizeof(*strobe));
|
||||
save_p += sizeof(*strobe);
|
||||
strobe->sector = (sector_t*)(strobe->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (th->function.acp1 == (actionf_p1)T_Glow)
|
||||
{
|
||||
*save_p++ = tc_glow;
|
||||
PADSAVEP();
|
||||
glow = (glow_t*)save_p;
|
||||
doom_memcpy(glow, th, sizeof(*glow));
|
||||
save_p += sizeof(*glow);
|
||||
glow->sector = (sector_t*)(glow->sector - sectors);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// add a terminating marker
|
||||
*save_p++ = tc_endspecials;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_UnArchiveSpecials
|
||||
//
|
||||
void P_UnArchiveSpecials(void)
|
||||
{
|
||||
byte tclass;
|
||||
ceiling_t* ceiling;
|
||||
vldoor_t* door;
|
||||
floormove_t* floor;
|
||||
plat_t* plat;
|
||||
lightflash_t* flash;
|
||||
strobe_t* strobe;
|
||||
glow_t* glow;
|
||||
|
||||
|
||||
// read in saved thinkers
|
||||
while (1)
|
||||
{
|
||||
tclass = *save_p++;
|
||||
switch (tclass)
|
||||
{
|
||||
case tc_endspecials:
|
||||
return; // end of list
|
||||
|
||||
case tc_ceiling:
|
||||
PADSAVEP();
|
||||
ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVEL, 0);
|
||||
doom_memcpy(ceiling, save_p, sizeof(*ceiling));
|
||||
save_p += sizeof(*ceiling);
|
||||
ceiling->sector = §ors[(long long)ceiling->sector];
|
||||
ceiling->sector->specialdata = ceiling;
|
||||
|
||||
if (ceiling->thinker.function.acp1)
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
||||
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
P_AddActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
case tc_door:
|
||||
PADSAVEP();
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVEL, 0);
|
||||
doom_memcpy(door, save_p, sizeof(*door));
|
||||
save_p += sizeof(*door);
|
||||
door->sector = §ors[(long long)door->sector];
|
||||
door->sector->specialdata = door;
|
||||
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
|
||||
P_AddThinker(&door->thinker);
|
||||
break;
|
||||
|
||||
case tc_floor:
|
||||
PADSAVEP();
|
||||
floor = Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
|
||||
doom_memcpy(floor, save_p, sizeof(*floor));
|
||||
save_p += sizeof(*floor);
|
||||
floor->sector = §ors[(long long)floor->sector];
|
||||
floor->sector->specialdata = floor;
|
||||
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
|
||||
P_AddThinker(&floor->thinker);
|
||||
break;
|
||||
|
||||
case tc_plat:
|
||||
PADSAVEP();
|
||||
plat = Z_Malloc(sizeof(*plat), PU_LEVEL, 0);
|
||||
doom_memcpy(plat, save_p, sizeof(*plat));
|
||||
save_p += sizeof(*plat);
|
||||
plat->sector = §ors[(long long)plat->sector];
|
||||
plat->sector->specialdata = plat;
|
||||
|
||||
if (plat->thinker.function.acp1)
|
||||
plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
|
||||
|
||||
P_AddThinker(&plat->thinker);
|
||||
P_AddActivePlat(plat);
|
||||
break;
|
||||
|
||||
case tc_flash:
|
||||
PADSAVEP();
|
||||
flash = Z_Malloc(sizeof(*flash), PU_LEVEL, 0);
|
||||
doom_memcpy(flash, save_p, sizeof(*flash));
|
||||
save_p += sizeof(*flash);
|
||||
flash->sector = §ors[(long long)flash->sector];
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
|
||||
P_AddThinker(&flash->thinker);
|
||||
break;
|
||||
|
||||
case tc_strobe:
|
||||
PADSAVEP();
|
||||
strobe = Z_Malloc(sizeof(*strobe), PU_LEVEL, 0);
|
||||
doom_memcpy(strobe, save_p, sizeof(*strobe));
|
||||
save_p += sizeof(*strobe);
|
||||
strobe->sector = §ors[(long long)strobe->sector];
|
||||
strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
|
||||
P_AddThinker(&strobe->thinker);
|
||||
break;
|
||||
|
||||
case tc_glow:
|
||||
PADSAVEP();
|
||||
glow = Z_Malloc(sizeof(*glow), PU_LEVEL, 0);
|
||||
doom_memcpy(glow, save_p, sizeof(*glow));
|
||||
save_p += sizeof(*glow);
|
||||
glow->sector = §ors[(long long)glow->sector];
|
||||
glow->thinker.function.acp1 = (actionf_p1)T_Glow;
|
||||
P_AddThinker(&glow->thinker);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
//I_Error("Error: P_UnarchiveSpecials:Unknown tclass %i "
|
||||
// "in savegame", tclass);
|
||||
|
||||
doom_strcpy(error_buf, "Error: P_UnarchiveSpecials:Unknown tclass ");
|
||||
doom_concat(error_buf, doom_itoa(tclass, 10));
|
||||
doom_concat(error_buf, " in savegame");
|
||||
I_Error(error_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
src/DOOM/p_saveg.h
Normal file
49
src/DOOM/p_saveg.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Savegame I/O, archiving, persistence.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_SAVEG__
|
||||
#define __P_SAVEG__
|
||||
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
|
||||
// Persistent storage/archiving.
|
||||
// These are the load / save game routines.
|
||||
void P_ArchivePlayers(void);
|
||||
void P_UnArchivePlayers(void);
|
||||
void P_ArchiveWorld(void);
|
||||
void P_UnArchiveWorld(void);
|
||||
void P_ArchiveThinkers(void);
|
||||
void P_UnArchiveThinkers(void);
|
||||
void P_ArchiveSpecials(void);
|
||||
void P_UnArchiveSpecials(void);
|
||||
|
||||
extern byte* save_p;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
674
src/DOOM/p_setup.c
Normal file
674
src/DOOM/p_setup.c
Normal file
@ -0,0 +1,674 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Do all the WAD I/O, get map description,
|
||||
// set up initial state and misc. LUTs.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "m_swap.h"
|
||||
#include "m_bbox.h"
|
||||
#include "g_game.h"
|
||||
#include "i_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
// Maintain single and multi player starting spots.
|
||||
#define MAX_DEATHMATCH_STARTS 10
|
||||
|
||||
|
||||
//
|
||||
// MAP related Lookup tables.
|
||||
// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
|
||||
//
|
||||
int numvertexes;
|
||||
vertex_t* vertexes;
|
||||
|
||||
int numsegs;
|
||||
seg_t* segs;
|
||||
|
||||
int numsectors;
|
||||
sector_t* sectors;
|
||||
|
||||
int numsubsectors;
|
||||
subsector_t* subsectors;
|
||||
|
||||
int numnodes;
|
||||
node_t* nodes;
|
||||
|
||||
int numlines;
|
||||
line_t* lines;
|
||||
|
||||
int numsides;
|
||||
side_t* sides;
|
||||
|
||||
// BLOCKMAP
|
||||
// Created from axis aligned bounding box
|
||||
// of the map, a rectangular array of
|
||||
// blocks of size ...
|
||||
// Used to speed up collision detection
|
||||
// by spatial subdivision in 2D.
|
||||
//
|
||||
// Blockmap size.
|
||||
int bmapwidth;
|
||||
int bmapheight; // size in mapblocks
|
||||
short* blockmap; // int for larger maps
|
||||
// offsets in blockmap are from here
|
||||
short* blockmaplump;
|
||||
// origin of block map
|
||||
fixed_t bmaporgx;
|
||||
fixed_t bmaporgy;
|
||||
// for thing chains
|
||||
mobj_t** blocklinks;
|
||||
|
||||
// REJECT
|
||||
// For fast sight rejection.
|
||||
// Speeds up enemy AI by skipping detailed
|
||||
// LineOf Sight calculation.
|
||||
// Without special effect, this could be
|
||||
// used as a PVS lookup as well.
|
||||
//
|
||||
byte* rejectmatrix;
|
||||
|
||||
mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS];
|
||||
mapthing_t* deathmatch_p;
|
||||
mapthing_t playerstarts[MAXPLAYERS];
|
||||
|
||||
|
||||
void P_SpawnMapThing(mapthing_t* mthing);
|
||||
|
||||
|
||||
//
|
||||
// P_LoadVertexes
|
||||
//
|
||||
void P_LoadVertexes(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapvertex_t* ml;
|
||||
vertex_t* li;
|
||||
|
||||
// Determine number of lumps:
|
||||
// total lump length / vertex record length.
|
||||
numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t);
|
||||
|
||||
// Allocate zone memory for buffer.
|
||||
vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0);
|
||||
|
||||
// Load data into cache.
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
ml = (mapvertex_t*)data;
|
||||
li = vertexes;
|
||||
|
||||
// Copy and convert vertex coordinates,
|
||||
// internal representation as fixed.
|
||||
for (i = 0; i < numvertexes; i++, li++, ml++)
|
||||
{
|
||||
li->x = SHORT(ml->x) << FRACBITS;
|
||||
li->y = SHORT(ml->y) << FRACBITS;
|
||||
}
|
||||
|
||||
// Free buffer memory.
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadSegs
|
||||
//
|
||||
void P_LoadSegs(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapseg_t* ml;
|
||||
seg_t* li;
|
||||
line_t* ldef;
|
||||
int linedef;
|
||||
int side;
|
||||
|
||||
numsegs = W_LumpLength(lump) / sizeof(mapseg_t);
|
||||
segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0);
|
||||
doom_memset(segs, 0, numsegs * sizeof(seg_t));
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
ml = (mapseg_t*)data;
|
||||
li = segs;
|
||||
for (i = 0; i < numsegs; i++, li++, ml++)
|
||||
{
|
||||
li->v1 = &vertexes[SHORT(ml->v1)];
|
||||
li->v2 = &vertexes[SHORT(ml->v2)];
|
||||
|
||||
li->angle = (SHORT(ml->angle)) << 16;
|
||||
li->offset = (SHORT(ml->offset)) << 16;
|
||||
linedef = SHORT(ml->linedef);
|
||||
ldef = &lines[linedef];
|
||||
li->linedef = ldef;
|
||||
side = SHORT(ml->side);
|
||||
li->sidedef = &sides[ldef->sidenum[side]];
|
||||
li->frontsector = sides[ldef->sidenum[side]].sector;
|
||||
if (ldef->flags & ML_TWOSIDED)
|
||||
li->backsector = sides[ldef->sidenum[side ^ 1]].sector;
|
||||
else
|
||||
li->backsector = 0;
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadSubsectors
|
||||
//
|
||||
void P_LoadSubsectors(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapsubsector_t* ms;
|
||||
subsector_t* ss;
|
||||
|
||||
numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t);
|
||||
subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0);
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
ms = (mapsubsector_t*)data;
|
||||
doom_memset(subsectors, 0, numsubsectors * sizeof(subsector_t));
|
||||
ss = subsectors;
|
||||
|
||||
for (i = 0; i < numsubsectors; i++, ss++, ms++)
|
||||
{
|
||||
ss->numlines = SHORT(ms->numsegs);
|
||||
ss->firstline = SHORT(ms->firstseg);
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadSectors
|
||||
//
|
||||
void P_LoadSectors(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapsector_t* ms;
|
||||
sector_t* ss;
|
||||
|
||||
numsectors = W_LumpLength(lump) / sizeof(mapsector_t);
|
||||
sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0);
|
||||
doom_memset(sectors, 0, numsectors * sizeof(sector_t));
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
ms = (mapsector_t*)data;
|
||||
ss = sectors;
|
||||
for (i = 0; i < numsectors; i++, ss++, ms++)
|
||||
{
|
||||
ss->floorheight = SHORT(ms->floorheight) << FRACBITS;
|
||||
ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS;
|
||||
ss->floorpic = R_FlatNumForName(ms->floorpic);
|
||||
ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
|
||||
ss->lightlevel = SHORT(ms->lightlevel);
|
||||
ss->special = SHORT(ms->special);
|
||||
ss->tag = SHORT(ms->tag);
|
||||
ss->thinglist = 0;
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadNodes
|
||||
//
|
||||
void P_LoadNodes(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
mapnode_t* mn;
|
||||
node_t* no;
|
||||
|
||||
numnodes = W_LumpLength(lump) / sizeof(mapnode_t);
|
||||
nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0);
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
mn = (mapnode_t*)data;
|
||||
no = nodes;
|
||||
|
||||
for (i = 0; i < numnodes; i++, no++, mn++)
|
||||
{
|
||||
no->x = SHORT(mn->x) << FRACBITS;
|
||||
no->y = SHORT(mn->y) << FRACBITS;
|
||||
no->dx = SHORT(mn->dx) << FRACBITS;
|
||||
no->dy = SHORT(mn->dy) << FRACBITS;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
no->children[j] = SHORT(mn->children[j]);
|
||||
for (k = 0; k < 4; k++)
|
||||
no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadThings
|
||||
//
|
||||
void P_LoadThings(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapthing_t* mt;
|
||||
int numthings;
|
||||
doom_boolean spawn;
|
||||
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
numthings = W_LumpLength(lump) / sizeof(mapthing_t);
|
||||
|
||||
mt = (mapthing_t*)data;
|
||||
for (i = 0; i < numthings; i++, mt++)
|
||||
{
|
||||
spawn = true;
|
||||
|
||||
// Do not spawn cool, new monsters if !commercial
|
||||
if (gamemode != commercial)
|
||||
{
|
||||
switch (mt->type)
|
||||
{
|
||||
case 68: // Arachnotron
|
||||
case 64: // Archvile
|
||||
case 88: // Boss Brain
|
||||
case 89: // Boss Shooter
|
||||
case 69: // Hell Knight
|
||||
case 67: // Mancubus
|
||||
case 71: // Pain Elemental
|
||||
case 65: // Former Human Commando
|
||||
case 66: // Revenant
|
||||
case 84: // Wolf SS
|
||||
spawn = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (spawn == false)
|
||||
break;
|
||||
|
||||
// Do spawn all other stuff.
|
||||
mt->x = SHORT(mt->x);
|
||||
mt->y = SHORT(mt->y);
|
||||
mt->angle = SHORT(mt->angle);
|
||||
mt->type = SHORT(mt->type);
|
||||
mt->options = SHORT(mt->options);
|
||||
|
||||
P_SpawnMapThing(mt);
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadLineDefs
|
||||
// Also counts secret lines for intermissions.
|
||||
//
|
||||
void P_LoadLineDefs(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
maplinedef_t* mld;
|
||||
line_t* ld;
|
||||
vertex_t* v1;
|
||||
vertex_t* v2;
|
||||
|
||||
numlines = W_LumpLength(lump) / sizeof(maplinedef_t);
|
||||
lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0);
|
||||
doom_memset(lines, 0, numlines * sizeof(line_t));
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
mld = (maplinedef_t*)data;
|
||||
ld = lines;
|
||||
for (i = 0; i < numlines; i++, mld++, ld++)
|
||||
{
|
||||
ld->flags = SHORT(mld->flags);
|
||||
ld->special = SHORT(mld->special);
|
||||
ld->tag = SHORT(mld->tag);
|
||||
v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
|
||||
v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
|
||||
ld->dx = v2->x - v1->x;
|
||||
ld->dy = v2->y - v1->y;
|
||||
|
||||
if (!ld->dx)
|
||||
ld->slopetype = ST_VERTICAL;
|
||||
else if (!ld->dy)
|
||||
ld->slopetype = ST_HORIZONTAL;
|
||||
else
|
||||
{
|
||||
if (FixedDiv(ld->dy, ld->dx) > 0)
|
||||
ld->slopetype = ST_POSITIVE;
|
||||
else
|
||||
ld->slopetype = ST_NEGATIVE;
|
||||
}
|
||||
|
||||
if (v1->x < v2->x)
|
||||
{
|
||||
ld->bbox[BOXLEFT] = v1->x;
|
||||
ld->bbox[BOXRIGHT] = v2->x;
|
||||
}
|
||||
else
|
||||
{
|
||||
ld->bbox[BOXLEFT] = v2->x;
|
||||
ld->bbox[BOXRIGHT] = v1->x;
|
||||
}
|
||||
|
||||
if (v1->y < v2->y)
|
||||
{
|
||||
ld->bbox[BOXBOTTOM] = v1->y;
|
||||
ld->bbox[BOXTOP] = v2->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ld->bbox[BOXBOTTOM] = v2->y;
|
||||
ld->bbox[BOXTOP] = v1->y;
|
||||
}
|
||||
|
||||
ld->sidenum[0] = SHORT(mld->sidenum[0]);
|
||||
ld->sidenum[1] = SHORT(mld->sidenum[1]);
|
||||
|
||||
if (ld->sidenum[0] != -1)
|
||||
ld->frontsector = sides[ld->sidenum[0]].sector;
|
||||
else
|
||||
ld->frontsector = 0;
|
||||
|
||||
if (ld->sidenum[1] != -1)
|
||||
ld->backsector = sides[ld->sidenum[1]].sector;
|
||||
else
|
||||
ld->backsector = 0;
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadSideDefs
|
||||
//
|
||||
void P_LoadSideDefs(int lump)
|
||||
{
|
||||
byte* data;
|
||||
int i;
|
||||
mapsidedef_t* msd;
|
||||
side_t* sd;
|
||||
|
||||
numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
|
||||
sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0);
|
||||
doom_memset(sides, 0, numsides * sizeof(side_t));
|
||||
data = W_CacheLumpNum(lump, PU_STATIC);
|
||||
|
||||
msd = (mapsidedef_t*)data;
|
||||
sd = sides;
|
||||
for (i = 0; i < numsides; i++, msd++, sd++)
|
||||
{
|
||||
sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS;
|
||||
sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS;
|
||||
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
||||
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
||||
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
||||
sd->sector = §ors[SHORT(msd->sector)];
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_LoadBlockMap
|
||||
//
|
||||
void P_LoadBlockMap(int lump)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
|
||||
blockmaplump = W_CacheLumpNum(lump, PU_LEVEL);
|
||||
blockmap = blockmaplump + 4;
|
||||
count = W_LumpLength(lump) / 2;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
blockmaplump[i] = SHORT(blockmaplump[i]);
|
||||
|
||||
bmaporgx = blockmaplump[0] << FRACBITS;
|
||||
bmaporgy = blockmaplump[1] << FRACBITS;
|
||||
bmapwidth = blockmaplump[2];
|
||||
bmapheight = blockmaplump[3];
|
||||
|
||||
// clear out mobj chains
|
||||
count = sizeof(*blocklinks) * bmapwidth * bmapheight;
|
||||
blocklinks = Z_Malloc(count, PU_LEVEL, 0);
|
||||
doom_memset(blocklinks, 0, count);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_GroupLines
|
||||
// Builds sector line lists and subsector sector numbers.
|
||||
// Finds block bounding boxes for sectors.
|
||||
//
|
||||
void P_GroupLines(void)
|
||||
{
|
||||
line_t** linebuffer;
|
||||
int i;
|
||||
int j;
|
||||
int total;
|
||||
line_t* li;
|
||||
sector_t* sector;
|
||||
subsector_t* ss;
|
||||
seg_t* seg;
|
||||
fixed_t bbox[4];
|
||||
int block;
|
||||
|
||||
// look up sector number for each subsector
|
||||
ss = subsectors;
|
||||
for (i = 0; i < numsubsectors; i++, ss++)
|
||||
{
|
||||
seg = &segs[ss->firstline];
|
||||
ss->sector = seg->sidedef->sector;
|
||||
}
|
||||
|
||||
// count number of lines in each sector
|
||||
li = lines;
|
||||
total = 0;
|
||||
for (i = 0; i < numlines; i++, li++)
|
||||
{
|
||||
total++;
|
||||
li->frontsector->linecount++;
|
||||
|
||||
if (li->backsector && li->backsector != li->frontsector)
|
||||
{
|
||||
li->backsector->linecount++;
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
// build line tables for each sector
|
||||
linebuffer = Z_Malloc(total * sizeof(line_t*), PU_LEVEL, 0);
|
||||
sector = sectors;
|
||||
for (i = 0; i < numsectors; i++, sector++)
|
||||
{
|
||||
M_ClearBox(bbox);
|
||||
sector->lines = linebuffer;
|
||||
li = lines;
|
||||
for (j = 0; j < numlines; j++, li++)
|
||||
{
|
||||
if (li->frontsector == sector || li->backsector == sector)
|
||||
{
|
||||
*linebuffer++ = li;
|
||||
M_AddToBox(bbox, li->v1->x, li->v1->y);
|
||||
M_AddToBox(bbox, li->v2->x, li->v2->y);
|
||||
}
|
||||
}
|
||||
if (linebuffer - sector->lines != sector->linecount)
|
||||
I_Error("Error: P_GroupLines: miscounted");
|
||||
|
||||
// set the degenmobj_t to the middle of the bounding box
|
||||
sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2;
|
||||
sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2;
|
||||
|
||||
// adjust bounding box to map blocks
|
||||
block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT;
|
||||
block = block >= bmapheight ? bmapheight - 1 : block;
|
||||
sector->blockbox[BOXTOP] = block;
|
||||
|
||||
block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT;
|
||||
block = block < 0 ? 0 : block;
|
||||
sector->blockbox[BOXBOTTOM] = block;
|
||||
|
||||
block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT;
|
||||
block = block >= bmapwidth ? bmapwidth - 1 : block;
|
||||
sector->blockbox[BOXRIGHT] = block;
|
||||
|
||||
block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT;
|
||||
block = block < 0 ? 0 : block;
|
||||
sector->blockbox[BOXLEFT] = block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SetupLevel
|
||||
//
|
||||
void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
|
||||
{
|
||||
int i;
|
||||
char lumpname[9];
|
||||
int lumpnum;
|
||||
|
||||
totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
|
||||
wminfo.partime = 180;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].killcount = players[i].secretcount
|
||||
= players[i].itemcount = 0;
|
||||
}
|
||||
|
||||
// Initial height of PointOfView
|
||||
// will be set by player think.
|
||||
players[consoleplayer].viewz = 1;
|
||||
|
||||
// Make sure all sounds are stopped before Z_FreeTags.
|
||||
S_Start();
|
||||
|
||||
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
|
||||
|
||||
// UNUSED W_Profile ();
|
||||
P_InitThinkers();
|
||||
|
||||
// if working with a devlopment map, reload it
|
||||
W_Reload();
|
||||
|
||||
// find map name
|
||||
if (gamemode == commercial)
|
||||
{
|
||||
if (map < 10)
|
||||
{
|
||||
//doom_sprintf(lumpname, "map0%i", map);
|
||||
doom_strcpy(lumpname, "map0");
|
||||
doom_concat(lumpname, doom_itoa(map, 10));
|
||||
}
|
||||
else
|
||||
{
|
||||
//doom_sprintf(lumpname, "map%i", map);
|
||||
doom_strcpy(lumpname, "map");
|
||||
doom_concat(lumpname, doom_itoa(map, 10));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lumpname[0] = 'E';
|
||||
lumpname[1] = '0' + episode;
|
||||
lumpname[2] = 'M';
|
||||
lumpname[3] = '0' + map;
|
||||
lumpname[4] = 0;
|
||||
}
|
||||
|
||||
lumpnum = W_GetNumForName(lumpname);
|
||||
|
||||
leveltime = 0;
|
||||
|
||||
// note: most of this ordering is important
|
||||
P_LoadBlockMap(lumpnum + ML_BLOCKMAP);
|
||||
P_LoadVertexes(lumpnum + ML_VERTEXES);
|
||||
P_LoadSectors(lumpnum + ML_SECTORS);
|
||||
P_LoadSideDefs(lumpnum + ML_SIDEDEFS);
|
||||
|
||||
P_LoadLineDefs(lumpnum + ML_LINEDEFS);
|
||||
P_LoadSubsectors(lumpnum + ML_SSECTORS);
|
||||
P_LoadNodes(lumpnum + ML_NODES);
|
||||
P_LoadSegs(lumpnum + ML_SEGS);
|
||||
|
||||
rejectmatrix = W_CacheLumpNum(lumpnum + ML_REJECT, PU_LEVEL);
|
||||
P_GroupLines();
|
||||
|
||||
bodyqueslot = 0;
|
||||
deathmatch_p = deathmatchstarts;
|
||||
P_LoadThings(lumpnum + ML_THINGS);
|
||||
|
||||
// if deathmatch, randomly spawn the active players
|
||||
if (deathmatch)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
{
|
||||
players[i].mo = 0;
|
||||
G_DeathMatchSpawnPlayer(i);
|
||||
}
|
||||
}
|
||||
|
||||
// clear special respawning que
|
||||
iquehead = iquetail = 0;
|
||||
|
||||
// set up world state
|
||||
P_SpawnSpecials();
|
||||
|
||||
// preload graphics
|
||||
if (precache)
|
||||
R_PrecacheLevel();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_Init
|
||||
//
|
||||
void P_Init(void)
|
||||
{
|
||||
P_InitSwitchList();
|
||||
P_InitPicAnims();
|
||||
R_InitSprites(sprnames);
|
||||
}
|
39
src/DOOM/p_setup.h
Normal file
39
src/DOOM/p_setup.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Setup a game, startup stuff.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_SETUP__
|
||||
#define __P_SETUP__
|
||||
|
||||
|
||||
// NOT called by W_Ticker. Fixme.
|
||||
void P_SetupLevel(int episode, int map, int playermask, skill_t skill);
|
||||
|
||||
// Called by startup code.
|
||||
void P_Init(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
341
src/DOOM/p_sight.c
Normal file
341
src/DOOM/p_sight.c
Normal file
@ -0,0 +1,341 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// LineOfSight/Visibility checks, uses REJECT Lookup Table.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "i_system.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
//
|
||||
// P_CheckSight
|
||||
//
|
||||
fixed_t sightzstart; // eye z of looker
|
||||
fixed_t topslope;
|
||||
fixed_t bottomslope; // slopes to top and bottom of target
|
||||
|
||||
divline_t strace; // from t1 to t2
|
||||
fixed_t t2x;
|
||||
fixed_t t2y;
|
||||
|
||||
int sightcounts[2];
|
||||
|
||||
|
||||
//
|
||||
// P_DivlineSide
|
||||
// Returns side 0 (front), 1 (back), or 2 (on).
|
||||
//
|
||||
int P_DivlineSide(fixed_t x, fixed_t y, divline_t* node)
|
||||
{
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
fixed_t left;
|
||||
fixed_t right;
|
||||
|
||||
if (!node->dx)
|
||||
{
|
||||
if (x == node->x)
|
||||
return 2;
|
||||
|
||||
if (x <= node->x)
|
||||
return node->dy > 0;
|
||||
|
||||
return node->dy < 0;
|
||||
}
|
||||
|
||||
if (!node->dy)
|
||||
{
|
||||
if (x == node->y)
|
||||
return 2;
|
||||
|
||||
if (y <= node->y)
|
||||
return node->dx < 0;
|
||||
|
||||
return node->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - node->x);
|
||||
dy = (y - node->y);
|
||||
|
||||
left = (node->dy >> FRACBITS) * (dx >> FRACBITS);
|
||||
right = (dy >> FRACBITS) * (node->dx >> FRACBITS);
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
|
||||
if (left == right)
|
||||
return 2;
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_InterceptVector2
|
||||
// Returns the fractional intercept point
|
||||
// along the first divline.
|
||||
// This is only called by the addthings and addlines traversers.
|
||||
//
|
||||
fixed_t P_InterceptVector2(divline_t* v2, divline_t* v1)
|
||||
{
|
||||
fixed_t frac;
|
||||
fixed_t num;
|
||||
fixed_t den;
|
||||
|
||||
den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy);
|
||||
|
||||
if (den == 0)
|
||||
return 0;
|
||||
|
||||
num = FixedMul((v1->x - v2->x) >> 8, v1->dy) +
|
||||
FixedMul((v2->y - v1->y) >> 8, v1->dx);
|
||||
frac = FixedDiv(num, den);
|
||||
|
||||
return frac;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CrossSubsector
|
||||
// Returns true
|
||||
// if strace crosses the given subsector successfully.
|
||||
//
|
||||
doom_boolean P_CrossSubsector(int num)
|
||||
{
|
||||
seg_t* seg;
|
||||
line_t* line;
|
||||
int s1;
|
||||
int s2;
|
||||
int count;
|
||||
subsector_t* sub;
|
||||
sector_t* front;
|
||||
sector_t* back;
|
||||
fixed_t opentop;
|
||||
fixed_t openbottom;
|
||||
divline_t divl;
|
||||
vertex_t* v1;
|
||||
vertex_t* v2;
|
||||
fixed_t frac;
|
||||
fixed_t slope;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
{
|
||||
//I_Error("Error: P_CrossSubsector: ss %i with numss = %i",
|
||||
// num,
|
||||
// numsubsectors);
|
||||
|
||||
doom_strcpy(error_buf, "Error: P_CrossSubsector: ss ");
|
||||
doom_concat(error_buf, doom_itoa(num, 10));
|
||||
doom_concat(error_buf, " with numss = ");
|
||||
doom_concat(error_buf, doom_itoa(numsubsectors, 10));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
sub = &subsectors[num];
|
||||
|
||||
// check lines
|
||||
count = sub->numlines;
|
||||
seg = &segs[sub->firstline];
|
||||
|
||||
for (; count; seg++, count--)
|
||||
{
|
||||
line = seg->linedef;
|
||||
|
||||
// allready checked other side?
|
||||
if (line->validcount == validcount)
|
||||
continue;
|
||||
|
||||
line->validcount = validcount;
|
||||
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
s1 = P_DivlineSide(v1->x, v1->y, &strace);
|
||||
s2 = P_DivlineSide(v2->x, v2->y, &strace);
|
||||
|
||||
// line isn't crossed?
|
||||
if (s1 == s2)
|
||||
continue;
|
||||
|
||||
divl.x = v1->x;
|
||||
divl.y = v1->y;
|
||||
divl.dx = v2->x - v1->x;
|
||||
divl.dy = v2->y - v1->y;
|
||||
s1 = P_DivlineSide(strace.x, strace.y, &divl);
|
||||
s2 = P_DivlineSide(t2x, t2y, &divl);
|
||||
|
||||
// line isn't crossed?
|
||||
if (s1 == s2)
|
||||
continue;
|
||||
|
||||
// stop because it is not two sided anyway
|
||||
// might do this after updating validcount?
|
||||
if (!(line->flags & ML_TWOSIDED))
|
||||
return false;
|
||||
|
||||
// crosses a two sided line
|
||||
front = seg->frontsector;
|
||||
back = seg->backsector;
|
||||
|
||||
// no wall to block sight with?
|
||||
if (front->floorheight == back->floorheight
|
||||
&& front->ceilingheight == back->ceilingheight)
|
||||
continue;
|
||||
|
||||
// possible occluder
|
||||
// because of ceiling height differences
|
||||
if (front->ceilingheight < back->ceilingheight)
|
||||
opentop = front->ceilingheight;
|
||||
else
|
||||
opentop = back->ceilingheight;
|
||||
|
||||
// because of ceiling height differences
|
||||
if (front->floorheight > back->floorheight)
|
||||
openbottom = front->floorheight;
|
||||
else
|
||||
openbottom = back->floorheight;
|
||||
|
||||
// quick test for totally closed doors
|
||||
if (openbottom >= opentop)
|
||||
return false; // stop
|
||||
|
||||
frac = P_InterceptVector2(&strace, &divl);
|
||||
|
||||
if (front->floorheight != back->floorheight)
|
||||
{
|
||||
slope = FixedDiv(openbottom - sightzstart, frac);
|
||||
if (slope > bottomslope)
|
||||
bottomslope = slope;
|
||||
}
|
||||
|
||||
if (front->ceilingheight != back->ceilingheight)
|
||||
{
|
||||
slope = FixedDiv(opentop - sightzstart, frac);
|
||||
if (slope < topslope)
|
||||
topslope = slope;
|
||||
}
|
||||
|
||||
if (topslope <= bottomslope)
|
||||
return false; // stop
|
||||
}
|
||||
|
||||
// passed the subsector ok
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CrossBSPNode
|
||||
// Returns true
|
||||
// if strace crosses the given node successfully.
|
||||
//
|
||||
doom_boolean P_CrossBSPNode(int bspnum)
|
||||
{
|
||||
node_t* bsp;
|
||||
int side;
|
||||
|
||||
if (bspnum & NF_SUBSECTOR)
|
||||
{
|
||||
if (bspnum == -1)
|
||||
return P_CrossSubsector(0);
|
||||
else
|
||||
return P_CrossSubsector(bspnum & (~NF_SUBSECTOR));
|
||||
}
|
||||
|
||||
bsp = &nodes[bspnum];
|
||||
|
||||
// decide which side the start point is on
|
||||
side = P_DivlineSide(strace.x, strace.y, (divline_t*)bsp);
|
||||
if (side == 2)
|
||||
side = 0; // an "on" should cross both sides
|
||||
|
||||
// cross the starting side
|
||||
if (!P_CrossBSPNode(bsp->children[side]))
|
||||
return false;
|
||||
|
||||
// the partition plane is crossed here
|
||||
if (side == P_DivlineSide(t2x, t2y, (divline_t*)bsp))
|
||||
{
|
||||
// the line doesn't touch the other side
|
||||
return true;
|
||||
}
|
||||
|
||||
// cross the ending side
|
||||
return P_CrossBSPNode(bsp->children[side ^ 1]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CheckSight
|
||||
// Returns true
|
||||
// if a straight line between t1 and t2 is unobstructed.
|
||||
// Uses REJECT.
|
||||
//
|
||||
doom_boolean P_CheckSight(mobj_t* t1, mobj_t* t2)
|
||||
{
|
||||
int s1;
|
||||
int s2;
|
||||
int pnum;
|
||||
int bytenum;
|
||||
int bitnum;
|
||||
|
||||
// First check for trivial rejection.
|
||||
|
||||
// Determine subsector entries in REJECT table.
|
||||
s1 = (int)(t1->subsector->sector - sectors);
|
||||
s2 = (int)(t2->subsector->sector - sectors);
|
||||
pnum = s1 * numsectors + s2;
|
||||
bytenum = pnum >> 3;
|
||||
bitnum = 1 << (pnum & 7);
|
||||
|
||||
// Check in REJECT table.
|
||||
if (rejectmatrix[bytenum] & bitnum)
|
||||
{
|
||||
sightcounts[0]++;
|
||||
|
||||
// can't possibly be connected
|
||||
return false;
|
||||
}
|
||||
|
||||
// An unobstructed LOS is possible.
|
||||
// Now look from eyes of t1 to any part of t2.
|
||||
sightcounts[1]++;
|
||||
|
||||
validcount++;
|
||||
|
||||
sightzstart = t1->z + t1->height - (t1->height >> 2);
|
||||
topslope = (t2->z + t2->height) - sightzstart;
|
||||
bottomslope = (t2->z) - sightzstart;
|
||||
|
||||
strace.x = t1->x;
|
||||
strace.y = t1->y;
|
||||
t2x = t2->x;
|
||||
t2y = t2->y;
|
||||
strace.dx = t2->x - t1->x;
|
||||
strace.dy = t2->y - t1->y;
|
||||
|
||||
// the head node is the last node output
|
||||
return P_CrossBSPNode(numnodes - 1);
|
||||
}
|
1313
src/DOOM/p_spec.c
Normal file
1313
src/DOOM/p_spec.c
Normal file
File diff suppressed because it is too large
Load Diff
429
src/DOOM/p_spec.h
Normal file
429
src/DOOM/p_spec.h
Normal file
@ -0,0 +1,429 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION: none
|
||||
// Implements special effects:
|
||||
// Texture animation, height or lighting changes
|
||||
// according to adjacent sectors, respective
|
||||
// utility functions, etc.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_SPEC__
|
||||
#define __P_SPEC__
|
||||
|
||||
|
||||
#include "p_mobj.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
|
||||
//
|
||||
// End-level timer (-TIMER option)
|
||||
//
|
||||
extern doom_boolean levelTimer;
|
||||
extern int levelTimeCount;
|
||||
|
||||
|
||||
// Define values for map objects
|
||||
#define MO_TELEPORTMAN 14
|
||||
|
||||
|
||||
// at game start
|
||||
void P_InitPicAnims(void);
|
||||
|
||||
// at map load
|
||||
void P_SpawnSpecials(void);
|
||||
|
||||
// every tic
|
||||
void P_UpdateSpecials(void);
|
||||
|
||||
// when needed
|
||||
doom_boolean P_UseSpecialLine(mobj_t* thing, line_t* line, int side);
|
||||
|
||||
void P_ShootSpecialLine(mobj_t* thing, line_t* line);
|
||||
void P_CrossSpecialLine(int linenum, int side, mobj_t* thing);
|
||||
void P_PlayerInSpecialSector(player_t* player);
|
||||
int twoSided(int sector, int line);
|
||||
sector_t* getSector(int currentSector, int line, int side);
|
||||
side_t* getSide(int currentSector, int line, int side);
|
||||
fixed_t P_FindLowestFloorSurrounding(sector_t* sec);
|
||||
fixed_t P_FindHighestFloorSurrounding(sector_t* sec);
|
||||
fixed_t P_FindNextHighestFloor(sector_t* sec, int currentheight);
|
||||
fixed_t P_FindLowestCeilingSurrounding(sector_t* sec);
|
||||
fixed_t P_FindHighestCeilingSurrounding(sector_t* sec);
|
||||
int P_FindSectorFromLineTag(line_t* line, int start);
|
||||
int P_FindMinSurroundingLight(sector_t* sector, int max);
|
||||
sector_t* getNextSector(line_t* line, sector_t* sec);
|
||||
|
||||
//
|
||||
// SPECIAL
|
||||
//
|
||||
int EV_DoDonut(line_t* line);
|
||||
|
||||
|
||||
//
|
||||
// P_LIGHTS
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t* sector;
|
||||
int count;
|
||||
int maxlight;
|
||||
int minlight;
|
||||
} fireflicker_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t* sector;
|
||||
int count;
|
||||
int maxlight;
|
||||
int minlight;
|
||||
int maxtime;
|
||||
int mintime;
|
||||
} lightflash_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t* sector;
|
||||
int count;
|
||||
int minlight;
|
||||
int maxlight;
|
||||
int darktime;
|
||||
int brighttime;
|
||||
} strobe_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t* sector;
|
||||
int minlight;
|
||||
int maxlight;
|
||||
int direction;
|
||||
} glow_t;
|
||||
|
||||
|
||||
#define GLOWSPEED 8
|
||||
#define STROBEBRIGHT 5
|
||||
#define FASTDARK 15
|
||||
#define SLOWDARK 35
|
||||
|
||||
void P_SpawnFireFlicker(sector_t* sector);
|
||||
void T_LightFlash(lightflash_t* flash);
|
||||
void P_SpawnLightFlash(sector_t* sector);
|
||||
void T_StrobeFlash(strobe_t* flash);
|
||||
|
||||
void P_SpawnStrobeFlash(sector_t* sector, int fastOrSlow, int inSync);
|
||||
void EV_StartLightStrobing(line_t* line);
|
||||
void EV_TurnTagLightsOff(line_t* line);
|
||||
|
||||
void EV_LightTurnOn(line_t* line, int bright);
|
||||
|
||||
void T_Glow(glow_t* g);
|
||||
void P_SpawnGlowingLight(sector_t* sector);
|
||||
|
||||
|
||||
//
|
||||
// P_SWITCH
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
char name1[9];
|
||||
char name2[9];
|
||||
short episode;
|
||||
} switchlist_t;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
top,
|
||||
middle,
|
||||
bottom
|
||||
} bwhere_e;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
line_t* line;
|
||||
bwhere_e where;
|
||||
int btexture;
|
||||
int btimer;
|
||||
mobj_t* soundorg;
|
||||
} button_t;
|
||||
|
||||
|
||||
// max # of wall switches in a level
|
||||
#define MAXSWITCHES 50
|
||||
|
||||
// 4 players, 4 buttons each at once, max.
|
||||
#define MAXBUTTONS 16
|
||||
|
||||
// 1 second, in ticks.
|
||||
#define BUTTONTIME 35
|
||||
|
||||
|
||||
extern button_t buttonlist[MAXBUTTONS];
|
||||
|
||||
|
||||
void P_ChangeSwitchTexture(line_t* line, int useAgain);
|
||||
void P_InitSwitchList(void);
|
||||
|
||||
|
||||
//
|
||||
// P_PLATS
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
up,
|
||||
down,
|
||||
waiting,
|
||||
in_stasis
|
||||
} plat_e;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
perpetualRaise,
|
||||
downWaitUpStay,
|
||||
raiseAndChange,
|
||||
raiseToNearestAndChange,
|
||||
blazeDWUS
|
||||
} plattype_e;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t* sector;
|
||||
fixed_t speed;
|
||||
fixed_t low;
|
||||
fixed_t high;
|
||||
int wait;
|
||||
int count;
|
||||
plat_e status;
|
||||
plat_e oldstatus;
|
||||
doom_boolean crush;
|
||||
int tag;
|
||||
plattype_e type;
|
||||
} plat_t;
|
||||
|
||||
|
||||
#define PLATWAIT 3
|
||||
#define PLATSPEED FRACUNIT
|
||||
#define MAXPLATS 30
|
||||
|
||||
|
||||
extern plat_t* activeplats[MAXPLATS];
|
||||
|
||||
|
||||
void T_PlatRaise(plat_t* plat);
|
||||
int EV_DoPlat(line_t* line, plattype_e type, int amount);
|
||||
void P_AddActivePlat(plat_t* plat);
|
||||
void P_RemoveActivePlat(plat_t* plat);
|
||||
void EV_StopPlat(line_t* line);
|
||||
void P_ActivateInStasis(int tag);
|
||||
|
||||
|
||||
//
|
||||
// P_DOORS
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
door_normal,
|
||||
close30ThenOpen,
|
||||
door_close,
|
||||
door_open,
|
||||
raiseIn5Mins,
|
||||
blazeRaise,
|
||||
blazeOpen,
|
||||
blazeClose
|
||||
} vldoor_e;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
vldoor_e type;
|
||||
sector_t* sector;
|
||||
fixed_t topheight;
|
||||
fixed_t speed;
|
||||
|
||||
// 1 = up, 0 = waiting at top, -1 = down
|
||||
int direction;
|
||||
|
||||
// tics to wait at the top
|
||||
int topwait;
|
||||
|
||||
// (keep in case a door going down is reset)
|
||||
// when it reaches 0, start going down
|
||||
int topcountdown;
|
||||
} vldoor_t;
|
||||
|
||||
|
||||
#define VDOORSPEED FRACUNIT*2
|
||||
#define VDOORWAIT 150
|
||||
|
||||
|
||||
void EV_VerticalDoor(line_t* line, mobj_t* thing);
|
||||
int EV_DoDoor(line_t* line, vldoor_e type);
|
||||
int EV_DoLockedDoor(line_t* line, vldoor_e type, mobj_t* thing);
|
||||
void T_VerticalDoor(vldoor_t* door);
|
||||
void P_SpawnDoorCloseIn30(sector_t* sec);
|
||||
void P_SpawnDoorRaiseIn5Mins(sector_t* sec, int secnum);
|
||||
|
||||
|
||||
//
|
||||
// P_CEILNG
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
lowerToFloor,
|
||||
raiseToHighest,
|
||||
lowerAndCrush,
|
||||
crushAndRaise,
|
||||
fastCrushAndRaise,
|
||||
silentCrushAndRaise
|
||||
} ceiling_e;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
ceiling_e type;
|
||||
sector_t* sector;
|
||||
fixed_t bottomheight;
|
||||
fixed_t topheight;
|
||||
fixed_t speed;
|
||||
doom_boolean crush;
|
||||
|
||||
// 1 = up, 0 = waiting, -1 = down
|
||||
int direction;
|
||||
|
||||
// ID
|
||||
int tag;
|
||||
int olddirection;
|
||||
} ceiling_t;
|
||||
|
||||
|
||||
#define CEILSPEED FRACUNIT
|
||||
#define CEILWAIT 150
|
||||
#define MAXCEILINGS 30
|
||||
|
||||
|
||||
extern ceiling_t* activeceilings[MAXCEILINGS];
|
||||
|
||||
|
||||
int EV_DoCeiling(line_t* line, ceiling_e type);
|
||||
void T_MoveCeiling(ceiling_t* ceiling);
|
||||
void P_AddActiveCeiling(ceiling_t* c);
|
||||
void P_RemoveActiveCeiling(ceiling_t* c);
|
||||
int EV_CeilingCrushStop(line_t* line);
|
||||
void P_ActivateInStasisCeiling(line_t* line);
|
||||
|
||||
|
||||
//
|
||||
// P_FLOOR
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// lower floor to highest surrounding floor
|
||||
lowerFloor,
|
||||
|
||||
// lower floor to lowest surrounding floor
|
||||
lowerFloorToLowest,
|
||||
|
||||
// lower floor to highest surrounding floor VERY FAST
|
||||
turboLower,
|
||||
|
||||
// raise floor to lowest surrounding CEILING
|
||||
raiseFloor,
|
||||
|
||||
// raise floor to next highest surrounding floor
|
||||
raiseFloorToNearest,
|
||||
|
||||
// raise floor to shortest height texture around it
|
||||
raiseToTexture,
|
||||
|
||||
// lower floor to lowest surrounding floor
|
||||
// and change floorpic
|
||||
lowerAndChange,
|
||||
|
||||
raiseFloor24,
|
||||
raiseFloor24AndChange,
|
||||
raiseFloorCrush,
|
||||
|
||||
// raise to next highest floor, turbo-speed
|
||||
raiseFloorTurbo,
|
||||
donutRaise,
|
||||
raiseFloor512
|
||||
} floor_e;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
build8, // slowly build by 8
|
||||
turbo16 // quickly build by 16
|
||||
} stair_e;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
floor_e type;
|
||||
doom_boolean crush;
|
||||
sector_t* sector;
|
||||
int direction;
|
||||
int newspecial;
|
||||
short texture;
|
||||
fixed_t floordestheight;
|
||||
fixed_t speed;
|
||||
} floormove_t;
|
||||
|
||||
|
||||
#define FLOORSPEED FRACUNIT
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ok,
|
||||
crushed,
|
||||
pastdest
|
||||
} result_e;
|
||||
|
||||
|
||||
result_e T_MovePlane(sector_t* sector, fixed_t speed, fixed_t dest, doom_boolean crush, int floorOrCeiling, int direction);
|
||||
int EV_BuildStairs(line_t* line, stair_e type);
|
||||
int EV_DoFloor(line_t* line, floor_e floortype);
|
||||
void T_MoveFloor(floormove_t* floor);
|
||||
|
||||
//
|
||||
// P_TELEPT
|
||||
//
|
||||
int EV_Teleport(line_t* line, int side, mobj_t* thing);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
612
src/DOOM/p_switch.c
Normal file
612
src/DOOM/p_switch.c
Normal file
@ -0,0 +1,612 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Switches, buttons. Two-state animation. Exits.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "g_game.h"
|
||||
#include "s_sound.h"
|
||||
#include "sounds.h" // Data.
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
//
|
||||
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
|
||||
//
|
||||
switchlist_t alphSwitchList[] =
|
||||
{
|
||||
// Doom shareware episode 1 switches
|
||||
{"SW1BRCOM", "SW2BRCOM", 1},
|
||||
{"SW1BRN1", "SW2BRN1", 1},
|
||||
{"SW1BRN2", "SW2BRN2", 1},
|
||||
{"SW1BRNGN", "SW2BRNGN", 1},
|
||||
{"SW1BROWN", "SW2BROWN", 1},
|
||||
{"SW1COMM", "SW2COMM", 1},
|
||||
{"SW1COMP", "SW2COMP", 1},
|
||||
{"SW1DIRT", "SW2DIRT", 1},
|
||||
{"SW1EXIT", "SW2EXIT", 1},
|
||||
{"SW1GRAY", "SW2GRAY", 1},
|
||||
{"SW1GRAY1", "SW2GRAY1", 1},
|
||||
{"SW1METAL", "SW2METAL", 1},
|
||||
{"SW1PIPE", "SW2PIPE", 1},
|
||||
{"SW1SLAD", "SW2SLAD", 1},
|
||||
{"SW1STARG", "SW2STARG", 1},
|
||||
{"SW1STON1", "SW2STON1", 1},
|
||||
{"SW1STON2", "SW2STON2", 1},
|
||||
{"SW1STONE", "SW2STONE", 1},
|
||||
{"SW1STRTN", "SW2STRTN", 1},
|
||||
|
||||
// Doom registered episodes 2&3 switches
|
||||
{"SW1BLUE", "SW2BLUE", 2},
|
||||
{"SW1CMT", "SW2CMT", 2},
|
||||
{"SW1GARG", "SW2GARG", 2},
|
||||
{"SW1GSTON", "SW2GSTON", 2},
|
||||
{"SW1HOT", "SW2HOT", 2},
|
||||
{"SW1LION", "SW2LION", 2},
|
||||
{"SW1SATYR", "SW2SATYR", 2},
|
||||
{"SW1SKIN", "SW2SKIN", 2},
|
||||
{"SW1VINE", "SW2VINE", 2},
|
||||
{"SW1WOOD", "SW2WOOD", 2},
|
||||
|
||||
// Doom II switches
|
||||
{"SW1PANEL", "SW2PANEL", 3},
|
||||
{"SW1ROCK", "SW2ROCK", 3},
|
||||
{"SW1MET2", "SW2MET2", 3},
|
||||
{"SW1WDMET", "SW2WDMET", 3},
|
||||
{"SW1BRIK", "SW2BRIK", 3},
|
||||
{"SW1MOD1", "SW2MOD1", 3},
|
||||
{"SW1ZIM", "SW2ZIM", 3},
|
||||
{"SW1STON6", "SW2STON6", 3},
|
||||
{"SW1TEK", "SW2TEK", 3},
|
||||
{"SW1MARB", "SW2MARB", 3},
|
||||
{"SW1SKULL", "SW2SKULL", 3},
|
||||
|
||||
{"\0", "\0", 0}
|
||||
};
|
||||
|
||||
int switchlist[MAXSWITCHES * 2];
|
||||
int numswitches;
|
||||
button_t buttonlist[MAXBUTTONS];
|
||||
|
||||
|
||||
//
|
||||
// P_InitSwitchList
|
||||
// Only called at game initialization.
|
||||
//
|
||||
void P_InitSwitchList(void)
|
||||
{
|
||||
int i;
|
||||
int index;
|
||||
int episode;
|
||||
|
||||
episode = 1;
|
||||
|
||||
if (gamemode == registered)
|
||||
episode = 2;
|
||||
else
|
||||
if (gamemode == commercial)
|
||||
episode = 3;
|
||||
|
||||
for (index = 0, i = 0; i < MAXSWITCHES; i++)
|
||||
{
|
||||
if (!alphSwitchList[i].episode)
|
||||
{
|
||||
numswitches = index / 2;
|
||||
switchlist[index] = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (alphSwitchList[i].episode <= episode)
|
||||
{
|
||||
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
|
||||
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Start a button counting down till it turns off.
|
||||
//
|
||||
void P_StartButton(line_t* line, bwhere_e w, int texture, int time)
|
||||
{
|
||||
int i;
|
||||
|
||||
// See if button is already pressed
|
||||
for (i = 0; i < MAXBUTTONS; i++)
|
||||
{
|
||||
if (buttonlist[i].btimer
|
||||
&& buttonlist[i].line == line)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXBUTTONS; i++)
|
||||
{
|
||||
if (!buttonlist[i].btimer)
|
||||
{
|
||||
buttonlist[i].line = line;
|
||||
buttonlist[i].where = w;
|
||||
buttonlist[i].btexture = texture;
|
||||
buttonlist[i].btimer = time;
|
||||
buttonlist[i].soundorg = (mobj_t*)&line->frontsector->soundorg;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
I_Error("Error: P_StartButton: no button slots left!");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Function that changes wall texture.
|
||||
// Tell it if switch is ok to use again (1=yes, it's a button).
|
||||
//
|
||||
void P_ChangeSwitchTexture(line_t* line, int useAgain)
|
||||
{
|
||||
int texTop;
|
||||
int texMid;
|
||||
int texBot;
|
||||
int i;
|
||||
int sound;
|
||||
|
||||
if (!useAgain)
|
||||
line->special = 0;
|
||||
|
||||
texTop = sides[line->sidenum[0]].toptexture;
|
||||
texMid = sides[line->sidenum[0]].midtexture;
|
||||
texBot = sides[line->sidenum[0]].bottomtexture;
|
||||
|
||||
sound = sfx_swtchn;
|
||||
|
||||
// EXIT SWITCH?
|
||||
if (line->special == 11)
|
||||
sound = sfx_swtchx;
|
||||
|
||||
for (i = 0; i < numswitches * 2; i++)
|
||||
{
|
||||
if (switchlist[i] == texTop)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg, sound);
|
||||
sides[line->sidenum[0]].toptexture = switchlist[i ^ 1];
|
||||
|
||||
if (useAgain)
|
||||
P_StartButton(line, top, switchlist[i], BUTTONTIME);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (switchlist[i] == texMid)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg, sound);
|
||||
sides[line->sidenum[0]].midtexture = switchlist[i ^ 1];
|
||||
|
||||
if (useAgain)
|
||||
P_StartButton(line, middle, switchlist[i], BUTTONTIME);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (switchlist[i] == texBot)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg, sound);
|
||||
sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1];
|
||||
|
||||
if (useAgain)
|
||||
P_StartButton(line, bottom, switchlist[i], BUTTONTIME);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_UseSpecialLine
|
||||
// Called when a thing uses a special line.
|
||||
// Only the front sides of lines are usable.
|
||||
//
|
||||
doom_boolean P_UseSpecialLine(mobj_t* thing, line_t* line, int side)
|
||||
{
|
||||
// Err...
|
||||
// Use the back sides of VERY SPECIAL lines...
|
||||
if (side)
|
||||
{
|
||||
switch (line->special)
|
||||
{
|
||||
case 124:
|
||||
// Sliding door open&close
|
||||
// UNUSED?
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Switches that other things can activate.
|
||||
if (!thing->player)
|
||||
{
|
||||
// never open secret doors
|
||||
if (line->flags & ML_SECRET)
|
||||
return false;
|
||||
|
||||
switch (line->special)
|
||||
{
|
||||
case 1: // MANUAL DOOR RAISE
|
||||
case 32: // MANUAL BLUE
|
||||
case 33: // MANUAL RED
|
||||
case 34: // MANUAL YELLOW
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// do something
|
||||
switch (line->special)
|
||||
{
|
||||
// MANUALS
|
||||
case 1: // Vertical Door
|
||||
case 26: // Blue Door/Locked
|
||||
case 27: // Yellow Door /Locked
|
||||
case 28: // Red Door /Locked
|
||||
|
||||
case 31: // Manual door open
|
||||
case 32: // Blue locked door open
|
||||
case 33: // Red locked door open
|
||||
case 34: // Yellow locked door open
|
||||
|
||||
case 117: // Blazing door raise
|
||||
case 118: // Blazing door open
|
||||
EV_VerticalDoor(line, thing);
|
||||
break;
|
||||
|
||||
//UNUSED - Door Slide Open&Close
|
||||
// case 124:
|
||||
// EV_SlidingDoor (line, thing);
|
||||
// break;
|
||||
|
||||
// SWITCHES
|
||||
case 7:
|
||||
// Build Stairs
|
||||
if (EV_BuildStairs(line, build8))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
// Change Donut
|
||||
if (EV_DoDonut(line))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
// Exit level
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
G_ExitLevel();
|
||||
break;
|
||||
|
||||
case 14:
|
||||
// Raise Floor 32 and change texture
|
||||
if (EV_DoPlat(line, raiseAndChange, 32))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
// Raise Floor 24 and change texture
|
||||
if (EV_DoPlat(line, raiseAndChange, 24))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 18:
|
||||
// Raise Floor to next highest floor
|
||||
if (EV_DoFloor(line, raiseFloorToNearest))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 20:
|
||||
// Raise Plat next highest floor and change texture
|
||||
if (EV_DoPlat(line, raiseToNearestAndChange, 0))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 21:
|
||||
// PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line, downWaitUpStay, 0))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 23:
|
||||
// Lower Floor to Lowest
|
||||
if (EV_DoFloor(line, lowerFloorToLowest))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 29:
|
||||
// Raise Door
|
||||
if (EV_DoDoor(line, door_normal))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 41:
|
||||
// Lower Ceiling to Floor
|
||||
if (EV_DoCeiling(line, lowerToFloor))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 71:
|
||||
// Turbo Lower Floor
|
||||
if (EV_DoFloor(line, turboLower))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 49:
|
||||
// Ceiling Crush And Raise
|
||||
if (EV_DoCeiling(line, crushAndRaise))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 50:
|
||||
// Close Door
|
||||
if (EV_DoDoor(line, door_close))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 51:
|
||||
// Secret EXIT
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
G_SecretExitLevel();
|
||||
break;
|
||||
|
||||
case 55:
|
||||
// Raise Floor Crush
|
||||
if (EV_DoFloor(line, raiseFloorCrush))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 101:
|
||||
// Raise Floor
|
||||
if (EV_DoFloor(line, raiseFloor))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 102:
|
||||
// Lower Floor to Surrounding floor height
|
||||
if (EV_DoFloor(line, lowerFloor))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 103:
|
||||
// Open Door
|
||||
if (EV_DoDoor(line, door_open))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 111:
|
||||
// Blazing Door Raise (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeRaise))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 112:
|
||||
// Blazing Door Open (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeOpen))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 113:
|
||||
// Blazing Door Close (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeClose))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 122:
|
||||
// Blazing PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line, blazeDWUS, 0))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 127:
|
||||
// Build Stairs Turbo 16
|
||||
if (EV_BuildStairs(line, turbo16))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 131:
|
||||
// Raise Floor Turbo
|
||||
if (EV_DoFloor(line, raiseFloorTurbo))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 133:
|
||||
// BlzOpenDoor BLUE
|
||||
case 135:
|
||||
// BlzOpenDoor RED
|
||||
case 137:
|
||||
// BlzOpenDoor YELLOW
|
||||
if (EV_DoLockedDoor(line, blazeOpen, thing))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
case 140:
|
||||
// Raise Floor 512
|
||||
if (EV_DoFloor(line, raiseFloor512))
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
break;
|
||||
|
||||
// BUTTONS
|
||||
case 42:
|
||||
// Close Door
|
||||
if (EV_DoDoor(line, door_close))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 43:
|
||||
// Lower Ceiling to Floor
|
||||
if (EV_DoCeiling(line, lowerToFloor))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 45:
|
||||
// Lower Floor to Surrounding floor height
|
||||
if (EV_DoFloor(line, lowerFloor))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 60:
|
||||
// Lower Floor to Lowest
|
||||
if (EV_DoFloor(line, lowerFloorToLowest))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 61:
|
||||
// Open Door
|
||||
if (EV_DoDoor(line, door_open))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 62:
|
||||
// PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line, downWaitUpStay, 1))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 63:
|
||||
// Raise Door
|
||||
if (EV_DoDoor(line, door_normal))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
// Raise Floor to ceiling
|
||||
if (EV_DoFloor(line, raiseFloor))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 66:
|
||||
// Raise Floor 24 and change texture
|
||||
if (EV_DoPlat(line, raiseAndChange, 24))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 67:
|
||||
// Raise Floor 32 and change texture
|
||||
if (EV_DoPlat(line, raiseAndChange, 32))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 65:
|
||||
// Raise Floor Crush
|
||||
if (EV_DoFloor(line, raiseFloorCrush))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 68:
|
||||
// Raise Plat to next highest floor and change texture
|
||||
if (EV_DoPlat(line, raiseToNearestAndChange, 0))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 69:
|
||||
// Raise Floor to next highest floor
|
||||
if (EV_DoFloor(line, raiseFloorToNearest))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 70:
|
||||
// Turbo Lower Floor
|
||||
if (EV_DoFloor(line, turboLower))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 114:
|
||||
// Blazing Door Raise (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeRaise))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 115:
|
||||
// Blazing Door Open (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeOpen))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 116:
|
||||
// Blazing Door Close (faster than TURBO!)
|
||||
if (EV_DoDoor(line, blazeClose))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 123:
|
||||
// Blazing PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line, blazeDWUS, 0))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 132:
|
||||
// Raise Floor Turbo
|
||||
if (EV_DoFloor(line, raiseFloorTurbo))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 99:
|
||||
// BlzOpenDoor BLUE
|
||||
case 134:
|
||||
// BlzOpenDoor RED
|
||||
case 136:
|
||||
// BlzOpenDoor YELLOW
|
||||
if (EV_DoLockedDoor(line, blazeOpen, thing))
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 138:
|
||||
// Light Turn On
|
||||
EV_LightTurnOn(line, 255);
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
|
||||
case 139:
|
||||
// Light Turn Off
|
||||
EV_LightTurnOn(line, 35);
|
||||
P_ChangeSwitchTexture(line, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
117
src/DOOM/p_telept.c
Normal file
117
src/DOOM/p_telept.c
Normal file
@ -0,0 +1,117 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Teleportation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "sounds.h" // Data.
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
//
|
||||
// TELEPORTATION
|
||||
//
|
||||
int EV_Teleport(line_t* line, int side, mobj_t* thing)
|
||||
{
|
||||
int i;
|
||||
int tag;
|
||||
mobj_t* m;
|
||||
mobj_t* fog;
|
||||
unsigned an;
|
||||
thinker_t* thinker;
|
||||
sector_t* sector;
|
||||
fixed_t oldx;
|
||||
fixed_t oldy;
|
||||
fixed_t oldz;
|
||||
|
||||
// don't teleport missiles
|
||||
if (thing->flags & MF_MISSILE)
|
||||
return 0;
|
||||
|
||||
// Don't teleport if hit back of line,
|
||||
// so you can get out of teleporter.
|
||||
if (side == 1)
|
||||
return 0;
|
||||
|
||||
tag = line->tag;
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (sectors[i].tag == tag)
|
||||
{
|
||||
thinker = thinkercap.next;
|
||||
for (thinker = thinkercap.next;
|
||||
thinker != &thinkercap;
|
||||
thinker = thinker->next)
|
||||
{
|
||||
// not a mobj
|
||||
if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
|
||||
m = (mobj_t*)thinker;
|
||||
|
||||
// not a teleportman
|
||||
if (m->type != MT_TELEPORTMAN)
|
||||
continue;
|
||||
|
||||
sector = m->subsector->sector;
|
||||
// wrong sector
|
||||
if (sector - sectors != i)
|
||||
continue;
|
||||
|
||||
oldx = thing->x;
|
||||
oldy = thing->y;
|
||||
oldz = thing->z;
|
||||
|
||||
if (!P_TeleportMove(thing, m->x, m->y))
|
||||
return 0;
|
||||
|
||||
thing->z = thing->floorz; //fixme: not needed?
|
||||
if (thing->player)
|
||||
thing->player->viewz = thing->z + thing->player->viewheight;
|
||||
|
||||
// spawn teleport fog at source and destination
|
||||
fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG);
|
||||
S_StartSound(fog, sfx_telept);
|
||||
an = m->angle >> ANGLETOFINESHIFT;
|
||||
fog = P_SpawnMobj(m->x + 20 * finecosine[an], m->y + 20 * finesine[an]
|
||||
, thing->z, MT_TFOG);
|
||||
|
||||
// emit sound, where?
|
||||
S_StartSound(fog, sfx_telept);
|
||||
|
||||
// don't move for a bit
|
||||
if (thing->player)
|
||||
thing->reactiontime = 18;
|
||||
|
||||
thing->angle = m->angle;
|
||||
thing->momx = thing->momy = thing->momz = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
138
src/DOOM/p_tick.c
Normal file
138
src/DOOM/p_tick.c
Normal file
@ -0,0 +1,138 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Archiving: SaveGame I/O.
|
||||
// Thinker, Ticker.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "p_local.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
int leveltime;
|
||||
|
||||
//
|
||||
// THINKERS
|
||||
// All thinkers should be allocated by Z_Malloc
|
||||
// so they can be operated on uniformly.
|
||||
// The actual structures will vary in size,
|
||||
// but the first element must be thinker_t.
|
||||
//
|
||||
|
||||
// Both the head and tail of the thinker list.
|
||||
thinker_t thinkercap;
|
||||
|
||||
|
||||
//
|
||||
// P_InitThinkers
|
||||
//
|
||||
void P_InitThinkers(void)
|
||||
{
|
||||
thinkercap.prev = thinkercap.next = &thinkercap;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_AddThinker
|
||||
// Adds a new thinker at the end of the list.
|
||||
//
|
||||
void P_AddThinker(thinker_t* thinker)
|
||||
{
|
||||
thinkercap.prev->next = thinker;
|
||||
thinker->next = &thinkercap;
|
||||
thinker->prev = thinkercap.prev;
|
||||
thinkercap.prev = thinker;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_RemoveThinker
|
||||
// Deallocation is lazy -- it will not actually be freed
|
||||
// until its thinking turn comes up.
|
||||
//
|
||||
void P_RemoveThinker(thinker_t* thinker)
|
||||
{
|
||||
// FIXME: NOP.
|
||||
thinker->function.acv = (actionf_v)(-1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_RunThinkers
|
||||
//
|
||||
void P_RunThinkers(void)
|
||||
{
|
||||
thinker_t* currentthinker;
|
||||
|
||||
currentthinker = thinkercap.next;
|
||||
while (currentthinker != &thinkercap)
|
||||
{
|
||||
if (currentthinker->function.acv == (actionf_v)(-1))
|
||||
{
|
||||
// time to remove it
|
||||
currentthinker->next->prev = currentthinker->prev;
|
||||
currentthinker->prev->next = currentthinker->next;
|
||||
Z_Free(currentthinker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentthinker->function.acp1)
|
||||
currentthinker->function.acp1(currentthinker);
|
||||
}
|
||||
currentthinker = currentthinker->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_Ticker
|
||||
//
|
||||
void P_Ticker(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// run the tic
|
||||
if (paused)
|
||||
return;
|
||||
|
||||
// pause if in menu and at least one tic has been run
|
||||
if (!netgame
|
||||
&& menuactive
|
||||
&& !demoplayback
|
||||
&& players[consoleplayer].viewz != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
P_PlayerThink(&players[i]);
|
||||
|
||||
P_RunThinkers();
|
||||
P_UpdateSpecials();
|
||||
P_RespawnSpecials();
|
||||
|
||||
// for par times
|
||||
leveltime++;
|
||||
}
|
38
src/DOOM/p_tick.h
Normal file
38
src/DOOM/p_tick.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// ?
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __P_TICK__
|
||||
#define __P_TICK__
|
||||
|
||||
|
||||
// Called by C_Ticker,
|
||||
// can call G_PlayerExited.
|
||||
// Carries out all thinking of monsters and players.
|
||||
void P_Ticker(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
370
src/DOOM/p_user.c
Normal file
370
src/DOOM/p_user.c
Normal file
@ -0,0 +1,370 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Player related stuff.
|
||||
// Bobbing POV/weapon, movement.
|
||||
// Pending weapon.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_event.h"
|
||||
#include "p_local.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
// Index of the special effects (INVUL inverse) map.
|
||||
#define INVERSECOLORMAP 32
|
||||
|
||||
// 16 pixels of bob
|
||||
#define MAXBOB 0x100000
|
||||
|
||||
#define ANG5 (ANG90/18)
|
||||
|
||||
|
||||
//
|
||||
// Movement.
|
||||
//
|
||||
|
||||
doom_boolean onground;
|
||||
|
||||
|
||||
//
|
||||
// P_Thrust
|
||||
// Moves the given origin along a given angle.
|
||||
//
|
||||
void P_Thrust(player_t* player, angle_t angle, fixed_t move)
|
||||
{
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
|
||||
player->mo->momx += FixedMul(move, finecosine[angle]);
|
||||
player->mo->momy += FixedMul(move, finesine[angle]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CalcHeight
|
||||
// Calculate the walking / running height adjustment
|
||||
//
|
||||
void P_CalcHeight(player_t* player)
|
||||
{
|
||||
int angle;
|
||||
fixed_t bob;
|
||||
|
||||
// Regular movement bobbing
|
||||
// (needs to be calculated for gun swing
|
||||
// even if not on ground)
|
||||
// OPTIMIZE: tablify angle
|
||||
// Note: a LUT allows for effects
|
||||
// like a ramp with low health.
|
||||
player->bob =
|
||||
FixedMul(player->mo->momx, player->mo->momx)
|
||||
+ FixedMul(player->mo->momy, player->mo->momy);
|
||||
|
||||
player->bob >>= 2;
|
||||
|
||||
if (player->bob > MAXBOB)
|
||||
player->bob = MAXBOB;
|
||||
|
||||
if ((player->cheats & CF_NOMOMENTUM) || !onground)
|
||||
{
|
||||
player->viewz = player->mo->z + VIEWHEIGHT;
|
||||
|
||||
if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT)
|
||||
player->viewz = player->mo->ceilingz - 4 * FRACUNIT;
|
||||
|
||||
player->viewz = player->mo->z + player->viewheight;
|
||||
return;
|
||||
}
|
||||
|
||||
angle = (FINEANGLES / 20 * leveltime) & FINEMASK;
|
||||
bob = FixedMul(player->bob / 2, finesine[angle]);
|
||||
|
||||
|
||||
// move viewheight
|
||||
if (player->playerstate == PST_LIVE)
|
||||
{
|
||||
player->viewheight += player->deltaviewheight;
|
||||
|
||||
if (player->viewheight > VIEWHEIGHT)
|
||||
{
|
||||
player->viewheight = VIEWHEIGHT;
|
||||
player->deltaviewheight = 0;
|
||||
}
|
||||
|
||||
if (player->viewheight < VIEWHEIGHT / 2)
|
||||
{
|
||||
player->viewheight = VIEWHEIGHT / 2;
|
||||
if (player->deltaviewheight <= 0)
|
||||
player->deltaviewheight = 1;
|
||||
}
|
||||
|
||||
if (player->deltaviewheight)
|
||||
{
|
||||
player->deltaviewheight += FRACUNIT / 4;
|
||||
if (!player->deltaviewheight)
|
||||
player->deltaviewheight = 1;
|
||||
}
|
||||
}
|
||||
player->viewz = player->mo->z + player->viewheight + bob;
|
||||
|
||||
if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT)
|
||||
player->viewz = player->mo->ceilingz - 4 * FRACUNIT;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_MovePlayer
|
||||
//
|
||||
void P_MovePlayer(player_t* player)
|
||||
{
|
||||
ticcmd_t* cmd;
|
||||
|
||||
cmd = &player->cmd;
|
||||
|
||||
player->mo->angle += (cmd->angleturn << 16);
|
||||
|
||||
// Do not let the player control movement
|
||||
// if not onground.
|
||||
onground = (player->mo->z <= player->mo->floorz);
|
||||
|
||||
if (cmd->forwardmove && onground)
|
||||
P_Thrust(player, player->mo->angle, cmd->forwardmove * 2048);
|
||||
|
||||
if (cmd->sidemove && onground)
|
||||
P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048);
|
||||
|
||||
if ((cmd->forwardmove || cmd->sidemove)
|
||||
&& player->mo->state == &states[S_PLAY])
|
||||
{
|
||||
P_SetMobjState(player->mo, S_PLAY_RUN1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_DeathThink
|
||||
// Fall on your face when dying.
|
||||
// Decrease POV height to floor height.
|
||||
//
|
||||
void P_DeathThink(player_t* player)
|
||||
{
|
||||
angle_t angle;
|
||||
angle_t delta;
|
||||
|
||||
P_MovePsprites(player);
|
||||
|
||||
// fall to the ground
|
||||
if (player->viewheight > 6 * FRACUNIT)
|
||||
player->viewheight -= FRACUNIT;
|
||||
|
||||
if (player->viewheight < 6 * FRACUNIT)
|
||||
player->viewheight = 6 * FRACUNIT;
|
||||
|
||||
player->deltaviewheight = 0;
|
||||
onground = (player->mo->z <= player->mo->floorz);
|
||||
P_CalcHeight(player);
|
||||
|
||||
if (player->attacker && player->attacker != player->mo)
|
||||
{
|
||||
angle = R_PointToAngle2(player->mo->x,
|
||||
player->mo->y,
|
||||
player->attacker->x,
|
||||
player->attacker->y);
|
||||
|
||||
delta = angle - player->mo->angle;
|
||||
|
||||
if (delta < ANG5 || delta >(unsigned) - ANG5)
|
||||
{
|
||||
// Looking at killer,
|
||||
// so fade damage flash down.
|
||||
player->mo->angle = angle;
|
||||
|
||||
if (player->damagecount)
|
||||
player->damagecount--;
|
||||
}
|
||||
else if (delta < ANG180)
|
||||
player->mo->angle += ANG5;
|
||||
else
|
||||
player->mo->angle -= ANG5;
|
||||
}
|
||||
else if (player->damagecount)
|
||||
player->damagecount--;
|
||||
|
||||
|
||||
if (player->cmd.buttons & BT_USE)
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_PlayerThink
|
||||
//
|
||||
void P_PlayerThink(player_t* player)
|
||||
{
|
||||
ticcmd_t* cmd;
|
||||
weapontype_t newweapon;
|
||||
|
||||
// fixme: do this in the cheat code
|
||||
if (player->cheats & CF_NOCLIP)
|
||||
player->mo->flags |= MF_NOCLIP;
|
||||
else
|
||||
player->mo->flags &= ~MF_NOCLIP;
|
||||
|
||||
// chain saw run forward
|
||||
cmd = &player->cmd;
|
||||
if (player->mo->flags & MF_JUSTATTACKED)
|
||||
{
|
||||
cmd->angleturn = 0;
|
||||
cmd->forwardmove = 0xc800 / 512;
|
||||
cmd->sidemove = 0;
|
||||
player->mo->flags &= ~MF_JUSTATTACKED;
|
||||
}
|
||||
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
P_DeathThink(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move around.
|
||||
// Reactiontime is used to prevent movement
|
||||
// for a bit after a teleport.
|
||||
if (player->mo->reactiontime)
|
||||
player->mo->reactiontime--;
|
||||
else
|
||||
P_MovePlayer(player);
|
||||
|
||||
P_CalcHeight(player);
|
||||
|
||||
if (player->mo->subsector->sector->special)
|
||||
P_PlayerInSpecialSector(player);
|
||||
|
||||
// Check for weapon change.
|
||||
|
||||
// A special event has no other buttons.
|
||||
if (cmd->buttons & BT_SPECIAL)
|
||||
cmd->buttons = 0;
|
||||
|
||||
if (cmd->buttons & BT_CHANGE)
|
||||
{
|
||||
// The actual changing of the weapon is done
|
||||
// when the weapon psprite can do it
|
||||
// (read: not in the middle of an attack).
|
||||
newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT;
|
||||
|
||||
if (newweapon == wp_fist
|
||||
&& player->weaponowned[wp_chainsaw]
|
||||
&& !(player->readyweapon == wp_chainsaw
|
||||
&& player->powers[pw_strength]))
|
||||
{
|
||||
newweapon = wp_chainsaw;
|
||||
}
|
||||
|
||||
if ((gamemode == commercial)
|
||||
&& newweapon == wp_shotgun
|
||||
&& player->weaponowned[wp_supershotgun]
|
||||
&& player->readyweapon != wp_supershotgun)
|
||||
{
|
||||
newweapon = wp_supershotgun;
|
||||
}
|
||||
|
||||
|
||||
if (player->weaponowned[newweapon]
|
||||
&& newweapon != player->readyweapon)
|
||||
{
|
||||
// Do not go to plasma or BFG in shareware,
|
||||
// even if cheated.
|
||||
if ((newweapon != wp_plasma
|
||||
&& newweapon != wp_bfg)
|
||||
|| (gamemode != shareware))
|
||||
{
|
||||
player->pendingweapon = newweapon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for use
|
||||
if (cmd->buttons & BT_USE)
|
||||
{
|
||||
if (!player->usedown)
|
||||
{
|
||||
P_UseLines(player);
|
||||
player->usedown = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
player->usedown = false;
|
||||
|
||||
// cycle psprites
|
||||
P_MovePsprites(player);
|
||||
|
||||
// Counters, time dependend power ups.
|
||||
|
||||
// Strength counts up to diminish fade.
|
||||
if (player->powers[pw_strength])
|
||||
player->powers[pw_strength]++;
|
||||
|
||||
if (player->powers[pw_invulnerability])
|
||||
player->powers[pw_invulnerability]--;
|
||||
|
||||
if (player->powers[pw_invisibility])
|
||||
if (!--player->powers[pw_invisibility])
|
||||
player->mo->flags &= ~MF_SHADOW;
|
||||
|
||||
if (player->powers[pw_infrared])
|
||||
player->powers[pw_infrared]--;
|
||||
|
||||
if (player->powers[pw_ironfeet])
|
||||
player->powers[pw_ironfeet]--;
|
||||
|
||||
if (player->damagecount)
|
||||
player->damagecount--;
|
||||
|
||||
if (player->bonuscount)
|
||||
player->bonuscount--;
|
||||
|
||||
|
||||
// Handling colormaps.
|
||||
if (player->powers[pw_invulnerability])
|
||||
{
|
||||
if (player->powers[pw_invulnerability] > 4 * 32
|
||||
|| (player->powers[pw_invulnerability] & 8))
|
||||
player->fixedcolormap = INVERSECOLORMAP;
|
||||
else
|
||||
player->fixedcolormap = 0;
|
||||
}
|
||||
else if (player->powers[pw_infrared])
|
||||
{
|
||||
if (player->powers[pw_infrared] > 4 * 32
|
||||
|| (player->powers[pw_infrared] & 8))
|
||||
{
|
||||
// almost full bright
|
||||
player->fixedcolormap = 1;
|
||||
}
|
||||
else
|
||||
player->fixedcolormap = 0;
|
||||
}
|
||||
else
|
||||
player->fixedcolormap = 0;
|
||||
}
|
563
src/DOOM/r_bsp.c
Normal file
563
src/DOOM/r_bsp.c
Normal file
@ -0,0 +1,563 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// BSP traversal, handling of LineSegs for rendering.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "doom_config.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "m_bbox.h"
|
||||
#include "i_system.h"
|
||||
#include "r_main.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_things.h"
|
||||
#include "doomstat.h" // State.
|
||||
#include "r_state.h" // State.
|
||||
|
||||
|
||||
#define MAXSEGS 32
|
||||
|
||||
|
||||
//
|
||||
// ClipWallSegment
|
||||
// Clips the given range of columns
|
||||
// and includes it in the new clip list.
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
int first;
|
||||
int last;
|
||||
} cliprange_t;
|
||||
|
||||
|
||||
seg_t* curline;
|
||||
side_t* sidedef;
|
||||
line_t* linedef;
|
||||
sector_t* frontsector;
|
||||
sector_t* backsector;
|
||||
|
||||
drawseg_t drawsegs[MAXDRAWSEGS];
|
||||
drawseg_t* ds_p;
|
||||
|
||||
// newend is one past the last valid seg
|
||||
cliprange_t* newend;
|
||||
cliprange_t solidsegs[MAXSEGS];
|
||||
|
||||
int checkcoord[12][4] =
|
||||
{
|
||||
{3,0,2,1},
|
||||
{3,0,2,0},
|
||||
{3,1,2,0},
|
||||
{0},
|
||||
{2,0,2,1},
|
||||
{0,0,0,0},
|
||||
{3,1,3,0},
|
||||
{0},
|
||||
{2,0,3,1},
|
||||
{2,1,3,1},
|
||||
{2,1,3,0}
|
||||
};
|
||||
|
||||
|
||||
void R_StoreWallRange(int start, int stop);
|
||||
|
||||
|
||||
//
|
||||
// R_ClearDrawSegs
|
||||
//
|
||||
void R_ClearDrawSegs(void)
|
||||
{
|
||||
ds_p = drawsegs;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_ClipSolidWallSegment
|
||||
// Does handle solid walls,
|
||||
// e.g. single sided LineDefs (middle texture)
|
||||
// that entirely block the view.
|
||||
//
|
||||
void R_ClipSolidWallSegment(int first, int last)
|
||||
{
|
||||
cliprange_t* next;
|
||||
cliprange_t* start;
|
||||
|
||||
// Find the first range that touches the range
|
||||
// (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start),
|
||||
// so insert a new clippost.
|
||||
R_StoreWallRange(first, last);
|
||||
next = newend;
|
||||
newend++;
|
||||
|
||||
while (next != start)
|
||||
{
|
||||
*next = *(next - 1);
|
||||
next--;
|
||||
}
|
||||
next->first = first;
|
||||
next->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
// Now adjust the clip size.
|
||||
start->first = first;
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
next = start;
|
||||
while (last >= (next + 1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
R_StoreWallRange(next->last + 1, (next + 1)->first - 1);
|
||||
next++;
|
||||
|
||||
if (last <= next->last)
|
||||
{
|
||||
// Bottom is contained in next.
|
||||
// Adjust the clip size.
|
||||
start->last = next->last;
|
||||
goto crunch;
|
||||
}
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
R_StoreWallRange(next->last + 1, last);
|
||||
// Adjust the clip size.
|
||||
start->last = last;
|
||||
|
||||
// Remove start+1 to next from the clip list,
|
||||
// because start now covers their area.
|
||||
crunch:
|
||||
if (next == start)
|
||||
{
|
||||
// Post just extended past the bottom of one post.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (next++ != newend)
|
||||
{
|
||||
// Remove a post.
|
||||
*++start = *next;
|
||||
}
|
||||
|
||||
newend = start + 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_ClipPassWallSegment
|
||||
// Clips the given range of columns,
|
||||
// but does not includes it in the clip list.
|
||||
// Does handle windows,
|
||||
// e.g. LineDefs with upper and lower texture.
|
||||
//
|
||||
void R_ClipPassWallSegment(int first, int last)
|
||||
{
|
||||
cliprange_t* start;
|
||||
|
||||
// Find the first range that touches the range
|
||||
// (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start).
|
||||
R_StoreWallRange(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
while (last >= (start + 1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
R_StoreWallRange(start->last + 1, (start + 1)->first - 1);
|
||||
start++;
|
||||
|
||||
if (last <= start->last)
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
R_StoreWallRange(start->last + 1, last);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_ClearClipSegs
|
||||
//
|
||||
void R_ClearClipSegs(void)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = -1;
|
||||
solidsegs[1].first = viewwidth;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs + 2;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_AddLine
|
||||
// Clips the given segment
|
||||
// and adds any visible pieces to the line list.
|
||||
//
|
||||
void R_AddLine(seg_t* line)
|
||||
{
|
||||
int x1;
|
||||
int x2;
|
||||
angle_t angle1;
|
||||
angle_t angle2;
|
||||
angle_t span;
|
||||
angle_t tspan;
|
||||
|
||||
curline = line;
|
||||
|
||||
// OPTIMIZE: quickly reject orthogonal back sides.
|
||||
angle1 = R_PointToAngle(line->v1->x, line->v1->y);
|
||||
angle2 = R_PointToAngle(line->v2->x, line->v2->y);
|
||||
|
||||
// Clip to view edges.
|
||||
// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).
|
||||
span = angle1 - angle2;
|
||||
|
||||
// Back side? I.e. backface culling?
|
||||
if (span >= ANG180)
|
||||
return;
|
||||
|
||||
// Global angle needed by segcalc.
|
||||
rw_angle1 = angle1;
|
||||
angle1 -= viewangle;
|
||||
angle2 -= viewangle;
|
||||
|
||||
tspan = angle1 + clipangle;
|
||||
if (tspan > 2 * clipangle)
|
||||
{
|
||||
tspan -= 2 * clipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return;
|
||||
|
||||
angle1 = clipangle;
|
||||
}
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > 2 * clipangle)
|
||||
{
|
||||
tspan -= 2 * clipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return;
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
angle2 = -clipangle;
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
// The seg is in the view range,
|
||||
// but not necessarily visible.
|
||||
angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT;
|
||||
angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT;
|
||||
x1 = viewangletox[angle1];
|
||||
x2 = viewangletox[angle2];
|
||||
|
||||
// Does not cross a pixel?
|
||||
if (x1 == x2)
|
||||
return;
|
||||
|
||||
backsector = line->backsector;
|
||||
|
||||
// Single sided line?
|
||||
if (!backsector)
|
||||
goto clipsolid;
|
||||
|
||||
// Closed door.
|
||||
if (backsector->ceilingheight <= frontsector->floorheight
|
||||
|| backsector->floorheight >= frontsector->ceilingheight)
|
||||
goto clipsolid;
|
||||
|
||||
// Window.
|
||||
if (backsector->ceilingheight != frontsector->ceilingheight
|
||||
|| backsector->floorheight != frontsector->floorheight)
|
||||
goto clippass;
|
||||
|
||||
// Reject empty lines used for triggers
|
||||
// and special events.
|
||||
// Identical floor and ceiling on both sides,
|
||||
// identical light levels on both sides,
|
||||
// and no middle texture.
|
||||
if (backsector->ceilingpic == frontsector->ceilingpic
|
||||
&& backsector->floorpic == frontsector->floorpic
|
||||
&& backsector->lightlevel == frontsector->lightlevel
|
||||
&& curline->sidedef->midtexture == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
clippass:
|
||||
R_ClipPassWallSegment(x1, x2 - 1);
|
||||
return;
|
||||
|
||||
clipsolid:
|
||||
R_ClipSolidWallSegment(x1, x2 - 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_CheckBBox
|
||||
// Checks BSP node/subtree bounding box.
|
||||
// Returns true
|
||||
// if some part of the bbox might be visible.
|
||||
//
|
||||
doom_boolean R_CheckBBox(fixed_t* bspcoord)
|
||||
{
|
||||
int boxx;
|
||||
int boxy;
|
||||
int boxpos;
|
||||
|
||||
fixed_t x1;
|
||||
fixed_t y1;
|
||||
fixed_t x2;
|
||||
fixed_t y2;
|
||||
|
||||
angle_t angle1;
|
||||
angle_t angle2;
|
||||
angle_t span;
|
||||
angle_t tspan;
|
||||
|
||||
cliprange_t* start;
|
||||
|
||||
int sx1;
|
||||
int sx2;
|
||||
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
if (viewx <= bspcoord[BOXLEFT])
|
||||
boxx = 0;
|
||||
else if (viewx < bspcoord[BOXRIGHT])
|
||||
boxx = 1;
|
||||
else
|
||||
boxx = 2;
|
||||
|
||||
if (viewy >= bspcoord[BOXTOP])
|
||||
boxy = 0;
|
||||
else if (viewy > bspcoord[BOXBOTTOM])
|
||||
boxy = 1;
|
||||
else
|
||||
boxy = 2;
|
||||
|
||||
boxpos = (boxy << 2) + boxx;
|
||||
if (boxpos == 5)
|
||||
return true;
|
||||
|
||||
x1 = bspcoord[checkcoord[boxpos][0]];
|
||||
y1 = bspcoord[checkcoord[boxpos][1]];
|
||||
x2 = bspcoord[checkcoord[boxpos][2]];
|
||||
y2 = bspcoord[checkcoord[boxpos][3]];
|
||||
|
||||
// check clip list for an open space
|
||||
angle1 = R_PointToAngle(x1, y1) - viewangle;
|
||||
angle2 = R_PointToAngle(x2, y2) - viewangle;
|
||||
|
||||
span = angle1 - angle2;
|
||||
|
||||
// Sitting on a line?
|
||||
if (span >= ANG180)
|
||||
return true;
|
||||
|
||||
tspan = angle1 + clipangle;
|
||||
|
||||
if (tspan > 2 * clipangle)
|
||||
{
|
||||
tspan -= 2 * clipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return false;
|
||||
|
||||
angle1 = clipangle;
|
||||
}
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > 2 * clipangle)
|
||||
{
|
||||
tspan -= 2 * clipangle;
|
||||
|
||||
// Totally off the left edge?
|
||||
if (tspan >= span)
|
||||
return false;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
angle2 = -clipangle;
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
|
||||
// Find the first clippost
|
||||
// that touches the source post
|
||||
// (adjacent pixels are touching).
|
||||
angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT;
|
||||
angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT;
|
||||
sx1 = viewangletox[angle1];
|
||||
sx2 = viewangletox[angle2];
|
||||
|
||||
// Does not cross a pixel.
|
||||
if (sx1 == sx2)
|
||||
return false;
|
||||
sx2--;
|
||||
|
||||
start = solidsegs;
|
||||
while (start->last < sx2)
|
||||
start++;
|
||||
|
||||
if (sx1 >= start->first
|
||||
&& sx2 <= start->last)
|
||||
{
|
||||
// The clippost contains the new span.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// R_Subsector
|
||||
// Determine floor/ceiling planes.
|
||||
// Add sprites of things in sector.
|
||||
// Draw one or more line segments.
|
||||
//
|
||||
void R_Subsector(int num)
|
||||
{
|
||||
int count;
|
||||
seg_t* line;
|
||||
subsector_t* sub;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
{
|
||||
//I_Error("Error: R_Subsector: ss %i with numss = %i",
|
||||
// num,
|
||||
// numsubsectors);
|
||||
|
||||
|
||||
doom_strcpy(error_buf, "Error: R_Subsector: ss ");
|
||||
doom_concat(error_buf, doom_itoa(num, 10));
|
||||
doom_concat(error_buf, " with numss = ");
|
||||
doom_concat(error_buf, doom_itoa(numsubsectors, 10));
|
||||
I_Error(error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
sscount++;
|
||||
sub = &subsectors[num];
|
||||
frontsector = sub->sector;
|
||||
count = sub->numlines;
|
||||
line = &segs[sub->firstline];
|
||||
|
||||
if (frontsector->floorheight < viewz)
|
||||
{
|
||||
floorplane = R_FindPlane(frontsector->floorheight,
|
||||
frontsector->floorpic,
|
||||
frontsector->lightlevel);
|
||||
}
|
||||
else
|
||||
floorplane = 0;
|
||||
|
||||
if (frontsector->ceilingheight > viewz
|
||||
|| frontsector->ceilingpic == skyflatnum)
|
||||
{
|
||||
ceilingplane = R_FindPlane(frontsector->ceilingheight,
|
||||
frontsector->ceilingpic,
|
||||
frontsector->lightlevel);
|
||||
}
|
||||
else
|
||||
ceilingplane = 0;
|
||||
|
||||
R_AddSprites(frontsector);
|
||||
|
||||
while (count--)
|
||||
{
|
||||
R_AddLine(line);
|
||||
line++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RenderBSPNode
|
||||
// Renders all subsectors below a given node,
|
||||
// traversing subtree recursively.
|
||||
// Just call with BSP root.
|
||||
void R_RenderBSPNode(int bspnum)
|
||||
{
|
||||
node_t* bsp;
|
||||
int side;
|
||||
|
||||
// Found a subsector?
|
||||
if (bspnum & NF_SUBSECTOR)
|
||||
{
|
||||
if (bspnum == -1)
|
||||
R_Subsector(0);
|
||||
else
|
||||
R_Subsector(bspnum & (~NF_SUBSECTOR));
|
||||
return;
|
||||
}
|
||||
|
||||
bsp = &nodes[bspnum];
|
||||
|
||||
// Decide which side the view point is on.
|
||||
side = R_PointOnSide(viewx, viewy, bsp);
|
||||
|
||||
// Recursively divide front space.
|
||||
R_RenderBSPNode(bsp->children[side]);
|
||||
|
||||
// Possibly divide back space.
|
||||
if (R_CheckBBox(bsp->bbox[side ^ 1]))
|
||||
R_RenderBSPNode(bsp->children[side ^ 1]);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user