as released 2010-08-12

This commit is contained in:
archive 2010-08-12 00:00:00 +00:00
commit 3d8bca1749
620 changed files with 480657 additions and 0 deletions

643
COPYING.txt Normal file
View File

@ -0,0 +1,643 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
ADDITIONAL TERMS APPLICABLE TO THE RETURN TO CASTLE WOLFENSTEIN SINGLE PLAYER GPL SOURCE CODE.
The following additional terms (“Additional Terms”) supplement and modify the GNU General Public License, Version 3 (“GPL”) applicable to the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). In addition to the terms and conditions of the GPL, the RTCW SP Source Code is subject to the further restrictions below.
1. Replacement of Section 15. Section 15 of the GPL shall be deleted in its entirety and replaced with the following:
“15. Disclaimer of Warranty.
THE PROGRAM IS PROVIDED WITHOUT ANY WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, TITLE AND MERCHANTABILITY. THE PROGRAM IS BEING DELIVERED OR MADE AVAILABLE “AS IS”, “WITH ALL FAULTS” AND WITHOUT WARRANTY OR REPRESENTATION. 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.”
2. Replacement of Section 16. Section 16 of the GPL shall be deleted in its entirety and replaced with the following:
“16. LIMITATION OF LIABILITY.
UNDER NO CIRCUMSTANCES SHALL ANY COPYRIGHT HOLDER OR ITS AFFILIATES, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, FOR ANY DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, DIRECT, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES ARISING FROM, OUT OF OR IN CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM OR OTHER DEALINGS WITH 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), WHETHER OR NOT ANY COPYRIGHT HOLDER OR SUCH OTHER PARTY RECEIVES NOTICE OF ANY SUCH DAMAGES AND WHETHER OR NOT SUCH DAMAGES COULD HAVE BEEN FORESEEN.”
3. LEGAL NOTICES; NO TRADEMARK LICENSE; ORIGIN. You must reproduce faithfully all trademark, copyright and other proprietary and legal notices on any copies of the Program or any other required author attributions. This license does not grant you rights to use any copyright holder or any other partys name, logo, or trademarks. Neither the name of the copyright holder or its affiliates, or any other party who modifies and/or conveys the Program may be used to endorse or promote products derived from this software without specific prior written permission. The origin of the Program must not be misrepresented; you must not claim that you wrote the original Program. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original Program.
4. INDEMNIFICATION. IF YOU CONVEY A COVERED WORK AND AGREE WITH ANY RECIPIENT OF THAT COVERED WORK THAT YOU WILL ASSUME ANY LIABILITY FOR THAT COVERED WORK, YOU HEREBY AGREE TO INDEMNIFY, DEFEND AND HOLD HARMLESS THE OTHER LICENSORS AND AUTHORS OF THAT COVERED WORK FOR ANY DAMAEGS, DEMANDS, CLAIMS, LOSSES, CAUSES OF ACTION, LAWSUITS, JUDGMENTS EXPENSES (INCLUDING WITHOUT LIMITATION REASONABLE ATTORNEYS' FEES AND EXPENSES) OR ANY OTHER LIABLITY ARISING FROM, RELATED TO OR IN CONNECTION WITH YOUR ASSUMPTIONS OF LIABILITY.

133
README.txt Normal file
View File

@ -0,0 +1,133 @@
Return to Castle Wolfenstein single player GPL source release
=============================================================
This file contains the following sections:
GENERAL NOTES
LICENSE
GENERAL NOTES
=============
Game data and patching:
-----------------------
This source release does not contain any game data, the game data is still
covered by the original EULA and must be obeyed as usual.
You must patch the game to the latest version.
Note that RTCW is available from the Steam store at
http://store.steampowered.com/app/9010/
Linux note: due to the game CD containing only a Windows version of the game,
you must install and update the game using WINE to get the game data.
Compiling on win32:
-------------------
A Visual C++ 2008 project is provided in src\wolf.sln.
The solution file is compatible with the Express release of Visual C++.
You will need to execute src\extractfuncs\extractfuncs.bat to generate src\game\g_save.c
You can test your binaries by replacing WolfSP.exe, qagamex86.dll, cgamex86.dll, uix86.dll at the top of the RTCW install
Compiling on GNU/Linux x86:
---------------------------
Go to the src/unix directory, and run the cons script
(cons is a perl based precursor to scons, this is what we were using at the time)
Run ./cons -h to review build options. Use ./cons -- release to compile in release mode.
If problems occur, consult the internet.
Other platforms, updated source code, security issues:
------------------------------------------------------
If you have obtained this source code several weeks after the time of release
(August 2010), it is likely that you can find modified and improved
versions of the engine in various open source projects across the internet.
Depending what is your interest with the source code, those may be a better
starting point.
LICENSE
=======
See COPYING.txt for the GNU GENERAL PUBLIC LICENSE
ADDITIONAL TERMS: The Return to Castle Wolfenstein single player GPL Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU GPL which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
EXCLUDED CODE: The code described below and contained in the Return to Castle Wolfenstein single player GPL Source Code release is not part of the Program covered by the GPL and is expressly excluded from its terms. You are solely responsible for obtaining from the copyright holder a license for such code and complying with the applicable license terms.
IO on .zip files using portions of zlib
---------------------------------------------------------------------------
lines file(s)
4301 src/qcommon/unzip.c
Copyright (C) 1998 Gilles Vollant
zlib is Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
MD4 Message-Digest Algorithm
-----------------------------------------------------------------------------
lines file(s)
289 src/qcommon/md4.c
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
License to copy and use this software is granted provided that it is identified
as the <93>RSA Data Security, Inc. MD4 Message-Digest Algorithm<94> in all mater
ial mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such work
s are identified as <93>derived from the RSA Data Security, Inc. MD4 Message-Dig
est Algorithm<94> in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchanta
bility of this software or the suitability of this software for any particular p
urpose. It is provided <93>as is<94> without express or implied warranty of any
kind.
JPEG library
-----------------------------------------------------------------------------
src/jpeg-6
Copyright (C) 1991-1995, Thomas G. Lane
Permission is hereby granted to use, copy, modify, and distribute this
software (or portions thereof) for any purpose, without fee, subject to these
conditions:
(1) If any part of the source code for this software is distributed, then this
README file must be included, with this copyright and no-warranty notice
unaltered; and any additions, deletions, or changes to the original files
must be clearly indicated in accompanying documentation.
(2) If only executable code is distributed, then the accompanying
documentation must state that "this software is based in part on the work of
the Independent JPEG Group".
(3) Permission for use of this software is granted only if the user accepts
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
NOTE: unfortunately the README that came with our copy of the library has
been lost, so the one from release 6b is included instead. There are a few
'glue type' modifications to the library to make it easier to use from
the engine, but otherwise the dependency can be easily cleaned up to a
better release of the library.

394
main/ui/menudef.h Normal file
View File

@ -0,0 +1,394 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#define ITEM_TYPE_TEXT 0 // simple text
#define ITEM_TYPE_BUTTON 1 // button, basically text with a border
#define ITEM_TYPE_RADIOBUTTON 2 // toggle button, may be grouped
#define ITEM_TYPE_CHECKBOX 3 // check box
#define ITEM_TYPE_EDITFIELD 4 // editable text, associated with a cvar
#define ITEM_TYPE_COMBO 5 // drop down list
#define ITEM_TYPE_LISTBOX 6 // scrollable list
#define ITEM_TYPE_MODEL 7 // model
#define ITEM_TYPE_OWNERDRAW 8 // owner draw, name specs what it is
#define ITEM_TYPE_NUMERICFIELD 9 // editable text, associated with a cvar
#define ITEM_TYPE_SLIDER 10 // mouse speed, volume, etc.
#define ITEM_TYPE_YESNO 11 // yes no cvar setting
#define ITEM_TYPE_MULTI 12 // multiple list setting, enumerated
#define ITEM_TYPE_BIND 13 // multiple list setting, enumerated
#define ITEM_TYPE_MENUMODEL 14 // special menu model
#define ITEM_TYPE_VALIDFILEFIELD 15 // text must be valid for use in a dos filename
#define ITEM_ALIGN_LEFT 0 // left alignment
#define ITEM_ALIGN_CENTER 1 // center alignment
#define ITEM_ALIGN_RIGHT 2 // right alignment
#define ITEM_TEXTSTYLE_NORMAL 0 // normal text
#define ITEM_TEXTSTYLE_BLINK 1 // fast blinking
#define ITEM_TEXTSTYLE_PULSE 2 // slow pulsing
#define ITEM_TEXTSTYLE_SHADOWED 3 // drop shadow ( need a color for this )
#define ITEM_TEXTSTYLE_OUTLINED 4 // drop shadow ( need a color for this )
#define ITEM_TEXTSTYLE_OUTLINESHADOWED 5 // drop shadow ( need a color for this )
#define ITEM_TEXTSTYLE_SHADOWEDMORE 6 // drop shadow ( need a color for this )
#define WINDOW_BORDER_NONE 0 // no border
#define WINDOW_BORDER_FULL 1 // full border based on border color ( single pixel )
#define WINDOW_BORDER_HORZ 2 // horizontal borders only
#define WINDOW_BORDER_VERT 3 // vertical borders only
#define WINDOW_BORDER_KCGRADIENT 4 // horizontal border using the gradient bars
#define WINDOW_STYLE_EMPTY 0 // no background
#define WINDOW_STYLE_FILLED 1 // filled with background color
#define WINDOW_STYLE_GRADIENT 2 // gradient bar based on background color
#define WINDOW_STYLE_SHADER 3 // gradient bar based on background color
#define WINDOW_STYLE_TEAMCOLOR 4 // team color
#define WINDOW_STYLE_CINEMATIC 5 // cinematic
#define MENU_TRUE 1 // uh.. true
#define MENU_FALSE 0 // and false
#define HUD_VERTICAL 0x00
#define HUD_HORIZONTAL 0x01
#define RANGETYPE_ABSOLUTE 0
#define RANGETYPE_RELATIVE 1
// list box element types
#define LISTBOX_TEXT 0x00
#define LISTBOX_IMAGE 0x01
// list feeders
#define FEEDER_HEADS 0x00 // model heads
#define FEEDER_MAPS 0x01 // text maps based on game type
#define FEEDER_SERVERS 0x02 // servers
#define FEEDER_CLANS 0x03 // clan names
#define FEEDER_ALLMAPS 0x04 // all maps available, in graphic format
#define FEEDER_REDTEAM_LIST 0x05 // red team members
#define FEEDER_BLUETEAM_LIST 0x06 // blue team members
#define FEEDER_PLAYER_LIST 0x07 // players
#define FEEDER_TEAM_LIST 0x08 // team members for team voting
#define FEEDER_MODS 0x09 // team members for team voting
#define FEEDER_DEMOS 0x0a // team members for team voting
#define FEEDER_SCOREBOARD 0x0b // team members for team voting
#define FEEDER_Q3HEADS 0x0c // model heads
#define FEEDER_SERVERSTATUS 0x0d // server status
#define FEEDER_FINDPLAYER 0x0e // find player
#define FEEDER_CINEMATICS 0x0f // cinematics
#define FEEDER_SAVEGAMES 0x10 // savegames
#define FEEDER_PICKSPAWN 0x11 // NERVE - SMF - wolf mp pick spawn point
// display flags
#define CG_SHOW_BLUE_TEAM_HAS_REDFLAG 0x00000001
#define CG_SHOW_RED_TEAM_HAS_BLUEFLAG 0x00000002
#define CG_SHOW_ANYTEAMGAME 0x00000004
#define CG_SHOW_HARVESTER 0x00000008
#define CG_SHOW_ONEFLAG 0x00000010
#define CG_SHOW_CTF 0x00000020
#define CG_SHOW_OBELISK 0x00000040
#define CG_SHOW_HEALTHCRITICAL 0x00000080
#define CG_SHOW_SINGLEPLAYER 0x00000100
#define CG_SHOW_TOURNAMENT 0x00000200
#define CG_SHOW_DURINGINCOMINGVOICE 0x00000400
#define CG_SHOW_IF_PLAYER_HAS_FLAG 0x00000800
#define CG_SHOW_LANPLAYONLY 0x00001000
#define CG_SHOW_MINED 0x00002000
#define CG_SHOW_HEALTHOK 0x00004000
#define CG_SHOW_TEAMINFO 0x00008000
#define CG_SHOW_NOTEAMINFO 0x00010000
#define CG_SHOW_OTHERTEAMHASFLAG 0x00020000
#define CG_SHOW_YOURTEAMHASENEMYFLAG 0x00040000
#define CG_SHOW_ANYNONTEAMGAME 0x00080000
//(SA)
#define CG_SHOW_TEXTASINT 0x00200000
#define CG_SHOW_HIGHLIGHTED 0x00100000
#define CG_SHOW_NOT_V_BINOC 0x00200000 //----(SA) added // hide on binoc huds
#define CG_SHOW_NOT_V_SNIPER 0x00400000 //----(SA) added // hide on sniper huds
#define CG_SHOW_NOT_V_SNOOPER 0x00800000 //----(SA) added // hide on snooper huds
#define CG_SHOW_NOT_V_FGSCOPE 0x01000000 //----(SA) added // hide on fg42 scope huds
#define CG_SHOW_NOT_V_CLEAR 0x02000000 //----(SA) added // hide on normal, full-view huds
#define CG_SHOW_2DONLY 0x10000000
#define UI_SHOW_LEADER 0x00000001
#define UI_SHOW_NOTLEADER 0x00000002
#define UI_SHOW_FAVORITESERVERS 0x00000004
#define UI_SHOW_ANYNONTEAMGAME 0x00000008
#define UI_SHOW_ANYTEAMGAME 0x00000010
#define UI_SHOW_NEWHIGHSCORE 0x00000020
#define UI_SHOW_DEMOAVAILABLE 0x00000040
#define UI_SHOW_NEWBESTTIME 0x00000080
#define UI_SHOW_FFA 0x00000100
#define UI_SHOW_NOTFFA 0x00000200
#define UI_SHOW_NETANYNONTEAMGAME 0x00000400
#define UI_SHOW_NETANYTEAMGAME 0x00000800
#define UI_SHOW_NOTFAVORITESERVERS 0x00001000
// font types
#define UI_FONT_DEFAULT 0 // auto-chose betwen big/reg/small
#define UI_FONT_NORMAL 1
#define UI_FONT_BIG 2
#define UI_FONT_SMALL 3
#define UI_FONT_HANDWRITING 4
// owner draw types
// ideally these should be done outside of this file but
// this makes it much easier for the macro expansion to
// convert them for the designers ( from the .menu files )
#define CG_OWNERDRAW_BASE 1
#define CG_PLAYER_ARMOR_ICON 1
#define CG_PLAYER_ARMOR_VALUE 2
#define CG_PLAYER_HEAD 3
#define CG_PLAYER_HEALTH 4
#define CG_PLAYER_AMMO_ICON 5
#define CG_PLAYER_AMMO_VALUE 6
#define CG_SELECTEDPLAYER_HEAD 7
#define CG_SELECTEDPLAYER_NAME 8
#define CG_SELECTEDPLAYER_LOCATION 9
#define CG_SELECTEDPLAYER_STATUS 10
#define CG_SELECTEDPLAYER_WEAPON 11
#define CG_SELECTEDPLAYER_POWERUP 12
#define CG_FLAGCARRIER_HEAD 13
#define CG_FLAGCARRIER_NAME 14
#define CG_FLAGCARRIER_LOCATION 15
#define CG_FLAGCARRIER_STATUS 16
#define CG_FLAGCARRIER_WEAPON 17
#define CG_FLAGCARRIER_POWERUP 18
#define CG_PLAYER_ITEM 19
#define CG_PLAYER_SCORE 20
#define CG_BLUE_FLAGHEAD 21
#define CG_BLUE_FLAGSTATUS 22
#define CG_BLUE_FLAGNAME 23
#define CG_RED_FLAGHEAD 24
#define CG_RED_FLAGSTATUS 25
#define CG_RED_FLAGNAME 26
#define CG_BLUE_SCORE 27
#define CG_RED_SCORE 28
#define CG_RED_NAME 29
#define CG_BLUE_NAME 30
#define CG_HARVESTER_SKULLS 31 // only shows in harvester
#define CG_ONEFLAG_STATUS 32 // only shows in one flag
#define CG_PLAYER_LOCATION 33
#define CG_TEAM_COLOR 34
#define CG_CTF_POWERUP 35
#define CG_AREA_POWERUP 36
#define CG_AREA_LAGOMETER 37 // painted with old system
#define CG_PLAYER_HASFLAG 38
#define CG_GAME_TYPE 39 // not done
#define CG_SELECTEDPLAYER_ARMOR 40
#define CG_SELECTEDPLAYER_HEALTH 41
#define CG_PLAYER_STATUS 42
#define CG_FRAGGED_MSG 43 // painted with old system
#define CG_PROXMINED_MSG 44 // painted with old system
#define CG_AREA_FPSINFO 45 // painted with old system
#define CG_AREA_SYSTEMCHAT 46 // painted with old system
#define CG_AREA_TEAMCHAT 47 // painted with old system
#define CG_AREA_CHAT 48 // painted with old system
#define CG_GAME_STATUS 49
#define CG_KILLER 50
#define CG_PLAYER_ARMOR_ICON2D 51
#define CG_PLAYER_AMMO_ICON2D 52
#define CG_ACCURACY 53
#define CG_ASSISTS 54
#define CG_DEFEND 55
#define CG_EXCELLENT 56
#define CG_IMPRESSIVE 57
#define CG_PERFECT 58
#define CG_GAUNTLET 59
#define CG_SPECTATORS 60
#define CG_TEAMINFO 61
#define CG_VOICE_HEAD 62
#define CG_VOICE_NAME 63
#define CG_PLAYER_HASFLAG2D 64
#define CG_HARVESTER_SKULLS2D 65 // only shows in harvester
#define CG_CAPFRAGLIMIT 66
#define CG_1STPLACE 67
#define CG_2NDPLACE 68
#define CG_CAPTURES 69
// (SA) adding
#define CG_PLAYER_AMMOCLIP_VALUE 70
#define CG_PLAYER_WEAPON_ICON2D 71
#define CG_CURSORHINT 72
#define CG_STAMINA 73
#define CG_PLAYER_WEAPON_HEAT 74
#define CG_PLAYER_POWERUP 75
#define CG_PLAYER_HOLDABLE 76
#define CG_PLAYER_INVENTORY 77
#define CG_AREA_WEAPON 78 // draw weapons here
#define CG_AREA_HOLDABLE 79
#define CG_CURSORHINT_STATUS 80 // like 'health' bar when pointing at a func_explosive
#define CG_PLAYER_WEAPON_STABILITY 81 // shows aimSpreadScale value
#define CG_NEWMESSAGE 82 // 'you got mail!' //----(SA) added
#define UI_OWNERDRAW_BASE 200
#define UI_HANDICAP 200
#define UI_EFFECTS 201
#define UI_PLAYERMODEL 202
#define UI_CLANNAME 203
#define UI_CLANLOGO 204
#define UI_GAMETYPE 205
#define UI_MAPPREVIEW 206
#define UI_SKILL 207
#define UI_BLUETEAMNAME 208
#define UI_REDTEAMNAME 209
#define UI_BLUETEAM1 210
#define UI_BLUETEAM2 211
#define UI_BLUETEAM3 212
#define UI_BLUETEAM4 213
#define UI_BLUETEAM5 214
#define UI_REDTEAM1 215
#define UI_REDTEAM2 216
#define UI_REDTEAM3 217
#define UI_REDTEAM4 218
#define UI_REDTEAM5 219
#define UI_NETSOURCE 220
#define UI_NETMAPPREVIEW 221
#define UI_NETFILTER 222
#define UI_TIER 223
#define UI_OPPONENTMODEL 224
#define UI_TIERMAP1 225
#define UI_TIERMAP2 226
#define UI_TIERMAP3 227
#define UI_PLAYERLOGO 228
#define UI_OPPONENTLOGO 229
#define UI_PLAYERLOGO_METAL 230
#define UI_OPPONENTLOGO_METAL 231
#define UI_PLAYERLOGO_NAME 232
#define UI_OPPONENTLOGO_NAME 233
#define UI_TIER_MAPNAME 234
#define UI_TIER_GAMETYPE 235
#define UI_ALLMAPS_SELECTION 236
#define UI_OPPONENT_NAME 237
#define UI_VOTE_KICK 238
#define UI_BOTNAME 239
#define UI_BOTSKILL 240
#define UI_REDBLUE 241
#define UI_CROSSHAIR 242
#define UI_SELECTEDPLAYER 243
#define UI_MAPCINEMATIC 244
#define UI_NETGAMETYPE 245
#define UI_NETMAPCINEMATIC 246
#define UI_SERVERREFRESHDATE 247
#define UI_SERVERMOTD 248
#define UI_GLINFO 249
#define UI_KEYBINDSTATUS 250
#define UI_CLANCINEMATIC 251
#define UI_MAP_TIMETOBEAT 252
#define UI_JOINGAMETYPE 253
#define UI_PREVIEWCINEMATIC 254
#define UI_STARTMAPCINEMATIC 255
#define UI_MAPS_SELECTION 256
#define UI_MENUMODEL 257
#define UI_SAVEGAME_SHOT 258
// NERVE - SMF
#define UI_LIMBOCHAT 259
// -NERVE - SMF
#define UI_LEVELSHOT 260
#define UI_LOADSTATUSBAR 261
#define UI_SAVEGAMENAME 262
#define UI_SAVEGAMEINFO 263
#define VOICECHAT_GETFLAG "getflag" // command someone to get the flag
#define VOICECHAT_OFFENSE "offense" // command someone to go on offense
#define VOICECHAT_DEFEND "defend" // command someone to go on defense
#define VOICECHAT_DEFENDFLAG "defendflag" // command someone to defend the flag
#define VOICECHAT_PATROL "patrol" // command someone to go on patrol (roam)
#define VOICECHAT_CAMP "camp" // command someone to camp (we don't have sounds for this one)
#define VOICECHAT_FOLLOWME "followme" // command someone to follow you
#define VOICECHAT_RETURNFLAG "returnflag" // command someone to return our flag
#define VOICECHAT_FOLLOWFLAGCARRIER "followflagcarrier" // command someone to follow the flag carrier
#define VOICECHAT_YES "yes" // yes, affirmative, etc.
#define VOICECHAT_NO "no" // no, negative, etc.
#define VOICECHAT_ONGETFLAG "ongetflag" // I'm getting the flag
#define VOICECHAT_ONOFFENSE "onoffense" // I'm on offense
#define VOICECHAT_ONDEFENSE "ondefense" // I'm on defense
#define VOICECHAT_ONPATROL "onpatrol" // I'm on patrol (roaming)
#define VOICECHAT_ONCAMPING "oncamp" // I'm camping somewhere
#define VOICECHAT_ONFOLLOW "onfollow" // I'm following
#define VOICECHAT_ONFOLLOWCARRIER "onfollowcarrier" // I'm following the flag carrier
#define VOICECHAT_ONRETURNFLAG "onreturnflag" // I'm returning our flag
#define VOICECHAT_INPOSITION "inposition" // I'm in position
#define VOICECHAT_IHAVEFLAG "ihaveflag" // I have the flag
#define VOICECHAT_BASEATTACK "baseattack" // the base is under attack
#define VOICECHAT_ENEMYHASFLAG "enemyhasflag" // the enemy has our flag (CTF)
#define VOICECHAT_STARTLEADER "startleader" // I'm the leader
#define VOICECHAT_STOPLEADER "stopleader" // I resign leadership
#define VOICECHAT_WHOISLEADER "whoisleader" // who is the team leader
#define VOICECHAT_WANTONDEFENSE "wantondefense" // I want to be on defense
#define VOICECHAT_WANTONOFFENSE "wantonoffense" // I want to be on offense
#define VOICECHAT_KILLINSULT "kill_insult" // I just killed you
#define VOICECHAT_TAUNT "taunt" // I want to taunt you
#define VOICECHAT_DEATHINSULT "death_insult" // you just killed me
#define VOICECHAT_KILLGAUNTLET "kill_gauntlet" // I just killed you with the gauntlet
#define VOICECHAT_PRAISE "praise" // you did something good
// NERVE - SMF - wolf multiplayer class/item selection mechanism
#define WM_START_SELECT 0
#define WM_SELECT_TEAM 1
#define WM_SELECT_CLASS 2
#define WM_SELECT_WEAPON 3
#define WM_SELECT_PISTOL 4
#define WM_SELECT_GRENADE 5
#define WM_SELECT_ITEM1 6
#define WM_AXIS 1
#define WM_ALLIES 2
#define WM_SPECTATOR 3
#define WM_SOLDIER 1
#define WM_MEDIC 2
#define WM_LIEUTENANT 3
#define WM_ENGINEER 4
#define WM_PISTOL_1911 1
#define WM_PISTOL_LUGER 2
#define WM_WEAPON_MP40 3
#define WM_WEAPON_THOMPSON 4
#define WM_WEAPON_STEN 5
#define WM_WEAPON_MAUSER 6
#define WM_WEAPON_GARAND 7
#define WM_WEAPON_PANZERFAUST 8
#define WM_WEAPON_VENOM 9
#define WM_WEAPON_FLAMETHROWER 10
#define WM_PINEAPPLE_GRENADE 11
#define WM_STICK_GRENADE 12
// -NERVE - SMF

3
src/Makefile Normal file
View File

@ -0,0 +1,3 @@
# nasty ugly to get build system working from Anjuta
all:
cd unix && (if [ `hostname` == antares ] ; then (./pcons-2.3.1 -j4) ; else ./cons ; fi)

1313
src/botai/ai_chat.c Normal file

File diff suppressed because it is too large Load Diff

66
src/botai/ai_chat.h Normal file
View File

@ -0,0 +1,66 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_chat.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
//
int BotChat_EnterGame( bot_state_t *bs );
//
int BotChat_ExitGame( bot_state_t *bs );
//
int BotChat_StartLevel( bot_state_t *bs );
//
int BotChat_EndLevel( bot_state_t *bs );
//
int BotChat_HitTalking( bot_state_t *bs );
//
int BotChat_HitNoDeath( bot_state_t *bs );
//
int BotChat_HitNoKill( bot_state_t *bs );
//
int BotChat_Death( bot_state_t *bs );
//
int BotChat_Kill( bot_state_t *bs );
//
int BotChat_EnemySuicide( bot_state_t *bs );
//
int BotChat_Random( bot_state_t *bs );
// time the selected chat takes to type in
float BotChatTime( bot_state_t *bs );
// returns true if the bot can chat at the current position
int BotValidChatPosition( bot_state_t *bs );
// test the initial bot chats
void BotChatTest( bot_state_t *bs );

1645
src/botai/ai_cmd.c Normal file

File diff suppressed because it is too large Load Diff

40
src/botai/ai_cmd.h Normal file
View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_cmd.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
int BotMatchMessage( bot_state_t *bs, char *message );
void BotPrintTeamGoal( bot_state_t *bs );

2045
src/botai/ai_dmnet.c Normal file

File diff suppressed because it is too large Load Diff

66
src/botai/ai_dmnet.h Normal file
View File

@ -0,0 +1,66 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_dmnet.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
#define MAX_NODESWITCHES 50
void AIEnter_Intermission( bot_state_t *bs );
void AIEnter_Observer( bot_state_t *bs );
void AIEnter_Respawn( bot_state_t *bs );
void AIEnter_Stand( bot_state_t *bs );
void AIEnter_Seek_ActivateEntity( bot_state_t *bs );
void AIEnter_Seek_NBG( bot_state_t *bs );
void AIEnter_Seek_LTG( bot_state_t *bs );
void AIEnter_Seek_Camp( bot_state_t *bs );
void AIEnter_Battle_Fight( bot_state_t *bs );
void AIEnter_Battle_Chase( bot_state_t *bs );
void AIEnter_Battle_Retreat( bot_state_t *bs );
void AIEnter_Battle_NBG( bot_state_t *bs );
int AINode_Intermission( bot_state_t *bs );
int AINode_Observer( bot_state_t *bs );
int AINode_Respawn( bot_state_t *bs );
int AINode_Stand( bot_state_t *bs );
int AINode_Seek_ActivateEntity( bot_state_t *bs );
int AINode_Seek_NBG( bot_state_t *bs );
int AINode_Seek_LTG( bot_state_t *bs );
int AINode_Battle_Fight( bot_state_t *bs );
int AINode_Battle_Chase( bot_state_t *bs );
int AINode_Battle_Retreat( bot_state_t *bs );
int AINode_Battle_NBG( bot_state_t *bs );
void BotResetNodeSwitches( void );
void BotDumpNodeSwitches( bot_state_t *bs );

2899
src/botai/ai_dmq3.c Normal file

File diff suppressed because it is too large Load Diff

156
src/botai/ai_dmq3.h Normal file
View File

@ -0,0 +1,156 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_dmq3.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
//setup the deathmatch AI
void BotSetupDeathmatchAI( void );
//shutdown the deathmatch AI
void BotShutdownDeathmatchAI( void );
//let the bot live within it's deathmatch AI net
void BotDeathmatchAI( bot_state_t *bs, float thinktime );
//free waypoints
void BotFreeWaypoints( bot_waypoint_t *wp );
//choose a weapon
void BotChooseWeapon( bot_state_t *bs );
//setup movement stuff
void BotSetupForMovement( bot_state_t *bs );
//update the inventory
void BotUpdateInventory( bot_state_t *bs );
//update the inventory during battle
void BotUpdateBattleInventory( bot_state_t *bs, int enemy );
//use holdable items during battle
void BotBattleUseItems( bot_state_t *bs );
//return true if the bot is dead
qboolean BotIsDead( bot_state_t *bs );
//returns true if the bot is in observer mode
qboolean BotIsObserver( bot_state_t *bs );
//returns true if the bot is in the intermission
qboolean BotIntermission( bot_state_t *bs );
//returns true if the bot is in lava
qboolean BotInLava( bot_state_t *bs );
//returns true if the bot is in slime
qboolean BotInSlime( bot_state_t *bs );
//returns true if the entity is dead
qboolean EntityIsDead( aas_entityinfo_t *entinfo );
//returns true if the entity is invisible
qboolean EntityIsInvisible( aas_entityinfo_t *entinfo );
//returns true if the entity is shooting
qboolean EntityIsShooting( aas_entityinfo_t *entinfo );
//returns the name of the client
char *ClientName( int client, char *name, int size );
//returns an simplyfied client name
char *EasyClientName( int client, char *name, int size );
//returns the skin used by the client
char *ClientSkin( int client, char *skin, int size );
//returns the aggression of the bot in the range [0, 100]
float BotAggression( bot_state_t *bs );
//returns true if the bot wants to retreat
int BotWantsToRetreat( bot_state_t *bs );
//returns true if the bot wants to chase
int BotWantsToChase( bot_state_t *bs );
//returns true if the bot wants to help
int BotWantsToHelp( bot_state_t *bs );
//returns true if the bot can and wants to rocketjump
int BotCanAndWantsToRocketJump( bot_state_t *bs );
//returns true if the bot wants to and goes camping
int BotWantsToCamp( bot_state_t *bs );
//the bot will perform attack movements
bot_moveresult_t BotAttackMove( bot_state_t *bs, int tfl );
//returns true if the bot and the entity are in the same team
int BotSameTeam( bot_state_t *bs, int entnum );
//returns true if teamplay is on
int TeamPlayIsOn( void );
//returns true and sets the .enemy field when an enemy is found
int BotFindEnemy( bot_state_t *bs, int curenemy );
//returns a roam goal
void BotRoamGoal( bot_state_t *bs, vec3_t goal );
//returns entity visibility in the range [0, 1]
float BotEntityVisible( int viewer, vec3_t eye, vec3_t viewangles, float fov, int ent );
//the bot will aim at the current enemy
void BotAimAtEnemy( bot_state_t *bs );
//check if the bot should attack
void BotCheckAttack( bot_state_t *bs );
//AI when the bot is blocked
void BotAIBlocked( bot_state_t *bs, bot_moveresult_t *moveresult, int activate );
//returns the CTF team the bot is in
int BotCTFTeam( bot_state_t *bs );
//returns the flag the bot is carrying (CTFFLAG_?)
int BotCTFCarryingFlag( bot_state_t *bs );
//set ctf goals (defend base, get enemy flag) during seek
void BotCTFSeekGoals( bot_state_t *bs );
//set ctf goals (defend base, get enemy flag) during retreat
void BotCTFRetreatGoals( bot_state_t *bs );
//create a new waypoint
bot_waypoint_t *BotCreateWayPoint( char *name, vec3_t origin, int areanum );
//find a waypoint with the given name
bot_waypoint_t *BotFindWayPoint( bot_waypoint_t *waypoints, char *name );
//strstr but case insensitive
char *stristr( char *str, char *charset );
//returns the number of the client with the given name
int ClientFromName( char *name );
//
int BotPointAreaNum( vec3_t origin );
//
void BotMapScripts( bot_state_t *bs );
//ctf flags
#define CTF_FLAG_NONE 0
#define CTF_FLAG_RED 1
#define CTF_FLAG_BLUE 2
//CTF skins
#define CTF_SKIN_REDTEAM "red"
#define CTF_SKIN_BLUETEAM "blue"
//CTF teams
#define CTF_TEAM_NONE 0
#define CTF_TEAM_RED 1
#define CTF_TEAM_BLUE 2
extern int dmflags; //deathmatch flags
extern int gametype; //game type
// Rafael gameskill
extern int gameskill;
// done
extern vmCvar_t bot_grapple;
extern vmCvar_t bot_rocketjump;
extern vmCvar_t bot_fastchat;
extern vmCvar_t bot_nochat;
extern vmCvar_t bot_testrchat;
extern bot_goal_t ctf_redflag;
extern bot_goal_t ctf_blueflag;

1208
src/botai/ai_main.c Normal file

File diff suppressed because it is too large Load Diff

242
src/botai/ai_main.h Normal file
View File

@ -0,0 +1,242 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_main.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
//#define DEBUG
#define CTF
#define MAX_ITEMS 256
//bot flags
#define BFL_STRAFERIGHT 1 //strafe to the right
#define BFL_ATTACKED 2 //bot has attacked last ai frame
#define BFL_ATTACKJUMPED 4 //bot jumped during attack last frame
#define BFL_AIMATENEMY 8 //bot aimed at the enemy this frame
#define BFL_AVOIDRIGHT 16 //avoid obstacles by going to the right
#define BFL_IDEALVIEWSET 32 //bot has ideal view angles set
//long term goal types
#define LTG_TEAMHELP 1 //help a team mate
#define LTG_TEAMACCOMPANY 2 //accompany a team mate
#define LTG_DEFENDKEYAREA 3 //defend a key area
#define LTG_GETFLAG 4 //get the enemy flag
#define LTG_RUSHBASE 5 //rush to the base
#define LTG_RETURNFLAG 6 //return the flag
#define LTG_CAMP 7 //camp somewhere
#define LTG_CAMPORDER 8 //ordered to camp somewhere
#define LTG_PATROL 9 //patrol
#define LTG_GETITEM 10 //get an item
#define LTG_KILL 11 //kill someone
//some goal dedication times
#define TEAM_HELP_TIME 60 //1 minute teamplay help time
#define TEAM_ACCOMPANY_TIME 600 //10 minutes teamplay accompany time
#define TEAM_DEFENDKEYAREA_TIME 240 //4 minutes ctf defend base time
#define TEAM_CAMP_TIME 600 //10 minutes camping time
#define TEAM_PATROL_TIME 600 //10 minutes patrolling time
#define TEAM_LEAD_TIME 600 //10 minutes taking the lead
#define TEAM_GETITEM_TIME 60 //1 minute
#define TEAM_KILL_SOMEONE 180 //3 minute to kill someone
#define CTF_GETFLAG_TIME 240 //4 minutes ctf get flag time
#define CTF_RUSHBASE_TIME 120 //2 minutes ctf rush base time
#define CTF_RETURNFLAG_TIME 180 //3 minutes to return the flag
#define CTF_ROAM_TIME 60 //1 minute ctf roam time
//patrol flags
#define PATROL_LOOP 1
#define PATROL_REVERSE 2
#define PATROL_BACK 4
//copied from the aas file header
#define PRESENCE_NONE 1
#define PRESENCE_NORMAL 2
#define PRESENCE_CROUCH 4
//check points
typedef struct bot_waypoint_s
{
int inuse;
char name[32];
bot_goal_t goal;
struct bot_waypoint_s *next, *prev;
} bot_waypoint_t;
//bot state
typedef struct bot_state_s
{
int inuse; //true if this state is used by a bot client
int botthink_residual; //residual for the bot thinks
int client; //client number of the bot
int entitynum; //entity number of the bot
playerState_t cur_ps; //current player state
int last_eFlags; //last ps flags
usercmd_t lastucmd; //usercmd from last frame
int entityeventTime[1024]; //last entity event time
//
bot_settings_t settings; //several bot settings
int ( *ainode )( struct bot_state_s *bs ); //current AI node
float thinktime; //time the bot thinks this frame
vec3_t origin; //origin of the bot
vec3_t velocity; //velocity of the bot
int presencetype; //presence type of the bot
vec3_t eye; //eye coordinates of the bot
int areanum; //the number of the area the bot is in
int inventory[MAX_ITEMS]; //string with items amounts the bot has
int tfl; //the travel flags the bot uses
int flags; //several flags
int respawn_wait; //wait until respawned
int lasthealth; //health value previous frame
int lastkilledplayer; //last killed player
int lastkilledby; //player that last killed this bot
int botdeathtype; //the death type of the bot
int enemydeathtype; //the death type of the enemy
int botsuicide; //true when the bot suicides
int enemysuicide; //true when the enemy of the bot suicides
int setupcount; //true when the bot has just been setup
int entergamechat; //true when the bot used an enter game chat
int num_deaths; //number of time this bot died
int num_kills; //number of kills of this bot
int revenge_enemy; //the revenge enemy
int revenge_kills; //number of kills the enemy made
int lastframe_health; //health value the last frame
int lasthitcount; //number of hits last frame
int chatto; //chat to all or team
float walker; //walker charactertic
float ltime; //local bot time
float entergame_time; //time the bot entered the game
float ltg_time; //long term goal time
float nbg_time; //nearby goal time
float respawn_time; //time the bot takes to respawn
float respawnchat_time; //time the bot started a chat during respawn
float chase_time; //time the bot will chase the enemy
float enemyvisible_time; //time the enemy was last visible
float check_time; //time to check for nearby items
float stand_time; //time the bot is standing still
float lastchat_time; //time the bot last selected a chat
float standfindenemy_time; //time to find enemy while standing
float attackstrafe_time; //time the bot is strafing in one dir
float attackcrouch_time; //time the bot will stop crouching
float attackchase_time; //time the bot chases during actual attack
float attackjump_time; //time the bot jumped during attack
float enemysight_time; //time before reacting to enemy
float enemydeath_time; //time the enemy died
float enemyposition_time; //time the position and velocity of the enemy were stored
float activate_time; //time to activate something
float activatemessage_time; //time to show activate message
float defendaway_time; //time away while defending
float defendaway_range; //max travel time away from defend area
float rushbaseaway_time; //time away from rushing to the base
float ctfroam_time; //time the bot is roaming in ctf
float killedenemy_time; //time the bot killed the enemy
float arrive_time; //time arrived (at companion)
float lastair_time; //last time the bot had air
float teleport_time; //last time the bot teleported
float camp_time; //last time camped
float camp_range; //camp range
float weaponchange_time; //time the bot started changing weapons
float firethrottlewait_time; //amount of time to wait
float firethrottleshoot_time; //amount of time to shoot
vec3_t aimtarget;
vec3_t enemyvelocity; //enemy velocity 0.5 secs ago during battle
vec3_t enemyorigin; //enemy origin 0.5 secs ago during battle
//
int character; //the bot character
int ms; //move state of the bot
int gs; //goal state of the bot
int cs; //chat state of the bot
int ws; //weapon state of the bot
//
int enemy; //enemy entity number
int lastenemyareanum; //last reachability area the enemy was in
vec3_t lastenemyorigin; //last origin of the enemy in the reachability area
int weaponnum; //current weapon number
vec3_t viewangles; //current view angles
vec3_t ideal_viewangles; //ideal view angles
//
int ltgtype; //long term goal type
//
int teammate; //team mate
bot_goal_t teamgoal; //the team goal
float teammessage_time; //time to message team mates what the bot is doing
float teamgoal_time; //time to stop helping team mate
float teammatevisible_time; //last time the team mate was NOT visible
//
int lead_teammate; //team mate the bot is leading
bot_goal_t lead_teamgoal; //team goal while leading
float lead_time; //time leading someone
float leadvisible_time; //last time the team mate was visible
float leadmessage_time; //last time a messaged was sent to the team mate
float leadbackup_time; //time backing up towards team mate
//
char teamleader[32]; //netname of the team leader
float askteamleader_time; //time asked for team leader
float becometeamleader_time; //time the bot will become the team leader
float teamgiveorders_time; //time to give team orders
int numteammates; //number of team mates
int redflagstatus; //0 = at base, 1 = not at base
int blueflagstatus; //0 = at base, 1 = not at base
int flagstatuschanged; //flag status changed
int forceorders; //true if forced to give orders
int flagcarrier; //team mate carrying the enemy flag
char subteam[32]; //sub team name
float formation_dist; //formation team mate intervening space
char formation_teammate[16]; //netname of the team mate the bot uses for relative positioning
float formation_angle; //angle relative to the formation team mate
vec3_t formation_dir; //the direction the formation is moving in
vec3_t formation_origin; //origin the bot uses for relative positioning
bot_goal_t formation_goal; //formation goal
bot_goal_t activategoal; //goal to activate (buttons etc.)
bot_waypoint_t *checkpoints; //check points
bot_waypoint_t *patrolpoints; //patrol points
bot_waypoint_t *curpatrolpoint; //current patrol point the bot is going for
int patrolflags; //patrol flags
} bot_state_t;
//resets the whole bot state
void BotResetState( bot_state_t *bs );
//returns the number of bots in the game
int NumBots( void );
//returns info about the entity
void BotEntityInfo( int entnum, aas_entityinfo_t *info );
// Ridah, defines for AI Cast system
int AICast_ShutdownClient( int client );
void AICast_Init( void );
void AICast_StartFrame( int time );
// done.
// from the game source
void QDECL BotAI_Print( int type, char *fmt, ... );
void QDECL QDECL BotAI_BotInitialChat( bot_state_t *bs, char *type, ... );
void BotAI_Trace( bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask );
int BotAI_GetClientState( int clientNum, playerState_t *state );
int BotAI_GetEntityState( int entityNum, entityState_t *state );
int BotAI_GetSnapshotEntity( int clientNum, int sequence, entityState_t *state );

612
src/botai/ai_team.c Normal file
View File

@ -0,0 +1,612 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_team.c
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
#include "../game/g_local.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "../game/be_ea.h"
#include "../game/be_ai_char.h"
#include "../game/be_ai_chat.h"
#include "../game/be_ai_gen.h"
#include "../game/be_ai_goal.h"
#include "../game/be_ai_move.h"
#include "../game/be_ai_weap.h"
#include "../botai/botai.h"
//
#include "ai_main.h"
#include "ai_dmq3.h"
#include "ai_chat.h"
#include "ai_cmd.h"
#include "ai_dmnet.h"
/*
==================
BotValidTeamLeader
==================
*/
int BotValidTeamLeader( bot_state_t *bs ) {
if ( !strlen( bs->teamleader ) ) {
return qfalse;
}
if ( ClientFromName( bs->teamleader ) == -1 ) {
return qfalse;
}
return qtrue;
}
/*
==================
BotNumTeamMates
==================
*/
int BotNumTeamMates( bot_state_t *bs ) {
int i, numplayers;
char buf[MAX_INFO_STRING];
static int maxclients;
if ( !maxclients ) {
maxclients = trap_Cvar_VariableIntegerValue( "sv_maxclients" );
}
numplayers = 0;
for ( i = 0; i < maxclients && i < MAX_CLIENTS; i++ ) {
trap_GetConfigstring( CS_PLAYERS + i, buf, sizeof( buf ) );
//if no config string or no name
if ( !strlen( buf ) || !strlen( Info_ValueForKey( buf, "n" ) ) ) {
continue;
}
//skip spectators
if ( atoi( Info_ValueForKey( buf, "t" ) ) == TEAM_SPECTATOR ) {
continue;
}
//
if ( BotSameTeam( bs, i ) ) {
numplayers++;
}
}
return numplayers;
}
/*
==================
BotClientTravelTimeToGoal
==================
*/
int BotClientTravelTimeToGoal( int client, bot_goal_t *goal ) {
playerState_t ps;
int areanum;
BotAI_GetClientState( client, &ps );
areanum = BotPointAreaNum( ps.origin );
if ( !areanum ) {
return 1;
}
return trap_AAS_AreaTravelTimeToGoalArea( areanum, ps.origin, goal->areanum, TFL_DEFAULT );
}
/*
==================
BotSortTeamMatesByBaseTravelTime
==================
*/
int BotSortTeamMatesByBaseTravelTime( bot_state_t *bs, int *teammates, int maxteammates ) {
int i, j, k, numteammates, traveltime;
char buf[MAX_INFO_STRING];
static int maxclients;
int traveltimes[MAX_CLIENTS];
bot_goal_t *goal;
if ( BotCTFTeam( bs ) == CTF_TEAM_RED ) {
goal = &ctf_redflag;
} else { goal = &ctf_blueflag;}
if ( !maxclients ) {
maxclients = trap_Cvar_VariableIntegerValue( "sv_maxclients" );
}
numteammates = 0;
for ( i = 0; i < maxclients && i < MAX_CLIENTS; i++ ) {
trap_GetConfigstring( CS_PLAYERS + i, buf, sizeof( buf ) );
//if no config string or no name
if ( !strlen( buf ) || !strlen( Info_ValueForKey( buf, "n" ) ) ) {
continue;
}
//skip spectators
if ( atoi( Info_ValueForKey( buf, "t" ) ) == TEAM_SPECTATOR ) {
continue;
}
//
if ( BotSameTeam( bs, i ) ) {
//
traveltime = BotClientTravelTimeToGoal( i, goal );
//
for ( j = 0; j < numteammates; j++ ) {
if ( traveltime < traveltimes[j] ) {
for ( k = numteammates; k > j; k-- ) {
traveltimes[k] = traveltimes[k - 1];
teammates[k] = teammates[k - 1];
}
traveltimes[j] = traveltime;
teammates[j] = i;
break;
}
}
if ( j >= numteammates ) {
traveltimes[j] = traveltime;
teammates[j] = i;
}
numteammates++;
if ( numteammates >= maxteammates ) {
break;
}
}
}
return numteammates;
}
/*
==================
BotSayTeamOrders
==================
*/
void BotSayTeamOrder( bot_state_t *bs, int toclient ) {
char teamchat[MAX_MESSAGE_SIZE];
char buf[MAX_MESSAGE_SIZE];
char name[MAX_NETNAME];
//if the bot is talking to itself
if ( bs->client == toclient ) {
//don't show the message just put it in the console message queue
trap_BotGetChatMessage( bs->cs, buf, sizeof( buf ) );
ClientName( bs->client, name, sizeof( name ) );
Com_sprintf( teamchat, sizeof( teamchat ), "(%s): %s", name, buf );
trap_BotQueueConsoleMessage( bs->cs, CMS_CHAT, teamchat );
} else {
trap_BotEnterChat( bs->cs, bs->client, CHAT_TEAM );
}
}
/*
==================
BotCTFOrders
==================
*/
void BotCTFOrders_BothFlagsNotAtBase( bot_state_t *bs ) {
int numteammates, defenders, attackers, i, other;
int teammates[MAX_CLIENTS];
char name[MAX_NETNAME], carriername[MAX_NETNAME];
numteammates = BotSortTeamMatesByBaseTravelTime( bs, teammates, sizeof( teammates ) );
//different orders based on the number of team mates
switch ( bs->numteammates ) {
case 1: break;
case 2:
{
//tell the one not carrying the flag to attack the enemy base
if ( teammates[0] != bs->flagcarrier ) {
other = teammates[0];
} else { other = teammates[1];}
ClientName( other, name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, other );
break;
}
case 3:
{
//tell the one closest to the base not carrying the flag to accompany the flag carrier
if ( teammates[0] != bs->flagcarrier ) {
other = teammates[0];
} else { other = teammates[1];}
ClientName( other, name, sizeof( name ) );
ClientName( bs->flagcarrier, carriername, sizeof( carriername ) );
if ( bs->flagcarrier == bs->client ) {
BotAI_BotInitialChat( bs, "cmd_accompanyme", name, NULL );
} else {
BotAI_BotInitialChat( bs, "cmd_accompany", name, carriername, NULL );
}
BotSayTeamOrder( bs, other );
//tell the one furthest from the the base not carrying the flag to get the enemy flag
if ( teammates[2] != bs->flagcarrier ) {
other = teammates[2];
} else { other = teammates[1];}
ClientName( other, name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, other );
break;
}
default:
{
defenders = (int) ( float ) numteammates * 0.4 + 0.5;
attackers = (int) ( float ) numteammates * 0.5 + 0.5;
ClientName( bs->flagcarrier, carriername, sizeof( carriername ) );
for ( i = 0; i < defenders; i++ ) {
//
if ( teammates[i] == bs->flagcarrier ) {
continue;
}
//
ClientName( teammates[i], name, sizeof( name ) );
if ( bs->flagcarrier == bs->client ) {
BotAI_BotInitialChat( bs, "cmd_accompanyme", name, NULL );
} else {
BotAI_BotInitialChat( bs, "cmd_accompany", name, carriername, NULL );
}
BotSayTeamOrder( bs, teammates[i] );
}
for ( i = 0; i < attackers; i++ ) {
//
if ( teammates[numteammates - i - 1] == bs->flagcarrier ) {
continue;
}
//
ClientName( teammates[numteammates - i - 1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[numteammates - i - 1] );
}
//
break;
}
}
}
/*
==================
BotCTFOrders
==================
*/
void BotCTFOrders_FlagNotAtBase( bot_state_t *bs ) {
int numteammates, defenders, attackers, i;
int teammates[MAX_CLIENTS];
char name[MAX_NETNAME];
numteammates = BotSortTeamMatesByBaseTravelTime( bs, teammates, sizeof( teammates ) );
//different orders based on the number of team mates
switch ( bs->numteammates ) {
case 1: break;
case 2:
{
//the one closest to the base will defend the base
ClientName( teammates[0], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[0] );
//the other will get the flag
ClientName( teammates[1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[1] );
break;
}
case 3:
{
//the one closest to the base will defend the base
ClientName( teammates[0], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[0] );
//the other two get the flag
ClientName( teammates[1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[1] );
//
ClientName( teammates[2], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[2] );
break;
}
default:
{
defenders = (int) ( float ) numteammates * 0.3 + 0.5;
attackers = (int) ( float ) numteammates * 0.5 + 0.5;
for ( i = 0; i < defenders; i++ ) {
//
ClientName( teammates[i], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[i] );
}
for ( i = 0; i < attackers; i++ ) {
//
ClientName( teammates[numteammates - i - 1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[numteammates - i - 1] );
}
//
break;
}
}
}
/*
==================
BotCTFOrders
==================
*/
void BotCTFOrders_EnemyFlagNotAtBase( bot_state_t *bs ) {
int numteammates, defenders, attackers, i, other;
int teammates[MAX_CLIENTS];
char name[MAX_NETNAME], carriername[MAX_NETNAME];
numteammates = BotSortTeamMatesByBaseTravelTime( bs, teammates, sizeof( teammates ) );
//different orders based on the number of team mates
switch ( numteammates ) {
case 1: break;
case 2:
{
//tell the one not carrying the flag to defend the base
if ( teammates[0] == bs->flagcarrier ) {
other = teammates[1];
} else { other = teammates[0];}
ClientName( other, name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, other );
break;
}
case 3:
{
//tell the one closest to the base not carrying the flag to defend the base
if ( teammates[0] != bs->flagcarrier ) {
other = teammates[0];
} else { other = teammates[1];}
ClientName( other, name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, other );
//tell the one furthest from the base not carrying the flag to accompany the flag carrier
if ( teammates[2] != bs->flagcarrier ) {
other = teammates[2];
} else { other = teammates[1];}
ClientName( other, name, sizeof( name ) );
ClientName( bs->flagcarrier, carriername, sizeof( carriername ) );
if ( bs->flagcarrier == bs->client ) {
BotAI_BotInitialChat( bs, "cmd_accompanyme", name, NULL );
} else {
BotAI_BotInitialChat( bs, "cmd_accompany", name, carriername, NULL );
}
BotSayTeamOrder( bs, other );
break;
}
default:
{
//40% will defend the base
defenders = (int) ( float ) numteammates * 0.4 + 0.5;
//50% accompanies the flag carrier
attackers = (int) ( float ) numteammates * 0.5 + 0.5;
for ( i = 0; i < defenders; i++ ) {
//
if ( teammates[i] == bs->flagcarrier ) {
continue;
}
ClientName( teammates[i], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[i] );
}
ClientName( bs->flagcarrier, carriername, sizeof( carriername ) );
for ( i = 0; i < attackers; i++ ) {
//
if ( teammates[numteammates - i - 1] == bs->flagcarrier ) {
continue;
}
//
ClientName( teammates[numteammates - i - 1], name, sizeof( name ) );
if ( bs->flagcarrier == bs->client ) {
BotAI_BotInitialChat( bs, "cmd_accompanyme", name, NULL );
} else {
BotAI_BotInitialChat( bs, "cmd_accompany", name, carriername, NULL );
}
BotSayTeamOrder( bs, teammates[numteammates - i - 1] );
}
//
break;
}
}
}
/*
==================
BotCTFOrders
==================
*/
void BotCTFOrders_BothFlagsAtBase( bot_state_t *bs ) {
int numteammates, defenders, attackers, i;
int teammates[MAX_CLIENTS];
char name[MAX_NETNAME];
// char buf[MAX_MESSAGE_SIZE];
numteammates = BotSortTeamMatesByBaseTravelTime( bs, teammates, sizeof( teammates ) );
//different orders based on the number of team mates
switch ( numteammates ) {
case 1: break;
case 2:
{
//the one closest to the base will defend the base
ClientName( teammates[0], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[0] );
//the other will get the flag
ClientName( teammates[1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[1] );
break;
}
case 3:
{
//the one closest to the base will defend the base
ClientName( teammates[0], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[0] );
//the second one closest to the base will defend the base
ClientName( teammates[1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[1] );
//the other will get the flag
ClientName( teammates[2], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[2] );
break;
}
default:
{
defenders = (int) ( float ) numteammates * 0.5 + 0.5;
attackers = (int) ( float ) numteammates * 0.3 + 0.5;
for ( i = 0; i < defenders; i++ ) {
//
ClientName( teammates[i], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_defendbase", name, NULL );
BotSayTeamOrder( bs, teammates[i] );
}
for ( i = 0; i < attackers; i++ ) {
//
ClientName( teammates[numteammates - i - 1], name, sizeof( name ) );
BotAI_BotInitialChat( bs, "cmd_getflag", name, NULL );
BotSayTeamOrder( bs, teammates[numteammates - i - 1] );
}
//
break;
}
}
}
/*
==================
BotTeamOrders
==================
*/
void BotTeamOrders( bot_state_t *bs ) {
//no teamplay orders at this time
}
/*
==================
BotTeamAI
==================
*/
void BotTeamAI( bot_state_t *bs ) {
int numteammates, flagstatus;
char netname[MAX_NETNAME];
//
if ( gametype != GT_TEAM && gametype != GT_CTF ) {
return;
}
//make sure we've got a valid team leader
if ( !BotValidTeamLeader( bs ) ) {
//
if ( !bs->askteamleader_time && !bs->becometeamleader_time ) {
if ( bs->entergame_time + 10 > trap_AAS_Time() ) {
bs->askteamleader_time = trap_AAS_Time() + 5 + random() * 10;
} else {
bs->becometeamleader_time = trap_AAS_Time() + 5 + random() * 10;
}
}
if ( bs->askteamleader_time && bs->askteamleader_time < trap_AAS_Time() ) {
//if asked for a team leader and no repsonse
BotAI_BotInitialChat( bs, "whoisteamleader", NULL );
trap_BotEnterChat( bs->cs, bs->client, CHAT_TEAM );
bs->askteamleader_time = 0;
bs->becometeamleader_time = trap_AAS_Time() + 15 + random() * 10;
}
if ( bs->becometeamleader_time && bs->becometeamleader_time < trap_AAS_Time() ) {
BotAI_BotInitialChat( bs, "iamteamleader", NULL );
trap_BotEnterChat( bs->cs, bs->client, CHAT_TEAM );
ClientName( bs->client, netname, sizeof( netname ) );
strncpy( bs->teamleader, netname, sizeof( bs->teamleader ) );
bs->teamleader[sizeof( bs->teamleader )] = '\0';
bs->becometeamleader_time = 0;
}
return;
}
bs->askteamleader_time = 0;
bs->becometeamleader_time = 0;
//return if this bot is NOT the team leader
ClientName( bs->client, netname, sizeof( netname ) );
if ( Q_stricmp( netname, bs->teamleader ) != 0 ) {
return;
}
//
//if the game starts OR a new player comes onto the team OR a player leaves the team
//
numteammates = BotNumTeamMates( bs );
//give orders
switch ( gametype ) {
case GT_TEAM:
{
if ( bs->numteammates != numteammates || bs->forceorders ) {
bs->teamgiveorders_time = trap_AAS_Time();
bs->numteammates = numteammates;
bs->forceorders = qfalse;
}
//if it's time to give orders
if ( bs->teamgiveorders_time < trap_AAS_Time() - 5 ) {
BotTeamOrders( bs );
//
bs->teamgiveorders_time = 0;
}
break;
}
case GT_CTF:
{
//
if ( bs->numteammates != numteammates || bs->flagstatuschanged || bs->forceorders ) {
bs->teamgiveorders_time = trap_AAS_Time();
bs->numteammates = numteammates;
bs->flagstatuschanged = qfalse;
bs->forceorders = qfalse;
}
//if it's time to give orders
if ( bs->teamgiveorders_time && bs->teamgiveorders_time < trap_AAS_Time() - 3 ) {
//
if ( BotCTFTeam( bs ) == CTF_TEAM_RED ) {
flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus;
} else { flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus;}
//
switch ( flagstatus ) {
case 0: BotCTFOrders_BothFlagsAtBase( bs ); break;
case 1: BotCTFOrders_EnemyFlagNotAtBase( bs ); break;
case 2: BotCTFOrders_FlagNotAtBase( bs ); break;
case 3: BotCTFOrders_BothFlagsNotAtBase( bs ); break;
}
//
bs->teamgiveorders_time = 0;
}
break;
}
}
}

40
src/botai/ai_team.h Normal file
View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: ai_team.h
*
* desc: Quake3 bot AI
*
*
*****************************************************************************/
void BotTeamAI( bot_state_t *bs );

110
src/botai/botai.h Normal file
View File

@ -0,0 +1,110 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: botai.h
// Function: bot AI
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-08-18
// Tab Size: 3
//===========================================================================
//debug line colors
#define LINECOLOR_NONE -1
#define LINECOLOR_RED 1
#define LINECOLOR_GREEN 2
#define LINECOLOR_BLUE 3
#define LINECOLOR_YELLOW 4
#define LINECOLOR_ORANGE 5
//Print types
#define PRT_MESSAGE 1
#define PRT_WARNING 2
#define PRT_ERROR 3
#define PRT_FATAL 4
#define PRT_EXIT 5
//console message types
#define CMS_NORMAL 0
#define CMS_CHAT 1
//some maxs
#define MAX_NETNAME 36
#define MAX_CLIENTSKINNAME 128
#define MAX_FILEPATH 144
#define MAX_CHARACTERNAME 144
#ifndef BSPTRACE
//bsp_trace_t hit surface
typedef struct bsp_surface_s
{
char name[16];
int flags;
int value;
} bsp_surface_t;
//remove the bsp_trace_s structure definition l8r on
//a trace is returned when a box is swept through the world
typedef struct bsp_trace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
float exp_dist; // expanded plane distance
int sidenum; // number of the brush side hit
bsp_surface_t surface; // the hit point surface
int contents; // contents on other side of surface hit
int ent; // number of entity hit
} bsp_trace_t;
#define BSPTRACE
#endif // BSPTRACE
//
// imported functions used for the BotAI
//
// from the server
/*
void trap_Cvar_Register( vmCvar_t *cvar, const char *var_name, const char *value, int flags );
void trap_Cvar_Update( vmCvar_t *cvar );
void trap_Cvar_Set( const char *var_name, const char *value );
int trap_Cvar_VariableIntegerValue( const char *var_name );
void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
void trap_GetConfigstring( int num, char *buffer, int bufferSize );
void trap_GetServerinfo( char *buffer, int bufferSize );
int trap_PointContents( const vec3_t point, int passEntityNum );
qboolean trap_InPVS( const vec3_t p1, const vec3_t p2 );
int trap_BotAllocateClient( void );
void trap_BotFreeClient( int clientNum );
*/

150
src/botai/chars.h Normal file
View File

@ -0,0 +1,150 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: chars.h
// Function: bot characteristics
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-09-08
// Tab Size: 4 (real tabs)
//===========================================================================
//========================================================
//========================================================
//name
#define CHARACTERISTIC_NAME 0 //string
//gender of the bot
#define CHARACTERISTIC_GENDER 1 //string ("male", "female", "it")
//attack skill
// > 0.0 && < 0.2 = don't move
// > 0.3 && < 1.0 = aim at enemy during retreat
// > 0.0 && < 0.4 = only move forward/backward
// >= 0.4 && < 1.0 = circle strafing
// > 0.7 && < 1.0 = random strafe direction change
#define CHARACTERISTIC_ATTACK_SKILL 2 //float [0, 1]
//weapon weight file
#define CHARACTERISTIC_WEAPONWEIGHTS 3 //string
//view angle difference to angle change factor
#define CHARACTERISTIC_VIEW_FACTOR 4 //float <0, 1]
//maximum view angle change
#define CHARACTERISTIC_VIEW_MAXCHANGE 5 //float [1, 360]
//reaction time in seconds
#define CHARACTERISTIC_REACTIONTIME 6 //float [0, 5]
//accuracy when aiming
#define CHARACTERISTIC_AIM_ACCURACY 7 //float [0, 1]
//weapon specific aim accuracy
#define CHARACTERISTIC_AIM_ACCURACY_MACHINEGUN 8 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_SHOTGUN 9 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_ROCKETLAUNCHER 10 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_GRENADELAUNCHER 11 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_LIGHTNING 12
#define CHARACTERISTIC_AIM_ACCURACY_SP5 13 //float [0, 1]
#define CHARACTERISTIC_AIM_ACCURACY_RAILGUN 14
#define CHARACTERISTIC_AIM_ACCURACY_BFG10K 15 //float [0, 1]
//skill when aiming
// > 0.0 && < 0.9 = aim is affected by enemy movement
// > 0.4 && <= 0.8 = enemy linear leading
// > 0.8 && <= 1.0 = enemy exact movement leading
// > 0.5 && <= 1.0 = prediction shots when enemy is not visible
// > 0.6 && <= 1.0 = splash damage by shooting nearby geometry
#define CHARACTERISTIC_AIM_SKILL 16 //float [0, 1]
//weapon specific aim skill
#define CHARACTERISTIC_AIM_SKILL_ROCKETLAUNCHER 17 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_GRENADELAUNCHER 18 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_SP5 19 //float [0, 1]
#define CHARACTERISTIC_AIM_SKILL_BFG10K 20 //float [0, 1]
//========================================================
//chat
//========================================================
//file with chats
#define CHARACTERISTIC_CHAT_FILE 21 //string
//name of the chat character
#define CHARACTERISTIC_CHAT_NAME 22 //string
//characters per minute type speed
#define CHARACTERISTIC_CHAT_CPM 23 //integer [1, 4000]
//tendency to insult/praise
#define CHARACTERISTIC_CHAT_INSULT 24 //float [0, 1]
//tendency to chat misc
#define CHARACTERISTIC_CHAT_MISC 25 //float [0, 1]
//tendency to chat at start or end of level
#define CHARACTERISTIC_CHAT_STARTENDLEVEL 26 //float [0, 1]
//tendency to chat entering or exiting the game
#define CHARACTERISTIC_CHAT_ENTEREXITGAME 27 //float [0, 1]
//tendency to chat when killed someone
#define CHARACTERISTIC_CHAT_KILL 28 //float [0, 1]
//tendency to chat when died
#define CHARACTERISTIC_CHAT_DEATH 29 //float [0, 1]
//tendency to chat when enemy suicides
#define CHARACTERISTIC_CHAT_ENEMYSUICIDE 30 //float [0, 1]
//tendency to chat when hit while talking
#define CHARACTERISTIC_CHAT_HITTALKING 31 //float [0, 1]
//tendency to chat when bot was hit but didn't dye
#define CHARACTERISTIC_CHAT_HITNODEATH 32 //float [0, 1]
//tendency to chat when bot hit the enemy but enemy didn't dye
#define CHARACTERISTIC_CHAT_HITNOKILL 33 //float [0, 1]
//tendency to randomly chat
#define CHARACTERISTIC_CHAT_RANDOM 34 //float [0, 1]
//tendency to reply
#define CHARACTERISTIC_CHAT_REPLY 35 //float [0, 1]
//========================================================
//movement
//========================================================
//tendency to crouch
#define CHARACTERISTIC_CROUCHER 36 //float [0, 1]
//tendency to jump
#define CHARACTERISTIC_JUMPER 37 //float [0, 1]
//tendency to walk
#define CHARACTERISTIC_WALKER 48 //float [0, 1]
//tendency to jump using a weapon
#define CHARACTERISTIC_WEAPONJUMPING 38 //float [0, 1]
//tendency to use the grapple hook when available
#define CHARACTERISTIC_GRAPPLE_USER 39 //float [0, 1] //use this!!
//========================================================
//goal
//========================================================
//item weight file
#define CHARACTERISTIC_ITEMWEIGHTS 40 //string
//the aggression of the bot
#define CHARACTERISTIC_AGGRESSION 41 //float [0, 1]
//the self preservation of the bot (rockets near walls etc.)
#define CHARACTERISTIC_SELFPRESERVATION 42 //float [0, 1]
//how likely the bot is to take revenge
#define CHARACTERISTIC_VENGEFULNESS 43 //float [0, 1] //use this!!
//tendency to camp
#define CHARACTERISTIC_CAMPER 44 //float [0, 1]
//========================================================
//========================================================
//tendency to get easy frags
#define CHARACTERISTIC_EASY_FRAGGER 45 //float [0, 1]
//how alert the bot is (view distance)
#define CHARACTERISTIC_ALERTNESS 46 //float [0, 1]
//how much the bot fires it's weapon
#define CHARACTERISTIC_FIRETHROTTLE 47 //float [0, 1]

128
src/botai/inv.h Normal file
View File

@ -0,0 +1,128 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
* name: inv.h
*
* desc:
*
*/
#define INVENTORY_NONE 0
//armor
#define INVENTORY_ARMOR 1
//weapons
#define INVENTORY_LUGER 4
#define INVENTORY_MAUSER 5
#define INVENTORY_MP40 6
#define INVENTORY_SP5 7
#define INVENTORY_ROCKETLAUNCHER 8
#define INVENTORY_GRENADELAUNCHER 9
#define INVENTORY_VENOM 10
#define INVENTORY_FLAMETHROWER 11
#define INVENTORY_CROSS 12
#define INVENTORY_GAUNTLET 13
// please leave these open up to 27 (INVENTORY_9MM) (and double check defines when merging)
// the inventory max (MAX_ITEMS) is 256, so we aren't too concerned about running out of space
//ammo
#define INVENTORY_9MM 27
#define INVENTORY_792MM 28
#define INVENTORY_SP5AMMO 29
#define INVENTORY_ROCKETS 30
#define INVENTORY_GRENADES 31
#define INVENTORY_127MM 32
#define INVENTORY_FUEL 33
#define INVENTORY_CHARGES 34
// please leave these open up to 48 (INVENTORY_HEALTH) (and double check defines when merging)
// the inventory max (MAX_ITEMS) is 256, so we aren't too concerned about running out of space
//powerups
#define INVENTORY_HEALTH 48
#define INVENTORY_TELEPORTER 49
#define INVENTORY_MEDKIT 50
#define INVENTORY_QUAD 51
#define INVENTORY_ENVIRONMENTSUIT 52
#define INVENTORY_HASTE 53
#define INVENTORY_INVISIBILITY 54
#define INVENTORY_REGEN 55
#define INVENTORY_FLIGHT 56
#define INVENTORY_REDFLAG 57
#define INVENTORY_BLUEFLAG 58
//enemy stuff
#define ENEMY_HORIZONTAL_DIST 200
#define ENEMY_HEIGHT 201
#define NUM_VISIBLE_ENEMIES 202
#define NUM_VISIBLE_TEAMMATES 203
//item numbers (make sure they are in sync with bg_itemlist in bg_misc.c)
#define MODELINDEX_ARMORSHARD 1
#define MODELINDEX_ARMORCOMBAT 2
#define MODELINDEX_ARMORBODY 3
#define MODELINDEX_HEALTHSMALL 4
#define MODELINDEX_HEALTH 5
#define MODELINDEX_HEALTHLARGE 6
#define MODELINDEX_HEALTHMEGA 7
#define MODELINDEX_GAUNTLET 8
#define MODELINDEX_SHOTGUN 9
#define MODELINDEX_MACHINEGUN 10
#define MODELINDEX_GRENADELAUNCHER 11
#define MODELINDEX_ROCKETLAUNCHER 12
#define MODELINDEX_LIGHTNING 13
#define MODELINDEX_RAILGUN 14
#define MODELINDEX_SP5 15
#define MODELINDEX_BFG10K 16
#define MODELINDEX_GRAPPLINGHOOK 17
#define MODELINDEX_SHELLS 18
#define MODELINDEX_BULLETS 19
#define MODELINDEX_GRENADES 20
#define MODELINDEX_CELLS 21
#define MODELINDEX_LIGHTNINGAMMO 22
#define MODELINDEX_ROCKETS 23
#define MODELINDEX_SLUGS 24
#define MODELINDEX_BFGAMMO 25
#define MODELINDEX_TELEPORTER 26
#define MODELINDEX_MEDKIT 27
#define MODELINDEX_QUAD 28
#define MODELINDEX_ENVIRONMENTSUIT 29
#define MODELINDEX_HASTE 30
#define MODELINDEX_INVISIBILITY 31
#define MODELINDEX_REGEN 32
#define MODELINDEX_FLIGHT 33
#define MODELINDEX_REDFLAG 34
#define MODELINDEX_BLUEFLAG 35

134
src/botai/match.h Normal file
View File

@ -0,0 +1,134 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: match.h
// Function: match template defines
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-10-01
// Tab Size: 4 (real tabs)
//
//===========================================================================
//match template contexts
#define MTCONTEXT_ENTERGAME 2
#define MTCONTEXT_INITIALTEAMCHAT 4
#define MTCONTEXT_TIME 8
#define MTCONTEXT_TEAMMATE 16
#define MTCONTEXT_ADDRESSEE 32
#define MTCONTEXT_PATROLKEYAREA 64
#define MTCONTEXT_REPLYCHAT 128
#define MTCONTEXT_CTF 256
//message types
#define MSG_ENTERGAME 2 //enter game message
#define MSG_HELP 3 //help someone
#define MSG_ACCOMPANY 4 //accompany someone
#define MSG_DEFENDKEYAREA 5 //defend a key area
#define MSG_RUSHBASE 6 //everyone rush to base
#define MSG_GETFLAG 7 //get the enemy flag
#define MSG_STARTTEAMLEADERSHIP 8 //someone wants to become the team leader
#define MSG_STOPTEAMLEADERSHIP 9 //someone wants to stop being the team leader
#define MSG_WHOISTEAMLAEDER 10 //who is the team leader
#define MSG_WAIT 11 //wait for someone
#define MSG_WHATAREYOUDOING 12 //what are you doing?
#define MSG_JOINSUBTEAM 13 //join a sub-team
#define MSG_LEAVESUBTEAM 14 //leave a sub-team
#define MSG_CREATENEWFORMATION 15 //create a new formation
#define MSG_FORMATIONPOSITION 16 //tell someone his/her position in a formation
#define MSG_FORMATIONSPACE 17 //set the formation intervening space
#define MSG_DOFORMATION 18 //form a known formation
#define MSG_DISMISS 19 //dismiss commanded team mates
#define MSG_CAMP 20 //camp somewhere
#define MSG_CHECKPOINT 21 //remember a check point
#define MSG_PATROL 22 //patrol between certain keypoints
#define MSG_LEADTHEWAY 23 //lead the way
#define MSG_GETITEM 24 //get an item
#define MSG_KILL 25 //kill someone
#define MSG_WHEREAREYOU 26 //where is someone
#define MSG_RETURNFLAG 27 //return the flag
#define MSG_WHATISMYCOMMAND 28 //ask the team leader what to do
#define MSG_WHICHTEAM 29 //ask which team a bot is in
//
#define MSG_ME 100
#define MSG_EVERYONE 101
#define MSG_MULTIPLENAMES 102
#define MSG_NAME 103
#define MSG_PATROLKEYAREA 104
#define MSG_MINUTES 105
#define MSG_SECONDS 106
#define MSG_FOREVER 107
//
#define MSG_CHATALL 200
#define MSG_CHATTEAM 201
//
#define MSG_CTF 300 //ctf message
//command sub types
#define ST_SOMEWHERE 0
#define ST_NEARITEM 1
#define ST_ADDRESSED 2
#define ST_METER 4
#define ST_FEET 8
#define ST_TIME 16
#define ST_HERE 32
#define ST_THERE 64
#define ST_I 128
#define ST_MORE 256
#define ST_BACK 512
#define ST_REVERSE 1024
#define ST_SOMEONE 2048
#define ST_GOTFLAG 4096
#define ST_CAPTUREDFLAG 8192
#define ST_RETURNEDFLAG 16384
#define ST_TEAM 32768
//word replacement variables
#define THE_ENEMY 7
#define THE_TEAM 7
//team message variables
#define NETNAME 0
#define PLACE 1
#define FLAG 1
#define MESSAGE 2
#define ADDRESSEE 2
#define ITEM 3
#define TEAMMATE 4
#define TEAMNAME 4
#define ENEMY 4
#define KEYAREA 5
#define FORMATION 5
#define POSITION 5
#define NUMBER 5
#define TIME 6
#define NAME 6
#define MORE 6

46
src/botai/syn.h Normal file
View File

@ -0,0 +1,46 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: syn.h
// Function: synonyms
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-09-08
// Tab Size: 4 (real tabs)
// Notes: -
//===========================================================================
#define CONTEXT_ALL 0xFFFFFFFF
#define CONTEXT_NORMAL 1
#define CONTEXT_NEARBYITEM 2
#define CONTEXT_CTFREDTEAM 4
#define CONTEXT_CTFBLUETEAM 8
#define CONTEXT_REPLY 16
#define CONTEXT_NAMES 1024

276
src/botlib/aasfile.h Normal file
View File

@ -0,0 +1,276 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//NOTE: int = default signed
// default long
#define AASID ( ( 'S' << 24 ) + ( 'A' << 16 ) + ( 'A' << 8 ) + 'E' )
#define AASVERSION 8
//presence types
#define PRESENCE_NONE 1
#define PRESENCE_NORMAL 2
#define PRESENCE_CROUCH 4
//travel types
#define MAX_TRAVELTYPES 32
#define TRAVEL_INVALID 1 //temporary not possible
#define TRAVEL_WALK 2 //walking
#define TRAVEL_CROUCH 3 //crouching
#define TRAVEL_BARRIERJUMP 4 //jumping onto a barrier
#define TRAVEL_JUMP 5 //jumping
#define TRAVEL_LADDER 6 //climbing a ladder
#define TRAVEL_WALKOFFLEDGE 7 //walking of a ledge
#define TRAVEL_SWIM 8 //swimming
#define TRAVEL_WATERJUMP 9 //jump out of the water
#define TRAVEL_TELEPORT 10 //teleportation
#define TRAVEL_ELEVATOR 11 //travel by elevator
#define TRAVEL_ROCKETJUMP 12 //rocket jumping required for travel
#define TRAVEL_BFGJUMP 13 //bfg jumping required for travel
#define TRAVEL_GRAPPLEHOOK 14 //grappling hook required for travel
#define TRAVEL_DOUBLEJUMP 15 //double jump
#define TRAVEL_RAMPJUMP 16 //ramp jump
#define TRAVEL_STRAFEJUMP 17 //strafe jump
#define TRAVEL_JUMPPAD 18 //jump pad
#define TRAVEL_FUNCBOB 19 //func bob
//additional travel flags
#define TRAVELTYPE_MASK 0xFFFFFF
#define TRAVELFLAG_NOTTEAM1 ( 1 << 24 )
#define TRAVELFLAG_NOTTEAM2 ( 2 << 24 )
//face flags
#define FACE_SOLID 1 //just solid at the other side
#define FACE_LADDER 2 //ladder
#define FACE_GROUND 4 //standing on ground when in this face
#define FACE_GAP 8 //gap in the ground
#define FACE_LIQUID 16
#define FACE_LIQUIDSURFACE 32
//area contents
#define AREACONTENTS_WATER 1
#define AREACONTENTS_LAVA 2
#define AREACONTENTS_SLIME 4
#define AREACONTENTS_CLUSTERPORTAL 8
#define AREACONTENTS_TELEPORTAL 16
#define AREACONTENTS_ROUTEPORTAL 32
#define AREACONTENTS_TELEPORTER 64
#define AREACONTENTS_JUMPPAD 128
#define AREACONTENTS_DONOTENTER 256
#define AREACONTENTS_VIEWPORTAL 512
// Rafael - nopass
#define AREACONTENTS_DONOTENTER_LARGE 1024
#define AREACONTENTS_MOVER 2048
//number of model of the mover inside this area
#define AREACONTENTS_MODELNUMSHIFT 24
#define AREACONTENTS_MAXMODELNUM 0xFF
#define AREACONTENTS_MODELNUM ( AREACONTENTS_MAXMODELNUM << AREACONTENTS_MODELNUMSHIFT )
//area flags
#define AREA_GROUNDED 1 //bot can stand on the ground
#define AREA_LADDER 2 //area contains one or more ladder faces
#define AREA_LIQUID 4 //area contains a liquid
// Ridah
#define AREA_DISABLED 8
#define AREA_USEFORROUTING 1024
//aas file header lumps
#define AAS_LUMPS 14
#define AASLUMP_BBOXES 0
#define AASLUMP_VERTEXES 1
#define AASLUMP_PLANES 2
#define AASLUMP_EDGES 3
#define AASLUMP_EDGEINDEX 4
#define AASLUMP_FACES 5
#define AASLUMP_FACEINDEX 6
#define AASLUMP_AREAS 7
#define AASLUMP_AREASETTINGS 8
#define AASLUMP_REACHABILITY 9
#define AASLUMP_NODES 10
#define AASLUMP_PORTALS 11
#define AASLUMP_PORTALINDEX 12
#define AASLUMP_CLUSTERS 13
//========== bounding box =========
//bounding box
typedef struct aas_bbox_s
{
int presencetype;
int flags;
vec3_t mins, maxs;
} aas_bbox_t;
//============ settings ===========
//reachability to another area
typedef struct aas_reachability_s
{
int areanum; //number of the reachable area
int facenum; //number of the face towards the other area
int edgenum; //number of the edge towards the other area
vec3_t start; //start point of inter area movement
vec3_t end; //end point of inter area movement
int traveltype; //type of travel required to get to the area
unsigned short int traveltime; //travel time of the inter area movement
} aas_reachability_t;
//area settings
typedef struct aas_areasettings_s
{
//could also add all kind of statistic fields
int contents; //contents of the convex area
int areaflags; //several area flags
int presencetype; //how a bot can be present in this convex area
int cluster; //cluster the area belongs to, if negative it's a portal
int clusterareanum; //number of the area in the cluster
int numreachableareas; //number of reachable areas from this one
int firstreachablearea; //first reachable area in the reachable area index
// Ridah, add a ground steepness stat, so we can avoid terrain when we can take a close-by flat route
float groundsteepness; // 0 = flat, 1 = steep
} aas_areasettings_t;
//cluster portal
typedef struct aas_portal_s
{
int areanum; //area that is the actual portal
int frontcluster; //cluster at front of portal
int backcluster; //cluster at back of portal
int clusterareanum[2]; //number of the area in the front and back cluster
} aas_portal_t;
//cluster portal index
typedef int aas_portalindex_t;
//cluster
typedef struct aas_cluster_s
{
int numareas; //number of areas in the cluster
int numreachabilityareas; //number of areas with reachabilities
int numportals; //number of cluster portals
int firstportal; //first cluster portal in the index
} aas_cluster_t;
//============ 3d definition ============
typedef vec3_t aas_vertex_t;
//just a plane in the third dimension
typedef struct aas_plane_s
{
vec3_t normal; //normal vector of the plane
float dist; //distance of the plane (normal vector * distance = point in plane)
int type;
} aas_plane_t;
//edge
typedef struct aas_edge_s
{
int v[2]; //numbers of the vertexes of this edge
} aas_edge_t;
//edge index, negative if vertexes are reversed
typedef int aas_edgeindex_t;
//a face bounds a convex area, often it will also seperate two convex areas
typedef struct aas_face_s
{
int planenum; //number of the plane this face is in
int faceflags; //face flags (no use to create face settings for just this field)
int numedges; //number of edges in the boundary of the face
int firstedge; //first edge in the edge index
int frontarea; //convex area at the front of this face
int backarea; //convex area at the back of this face
} aas_face_t;
//face index, stores a negative index if backside of face
typedef int aas_faceindex_t;
//convex area with a boundary of faces
typedef struct aas_area_s
{
int areanum; //number of this area
//3d definition
int numfaces; //number of faces used for the boundary of the convex area
int firstface; //first face in the face index used for the boundary of the convex area
vec3_t mins; //mins of the convex area
vec3_t maxs; //maxs of the convex area
vec3_t center; //'center' of the convex area
} aas_area_t;
//nodes of the bsp tree
typedef struct aas_node_s
{
int planenum;
int children[2]; //child nodes of this node, or convex areas as leaves when negative
//when a child is zero it's a solid leaf
} aas_node_t;
//=========== aas file ===============
//header lump
typedef struct
{
int fileofs;
int filelen;
} aas_lump_t;
//aas file header
typedef struct aas_header_s
{
int ident;
int version;
int bspchecksum;
//data entries
aas_lump_t lumps[AAS_LUMPS];
} aas_header_t;
//====== additional information ======
/*
- when a node child is a solid leaf the node child number is zero
- two adjacent areas (sharing a plane at opposite sides) share a face
this face is a portal between the areas
- when an area uses a face from the faceindex with a positive index
then the face plane normal points into the area
- the face edges are stored counter clockwise using the edgeindex
- two adjacent convex areas (sharing a face) only share One face
this is a simple result of the areas being convex
- the convex areas can't have a mixture of ground and gap faces
other mixtures of faces in one area are allowed
- areas with the AREACONTENTS_CLUSTERPORTAL in the settings have
cluster number zero
- edge zero is a dummy
- face zero is a dummy
- area zero is a dummy
- node zero is a dummy
*/

193
src/botlib/be_aas.h Normal file
View File

@ -0,0 +1,193 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas.h
*
* desc: Area Awareness System, stuff exported to the AI
*
* $Archive: /Wolf4/src/botlib/be_aas.h $
*
*****************************************************************************/
#define MAX_AAS_WORLDS 2 // one for each bounding box type
#ifndef MAX_STRINGFIELD
#define MAX_STRINGFIELD 80
#endif
//travel flags
#define TFL_INVALID 0x0000001 //traveling temporary not possible
#define TFL_WALK 0x0000002 //walking
#define TFL_CROUCH 0x0000004 //crouching
#define TFL_BARRIERJUMP 0x0000008 //jumping onto a barrier
#define TFL_JUMP 0x0000010 //jumping
#define TFL_LADDER 0x0000020 //climbing a ladder
#define TFL_WALKOFFLEDGE 0x0000080 //walking of a ledge
#define TFL_SWIM 0x0000100 //swimming
#define TFL_WATERJUMP 0x0000200 //jumping out of the water
#define TFL_TELEPORT 0x0000400 //teleporting
#define TFL_ELEVATOR 0x0000800 //elevator
#define TFL_ROCKETJUMP 0x0001000 //rocket jumping
#define TFL_BFGJUMP 0x0002000 //bfg jumping
#define TFL_GRAPPLEHOOK 0x0004000 //grappling hook
#define TFL_DOUBLEJUMP 0x0008000 //double jump
#define TFL_RAMPJUMP 0x0010000 //ramp jump
#define TFL_STRAFEJUMP 0x0020000 //strafe jump
#define TFL_JUMPPAD 0x0040000 //jump pad
#define TFL_AIR 0x0080000 //travel through air
#define TFL_WATER 0x0100000 //travel through water
#define TFL_SLIME 0x0200000 //travel through slime
#define TFL_LAVA 0x0400000 //travel through lava
#define TFL_DONOTENTER 0x0800000 //travel through donotenter area
#define TFL_FUNCBOB 0x1000000 //func bobbing
#define TFL_DONOTENTER_LARGE 0x2000000 //travel through donotenter area
//default travel flags
//----(SA) modified since slime is no longer deadly
#define TFL_DEFAULT TFL_WALK | TFL_CROUCH | TFL_BARRIERJUMP | \
TFL_JUMP | TFL_LADDER | \
TFL_WALKOFFLEDGE | TFL_SWIM | TFL_WATERJUMP | \
TFL_TELEPORT | TFL_ELEVATOR | TFL_AIR | \
TFL_WATER | TFL_SLIME | \
TFL_JUMPPAD | TFL_FUNCBOB
typedef enum
{
SOLID_NOT, // no interaction with other objects
SOLID_TRIGGER, // only touch when inside, after moving
SOLID_BBOX, // touch on edge
SOLID_BSP // bsp clip, touch on edge
} solid_t;
//a trace is returned when a box is swept through the AAS world
typedef struct aas_trace_s
{
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
int ent; // entity blocking the trace
int lastarea; // last area the trace was in (zero if none)
int area; // area blocking the trace (zero if none)
int planenum; // number of the plane that was hit
} aas_trace_t;
/* Defined in botlib.h
//bsp_trace_t hit surface
typedef struct bsp_surface_s
{
char name[16];
int flags;
int value;
} bsp_surface_t;
//a trace is returned when a box is swept through the BSP world
typedef struct bsp_trace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
float exp_dist; // expanded plane distance
int sidenum; // number of the brush side hit
bsp_surface_t surface; // hit surface
int contents; // contents on other side of surface hit
int ent; // number of entity hit
} bsp_trace_t;
//
*/
//entity info
typedef struct aas_entityinfo_s
{
int valid; // true if updated this frame
int type; // entity type
int flags; // entity flags
float ltime; // local time
float update_time; // time between last and current update
int number; // number of the entity
vec3_t origin; // origin of the entity
vec3_t angles; // angles of the model
vec3_t old_origin; // for lerping
vec3_t lastvisorigin; // last visible origin
vec3_t mins; // bounding box minimums
vec3_t maxs; // bounding box maximums
int groundent; // ground entity
int solid; // solid type
int modelindex; // model used
int modelindex2; // weapons, CTF flags, etc
int frame; // model frame number
int event; // impulse events -- muzzle flashes, footsteps, etc
int eventParm; // even parameter
int powerups; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim; // mask off ANIM_TOGGLEBIT
int torsoAnim; // mask off ANIM_TOGGLEBIT
// int weapAnim; // mask off ANIM_TOGGLEBIT //----(SA) added
//----(SA) didn't want to comment in as I wasn't sure of any implications of changing this structure.
} aas_entityinfo_t;
//client movement prediction stop events, stop as soon as:
#define SE_NONE 0
#define SE_HITGROUND 1 // the ground is hit
#define SE_LEAVEGROUND 2 // there's no ground
#define SE_ENTERWATER 4 // water is entered
#define SE_ENTERSLIME 8 // slime is entered
#define SE_ENTERLAVA 16 // lava is entered
#define SE_HITGROUNDDAMAGE 32 // the ground is hit with damage
#define SE_GAP 64 // there's a gap
#define SE_TOUCHJUMPPAD 128 // touching a jump pad area
#define SE_TOUCHTELEPORTER 256 // touching teleporter
#define SE_ENTERAREA 512 // the given stoparea is entered
#define SE_HITGROUNDAREA 1024 // a ground face in the area is hit
typedef struct aas_clientmove_s
{
vec3_t endpos; //position at the end of movement prediction
vec3_t velocity; //velocity at the end of movement prediction
aas_trace_t trace; //last trace
int presencetype; //presence type at end of movement prediction
int stopevent; //event that made the prediction stop
float endcontents; //contents at the end of movement prediction
float time; //time predicted ahead
int frames; //number of frames predicted ahead
} aas_clientmove_t;
typedef struct aas_altroutegoal_s
{
vec3_t origin;
int areanum;
unsigned short starttraveltime;
unsigned short goaltraveltime;
unsigned short extratraveltime;
} aas_altroutegoal_t;

96
src/botlib/be_aas_bsp.h Normal file
View File

@ -0,0 +1,96 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_bsp.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//loads the given BSP file
int AAS_LoadBSPFile( void );
//dump the loaded BSP data
void AAS_DumpBSPData( void );
//unlink the given entity from the bsp tree leaves
void AAS_UnlinkFromBSPLeaves( bsp_link_t *leaves );
//link the given entity to the bsp tree leaves of the given model
bsp_link_t *AAS_BSPLinkEntity( vec3_t absmins,
vec3_t absmaxs,
int entnum,
int modelnum );
//calculates collision with given entity
qboolean AAS_EntityCollision( int entnum,
vec3_t start,
vec3_t boxmins,
vec3_t boxmaxs,
vec3_t end,
int contentmask,
bsp_trace_t *trace );
//for debugging
void AAS_PrintFreeBSPLinks( char *str );
//
#endif //AASINTERN
#define MAX_EPAIRKEY 128
//trace through the world
bsp_trace_t AAS_Trace( vec3_t start,
vec3_t mins,
vec3_t maxs,
vec3_t end,
int passent,
int contentmask );
//returns the contents at the given point
int AAS_PointContents( vec3_t point );
//returns true when p2 is in the PVS of p1
qboolean AAS_inPVS( vec3_t p1, vec3_t p2 );
//returns true when p2 is in the PHS of p1
qboolean AAS_inPHS( vec3_t p1, vec3_t p2 );
//returns true if the given areas are connected
qboolean AAS_AreasConnected( int area1, int area2 );
//creates a list with entities totally or partly within the given box
int AAS_BoxEntities( vec3_t absmins, vec3_t absmaxs, int *list, int maxcount );
//gets the mins, maxs and origin of a BSP model
void AAS_BSPModelMinsMaxsOrigin( int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin );
//handle to the next bsp entity
int AAS_NextBSPEntity( int ent );
//return the value of the BSP epair key
int AAS_ValueForBSPEpairKey( int ent, char *key, char *value, int size );
//get a vector for the BSP epair key
int AAS_VectorForBSPEpairKey( int ent, char *key, vec3_t v );
//get a float for the BSP epair key
int AAS_FloatForBSPEpairKey( int ent, char *key, float *value );
//get an integer for the BSP epair key
int AAS_IntForBSPEpairKey( int ent, char *key, int *value );

525
src/botlib/be_aas_bspq3.c Normal file
View File

@ -0,0 +1,525 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_bspq3.c
*
* desc: BSP, Environment Sampling
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
extern botlib_import_t botimport;
//#define TRACE_DEBUG
#define ON_EPSILON 0.005
//#define DEG2RAD( a ) (( a * M_PI ) / 180.0F)
#define MAX_BSPENTITIES 2048
typedef struct rgb_s
{
int red;
int green;
int blue;
} rgb_t;
//bsp entity epair
typedef struct bsp_epair_s
{
char *key;
char *value;
struct bsp_epair_s *next;
} bsp_epair_t;
//bsp data entity
typedef struct bsp_entity_s
{
bsp_epair_t *epairs;
} bsp_entity_t;
//id Sofware BSP data
typedef struct bsp_s
{
//true when bsp file is loaded
int loaded;
//entity data
int entdatasize;
char *dentdata;
//bsp entities
int numentities;
bsp_entity_t entities[MAX_BSPENTITIES];
//memory used for strings and epairs
byte *ebuffer;
} bsp_t;
//global bsp
bsp_t bspworld;
#ifdef BSP_DEBUG
typedef struct cname_s
{
int value;
char *name;
} cname_t;
cname_t contentnames[] =
{
{CONTENTS_SOLID,"CONTENTS_SOLID"},
{CONTENTS_WINDOW,"CONTENTS_WINDOW"},
{CONTENTS_AUX,"CONTENTS_AUX"},
{CONTENTS_LAVA,"CONTENTS_LAVA"},
{CONTENTS_SLIME,"CONTENTS_SLIME"},
{CONTENTS_WATER,"CONTENTS_WATER"},
{CONTENTS_MIST,"CONTENTS_MIST"},
{LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
{CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
{CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
{CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
{CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
{CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
{CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
{CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
{CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
{CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
{CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
{CONTENTS_MONSTER,"CONTENTS_MONSTER"},
{CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
{CONTENTS_DETAIL,"CONTENTS_DETAIL"},
{CONTENTS_TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
{CONTENTS_LADDER,"CONTENTS_LADDER"},
{0, 0}
};
void PrintContents( int contents ) {
int i;
for ( i = 0; contentnames[i].value; i++ )
{
if ( contents & contentnames[i].value ) {
botimport.Print( PRT_MESSAGE, "%s\n", contentnames[i].name );
} //end if
} //end for
} //end of the function PrintContents
#endif //BSP_DEBUG
//===========================================================================
// traces axial boxes of any size through the world
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bsp_trace_t AAS_Trace( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask ) {
bsp_trace_t bsptrace;
botimport.Trace( &bsptrace, start, mins, maxs, end, passent, contentmask );
return bsptrace;
} //end of the function AAS_Trace
//===========================================================================
// returns the contents at the given point
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_PointContents( vec3_t point ) {
return botimport.PointContents( point );
} //end of the function AAS_PointContents
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_EntityCollision( int entnum,
vec3_t start, vec3_t boxmins, vec3_t boxmaxs, vec3_t end,
int contentmask, bsp_trace_t *trace ) {
bsp_trace_t enttrace;
botimport.EntityTrace( &enttrace, start, boxmins, boxmaxs, end, entnum, contentmask );
if ( enttrace.fraction < trace->fraction ) {
memcpy( trace, &enttrace, sizeof( bsp_trace_t ) );
return qtrue;
} //end if
return qfalse;
} //end of the function AAS_EntityCollision
//===========================================================================
// returns true if in Potentially Hearable Set
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_inPVS( vec3_t p1, vec3_t p2 ) {
return botimport.inPVS( p1, p2 );
} //end of the function AAS_InPVS
//===========================================================================
// returns true if in Potentially Visible Set
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_inPHS( vec3_t p1, vec3_t p2 ) {
return qtrue;
} //end of the function AAS_inPHS
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_BSPModelMinsMaxsOrigin( int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin ) {
botimport.BSPModelMinsMaxsOrigin( modelnum, angles, mins, maxs, origin );
} //end of the function AAS_BSPModelMinsMaxs
//===========================================================================
// unlinks the entity from all leaves
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_UnlinkFromBSPLeaves( bsp_link_t *leaves ) {
} //end of the function AAS_UnlinkFromBSPLeaves
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bsp_link_t *AAS_BSPLinkEntity( vec3_t absmins, vec3_t absmaxs, int entnum, int modelnum ) {
return NULL;
} //end of the function AAS_BSPLinkEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_BoxEntities( vec3_t absmins, vec3_t absmaxs, int *list, int maxcount ) {
return 0;
} //end of the function AAS_BoxEntities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_NextBSPEntity( int ent ) {
ent++;
if ( ent >= 1 && ent < bspworld.numentities ) {
return ent;
}
return 0;
} //end of the function AAS_NextBSPEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_BSPEntityInRange( int ent ) {
if ( ent <= 0 || ent >= bspworld.numentities ) {
botimport.Print( PRT_MESSAGE, "bsp entity out of range\n" );
return qfalse;
} //end if
return qtrue;
} //end of the function AAS_BSPEntityInRange
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_ValueForBSPEpairKey( int ent, char *key, char *value, int size ) {
bsp_epair_t *epair;
value[0] = '\0';
if ( !AAS_BSPEntityInRange( ent ) ) {
return qfalse;
}
for ( epair = bspworld.entities[ent].epairs; epair; epair = epair->next )
{
if ( !strcmp( epair->key, key ) ) {
strncpy( value, epair->value, size - 1 );
value[size - 1] = '\0';
return qtrue;
} //end if
} //end for
return qfalse;
} //end of the function AAS_FindBSPEpair
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_VectorForBSPEpairKey( int ent, char *key, vec3_t v ) {
char buf[MAX_EPAIRKEY];
double v1, v2, v3;
VectorClear( v );
if ( !AAS_ValueForBSPEpairKey( ent, key, buf, MAX_EPAIRKEY ) ) {
return qfalse;
}
//scanf into doubles, then assign, so it is vec_t size independent
v1 = v2 = v3 = 0;
sscanf( buf, "%lf %lf %lf", &v1, &v2, &v3 );
v[0] = v1;
v[1] = v2;
v[2] = v3;
return qtrue;
} //end of the function AAS_VectorForBSPEpairKey
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_FloatForBSPEpairKey( int ent, char *key, float *value ) {
char buf[MAX_EPAIRKEY];
*value = 0;
if ( !AAS_ValueForBSPEpairKey( ent, key, buf, MAX_EPAIRKEY ) ) {
return qfalse;
}
*value = atof( buf );
return qtrue;
} //end of the function AAS_FloatForBSPEpairKey
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_IntForBSPEpairKey( int ent, char *key, int *value ) {
char buf[MAX_EPAIRKEY];
*value = 0;
if ( !AAS_ValueForBSPEpairKey( ent, key, buf, MAX_EPAIRKEY ) ) {
return qfalse;
}
*value = atoi( buf );
return qtrue;
} //end of the function AAS_IntForBSPEpairKey
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_FreeBSPEntities( void ) {
// RF, optimized memory allocation
/*
int i;
bsp_entity_t *ent;
bsp_epair_t *epair, *nextepair;
for (i = 1; i < bspworld.numentities; i++)
{
ent = &bspworld.entities[i];
for (epair = ent->epairs; epair; epair = nextepair)
{
nextepair = epair->next;
//
if (epair->key) FreeMemory(epair->key);
if (epair->value) FreeMemory(epair->value);
FreeMemory(epair);
} //end for
} //end for
*/
if ( bspworld.ebuffer ) {
FreeMemory( bspworld.ebuffer );
}
bspworld.numentities = 0;
} //end of the function AAS_FreeBSPEntities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ParseBSPEntities( void ) {
script_t *script;
token_t token;
bsp_entity_t *ent;
bsp_epair_t *epair;
byte *buffer, *buftrav;
int bufsize;
// RF, modified this, so that it first gathers up memory requirements, then allocates a single chunk,
// and places the strings all in there
bspworld.ebuffer = NULL;
script = LoadScriptMemory( bspworld.dentdata, bspworld.entdatasize, "entdata" );
SetScriptFlags( script, SCFL_NOSTRINGWHITESPACES | SCFL_NOSTRINGESCAPECHARS ); //SCFL_PRIMITIVE);
bufsize = 0;
while ( PS_ReadToken( script, &token ) )
{
if ( strcmp( token.string, "{" ) ) {
ScriptError( script, "invalid %s\n", token.string );
AAS_FreeBSPEntities();
FreeScript( script );
return;
} //end if
if ( bspworld.numentities >= MAX_BSPENTITIES ) {
botimport.Print( PRT_MESSAGE, "too many entities in BSP file\n" );
break;
} //end if
while ( PS_ReadToken( script, &token ) )
{
if ( !strcmp( token.string, "}" ) ) {
break;
}
bufsize += sizeof( bsp_epair_t );
if ( token.type != TT_STRING ) {
ScriptError( script, "invalid %s\n", token.string );
AAS_FreeBSPEntities();
FreeScript( script );
return;
} //end if
StripDoubleQuotes( token.string );
bufsize += strlen( token.string ) + 1;
if ( !PS_ExpectTokenType( script, TT_STRING, 0, &token ) ) {
AAS_FreeBSPEntities();
FreeScript( script );
return;
} //end if
StripDoubleQuotes( token.string );
bufsize += strlen( token.string ) + 1;
} //end while
if ( strcmp( token.string, "}" ) ) {
ScriptError( script, "missing }\n" );
AAS_FreeBSPEntities();
FreeScript( script );
return;
} //end if
} //end while
FreeScript( script );
buffer = (byte *)GetClearedHunkMemory( bufsize );
buftrav = buffer;
bspworld.ebuffer = buffer;
// RF, now parse the entities into memory
// RF, NOTE: removed error checks for speed, no need to do them twice
script = LoadScriptMemory( bspworld.dentdata, bspworld.entdatasize, "entdata" );
SetScriptFlags( script, SCFL_NOSTRINGWHITESPACES | SCFL_NOSTRINGESCAPECHARS ); //SCFL_PRIMITIVE);
bspworld.numentities = 1;
while ( PS_ReadToken( script, &token ) )
{
ent = &bspworld.entities[bspworld.numentities];
bspworld.numentities++;
ent->epairs = NULL;
while ( PS_ReadToken( script, &token ) )
{
if ( !strcmp( token.string, "}" ) ) {
break;
}
epair = (bsp_epair_t *) buftrav; buftrav += sizeof( bsp_epair_t );
epair->next = ent->epairs;
ent->epairs = epair;
StripDoubleQuotes( token.string );
epair->key = (char *) buftrav; buftrav += ( strlen( token.string ) + 1 );
strcpy( epair->key, token.string );
if ( !PS_ExpectTokenType( script, TT_STRING, 0, &token ) ) {
AAS_FreeBSPEntities();
FreeScript( script );
return;
} //end if
StripDoubleQuotes( token.string );
epair->value = (char *) buftrav; buftrav += ( strlen( token.string ) + 1 );
strcpy( epair->value, token.string );
} //end while
} //end while
FreeScript( script );
} //end of the function AAS_ParseBSPEntities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_BSPTraceLight( vec3_t start, vec3_t end, vec3_t endpos, int *red, int *green, int *blue ) {
return 0;
} //end of the function AAS_BSPTraceLight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DumpBSPData( void ) {
AAS_FreeBSPEntities();
if ( bspworld.dentdata ) {
FreeMemory( bspworld.dentdata );
}
bspworld.dentdata = NULL;
bspworld.entdatasize = 0;
//
bspworld.loaded = qfalse;
memset( &bspworld, 0, sizeof( bspworld ) );
} //end of the function AAS_DumpBSPData
//===========================================================================
// load an bsp file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_LoadBSPFile( void ) {
AAS_DumpBSPData();
bspworld.entdatasize = strlen( botimport.BSPEntityData() ) + 1;
bspworld.dentdata = (char *) GetClearedHunkMemory( bspworld.entdatasize );
memcpy( bspworld.dentdata, botimport.BSPEntityData(), bspworld.entdatasize );
AAS_ParseBSPEntities();
bspworld.loaded = qtrue;
return BLERR_NOERROR;
} //end of the function AAS_LoadBSPFile

1601
src/botlib/be_aas_cluster.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_cluster.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//initialize the AAS clustering
void AAS_InitClustering( void );
void AAS_SetViewPortalsAsClusterPortals( void );
#endif //AASINTERN

692
src/botlib/be_aas_debug.c Normal file
View File

@ -0,0 +1,692 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_debug.c
*
* desc: AAS debug code
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_libvar.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_interface.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
#define MAX_DEBUGLINES 1024
#define MAX_DEBUGPOLYGONS 128
int debuglines[MAX_DEBUGLINES];
int debuglinevisible[MAX_DEBUGLINES];
int numdebuglines;
static int debugpolygons[MAX_DEBUGPOLYGONS];
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ClearShownPolygons( void ) {
int i;
//*
for ( i = 0; i < MAX_DEBUGPOLYGONS; i++ )
{
if ( debugpolygons[i] ) {
botimport.DebugPolygonDelete( debugpolygons[i] );
}
debugpolygons[i] = 0;
} //end for
//*/
/*
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
{
botimport.DebugPolygonDelete(i);
debugpolygons[i] = 0;
} //end for
*/
} //end of the function AAS_ClearShownPolygons
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowPolygon( int color, int numpoints, vec3_t *points ) {
int i;
for ( i = 0; i < MAX_DEBUGPOLYGONS; i++ )
{
if ( !debugpolygons[i] ) {
debugpolygons[i] = botimport.DebugPolygonCreate( color, numpoints, points );
break;
} //end if
} //end for
} //end of the function AAS_ShowPolygon
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ClearShownDebugLines( void ) {
int i;
//make all lines invisible
for ( i = 0; i < MAX_DEBUGLINES; i++ )
{
if ( debuglines[i] ) {
//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
botimport.DebugLineDelete( debuglines[i] );
debuglines[i] = 0;
debuglinevisible[i] = qfalse;
} //end if
} //end for
} //end of the function AAS_ClearShownDebugLines
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DebugLine( vec3_t start, vec3_t end, int color ) {
int line;
for ( line = 0; line < MAX_DEBUGLINES; line++ )
{
if ( !debuglines[line] ) {
debuglines[line] = botimport.DebugLineCreate();
debuglinevisible[line] = qfalse;
numdebuglines++;
} //end if
if ( !debuglinevisible[line] ) {
botimport.DebugLineShow( debuglines[line], start, end, color );
debuglinevisible[line] = qtrue;
return;
} //end else
} //end for
} //end of the function AAS_DebugLine
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PermanentLine( vec3_t start, vec3_t end, int color ) {
int line;
line = botimport.DebugLineCreate();
botimport.DebugLineShow( line, start, end, color );
} //end of the function AAS_PermenentLine
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DrawPermanentCross( vec3_t origin, float size, int color ) {
int i, debugline;
vec3_t start, end;
for ( i = 0; i < 3; i++ )
{
VectorCopy( origin, start );
start[i] += size;
VectorCopy( origin, end );
end[i] -= size;
AAS_DebugLine( start, end, color );
debugline = botimport.DebugLineCreate();
botimport.DebugLineShow( debugline, start, end, color );
} //end for
} //end of the function AAS_DrawPermanentCross
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DrawPlaneCross( vec3_t point, vec3_t normal, float dist, int type, int color ) {
int n0, n1, n2, j, line, lines[2];
vec3_t start1, end1, start2, end2;
//make a cross in the hit plane at the hit point
VectorCopy( point, start1 );
VectorCopy( point, end1 );
VectorCopy( point, start2 );
VectorCopy( point, end2 );
n0 = type % 3;
n1 = ( type + 1 ) % 3;
n2 = ( type + 2 ) % 3;
start1[n1] -= 6;
start1[n2] -= 6;
end1[n1] += 6;
end1[n2] += 6;
start2[n1] += 6;
start2[n2] -= 6;
end2[n1] -= 6;
end2[n2] += 6;
start1[n0] = ( dist - ( start1[n1] * normal[n1] +
start1[n2] * normal[n2] ) ) / normal[n0];
end1[n0] = ( dist - ( end1[n1] * normal[n1] +
end1[n2] * normal[n2] ) ) / normal[n0];
start2[n0] = ( dist - ( start2[n1] * normal[n1] +
start2[n2] * normal[n2] ) ) / normal[n0];
end2[n0] = ( dist - ( end2[n1] * normal[n1] +
end2[n2] * normal[n2] ) ) / normal[n0];
for ( j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++ )
{
if ( !debuglines[line] ) {
debuglines[line] = botimport.DebugLineCreate();
lines[j++] = debuglines[line];
debuglinevisible[line] = qtrue;
numdebuglines++;
} //end if
else if ( !debuglinevisible[line] ) {
lines[j++] = debuglines[line];
debuglinevisible[line] = qtrue;
} //end else
} //end for
botimport.DebugLineShow( lines[0], start1, end1, color );
botimport.DebugLineShow( lines[1], start2, end2, color );
} //end of the function AAS_DrawPlaneCross
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs ) {
vec3_t bboxcorners[8];
int lines[3];
int i, j, line;
//upper corners
bboxcorners[0][0] = origin[0] + maxs[0];
bboxcorners[0][1] = origin[1] + maxs[1];
bboxcorners[0][2] = origin[2] + maxs[2];
//
bboxcorners[1][0] = origin[0] + mins[0];
bboxcorners[1][1] = origin[1] + maxs[1];
bboxcorners[1][2] = origin[2] + maxs[2];
//
bboxcorners[2][0] = origin[0] + mins[0];
bboxcorners[2][1] = origin[1] + mins[1];
bboxcorners[2][2] = origin[2] + maxs[2];
//
bboxcorners[3][0] = origin[0] + maxs[0];
bboxcorners[3][1] = origin[1] + mins[1];
bboxcorners[3][2] = origin[2] + maxs[2];
//lower corners
memcpy( bboxcorners[4], bboxcorners[0], sizeof( vec3_t ) * 4 );
for ( i = 0; i < 4; i++ ) bboxcorners[4 + i][2] = origin[2] + mins[2];
//draw bounding box
for ( i = 0; i < 4; i++ )
{
for ( j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++ )
{
if ( !debuglines[line] ) {
debuglines[line] = botimport.DebugLineCreate();
lines[j++] = debuglines[line];
debuglinevisible[line] = qtrue;
numdebuglines++;
} //end if
else if ( !debuglinevisible[line] ) {
lines[j++] = debuglines[line];
debuglinevisible[line] = qtrue;
} //end else
} //end for
//top plane
botimport.DebugLineShow( lines[0], bboxcorners[i],
bboxcorners[( i + 1 ) & 3], LINECOLOR_RED );
//bottom plane
botimport.DebugLineShow( lines[1], bboxcorners[4 + i],
bboxcorners[4 + ( ( i + 1 ) & 3 )], LINECOLOR_RED );
//vertical lines
botimport.DebugLineShow( lines[2], bboxcorners[i],
bboxcorners[4 + i], LINECOLOR_RED );
} //end for
} //end of the function AAS_ShowBoundingBox
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowFace( int facenum ) {
int i, color, edgenum;
aas_edge_t *edge;
aas_face_t *face;
aas_plane_t *plane;
vec3_t start, end;
color = LINECOLOR_YELLOW;
//check if face number is in range
if ( facenum >= ( *aasworld ).numfaces ) {
botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
} //end if
face = &( *aasworld ).faces[facenum];
//walk through the edges of the face
for ( i = 0; i < face->numedges; i++ )
{
//edge number
edgenum = abs( ( *aasworld ).edgeindex[face->firstedge + i] );
//check if edge number is in range
if ( edgenum >= ( *aasworld ).numedges ) {
botimport.Print( PRT_ERROR, "edgenum %d out of range\n", edgenum );
} //end if
edge = &( *aasworld ).edges[edgenum];
if ( color == LINECOLOR_RED ) {
color = LINECOLOR_GREEN;
} else if ( color == LINECOLOR_GREEN ) {
color = LINECOLOR_BLUE;
} else if ( color == LINECOLOR_BLUE ) {
color = LINECOLOR_YELLOW;
} else { color = LINECOLOR_RED;}
AAS_DebugLine( ( *aasworld ).vertexes[edge->v[0]],
( *aasworld ).vertexes[edge->v[1]],
color );
} //end for
plane = &( *aasworld ).planes[face->planenum];
edgenum = abs( ( *aasworld ).edgeindex[face->firstedge] );
edge = &( *aasworld ).edges[edgenum];
VectorCopy( ( *aasworld ).vertexes[edge->v[0]], start );
VectorMA( start, 20, plane->normal, end );
AAS_DebugLine( start, end, LINECOLOR_RED );
} //end of the function AAS_ShowFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowFacePolygon( int facenum, int color, int flip ) {
int i, edgenum, numpoints;
vec3_t points[128];
aas_edge_t *edge;
aas_face_t *face;
//check if face number is in range
if ( facenum >= ( *aasworld ).numfaces ) {
botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
} //end if
face = &( *aasworld ).faces[facenum];
//walk through the edges of the face
numpoints = 0;
if ( flip ) {
for ( i = face->numedges - 1; i >= 0; i-- )
{
//edge number
edgenum = ( *aasworld ).edgeindex[face->firstedge + i];
edge = &( *aasworld ).edges[abs( edgenum )];
VectorCopy( ( *aasworld ).vertexes[edge->v[edgenum < 0]], points[numpoints] );
numpoints++;
} //end for
} //end if
else
{
for ( i = 0; i < face->numedges; i++ )
{
//edge number
edgenum = ( *aasworld ).edgeindex[face->firstedge + i];
edge = &( *aasworld ).edges[abs( edgenum )];
VectorCopy( ( *aasworld ).vertexes[edge->v[edgenum < 0]], points[numpoints] );
numpoints++;
} //end for
} //end else
AAS_ShowPolygon( color, numpoints, points );
} //end of the function AAS_ShowFacePolygon
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowArea( int areanum, int groundfacesonly ) {
int areaedges[MAX_DEBUGLINES];
int numareaedges, i, j, n, color = 0, line;
int facenum, edgenum;
aas_area_t *area;
aas_face_t *face;
aas_edge_t *edge;
//
numareaedges = 0;
//
if ( areanum < 0 || areanum >= ( *aasworld ).numareas ) {
botimport.Print( PRT_ERROR, "area %d out of range [0, %d]\n",
areanum, ( *aasworld ).numareas );
return;
} //end if
//pointer to the convex area
area = &( *aasworld ).areas[areanum];
//walk through the faces of the area
for ( i = 0; i < area->numfaces; i++ )
{
facenum = abs( ( *aasworld ).faceindex[area->firstface + i] );
//check if face number is in range
if ( facenum >= ( *aasworld ).numfaces ) {
botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
} //end if
face = &( *aasworld ).faces[facenum];
//ground faces only
if ( groundfacesonly ) {
if ( !( face->faceflags & ( FACE_GROUND | FACE_LADDER ) ) ) {
continue;
}
} //end if
//walk through the edges of the face
for ( j = 0; j < face->numedges; j++ )
{
//edge number
edgenum = abs( ( *aasworld ).edgeindex[face->firstedge + j] );
//check if edge number is in range
if ( edgenum >= ( *aasworld ).numedges ) {
botimport.Print( PRT_ERROR, "edgenum %d out of range\n", edgenum );
} //end if
//check if the edge is stored already
for ( n = 0; n < numareaedges; n++ )
{
if ( areaedges[n] == edgenum ) {
break;
}
} //end for
if ( n == numareaedges && numareaedges < MAX_DEBUGLINES ) {
areaedges[numareaedges++] = edgenum;
} //end if
} //end for
//AAS_ShowFace(facenum);
} //end for
//draw all the edges
for ( n = 0; n < numareaedges; n++ )
{
for ( line = 0; line < MAX_DEBUGLINES; line++ )
{
if ( !debuglines[line] ) {
debuglines[line] = botimport.DebugLineCreate();
debuglinevisible[line] = qfalse;
numdebuglines++;
} //end if
if ( !debuglinevisible[line] ) {
break;
} //end else
} //end for
if ( line >= MAX_DEBUGLINES ) {
return;
}
edge = &( *aasworld ).edges[areaedges[n]];
if ( color == LINECOLOR_RED ) {
color = LINECOLOR_BLUE;
} else if ( color == LINECOLOR_BLUE ) {
color = LINECOLOR_GREEN;
} else if ( color == LINECOLOR_GREEN ) {
color = LINECOLOR_YELLOW;
} else { color = LINECOLOR_RED;}
botimport.DebugLineShow( debuglines[line],
( *aasworld ).vertexes[edge->v[0]],
( *aasworld ).vertexes[edge->v[1]],
color );
debuglinevisible[line] = qtrue;
} //end for*/
} //end of the function AAS_ShowArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowAreaPolygons( int areanum, int color, int groundfacesonly ) {
int i, facenum;
aas_area_t *area;
aas_face_t *face;
//
if ( areanum < 0 || areanum >= ( *aasworld ).numareas ) {
botimport.Print( PRT_ERROR, "area %d out of range [0, %d]\n",
areanum, ( *aasworld ).numareas );
return;
} //end if
//pointer to the convex area
area = &( *aasworld ).areas[areanum];
//walk through the faces of the area
for ( i = 0; i < area->numfaces; i++ )
{
facenum = abs( ( *aasworld ).faceindex[area->firstface + i] );
//check if face number is in range
if ( facenum >= ( *aasworld ).numfaces ) {
botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
} //end if
face = &( *aasworld ).faces[facenum];
//ground faces only
if ( groundfacesonly ) {
if ( !( face->faceflags & ( FACE_GROUND | FACE_LADDER ) ) ) {
continue;
}
} //end if
AAS_ShowFacePolygon( facenum, color, face->frontarea != areanum );
} //end for
} //end of the function AAS_ShowAreaPolygons
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DrawCross( vec3_t origin, float size, int color ) {
int i;
vec3_t start, end;
for ( i = 0; i < 3; i++ )
{
VectorCopy( origin, start );
start[i] += size;
VectorCopy( origin, end );
end[i] -= size;
AAS_DebugLine( start, end, color );
} //end for
} //end of the function AAS_DrawCross
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PrintTravelType( int traveltype ) {
#ifdef DEBUG
char *str;
//
switch ( traveltype )
{
case TRAVEL_INVALID: str = "TRAVEL_INVALID"; break;
case TRAVEL_WALK: str = "TRAVEL_WALK"; break;
case TRAVEL_CROUCH: str = "TRAVEL_CROUCH"; break;
case TRAVEL_BARRIERJUMP: str = "TRAVEL_BARRIERJUMP"; break;
case TRAVEL_JUMP: str = "TRAVEL_JUMP"; break;
case TRAVEL_LADDER: str = "TRAVEL_LADDER"; break;
case TRAVEL_WALKOFFLEDGE: str = "TRAVEL_WALKOFFLEDGE"; break;
case TRAVEL_SWIM: str = "TRAVEL_SWIM"; break;
case TRAVEL_WATERJUMP: str = "TRAVEL_WATERJUMP"; break;
case TRAVEL_TELEPORT: str = "TRAVEL_TELEPORT"; break;
case TRAVEL_ELEVATOR: str = "TRAVEL_ELEVATOR"; break;
case TRAVEL_ROCKETJUMP: str = "TRAVEL_ROCKETJUMP"; break;
case TRAVEL_BFGJUMP: str = "TRAVEL_BFGJUMP"; break;
case TRAVEL_GRAPPLEHOOK: str = "TRAVEL_GRAPPLEHOOK"; break;
case TRAVEL_JUMPPAD: str = "TRAVEL_JUMPPAD"; break;
case TRAVEL_FUNCBOB: str = "TRAVEL_FUNCBOB"; break;
default: str = "UNKNOWN TRAVEL TYPE"; break;
} //end switch
botimport.Print( PRT_MESSAGE, "%s", str );
#endif //DEBUG
} //end of the function AAS_PrintTravelType
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DrawArrow( vec3_t start, vec3_t end, int linecolor, int arrowcolor ) {
vec3_t dir, cross, p1, p2, up = {0, 0, 1};
float dot;
VectorSubtract( end, start, dir );
VectorNormalize( dir );
dot = DotProduct( dir, up );
if ( dot > 0.99 || dot < -0.99 ) {
VectorSet( cross, 1, 0, 0 );
} else { CrossProduct( dir, up, cross );}
VectorMA( end, -6, dir, p1 );
VectorCopy( p1, p2 );
VectorMA( p1, 6, cross, p1 );
VectorMA( p2, -6, cross, p2 );
AAS_DebugLine( start, end, linecolor );
AAS_DebugLine( p1, end, arrowcolor );
AAS_DebugLine( p2, end, arrowcolor );
} //end of the function AAS_DrawArrow
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowReachability( aas_reachability_t *reach ) {
vec3_t dir, cmdmove, velocity;
float speed, zvel;
aas_clientmove_t move;
AAS_ShowAreaPolygons( reach->areanum, 5, qtrue );
//AAS_ShowArea(reach->areanum, qtrue);
AAS_DrawArrow( reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW );
//
if ( reach->traveltype == TRAVEL_JUMP || reach->traveltype == TRAVEL_WALKOFFLEDGE ) {
AAS_HorizontalVelocityForJump( aassettings.sv_jumpvel, reach->start, reach->end, &speed );
//
VectorSubtract( reach->end, reach->start, dir );
dir[2] = 0;
VectorNormalize( dir );
//set the velocity
VectorScale( dir, speed, velocity );
//set the command movement
VectorClear( cmdmove );
cmdmove[2] = aassettings.sv_jumpvel;
//
AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 3, 30, 0.1,
SE_HITGROUND | SE_ENTERWATER | SE_ENTERSLIME |
SE_ENTERLAVA | SE_HITGROUNDDAMAGE, 0, qtrue );
//
if ( reach->traveltype == TRAVEL_JUMP ) {
AAS_JumpReachRunStart( reach, dir );
AAS_DrawCross( dir, 4, LINECOLOR_BLUE );
} //end if
} //end if
else if ( reach->traveltype == TRAVEL_ROCKETJUMP ) {
zvel = AAS_RocketJumpZVelocity( reach->start );
AAS_HorizontalVelocityForJump( zvel, reach->start, reach->end, &speed );
//
VectorSubtract( reach->end, reach->start, dir );
dir[2] = 0;
VectorNormalize( dir );
//get command movement
VectorScale( dir, speed, cmdmove );
VectorSet( velocity, 0, 0, zvel );
//
AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 30, 30, 0.1,
SE_ENTERWATER | SE_ENTERSLIME |
SE_ENTERLAVA | SE_HITGROUNDDAMAGE |
SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue );
} //end else if
else if ( reach->traveltype == TRAVEL_JUMPPAD ) {
VectorSet( cmdmove, 0, 0, 0 );
//
VectorSubtract( reach->end, reach->start, dir );
dir[2] = 0;
VectorNormalize( dir );
//set the velocity
//NOTE: the edgenum is the horizontal velocity
VectorScale( dir, reach->edgenum, velocity );
//NOTE: the facenum is the Z velocity
velocity[2] = reach->facenum;
//
AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 30, 30, 0.1,
SE_ENTERWATER | SE_ENTERSLIME |
SE_ENTERLAVA | SE_HITGROUNDDAMAGE |
SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue );
} //end else if
} //end of the function AAS_ShowReachability
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowReachableAreas( int areanum ) {
aas_areasettings_t *settings;
static aas_reachability_t reach;
static int index, lastareanum;
static float lasttime;
if ( areanum != lastareanum ) {
index = 0;
lastareanum = areanum;
} //end if
settings = &( *aasworld ).areasettings[areanum];
//
if ( !settings->numreachableareas ) {
return;
}
//
if ( index >= settings->numreachableareas ) {
index = 0;
}
//
if ( AAS_Time() - lasttime > 1.5 ) {
memcpy( &reach, &( *aasworld ).reachability[settings->firstreachablearea + index], sizeof( aas_reachability_t ) );
index++;
lasttime = AAS_Time();
AAS_PrintTravelType( reach.traveltype );
botimport.Print( PRT_MESSAGE, "(traveltime: %i)\n", reach.traveltime );
} //end if
AAS_ShowReachability( &reach );
} //end of the function ShowReachableAreas

68
src/botlib/be_aas_debug.h Normal file
View File

@ -0,0 +1,68 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_debug.h
*
* desc: AAS
*
*
*****************************************************************************/
//clear the shown debug lines
void AAS_ClearShownDebugLines( void );
//
void AAS_ClearShownPolygons( void );
//show a debug line
void AAS_DebugLine( vec3_t start, vec3_t end, int color );
//show a permenent line
void AAS_PermanentLine( vec3_t start, vec3_t end, int color );
//show a permanent cross
void AAS_DrawPermanentCross( vec3_t origin, float size, int color );
//draw a cross in the plane
void AAS_DrawPlaneCross( vec3_t point, vec3_t normal, float dist, int type, int color );
//show a bounding box
void AAS_ShowBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs );
//show a face
void AAS_ShowFace( int facenum );
//show an area
void AAS_ShowArea( int areanum, int groundfacesonly );
//
void AAS_ShowAreaPolygons( int areanum, int color, int groundfacesonly );
//draw a cros
void AAS_DrawCross( vec3_t origin, float size, int color );
//print the travel type
void AAS_PrintTravelType( int traveltype );
//draw an arrow
void AAS_DrawArrow( vec3_t start, vec3_t end, int linecolor, int arrowcolor );
//visualize the given reachability
void AAS_ShowReachability( struct aas_reachability_s *reach );
//show the reachable areas from the given area
void AAS_ShowReachableAreas( int areanum );

295
src/botlib/be_aas_def.h Normal file
View File

@ -0,0 +1,295 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_def.h
*
* desc: AAS
*
*
*****************************************************************************/
//debugging on
#define AAS_DEBUG
//#define MAX_CLIENTS 128
//#define MAX_MODELS 256 // these are sent over the net as 8 bits
//#define MAX_SOUNDS 256 // so they cannot be blindly increased
//#define MAX_CONFIGSTRINGS 1024
#define MAX_CONFIGSTRINGS 2048 //----(SA) upped
//#define CS_SCORES 32
//#define CS_MODELS (CS_SCORES+MAX_CLIENTS)
//#define CS_SOUNDS (CS_MODELS+MAX_MODELS)
#define DF_AASENTNUMBER( x ) ( x - ( *aasworlds ).entities )
#define DF_NUMBERAASENT( x ) ( &( *aasworlds ).entities[x] )
#define DF_AASENTCLIENT( x ) ( x - ( *aasworlds ).entities - 1 )
#define DF_CLIENTAASENT( x ) ( &( *aasworlds ).entities[x + 1] )
#ifndef MAX_PATH
#define MAX_PATH MAX_QPATH
#endif
//string index (for model, sound and image index)
typedef struct aas_stringindex_s
{
int numindexes;
char **index;
} aas_stringindex_t;
//structure to link entities to areas and areas to entities
typedef struct aas_link_s
{
int entnum;
int areanum;
struct aas_link_s *next_ent, *prev_ent;
struct aas_link_s *next_area, *prev_area;
} aas_link_t;
//structure to link entities to leaves and leaves to entities
typedef struct bsp_link_s
{
int entnum;
int leafnum;
struct bsp_link_s *next_ent, *prev_ent;
struct bsp_link_s *next_leaf, *prev_leaf;
} bsp_link_t;
typedef struct bsp_entdata_s
{
vec3_t origin;
vec3_t angles;
vec3_t absmins;
vec3_t absmaxs;
int solid;
int modelnum;
} bsp_entdata_t;
//entity
typedef struct aas_entity_s
{
//entity info
aas_entityinfo_t i;
//links into the AAS areas
aas_link_t *areas;
//links into the BSP leaves
bsp_link_t *leaves;
} aas_entity_t;
typedef struct aas_settings_s
{
float sv_friction;
float sv_stopspeed;
float sv_gravity;
float sv_waterfriction;
float sv_watergravity;
float sv_maxvelocity;
float sv_maxwalkvelocity;
float sv_maxcrouchvelocity;
float sv_maxswimvelocity;
float sv_walkaccelerate;
float sv_airaccelerate;
float sv_swimaccelerate;
float sv_maxstep;
float sv_maxsteepness;
float sv_maxwaterjump;
float sv_maxbarrier;
float sv_jumpvel;
qboolean sv_allowladders;
} aas_settings_t;
//routing cache
typedef struct aas_routingcache_s
{
int size; //size of the routing cache
float time; //last time accessed or updated
int cluster; //cluster the cache is for
int areanum; //area the cache is created for
vec3_t origin; //origin within the area
float starttraveltime; //travel time to start with
int travelflags; //combinations of the travel flags
struct aas_routingcache_s *prev, *next;
unsigned char *reachabilities; //reachabilities used for routing
unsigned short int traveltimes[1]; //travel time for every area (variable sized)
} aas_routingcache_t;
//fields for the routing algorithm
typedef struct aas_routingupdate_s
{
int cluster;
int areanum; //area number of the update
vec3_t start; //start point the area was entered
unsigned short int tmptraveltime; //temporary travel time
unsigned short int *areatraveltimes; //travel times within the area
qboolean inlist; //true if the update is in the list
struct aas_routingupdate_s *next;
struct aas_routingupdate_s *prev;
} aas_routingupdate_t;
//reversed reachability link
typedef struct aas_reversedlink_s
{
int linknum; //the aas_areareachability_t
int areanum; //reachable from this area
struct aas_reversedlink_s *next; //next link
} aas_reversedlink_t;
//reversed area reachability
typedef struct aas_reversedreachability_s
{
int numlinks;
aas_reversedlink_t *first;
} aas_reversedreachability_t;
// Ridah, route-tables
#include "be_aas_routetable.h"
// done.
typedef struct aas_s
{
int loaded; //true when an AAS file is loaded
int initialized; //true when AAS has been initialized
int savefile; //set true when file should be saved
int bspchecksum;
//current time
float time;
int numframes;
//name of the aas file
char filename[MAX_PATH];
char mapname[MAX_PATH];
//bounding boxes
int numbboxes;
aas_bbox_t *bboxes;
//vertexes
int numvertexes;
aas_vertex_t *vertexes;
//planes
int numplanes;
aas_plane_t *planes;
//edges
int numedges;
aas_edge_t *edges;
//edge index
int edgeindexsize;
aas_edgeindex_t *edgeindex;
//faces
int numfaces;
aas_face_t *faces;
//face index
int faceindexsize;
aas_faceindex_t *faceindex;
//convex areas
int numareas;
aas_area_t *areas;
//convex area settings
int numareasettings;
aas_areasettings_t *areasettings;
//reachablity list
int reachabilitysize;
aas_reachability_t *reachability;
//nodes of the bsp tree
int numnodes;
aas_node_t *nodes;
//cluster portals
int numportals;
aas_portal_t *portals;
//cluster portal index
int portalindexsize;
aas_portalindex_t *portalindex;
//clusters
int numclusters;
aas_cluster_t *clusters;
//
int reachabilityareas;
float reachabilitytime;
//enities linked in the areas
aas_link_t *linkheap; //heap with link structures
int linkheapsize; //size of the link heap
aas_link_t *freelinks; //first free link
aas_link_t **arealinkedentities; //entities linked into areas
//entities
int maxentities;
int maxclients;
aas_entity_t *entities;
//string indexes
char *configstrings[MAX_CONFIGSTRINGS];
int indexessetup;
//index to retrieve travel flag for a travel type
int travelflagfortype[MAX_TRAVELTYPES];
//routing update
aas_routingupdate_t *areaupdate;
aas_routingupdate_t *portalupdate;
//number of routing updates during a frame (reset every frame)
int frameroutingupdates;
//reversed reachability links
aas_reversedreachability_t *reversedreachability;
//travel times within the areas
unsigned short ***areatraveltimes;
//array of size numclusters with cluster cache
aas_routingcache_t ***clusterareacache;
aas_routingcache_t **portalcache;
//maximum travel time through portals
int *portalmaxtraveltimes;
// Ridah, pointer to Route-Table information
aas_rt_t *routetable;
//hide travel times
unsigned short int *hidetraveltimes;
//vis data
byte *decompressedvis;
int decompressedvisarea;
byte **areavisibility;
// done.
// Ridah, store the area's waypoint for hidepos calculations (center traced downwards)
vec3_t *areawaypoints;
// Ridah, so we can cache the areas that have already been tested for visibility/attackability
byte *visCache;
} aas_t;
#define AASINTERN
#ifndef BSPCINCLUDE
#include "be_aas_main.h"
#include "be_aas_entity.h"
#include "be_aas_sample.h"
#include "be_aas_cluster.h"
#include "be_aas_reach.h"
#include "be_aas_route.h"
#include "be_aas_routealt.h"
#include "be_aas_debug.h"
#include "be_aas_file.h"
#include "be_aas_optimize.h"
#include "be_aas_bsp.h"
#include "be_aas_move.h"
// Ridah, route-tables
#include "be_aas_routetable.h"
#endif //BSPCINCLUDE

499
src/botlib/be_aas_entity.c Normal file
View File

@ -0,0 +1,499 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_entity.c
*
* desc: AAS entities
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_utils.h"
#include "l_log.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
#define MASK_SOLID CONTENTS_PLAYERCLIP
// Ridah, always use the default world for entities
extern aas_t aasworlds[MAX_AAS_WORLDS];
aas_t *defaultaasworld = aasworlds;
//FIXME: these might change
enum {
ET_GENERAL,
ET_PLAYER,
ET_ITEM,
ET_MISSILE,
ET_MOVER
};
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_UpdateEntity( int entnum, bot_entitystate_t *state ) {
int relink;
aas_entity_t *ent;
vec3_t absmins, absmaxs;
if ( !( *defaultaasworld ).loaded ) {
botimport.Print( PRT_MESSAGE, "AAS_UpdateEntity: not loaded\n" );
return BLERR_NOAASFILE;
} //end if
ent = &( *defaultaasworld ).entities[entnum];
ent->i.update_time = AAS_Time() - ent->i.ltime;
ent->i.type = state->type;
ent->i.flags = state->flags;
ent->i.ltime = AAS_Time();
VectorCopy( ent->i.origin, ent->i.lastvisorigin );
VectorCopy( state->old_origin, ent->i.old_origin );
ent->i.solid = state->solid;
ent->i.groundent = state->groundent;
ent->i.modelindex = state->modelindex;
ent->i.modelindex2 = state->modelindex2;
ent->i.frame = state->frame;
//ent->i.event = state->event;
ent->i.eventParm = state->eventParm;
ent->i.powerups = state->powerups;
ent->i.weapon = state->weapon;
ent->i.legsAnim = state->legsAnim;
ent->i.torsoAnim = state->torsoAnim;
// ent->i.weapAnim = state->weapAnim; //----(SA)
//----(SA) didn't want to comment in as I wasn't sure of any implications of changing the aas_entityinfo_t and bot_entitystate_t structures.
//number of the entity
ent->i.number = entnum;
//updated so set valid flag
ent->i.valid = qtrue;
//link everything the first frame
if ( ( *defaultaasworld ).numframes == 1 ) {
relink = qtrue;
} else { relink = qfalse;}
//
if ( ent->i.solid == SOLID_BSP ) {
//if the angles of the model changed
if ( !VectorCompare( state->angles, ent->i.angles ) ) {
VectorCopy( state->angles, ent->i.angles );
relink = qtrue;
} //end if
//get the mins and maxs of the model
//FIXME: rotate mins and maxs
AAS_BSPModelMinsMaxsOrigin( ent->i.modelindex, ent->i.angles, ent->i.mins, ent->i.maxs, NULL );
} //end if
else if ( ent->i.solid == SOLID_BBOX ) {
//if the bounding box size changed
if ( !VectorCompare( state->mins, ent->i.mins ) ||
!VectorCompare( state->maxs, ent->i.maxs ) ) {
VectorCopy( state->mins, ent->i.mins );
VectorCopy( state->maxs, ent->i.maxs );
relink = qtrue;
} //end if
} //end if
//if the origin changed
if ( !VectorCompare( state->origin, ent->i.origin ) ) {
VectorCopy( state->origin, ent->i.origin );
relink = qtrue;
} //end if
//if the entity should be relinked
if ( relink ) {
//don't link the world model
if ( entnum != ENTITYNUM_WORLD ) {
//absolute mins and maxs
VectorAdd( ent->i.mins, ent->i.origin, absmins );
VectorAdd( ent->i.maxs, ent->i.origin, absmaxs );
//unlink the entity
AAS_UnlinkFromAreas( ent->areas );
//relink the entity to the AAS areas (use the larges bbox)
ent->areas = AAS_LinkEntityClientBBox( absmins, absmaxs, entnum, PRESENCE_NORMAL );
//unlink the entity from the BSP leaves
AAS_UnlinkFromBSPLeaves( ent->leaves );
//link the entity to the world BSP tree
ent->leaves = AAS_BSPLinkEntity( absmins, absmaxs, entnum, 0 );
} //end if
} //end if
return BLERR_NOERROR;
} //end of the function AAS_UpdateEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_EntityInfo( int entnum, aas_entityinfo_t *info ) {
if ( !( *defaultaasworld ).initialized ) {
botimport.Print( PRT_FATAL, "AAS_EntityInfo: (*defaultaasworld) not initialized\n" );
memset( info, 0, sizeof( aas_entityinfo_t ) );
return;
} //end if
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntityInfo: entnum %d out of range\n", entnum );
memset( info, 0, sizeof( aas_entityinfo_t ) );
return;
} //end if
memcpy( info, &( *defaultaasworld ).entities[entnum].i, sizeof( aas_entityinfo_t ) );
} //end of the function AAS_EntityInfo
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_EntityOrigin( int entnum, vec3_t origin ) {
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntityOrigin: entnum %d out of range\n", entnum );
VectorClear( origin );
return;
} //end if
VectorCopy( ( *defaultaasworld ).entities[entnum].i.origin, origin );
} //end of the function AAS_EntityOrigin
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityModelindex( int entnum ) {
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntityModelindex: entnum %d out of range\n", entnum );
return 0;
} //end if
return ( *defaultaasworld ).entities[entnum].i.modelindex;
} //end of the function AAS_EntityModelindex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityType( int entnum ) {
if ( !( *defaultaasworld ).initialized ) {
return 0;
}
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntityType: entnum %d out of range\n", entnum );
return 0;
} //end if
return ( *defaultaasworld ).entities[entnum].i.type;
} //end of the AAS_EntityType
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityModelNum( int entnum ) {
if ( !( *defaultaasworld ).initialized ) {
return 0;
}
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntityModelNum: entnum %d out of range\n", entnum );
return 0;
} //end if
return ( *defaultaasworld ).entities[entnum].i.modelindex;
} //end of the function AAS_EntityModelNum
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_OriginOfEntityWithModelNum( int modelnum, vec3_t origin ) {
int i;
aas_entity_t *ent;
for ( i = 0; i < ( *defaultaasworld ).maxentities; i++ )
{
ent = &( *defaultaasworld ).entities[i];
if ( ent->i.type == ET_MOVER ) {
if ( ent->i.modelindex == modelnum ) {
VectorCopy( ent->i.origin, origin );
return qtrue;
} //end if
}
} //end for
return qfalse;
} //end of the function AAS_OriginOfEntityWithModelNum
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_EntitySize( int entnum, vec3_t mins, vec3_t maxs ) {
aas_entity_t *ent;
if ( !( *defaultaasworld ).initialized ) {
return;
}
if ( entnum < 0 || entnum >= ( *defaultaasworld ).maxentities ) {
botimport.Print( PRT_FATAL, "AAS_EntitySize: entnum %d out of range\n", entnum );
return;
} //end if
ent = &( *defaultaasworld ).entities[entnum];
VectorCopy( ent->i.mins, mins );
VectorCopy( ent->i.maxs, maxs );
} //end of the function AAS_EntitySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_EntityBSPData( int entnum, bsp_entdata_t *entdata ) {
aas_entity_t *ent;
ent = &( *defaultaasworld ).entities[entnum];
VectorCopy( ent->i.origin, entdata->origin );
VectorCopy( ent->i.angles, entdata->angles );
VectorAdd( ent->i.origin, ent->i.mins, entdata->absmins );
VectorAdd( ent->i.origin, ent->i.maxs, entdata->absmaxs );
entdata->solid = ent->i.solid;
entdata->modelnum = ent->i.modelindex - 1;
} //end of the function AAS_EntityBSPData
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ResetEntityLinks( void ) {
int i;
for ( i = 0; i < ( *defaultaasworld ).maxentities; i++ )
{
( *defaultaasworld ).entities[i].areas = NULL;
( *defaultaasworld ).entities[i].leaves = NULL;
} //end for
} //end of the function AAS_ResetEntityLinks
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InvalidateEntities( void ) {
int i;
for ( i = 0; i < ( *defaultaasworld ).maxentities; i++ )
{
( *defaultaasworld ).entities[i].i.valid = qfalse;
( *defaultaasworld ).entities[i].i.number = i;
} //end for
} //end of the function AAS_InvalidateEntities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_NearestEntity( vec3_t origin, int modelindex ) {
int i, bestentnum;
float dist, bestdist;
aas_entity_t *ent;
vec3_t dir;
bestentnum = 0;
bestdist = 99999;
for ( i = 0; i < ( *defaultaasworld ).maxentities; i++ )
{
ent = &( *defaultaasworld ).entities[i];
if ( ent->i.modelindex != modelindex ) {
continue;
}
VectorSubtract( ent->i.origin, origin, dir );
if ( abs( dir[0] ) < 40 ) {
if ( abs( dir[1] ) < 40 ) {
dist = VectorLength( dir );
if ( dist < bestdist ) {
bestdist = dist;
bestentnum = i;
} //end if
} //end if
} //end if
} //end for
return bestentnum;
} //end of the function AAS_NearestEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_BestReachableEntityArea( int entnum ) {
aas_entity_t *ent;
ent = &( *defaultaasworld ).entities[entnum];
return AAS_BestReachableLinkArea( ent->areas );
} //end of the function AAS_BestReachableEntityArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_NextEntity( int entnum ) {
if ( !( *defaultaasworld ).loaded ) {
return 0;
}
if ( entnum < 0 ) {
entnum = -1;
}
while ( ++entnum < ( *defaultaasworld ).maxentities )
{
if ( ( *defaultaasworld ).entities[entnum].i.valid ) {
return entnum;
}
} //end while
return 0;
} //end of the function AAS_NextEntity
// Ridah, used to find out if there is an entity touching the given area, if so, try and avoid it
/*
============
AAS_EntityInArea
============
*/
int AAS_IsEntityInArea( int entnumIgnore, int entnumIgnore2, int areanum ) {
aas_link_t *link;
aas_entity_t *ent;
// int i;
// RF, not functional (doesnt work with multiple areas)
return qfalse;
for ( link = ( *aasworld ).arealinkedentities[areanum]; link; link = link->next_ent )
{
//ignore the pass entity
if ( link->entnum == entnumIgnore ) {
continue;
}
if ( link->entnum == entnumIgnore2 ) {
continue;
}
//
ent = &( *defaultaasworld ).entities[link->entnum];
if ( !ent->i.valid ) {
continue;
}
if ( !ent->i.solid ) {
continue;
}
return qtrue;
}
/*
ent = (*defaultaasworld).entities;
for (i = 0; i < (*defaultaasworld).maxclients; i++, ent++)
{
if (!ent->i.valid)
continue;
if (!ent->i.solid)
continue;
if (i == entnumIgnore)
continue;
if (i == entnumIgnore2)
continue;
for (link = ent->areas; link; link = link->next_area)
{
if (link->areanum == areanum)
{
return qtrue;
} //end if
} //end for
}
*/
return qfalse;
}
/*
=============
AAS_SetAASBlockingEntity
=============
*/
int AAS_EnableRoutingArea( int areanum, int enable );
void AAS_SetAASBlockingEntity( vec3_t absmin, vec3_t absmax, qboolean blocking ) {
int areas[128];
int numareas, i, w;
//
// check for resetting AAS blocking
if ( VectorCompare( absmin, absmax ) && blocking < 0 ) {
for ( w = 0; w < MAX_AAS_WORLDS; w++ ) {
AAS_SetCurrentWorld( w );
//
if ( !( *aasworld ).loaded ) {
continue;
}
// now clear blocking status
for ( i = 1; i < ( *aasworld ).numareas; i++ ) {
AAS_EnableRoutingArea( i, qtrue );
}
}
//
return;
}
//
for ( w = 0; w < MAX_AAS_WORLDS; w++ ) {
AAS_SetCurrentWorld( w );
//
if ( !( *aasworld ).loaded ) {
continue;
}
// grab the list of areas
numareas = AAS_BBoxAreas( absmin, absmax, areas, 128 );
// now set their blocking status
for ( i = 0; i < numareas; i++ ) {
AAS_EnableRoutingArea( areas[i], !blocking );
}
}
}

View File

@ -0,0 +1,68 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_entity.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//invalidates all entity infos
void AAS_InvalidateEntities( void );
//resets the entity AAS and BSP links (sets areas and leaves pointers to NULL)
void AAS_ResetEntityLinks( void );
//updates an entity
int AAS_UpdateEntity( int ent, bot_entitystate_t *state );
//gives the entity data used for collision detection
void AAS_EntityBSPData( int entnum, bsp_entdata_t *entdata );
#endif //AASINTERN
//returns the size of the entity bounding box in mins and maxs
void AAS_EntitySize( int entnum, vec3_t mins, vec3_t maxs );
//returns the BSP model number of the entity
int AAS_EntityModelNum( int entnum );
//returns the origin of an entity with the given model number
int AAS_OriginOfEntityWithModelNum( int modelnum, vec3_t origin );
//returns the best reachable area the entity is situated in
int AAS_BestReachableEntityArea( int entnum );
//returns the info of the given entity
void AAS_EntityInfo( int entnum, aas_entityinfo_t *info );
//returns the next entity
int AAS_NextEntity( int entnum );
//returns the origin of the entity
void AAS_EntityOrigin( int entnum, vec3_t origin );
//returns the entity type
int AAS_EntityType( int entnum );
//returns the model index of the entity
int AAS_EntityModelindex( int entnum );
// Ridah
int AAS_IsEntityInArea( int entnumIgnore, int entnumIgnore2, int areanum );

662
src/botlib/be_aas_file.c Normal file
View File

@ -0,0 +1,662 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_file.c
*
* desc: AAS file loading/writing
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_libvar.h"
#include "l_utils.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
//#define AASFILEDEBUG
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SwapAASData( void ) {
int i, j;
// Ridah, no need to do anything if this OS doesn't need byte swapping
if ( LittleLong( 1 ) == 1 ) {
return;
}
// done.
//bounding boxes
for ( i = 0; i < ( *aasworld ).numbboxes; i++ )
{
( *aasworld ).bboxes[i].presencetype = LittleLong( ( *aasworld ).bboxes[i].presencetype );
( *aasworld ).bboxes[i].flags = LittleLong( ( *aasworld ).bboxes[i].flags );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).bboxes[i].mins[j] = LittleFloat( ( *aasworld ).bboxes[i].mins[j] );
( *aasworld ).bboxes[i].maxs[j] = LittleFloat( ( *aasworld ).bboxes[i].maxs[j] );
} //end for
} //end for
//vertexes
for ( i = 0; i < ( *aasworld ).numvertexes; i++ )
{
for ( j = 0; j < 3; j++ )
( *aasworld ).vertexes[i][j] = LittleFloat( ( *aasworld ).vertexes[i][j] );
} //end for
//planes
for ( i = 0; i < ( *aasworld ).numplanes; i++ )
{
for ( j = 0; j < 3; j++ )
( *aasworld ).planes[i].normal[j] = LittleFloat( ( *aasworld ).planes[i].normal[j] );
( *aasworld ).planes[i].dist = LittleFloat( ( *aasworld ).planes[i].dist );
( *aasworld ).planes[i].type = LittleLong( ( *aasworld ).planes[i].type );
} //end for
//edges
for ( i = 0; i < ( *aasworld ).numedges; i++ )
{
( *aasworld ).edges[i].v[0] = LittleLong( ( *aasworld ).edges[i].v[0] );
( *aasworld ).edges[i].v[1] = LittleLong( ( *aasworld ).edges[i].v[1] );
} //end for
//edgeindex
for ( i = 0; i < ( *aasworld ).edgeindexsize; i++ )
{
( *aasworld ).edgeindex[i] = LittleLong( ( *aasworld ).edgeindex[i] );
} //end for
//faces
for ( i = 0; i < ( *aasworld ).numfaces; i++ )
{
( *aasworld ).faces[i].planenum = LittleLong( ( *aasworld ).faces[i].planenum );
( *aasworld ).faces[i].faceflags = LittleLong( ( *aasworld ).faces[i].faceflags );
( *aasworld ).faces[i].numedges = LittleLong( ( *aasworld ).faces[i].numedges );
( *aasworld ).faces[i].firstedge = LittleLong( ( *aasworld ).faces[i].firstedge );
( *aasworld ).faces[i].frontarea = LittleLong( ( *aasworld ).faces[i].frontarea );
( *aasworld ).faces[i].backarea = LittleLong( ( *aasworld ).faces[i].backarea );
} //end for
//face index
for ( i = 0; i < ( *aasworld ).faceindexsize; i++ )
{
( *aasworld ).faceindex[i] = LittleLong( ( *aasworld ).faceindex[i] );
} //end for
//convex areas
for ( i = 0; i < ( *aasworld ).numareas; i++ )
{
( *aasworld ).areas[i].areanum = LittleLong( ( *aasworld ).areas[i].areanum );
( *aasworld ).areas[i].numfaces = LittleLong( ( *aasworld ).areas[i].numfaces );
( *aasworld ).areas[i].firstface = LittleLong( ( *aasworld ).areas[i].firstface );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).areas[i].mins[j] = LittleFloat( ( *aasworld ).areas[i].mins[j] );
( *aasworld ).areas[i].maxs[j] = LittleFloat( ( *aasworld ).areas[i].maxs[j] );
( *aasworld ).areas[i].center[j] = LittleFloat( ( *aasworld ).areas[i].center[j] );
} //end for
} //end for
//area settings
for ( i = 0; i < ( *aasworld ).numareasettings; i++ )
{
( *aasworld ).areasettings[i].contents = LittleLong( ( *aasworld ).areasettings[i].contents );
( *aasworld ).areasettings[i].areaflags = LittleLong( ( *aasworld ).areasettings[i].areaflags );
( *aasworld ).areasettings[i].presencetype = LittleLong( ( *aasworld ).areasettings[i].presencetype );
( *aasworld ).areasettings[i].cluster = LittleLong( ( *aasworld ).areasettings[i].cluster );
( *aasworld ).areasettings[i].clusterareanum = LittleLong( ( *aasworld ).areasettings[i].clusterareanum );
( *aasworld ).areasettings[i].numreachableareas = LittleLong( ( *aasworld ).areasettings[i].numreachableareas );
( *aasworld ).areasettings[i].firstreachablearea = LittleLong( ( *aasworld ).areasettings[i].firstreachablearea );
( *aasworld ).areasettings[i].groundsteepness = LittleLong( ( *aasworld ).areasettings[i].groundsteepness );
} //end for
//area reachability
for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ )
{
( *aasworld ).reachability[i].areanum = LittleLong( ( *aasworld ).reachability[i].areanum );
( *aasworld ).reachability[i].facenum = LittleLong( ( *aasworld ).reachability[i].facenum );
( *aasworld ).reachability[i].edgenum = LittleLong( ( *aasworld ).reachability[i].edgenum );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).reachability[i].start[j] = LittleFloat( ( *aasworld ).reachability[i].start[j] );
( *aasworld ).reachability[i].end[j] = LittleFloat( ( *aasworld ).reachability[i].end[j] );
} //end for
( *aasworld ).reachability[i].traveltype = LittleLong( ( *aasworld ).reachability[i].traveltype );
( *aasworld ).reachability[i].traveltime = LittleShort( ( *aasworld ).reachability[i].traveltime );
} //end for
//nodes
for ( i = 0; i < ( *aasworld ).numnodes; i++ )
{
( *aasworld ).nodes[i].planenum = LittleLong( ( *aasworld ).nodes[i].planenum );
( *aasworld ).nodes[i].children[0] = LittleLong( ( *aasworld ).nodes[i].children[0] );
( *aasworld ).nodes[i].children[1] = LittleLong( ( *aasworld ).nodes[i].children[1] );
} //end for
//cluster portals
for ( i = 0; i < ( *aasworld ).numportals; i++ )
{
( *aasworld ).portals[i].areanum = LittleLong( ( *aasworld ).portals[i].areanum );
( *aasworld ).portals[i].frontcluster = LittleLong( ( *aasworld ).portals[i].frontcluster );
( *aasworld ).portals[i].backcluster = LittleLong( ( *aasworld ).portals[i].backcluster );
( *aasworld ).portals[i].clusterareanum[0] = LittleLong( ( *aasworld ).portals[i].clusterareanum[0] );
( *aasworld ).portals[i].clusterareanum[1] = LittleLong( ( *aasworld ).portals[i].clusterareanum[1] );
} //end for
//cluster portal index
for ( i = 0; i < ( *aasworld ).portalindexsize; i++ )
{
( *aasworld ).portalindex[i] = LittleLong( ( *aasworld ).portalindex[i] );
} //end for
//cluster
for ( i = 0; i < ( *aasworld ).numclusters; i++ )
{
( *aasworld ).clusters[i].numareas = LittleLong( ( *aasworld ).clusters[i].numareas );
( *aasworld ).clusters[i].numreachabilityareas = LittleLong( ( *aasworld ).clusters[i].numreachabilityareas );
( *aasworld ).clusters[i].numportals = LittleLong( ( *aasworld ).clusters[i].numportals );
( *aasworld ).clusters[i].firstportal = LittleLong( ( *aasworld ).clusters[i].firstportal );
} //end for
} //end of the function AAS_SwapAASData
//===========================================================================
// dump the current loaded aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DumpAASData( void ) {
( *aasworld ).numbboxes = 0;
if ( ( *aasworld ).bboxes ) {
FreeMemory( ( *aasworld ).bboxes );
}
( *aasworld ).bboxes = NULL;
( *aasworld ).numvertexes = 0;
if ( ( *aasworld ).vertexes ) {
FreeMemory( ( *aasworld ).vertexes );
}
( *aasworld ).vertexes = NULL;
( *aasworld ).numplanes = 0;
if ( ( *aasworld ).planes ) {
FreeMemory( ( *aasworld ).planes );
}
( *aasworld ).planes = NULL;
( *aasworld ).numedges = 0;
if ( ( *aasworld ).edges ) {
FreeMemory( ( *aasworld ).edges );
}
( *aasworld ).edges = NULL;
( *aasworld ).edgeindexsize = 0;
if ( ( *aasworld ).edgeindex ) {
FreeMemory( ( *aasworld ).edgeindex );
}
( *aasworld ).edgeindex = NULL;
( *aasworld ).numfaces = 0;
if ( ( *aasworld ).faces ) {
FreeMemory( ( *aasworld ).faces );
}
( *aasworld ).faces = NULL;
( *aasworld ).faceindexsize = 0;
if ( ( *aasworld ).faceindex ) {
FreeMemory( ( *aasworld ).faceindex );
}
( *aasworld ).faceindex = NULL;
( *aasworld ).numareas = 0;
if ( ( *aasworld ).areas ) {
FreeMemory( ( *aasworld ).areas );
}
( *aasworld ).areas = NULL;
( *aasworld ).numareasettings = 0;
if ( ( *aasworld ).areasettings ) {
FreeMemory( ( *aasworld ).areasettings );
}
( *aasworld ).areasettings = NULL;
( *aasworld ).reachabilitysize = 0;
if ( ( *aasworld ).reachability ) {
FreeMemory( ( *aasworld ).reachability );
}
( *aasworld ).reachability = NULL;
( *aasworld ).numnodes = 0;
if ( ( *aasworld ).nodes ) {
FreeMemory( ( *aasworld ).nodes );
}
( *aasworld ).nodes = NULL;
( *aasworld ).numportals = 0;
if ( ( *aasworld ).portals ) {
FreeMemory( ( *aasworld ).portals );
}
( *aasworld ).portals = NULL;
( *aasworld ).numportals = 0;
if ( ( *aasworld ).portalindex ) {
FreeMemory( ( *aasworld ).portalindex );
}
( *aasworld ).portalindex = NULL;
( *aasworld ).portalindexsize = 0;
if ( ( *aasworld ).clusters ) {
FreeMemory( ( *aasworld ).clusters );
}
( *aasworld ).clusters = NULL;
( *aasworld ).numclusters = 0;
//
( *aasworld ).loaded = qfalse;
( *aasworld ).initialized = qfalse;
( *aasworld ).savefile = qfalse;
} //end of the function AAS_DumpAASData
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef AASFILEDEBUG
void AAS_FileInfo( void ) {
int i, n, optimized;
botimport.Print( PRT_MESSAGE, "version = %d\n", AASVERSION );
botimport.Print( PRT_MESSAGE, "numvertexes = %d\n", ( *aasworld ).numvertexes );
botimport.Print( PRT_MESSAGE, "numplanes = %d\n", ( *aasworld ).numplanes );
botimport.Print( PRT_MESSAGE, "numedges = %d\n", ( *aasworld ).numedges );
botimport.Print( PRT_MESSAGE, "edgeindexsize = %d\n", ( *aasworld ).edgeindexsize );
botimport.Print( PRT_MESSAGE, "numfaces = %d\n", ( *aasworld ).numfaces );
botimport.Print( PRT_MESSAGE, "faceindexsize = %d\n", ( *aasworld ).faceindexsize );
botimport.Print( PRT_MESSAGE, "numareas = %d\n", ( *aasworld ).numareas );
botimport.Print( PRT_MESSAGE, "numareasettings = %d\n", ( *aasworld ).numareasettings );
botimport.Print( PRT_MESSAGE, "reachabilitysize = %d\n", ( *aasworld ).reachabilitysize );
botimport.Print( PRT_MESSAGE, "numnodes = %d\n", ( *aasworld ).numnodes );
botimport.Print( PRT_MESSAGE, "numportals = %d\n", ( *aasworld ).numportals );
botimport.Print( PRT_MESSAGE, "portalindexsize = %d\n", ( *aasworld ).portalindexsize );
botimport.Print( PRT_MESSAGE, "numclusters = %d\n", ( *aasworld ).numclusters );
//
for ( n = 0, i = 0; i < ( *aasworld ).numareasettings; i++ )
{
if ( ( *aasworld ).areasettings[i].areaflags & AREA_GROUNDED ) {
n++;
}
} //end for
botimport.Print( PRT_MESSAGE, "num grounded areas = %d\n", n );
//
botimport.Print( PRT_MESSAGE, "planes size %d bytes\n", ( *aasworld ).numplanes * sizeof( aas_plane_t ) );
botimport.Print( PRT_MESSAGE, "areas size %d bytes\n", ( *aasworld ).numareas * sizeof( aas_area_t ) );
botimport.Print( PRT_MESSAGE, "areasettings size %d bytes\n", ( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) );
botimport.Print( PRT_MESSAGE, "nodes size %d bytes\n", ( *aasworld ).numnodes * sizeof( aas_node_t ) );
botimport.Print( PRT_MESSAGE, "reachability size %d bytes\n", ( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) );
botimport.Print( PRT_MESSAGE, "portals size %d bytes\n", ( *aasworld ).numportals * sizeof( aas_portal_t ) );
botimport.Print( PRT_MESSAGE, "clusters size %d bytes\n", ( *aasworld ).numclusters * sizeof( aas_cluster_t ) );
optimized = ( *aasworld ).numplanes * sizeof( aas_plane_t ) +
( *aasworld ).numareas * sizeof( aas_area_t ) +
( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) +
( *aasworld ).numnodes * sizeof( aas_node_t ) +
( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) +
( *aasworld ).numportals * sizeof( aas_portal_t ) +
( *aasworld ).numclusters * sizeof( aas_cluster_t );
botimport.Print( PRT_MESSAGE, "optimzed size %d KB\n", optimized >> 10 );
} //end of the function AAS_FileInfo
#endif //AASFILEDEBUG
//===========================================================================
// allocate memory and read a lump of a AAS file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_LoadAASLump( fileHandle_t fp, int offset, int length, int *lastoffset ) {
char *buf;
//
if ( !length ) {
return NULL;
}
//seek to the data
if ( offset != *lastoffset ) {
botimport.Print( PRT_WARNING, "AAS file not sequentially read\n" );
if ( botimport.FS_Seek( fp, offset, FS_SEEK_SET ) ) {
AAS_Error( "can't seek to aas lump\n" );
AAS_DumpAASData();
botimport.FS_FCloseFile( fp );
return 0;
} //end if
} //end if
//allocate memory
buf = (char *) GetClearedHunkMemory( length + 1 );
//read the data
if ( length ) {
botimport.FS_Read( buf, length, fp );
*lastoffset += length;
} //end if
return buf;
} //end of the function AAS_LoadAASLump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DData( unsigned char *data, int size ) {
int i;
for ( i = 0; i < size; i++ )
{
data[i] ^= (unsigned char) i * 119;
} //end for
} //end of the function AAS_DData
//===========================================================================
// load an aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_LoadAASFile( char *filename ) {
fileHandle_t fp;
aas_header_t header;
int offset, length, lastoffset;
botimport.Print( PRT_MESSAGE, "trying to load %s\n", filename );
//dump current loaded aas file
AAS_DumpAASData();
//open the file
botimport.FS_FOpenFile( filename, &fp, FS_READ );
if ( !fp ) {
AAS_Error( "can't open %s\n", filename );
return BLERR_CANNOTOPENAASFILE;
} //end if
//read the header
botimport.FS_Read( &header, sizeof( aas_header_t ), fp );
lastoffset = sizeof( aas_header_t );
//check header identification
header.ident = LittleLong( header.ident );
if ( header.ident != AASID ) {
AAS_Error( "%s is not an AAS file\n", filename );
botimport.FS_FCloseFile( fp );
return BLERR_WRONGAASFILEID;
} //end if
//check the version
header.version = LittleLong( header.version );
//
if ( header.version != AASVERSION ) {
AAS_Error( "aas file %s is version %i, not %i\n", filename, header.version, AASVERSION );
botimport.FS_FCloseFile( fp );
return BLERR_WRONGAASFILEVERSION;
} //end if
//
if ( header.version == AASVERSION ) {
AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 );
} //end if
//
( *aasworld ).bspchecksum = atoi( LibVarGetString( "sv_mapChecksum" ) );
if ( LittleLong( header.bspchecksum ) != ( *aasworld ).bspchecksum ) {
AAS_Error( "aas file %s is out of date\n", filename );
botimport.FS_FCloseFile( fp );
return BLERR_WRONGAASFILEVERSION;
} //end if
//load the lumps:
//bounding boxes
offset = LittleLong( header.lumps[AASLUMP_BBOXES].fileofs );
length = LittleLong( header.lumps[AASLUMP_BBOXES].filelen );
( *aasworld ).bboxes = (aas_bbox_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numbboxes = length / sizeof( aas_bbox_t );
if ( ( *aasworld ).numbboxes && !( *aasworld ).bboxes ) {
return BLERR_CANNOTREADAASLUMP;
}
//vertexes
offset = LittleLong( header.lumps[AASLUMP_VERTEXES].fileofs );
length = LittleLong( header.lumps[AASLUMP_VERTEXES].filelen );
( *aasworld ).vertexes = (aas_vertex_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numvertexes = length / sizeof( aas_vertex_t );
if ( ( *aasworld ).numvertexes && !( *aasworld ).vertexes ) {
return BLERR_CANNOTREADAASLUMP;
}
//planes
offset = LittleLong( header.lumps[AASLUMP_PLANES].fileofs );
length = LittleLong( header.lumps[AASLUMP_PLANES].filelen );
( *aasworld ).planes = (aas_plane_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numplanes = length / sizeof( aas_plane_t );
if ( ( *aasworld ).numplanes && !( *aasworld ).planes ) {
return BLERR_CANNOTREADAASLUMP;
}
//edges
offset = LittleLong( header.lumps[AASLUMP_EDGES].fileofs );
length = LittleLong( header.lumps[AASLUMP_EDGES].filelen );
( *aasworld ).edges = (aas_edge_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numedges = length / sizeof( aas_edge_t );
if ( ( *aasworld ).numedges && !( *aasworld ).edges ) {
return BLERR_CANNOTREADAASLUMP;
}
//edgeindex
offset = LittleLong( header.lumps[AASLUMP_EDGEINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_EDGEINDEX].filelen );
( *aasworld ).edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).edgeindexsize = length / sizeof( aas_edgeindex_t );
if ( ( *aasworld ).edgeindexsize && !( *aasworld ).edgeindex ) {
return BLERR_CANNOTREADAASLUMP;
}
//faces
offset = LittleLong( header.lumps[AASLUMP_FACES].fileofs );
length = LittleLong( header.lumps[AASLUMP_FACES].filelen );
( *aasworld ).faces = (aas_face_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numfaces = length / sizeof( aas_face_t );
if ( ( *aasworld ).numfaces && !( *aasworld ).faces ) {
return BLERR_CANNOTREADAASLUMP;
}
//faceindex
offset = LittleLong( header.lumps[AASLUMP_FACEINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_FACEINDEX].filelen );
( *aasworld ).faceindex = (aas_faceindex_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).faceindexsize = length / sizeof( int );
if ( ( *aasworld ).faceindexsize && !( *aasworld ).faceindex ) {
return BLERR_CANNOTREADAASLUMP;
}
//convex areas
offset = LittleLong( header.lumps[AASLUMP_AREAS].fileofs );
length = LittleLong( header.lumps[AASLUMP_AREAS].filelen );
( *aasworld ).areas = (aas_area_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numareas = length / sizeof( aas_area_t );
if ( ( *aasworld ).numareas && !( *aasworld ).areas ) {
return BLERR_CANNOTREADAASLUMP;
}
//area settings
offset = LittleLong( header.lumps[AASLUMP_AREASETTINGS].fileofs );
length = LittleLong( header.lumps[AASLUMP_AREASETTINGS].filelen );
( *aasworld ).areasettings = (aas_areasettings_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numareasettings = length / sizeof( aas_areasettings_t );
if ( ( *aasworld ).numareasettings && !( *aasworld ).areasettings ) {
return BLERR_CANNOTREADAASLUMP;
}
//reachability list
offset = LittleLong( header.lumps[AASLUMP_REACHABILITY].fileofs );
length = LittleLong( header.lumps[AASLUMP_REACHABILITY].filelen );
( *aasworld ).reachability = (aas_reachability_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).reachabilitysize = length / sizeof( aas_reachability_t );
if ( ( *aasworld ).reachabilitysize && !( *aasworld ).reachability ) {
return BLERR_CANNOTREADAASLUMP;
}
//nodes
offset = LittleLong( header.lumps[AASLUMP_NODES].fileofs );
length = LittleLong( header.lumps[AASLUMP_NODES].filelen );
( *aasworld ).nodes = (aas_node_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numnodes = length / sizeof( aas_node_t );
if ( ( *aasworld ).numnodes && !( *aasworld ).nodes ) {
return BLERR_CANNOTREADAASLUMP;
}
//cluster portals
offset = LittleLong( header.lumps[AASLUMP_PORTALS].fileofs );
length = LittleLong( header.lumps[AASLUMP_PORTALS].filelen );
( *aasworld ).portals = (aas_portal_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numportals = length / sizeof( aas_portal_t );
if ( ( *aasworld ).numportals && !( *aasworld ).portals ) {
return BLERR_CANNOTREADAASLUMP;
}
//cluster portal index
offset = LittleLong( header.lumps[AASLUMP_PORTALINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_PORTALINDEX].filelen );
( *aasworld ).portalindex = (aas_portalindex_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).portalindexsize = length / sizeof( aas_portalindex_t );
if ( ( *aasworld ).portalindexsize && !( *aasworld ).portalindex ) {
return BLERR_CANNOTREADAASLUMP;
}
//clusters
offset = LittleLong( header.lumps[AASLUMP_CLUSTERS].fileofs );
length = LittleLong( header.lumps[AASLUMP_CLUSTERS].filelen );
( *aasworld ).clusters = (aas_cluster_t *) AAS_LoadAASLump( fp, offset, length, &lastoffset );
( *aasworld ).numclusters = length / sizeof( aas_cluster_t );
if ( ( *aasworld ).numclusters && !( *aasworld ).clusters ) {
return BLERR_CANNOTREADAASLUMP;
}
//swap everything
AAS_SwapAASData();
//aas file is loaded
( *aasworld ).loaded = qtrue;
//close the file
botimport.FS_FCloseFile( fp );
//
#ifdef AASFILEDEBUG
AAS_FileInfo();
#endif //AASFILEDEBUG
//
return BLERR_NOERROR;
} //end of the function AAS_LoadAASFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
static int AAS_WriteAASLump_offset;
int AAS_WriteAASLump( fileHandle_t fp, aas_header_t *h, int lumpnum, void *data, int length ) {
aas_lump_t *lump;
lump = &h->lumps[lumpnum];
lump->fileofs = LittleLong( AAS_WriteAASLump_offset ); //LittleLong(ftell(fp));
lump->filelen = LittleLong( length );
if ( length > 0 ) {
botimport.FS_Write( data, length, fp );
} //end if
AAS_WriteAASLump_offset += length;
return qtrue;
} //end of the function AAS_WriteAASLump
//===========================================================================
// aas data is useless after writing to file because it is byte swapped
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_WriteAASFile( char *filename ) {
aas_header_t header;
fileHandle_t fp;
botimport.Print( PRT_MESSAGE, "writing %s\n", filename );
//swap the aas data
AAS_SwapAASData();
//initialize the file header
memset( &header, 0, sizeof( aas_header_t ) );
header.ident = LittleLong( AASID );
header.version = LittleLong( AASVERSION );
header.bspchecksum = LittleLong( ( *aasworld ).bspchecksum );
//open a new file
botimport.FS_FOpenFile( filename, &fp, FS_WRITE );
if ( !fp ) {
botimport.Print( PRT_ERROR, "error opening %s\n", filename );
return qfalse;
} //end if
//write the header
botimport.FS_Write( &header, sizeof( aas_header_t ), fp );
AAS_WriteAASLump_offset = sizeof( aas_header_t );
//add the data lumps to the file
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_BBOXES, ( *aasworld ).bboxes,
( *aasworld ).numbboxes * sizeof( aas_bbox_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_VERTEXES, ( *aasworld ).vertexes,
( *aasworld ).numvertexes * sizeof( aas_vertex_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PLANES, ( *aasworld ).planes,
( *aasworld ).numplanes * sizeof( aas_plane_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGES, ( *aasworld ).edges,
( *aasworld ).numedges * sizeof( aas_edge_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGEINDEX, ( *aasworld ).edgeindex,
( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACES, ( *aasworld ).faces,
( *aasworld ).numfaces * sizeof( aas_face_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACEINDEX, ( *aasworld ).faceindex,
( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREAS, ( *aasworld ).areas,
( *aasworld ).numareas * sizeof( aas_area_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREASETTINGS, ( *aasworld ).areasettings,
( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_REACHABILITY, ( *aasworld ).reachability,
( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_NODES, ( *aasworld ).nodes,
( *aasworld ).numnodes * sizeof( aas_node_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALS, ( *aasworld ).portals,
( *aasworld ).numportals * sizeof( aas_portal_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALINDEX, ( *aasworld ).portalindex,
( *aasworld ).portalindexsize * sizeof( aas_portalindex_t ) ) ) {
return qfalse;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_CLUSTERS, ( *aasworld ).clusters,
( *aasworld ).numclusters * sizeof( aas_cluster_t ) ) ) {
return qfalse;
}
//rewrite the header with the added lumps
botimport.FS_Seek( fp, 0, FS_SEEK_SET );
botimport.FS_Write( &header, sizeof( aas_header_t ), fp );
//close the file
botimport.FS_FCloseFile( fp );
return qtrue;
} //end of the function AAS_WriteAASFile

48
src/botlib/be_aas_file.h Normal file
View File

@ -0,0 +1,48 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_file.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//loads the AAS file with the given name
int AAS_LoadAASFile( char *filename );
//writes an AAS file with the given name
qboolean AAS_WriteAASFile( char *filename );
//dumps the loaded AAS data
void AAS_DumpAASData( void );
//print AAS file information
void AAS_FileInfo( void );
#endif //AASINTERN

56
src/botlib/be_aas_funcs.h Normal file
View File

@ -0,0 +1,56 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_funcs.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifndef BSPCINCLUDE
#include "be_aas_main.h"
#include "be_aas_entity.h"
#include "be_aas_sample.h"
#include "be_aas_cluster.h"
#include "be_aas_reach.h"
#include "be_aas_route.h"
#include "be_aas_routealt.h"
#include "be_aas_debug.h"
#include "be_aas_file.h"
#include "be_aas_optimize.h"
#include "be_aas_bsp.h"
#include "be_aas_move.h"
// Ridah, route-tables
#include "be_aas_routetable.h"
#endif //BSPCINCLUDE

486
src/botlib/be_aas_main.c Normal file
View File

@ -0,0 +1,486 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_main.c
*
* desc: AAS
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_libvar.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_log.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
aas_t aasworlds[MAX_AAS_WORLDS];
aas_t *aasworld;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void QDECL AAS_Error( char *fmt, ... ) {
char str[1024];
va_list arglist;
va_start( arglist, fmt );
vsprintf( str, fmt, arglist );
va_end( arglist );
botimport.Print( PRT_FATAL, str );
} //end of the function AAS_Error
// Ridah, multiple AAS worlds
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SetCurrentWorld( int index ) {
if ( index >= MAX_AAS_WORLDS || index < 0 ) {
AAS_Error( "AAS_SetCurrentWorld: index out of range\n" );
return;
}
// set the current world pointer
aasworld = &aasworlds[index];
}
// done.
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_StringFromIndex( char *indexname, char *stringindex[], int numindexes, int index ) {
if ( !( *aasworld ).indexessetup ) {
botimport.Print( PRT_ERROR, "%s: index %d not setup\n", indexname, index );
return "";
} //end if
if ( index < 0 || index >= numindexes ) {
botimport.Print( PRT_ERROR, "%s: index %d out of range\n", indexname, index );
return "";
} //end if
if ( !stringindex[index] ) {
if ( index ) {
botimport.Print( PRT_ERROR, "%s: reference to unused index %d\n", indexname, index );
} //end if
return "";
} //end if
return stringindex[index];
} //end of the function AAS_StringFromIndex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_IndexFromString( char *indexname, char *stringindex[], int numindexes, char *string ) {
int i;
if ( !( *aasworld ).indexessetup ) {
botimport.Print( PRT_ERROR, "%s: index not setup \"%s\"\n", indexname, string );
return 0;
} //end if
for ( i = 0; i < numindexes; i++ )
{
if ( !stringindex[i] ) {
continue;
}
if ( !Q_stricmp( stringindex[i], string ) ) {
return i;
}
} //end for
return 0;
} //end of the function AAS_IndexFromString
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_ModelFromIndex( int index ) {
// return AAS_StringFromIndex("ModelFromIndex", &(*aasworld).configstrings[CS_MODELS], MAX_MODELS, index);
return 0; // removed so the CS_ defines could be removed from be_aas_def.h
} //end of the function AAS_ModelFromIndex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_IndexFromModel( char *modelname ) {
// return AAS_IndexFromString("IndexFromModel", &(*aasworld).configstrings[CS_MODELS], MAX_MODELS, modelname);
return 0; // removed so the CS_ defines could be removed from be_aas_def.h
} //end of the function AAS_IndexFromModel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_UpdateStringIndexes( int numconfigstrings, char *configstrings[] ) {
int i;
//set string pointers and copy the strings
for ( i = 0; i < numconfigstrings; i++ )
{
if ( configstrings[i] ) {
//if ((*aasworld).configstrings[i]) FreeMemory((*aasworld).configstrings[i]);
( *aasworld ).configstrings[i] = (char *) GetMemory( strlen( configstrings[i] ) + 1 );
strcpy( ( *aasworld ).configstrings[i], configstrings[i] );
} //end if
} //end for
( *aasworld ).indexessetup = qtrue;
} //end of the function AAS_UpdateStringIndexes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_Loaded( void ) {
return ( *aasworld ).loaded;
} //end of the function AAS_Loaded
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_Initialized( void ) {
return ( *aasworld ).initialized;
} //end of the function AAS_Initialized
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SetInitialized( void ) {
( *aasworld ).initialized = qtrue;
botimport.Print( PRT_MESSAGE, "AAS initialized.\n" );
#ifdef DEBUG
//create all the routing cache
//AAS_CreateAllRoutingCache();
//
//AAS_RoutingInfo();
#endif
// Ridah, build/load the route-table
AAS_RT_BuildRouteTable();
// done.
} //end of the function AAS_SetInitialized
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ContinueInit( float time ) {
//if no AAS file loaded
if ( !( *aasworld ).loaded ) {
return;
}
//if AAS is already initialized
if ( ( *aasworld ).initialized ) {
return;
}
//calculate reachability, if not finished return
if ( AAS_ContinueInitReachability( time ) ) {
return;
}
//initialize clustering for the new map
AAS_InitClustering();
//if reachability has been calculated and an AAS file should be written
//or there is a forced data optimization
if ( ( *aasworld ).savefile || ( (int)LibVarGetValue( "forcewrite" ) ) ) {
//optimize the AAS data
if ( !( (int)LibVarValue( "nooptimize", "1" ) ) ) {
AAS_Optimize();
}
//save the AAS file
if ( AAS_WriteAASFile( ( *aasworld ).filename ) ) {
botimport.Print( PRT_MESSAGE, "%s written succesfully\n", ( *aasworld ).filename );
} //end if
else
{
botimport.Print( PRT_ERROR, "couldn't write %s\n", ( *aasworld ).filename );
} //end else
} //end if
//initialize the routing
AAS_InitRouting();
//at this point AAS is initialized
AAS_SetInitialized();
} //end of the function AAS_ContinueInit
//===========================================================================
// called at the start of every frame
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_StartFrame( float time ) {
// Ridah, do each of the aasworlds
int i;
for ( i = 0; i < MAX_AAS_WORLDS; i++ )
{
AAS_SetCurrentWorld( i );
( *aasworld ).time = time;
//invalidate the entities
AAS_InvalidateEntities();
//initialize AAS
AAS_ContinueInit( time );
//
( *aasworld ).frameroutingupdates = 0;
//
/* Ridah, disabled for speed
if (LibVarGetValue("showcacheupdates"))
{
AAS_RoutingInfo();
LibVarSet("showcacheupdates", "0");
} //end if
if (LibVarGetValue("showmemoryusage"))
{
PrintUsedMemorySize();
LibVarSet("showmemoryusage", "0");
} //end if
if (LibVarGetValue("memorydump"))
{
PrintMemoryLabels();
LibVarSet("memorydump", "0");
} //end if
*/
} //end if
( *aasworld ).numframes++;
return BLERR_NOERROR;
} //end of the function AAS_StartFrame
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float AAS_Time( void ) {
return ( *aasworld ).time;
} //end of the function AAS_Time
//===========================================================================
// basedir = Quake2 console basedir
// gamedir = Quake2 console gamedir
// mapname = name of the map without extension (.bsp)
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_LoadFiles( const char *mapname ) {
int errnum;
char aasfile[MAX_PATH];
// char bspfile[MAX_PATH];
strcpy( ( *aasworld ).mapname, mapname );
//NOTE: first reset the entity links into the AAS areas and BSP leaves
// the AAS link heap and BSP link heap are reset after respectively the
// AAS file and BSP file are loaded
AAS_ResetEntityLinks();
//
// load bsp info
AAS_LoadBSPFile();
//load the aas file
Com_sprintf( aasfile, MAX_PATH, "maps/%s.aas", mapname );
errnum = AAS_LoadAASFile( aasfile );
if ( errnum != BLERR_NOERROR ) {
return errnum;
}
botimport.Print( PRT_MESSAGE, "loaded %s\n", aasfile );
strncpy( ( *aasworld ).filename, aasfile, MAX_PATH );
return BLERR_NOERROR;
} //end of the function AAS_LoadFiles
//===========================================================================
// called everytime a map changes
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
// Ridah, modified this for multiple AAS files
int AAS_LoadMap( const char *mapname ) {
int errnum;
int i;
char this_mapname[256], intstr[4];
qboolean loaded = qfalse;
int missingErrNum = 0; // TTimo: init
for ( i = 0; i < MAX_AAS_WORLDS; i++ )
{
AAS_SetCurrentWorld( i );
strncpy( this_mapname, mapname, 256 );
strncat( this_mapname, "_b", 256 );
sprintf( intstr, "%i", i );
strncat( this_mapname, intstr, 256 );
//if no mapname is provided then the string indexes are updated
if ( !mapname ) {
return 0;
} //end if
//
( *aasworld ).initialized = qfalse;
//NOTE: free the routing caches before loading a new map because
// to free the caches the old number of areas, number of clusters
// and number of areas in a clusters must be available
AAS_FreeRoutingCaches();
//load the map
errnum = AAS_LoadFiles( this_mapname );
if ( errnum != BLERR_NOERROR ) {
( *aasworld ).loaded = qfalse;
// RF, we are allowed to skip one of the files, but not both
//return errnum;
missingErrNum = errnum;
continue;
} //end if
//
loaded = qtrue;
//
AAS_InitSettings();
//initialize the AAS link heap for the new map
AAS_InitAASLinkHeap();
//initialize the AAS linked entities for the new map
AAS_InitAASLinkedEntities();
//initialize reachability for the new map
AAS_InitReachability();
//initialize the alternative routing
AAS_InitAlternativeRouting();
}
if ( !loaded ) {
return missingErrNum;
}
//everything went ok
return 0;
} //end of the function AAS_LoadMap
// done.
//===========================================================================
// called when the library is first loaded
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_Setup( void ) {
// Ridah, just use the default world for entities
AAS_SetCurrentWorld( 0 );
( *aasworlds ).maxclients = (int) LibVarValue( "maxclients", "128" );
( *aasworlds ).maxentities = (int) LibVarValue( "maxentities", "1024" );
//allocate memory for the entities
if ( ( *aasworld ).entities ) {
FreeMemory( ( *aasworld ).entities );
}
( *aasworld ).entities = (aas_entity_t *) GetClearedHunkMemory( ( *aasworld ).maxentities * sizeof( aas_entity_t ) );
//invalidate all the entities
AAS_InvalidateEntities();
//force some recalculations
//LibVarSet("forceclustering", "1"); //force clustering calculation
//LibVarSet("forcereachability", "1"); //force reachability calculation
( *aasworld ).numframes = 0;
return BLERR_NOERROR;
} //end of the function AAS_Setup
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_Shutdown( void ) {
// Ridah, do each of the worlds
int i;
for ( i = 0; i < MAX_AAS_WORLDS; i++ )
{
AAS_SetCurrentWorld( i );
// Ridah, kill the route-table data
AAS_RT_ShutdownRouteTable();
AAS_ShutdownAlternativeRouting();
AAS_DumpBSPData();
//free routing caches
AAS_FreeRoutingCaches();
//free aas link heap
AAS_FreeAASLinkHeap();
//free aas linked entities
AAS_FreeAASLinkedEntities();
//free the aas data
AAS_DumpAASData();
if ( i == 0 ) {
//free the entities
if ( ( *aasworld ).entities ) {
FreeMemory( ( *aasworld ).entities );
}
}
//clear the (*aasworld) structure
memset( &( *aasworld ), 0, sizeof( aas_t ) );
//aas has not been initialized
( *aasworld ).initialized = qfalse;
}
//NOTE: as soon as a new .bsp file is loaded the .bsp file memory is
// freed an reallocated, so there's no need to free that memory here
//print shutdown
botimport.Print( PRT_MESSAGE, "AAS shutdown.\n" );
} //end of the function AAS_Shutdown

69
src/botlib/be_aas_main.h Normal file
View File

@ -0,0 +1,69 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_main.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
extern aas_t( *aasworld );
//AAS error message
void QDECL AAS_Error( char *fmt, ... );
//set AAS initialized
void AAS_SetInitialized( void );
//setup AAS with the given number of entities and clients
int AAS_Setup( void );
//shutdown AAS
void AAS_Shutdown( void );
//start a new map
int AAS_LoadMap( const char *mapname );
//start a new time frame
int AAS_StartFrame( float time );
#endif //AASINTERN
//returns true if AAS is initialized
int AAS_Initialized( void );
//returns true if the AAS file is loaded
int AAS_Loaded( void );
//returns the model name from the given index
char *AAS_ModelFromIndex( int index );
//returns the index from the given model name
int AAS_IndexFromModel( char *modelname );
//returns the current time
float AAS_Time( void );
// Ridah
void AAS_SetCurrentWorld( int index );
// done.

912
src/botlib/be_aas_move.c Normal file
View File

@ -0,0 +1,912 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_move.c
*
* desc: AAS
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
//#define BSPC
extern botlib_import_t botimport;
aas_settings_t aassettings;
//#define AAS_MOVE_DEBUG
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_DropToFloor( vec3_t origin, vec3_t mins, vec3_t maxs ) {
vec3_t end;
bsp_trace_t trace;
VectorCopy( origin, end );
end[2] -= 100;
trace = AAS_Trace( origin, mins, maxs, end, 0, CONTENTS_SOLID );
if ( trace.startsolid ) {
return qfalse;
}
VectorCopy( trace.endpos, origin );
return qtrue;
} //end of the function AAS_DropToFloor
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InitSettings( void ) {
aassettings.sv_friction = 6;
aassettings.sv_stopspeed = 100;
aassettings.sv_gravity = 800;
aassettings.sv_waterfriction = 1;
aassettings.sv_watergravity = 400;
aassettings.sv_maxvelocity = 320;
aassettings.sv_maxwalkvelocity = 300;
aassettings.sv_maxcrouchvelocity = 100;
aassettings.sv_maxswimvelocity = 150;
aassettings.sv_walkaccelerate = 10;
aassettings.sv_airaccelerate = 1;
aassettings.sv_swimaccelerate = 4;
aassettings.sv_maxstep = 18;
aassettings.sv_maxsteepness = 0.7;
aassettings.sv_maxwaterjump = 17;
// Ridah, calculate maxbarrier according to jumpvel and gravity
aassettings.sv_jumpvel = 270;
aassettings.sv_maxbarrier = 49; //-0.8 + (0.5 * aassettings.sv_gravity * (aassettings.sv_jumpvel / aassettings.sv_gravity) * (aassettings.sv_jumpvel / aassettings.sv_gravity));
// done.
} //end of the function AAS_InitSettings
//===========================================================================
// returns qtrue if the bot is against a ladder
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_AgainstLadder( vec3_t origin, int ms_areanum ) {
int areanum, i, facenum, side;
vec3_t org;
aas_plane_t *plane;
aas_face_t *face;
aas_area_t *area;
VectorCopy( origin, org );
areanum = AAS_PointAreaNum( org );
if ( !areanum ) {
org[0] += 1;
areanum = AAS_PointAreaNum( org );
if ( !areanum ) {
org[1] += 1;
areanum = AAS_PointAreaNum( org );
if ( !areanum ) {
org[0] -= 2;
areanum = AAS_PointAreaNum( org );
if ( !areanum ) {
org[1] -= 2;
areanum = AAS_PointAreaNum( org );
} //end if
} //end if
} //end if
} //end if
//if in solid... wrrr shouldn't happen
//if (!areanum) return qfalse;
// RF, it does if they're in a monsterclip brush
if ( !areanum ) {
areanum = ms_areanum;
}
//if not in a ladder area
if ( !( ( *aasworld ).areasettings[areanum].areaflags & AREA_LADDER ) ) {
return qfalse;
}
//if a crouch only area
if ( !( ( *aasworld ).areasettings[areanum].presencetype & PRESENCE_NORMAL ) ) {
return qfalse;
}
//
area = &( *aasworld ).areas[areanum];
for ( i = 0; i < area->numfaces; i++ )
{
facenum = ( *aasworld ).faceindex[area->firstface + i];
side = facenum < 0;
face = &( *aasworld ).faces[abs( facenum )];
//if the face isn't a ladder face
if ( !( face->faceflags & FACE_LADDER ) ) {
continue;
}
//get the plane the face is in
plane = &( *aasworld ).planes[face->planenum ^ side];
//if the origin is pretty close to the plane
if ( abs( DotProduct( plane->normal, origin ) - plane->dist ) < 3 ) {
if ( AAS_PointInsideFace( abs( facenum ), origin, 0.1 ) ) {
return qtrue;
}
} //end if
} //end for
return qfalse;
} //end of the function AAS_AgainstLadder
//===========================================================================
// returns qtrue if the bot is on the ground
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_OnGround( vec3_t origin, int presencetype, int passent ) {
aas_trace_t trace;
vec3_t end, up = {0, 0, 1};
aas_plane_t *plane;
VectorCopy( origin, end );
end[2] -= 10;
trace = AAS_TraceClientBBox( origin, end, presencetype, passent );
//if in solid
if ( trace.startsolid ) {
return qtrue; //qfalse;
}
//if nothing hit at all
if ( trace.fraction >= 1.0 ) {
return qfalse;
}
//if too far from the hit plane
if ( origin[2] - trace.endpos[2] > 10 ) {
return qfalse;
}
//check if the plane isn't too steep
plane = AAS_PlaneFromNum( trace.planenum );
if ( DotProduct( plane->normal, up ) < aassettings.sv_maxsteepness ) {
return qfalse;
}
//the bot is on the ground
return qtrue;
} //end of the function AAS_OnGround
//===========================================================================
// returns qtrue if a bot at the given position is swimming
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_Swimming( vec3_t origin ) {
vec3_t testorg;
VectorCopy( origin, testorg );
testorg[2] -= 2;
if ( AAS_PointContents( testorg ) & ( CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER ) ) {
return qtrue;
}
return qfalse;
} //end of the function AAS_Swimming
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec3_t VEC_UP = {0, -1, 0};
vec3_t MOVEDIR_UP = {0, 0, 1};
vec3_t VEC_DOWN = {0, -2, 0};
vec3_t MOVEDIR_DOWN = {0, 0, -1};
void AAS_SetMovedir( vec3_t angles, vec3_t movedir ) {
if ( VectorCompare( angles, VEC_UP ) ) {
VectorCopy( MOVEDIR_UP, movedir );
} //end if
else if ( VectorCompare( angles, VEC_DOWN ) ) {
VectorCopy( MOVEDIR_DOWN, movedir );
} //end else if
else
{
AngleVectors( angles, movedir, NULL, NULL );
} //end else
} //end of the function AAS_SetMovedir
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_JumpReachRunStart( aas_reachability_t *reach, vec3_t runstart ) {
vec3_t hordir, start, cmdmove;
aas_clientmove_t move;
//
hordir[0] = reach->start[0] - reach->end[0];
hordir[1] = reach->start[1] - reach->end[1];
hordir[2] = 0;
VectorNormalize( hordir );
//start point
VectorCopy( reach->start, start );
start[2] += 1;
//get command movement
VectorScale( hordir, 400, cmdmove );
//
AAS_PredictClientMovement( &move, -1, start, PRESENCE_NORMAL, qtrue,
vec3_origin, cmdmove, 1, 2, 0.1,
SE_ENTERWATER | SE_ENTERSLIME | SE_ENTERLAVA |
SE_HITGROUNDDAMAGE | SE_GAP, 0, qfalse );
VectorCopy( move.endpos, runstart );
//don't enter slime or lava and don't fall from too high
if ( move.stopevent & ( SE_ENTERLAVA | SE_HITGROUNDDAMAGE ) ) { //----(SA) modified since slime is no longer deadly
// if (move.stopevent & (SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
VectorCopy( start, runstart );
} //end if
} //end of the function AAS_JumpReachRunStart
//===========================================================================
// returns the Z velocity when rocket jumping at the origin
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float AAS_WeaponJumpZVelocity( vec3_t origin, float radiusdamage ) {
vec3_t kvel, v, start, end, forward, right, viewangles, dir;
float mass, knockback, points;
vec3_t rocketoffset = {8, 8, -8};
vec3_t botmins = {-16, -16, -24};
vec3_t botmaxs = {16, 16, 32};
bsp_trace_t bsptrace;
//look down (90 degrees)
viewangles[PITCH] = 90;
viewangles[YAW] = 0;
viewangles[ROLL] = 0;
//get the start point shooting from
VectorCopy( origin, start );
start[2] += 8; //view offset Z
AngleVectors( viewangles, forward, right, NULL );
start[0] += forward[0] * rocketoffset[0] + right[0] * rocketoffset[1];
start[1] += forward[1] * rocketoffset[0] + right[1] * rocketoffset[1];
start[2] += forward[2] * rocketoffset[0] + right[2] * rocketoffset[1] + rocketoffset[2];
//end point of the trace
VectorMA( start, 500, forward, end );
//trace a line to get the impact point
bsptrace = AAS_Trace( start, NULL, NULL, end, 1, CONTENTS_SOLID );
//calculate the damage the bot will get from the rocket impact
VectorAdd( botmins, botmaxs, v );
VectorMA( origin, 0.5, v, v );
VectorSubtract( bsptrace.endpos, v, v );
//
points = radiusdamage - 0.5 * VectorLength( v );
if ( points < 0 ) {
points = 0;
}
//the owner of the rocket gets half the damage
points *= 0.5;
//mass of the bot (p_client.c: PutClientInServer)
mass = 200;
//knockback is the same as the damage points
knockback = points;
//direction of the damage (from trace.endpos to bot origin)
VectorSubtract( origin, bsptrace.endpos, dir );
VectorNormalize( dir );
//damage velocity
VectorScale( dir, 1600.0 * (float)knockback / mass, kvel ); //the rocket jump hack...
//rocket impact velocity + jump velocity
return kvel[2] + aassettings.sv_jumpvel;
} //end of the function AAS_WeaponJumpZVelocity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float AAS_RocketJumpZVelocity( vec3_t origin ) {
//rocket radius damage is 120 (p_weapon.c: Weapon_RocketLauncher_Fire)
return AAS_WeaponJumpZVelocity( origin, 120 );
} //end of the function AAS_RocketJumpZVelocity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float AAS_BFGJumpZVelocity( vec3_t origin ) {
//bfg radius damage is 1000 (p_weapon.c: weapon_bfg_fire)
return AAS_WeaponJumpZVelocity( origin, 120 );
} //end of the function AAS_BFGJumpZVelocity
//===========================================================================
// applies ground friction to the given velocity
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_Accelerate( vec3_t velocity, float frametime, vec3_t wishdir, float wishspeed, float accel ) {
// q2 style
int i;
float addspeed, accelspeed, currentspeed;
currentspeed = DotProduct( velocity, wishdir );
addspeed = wishspeed - currentspeed;
if ( addspeed <= 0 ) {
return;
}
accelspeed = accel * frametime * wishspeed;
if ( accelspeed > addspeed ) {
accelspeed = addspeed;
}
for ( i = 0 ; i < 3 ; i++ ) {
velocity[i] += accelspeed * wishdir[i];
}
} //end of the function AAS_Accelerate
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_AirControl( vec3_t start, vec3_t end, vec3_t velocity, vec3_t cmdmove ) {
vec3_t dir;
VectorSubtract( end, start, dir );
} //end of the function AAS_AirControl
//===========================================================================
// applies ground friction to the given velocity
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ApplyFriction( vec3_t vel, float friction, float stopspeed,
float frametime ) {
float speed, control, newspeed;
//horizontal speed
speed = sqrt( vel[0] * vel[0] + vel[1] * vel[1] );
if ( speed ) {
control = speed < stopspeed ? stopspeed : speed;
newspeed = speed - frametime * control * friction;
if ( newspeed < 0 ) {
newspeed = 0;
}
newspeed /= speed;
vel[0] *= newspeed;
vel[1] *= newspeed;
} //end if
} //end of the function AAS_ApplyFriction
//===========================================================================
// predicts the movement
// assumes regular bounding box sizes
// NOTE: out of water jumping is not included
// NOTE: grappling hook is not included
//
// Parameter: origin : origin to start with
// presencetype : presence type to start with
// velocity : velocity to start with
// cmdmove : client command movement
// cmdframes : number of frame cmdmove is valid
// maxframes : maximum number of predicted frames
// frametime : duration of one predicted frame
// stopevent : events that stop the prediction
// stopareanum : stop as soon as entered this area
// Returns: aas_clientmove_t
// Changes Globals: -
//===========================================================================
int AAS_PredictClientMovement( struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
int stopevent, int stopareanum, int visualize ) {
float sv_friction, sv_stopspeed, sv_gravity, sv_waterfriction;
float sv_watergravity;
float sv_walkaccelerate, sv_airaccelerate, sv_swimaccelerate;
float sv_maxwalkvelocity, sv_maxcrouchvelocity, sv_maxswimvelocity;
float sv_maxstep, sv_maxsteepness, sv_jumpvel, friction;
float gravity, delta, maxvel, wishspeed, accelerate;
//float velchange, newvel;
int n, i, j, pc, step, swimming, ax, crouch, event, jump_frame, areanum;
int areas[20], numareas;
vec3_t points[20];
vec3_t org, end, feet, start, stepend, lastorg, wishdir;
vec3_t frame_test_vel, old_frame_test_vel, left_test_vel;
vec3_t up = {0, 0, 1};
aas_plane_t *plane, *plane2;
aas_trace_t trace, steptrace;
if ( frametime <= 0 ) {
frametime = 0.1;
}
//
sv_friction = aassettings.sv_friction;
sv_stopspeed = aassettings.sv_stopspeed;
sv_gravity = aassettings.sv_gravity;
sv_waterfriction = aassettings.sv_waterfriction;
sv_watergravity = aassettings.sv_watergravity;
sv_maxwalkvelocity = aassettings.sv_maxwalkvelocity; // * frametime;
sv_maxcrouchvelocity = aassettings.sv_maxcrouchvelocity; // * frametime;
sv_maxswimvelocity = aassettings.sv_maxswimvelocity; // * frametime;
sv_walkaccelerate = aassettings.sv_walkaccelerate;
sv_airaccelerate = aassettings.sv_airaccelerate;
sv_swimaccelerate = aassettings.sv_swimaccelerate;
sv_maxstep = aassettings.sv_maxstep;
sv_maxsteepness = aassettings.sv_maxsteepness;
sv_jumpvel = aassettings.sv_jumpvel * frametime;
//
memset( move, 0, sizeof( aas_clientmove_t ) );
memset( &trace, 0, sizeof( aas_trace_t ) );
//start at the current origin
VectorCopy( origin, org );
org[2] += 0.25;
//velocity to test for the first frame
VectorScale( velocity, frametime, frame_test_vel );
//
jump_frame = -1;
//predict a maximum of 'maxframes' ahead
for ( n = 0; n < maxframes; n++ )
{
swimming = AAS_Swimming( org );
//get gravity depending on swimming or not
gravity = swimming ? sv_watergravity : sv_gravity;
//apply gravity at the START of the frame
frame_test_vel[2] = frame_test_vel[2] - ( gravity * 0.1 * frametime );
//if on the ground or swimming
if ( onground || swimming ) {
friction = swimming ? sv_friction : sv_waterfriction;
//apply friction
VectorScale( frame_test_vel, 1 / frametime, frame_test_vel );
AAS_ApplyFriction( frame_test_vel, friction, sv_stopspeed, frametime );
VectorScale( frame_test_vel, frametime, frame_test_vel );
} //end if
crouch = qfalse;
//apply command movement
if ( n < cmdframes ) {
ax = 0;
maxvel = sv_maxwalkvelocity;
accelerate = sv_airaccelerate;
VectorCopy( cmdmove, wishdir );
if ( onground ) {
if ( cmdmove[2] < -300 ) {
crouch = qtrue;
maxvel = sv_maxcrouchvelocity;
} //end if
//if not swimming and upmove is positive then jump
if ( !swimming && cmdmove[2] > 1 ) {
//jump velocity minus the gravity for one frame + 5 for safety
frame_test_vel[2] = sv_jumpvel - ( gravity * 0.1 * frametime ) + 5;
jump_frame = n;
//jumping so air accelerate
accelerate = sv_airaccelerate;
} //end if
else
{
accelerate = sv_walkaccelerate;
} //end else
ax = 2;
} //end if
if ( swimming ) {
maxvel = sv_maxswimvelocity;
accelerate = sv_swimaccelerate;
ax = 3;
} //end if
else
{
wishdir[2] = 0;
} //end else
//
wishspeed = VectorNormalize( wishdir );
if ( wishspeed > maxvel ) {
wishspeed = maxvel;
}
VectorScale( frame_test_vel, 1 / frametime, frame_test_vel );
AAS_Accelerate( frame_test_vel, frametime, wishdir, wishspeed, accelerate );
VectorScale( frame_test_vel, frametime, frame_test_vel );
/*
for (i = 0; i < ax; i++)
{
velchange = (cmdmove[i] * frametime) - frame_test_vel[i];
if (velchange > sv_maxacceleration) velchange = sv_maxacceleration;
else if (velchange < -sv_maxacceleration) velchange = -sv_maxacceleration;
newvel = frame_test_vel[i] + velchange;
//
if (frame_test_vel[i] <= maxvel && newvel > maxvel) frame_test_vel[i] = maxvel;
else if (frame_test_vel[i] >= -maxvel && newvel < -maxvel) frame_test_vel[i] = -maxvel;
else frame_test_vel[i] = newvel;
} //end for
*/
} //end if
if ( crouch ) {
presencetype = PRESENCE_CROUCH;
} //end if
else if ( presencetype == PRESENCE_CROUCH ) {
if ( AAS_PointPresenceType( org ) & PRESENCE_NORMAL ) {
presencetype = PRESENCE_NORMAL;
} //end if
} //end else
//save the current origin
VectorCopy( org, lastorg );
//move linear during one frame
VectorCopy( frame_test_vel, left_test_vel );
j = 0;
do
{
VectorAdd( org, left_test_vel, end );
//trace a bounding box
trace = AAS_TraceClientBBox( org, end, presencetype, entnum );
//
//#ifdef AAS_MOVE_DEBUG
if ( visualize ) {
if ( trace.startsolid ) {
botimport.Print( PRT_MESSAGE, "PredictMovement: start solid\n" );
}
AAS_DebugLine( org, trace.endpos, LINECOLOR_RED );
} //end if
//#endif //AAS_MOVE_DEBUG
//
if ( stopevent & SE_ENTERAREA ) {
numareas = AAS_TraceAreas( org, trace.endpos, areas, points, 20 );
for ( i = 0; i < numareas; i++ )
{
if ( areas[i] == stopareanum ) {
VectorCopy( points[i], move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_ENTERAREA;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end for
} //end if
//move the entity to the trace end point
VectorCopy( trace.endpos, org );
//if there was a collision
if ( trace.fraction < 1.0 ) {
//get the plane the bounding box collided with
plane = AAS_PlaneFromNum( trace.planenum );
//
if ( stopevent & SE_HITGROUNDAREA ) {
if ( DotProduct( plane->normal, up ) > sv_maxsteepness ) {
VectorCopy( org, start );
start[2] += 0.5;
if ( AAS_PointAreaNum( start ) == stopareanum ) {
VectorCopy( start, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_HITGROUNDAREA;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
//assume there's no step
step = qfalse;
//if it is a vertical plane and the bot didn't jump recently
if ( plane->normal[2] == 0 && ( jump_frame < 0 || n - jump_frame > 2 ) ) {
//check for a step
VectorMA( org, -0.25, plane->normal, start );
VectorCopy( start, stepend );
start[2] += sv_maxstep;
steptrace = AAS_TraceClientBBox( start, stepend, presencetype, entnum );
//
if ( !steptrace.startsolid ) {
plane2 = AAS_PlaneFromNum( steptrace.planenum );
if ( DotProduct( plane2->normal, up ) > sv_maxsteepness ) {
VectorSubtract( end, steptrace.endpos, left_test_vel );
left_test_vel[2] = 0;
frame_test_vel[2] = 0;
//#ifdef AAS_MOVE_DEBUG
if ( visualize ) {
if ( steptrace.endpos[2] - org[2] > 0.125 ) {
VectorCopy( org, start );
start[2] = steptrace.endpos[2];
AAS_DebugLine( org, start, LINECOLOR_BLUE );
} //end if
} //end if
//#endif //AAS_MOVE_DEBUG
org[2] = steptrace.endpos[2];
step = qtrue;
} //end if
} //end if
} //end if
//
if ( !step ) {
//velocity left to test for this frame is the projection
//of the current test velocity into the hit plane
VectorMA( left_test_vel, -DotProduct( left_test_vel, plane->normal ),
plane->normal, left_test_vel );
//store the old velocity for landing check
VectorCopy( frame_test_vel, old_frame_test_vel );
//test velocity for the next frame is the projection
//of the velocity of the current frame into the hit plane
VectorMA( frame_test_vel, -DotProduct( frame_test_vel, plane->normal ),
plane->normal, frame_test_vel );
//check for a landing on an almost horizontal floor
if ( DotProduct( plane->normal, up ) > sv_maxsteepness ) {
onground = qtrue;
} //end if
if ( stopevent & SE_HITGROUNDDAMAGE ) {
delta = 0;
if ( old_frame_test_vel[2] < 0 &&
frame_test_vel[2] > old_frame_test_vel[2] &&
!onground ) {
delta = old_frame_test_vel[2];
} //end if
else if ( onground ) {
delta = frame_test_vel[2] - old_frame_test_vel[2];
} //end else
if ( delta ) {
delta = delta * 10;
delta = delta * delta * 0.0001;
if ( swimming ) {
delta = 0;
}
// never take falling damage if completely underwater
/*
if (ent->waterlevel == 3) return;
if (ent->waterlevel == 2) delta *= 0.25;
if (ent->waterlevel == 1) delta *= 0.5;
*/
if ( delta > 40 ) {
VectorCopy( org, move->endpos );
VectorCopy( frame_test_vel, move->velocity );
move->trace = trace;
move->stopevent = SE_HITGROUNDDAMAGE;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
} //end if
} //end if
//extra check to prevent endless loop
if ( ++j > 20 ) {
return qfalse;
}
//while there is a plane hit
} while ( trace.fraction < 1.0 );
//if going down
if ( frame_test_vel[2] <= 10 ) {
//check for a liquid at the feet of the bot
VectorCopy( org, feet );
feet[2] -= 22;
pc = AAS_PointContents( feet );
//get event from pc
event = SE_NONE;
if ( pc & CONTENTS_LAVA ) {
event |= SE_ENTERLAVA;
}
if ( pc & CONTENTS_SLIME ) {
event |= SE_ENTERSLIME;
}
if ( pc & CONTENTS_WATER ) {
event |= SE_ENTERWATER;
}
//
areanum = AAS_PointAreaNum( org );
if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_LAVA ) {
event |= SE_ENTERLAVA;
}
if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_SLIME ) {
event |= SE_ENTERSLIME;
}
if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_WATER ) {
event |= SE_ENTERWATER;
}
//if in lava or slime
if ( event & stopevent ) {
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->stopevent = event & stopevent;
move->presencetype = presencetype;
move->endcontents = pc;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
//
onground = AAS_OnGround( org, presencetype, entnum );
//if onground and on the ground for at least one whole frame
if ( onground ) {
if ( stopevent & SE_HITGROUND ) {
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_HITGROUND;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
else if ( stopevent & SE_LEAVEGROUND ) {
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_LEAVEGROUND;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end else if
else if ( stopevent & SE_GAP ) {
aas_trace_t gaptrace;
VectorCopy( org, start );
VectorCopy( start, end );
end[2] -= 48 + aassettings.sv_maxbarrier;
gaptrace = AAS_TraceClientBBox( start, end, PRESENCE_CROUCH, -1 );
//if solid is found the bot cannot walk any further and will not fall into a gap
if ( !gaptrace.startsolid ) {
//if it is a gap (lower than one step height)
if ( gaptrace.endpos[2] < org[2] - aassettings.sv_maxstep - 1 ) {
if ( !( AAS_PointContents( end ) & ( CONTENTS_WATER | CONTENTS_SLIME ) ) ) { //----(SA) modified since slime is no longer deadly
// if (!(AAS_PointContents(end) & CONTENTS_WATER))
VectorCopy( lastorg, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_GAP;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
} //end else if
if ( stopevent & SE_TOUCHJUMPPAD ) {
if ( ( *aasworld ).areasettings[AAS_PointAreaNum( org )].contents & AREACONTENTS_JUMPPAD ) {
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_TOUCHJUMPPAD;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
if ( stopevent & SE_TOUCHTELEPORTER ) {
if ( ( *aasworld ).areasettings[AAS_PointAreaNum( org )].contents & AREACONTENTS_TELEPORTER ) {
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->trace = trace;
move->stopevent = SE_TOUCHTELEPORTER;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end for
//
VectorCopy( org, move->endpos );
VectorScale( frame_test_vel, 1 / frametime, move->velocity );
move->stopevent = SE_NONE;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
//
return qtrue;
} //end of the function AAS_PredictClientMovement
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_TestMovementPrediction( int entnum, vec3_t origin, vec3_t dir ) {
vec3_t velocity, cmdmove;
aas_clientmove_t move;
VectorClear( velocity );
if ( !AAS_Swimming( origin ) ) {
dir[2] = 0;
}
VectorNormalize( dir );
VectorScale( dir, 400, cmdmove );
cmdmove[2] = 224;
AAS_ClearShownDebugLines();
AAS_PredictClientMovement( &move, entnum, origin, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 13, 13, 0.1, SE_HITGROUND, 0, qtrue ); //SE_LEAVEGROUND);
if ( move.stopevent & SE_LEAVEGROUND ) {
botimport.Print( PRT_MESSAGE, "leave ground\n" );
} //end if
} //end of the function TestMovementPrediction
//===========================================================================
// calculates the horizontal velocity needed to perform a jump from start
// to end
//
// Parameter: zvel : z velocity for jump
// start : start position of jump
// end : end position of jump
// *speed : returned speed for jump
// Returns: qfalse if too high or too far from start to end
// Changes Globals: -
//===========================================================================
int AAS_HorizontalVelocityForJump( float zvel, vec3_t start, vec3_t end, float *velocity ) {
float sv_gravity, sv_maxvelocity;
float maxjump, height2fall, t, top;
vec3_t dir;
sv_gravity = aassettings.sv_gravity;
sv_maxvelocity = aassettings.sv_maxvelocity;
//maximum height a player can jump with the given initial z velocity
maxjump = 0.5 * sv_gravity * ( zvel / sv_gravity ) * ( zvel / sv_gravity );
//top of the parabolic jump
top = start[2] + maxjump;
//height the bot will fall from the top
height2fall = top - end[2];
//if the goal is to high to jump to
if ( height2fall < 0 ) {
*velocity = sv_maxvelocity;
return 0;
} //end if
//time a player takes to fall the height
t = sqrt( height2fall / ( 0.5 * sv_gravity ) );
//direction from start to end
VectorSubtract( end, start, dir );
//calculate horizontal speed
*velocity = sqrt( dir[0] * dir[0] + dir[1] * dir[1] ) / ( t + zvel / sv_gravity );
//the horizontal speed must be lower than the max speed
if ( *velocity > sv_maxvelocity ) {
*velocity = sv_maxvelocity;
return 0;
} //end if
return 1;
} //end of the function AAS_HorizontalVelocityForJump

69
src/botlib/be_aas_move.h Normal file
View File

@ -0,0 +1,69 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_move.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
extern aas_settings_t aassettings;
#endif //AASINTERN
//movement prediction
int AAS_PredictClientMovement( struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
int stopevent, int stopareanum, int visualize );
//returns true if on the ground at the given origin
int AAS_OnGround( vec3_t origin, int presencetype, int passent );
//returns true if swimming at the given origin
int AAS_Swimming( vec3_t origin );
//returns the jump reachability run start point
void AAS_JumpReachRunStart( struct aas_reachability_s *reach, vec3_t runstart );
//returns true if against a ladder at the given origin
int AAS_AgainstLadder( vec3_t origin, int ms_areanum );
//rocket jump Z velocity when rocket-jumping at origin
float AAS_RocketJumpZVelocity( vec3_t origin );
//bfg jump Z velocity when bfg-jumping at origin
float AAS_BFGJumpZVelocity( vec3_t origin );
//calculates the horizontal velocity needed for a jump and returns true this velocity could be calculated
int AAS_HorizontalVelocityForJump( float zvel, vec3_t start, vec3_t end, float *velocity );
//
void AAS_SetMovedir( vec3_t angles, vec3_t movedir );
//
int AAS_DropToFloor( vec3_t origin, vec3_t mins, vec3_t maxs );
//
void AAS_InitSettings( void );

View File

@ -0,0 +1,337 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_optimize.c
*
* desc: decreases the .aas file size after the reachabilities have
* been calculated, just dumps all the faces, edges and vertexes
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_libvar.h"
//#include "l_utils.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
typedef struct optimized_s
{
//vertixes
int numvertexes;
aas_vertex_t *vertexes;
//edges
int numedges;
aas_edge_t *edges;
//edge index
int edgeindexsize;
aas_edgeindex_t *edgeindex;
//faces
int numfaces;
aas_face_t *faces;
//face index
int faceindexsize;
aas_faceindex_t *faceindex;
//convex areas
int numareas;
aas_area_t *areas;
//
int *vertexoptimizeindex;
int *edgeoptimizeindex;
int *faceoptimizeindex;
} optimized_t;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_KeepEdge( aas_edge_t *edge ) {
return 1;
} //end of the function AAS_KeepFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_OptimizeEdge( optimized_t *optimized, int edgenum ) {
int i, optedgenum;
aas_edge_t *edge, *optedge;
edge = &( *aasworld ).edges[abs( edgenum )];
if ( !AAS_KeepEdge( edge ) ) {
return 0;
}
optedgenum = optimized->edgeoptimizeindex[abs( edgenum )];
if ( optedgenum ) {
//keep the edge reversed sign
if ( edgenum > 0 ) {
return optedgenum;
} else { return -optedgenum;}
} //end if
optedge = &optimized->edges[optimized->numedges];
for ( i = 0; i < 2; i++ )
{
if ( optimized->vertexoptimizeindex[edge->v[i]] ) {
optedge->v[i] = optimized->vertexoptimizeindex[edge->v[i]];
} //end if
else
{
VectorCopy( ( *aasworld ).vertexes[edge->v[i]], optimized->vertexes[optimized->numvertexes] );
optedge->v[i] = optimized->numvertexes;
optimized->vertexoptimizeindex[edge->v[i]] = optimized->numvertexes;
optimized->numvertexes++;
} //end else
} //end for
optimized->edgeoptimizeindex[abs( edgenum )] = optimized->numedges;
optedgenum = optimized->numedges;
optimized->numedges++;
//keep the edge reversed sign
if ( edgenum > 0 ) {
return optedgenum;
} else { return -optedgenum;}
} //end of the function AAS_OptimizeEdge
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_KeepFace( aas_face_t *face ) {
if ( !( face->faceflags & FACE_LADDER ) ) {
return 0;
} else { return 1;}
} //end of the function AAS_KeepFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_OptimizeFace( optimized_t *optimized, int facenum ) {
int i, edgenum, optedgenum, optfacenum;
aas_face_t *face, *optface;
face = &( *aasworld ).faces[abs( facenum )];
if ( !AAS_KeepFace( face ) ) {
return 0;
}
optfacenum = optimized->faceoptimizeindex[abs( facenum )];
if ( optfacenum ) {
//keep the face side sign
if ( facenum > 0 ) {
return optfacenum;
} else { return -optfacenum;}
} //end if
optface = &optimized->faces[optimized->numfaces];
memcpy( optface, face, sizeof( aas_face_t ) );
optface->numedges = 0;
optface->firstedge = optimized->edgeindexsize;
for ( i = 0; i < face->numedges; i++ )
{
edgenum = ( *aasworld ).edgeindex[face->firstedge + i];
optedgenum = AAS_OptimizeEdge( optimized, edgenum );
if ( optedgenum ) {
optimized->edgeindex[optface->firstedge + optface->numedges] = optedgenum;
optface->numedges++;
optimized->edgeindexsize++;
} //end if
} //end for
optimized->faceoptimizeindex[abs( facenum )] = optimized->numfaces;
optfacenum = optimized->numfaces;
optimized->numfaces++;
//keep the face side sign
if ( facenum > 0 ) {
return optfacenum;
} else { return -optfacenum;}
} //end of the function AAS_OptimizeFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_OptimizeArea( optimized_t *optimized, int areanum ) {
int i, facenum, optfacenum;
aas_area_t *area, *optarea;
area = &( *aasworld ).areas[areanum];
optarea = &optimized->areas[areanum];
memcpy( optarea, area, sizeof( aas_area_t ) );
optarea->numfaces = 0;
optarea->firstface = optimized->faceindexsize;
for ( i = 0; i < area->numfaces; i++ )
{
facenum = ( *aasworld ).faceindex[area->firstface + i];
optfacenum = AAS_OptimizeFace( optimized, facenum );
if ( optfacenum ) {
optimized->faceindex[optarea->firstface + optarea->numfaces] = optfacenum;
optarea->numfaces++;
optimized->faceindexsize++;
} //end if
} //end for
} //end of the function AAS_OptimizeArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_OptimizeAlloc( optimized_t *optimized ) {
optimized->vertexes = (aas_vertex_t *) GetClearedMemory( ( *aasworld ).numvertexes * sizeof( aas_vertex_t ) );
optimized->numvertexes = 0;
optimized->edges = (aas_edge_t *) GetClearedMemory( ( *aasworld ).numedges * sizeof( aas_edge_t ) );
optimized->numedges = 1; //edge zero is a dummy
optimized->edgeindex = (aas_edgeindex_t *) GetClearedMemory( ( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) );
optimized->edgeindexsize = 0;
optimized->faces = (aas_face_t *) GetClearedMemory( ( *aasworld ).numfaces * sizeof( aas_face_t ) );
optimized->numfaces = 1; //face zero is a dummy
optimized->faceindex = (aas_faceindex_t *) GetClearedMemory( ( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) );
optimized->faceindexsize = 0;
optimized->areas = (aas_area_t *) GetClearedMemory( ( *aasworld ).numareas * sizeof( aas_area_t ) );
optimized->numareas = ( *aasworld ).numareas;
//
optimized->vertexoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numvertexes * sizeof( int ) );
optimized->edgeoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numedges * sizeof( int ) );
optimized->faceoptimizeindex = (int *) GetClearedMemory( ( *aasworld ).numfaces * sizeof( int ) );
} //end of the function AAS_OptimizeAlloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_OptimizeStore( optimized_t *optimized ) {
//store the optimized vertexes
if ( ( *aasworld ).vertexes ) {
FreeMemory( ( *aasworld ).vertexes );
}
( *aasworld ).vertexes = optimized->vertexes;
( *aasworld ).numvertexes = optimized->numvertexes;
//store the optimized edges
if ( ( *aasworld ).edges ) {
FreeMemory( ( *aasworld ).edges );
}
( *aasworld ).edges = optimized->edges;
( *aasworld ).numedges = optimized->numedges;
//store the optimized edge index
if ( ( *aasworld ).edgeindex ) {
FreeMemory( ( *aasworld ).edgeindex );
}
( *aasworld ).edgeindex = optimized->edgeindex;
( *aasworld ).edgeindexsize = optimized->edgeindexsize;
//store the optimized faces
if ( ( *aasworld ).faces ) {
FreeMemory( ( *aasworld ).faces );
}
( *aasworld ).faces = optimized->faces;
( *aasworld ).numfaces = optimized->numfaces;
//store the optimized face index
if ( ( *aasworld ).faceindex ) {
FreeMemory( ( *aasworld ).faceindex );
}
( *aasworld ).faceindex = optimized->faceindex;
( *aasworld ).faceindexsize = optimized->faceindexsize;
//store the optimized areas
if ( ( *aasworld ).areas ) {
FreeMemory( ( *aasworld ).areas );
}
( *aasworld ).areas = optimized->areas;
( *aasworld ).numareas = optimized->numareas;
//free optimize indexes
FreeMemory( optimized->vertexoptimizeindex );
FreeMemory( optimized->edgeoptimizeindex );
FreeMemory( optimized->faceoptimizeindex );
} //end of the function AAS_OptimizeStore
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_Optimize( void ) {
int i, sign;
optimized_t optimized;
AAS_OptimizeAlloc( &optimized );
for ( i = 1; i < ( *aasworld ).numareas; i++ )
{
AAS_OptimizeArea( &optimized, i );
} //end for
//reset the reachability face pointers
for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ )
{
//NOTE: for TRAVEL_ELEVATOR the facenum is the model number of
// the elevator
if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_ELEVATOR ) {
continue;
}
//NOTE: for TRAVEL_JUMPPAD the facenum is the Z velocity and the edgenum is the hor velocity
if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_JUMPPAD ) {
continue;
}
//NOTE: for TRAVEL_FUNCBOB the facenum and edgenum contain other coded information
if ( ( *aasworld ).reachability[i].traveltype == TRAVEL_FUNCBOB ) {
continue;
}
//
sign = ( *aasworld ).reachability[i].facenum;
( *aasworld ).reachability[i].facenum = optimized.faceoptimizeindex[abs( ( *aasworld ).reachability[i].facenum )];
if ( sign < 0 ) {
( *aasworld ).reachability[i].facenum = -( *aasworld ).reachability[i].facenum;
}
sign = ( *aasworld ).reachability[i].edgenum;
( *aasworld ).reachability[i].edgenum = optimized.edgeoptimizeindex[abs( ( *aasworld ).reachability[i].edgenum )];
if ( sign < 0 ) {
( *aasworld ).reachability[i].edgenum = -( *aasworld ).reachability[i].edgenum;
}
} //end for
//store the optimized AAS data into (*aasworld)
AAS_OptimizeStore( &optimized );
//print some nice stuff :)
botimport.Print( PRT_MESSAGE, "AAS data optimized.\n" );
} //end of the function AAS_Optimize

View File

@ -0,0 +1,39 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_optimize.h
*
* desc: AAS
*
*
*****************************************************************************/
void AAS_Optimize( void );

4480
src/botlib/be_aas_reach.c Normal file

File diff suppressed because it is too large Load Diff

74
src/botlib/be_aas_reach.h Normal file
View File

@ -0,0 +1,74 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_reach.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//initialize calculating the reachabilities
void AAS_InitReachability( void );
//continue calculating the reachabilities
int AAS_ContinueInitReachability( float time );
//
int AAS_BestReachableLinkArea( aas_link_t *areas );
#endif //AASINTERN
//returns true if the are has reachabilities to other areas
int AAS_AreaReachability( int areanum );
//returns the best reachable area and goal origin for a bounding box at the given origin
int AAS_BestReachableArea( vec3_t origin, vec3_t mins, vec3_t maxs, vec3_t goalorigin );
//returns the next reachability using the given model
int AAS_NextModelReachability( int num, int modelnum );
//returns the total area of the ground faces of the given area
float AAS_AreaGroundFaceArea( int areanum );
//returns true if the area is crouch only
int AAS_AreaCrouch( int areanum );
//returns true if a player can swim in this area
int AAS_AreaSwim( int areanum );
//returns true if the area is filled with a liquid
int AAS_AreaLiquid( int areanum );
//returns true if the area contains lava
int AAS_AreaLava( int areanum );
//returns true if the area contains slime
int AAS_AreaSlime( int areanum );
//returns true if the area has one or more ground faces
int AAS_AreaGrounded( int areanum );
//returns true if the area has one or more ladder faces
int AAS_AreaLadder( int areanum );
//returns true if the area is a jump pad
int AAS_AreaJumpPad( int areanum );
//returns true if the area is donotenter
int AAS_AreaDoNotEnter( int areanum );
//returns true if the area is donotenterlarge
int AAS_AreaDoNotEnterLarge( int areanum );

2640
src/botlib/be_aas_route.c Normal file

File diff suppressed because it is too large Load Diff

68
src/botlib/be_aas_route.h Normal file
View File

@ -0,0 +1,68 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_route.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
//initialize the AAS routing
void AAS_InitRouting( void );
//free the AAS routing caches
void AAS_FreeRoutingCaches( void );
//returns the travel time from start to end in the given area
unsigned short int AAS_AreaTravelTime( int areanum, vec3_t start, vec3_t end );
//
void AAS_CreateAllRoutingCache( void );
//
void AAS_RoutingInfo( void );
#endif //AASINTERN
//returns the travel flag for the given travel type
int AAS_TravelFlagForType( int traveltype );
//
int AAS_AreaContentsTravelFlag( int areanum );
//returns the index of the next reachability for the given area
int AAS_NextAreaReachability( int areanum, int reachnum );
//returns the reachability with the given index
void AAS_ReachabilityFromNum( int num, struct aas_reachability_s *reach );
//returns a random goal area and goal origin
int AAS_RandomGoalArea( int areanum, int travelflags, int *goalareanum, vec3_t goalorigin );
//returns the travel time within the given area from start to end
unsigned short int AAS_AreaTravelTime( int areanum, vec3_t start, vec3_t end );
//returns the travel time from the area to the goal area using the given travel flags
int AAS_AreaTravelTimeToGoalArea( int areanum, vec3_t origin, int goalareanum, int travelflags );
//returns the travel time from the area to the goal area using the given travel flags
int AAS_AreaTravelTimeToGoalAreaCheckLoop( int areanum, vec3_t origin, int goalareanum, int travelflags, int loopareanum );
extern int BotFuzzyPointReachabilityArea( vec3_t origin );

View File

@ -0,0 +1,271 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_routealt.c
*
* desc: AAS
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_utils.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
//#define ENABLE_ALTROUTING
typedef struct midrangearea_s
{
int valid;
unsigned short starttime;
unsigned short goaltime;
} midrangearea_t;
midrangearea_t *midrangeareas;
int *clusterareas;
int numclusterareas;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_AltRoutingFloodCluster_r( int areanum ) {
int i, otherareanum;
aas_area_t *area;
aas_face_t *face;
//add the current area to the areas of the current cluster
clusterareas[numclusterareas] = areanum;
numclusterareas++;
//remove the area from the mid range areas
midrangeareas[areanum].valid = qfalse;
//flood to other areas through the faces of this area
area = &( *aasworld ).areas[areanum];
for ( i = 0; i < area->numfaces; i++ )
{
face = &( *aasworld ).faces[abs( ( *aasworld ).faceindex[area->firstface + i] )];
//get the area at the other side of the face
if ( face->frontarea == areanum ) {
otherareanum = face->backarea;
} else { otherareanum = face->frontarea;}
//if there is an area at the other side of this face
if ( !otherareanum ) {
continue;
}
//if the other area is not a midrange area
if ( !midrangeareas[otherareanum].valid ) {
continue;
}
//
AAS_AltRoutingFloodCluster_r( otherareanum );
} //end for
} //end of the function AAS_AltRoutingFloodCluster_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_AlternativeRouteGoals( vec3_t start, vec3_t goal, int travelflags,
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
int color ) {
#ifndef ENABLE_ALTROUTING
return 0;
#else
int i, j, startareanum, goalareanum, bestareanum;
int numaltroutegoals, nummidrangeareas;
int starttime, goaltime, goaltraveltime;
float dist, bestdist;
vec3_t mid, dir;
#ifdef DEBUG
int startmillisecs;
startmillisecs = Sys_MilliSeconds();
#endif
startareanum = AAS_PointAreaNum( start );
if ( !startareanum ) {
return 0;
}
goalareanum = AAS_PointAreaNum( goal );
if ( !goalareanum ) {
return 0;
}
//travel time towards the goal area
goaltraveltime = AAS_AreaTravelTimeToGoalArea( startareanum, start, goalareanum, travelflags );
//clear the midrange areas
memset( midrangeareas, 0, ( *aasworld ).numareas * sizeof( midrangearea_t ) );
numaltroutegoals = 0;
//
nummidrangeareas = 0;
//
for ( i = 1; i < ( *aasworld ).numareas; i++ )
{
//
if ( !( ( *aasworld ).areasettings[i].contents & AREACONTENTS_ROUTEPORTAL ) ) {
continue;
}
//if the area has no reachabilities
if ( !AAS_AreaReachability( i ) ) {
continue;
}
//tavel time from the area to the start area
starttime = AAS_AreaTravelTimeToGoalArea( startareanum, start, i, travelflags );
if ( !starttime ) {
continue;
}
//if the travel time from the start to the area is greater than the shortest goal travel time
if ( starttime > 1.5 * goaltraveltime ) {
continue;
}
//travel time from the area to the goal area
goaltime = AAS_AreaTravelTimeToGoalArea( i, NULL, goalareanum, travelflags );
if ( !goaltime ) {
continue;
}
//if the travel time from the area to the goal is greater than the shortest goal travel time
if ( goaltime > 1.5 * goaltraveltime ) {
continue;
}
//this is a mid range area
midrangeareas[i].valid = qtrue;
midrangeareas[i].starttime = starttime;
midrangeareas[i].goaltime = goaltime;
Log_Write( "%d midrange area %d", nummidrangeareas, i );
nummidrangeareas++;
} //end for
//
for ( i = 1; i < ( *aasworld ).numareas; i++ )
{
if ( !midrangeareas[i].valid ) {
continue;
}
//get the areas in one cluster
numclusterareas = 0;
AAS_AltRoutingFloodCluster_r( i );
//now we've got a cluster with areas through which an alternative route could go
//get the 'center' of the cluster
VectorClear( mid );
for ( j = 0; j < numclusterareas; j++ )
{
VectorAdd( mid, ( *aasworld ).areas[clusterareas[j]].center, mid );
} //end for
VectorScale( mid, 1.0 / numclusterareas, mid );
//get the area closest to the center of the cluster
bestdist = 999999;
bestareanum = 0;
for ( j = 0; j < numclusterareas; j++ )
{
VectorSubtract( mid, ( *aasworld ).areas[clusterareas[j]].center, dir );
dist = VectorLength( dir );
if ( dist < bestdist ) {
bestdist = dist;
bestareanum = clusterareas[j];
} //end if
} //end for
//now we've got an area for an alternative route
//FIXME: add alternative goal origin
VectorCopy( ( *aasworld ).areas[bestareanum].center, altroutegoals[numaltroutegoals].origin );
altroutegoals[numaltroutegoals].areanum = bestareanum;
altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime;
altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime;
altroutegoals[numaltroutegoals].extratraveltime =
( midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime ) -
goaltraveltime;
numaltroutegoals++;
//
#ifdef DEBUG
botimport.Print( PRT_MESSAGE, "alternative route goal area %d, numclusterareas = %d\n", bestareanum, numclusterareas );
if ( color ) {
AAS_DrawPermanentCross( ( *aasworld ).areas[bestareanum].center, 10, color );
} //end if
//AAS_ShowArea(bestarea, qtrue);
#endif
//don't return more than the maximum alternative route goals
if ( numaltroutegoals >= maxaltroutegoals ) {
break;
}
} //end for
botimport.Print( PRT_MESSAGE, "%d alternative route goals\n", numaltroutegoals );
#ifdef DEBUG
botimport.Print( PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs );
#endif
return numaltroutegoals;
#endif
} //end of the function AAS_AlternativeRouteGoals
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InitAlternativeRouting( void ) {
#ifdef ENABLE_ALTROUTING
if ( midrangeareas ) {
FreeMemory( midrangeareas );
}
midrangeareas = (midrangearea_t *) GetMemory( ( *aasworld ).numareas * sizeof( midrangearea_t ) );
if ( clusterareas ) {
FreeMemory( clusterareas );
}
clusterareas = (int *) GetMemory( aasworld.numareas * sizeof( int ) );
#endif
} //end of the function AAS_InitAlternativeRouting
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShutdownAlternativeRouting( void ) {
#ifdef ENABLE_ALTROUTING
if ( midrangeareas ) {
FreeMemory( midrangeareas );
}
midrangeareas = NULL;
if ( clusterareas ) {
FreeMemory( clusterareas );
}
clusterareas = NULL;
numclusterareas = 0;
#endif
}

View File

@ -0,0 +1,46 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_routealt.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
void AAS_InitAlternativeRouting( void );
void AAS_ShutdownAlternativeRouting( void );
#endif //AASINTERN
int AAS_AlternativeRouteGoals( vec3_t start, vec3_t goal, int travelflags,
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
int color );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: be_aas_routetable.h
// Function: Area Awareness System, Route-table defines
// Programmer: Ridah
// Tab Size: 3
//===========================================================================
#ifndef RT_DEFINED
#define RT_DEFINED
#define RTBID ( ( 'B' << 24 ) + ( 'T' << 16 ) + ( 'R' << 8 ) + 'X' )
#define RTBVERSION 17
#define RTB_BADTRAVELFLAGS ( TFL_JUMPPAD | TFL_ROCKETJUMP | TFL_BFGJUMP | TFL_GRAPPLEHOOK | TFL_DOUBLEJUMP | TFL_RAMPJUMP | TFL_STRAFEJUMP | TFL_LAVA ) //----(SA) modified since slime is no longer deadly
//#define RTB_BADTRAVELFLAGS (TFL_JUMPPAD|TFL_ROCKETJUMP|TFL_BFGJUMP|TFL_GRAPPLEHOOK|TFL_DOUBLEJUMP|TFL_RAMPJUMP|TFL_STRAFEJUMP|TFL_SLIME|TFL_LAVA)
#define MAX_VISIBLE_AREAS 1024 // going over this limit will result in excessive memory usage, try and keep RANGE low enough so this limit won't be reached
#define MAX_LOCALTRAVELTIME 60 // use this to tweak memory usage (reduces parent count, increases local count (and cpu usage) - find a balance)
#define MAX_PARENTS 8192
extern int disable_routetable;
//....................................................................
// Permanent structures (in order of highest to lowest count)
typedef struct
{
unsigned short int reachable_index; // reachability index (from this area's first reachability link in the world) to head for to get to the destination
unsigned short int travel_time; // travel time (!)
} aas_rt_route_t;
typedef struct
{
unsigned short int parent; // parent we belong to
unsigned short int childIndex; // our index in the parent's list of children
// unsigned short int numRouteIndexes;
// int startRouteIndexes;
} aas_rt_parent_link_t;
typedef struct
{
unsigned short int areanum;
// int numLocalRoutes;
// int startLocalRoutes;
// int numParentRoutes;
// int startParentRoutes;
int numParentLinks;
int startParentLinks;
} aas_rt_child_t;
typedef struct
{
unsigned short int areanum; // out area number in the global list
int numParentChildren;
int startParentChildren;
int numVisibleParents;
int startVisibleParents; // list of other parents that we can see (used for fast hide/retreat checks)
// int startParentTravelTimes;
} aas_rt_parent_t;
// this is what each aasworld attaches itself to
typedef struct
{
unsigned short int *areaChildIndexes; // each aas area that is part of the Route-Table has a pointer here to their position in the list of children
int numChildren;
aas_rt_child_t *children;
int numParents;
aas_rt_parent_t *parents;
int numParentChildren;
unsigned short int *parentChildren;
int numVisibleParents;
unsigned short int *visibleParents;
// int numLocalRoutes;
// aas_rt_route_t *localRoutes; // the list of routes to all other local areas
// int numParentRoutes;
// unsigned char *parentRoutes; // reachability to each other parent, as an offset from our first reachability
int numParentLinks;
aas_rt_parent_link_t *parentLinks; // links from each child to the parent's it belongs to
// int numParentTravelTimes;
// unsigned short int *parentTravelTimes; // travel times between all parent areas
// int numRouteIndexes;
// unsigned short int *routeIndexes; // each parentLink has a list within here, which
// contains the local indexes of each child that
// belongs to the parent, within the source child's
// localroutes
} aas_rt_t;
//....................................................................
// Temp structures used only during route-table contruction
typedef struct
{
unsigned short int numvisible; // number of areas that are visible and within range
unsigned short int
visible[MAX_VISIBLE_AREAS]; // list of area indexes of visible and within range areas
} aas_area_buildlocalinfo_t;
typedef struct aas_parent_link_s
{
unsigned short int parent; // parent we belong to
unsigned short int childindex; // our index in the parent's list of children
unsigned short int *routeindexes; // for this parent link, list the children that fall under that parent, and their associated indexes in our localroutes table
struct aas_parent_link_s *next;
} aas_parent_link_t;
typedef struct
{
unsigned short int areanum;
unsigned short int numlocal;
aas_parent_link_t *parentlink; // linked list of parents that we belong to
aas_rt_route_t *localroutes; // the list of routes to all other local areas
aas_rt_route_t *parentroutes; // the list of routes to all other parent areas
} aas_area_childlocaldata_t;
typedef struct
{
unsigned short int areanum; // out area number in the global list
unsigned short int numchildren;
unsigned short int *children;
unsigned short int numVisibleParents;
unsigned short int *visibleParents; // list of other parents that we can see (used for fast hide/retreat checks)
} aas_area_parent_t;
#endif // RT_DEFINED
//....................................................................
void AAS_RT_BuildRouteTable( void );
void AAS_RT_ShowRoute( vec3_t srcpos, int srcnum, int destnum );
aas_rt_route_t *AAS_RT_GetRoute( int srcnum, vec3_t origin, int destnum );
void AAS_RT_ShutdownRouteTable( void );
qboolean AAS_RT_GetHidePos( vec3_t srcpos, int srcnum, int srcarea, vec3_t destpos, int destnum, int destarea, vec3_t returnPos );
int AAS_RT_GetReachabilityIndex( int areanum, int reachIndex );

1274
src/botlib/be_aas_sample.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_aas_sample.h
*
* desc: AAS
*
*
*****************************************************************************/
#ifdef AASINTERN
void AAS_InitAASLinkHeap( void );
void AAS_InitAASLinkedEntities( void );
void AAS_FreeAASLinkHeap( void );
void AAS_FreeAASLinkedEntities( void );
aas_face_t *AAS_AreaGroundFace( int areanum, vec3_t point );
aas_face_t *AAS_TraceEndFace( aas_trace_t *trace );
aas_plane_t *AAS_PlaneFromNum( int planenum );
aas_link_t *AAS_AASLinkEntity( vec3_t absmins, vec3_t absmaxs, int entnum );
aas_link_t *AAS_LinkEntityClientBBox( vec3_t absmins, vec3_t absmaxs, int entnum, int presencetype );
qboolean AAS_PointInsideFace( int facenum, vec3_t point, float epsilon );
qboolean AAS_InsideFace( aas_face_t *face, vec3_t pnormal, vec3_t point, float epsilon );
void AAS_UnlinkFromAreas( aas_link_t *areas );
#endif //AASINTERN
//returns the mins and maxs of the bounding box for the given presence type
void AAS_PresenceTypeBoundingBox( int presencetype, vec3_t mins, vec3_t maxs );
//returns the cluster the area is in (negative portal number if the area is a portal)
int AAS_AreaCluster( int areanum );
//returns the presence type(s) of the area
int AAS_AreaPresenceType( int areanum );
//returns the presence type(s) at the given point
int AAS_PointPresenceType( vec3_t point );
//returns the result of the trace of a client bbox
aas_trace_t AAS_TraceClientBBox( vec3_t start, vec3_t end, int presencetype, int passent );
//stores the areas the trace went through and returns the number of passed areas
int AAS_TraceAreas( vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas );
//returns the area the point is in
int AAS_PointAreaNum( vec3_t point );
//returns the plane the given face is in
void AAS_FacePlane( int facenum, vec3_t normal, float *dist );
int AAS_BBoxAreas( vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas );

765
src/botlib/be_ai_char.c Normal file
View File

@ -0,0 +1,765 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ai_char.c
*
* desc: bot characters
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_log.h"
#include "l_memory.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_libvar.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "../game/be_ai_char.h"
#define MAX_CHARACTERISTICS 80
#define CT_INTEGER 1
#define CT_FLOAT 2
#define CT_STRING 3
#define DEFAULT_CHARACTER "bots/default_c.c"
//characteristic value
union cvalue
{
int integer;
float _float;
char *string;
};
//a characteristic
typedef struct bot_characteristic_s
{
char type; //characteristic type
union cvalue value; //characteristic value
} bot_characteristic_t;
//a bot character
typedef struct bot_character_s
{
char filename[MAX_QPATH];
int skill;
bot_characteristic_t c[1]; //variable sized
} bot_character_t;
bot_character_t *botcharacters[MAX_CLIENTS + 1];
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
bot_character_t *BotCharacterFromHandle( int handle ) {
if ( handle <= 0 || handle > MAX_CLIENTS ) {
botimport.Print( PRT_FATAL, "character handle %d out of range\n", handle );
return NULL;
} //end if
if ( !botcharacters[handle] ) {
botimport.Print( PRT_FATAL, "invalid character %d\n", handle );
return NULL;
} //end if
return botcharacters[handle];
} //end of the function BotCharacterFromHandle
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotDumpCharacter( bot_character_t *ch ) {
int i;
Log_Write( "%s", ch->filename );
Log_Write( "skill %d\n", ch->skill );
Log_Write( "{\n" );
for ( i = 0; i < MAX_CHARACTERISTICS; i++ )
{
switch ( ch->c[i].type )
{
case CT_INTEGER: Log_Write( " %4d %d\n", i, ch->c[i].value.integer ); break;
case CT_FLOAT: Log_Write( " %4d %f\n", i, ch->c[i].value._float ); break;
case CT_STRING: Log_Write( " %4d %s\n", i, ch->c[i].value.string ); break;
} //end case
} //end for
Log_Write( "}\n" );
} //end of the function BotDumpCharacter
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeCharacterStrings( bot_character_t *ch ) {
int i;
for ( i = 0; i < MAX_CHARACTERISTICS; i++ )
{
if ( ch->c[i].type == CT_STRING ) {
FreeMemory( ch->c[i].value.string );
} //end if
} //end for
} //end of the function BotFreeCharacterStrings
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeCharacter2( int handle ) {
if ( handle <= 0 || handle > MAX_CLIENTS ) {
botimport.Print( PRT_FATAL, "character handle %d out of range\n", handle );
return;
} //end if
if ( !botcharacters[handle] ) {
botimport.Print( PRT_FATAL, "invalid character %d\n", handle );
return;
} //end if
BotFreeCharacterStrings( botcharacters[handle] );
FreeMemory( botcharacters[handle] );
botcharacters[handle] = NULL;
} //end of the function BotFreeCharacter2
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeCharacter( int handle ) {
if ( !LibVarGetValue( "bot_reloadcharacters" ) ) {
return;
}
BotFreeCharacter2( handle );
} //end of the function BotFreeCharacter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotDefaultCharacteristics( bot_character_t *ch, bot_character_t *defaultch ) {
int i;
for ( i = 0; i < MAX_CHARACTERISTICS; i++ )
{
if ( ch->c[i].type ) {
continue;
}
//
if ( defaultch->c[i].type == CT_FLOAT ) {
ch->c[i].type = CT_FLOAT;
ch->c[i].value._float = defaultch->c[i].value._float;
} //end if
else if ( defaultch->c[i].type == CT_INTEGER ) {
ch->c[i].type = CT_INTEGER;
ch->c[i].value.integer = defaultch->c[i].value.integer;
} //end else if
else if ( defaultch->c[i].type == CT_STRING ) {
ch->c[i].type = CT_STRING;
ch->c[i].value.string = (char *) GetMemory( strlen( defaultch->c[i].value.string ) + 1 );
strcpy( ch->c[i].value.string, defaultch->c[i].value.string );
} //end else if
} //end for
} //end of the function BotDefaultCharacteristics
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bot_character_t *BotLoadCharacterFromFile( char *charfile, int skill ) {
int indent, index, foundcharacter;
bot_character_t *ch;
source_t *source;
token_t token;
foundcharacter = qfalse;
//a bot character is parsed in two phases
source = LoadSourceFile( charfile );
if ( !source ) {
botimport.Print( PRT_ERROR, "counldn't load %s\n", charfile );
return NULL;
} //end if
ch = (bot_character_t *) GetClearedMemory( sizeof( bot_character_t ) +
MAX_CHARACTERISTICS * sizeof( bot_characteristic_t ) );
strcpy( ch->filename, charfile );
while ( PC_ReadToken( source, &token ) )
{
if ( !strcmp( token.string, "skill" ) ) {
if ( !PC_ExpectTokenType( source, TT_NUMBER, 0, &token ) ) {
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
if ( !PC_ExpectTokenString( source, "{" ) ) {
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
//if it's the correct skill
if ( skill < 0 || token.intvalue == skill ) {
foundcharacter = qtrue;
ch->skill = token.intvalue;
while ( PC_ExpectAnyToken( source, &token ) )
{
if ( !strcmp( token.string, "}" ) ) {
break;
}
if ( token.type != TT_NUMBER || !( token.subtype & TT_INTEGER ) ) {
SourceError( source, "expected integer index, found %s\n", token.string );
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
index = token.intvalue;
if ( index < 0 || index > MAX_CHARACTERISTICS ) {
SourceError( source, "characteristic index out of range [0, %d]\n", MAX_CHARACTERISTICS );
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
if ( ch->c[index].type ) {
SourceError( source, "characteristic %d already initialized\n", index );
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
if ( token.type == TT_NUMBER ) {
if ( token.subtype & TT_FLOAT ) {
ch->c[index].value._float = token.floatvalue;
ch->c[index].type = CT_FLOAT;
} //end if
else
{
ch->c[index].value.integer = token.intvalue;
ch->c[index].type = CT_INTEGER;
} //end else
} //end if
else if ( token.type == TT_STRING ) {
StripDoubleQuotes( token.string );
ch->c[index].value.string = GetMemory( strlen( token.string ) + 1 );
strcpy( ch->c[index].value.string, token.string );
ch->c[index].type = CT_STRING;
} //end else if
else
{
SourceError( source, "expected integer, float or string, found %s\n", token.string );
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end else
} //end if
break;
} //end if
else
{
indent = 1;
while ( indent )
{
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
if ( !strcmp( token.string, "{" ) ) {
indent++;
} else if ( !strcmp( token.string, "}" ) ) {
indent--;
}
} //end while
} //end else
} //end if
else
{
SourceError( source, "unknown definition %s\n", token.string );
FreeSource( source );
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end else
} //end while
FreeSource( source );
//
if ( !foundcharacter ) {
BotFreeCharacterStrings( ch );
FreeMemory( ch );
return NULL;
} //end if
return ch;
} //end of the function BotLoadCharacterFromFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotFindCachedCharacter( char *charfile, int skill ) {
int handle;
for ( handle = 1; handle <= MAX_CLIENTS; handle++ )
{
if ( !botcharacters[handle] ) {
continue;
}
if ( strcmp( botcharacters[handle]->filename, charfile ) == 0 &&
( skill < 0 || botcharacters[handle]->skill == skill ) ) {
return handle;
} //end if
} //end for
return 0;
} //end of the function BotFindCachedCharacter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadCachedCharacter( char *charfile, int skill, int reload ) {
int handle, cachedhandle;
bot_character_t *ch = NULL;
#ifdef DEBUG
int starttime;
starttime = Sys_MilliSeconds();
#endif //DEBUG
//find a free spot for a character
for ( handle = 1; handle <= MAX_CLIENTS; handle++ )
{
if ( !botcharacters[handle] ) {
break;
}
} //end for
if ( handle > MAX_CLIENTS ) {
return 0;
}
//try to load a cached character with the given skill
if ( !reload ) {
cachedhandle = BotFindCachedCharacter( charfile, skill );
if ( cachedhandle ) {
botimport.Print( PRT_MESSAGE, "loaded cached skill %d from %s\n", skill, charfile );
return cachedhandle;
} //end if
} //end else
//try to load the character with the given skill
ch = BotLoadCharacterFromFile( charfile, skill );
if ( ch ) {
botcharacters[handle] = ch;
//
botimport.Print( PRT_MESSAGE, "loaded skill %d from %s\n", skill, charfile );
#ifdef DEBUG
if ( bot_developer ) {
botimport.Print( PRT_MESSAGE, "skill %d loaded in %d msec from %s\n", skill, Sys_MilliSeconds() - starttime, charfile );
} //end if
#endif //DEBUG
return handle;
} //end if
//
botimport.Print( PRT_WARNING, "couldn't find skill %d in %s\n", skill, charfile );
//
if ( !reload ) {
//try to load a cached default character with the given skill
cachedhandle = BotFindCachedCharacter( "bots/default_c.c", skill );
if ( cachedhandle ) {
botimport.Print( PRT_MESSAGE, "loaded cached default skill %d from %s\n", skill, charfile );
return cachedhandle;
} //end if
} //end if
//try to load the default character with the given skill
ch = BotLoadCharacterFromFile( DEFAULT_CHARACTER, skill );
if ( ch ) {
botcharacters[handle] = ch;
botimport.Print( PRT_MESSAGE, "loaded default skill %d from %s\n", skill, charfile );
return handle;
} //end if
//
if ( !reload ) {
//try to load a cached character with any skill
cachedhandle = BotFindCachedCharacter( charfile, -1 );
if ( cachedhandle ) {
botimport.Print( PRT_MESSAGE, "loaded cached skill %d from %s\n", botcharacters[cachedhandle]->skill, charfile );
return cachedhandle;
} //end if
} //end if
//try to load a character with any skill
ch = BotLoadCharacterFromFile( charfile, -1 );
if ( ch ) {
botcharacters[handle] = ch;
botimport.Print( PRT_MESSAGE, "loaded skill %d from %s\n", ch->skill, charfile );
return handle;
} //end if
//
if ( !reload ) {
//try to load a cached character with any skill
cachedhandle = BotFindCachedCharacter( DEFAULT_CHARACTER, -1 );
if ( cachedhandle ) {
botimport.Print( PRT_MESSAGE, "loaded cached default skill %d from %s\n", botcharacters[cachedhandle]->skill, charfile );
return cachedhandle;
} //end if
} //end if
//try to load a character with any skill
ch = BotLoadCharacterFromFile( DEFAULT_CHARACTER, -1 );
if ( ch ) {
botcharacters[handle] = ch;
botimport.Print( PRT_MESSAGE, "loaded default skill %d from %s\n", ch->skill, charfile );
return handle;
} //end if
//
botimport.Print( PRT_WARNING, "couldn't load any skill from %s\n", charfile );
//couldn't load any character
return 0;
} //end of the function BotLoadCachedCharacter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadCharacterSkill( char *charfile, int skill ) {
int ch, defaultch;
defaultch = BotLoadCachedCharacter( DEFAULT_CHARACTER, skill, qfalse );
ch = BotLoadCachedCharacter( charfile, skill, LibVarGetValue( "bot_reloadcharacters" ) );
if ( defaultch && ch ) {
BotDefaultCharacteristics( botcharacters[ch], botcharacters[defaultch] );
} //end if
return ch;
} //end of the function BotLoadCharacterSkill
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotInterpolateCharacters( int handle1, int handle2, int desiredskill ) {
bot_character_t *ch1, *ch2, *out;
int i, handle;
float scale;
ch1 = BotCharacterFromHandle( handle1 );
ch2 = BotCharacterFromHandle( handle2 );
if ( !ch1 || !ch2 ) {
return 0;
}
//find a free spot for a character
for ( handle = 1; handle <= MAX_CLIENTS; handle++ )
{
if ( !botcharacters[handle] ) {
break;
}
} //end for
if ( handle > MAX_CLIENTS ) {
return 0;
}
out = (bot_character_t *) GetClearedMemory( sizeof( bot_character_t ) +
MAX_CHARACTERISTICS * sizeof( bot_characteristic_t ) );
out->skill = desiredskill;
strcpy( out->filename, ch1->filename );
botcharacters[handle] = out;
scale = (float) ( desiredskill - 1 ) / ( ch2->skill - ch1->skill );
for ( i = 0; i < MAX_CHARACTERISTICS; i++ )
{
//
if ( ch1->c[i].type == CT_FLOAT && ch2->c[i].type == CT_FLOAT ) {
out->c[i].type = CT_FLOAT;
out->c[i].value._float = ch1->c[i].value._float +
( ch2->c[i].value._float - ch1->c[i].value._float ) * scale;
} //end if
else if ( ch1->c[i].type == CT_INTEGER ) {
out->c[i].type = CT_INTEGER;
out->c[i].value.integer = ch1->c[i].value.integer;
} //end else if
else if ( ch1->c[i].type == CT_STRING ) {
out->c[i].type = CT_STRING;
out->c[i].value.string = (char *) GetMemory( strlen( ch1->c[i].value.string ) + 1 );
strcpy( out->c[i].value.string, ch1->c[i].value.string );
} //end else if
} //end for
return handle;
} //end of the function BotInterpolateCharacters
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadCharacter( char *charfile, int skill ) {
int skill1, skill4, handle;
//make sure the skill is in the valid range
if ( skill < 1 ) {
skill = 1;
} else if ( skill > 5 ) {
skill = 5;
}
//skill 1, 4 and 5 should be available in the character files
if ( skill == 1 || skill == 4 || skill == 5 ) {
return BotLoadCharacterSkill( charfile, skill );
} //end if
//check if there's a cached skill 2 or 3
handle = BotFindCachedCharacter( charfile, skill );
if ( handle ) {
botimport.Print( PRT_MESSAGE, "loaded cached skill %d from %s\n", skill, charfile );
return handle;
} //end if
//load skill 1 and 4
skill1 = BotLoadCharacterSkill( charfile, 1 );
if ( !skill1 ) {
return 0;
}
skill4 = BotLoadCharacterSkill( charfile, 4 );
if ( !skill4 ) {
return skill1;
}
//interpolate between 1 and 4 to create skill 2 or 3
handle = BotInterpolateCharacters( skill1, skill4, skill );
if ( !handle ) {
return 0;
}
//write the character to the log file
BotDumpCharacter( botcharacters[handle] );
//
return handle;
} //end of the function BotLoadCharacter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int CheckCharacteristicIndex( int character, int index ) {
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return qfalse;
}
if ( index < 0 || index >= MAX_CHARACTERISTICS ) {
botimport.Print( PRT_ERROR, "characteristic %d does not exist\n", index );
return qfalse;
} //end if
if ( !ch->c[index].type ) {
botimport.Print( PRT_ERROR, "characteristic %d is not initialized\n", index );
return qfalse;
} //end if
return qtrue;
} //end of the function CheckCharacteristicIndex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float Characteristic_Float( int character, int index ) {
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return 0;
}
//check if the index is in range
if ( !CheckCharacteristicIndex( character, index ) ) {
return 0;
}
//an integer will be converted to a float
if ( ch->c[index].type == CT_INTEGER ) {
return (float) ch->c[index].value.integer;
} //end if
//floats are just returned
else if ( ch->c[index].type == CT_FLOAT ) {
return ch->c[index].value._float;
} //end else if
//cannot convert a string pointer to a float
else
{
botimport.Print( PRT_ERROR, "characteristic %d is not a float\n", index );
return 0;
} //end else if
// return 0;
} //end of the function Characteristic_Float
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float Characteristic_BFloat( int character, int index, float min, float max ) {
float value;
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return 0;
}
if ( min > max ) {
botimport.Print( PRT_ERROR, "cannot bound characteristic %d between %f and %f\n", index, min, max );
return 0;
} //end if
value = Characteristic_Float( character, index );
if ( value < min ) {
return min;
}
if ( value > max ) {
return max;
}
return value;
} //end of the function Characteristic_BFloat
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Characteristic_Integer( int character, int index ) {
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return 0;
}
//check if the index is in range
if ( !CheckCharacteristicIndex( character, index ) ) {
return 0;
}
//an integer will just be returned
if ( ch->c[index].type == CT_INTEGER ) {
return ch->c[index].value.integer;
} //end if
//floats are casted to integers
else if ( ch->c[index].type == CT_FLOAT ) {
return (int) ch->c[index].value._float;
} //end else if
else
{
botimport.Print( PRT_ERROR, "characteristic %d is not a integer\n", index );
return 0;
} //end else if
// return 0;
} //end of the function Characteristic_Integer
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Characteristic_BInteger( int character, int index, int min, int max ) {
int value;
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return 0;
}
if ( min > max ) {
botimport.Print( PRT_ERROR, "cannot bound characteristic %d between %d and %d\n", index, min, max );
return 0;
} //end if
value = Characteristic_Integer( character, index );
if ( value < min ) {
return min;
}
if ( value > max ) {
return max;
}
return value;
} //end of the function Characteristic_BInteger
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Characteristic_String( int character, int index, char *buf, int size ) {
bot_character_t *ch;
ch = BotCharacterFromHandle( character );
if ( !ch ) {
return;
}
//check if the index is in range
if ( !CheckCharacteristicIndex( character, index ) ) {
return;
}
//an integer will be converted to a float
if ( ch->c[index].type == CT_STRING ) {
strncpy( buf, ch->c[index].value.string, size - 1 );
buf[size - 1] = '\0';
return;
} //end if
else
{
botimport.Print( PRT_ERROR, "characteristic %d is not a string\n", index );
return;
} //end else if
return;
} //end of the function Characteristic_String
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotShutdownCharacters( void ) {
int handle;
for ( handle = 1; handle <= MAX_CLIENTS; handle++ )
{
if ( botcharacters[handle] ) {
BotFreeCharacter2( handle );
} //end if
} //end for
} //end of the function BotShutdownCharacters

2883
src/botlib/be_ai_chat.c Normal file

File diff suppressed because it is too large Load Diff

151
src/botlib/be_ai_gen.c Normal file
View File

@ -0,0 +1,151 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ai_gen.c
*
* desc: genetic selection
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "../game/be_ai_gen.h"
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int GeneticSelection( int numranks, float *rankings ) {
float sum, select;
int i, index;
sum = 0;
for ( i = 0; i < numranks; i++ )
{
if ( rankings[i] < 0 ) {
continue;
}
sum += rankings[i];
} //end for
if ( sum > 0 ) {
//select a bot where the ones with the higest rankings have
//the highest chance of being selected
select = random() * sum;
for ( i = 0; i < numranks; i++ )
{
if ( rankings[i] < 0 ) {
continue;
}
sum -= rankings[i];
if ( sum <= 0 ) {
return i;
}
} //end for
} //end if
//select a bot randomly
index = random() * numranks;
for ( i = 0; i < numranks; i++ )
{
if ( rankings[index] >= 0 ) {
return index;
}
index = ( index + 1 ) % numranks;
} //end for
return 0;
} //end of the function GeneticSelection
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int GeneticParentsAndChildSelection( int numranks, float *ranks, int *parent1, int *parent2, int *child ) {
float rankings[256], max;
int i;
if ( numranks > 256 ) {
botimport.Print( PRT_WARNING, "GeneticParentsAndChildSelection: too many bots\n" );
*parent1 = *parent2 = *child = 0;
return qfalse;
} //end if
for ( max = 0, i = 0; i < numranks; i++ )
{
if ( ranks[i] < 0 ) {
continue;
}
max++;
} //end for
if ( max < 3 ) {
botimport.Print( PRT_WARNING, "GeneticParentsAndChildSelection: too few valid bots\n" );
*parent1 = *parent2 = *child = 0;
return qfalse;
} //end if
memcpy( rankings, ranks, sizeof( float ) * numranks );
//select first parent
*parent1 = GeneticSelection( numranks, rankings );
rankings[*parent1] = -1;
//select second parent
*parent2 = GeneticSelection( numranks, rankings );
rankings[*parent2] = -1;
//reverse the rankings
max = 0;
for ( i = 0; i < numranks; i++ )
{
if ( rankings[i] < 0 ) {
continue;
}
if ( rankings[i] > max ) {
max = rankings[i];
}
} //end for
for ( i = 0; i < numranks; i++ )
{
if ( rankings[i] < 0 ) {
continue;
}
rankings[i] = max - rankings[i];
} //end for
//select child
*child = GeneticSelection( numranks, rankings );
return qtrue;
} //end of the function GeneticParentsAndChildSelection

1630
src/botlib/be_ai_goal.c Normal file

File diff suppressed because it is too large Load Diff

3697
src/botlib/be_ai_move.c Normal file

File diff suppressed because it is too large Load Diff

547
src/botlib/be_ai_weap.c Normal file
View File

@ -0,0 +1,547 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weap.c
*
* desc: weapon AI
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_libvar.h"
#include "l_log.h"
#include "l_memory.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_ai_weight.h" //fuzzy weights
#include "../game/be_ai_weap.h"
//#define DEBUG_AI_WEAP
//structure field offsets
#define WEAPON_OFS( x ) (int)&( ( (weaponinfo_t *)0 )->x )
#define PROJECTILE_OFS( x ) (int)&( ( (projectileinfo_t *)0 )->x )
//weapon definition
fielddef_t weaponinfo_fields[] =
{
{"number", WEAPON_OFS( number ), FT_INT}, //weapon number
{"name", WEAPON_OFS( name ), FT_STRING}, //name of the weapon
{"level", WEAPON_OFS( level ), FT_INT},
{"model", WEAPON_OFS( model ), FT_STRING}, //model of the weapon
{"weaponindex", WEAPON_OFS( weaponindex ), FT_INT}, //index of weapon in inventory
{"flags", WEAPON_OFS( flags ), FT_INT}, //special flags
{"projectile", WEAPON_OFS( projectile ), FT_STRING}, //projectile used by the weapon
{"numprojectiles", WEAPON_OFS( numprojectiles ), FT_INT}, //number of projectiles
{"hspread", WEAPON_OFS( hspread ), FT_FLOAT}, //horizontal spread of projectiles (degrees from middle)
{"vspread", WEAPON_OFS( vspread ), FT_FLOAT}, //vertical spread of projectiles (degrees from middle)
{"speed", WEAPON_OFS( speed ), FT_FLOAT}, //speed of the projectile (0 = instant hit)
{"acceleration", WEAPON_OFS( acceleration ), FT_FLOAT}, //"acceleration" * time (in seconds) + "speed" = projectile speed
{"recoil", WEAPON_OFS( recoil ), FT_FLOAT | FT_ARRAY, 3}, //amount of recoil the player gets from the weapon
{"offset", WEAPON_OFS( offset ), FT_FLOAT | FT_ARRAY, 3}, //projectile start offset relative to eye and view angles
{"angleoffset", WEAPON_OFS( angleoffset ), FT_FLOAT | FT_ARRAY, 3}, //offset of the shoot angles relative to the view angles
{"extrazvelocity", WEAPON_OFS( extrazvelocity ), FT_FLOAT}, //extra z velocity the projectile gets
{"ammoamount", WEAPON_OFS( ammoamount ), FT_INT}, //ammo amount used per shot
{"ammoindex", WEAPON_OFS( ammoindex ), FT_INT}, //index of ammo in inventory
{"activate", WEAPON_OFS( activate ), FT_FLOAT}, //time it takes to select the weapon
{"reload", WEAPON_OFS( reload ), FT_FLOAT}, //time it takes to reload the weapon
{"spinup", WEAPON_OFS( spinup ), FT_FLOAT}, //time it takes before first shot
{"spindown", WEAPON_OFS( spindown ), FT_FLOAT}, //time it takes before weapon stops firing
{NULL, 0, 0, 0}
};
//projectile definition
fielddef_t projectileinfo_fields[] =
{
{"name", PROJECTILE_OFS( name ), FT_STRING}, //name of the projectile
{"model", WEAPON_OFS( model ), FT_STRING}, //model of the projectile
{"flags", PROJECTILE_OFS( flags ), FT_INT}, //special flags
{"gravity", PROJECTILE_OFS( gravity ), FT_FLOAT}, //amount of gravity applied to the projectile [0,1]
{"damage", PROJECTILE_OFS( damage ), FT_INT}, //damage of the projectile
{"radius", PROJECTILE_OFS( radius ), FT_FLOAT}, //radius of damage
{"visdamage", PROJECTILE_OFS( visdamage ), FT_INT}, //damage of the projectile to visible entities
{"damagetype", PROJECTILE_OFS( damagetype ), FT_INT}, //type of damage (combination of the DAMAGETYPE_? flags)
{"healthinc", PROJECTILE_OFS( healthinc ), FT_INT}, //health increase the owner gets
{"push", PROJECTILE_OFS( push ), FT_FLOAT}, //amount a player is pushed away from the projectile impact
{"detonation", PROJECTILE_OFS( detonation ), FT_FLOAT}, //time before projectile explodes after fire pressed
{"bounce", PROJECTILE_OFS( bounce ), FT_FLOAT}, //amount the projectile bounces
{"bouncefric", PROJECTILE_OFS( bouncefric ), FT_FLOAT}, //amount the bounce decreases per bounce
{"bouncestop", PROJECTILE_OFS( bouncestop ), FT_FLOAT}, //minimum bounce value before bouncing stops
//recurive projectile definition??
{NULL, 0, 0, 0}
};
structdef_t weaponinfo_struct =
{
sizeof( weaponinfo_t ), weaponinfo_fields
};
structdef_t projectileinfo_struct =
{
sizeof( projectileinfo_t ), projectileinfo_fields
};
//weapon configuration: set of weapons with projectiles
typedef struct weaponconfig_s
{
int numweapons;
int numprojectiles;
projectileinfo_t *projectileinfo;
weaponinfo_t *weaponinfo;
} weaponconfig_t;
//the bot weapon state
typedef struct bot_weaponstate_s
{
struct weightconfig_s *weaponweightconfig; //weapon weight configuration
int *weaponweightindex; //weapon weight index
} bot_weaponstate_t;
bot_weaponstate_t *botweaponstates[MAX_CLIENTS + 1];
weaponconfig_t *weaponconfig;
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
int BotValidWeaponNumber( int weaponnum ) {
if ( weaponnum <= 0 || weaponnum > weaponconfig->numweapons ) {
botimport.Print( PRT_ERROR, "weapon number out of range\n" );
return qfalse;
} //end if
return qtrue;
} //end of the function BotValidWeaponNumber
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
bot_weaponstate_t *BotWeaponStateFromHandle( int handle ) {
if ( handle <= 0 || handle > MAX_CLIENTS ) {
botimport.Print( PRT_FATAL, "move state handle %d out of range\n", handle );
return NULL;
} //end if
if ( !botweaponstates[handle] ) {
botimport.Print( PRT_FATAL, "invalid move state %d\n", handle );
return NULL;
} //end if
return botweaponstates[handle];
} //end of the function BotWeaponStateFromHandle
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef DEBUG_AI_WEAP
void DumpWeaponConfig( weaponconfig_t *wc ) {
FILE *fp;
int i;
fp = Log_FileStruct();
if ( !fp ) {
return;
}
for ( i = 0; i < wc->numprojectiles; i++ )
{
WriteStructure( fp, &projectileinfo_struct, (char *) &wc->projectileinfo[i] );
Log_Flush();
} //end for
for ( i = 0; i < wc->numweapons; i++ )
{
WriteStructure( fp, &weaponinfo_struct, (char *) &wc->weaponinfo[i] );
Log_Flush();
} //end for
} //end of the function DumpWeaponConfig
#endif //DEBUG_AI_WEAP
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
weaponconfig_t *LoadWeaponConfig( char *filename ) {
int max_weaponinfo, max_projectileinfo;
token_t token;
char path[MAX_PATH];
int i, j;
source_t *source;
weaponconfig_t *wc;
weaponinfo_t weaponinfo;
max_weaponinfo = (int) LibVarValue( "max_weaponinfo", "32" );
if ( max_weaponinfo < 0 ) {
botimport.Print( PRT_ERROR, "max_weaponinfo = %d\n", max_weaponinfo );
max_weaponinfo = 32;
LibVarSet( "max_weaponinfo", "32" );
} //end if
max_projectileinfo = (int) LibVarValue( "max_projectileinfo", "32" );
if ( max_projectileinfo < 0 ) {
botimport.Print( PRT_ERROR, "max_projectileinfo = %d\n", max_projectileinfo );
max_projectileinfo = 32;
LibVarSet( "max_projectileinfo", "32" );
} //end if
strncpy( path, filename, MAX_PATH );
source = LoadSourceFile( path );
if ( !source ) {
botimport.Print( PRT_ERROR, "counldn't load %s\n", path );
return NULL;
} //end if
//initialize weapon config
wc = (weaponconfig_t *) GetClearedHunkMemory( sizeof( weaponconfig_t ) +
max_weaponinfo * sizeof( weaponinfo_t ) +
max_projectileinfo * sizeof( projectileinfo_t ) );
wc->weaponinfo = ( weaponinfo_t * )( (char *) wc + sizeof( weaponconfig_t ) );
wc->projectileinfo = ( projectileinfo_t * )( (char *) wc->weaponinfo +
max_weaponinfo * sizeof( weaponinfo_t ) );
wc->numweapons = max_weaponinfo;
wc->numprojectiles = 0;
//parse the source file
while ( PC_ReadToken( source, &token ) )
{
if ( !strcmp( token.string, "weaponinfo" ) ) {
memset( &weaponinfo, 0, sizeof( weaponinfo_t ) );
if ( !ReadStructure( source, &weaponinfo_struct, (char *) &weaponinfo ) ) {
FreeMemory( wc );
FreeSource( source );
return NULL;
} //end if
if ( weaponinfo.number < 0 || weaponinfo.number >= max_weaponinfo ) {
botimport.Print( PRT_ERROR, "weapon info number %d out of range in %s\n", weaponinfo.number, path );
FreeMemory( wc );
FreeSource( source );
return NULL;
} //end if
memcpy( &wc->weaponinfo[weaponinfo.number], &weaponinfo, sizeof( weaponinfo_t ) );
wc->weaponinfo[weaponinfo.number].valid = qtrue;
} //end if
else if ( !strcmp( token.string, "projectileinfo" ) ) {
if ( wc->numprojectiles >= max_projectileinfo ) {
botimport.Print( PRT_ERROR, "more than %d projectiles defined in %s\n", max_projectileinfo, path );
FreeMemory( wc );
FreeSource( source );
return NULL;
} //end if
memset( &wc->projectileinfo[wc->numprojectiles], 0, sizeof( projectileinfo_t ) );
if ( !ReadStructure( source, &projectileinfo_struct, (char *) &wc->projectileinfo[wc->numprojectiles] ) ) {
FreeMemory( wc );
FreeSource( source );
return NULL;
} //end if
wc->numprojectiles++;
} //end if
else
{
botimport.Print( PRT_ERROR, "unknown definition %s in %s\n", token.string, path );
FreeMemory( wc );
FreeSource( source );
return NULL;
} //end else
} //end while
FreeSource( source );
//fix up weapons
for ( i = 0; i < wc->numweapons; i++ )
{
if ( !wc->weaponinfo[i].valid ) {
continue;
}
if ( !wc->weaponinfo[i].name[0] ) {
botimport.Print( PRT_ERROR, "weapon %d has no name in %s\n", i, path );
FreeMemory( wc );
return NULL;
} //end if
if ( !wc->weaponinfo[i].projectile[0] ) {
botimport.Print( PRT_ERROR, "weapon %s has no projectile in %s\n", wc->weaponinfo[i].name, path );
FreeMemory( wc );
return NULL;
} //end if
//find the projectile info and copy it to the weapon info
for ( j = 0; j < wc->numprojectiles; j++ )
{
if ( !strcmp( wc->projectileinfo[j].name, wc->weaponinfo[i].projectile ) ) {
memcpy( &wc->weaponinfo[i].proj, &wc->projectileinfo[j], sizeof( projectileinfo_t ) );
break;
} //end if
} //end for
if ( j == wc->numprojectiles ) {
botimport.Print( PRT_ERROR, "weapon %s uses undefined projectile in %s\n", wc->weaponinfo[i].name, path );
FreeMemory( wc );
return NULL;
} //end if
} //end for
if ( !wc->numweapons ) {
botimport.Print( PRT_WARNING, "no weapon info loaded\n" );
}
botimport.Print( PRT_MESSAGE, "loaded %s\n", path );
return wc;
} //end of the function LoadWeaponConfig
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int *WeaponWeightIndex( weightconfig_t *wwc, weaponconfig_t *wc ) {
int *index, i;
//initialize item weight index
index = (int *) GetClearedMemory( sizeof( int ) * wc->numweapons );
for ( i = 0; i < wc->numweapons; i++ )
{
index[i] = FindFuzzyWeight( wwc, wc->weaponinfo[i].name );
} //end for
return index;
} //end of the function WeaponWeightIndex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotFreeWeaponWeights( int weaponstate ) {
bot_weaponstate_t *ws;
ws = BotWeaponStateFromHandle( weaponstate );
if ( !ws ) {
return;
}
if ( ws->weaponweightconfig ) {
FreeWeightConfig( ws->weaponweightconfig );
}
if ( ws->weaponweightindex ) {
FreeMemory( ws->weaponweightindex );
}
} //end of the function BotFreeWeaponWeights
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadWeaponWeights( int weaponstate, char *filename ) {
bot_weaponstate_t *ws;
ws = BotWeaponStateFromHandle( weaponstate );
if ( !ws ) {
return BLERR_CANNOTLOADWEAPONWEIGHTS;
}
BotFreeWeaponWeights( weaponstate );
//
ws->weaponweightconfig = ReadWeightConfig( filename );
if ( !ws->weaponweightconfig ) {
botimport.Print( PRT_FATAL, "couldn't load weapon config %s\n", filename );
return BLERR_CANNOTLOADWEAPONWEIGHTS;
} //end if
if ( !weaponconfig ) {
return BLERR_CANNOTLOADWEAPONCONFIG;
}
ws->weaponweightindex = WeaponWeightIndex( ws->weaponweightconfig, weaponconfig );
return BLERR_NOERROR;
} //end of the function BotLoadWeaponWeights
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotGetWeaponInfo( int weaponstate, int weapon, weaponinfo_t *weaponinfo ) {
bot_weaponstate_t *ws;
if ( !BotValidWeaponNumber( weapon ) ) {
return;
}
ws = BotWeaponStateFromHandle( weaponstate );
if ( !ws ) {
return;
}
if ( !weaponconfig ) {
return;
}
memcpy( weaponinfo, &weaponconfig->weaponinfo[weapon], sizeof( weaponinfo_t ) );
} //end of the function BotGetWeaponInfo
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotChooseBestFightWeapon( int weaponstate, int *inventory ) {
int i, index, bestweapon;
float weight, bestweight;
weaponconfig_t *wc;
bot_weaponstate_t *ws;
ws = BotWeaponStateFromHandle( weaponstate );
if ( !ws ) {
return 0;
}
wc = weaponconfig;
if ( !weaponconfig ) {
return 0;
}
//if the bot has no weapon weight configuration
if ( !ws->weaponweightconfig ) {
return 0;
}
bestweight = 0;
bestweapon = 0;
for ( i = 0; i < wc->numweapons; i++ )
{
if ( !wc->weaponinfo[i].valid ) {
continue;
}
index = ws->weaponweightindex[i];
if ( index < 0 ) {
continue;
}
weight = FuzzyWeight( inventory, ws->weaponweightconfig, index );
if ( weight > bestweight ) {
bestweight = weight;
bestweapon = i;
} //end if
} //end for
return bestweapon;
} //end of the function BotChooseBestFightWeapon
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotResetWeaponState( int weaponstate ) {
struct weightconfig_s *weaponweightconfig;
int *weaponweightindex;
bot_weaponstate_t *ws;
ws = BotWeaponStateFromHandle( weaponstate );
if ( !ws ) {
return;
}
weaponweightconfig = ws->weaponweightconfig;
weaponweightindex = ws->weaponweightindex;
//memset(ws, 0, sizeof(bot_weaponstate_t));
ws->weaponweightconfig = weaponweightconfig;
ws->weaponweightindex = weaponweightindex;
} //end of the function BotResetWeaponState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
int BotAllocWeaponState( void ) {
int i;
for ( i = 1; i <= MAX_CLIENTS; i++ )
{
if ( !botweaponstates[i] ) {
botweaponstates[i] = GetClearedMemory( sizeof( bot_weaponstate_t ) );
return i;
} //end if
} //end for
return 0;
} //end of the function BotAllocWeaponState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeWeaponState( int handle ) {
if ( handle <= 0 || handle > MAX_CLIENTS ) {
botimport.Print( PRT_FATAL, "move state handle %d out of range\n", handle );
return;
} //end if
if ( !botweaponstates[handle] ) {
botimport.Print( PRT_FATAL, "invalid move state %d\n", handle );
return;
} //end if
BotFreeWeaponWeights( handle );
FreeMemory( botweaponstates[handle] );
botweaponstates[handle] = NULL;
} //end of the function BotFreeWeaponState
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotSetupWeaponAI( void ) {
char *file;
file = LibVarString( "weaponconfig", "weapons.c" );
weaponconfig = LoadWeaponConfig( file );
if ( !weaponconfig ) {
botimport.Print( PRT_FATAL, "couldn't load the weapon config\n" );
return BLERR_CANNOTLOADWEAPONCONFIG;
} //end if
#ifdef DEBUG_AI_WEAP
DumpWeaponConfig( weaponconfig );
#endif //DEBUG_AI_WEAP
//
return BLERR_NOERROR;
} //end of the function BotSetupWeaponAI
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotShutdownWeaponAI( void ) {
int i;
if ( weaponconfig ) {
FreeMemory( weaponconfig );
}
weaponconfig = NULL;
for ( i = 1; i <= MAX_CLIENTS; i++ )
{
if ( botweaponstates[i] ) {
BotFreeWeaponState( i );
} //end if
} //end for
} //end of the function BotShutdownWeaponAI

972
src/botlib/be_ai_weight.c Normal file
View File

@ -0,0 +1,972 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weight.c
*
* desc: fuzzy logic
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_libvar.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_ai_weight.h"
#define MAX_INVENTORYVALUE 999999
#define EVALUATERECURSIVELY
#define MAX_WEIGHT_FILES 128
weightconfig_t *weightFileList[MAX_WEIGHT_FILES];
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int ReadValue( source_t *source, float *value ) {
token_t token;
if ( !PC_ExpectAnyToken( source, &token ) ) {
return qfalse;
}
if ( !strcmp( token.string, "-" ) ) {
SourceWarning( source, "negative value set to zero\n" );
if ( !PC_ExpectTokenType( source, TT_NUMBER, 0, &token ) ) {
return qfalse;
}
} //end if
if ( token.type != TT_NUMBER ) {
SourceError( source, "invalid return value %s\n", token.string );
return qfalse;
} //end if
*value = token.floatvalue;
return qtrue;
} //end of the function ReadValue
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int ReadFuzzyWeight( source_t *source, fuzzyseperator_t *fs ) {
if ( PC_CheckTokenString( source, "balance" ) ) {
fs->type = WT_BALANCE;
if ( !PC_ExpectTokenString( source, "(" ) ) {
return qfalse;
}
if ( !ReadValue( source, &fs->weight ) ) {
return qfalse;
}
if ( !PC_ExpectTokenString( source, "," ) ) {
return qfalse;
}
if ( !ReadValue( source, &fs->minweight ) ) {
return qfalse;
}
if ( !PC_ExpectTokenString( source, "," ) ) {
return qfalse;
}
if ( !ReadValue( source, &fs->maxweight ) ) {
return qfalse;
}
if ( !PC_ExpectTokenString( source, ")" ) ) {
return qfalse;
}
} //end if
else
{
fs->type = 0;
if ( !ReadValue( source, &fs->weight ) ) {
return qfalse;
}
fs->minweight = fs->weight;
fs->maxweight = fs->weight;
} //end if
if ( !PC_ExpectTokenString( source, ";" ) ) {
return qfalse;
}
return qtrue;
} //end of the function ReadFuzzyWeight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeFuzzySeperators_r( fuzzyseperator_t *fs ) {
if ( !fs ) {
return;
}
if ( fs->child ) {
FreeFuzzySeperators_r( fs->child );
}
if ( fs->next ) {
FreeFuzzySeperators_r( fs->next );
}
FreeMemory( fs );
} //end of the function FreeFuzzySeperators
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeWeightConfig2( weightconfig_t *config ) {
int i;
for ( i = 0; i < config->numweights; i++ )
{
FreeFuzzySeperators_r( config->weights[i].firstseperator );
if ( config->weights[i].name ) {
FreeMemory( config->weights[i].name );
}
} //end for
FreeMemory( config );
} //end of the function FreeWeightConfig2
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeWeightConfig( weightconfig_t *config ) {
if ( !LibVarGetValue( "bot_reloadcharacters" ) ) {
return;
}
FreeWeightConfig2( config );
} //end of the function FreeWeightConfig
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
fuzzyseperator_t *ReadFuzzySeperators_r( source_t *source ) {
int newindent, index, def, founddefault;
token_t token;
fuzzyseperator_t *fs, *lastfs, *firstfs;
founddefault = qfalse;
firstfs = NULL;
lastfs = NULL;
if ( !PC_ExpectTokenString( source, "(" ) ) {
return NULL;
}
if ( !PC_ExpectTokenType( source, TT_NUMBER, TT_INTEGER, &token ) ) {
return NULL;
}
index = token.intvalue;
if ( !PC_ExpectTokenString( source, ")" ) ) {
return NULL;
}
if ( !PC_ExpectTokenString( source, "{" ) ) {
return NULL;
}
if ( !PC_ExpectAnyToken( source, &token ) ) {
return NULL;
}
do
{
def = !strcmp( token.string, "default" );
if ( def || !strcmp( token.string, "case" ) ) {
fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) );
fs->index = index;
if ( lastfs ) {
lastfs->next = fs;
} else { firstfs = fs;}
lastfs = fs;
if ( def ) {
if ( founddefault ) {
SourceError( source, "switch already has a default\n" );
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
fs->value = MAX_INVENTORYVALUE;
founddefault = qtrue;
} //end if
else
{
if ( !PC_ExpectTokenType( source, TT_NUMBER, TT_INTEGER, &token ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
fs->value = token.intvalue;
} //end else
if ( !PC_ExpectTokenString( source, ":" ) || !PC_ExpectAnyToken( source, &token ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
newindent = qfalse;
if ( !strcmp( token.string, "{" ) ) {
newindent = qtrue;
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
} //end if
if ( !strcmp( token.string, "return" ) ) {
if ( !ReadFuzzyWeight( source, fs ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
} //end if
else if ( !strcmp( token.string, "switch" ) ) {
fs->child = ReadFuzzySeperators_r( source );
if ( !fs->child ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
} //end else if
else
{
SourceError( source, "invalid name %s\n", token.string );
return NULL;
} //end else
if ( newindent ) {
if ( !PC_ExpectTokenString( source, "}" ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
} //end if
} //end if
else
{
FreeFuzzySeperators_r( firstfs );
SourceError( source, "invalid name %s\n", token.string );
return NULL;
} //end else
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeFuzzySeperators_r( firstfs );
return NULL;
} //end if
} while ( strcmp( token.string, "}" ) );
//
if ( !founddefault ) {
SourceWarning( source, "switch without default\n" );
fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) );
fs->index = index;
fs->value = MAX_INVENTORYVALUE;
fs->weight = 0;
fs->next = NULL;
fs->child = NULL;
if ( lastfs ) {
lastfs->next = fs;
} else { firstfs = fs;}
lastfs = fs;
} //end if
//
return firstfs;
} //end of the function ReadFuzzySeperators_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
weightconfig_t *ReadWeightConfig( char *filename ) {
int newindent, avail = 0, n;
token_t token;
source_t *source;
fuzzyseperator_t *fs;
weightconfig_t *config = NULL;
#ifdef DEBUG
int starttime;
starttime = Sys_MilliSeconds();
#endif //DEBUG
if ( !LibVarGetValue( "bot_reloadcharacters" ) ) {
avail = -1;
for ( n = 0; n < MAX_WEIGHT_FILES; n++ )
{
config = weightFileList[n];
if ( !config ) {
if ( avail == -1 ) {
avail = n;
} //end if
continue;
} //end if
if ( strcmp( filename, config->filename ) == 0 ) {
//botimport.Print( PRT_MESSAGE, "retained %s\n", filename );
return config;
} //end if
} //end for
if ( avail == -1 ) {
botimport.Print( PRT_ERROR, "weightFileList was full trying to load %s\n", filename );
return NULL;
} //end if
} //end if
source = LoadSourceFile( filename );
if ( !source ) {
botimport.Print( PRT_ERROR, "counldn't load %s\n", filename );
return NULL;
} //end if
//
config = (weightconfig_t *) GetClearedMemory( sizeof( weightconfig_t ) );
config->numweights = 0;
Q_strncpyz( config->filename, filename, sizeof( config->filename ) );
//parse the item config file
while ( PC_ReadToken( source, &token ) )
{
if ( !strcmp( token.string, "weight" ) ) {
if ( config->numweights >= MAX_WEIGHTS ) {
SourceWarning( source, "too many fuzzy weights\n" );
break;
} //end if
if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) {
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
StripDoubleQuotes( token.string );
config->weights[config->numweights].name = (char *) GetClearedMemory( strlen( token.string ) + 1 );
strcpy( config->weights[config->numweights].name, token.string );
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
newindent = qfalse;
if ( !strcmp( token.string, "{" ) ) {
newindent = qtrue;
if ( !PC_ExpectAnyToken( source, &token ) ) {
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
} //end if
if ( !strcmp( token.string, "switch" ) ) {
fs = ReadFuzzySeperators_r( source );
if ( !fs ) {
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
config->weights[config->numweights].firstseperator = fs;
} //end if
else if ( !strcmp( token.string, "return" ) ) {
fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) );
fs->index = 0;
fs->value = MAX_INVENTORYVALUE;
fs->next = NULL;
fs->child = NULL;
if ( !ReadFuzzyWeight( source, fs ) ) {
FreeMemory( fs );
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
config->weights[config->numweights].firstseperator = fs;
} //end else if
else
{
SourceError( source, "invalid name %s\n", token.string );
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end else
if ( newindent ) {
if ( !PC_ExpectTokenString( source, "}" ) ) {
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end if
} //end if
config->numweights++;
} //end if
else
{
SourceError( source, "invalid name %s\n", token.string );
FreeWeightConfig( config );
FreeSource( source );
return NULL;
} //end else
} //end while
//free the source at the end of a pass
FreeSource( source );
//if the file was located in a pak file
botimport.Print( PRT_MESSAGE, "loaded %s\n", filename );
#ifdef DEBUG
if ( bot_developer ) {
botimport.Print( PRT_MESSAGE, "weights loaded in %d msec\n", Sys_MilliSeconds() - starttime );
} //end if
#endif //DEBUG
//
if ( !LibVarGetValue( "bot_reloadcharacters" ) ) {
weightFileList[avail] = config;
} //end if
//
return config;
} //end of the function ReadWeightConfig
#if 0
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteFuzzyWeight( FILE *fp, fuzzyseperator_t *fs ) {
if ( fs->type == WT_BALANCE ) {
if ( fprintf( fp, " return balance(" ) < 0 ) {
return qfalse;
}
if ( !WriteFloat( fp, fs->weight ) ) {
return qfalse;
}
if ( fprintf( fp, "," ) < 0 ) {
return qfalse;
}
if ( !WriteFloat( fp, fs->minweight ) ) {
return qfalse;
}
if ( fprintf( fp, "," ) < 0 ) {
return qfalse;
}
if ( !WriteFloat( fp, fs->maxweight ) ) {
return qfalse;
}
if ( fprintf( fp, ");\n" ) < 0 ) {
return qfalse;
}
} //end if
else
{
if ( fprintf( fp, " return " ) < 0 ) {
return qfalse;
}
if ( !WriteFloat( fp, fs->weight ) ) {
return qfalse;
}
if ( fprintf( fp, ";\n" ) < 0 ) {
return qfalse;
}
} //end else
return qtrue;
} //end of the function WriteFuzzyWeight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteFuzzySeperators_r( FILE *fp, fuzzyseperator_t *fs, int indent ) {
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "switch(%d)\n", fs->index ) < 0 ) {
return qfalse;
}
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "{\n" ) < 0 ) {
return qfalse;
}
indent++;
do
{
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fs->next ) {
if ( fprintf( fp, "case %d:", fs->value ) < 0 ) {
return qfalse;
}
} //end if
else
{
if ( fprintf( fp, "default:" ) < 0 ) {
return qfalse;
}
} //end else
if ( fs->child ) {
if ( fprintf( fp, "\n" ) < 0 ) {
return qfalse;
}
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "{\n" ) < 0 ) {
return qfalse;
}
if ( !WriteFuzzySeperators_r( fp, fs->child, indent + 1 ) ) {
return qfalse;
}
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fs->next ) {
if ( fprintf( fp, "} //end case\n" ) < 0 ) {
return qfalse;
}
} //end if
else
{
if ( fprintf( fp, "} //end default\n" ) < 0 ) {
return qfalse;
}
} //end else
} //end if
else
{
if ( !WriteFuzzyWeight( fp, fs ) ) {
return qfalse;
}
} //end else
fs = fs->next;
} while ( fs );
indent--;
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "} //end switch\n" ) < 0 ) {
return qfalse;
}
return qtrue;
} //end of the function WriteItemFuzzyWeights_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteWeightConfig( char *filename, weightconfig_t *config ) {
int i;
FILE *fp;
weight_t *ifw;
fp = fopen( filename, "wb" );
if ( !fp ) {
return qfalse;
}
for ( i = 0; i < config->numweights; i++ )
{
ifw = &config->weights[i];
if ( fprintf( fp, "\nweight \"%s\"\n", ifw->name ) < 0 ) {
return qfalse;
}
if ( fprintf( fp, "{\n" ) < 0 ) {
return qfalse;
}
if ( ifw->firstseperator->index > 0 ) {
if ( !WriteFuzzySeperators_r( fp, ifw->firstseperator, 1 ) ) {
return qfalse;
}
} //end if
else
{
if ( !WriteIndent( fp, 1 ) ) {
return qfalse;
}
if ( !WriteFuzzyWeight( fp, ifw->firstseperator ) ) {
return qfalse;
}
} //end else
if ( fprintf( fp, "} //end weight\n" ) < 0 ) {
return qfalse;
}
} //end for
fclose( fp );
return qtrue;
} //end of the function WriteWeightConfig
#endif
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int FindFuzzyWeight( weightconfig_t *wc, char *name ) {
int i;
for ( i = 0; i < wc->numweights; i++ )
{
if ( !strcmp( wc->weights[i].name, name ) ) {
return i;
} //end if
} //end if
return -1;
} //end of the function FindFuzzyWeight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float FuzzyWeight_r( int *inventory, fuzzyseperator_t *fs ) {
float scale, w1, w2;
if ( inventory[fs->index] < fs->value ) {
if ( fs->child ) {
return FuzzyWeight_r( inventory, fs->child );
} else { return fs->weight;}
} //end if
else if ( fs->next ) {
if ( inventory[fs->index] < fs->next->value ) {
//first weight
if ( fs->child ) {
w1 = FuzzyWeight_r( inventory, fs->child );
} else { w1 = fs->weight;}
//second weight
if ( fs->next->child ) {
w2 = FuzzyWeight_r( inventory, fs->next->child );
} else { w2 = fs->next->weight;}
//the scale factor
scale = ( inventory[fs->index] - fs->value ) / ( fs->next->value - fs->value );
//scale between the two weights
return scale * w1 + ( 1 - scale ) * w2;
} //end if
return FuzzyWeight_r( inventory, fs->next );
} //end else if
return fs->weight;
} //end of the function FuzzyWeight_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float FuzzyWeightUndecided_r( int *inventory, fuzzyseperator_t *fs ) {
float scale, w1, w2;
if ( inventory[fs->index] < fs->value ) {
if ( fs->child ) {
return FuzzyWeightUndecided_r( inventory, fs->child );
} else { return fs->minweight + random() * ( fs->maxweight - fs->minweight );}
} //end if
else if ( fs->next ) {
if ( inventory[fs->index] < fs->next->value ) {
//first weight
if ( fs->child ) {
w1 = FuzzyWeightUndecided_r( inventory, fs->child );
} else { w1 = fs->minweight + random() * ( fs->maxweight - fs->minweight );}
//second weight
if ( fs->next->child ) {
w2 = FuzzyWeight_r( inventory, fs->next->child );
} else { w2 = fs->next->minweight + random() * ( fs->next->maxweight - fs->next->minweight );}
//the scale factor
scale = ( inventory[fs->index] - fs->value ) / ( fs->next->value - fs->value );
//scale between the two weights
return scale * w1 + ( 1 - scale ) * w2;
} //end if
return FuzzyWeightUndecided_r( inventory, fs->next );
} //end else if
return fs->weight;
} //end of the function FuzzyWeightUndecided_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float FuzzyWeight( int *inventory, weightconfig_t *wc, int weightnum ) {
#ifdef EVALUATERECURSIVELY
return FuzzyWeight_r( inventory, wc->weights[weightnum].firstseperator );
#else
fuzzyseperator_t *s;
s = wc->weights[weightnum].firstseperator;
if ( !s ) {
return 0;
}
while ( 1 )
{
if ( inventory[s->index] < s->value ) {
if ( s->child ) {
s = s->child;
} else { return s->weight;}
} //end if
else
{
if ( s->next ) {
s = s->next;
} else { return s->weight;}
} //end else
} //end if
return 0;
#endif
} //end of the function FuzzyWeight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float FuzzyWeightUndecided( int *inventory, weightconfig_t *wc, int weightnum ) {
#ifdef EVALUATERECURSIVELY
return FuzzyWeightUndecided_r( inventory, wc->weights[weightnum].firstseperator );
#else
fuzzyseperator_t *s;
s = wc->weights[weightnum].firstseperator;
if ( !s ) {
return 0;
}
while ( 1 )
{
if ( inventory[s->index] < s->value ) {
if ( s->child ) {
s = s->child;
} else { return s->minweight + random() * ( s->maxweight - s->minweight );}
} //end if
else
{
if ( s->next ) {
s = s->next;
} else { return s->minweight + random() * ( s->maxweight - s->minweight );}
} //end else
} //end if
return 0;
#endif
} //end of the function FuzzyWeightUndecided
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EvolveFuzzySeperator_r( fuzzyseperator_t *fs ) {
if ( fs->child ) {
EvolveFuzzySeperator_r( fs->child );
} //end if
else if ( fs->type == WT_BALANCE ) {
//every once in a while an evolution leap occurs, mutation
if ( random() < 0.01 ) {
fs->weight += crandom() * ( fs->maxweight - fs->minweight );
} else { fs->weight += crandom() * ( fs->maxweight - fs->minweight ) * 0.5;}
//modify bounds if necesary because of mutation
if ( fs->weight < fs->minweight ) {
fs->minweight = fs->weight;
} else if ( fs->weight > fs->maxweight ) {
fs->maxweight = fs->weight;
}
} //end else if
if ( fs->next ) {
EvolveFuzzySeperator_r( fs->next );
}
} //end of the function EvolveFuzzySeperator_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EvolveWeightConfig( weightconfig_t *config ) {
int i;
for ( i = 0; i < config->numweights; i++ )
{
EvolveFuzzySeperator_r( config->weights[i].firstseperator );
} //end for
} //end of the function EvolveWeightConfig
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ScaleFuzzySeperator_r( fuzzyseperator_t *fs, float scale ) {
if ( fs->child ) {
ScaleFuzzySeperator_r( fs->child, scale );
} //end if
else if ( fs->type == WT_BALANCE ) {
//
fs->weight = ( fs->maxweight + fs->minweight ) * scale;
//get the weight between bounds
if ( fs->weight < fs->minweight ) {
fs->weight = fs->minweight;
} else if ( fs->weight > fs->maxweight ) {
fs->weight = fs->maxweight;
}
} //end else if
if ( fs->next ) {
ScaleFuzzySeperator_r( fs->next, scale );
}
} //end of the function ScaleFuzzySeperator_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ScaleWeight( weightconfig_t *config, char *name, float scale ) {
int i;
if ( scale < 0 ) {
scale = 0;
} else if ( scale > 1 ) {
scale = 1;
}
for ( i = 0; i < config->numweights; i++ )
{
if ( !strcmp( name, config->weights[i].name ) ) {
ScaleFuzzySeperator_r( config->weights[i].firstseperator, scale );
break;
} //end if
} //end for
} //end of the function ScaleWeight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ScaleFuzzySeperatorBalanceRange_r( fuzzyseperator_t *fs, float scale ) {
if ( fs->child ) {
ScaleFuzzySeperatorBalanceRange_r( fs->child, scale );
} //end if
else if ( fs->type == WT_BALANCE ) {
float mid = ( fs->minweight + fs->maxweight ) * 0.5;
//get the weight between bounds
fs->maxweight = mid + ( fs->maxweight - mid ) * scale;
fs->minweight = mid + ( fs->minweight - mid ) * scale;
if ( fs->maxweight < fs->minweight ) {
fs->maxweight = fs->minweight;
} //end if
} //end else if
if ( fs->next ) {
ScaleFuzzySeperatorBalanceRange_r( fs->next, scale );
}
} //end of the function ScaleFuzzySeperatorBalanceRange_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ScaleFuzzyBalanceRange( weightconfig_t *config, float scale ) {
int i;
if ( scale < 0 ) {
scale = 0;
} else if ( scale > 100 ) {
scale = 100;
}
for ( i = 0; i < config->numweights; i++ )
{
ScaleFuzzySeperatorBalanceRange_r( config->weights[i].firstseperator, scale );
} //end for
} //end of the function ScaleFuzzyBalanceRange
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int InterbreedFuzzySeperator_r( fuzzyseperator_t *fs1, fuzzyseperator_t *fs2,
fuzzyseperator_t *fsout ) {
if ( fs1->child ) {
if ( !fs2->child || !fsout->child ) {
botimport.Print( PRT_ERROR, "cannot interbreed weight configs, unequal child\n" );
return qfalse;
} //end if
if ( !InterbreedFuzzySeperator_r( fs2->child, fs2->child, fsout->child ) ) {
return qfalse;
} //end if
} //end if
else if ( fs1->type == WT_BALANCE ) {
if ( fs2->type != WT_BALANCE || fsout->type != WT_BALANCE ) {
botimport.Print( PRT_ERROR, "cannot interbreed weight configs, unequal balance\n" );
return qfalse;
} //end if
fsout->weight = ( fs1->weight + fs2->weight ) / 2;
if ( fsout->weight > fsout->maxweight ) {
fsout->maxweight = fsout->weight;
}
if ( fsout->weight > fsout->minweight ) {
fsout->minweight = fsout->weight;
}
} //end else if
if ( fs1->next ) {
if ( !fs2->next || !fsout->next ) {
botimport.Print( PRT_ERROR, "cannot interbreed weight configs, unequal next\n" );
return qfalse;
} //end if
if ( !InterbreedFuzzySeperator_r( fs1->next, fs2->next, fsout->next ) ) {
return qfalse;
} //end if
} //end if
return qtrue;
} //end of the function InterbreedFuzzySeperator_r
//===========================================================================
// config1 and config2 are interbreeded and stored in configout
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void InterbreedWeightConfigs( weightconfig_t *config1, weightconfig_t *config2,
weightconfig_t *configout ) {
int i;
if ( config1->numweights != config2->numweights ||
config1->numweights != configout->numweights ) {
botimport.Print( PRT_ERROR, "cannot interbreed weight configs, unequal numweights\n" );
return;
} //end if
for ( i = 0; i < config1->numweights; i++ )
{
InterbreedFuzzySeperator_r( config1->weights[i].firstseperator,
config2->weights[i].firstseperator,
configout->weights[i].firstseperator );
} //end for
} //end of the function InterbreedWeightConfigs
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotShutdownWeights( void ) {
int i;
for ( i = 0; i < MAX_WEIGHT_FILES; i++ )
{
if ( weightFileList[i] ) {
FreeWeightConfig2( weightFileList[i] );
weightFileList[i] = NULL;
} //end if
} //end for
} //end of the function BotShutdownWeights

89
src/botlib/be_ai_weight.h Normal file
View File

@ -0,0 +1,89 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weight.h
*
* desc: fuzzy weights
*
*
*****************************************************************************/
#define WT_BALANCE 1
#define MAX_WEIGHTS 128
//fuzzy seperator
typedef struct fuzzyseperator_s
{
int index;
int value;
int type;
float weight;
float minweight;
float maxweight;
struct fuzzyseperator_s *child;
struct fuzzyseperator_s *next;
} fuzzyseperator_t;
//fuzzy weight
typedef struct weight_s
{
char *name;
struct fuzzyseperator_s *firstseperator;
} weight_t;
//weight configuration
typedef struct weightconfig_s
{
int numweights;
weight_t weights[MAX_WEIGHTS];
char filename[MAX_QPATH];
} weightconfig_t;
//reads a weight configuration
weightconfig_t *ReadWeightConfig( char *filename );
//free a weight configuration
void FreeWeightConfig( weightconfig_t *config );
//writes a weight configuration, returns true if successfull
qboolean WriteWeightConfig( char *filename, weightconfig_t *config );
//find the fuzzy weight with the given name
int FindFuzzyWeight( weightconfig_t *wc, char *name );
//returns the fuzzy weight for the given inventory and weight
float FuzzyWeight( int *inventory, weightconfig_t *wc, int weightnum );
float FuzzyWeightUndecided( int *inventory, weightconfig_t *wc, int weightnum );
//scales the weight with the given name
void ScaleWeight( weightconfig_t *config, char *name, float scale );
//scale the balance range
void ScaleBalanceRange( weightconfig_t *config, float scale );
//evolves the weight configuration
void EvolveWeightConfig( weightconfig_t *config );
//interbreed the weight configurations and stores the interbreeded one in configout
void InterbreedWeightConfigs( weightconfig_t *config1, weightconfig_t *config2, weightconfig_t *configout );
//frees cached weight configurations
void BotShutdownWeights( void );

480
src/botlib/be_ea.c Normal file
View File

@ -0,0 +1,480 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_ea.c
*
* desc: elementary actions
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "../game/botlib.h"
#include "be_interface.h"
#define MAX_USERMOVE 400
#define MAX_COMMANDARGUMENTS 10
#define ACTION_JUMPEDLASTFRAME 128
bot_input_t *botinputs;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Say( int client, char *str ) {
botimport.BotClientCommand( client, va( "say %s", str ) );
} //end of the function EA_Say
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_SayTeam( int client, char *str ) {
botimport.BotClientCommand( client, va( "say_team %s", str ) );
} //end of the function EA_SayTeam
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_UseItem( int client, char *it ) {
botimport.BotClientCommand( client, va( "use %s", it ) );
} //end of the function EA_UseItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_DropItem( int client, char *it ) {
botimport.BotClientCommand( client, va( "drop %s", it ) );
} //end of the function EA_DropItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_UseInv( int client, char *inv ) {
botimport.BotClientCommand( client, va( "invuse %s", inv ) );
} //end of the function EA_UseInv
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_DropInv( int client, char *inv ) {
botimport.BotClientCommand( client, va( "invdrop %s", inv ) );
} //end of the function EA_DropInv
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Gesture( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_GESTURE;
} //end of the function EA_Gesture
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Command( int client, char *command ) {
botimport.BotClientCommand( client, command );
} //end of the function EA_Command
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_SelectWeapon( int client, int weapon ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->weapon = weapon;
} //end of the function EA_SelectWeapon
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Attack( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_ATTACK;
} //end of the function EA_Attack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Reload( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_RELOAD;
} //end of the function EA_Attack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Talk( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_TALK;
} //end of the function EA_Talk
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Use( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_USE;
} //end of the function EA_Use
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Respawn( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_RESPAWN;
} //end of the function EA_Respawn
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Jump( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
if ( bi->actionflags & ACTION_JUMPEDLASTFRAME ) {
bi->actionflags &= ~ACTION_JUMP;
} //end if
else
{
bi->actionflags |= ACTION_JUMP;
} //end if
} //end of the function EA_Jump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_DelayedJump( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
if ( bi->actionflags & ACTION_JUMPEDLASTFRAME ) {
bi->actionflags &= ~ACTION_DELAYEDJUMP;
} //end if
else
{
bi->actionflags |= ACTION_DELAYEDJUMP;
} //end if
} //end of the function EA_DelayedJump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Crouch( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_CROUCH;
} //end of the function EA_Crouch
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Walk( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_WALK;
} //end of the function EA_Walk
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveUp( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVEUP;
} //end of the function EA_MoveUp
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveDown( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVEDOWN;
} //end of the function EA_MoveDown
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveForward( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVEFORWARD;
} //end of the function EA_MoveForward
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveBack( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVEBACK;
} //end of the function EA_MoveBack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveLeft( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVELEFT;
} //end of the function EA_MoveLeft
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_MoveRight( int client ) {
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_MOVERIGHT;
} //end of the function EA_MoveRight
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Move( int client, vec3_t dir, float speed ) {
bot_input_t *bi;
bi = &botinputs[client];
VectorCopy( dir, bi->dir );
//cap speed
if ( speed > MAX_USERMOVE ) {
speed = MAX_USERMOVE;
} else if ( speed < -MAX_USERMOVE ) {
speed = -MAX_USERMOVE;
}
bi->speed = speed;
} //end of the function EA_Move
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_View( int client, vec3_t viewangles ) {
bot_input_t *bi;
bi = &botinputs[client];
VectorCopy( viewangles, bi->viewangles );
} //end of the function EA_View
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_EndRegular( int client, float thinktime ) {
/*
bot_input_t *bi;
int jumped = qfalse;
bi = &botinputs[client];
bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
bi->thinktime = thinktime;
botimport.BotInput(client, bi);
bi->thinktime = 0;
VectorClear(bi->dir);
bi->speed = 0;
jumped = bi->actionflags & ACTION_JUMP;
bi->actionflags = 0;
if (jumped) bi->actionflags |= ACTION_JUMPEDLASTFRAME;
*/
} //end of the function EA_EndRegular
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_GetInput( int client, float thinktime, bot_input_t *input ) {
bot_input_t *bi;
// int jumped = qfalse;
bi = &botinputs[client];
// bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
bi->thinktime = thinktime;
memcpy( input, bi, sizeof( bot_input_t ) );
/*
bi->thinktime = 0;
VectorClear(bi->dir);
bi->speed = 0;
jumped = bi->actionflags & ACTION_JUMP;
bi->actionflags = 0;
if (jumped) bi->actionflags |= ACTION_JUMPEDLASTFRAME;
*/
} //end of the function EA_GetInput
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_ResetInput( int client, bot_input_t *init ) {
bot_input_t *bi;
int jumped = qfalse;
bi = &botinputs[client];
bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
bi->thinktime = 0;
VectorClear( bi->dir );
bi->speed = 0;
jumped = bi->actionflags & ACTION_JUMP;
bi->actionflags = 0;
if ( jumped ) {
bi->actionflags |= ACTION_JUMPEDLASTFRAME;
}
if ( init ) {
memcpy( bi, init, sizeof( bot_input_t ) );
}
} //end of the function EA_ResetInput
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int EA_Setup( void ) {
//initialize the bot inputs
botinputs = (bot_input_t *) GetClearedHunkMemory(
botlibglobals.maxclients * sizeof( bot_input_t ) );
return BLERR_NOERROR;
} //end of the function EA_Setup
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void EA_Shutdown( void ) {
FreeMemory( botinputs );
botinputs = NULL;
} //end of the function EA_Shutdown

936
src/botlib/be_interface.c Normal file
View File

@ -0,0 +1,936 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_interface.c
*
* desc: bot library interface
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_log.h"
#include "l_libvar.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
#include "be_interface.h"
#include "../game/be_ea.h"
#include "be_ai_weight.h"
#include "../game/be_ai_goal.h"
#include "../game/be_ai_move.h"
#include "../game/be_ai_weap.h"
#include "../game/be_ai_chat.h"
#include "../game/be_ai_char.h"
#include "../game/be_ai_gen.h"
//library globals in a structure
botlib_globals_t botlibglobals;
botlib_export_t be_botlib_export;
botlib_import_t botimport;
//
int bot_developer;
//qtrue if the library is setup
int botlibsetup = qfalse;
//===========================================================================
//
// several functions used by the exported functions
//
//===========================================================================
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
// Ridah, faster Win32 code
#ifdef _WIN32
#undef MAX_PATH // this is an ugly hack, to temporarily ignore the current definition, since it's also defined in windows.h
#include <windows.h>
#undef MAX_PATH
#define MAX_PATH MAX_QPATH
#endif
int Sys_MilliSeconds( void ) {
// Ridah, faster Win32 code
#ifdef _WIN32
int sys_curtime;
static qboolean initialized = qfalse;
static int sys_timeBase;
if ( !initialized ) {
sys_timeBase = timeGetTime();
initialized = qtrue;
}
sys_curtime = timeGetTime() - sys_timeBase;
return sys_curtime;
#else
return clock() * 1000 / CLOCKS_PER_SEC;
#endif
} //end of the function Sys_MilliSeconds
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean ValidClientNumber( int num, char *str ) {
if ( num < 0 || num > botlibglobals.maxclients ) {
//weird: the disabled stuff results in a crash
botimport.Print( PRT_ERROR, "%s: invalid client number %d, [0, %d]\n",
str, num, botlibglobals.maxclients );
return qfalse;
} //end if
return qtrue;
} //end of the function BotValidateClientNumber
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean ValidEntityNumber( int num, char *str ) {
if ( num < 0 || num > botlibglobals.maxentities ) {
botimport.Print( PRT_ERROR, "%s: invalid entity number %d, [0, %d]\n",
str, num, botlibglobals.maxentities );
return qfalse;
} //end if
return qtrue;
} //end of the function BotValidateClientNumber
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean BotLibSetup( char *str ) {
// return qtrue;
if ( !botlibglobals.botlibsetup ) {
botimport.Print( PRT_ERROR, "%s: bot library used before being setup\n", str );
return qfalse;
} //end if
return qtrue;
} //end of the function BotLibSetup
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibSetup( void ) {
int errnum;
bot_developer = LibVarGetValue( "bot_developer" );
//initialize byte swapping (litte endian etc.)
Swap_Init();
Log_Open( "botlib.log" );
//
botimport.Print( PRT_MESSAGE, "------- BotLib Initialization -------\n" );
//
botlibglobals.maxclients = (int) LibVarValue( "maxclients", "128" );
botlibglobals.maxentities = (int) LibVarValue( "maxentities", "2048" );
errnum = AAS_Setup(); //be_aas_main.c
if ( errnum != BLERR_NOERROR ) {
return errnum;
}
errnum = EA_Setup(); //be_ea.c
if ( errnum != BLERR_NOERROR ) {
return errnum;
}
// errnum = BotSetupWeaponAI(); //be_ai_weap.c
// if (errnum != BLERR_NOERROR)return errnum;
// errnum = BotSetupGoalAI(); //be_ai_goal.c
// if (errnum != BLERR_NOERROR) return errnum;
// errnum = BotSetupChatAI(); //be_ai_chat.c
// if (errnum != BLERR_NOERROR) return errnum;
errnum = BotSetupMoveAI(); //be_ai_move.c
if ( errnum != BLERR_NOERROR ) {
return errnum;
}
botlibsetup = qtrue;
botlibglobals.botlibsetup = qtrue;
return BLERR_NOERROR;
} //end of the function Export_BotLibSetup
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibShutdown( void ) {
static int recursive = 0;
if ( !BotLibSetup( "BotLibShutdown" ) ) {
return BLERR_LIBRARYNOTSETUP;
}
//
if ( recursive ) {
return BLERR_NOERROR;
}
recursive = 1;
// shutdown all AI subsystems
BotShutdownChatAI(); //be_ai_chat.c
BotShutdownMoveAI(); //be_ai_move.c
BotShutdownGoalAI(); //be_ai_goal.c
BotShutdownWeaponAI(); //be_ai_weap.c
BotShutdownWeights(); //be_ai_weight.c
BotShutdownCharacters(); //be_ai_char.c
// shutdown AAS
AAS_Shutdown();
// shutdown bot elemantary actions
EA_Shutdown();
// free all libvars
LibVarDeAllocAll();
// remove all global defines from the pre compiler
PC_RemoveAllGlobalDefines();
// shut down library log file
Log_Shutdown();
//
botlibsetup = qfalse;
botlibglobals.botlibsetup = qfalse;
recursive = 0;
// print any files still open
PC_CheckOpenSourceHandles();
//
#ifdef _DEBUG
Log_AlwaysOpen( "memory.log" );
PrintMemoryLabels();
Log_Shutdown();
#endif
return BLERR_NOERROR;
} //end of the function Export_BotLibShutdown
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibVarSet( char *var_name, char *value ) {
LibVarSet( var_name, value );
return BLERR_NOERROR;
} //end of the function Export_BotLibVarSet
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibVarGet( char *var_name, char *value, int size ) {
char *varvalue;
varvalue = LibVarGetString( var_name );
strncpy( value, varvalue, size - 1 );
value[size - 1] = '\0';
return BLERR_NOERROR;
} //end of the function Export_BotLibVarGet
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibStartFrame( float time ) {
if ( !BotLibSetup( "BotStartFrame" ) ) {
return BLERR_LIBRARYNOTSETUP;
}
return AAS_StartFrame( time );
} //end of the function Export_BotLibStartFrame
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibLoadMap( const char *mapname ) {
#ifdef DEBUG
int starttime = Sys_MilliSeconds();
#endif
int errnum;
if ( !BotLibSetup( "BotLoadMap" ) ) {
return BLERR_LIBRARYNOTSETUP;
}
//
botimport.Print( PRT_MESSAGE, "------------ Map Loading ------------\n" );
//startup AAS for the current map, model and sound index
errnum = AAS_LoadMap( mapname );
if ( errnum != BLERR_NOERROR ) {
return errnum;
}
//initialize the items in the level
BotInitLevelItems(); //be_ai_goal.h
BotSetBrushModelTypes(); //be_ai_move.h
//
botimport.Print( PRT_MESSAGE, "-------------------------------------\n" );
#ifdef DEBUG
botimport.Print( PRT_MESSAGE, "map loaded in %d msec\n", Sys_MilliSeconds() - starttime );
#endif
//
return BLERR_NOERROR;
} //end of the function Export_BotLibLoadMap
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibUpdateEntity( int ent, bot_entitystate_t *state ) {
if ( !BotLibSetup( "BotUpdateEntity" ) ) {
return BLERR_LIBRARYNOTSETUP;
}
if ( !ValidEntityNumber( ent, "BotUpdateEntity" ) ) {
return BLERR_INVALIDENTITYNUMBER;
}
return AAS_UpdateEntity( ent, state );
} //end of the function Export_BotLibUpdateEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_TestMovementPrediction( int entnum, vec3_t origin, vec3_t dir );
void ElevatorBottomCenter( aas_reachability_t *reach, vec3_t bottomcenter );
int BotGetReachabilityToGoal( vec3_t origin, int areanum, int entnum,
int lastgoalareanum, int lastareanum,
int *avoidreach, float *avoidreachtimes, int *avoidreachtries,
bot_goal_t *goal, int travelflags, int movetravelflags );
int AAS_PointLight( vec3_t origin, int *red, int *green, int *blue );
int AAS_TraceAreas( vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas );
int AAS_Reachability_WeaponJump( int area1num, int area2num );
int BotFuzzyPointReachabilityArea( vec3_t origin );
float BotGapDistance( vec3_t origin, vec3_t hordir, int entnum );
int AAS_NearestHideArea( int srcnum, vec3_t origin, int areanum, int enemynum, vec3_t enemyorigin, int enemyareanum, int travelflags );
int AAS_FindAttackSpotWithinRange( int srcnum, int rangenum, int enemynum, float rangedist, int travelflags, float *outpos );
qboolean AAS_GetRouteFirstVisPos( vec3_t srcpos, vec3_t destpos, int travelflags, vec3_t retpos );
void AAS_SetAASBlockingEntity( vec3_t absmin, vec3_t absmax, qboolean blocking );
int BotExportTest( int parm0, char *parm1, vec3_t parm2, vec3_t parm3 ) {
// return AAS_PointLight(parm2, NULL, NULL, NULL);
#ifdef DEBUG
static int area = -1;
static int line[2];
int newarea, i, highlightarea, bot_testhidepos, hideposarea, bot_testroutevispos;
// int reachnum;
vec3_t eye, forward, right, end, origin;
// vec3_t bottomcenter;
// aas_trace_t trace;
// aas_face_t *face;
// aas_entity_t *ent;
// bsp_trace_t bsptrace;
// aas_reachability_t reach;
// bot_goal_t goal;
// clock_t start_time, end_time;
vec3_t mins = {-16, -16, -24};
vec3_t maxs = {16, 16, 32};
// int areas[10], numareas;
//return 0;
if ( !( *aasworld ).loaded ) {
return 0;
}
AAS_SetCurrentWorld( 0 );
for ( i = 0; i < 2; i++ ) if ( !line[i] ) {
line[i] = botimport.DebugLineCreate();
}
// AAS_ClearShownDebugLines();
bot_testhidepos = LibVarGetValue( "bot_testhidepos" );
if ( bot_testhidepos ) {
VectorCopy( parm2, origin );
newarea = BotFuzzyPointReachabilityArea( origin );
if ( parm0 & 1 ) {
botlibglobals.goalareanum = newarea;
VectorCopy( origin, botlibglobals.goalorigin );
botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea );
} //end if
AAS_ClearShownPolygons();
AAS_ClearShownDebugLines();
hideposarea = AAS_NearestHideArea( -1, origin, AAS_PointAreaNum( origin ), 0,
botlibglobals.goalorigin, botlibglobals.goalareanum, TFL_DEFAULT );
if ( bot_testhidepos > 1 ) {
if ( hideposarea ) {
botimport.Print( PRT_MESSAGE, "hidepos (%i) %2.1f %2.1f %2.1f\n",
hideposarea,
( *aasworld ).areawaypoints[hideposarea][0],
( *aasworld ).areawaypoints[hideposarea][1],
( *aasworld ).areawaypoints[hideposarea][2] );
} else {
botimport.Print( PRT_MESSAGE, "no hidepos found\n" );
}
}
//area we are currently in
AAS_ShowAreaPolygons( newarea, 1, qtrue );
//enemy position
AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
//area we should go hide
AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
return 0;
}
bot_testroutevispos = LibVarGetValue( "bot_testroutevispos" );
if ( bot_testroutevispos ) {
VectorCopy( parm2, origin );
newarea = BotFuzzyPointReachabilityArea( origin );
if ( parm0 & 1 ) {
botlibglobals.goalareanum = newarea;
VectorCopy( origin, botlibglobals.goalorigin );
botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea );
} //end if
AAS_ClearShownPolygons();
AAS_ClearShownDebugLines();
AAS_GetRouteFirstVisPos( botlibglobals.goalorigin, origin, TFL_DEFAULT, eye );
//area we are currently in
AAS_ShowAreaPolygons( newarea, 1, qtrue );
//enemy position
AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
//area that is visible in path from enemy pos
hideposarea = BotFuzzyPointReachabilityArea( eye );
AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
return 0;
}
//if (AAS_AgainstLadder(parm2)) botimport.Print(PRT_MESSAGE, "against ladder\n");
//BotOnGround(parm2, PRESENCE_NORMAL, 1, &newarea, &newarea);
//botimport.Print(PRT_MESSAGE, "%f %f %f\n", parm2[0], parm2[1], parm2[2]);
//*
highlightarea = LibVarGetValue( "bot_highlightarea" );
if ( highlightarea > 0 ) {
newarea = highlightarea;
} //end if
else
{
VectorCopy( parm2, origin );
origin[2] += 0.5;
//newarea = AAS_PointAreaNum(origin);
newarea = BotFuzzyPointReachabilityArea( origin );
} //end else
botimport.Print( PRT_MESSAGE, "\rtravel time to goal (%d) = %d ", botlibglobals.goalareanum,
AAS_AreaTravelTimeToGoalArea( newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT ) );
//newarea = BotReachabilityArea(origin, qtrue);
if ( newarea != area ) {
botimport.Print( PRT_MESSAGE, "origin = %f, %f, %f\n", origin[0], origin[1], origin[2] );
area = newarea;
botimport.Print( PRT_MESSAGE, "new area %d, cluster %d, presence type %d\n",
area, AAS_AreaCluster( area ), AAS_PointPresenceType( origin ) );
if ( ( *aasworld ).areasettings[area].areaflags & AREA_LIQUID ) {
botimport.Print( PRT_MESSAGE, "liquid area\n" );
} //end if
botimport.Print( PRT_MESSAGE, "area contents: " );
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_WATER ) {
botimport.Print( PRT_MESSAGE, "water " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_LAVA ) {
botimport.Print( PRT_MESSAGE, "lava " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_SLIME ) {
// botimport.Print(PRT_MESSAGE, "slime ");
botimport.Print( PRT_MESSAGE, "slag " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_JUMPPAD ) {
botimport.Print( PRT_MESSAGE, "jump pad " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_CLUSTERPORTAL ) {
botimport.Print( PRT_MESSAGE, "cluster portal " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_DONOTENTER ) {
botimport.Print( PRT_MESSAGE, "do not enter " );
} //end if
if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_DONOTENTER_LARGE ) {
botimport.Print( PRT_MESSAGE, "do not enter large " );
} //end if
if ( !( *aasworld ).areasettings[area].contents ) {
botimport.Print( PRT_MESSAGE, "empty " );
} //end if
if ( ( *aasworld ).areasettings[area].areaflags & AREA_DISABLED ) {
botimport.Print( PRT_MESSAGE, "DISABLED" );
} //end if
botimport.Print( PRT_MESSAGE, "\n" );
botimport.Print( PRT_MESSAGE, "travel time to goal (%d) = %d\n", botlibglobals.goalareanum,
AAS_AreaTravelTimeToGoalArea( newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT | TFL_ROCKETJUMP ) );
/*
VectorCopy(origin, end);
end[2] += 5;
numareas = AAS_TraceAreas(origin, end, areas, NULL, 10);
AAS_TraceClientBBox(origin, end, PRESENCE_CROUCH, -1);
botimport.Print(PRT_MESSAGE, "num areas = %d, area = %d\n", numareas, areas[0]);
*/
/*
botlibglobals.goalareanum = newarea;
VectorCopy(parm2, botlibglobals.goalorigin);
botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea);
*/
} //end if
//*
if ( parm0 & 1 ) {
botlibglobals.goalareanum = newarea;
VectorCopy( parm2, botlibglobals.goalorigin );
botimport.Print( PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea );
} //end if*/
// if (parm0 & BUTTON_USE)
// {
// botlibglobals.runai = !botlibglobals.runai;
// if (botlibglobals.runai) botimport.Print(PRT_MESSAGE, "started AI\n");
// else botimport.Print(PRT_MESSAGE, "stopped AI\n");
//* /
/*
goal.areanum = botlibglobals.goalareanum;
reachnum = BotGetReachabilityToGoal(parm2, newarea, 1,
ms.avoidreach, ms.avoidreachtimes,
&goal, TFL_DEFAULT);
if (!reachnum)
{
botimport.Print(PRT_MESSAGE, "goal not reachable\n");
} //end if
else
{
AAS_ReachabilityFromNum(reachnum, &reach);
AAS_ClearShownDebugLines();
AAS_ShowArea(area, qtrue);
AAS_ShowArea(reach.areanum, qtrue);
AAS_DrawCross(reach.start, 6, LINECOLOR_BLUE);
AAS_DrawCross(reach.end, 6, LINECOLOR_RED);
//
if (reach.traveltype == TRAVEL_ELEVATOR)
{
ElevatorBottomCenter(&reach, bottomcenter);
AAS_DrawCross(bottomcenter, 10, LINECOLOR_GREEN);
} //end if
} //end else*/
// botimport.Print(PRT_MESSAGE, "travel time to goal = %d\n",
// AAS_AreaTravelTimeToGoalArea(area, origin, botlibglobals.goalareanum, TFL_DEFAULT));
// botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
// AAS_Reachability_WeaponJump(703, 716);
// } //end if*/
/* face = AAS_AreaGroundFace(newarea, parm2);
if (face)
{
AAS_ShowFace(face - (*aasworld).faces);
} //end if*/
/*
AAS_ClearShownDebugLines();
AAS_ShowArea(newarea, parm0 & BUTTON_USE);
AAS_ShowReachableAreas(area);
*/
AAS_ClearShownPolygons();
AAS_ClearShownDebugLines();
AAS_ShowAreaPolygons( newarea, 1, parm0 & 4 );
if ( parm0 & 2 ) {
AAS_ShowReachableAreas( area );
} else
{
static int lastgoalareanum, lastareanum;
static int avoidreach[MAX_AVOIDREACH];
static float avoidreachtimes[MAX_AVOIDREACH];
static int avoidreachtries[MAX_AVOIDREACH];
int reachnum;
bot_goal_t goal;
aas_reachability_t reach;
goal.areanum = botlibglobals.goalareanum;
VectorCopy( botlibglobals.goalorigin, goal.origin );
reachnum = BotGetReachabilityToGoal( origin, newarea, -1,
lastgoalareanum, lastareanum,
avoidreach, avoidreachtimes, avoidreachtries,
&goal, TFL_DEFAULT | TFL_FUNCBOB, TFL_DEFAULT | TFL_FUNCBOB );
AAS_ReachabilityFromNum( reachnum, &reach );
AAS_ShowReachability( &reach );
} //end else
VectorClear( forward );
//BotGapDistance(origin, forward, 0);
/*
if (parm0 & BUTTON_USE)
{
botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
AAS_Reachability_WeaponJump(703, 716);
} //end if*/
AngleVectors( parm3, forward, right, NULL );
//get the eye 16 units to the right of the origin
VectorMA( parm2, 8, right, eye );
//get the eye 24 units up
eye[2] += 24;
//get the end point for the line to be traced
VectorMA( eye, 800, forward, end );
// AAS_TestMovementPrediction(1, parm2, forward);
/* //trace the line to find the hit point
trace = AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
if (!line[0]) line[0] = botimport.DebugLineCreate();
botimport.DebugLineShow(line[0], eye, trace.endpos, LINECOLOR_BLUE);
//
AAS_ClearShownDebugLines();
if (trace.ent)
{
ent = &(*aasworld).entities[trace.ent];
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
} //end if*/
/*
start_time = clock();
for (i = 0; i < 2000; i++)
{
AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
// AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
} //end for
end_time = clock();
botimport.Print(PRT_MESSAGE, "me %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
start_time = clock();
for (i = 0; i < 2000; i++)
{
AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
} //end for
end_time = clock();
botimport.Print(PRT_MESSAGE, "id %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
*/
/*
AAS_ClearShownDebugLines();
//bsptrace = AAS_Trace(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
bsptrace = AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
if (!line[0]) line[0] = botimport.DebugLineCreate();
botimport.DebugLineShow(line[0], eye, bsptrace.endpos, LINECOLOR_YELLOW);
if (bsptrace.fraction < 1.0)
{
face = AAS_TraceEndFace(&trace);
if (face)
{
AAS_ShowFace(face - (*aasworld).faces);
} //end if
AAS_DrawPlaneCross(bsptrace.endpos,
bsptrace.plane.normal,
bsptrace.plane.dist + bsptrace.exp_dist,
bsptrace.plane.type, LINECOLOR_GREEN);
if (trace.ent)
{
ent = &(*aasworld).entities[trace.ent];
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
} //end if
} //end if*/
/*/
//bsptrace = AAS_Trace2(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
bsptrace = AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
botimport.DebugLineShow(line[1], eye, bsptrace.endpos, LINECOLOR_BLUE);
if (bsptrace.fraction < 1.0)
{
AAS_DrawPlaneCross(bsptrace.endpos,
bsptrace.plane.normal,
bsptrace.plane.dist,// + bsptrace.exp_dist,
bsptrace.plane.type, LINECOLOR_RED);
if (bsptrace.ent)
{
ent = &(*aasworld).entities[bsptrace.ent];
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
} //end if
} //end if
*/
#endif
return 0;
} //end of the function BotExportTest
/*
============
Init_AAS_Export
============
*/
static void Init_AAS_Export( aas_export_t *aas ) {
//--------------------------------------------
// be_aas_entity.c
//--------------------------------------------
aas->AAS_EntityInfo = AAS_EntityInfo;
//--------------------------------------------
// be_aas_main.c
//--------------------------------------------
aas->AAS_Initialized = AAS_Initialized;
aas->AAS_PresenceTypeBoundingBox = AAS_PresenceTypeBoundingBox;
aas->AAS_Time = AAS_Time;
//--------------------------------------------
// be_aas_sample.c
//--------------------------------------------
aas->AAS_PointAreaNum = AAS_PointAreaNum;
aas->AAS_TraceAreas = AAS_TraceAreas;
//--------------------------------------------
// be_aas_bspq3.c
//--------------------------------------------
aas->AAS_PointContents = AAS_PointContents;
aas->AAS_NextBSPEntity = AAS_NextBSPEntity;
aas->AAS_ValueForBSPEpairKey = AAS_ValueForBSPEpairKey;
aas->AAS_VectorForBSPEpairKey = AAS_VectorForBSPEpairKey;
aas->AAS_FloatForBSPEpairKey = AAS_FloatForBSPEpairKey;
aas->AAS_IntForBSPEpairKey = AAS_IntForBSPEpairKey;
//--------------------------------------------
// be_aas_reach.c
//--------------------------------------------
aas->AAS_AreaReachability = AAS_AreaReachability;
//--------------------------------------------
// be_aas_route.c
//--------------------------------------------
aas->AAS_AreaTravelTimeToGoalArea = AAS_AreaTravelTimeToGoalArea;
//--------------------------------------------
// be_aas_move.c
//--------------------------------------------
aas->AAS_Swimming = AAS_Swimming;
aas->AAS_PredictClientMovement = AAS_PredictClientMovement;
// Ridah, route-tables
//--------------------------------------------
// be_aas_routetable.c
//--------------------------------------------
aas->AAS_RT_ShowRoute = AAS_RT_ShowRoute;
aas->AAS_RT_GetHidePos = AAS_RT_GetHidePos;
aas->AAS_FindAttackSpotWithinRange = AAS_FindAttackSpotWithinRange;
aas->AAS_GetRouteFirstVisPos = AAS_GetRouteFirstVisPos;
aas->AAS_SetAASBlockingEntity = AAS_SetAASBlockingEntity;
// done.
// Ridah, multiple AAS files
aas->AAS_SetCurrentWorld = AAS_SetCurrentWorld;
// done.
}
/*
============
Init_EA_Export
============
*/
static void Init_EA_Export( ea_export_t *ea ) {
//ClientCommand elementary actions
ea->EA_Say = EA_Say;
ea->EA_SayTeam = EA_SayTeam;
ea->EA_UseItem = EA_UseItem;
ea->EA_DropItem = EA_DropItem;
ea->EA_UseInv = EA_UseInv;
ea->EA_DropInv = EA_DropInv;
ea->EA_Gesture = EA_Gesture;
ea->EA_Command = EA_Command;
ea->EA_SelectWeapon = EA_SelectWeapon;
ea->EA_Talk = EA_Talk;
ea->EA_Attack = EA_Attack;
ea->EA_Reload = EA_Reload;
ea->EA_Use = EA_Use;
ea->EA_Respawn = EA_Respawn;
ea->EA_Jump = EA_Jump;
ea->EA_DelayedJump = EA_DelayedJump;
ea->EA_Crouch = EA_Crouch;
ea->EA_MoveUp = EA_MoveUp;
ea->EA_MoveDown = EA_MoveDown;
ea->EA_MoveForward = EA_MoveForward;
ea->EA_MoveBack = EA_MoveBack;
ea->EA_MoveLeft = EA_MoveLeft;
ea->EA_MoveRight = EA_MoveRight;
ea->EA_Move = EA_Move;
ea->EA_View = EA_View;
ea->EA_GetInput = EA_GetInput;
ea->EA_EndRegular = EA_EndRegular;
ea->EA_ResetInput = EA_ResetInput;
}
/*
============
Init_AI_Export
============
*/
static void Init_AI_Export( ai_export_t *ai ) {
//-----------------------------------
// be_ai_char.h
//-----------------------------------
ai->BotLoadCharacter = BotLoadCharacter;
ai->BotFreeCharacter = BotFreeCharacter;
ai->Characteristic_Float = Characteristic_Float;
ai->Characteristic_BFloat = Characteristic_BFloat;
ai->Characteristic_Integer = Characteristic_Integer;
ai->Characteristic_BInteger = Characteristic_BInteger;
ai->Characteristic_String = Characteristic_String;
//-----------------------------------
// be_ai_chat.h
//-----------------------------------
ai->BotAllocChatState = BotAllocChatState;
ai->BotFreeChatState = BotFreeChatState;
ai->BotQueueConsoleMessage = BotQueueConsoleMessage;
ai->BotRemoveConsoleMessage = BotRemoveConsoleMessage;
ai->BotNextConsoleMessage = BotNextConsoleMessage;
ai->BotNumConsoleMessages = BotNumConsoleMessages;
ai->BotInitialChat = BotInitialChat;
ai->BotNumInitialChats = BotNumInitialChats;
ai->BotReplyChat = BotReplyChat;
ai->BotChatLength = BotChatLength;
ai->BotEnterChat = BotEnterChat;
ai->BotGetChatMessage = BotGetChatMessage;
ai->StringContains = StringContains;
ai->BotFindMatch = BotFindMatch;
ai->BotMatchVariable = BotMatchVariable;
ai->UnifyWhiteSpaces = UnifyWhiteSpaces;
ai->BotReplaceSynonyms = BotReplaceSynonyms;
ai->BotLoadChatFile = BotLoadChatFile;
ai->BotSetChatGender = BotSetChatGender;
ai->BotSetChatName = BotSetChatName;
//-----------------------------------
// be_ai_goal.h
//-----------------------------------
ai->BotResetGoalState = BotResetGoalState;
ai->BotResetAvoidGoals = BotResetAvoidGoals;
ai->BotRemoveFromAvoidGoals = BotRemoveFromAvoidGoals;
ai->BotPushGoal = BotPushGoal;
ai->BotPopGoal = BotPopGoal;
ai->BotEmptyGoalStack = BotEmptyGoalStack;
ai->BotDumpAvoidGoals = BotDumpAvoidGoals;
ai->BotDumpGoalStack = BotDumpGoalStack;
ai->BotGoalName = BotGoalName;
ai->BotGetTopGoal = BotGetTopGoal;
ai->BotGetSecondGoal = BotGetSecondGoal;
ai->BotChooseLTGItem = BotChooseLTGItem;
ai->BotChooseNBGItem = BotChooseNBGItem;
ai->BotTouchingGoal = BotTouchingGoal;
ai->BotItemGoalInVisButNotVisible = BotItemGoalInVisButNotVisible;
ai->BotGetLevelItemGoal = BotGetLevelItemGoal;
ai->BotGetNextCampSpotGoal = BotGetNextCampSpotGoal;
ai->BotGetMapLocationGoal = BotGetMapLocationGoal;
ai->BotAvoidGoalTime = BotAvoidGoalTime;
ai->BotInitLevelItems = BotInitLevelItems;
ai->BotUpdateEntityItems = BotUpdateEntityItems;
ai->BotLoadItemWeights = BotLoadItemWeights;
ai->BotFreeItemWeights = BotFreeItemWeights;
ai->BotInterbreedGoalFuzzyLogic = BotInterbreedGoalFuzzyLogic;
ai->BotSaveGoalFuzzyLogic = BotSaveGoalFuzzyLogic;
ai->BotMutateGoalFuzzyLogic = BotMutateGoalFuzzyLogic;
ai->BotAllocGoalState = BotAllocGoalState;
ai->BotFreeGoalState = BotFreeGoalState;
//-----------------------------------
// be_ai_move.h
//-----------------------------------
ai->BotResetMoveState = BotResetMoveState;
ai->BotMoveToGoal = BotMoveToGoal;
ai->BotMoveInDirection = BotMoveInDirection;
ai->BotResetAvoidReach = BotResetAvoidReach;
ai->BotResetLastAvoidReach = BotResetLastAvoidReach;
ai->BotReachabilityArea = BotReachabilityArea;
ai->BotMovementViewTarget = BotMovementViewTarget;
ai->BotPredictVisiblePosition = BotPredictVisiblePosition;
ai->BotAllocMoveState = BotAllocMoveState;
ai->BotFreeMoveState = BotFreeMoveState;
ai->BotInitMoveState = BotInitMoveState;
// Ridah
ai->BotInitAvoidReach = BotInitAvoidReach;
// done.
//-----------------------------------
// be_ai_weap.h
//-----------------------------------
ai->BotChooseBestFightWeapon = BotChooseBestFightWeapon;
ai->BotGetWeaponInfo = BotGetWeaponInfo;
ai->BotLoadWeaponWeights = BotLoadWeaponWeights;
ai->BotAllocWeaponState = BotAllocWeaponState;
ai->BotFreeWeaponState = BotFreeWeaponState;
ai->BotResetWeaponState = BotResetWeaponState;
//-----------------------------------
// be_ai_gen.h
//-----------------------------------
ai->GeneticParentsAndChildSelection = GeneticParentsAndChildSelection;
}
/*
============
GetBotLibAPI
============
*/
botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import ) {
botimport = *import;
memset( &be_botlib_export, 0, sizeof( be_botlib_export ) );
if ( apiVersion != BOTLIB_API_VERSION ) {
botimport.Print( PRT_ERROR, "Mismatched BOTLIB_API_VERSION: expected %i, got %i\n", BOTLIB_API_VERSION, apiVersion );
return NULL;
}
Init_AAS_Export( &be_botlib_export.aas );
Init_EA_Export( &be_botlib_export.ea );
Init_AI_Export( &be_botlib_export.ai );
be_botlib_export.BotLibSetup = Export_BotLibSetup;
be_botlib_export.BotLibShutdown = Export_BotLibShutdown;
be_botlib_export.BotLibVarSet = Export_BotLibVarSet;
be_botlib_export.BotLibVarGet = Export_BotLibVarGet;
be_botlib_export.PC_AddGlobalDefine = PC_AddGlobalDefine;
be_botlib_export.PC_LoadSourceHandle = PC_LoadSourceHandle;
be_botlib_export.PC_FreeSourceHandle = PC_FreeSourceHandle;
be_botlib_export.PC_ReadTokenHandle = PC_ReadTokenHandle;
be_botlib_export.PC_SourceFileAndLine = PC_SourceFileAndLine;
be_botlib_export.BotLibStartFrame = Export_BotLibStartFrame;
be_botlib_export.BotLibLoadMap = Export_BotLibLoadMap;
be_botlib_export.BotLibUpdateEntity = Export_BotLibUpdateEntity;
be_botlib_export.Test = BotExportTest;
return &be_botlib_export;
}

93
src/botlib/be_interface.h Normal file
View File

@ -0,0 +1,93 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: be_interface.h
*
* desc: botlib interface
*
*
*****************************************************************************/
/*
"Do not go where the path leads, rather go where there's no track and leave a trail."
"AAS (Area Awareness System)"
"Part of the Gladiator is BoGuS (Bot Guidance System)"
"ANSI (Advanced Navigational System Interface)"
"to make things work the only thing you really have to do is think things work."
"a madman is just someone living in another reality which isn't shared among many people"
*/
//#define DEBUG //debug code
#define RANDOMIZE //randomize bot behaviour
#if defined( WIN32 ) || defined( _WIN32 )
#define AASZIP //allow reading directly from aasX.zip files
#endif
#define QUAKE2 //bot for Quake2
//#define HALFLIFE //bot for Half-Life
//==========================================================
//
// global variable structures
//
//==========================================================
//FIXME: get rid of this global structure
typedef struct botlib_globals_s
{
int botlibsetup; //true when the bot library has been setup
int maxentities; //maximum number of entities
int maxclients; //maximum number of clients
float time; //the global time
#ifdef DEBUG
qboolean debug; //true if debug is on
int goalareanum;
vec3_t goalorigin;
int runai;
#endif
} botlib_globals_t;
//==========================================================
//
// global variables
//
//==========================================================
extern botlib_globals_t botlibglobals;
extern botlib_import_t botimport;
extern int bot_developer; //true if developer is on
//
int Sys_MilliSeconds( void );

512
src/botlib/botlib.h Normal file
View File

@ -0,0 +1,512 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: botlib.h
// Function: bot AI Library
// Programmer: Mr Elusive (MrElusive@idsoftware.com)
// Last update: 1999-08-18
// Tab Size: 3
//===========================================================================
#define BOTLIB_API_VERSION 2
struct aas_clientmove_s;
struct aas_entityinfo_s;
struct bot_consolemessage_s;
struct bot_match_s;
struct bot_goal_s;
struct bot_moveresult_s;
struct bot_initmove_s;
struct weaponinfo_s;
//debug line colors
#define LINECOLOR_NONE -1
#define LINECOLOR_RED 1 //0xf2f2f0f0L
#define LINECOLOR_GREEN 2 //0xd0d1d2d3L
#define LINECOLOR_BLUE 3 //0xf3f3f1f1L
#define LINECOLOR_YELLOW 4 //0xdcdddedfL
#define LINECOLOR_ORANGE 5 //0xe0e1e2e3L
//Print types
#define PRT_MESSAGE 1
#define PRT_WARNING 2
#define PRT_ERROR 3
#define PRT_FATAL 4
#define PRT_EXIT 5
//console message types
#define CMS_NORMAL 0
#define CMS_CHAT 1
//botlib error codes
#define BLERR_NOERROR 0 //no error
#define BLERR_LIBRARYNOTSETUP 1 //library not setup
#define BLERR_LIBRARYALREADYSETUP 2 //BotSetupLibrary: library already setup
#define BLERR_INVALIDCLIENTNUMBER 3 //invalid client number
#define BLERR_INVALIDENTITYNUMBER 4 //invalid entity number
#define BLERR_NOAASFILE 5 //BotLoadMap: no AAS file available
#define BLERR_CANNOTOPENAASFILE 6 //BotLoadMap: cannot open AAS file
#define BLERR_CANNOTSEEKTOAASFILE 7 //BotLoadMap: cannot seek to AAS file
#define BLERR_CANNOTREADAASHEADER 8 //BotLoadMap: cannot read AAS header
#define BLERR_WRONGAASFILEID 9 //BotLoadMap: incorrect AAS file id
#define BLERR_WRONGAASFILEVERSION 10 //BotLoadMap: incorrect AAS file version
#define BLERR_CANNOTREADAASLUMP 11 //BotLoadMap: cannot read AAS file lump
#define BLERR_NOBSPFILE 12 //BotLoadMap: no BSP file available
#define BLERR_CANNOTOPENBSPFILE 13 //BotLoadMap: cannot open BSP file
#define BLERR_CANNOTSEEKTOBSPFILE 14 //BotLoadMap: cannot seek to BSP file
#define BLERR_CANNOTREADBSPHEADER 15 //BotLoadMap: cannot read BSP header
#define BLERR_WRONGBSPFILEID 16 //BotLoadMap: incorrect BSP file id
#define BLERR_WRONGBSPFILEVERSION 17 //BotLoadMap: incorrect BSP file version
#define BLERR_CANNOTREADBSPLUMP 18 //BotLoadMap: cannot read BSP file lump
#define BLERR_AICLIENTNOTSETUP 19 //BotAI: client not setup
#define BLERR_AICLIENTALREADYSETUP 20 //BotSetupClient: client already setup
#define BLERR_AIMOVEINACTIVECLIENT 21 //BotMoveClient: cannot move inactive client
#define BLERR_AIMOVETOACTIVECLIENT 22 //BotMoveClient: cannot move to active client
#define BLERR_AICLIENTALREADYSHUTDOWN 23 //BotShutdownClient: client not setup
#define BLERR_AIUPDATEINACTIVECLIENT 24 //BotUpdateClient: called for inactive client
#define BLERR_AICMFORINACTIVECLIENT 25 //BotConsoleMessage: called for inactive client
#define BLERR_SETTINGSINACTIVECLIENT 26 //BotClientSettings: called for inactive client
#define BLERR_CANNOTLOADICHAT 27 //BotSetupClient: cannot load initial chats
#define BLERR_CANNOTLOADITEMWEIGHTS 28 //BotSetupClient: cannot load item weights
#define BLERR_CANNOTLOADITEMCONFIG 29 //BotSetupLibrary: cannot load item config
#define BLERR_CANNOTLOADWEAPONWEIGHTS 30 //BotSetupClient: cannot load weapon weights
#define BLERR_CANNOTLOADWEAPONCONFIG 31 //BotSetupLibrary: cannot load weapon config
#define BLERR_INVALIDSOUNDINDEX 32 //BotAddSound: invalid sound index value
//action flags
#define ACTION_ATTACK 1
#define ACTION_USE 2
#define ACTION_RESPAWN 4
#define ACTION_JUMP 8
#define ACTION_MOVEUP 8
#define ACTION_CROUCH 16
#define ACTION_MOVEDOWN 16
#define ACTION_MOVEFORWARD 32
#define ACTION_MOVEBACK 64
#define ACTION_MOVELEFT 128
#define ACTION_MOVERIGHT 256
#define ACTION_DELAYEDJUMP 512
#define ACTION_TALK 1024
#define ACTION_GESTURE 2048
#define ACTION_WALK 4096
//the bot input, will be converted to an usercmd_t
typedef struct bot_input_s
{
float thinktime; //time since last output (in seconds)
vec3_t dir; //movement direction
float speed; //speed in the range [0, 400]
vec3_t viewangles; //the view angles
int actionflags; //one of the ACTION_? flags
int weapon; //weapon to use
} bot_input_t;
#ifndef BSPTRACE
//bsp_trace_t hit surface
typedef struct bsp_surface_s
{
char name[16];
int flags;
int value;
} bsp_surface_t;
//remove the bsp_trace_s structure definition l8r on
//a trace is returned when a box is swept through the world
typedef struct bsp_trace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
float exp_dist; // expanded plane distance
int sidenum; // number of the brush side hit
bsp_surface_t surface; // the hit point surface
int contents; // contents on other side of surface hit
int ent; // number of entity hit
} bsp_trace_t;
#define BSPTRACE
#endif // BSPTRACE
//entity state
typedef struct bot_entitystate_s
{
int type; // entity type
int flags; // entity flags
vec3_t origin; // origin of the entity
vec3_t angles; // angles of the model
vec3_t old_origin; // for lerping
vec3_t mins; // bounding box minimums
vec3_t maxs; // bounding box maximums
int groundent; // ground entity
int solid; // solid type
int modelindex; // model used
int modelindex2; // weapons, CTF flags, etc
int frame; // model frame number
int event; // impulse events -- muzzle flashes, footsteps, etc
int eventParm; // even parameter
int powerups; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim; // mask off ANIM_TOGGLEBIT
int torsoAnim; // mask off ANIM_TOGGLEBIT
// int weapAnim; // mask off ANIM_TOGGLEBIT //----(SA) added
//----(SA) didn't want to comment in as I wasn't sure of any implications of changing this structure.
} bot_entitystate_t;
//bot AI library exported functions
typedef struct botlib_import_s
{
//print messages from the bot library
void ( QDECL * Print )( int type, char *fmt, ... );
//trace a bbox through the world
void ( *Trace )( bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask );
//trace a bbox against a specific entity
void ( *EntityTrace )( bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask );
//retrieve the contents at the given point
int ( *PointContents )( vec3_t point );
//check if the point is in potential visible sight
int ( *inPVS )( vec3_t p1, vec3_t p2 );
//retrieve the BSP entity data lump
char *( *BSPEntityData )( void );
//
void ( *BSPModelMinsMaxsOrigin )( int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin );
//send a bot client command
void ( *BotClientCommand )( int client, char *command );
//memory allocation
void *( *GetMemory )( int size );
void ( *FreeMemory )( void *ptr );
void ( *FreeZoneMemory )( void );
void *( *HunkAlloc )( int size );
//file system access
int ( *FS_FOpenFile )( const char *qpath, fileHandle_t *file, fsMode_t mode );
int ( *FS_Read )( void *buffer, int len, fileHandle_t f );
int ( *FS_Write )( const void *buffer, int len, fileHandle_t f );
void ( *FS_FCloseFile )( fileHandle_t f );
int ( *FS_Seek )( fileHandle_t f, long offset, int origin );
//debug visualisation stuff
int ( *DebugLineCreate )( void );
void ( *DebugLineDelete )( int line );
void ( *DebugLineShow )( int line, vec3_t start, vec3_t end, int color );
//
int ( *DebugPolygonCreate )( int color, int numPoints, vec3_t *points );
void ( *DebugPolygonDelete )( int id );
//
// Ridah, Cast AI stuff
qboolean ( *AICast_VisibleFromPos )( vec3_t srcpos, int srcnum,
vec3_t destpos, int destnum, qboolean updateVisPos );
qboolean ( *AICast_CheckAttackAtPos )( int entnum, int enemy, vec3_t pos, qboolean ducking, qboolean allowHitWorld );
// done.
} botlib_import_t;
typedef struct aas_export_s
{
//-----------------------------------
// be_aas_entity.h
//-----------------------------------
void ( *AAS_EntityInfo )( int entnum, struct aas_entityinfo_s *info );
//-----------------------------------
// be_aas_main.h
//-----------------------------------
int ( *AAS_Initialized )( void );
void ( *AAS_PresenceTypeBoundingBox )( int presencetype, vec3_t mins, vec3_t maxs );
float ( *AAS_Time )( void );
//--------------------------------------------
// be_aas_sample.c
//--------------------------------------------
int ( *AAS_PointAreaNum )( vec3_t point );
int ( *AAS_TraceAreas )( vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas );
//--------------------------------------------
// be_aas_bspq3.c
//--------------------------------------------
int ( *AAS_PointContents )( vec3_t point );
int ( *AAS_NextBSPEntity )( int ent );
int ( *AAS_ValueForBSPEpairKey )( int ent, char *key, char *value, int size );
int ( *AAS_VectorForBSPEpairKey )( int ent, char *key, vec3_t v );
int ( *AAS_FloatForBSPEpairKey )( int ent, char *key, float *value );
int ( *AAS_IntForBSPEpairKey )( int ent, char *key, int *value );
//--------------------------------------------
// be_aas_reach.c
//--------------------------------------------
int ( *AAS_AreaReachability )( int areanum );
//--------------------------------------------
// be_aas_route.c
//--------------------------------------------
int ( *AAS_AreaTravelTimeToGoalArea )( int areanum, vec3_t origin, int goalareanum, int travelflags );
//--------------------------------------------
// be_aas_move.c
//--------------------------------------------
int ( *AAS_Swimming )( vec3_t origin );
int ( *AAS_PredictClientMovement )( struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
int stopevent, int stopareanum, int visualize );
// Ridah, route-tables
//--------------------------------------------
// be_aas_routetable.c
//--------------------------------------------
void ( *AAS_RT_ShowRoute )( vec3_t srcpos, int srcnum, int destnum );
qboolean ( *AAS_RT_GetHidePos )( vec3_t srcpos, int srcnum, int srcarea, vec3_t destpos, int destnum, int destarea, vec3_t returnPos );
int ( *AAS_FindAttackSpotWithinRange )( int srcnum, int rangenum, int enemynum, float rangedist, int travelflags, float *outpos );
void ( *AAS_SetAASBlockingEntity )( vec3_t absmin, vec3_t absmax, qboolean blocking );
// done.
// Ridah
void ( *AAS_SetCurrentWorld )( int index );
// done.
} aas_export_t;
typedef struct ea_export_s
{
//ClientCommand elementary actions
void ( *EA_Say )( int client, char *str );
void ( *EA_SayTeam )( int client, char *str );
void ( *EA_UseItem )( int client, char *it );
void ( *EA_DropItem )( int client, char *it );
void ( *EA_UseInv )( int client, char *inv );
void ( *EA_DropInv )( int client, char *inv );
void ( *EA_Gesture )( int client );
void ( *EA_Command )( int client, char *command );
//regular elementary actions
void ( *EA_SelectWeapon )( int client, int weapon );
void ( *EA_Talk )( int client );
void ( *EA_Attack )( int client );
void ( *EA_Use )( int client );
void ( *EA_Respawn )( int client );
void ( *EA_Jump )( int client );
void ( *EA_DelayedJump )( int client );
void ( *EA_Crouch )( int client );
void ( *EA_MoveUp )( int client );
void ( *EA_MoveDown )( int client );
void ( *EA_MoveForward )( int client );
void ( *EA_MoveBack )( int client );
void ( *EA_MoveLeft )( int client );
void ( *EA_MoveRight )( int client );
void ( *EA_Move )( int client, vec3_t dir, float speed );
void ( *EA_View )( int client, vec3_t viewangles );
//send regular input to the server
void ( *EA_EndRegular )( int client, float thinktime );
void ( *EA_GetInput )( int client, float thinktime, bot_input_t *input );
void ( *EA_ResetInput )( int client, bot_input_t *init );
} ea_export_t;
typedef struct ai_export_s
{
//-----------------------------------
// be_ai_char.h
//-----------------------------------
int ( *BotLoadCharacter )( char *charfile, int skill );
void ( *BotFreeCharacter )( int character );
float ( *Characteristic_Float )( int character, int index );
float ( *Characteristic_BFloat )( int character, int index, float min, float max );
int ( *Characteristic_Integer )( int character, int index );
int ( *Characteristic_BInteger )( int character, int index, int min, int max );
void ( *Characteristic_String )( int character, int index, char *buf, int size );
//-----------------------------------
// be_ai_chat.h
//-----------------------------------
int ( *BotAllocChatState )( void );
void ( *BotFreeChatState )( int handle );
void ( *BotQueueConsoleMessage )( int chatstate, int type, char *message );
void ( *BotRemoveConsoleMessage )( int chatstate, int handle );
int ( *BotNextConsoleMessage )( int chatstate, struct bot_consolemessage_s *cm );
int ( *BotNumConsoleMessages )( int chatstate );
void ( *BotInitialChat )( int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 );
int ( *BotNumInitialChats )( int chatstate, char *type );
int ( *BotReplyChat )( int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 );
int ( *BotChatLength )( int chatstate );
void ( *BotEnterChat )( int chatstate, int client, int sendto );
void ( *BotGetChatMessage )( int chatstate, char *buf, int size );
int ( *StringContains )( char *str1, char *str2, int casesensitive );
int ( *BotFindMatch )( char *str, struct bot_match_s *match, unsigned long int context );
void ( *BotMatchVariable )( struct bot_match_s *match, int variable, char *buf, int size );
void ( *UnifyWhiteSpaces )( char *string );
void ( *BotReplaceSynonyms )( char *string, unsigned long int context );
int ( *BotLoadChatFile )( int chatstate, char *chatfile, char *chatname );
void ( *BotSetChatGender )( int chatstate, int gender );
void ( *BotSetChatName )( int chatstate, char *name );
//-----------------------------------
// be_ai_goal.h
//-----------------------------------
void ( *BotResetGoalState )( int goalstate );
void ( *BotResetAvoidGoals )( int goalstate );
void ( *BotRemoveFromAvoidGoals )( int goalstate, int number );
void ( *BotPushGoal )( int goalstate, struct bot_goal_s *goal );
void ( *BotPopGoal )( int goalstate );
void ( *BotEmptyGoalStack )( int goalstate );
void ( *BotDumpAvoidGoals )( int goalstate );
void ( *BotDumpGoalStack )( int goalstate );
void ( *BotGoalName )( int number, char *name, int size );
int ( *BotGetTopGoal )( int goalstate, struct bot_goal_s *goal );
int ( *BotGetSecondGoal )( int goalstate, struct bot_goal_s *goal );
int ( *BotChooseLTGItem )( int goalstate, vec3_t origin, int *inventory, int travelflags );
int ( *BotChooseNBGItem )( int goalstate, vec3_t origin, int *inventory, int travelflags,
struct bot_goal_s *ltg, float maxtime );
int ( *BotTouchingGoal )( vec3_t origin, struct bot_goal_s *goal );
int ( *BotItemGoalInVisButNotVisible )( int viewer, vec3_t eye, vec3_t viewangles, struct bot_goal_s *goal );
int ( *BotGetLevelItemGoal )( int index, char *classname, struct bot_goal_s *goal );
int ( *BotGetNextCampSpotGoal )( int num, struct bot_goal_s *goal );
int ( *BotGetMapLocationGoal )( char *name, struct bot_goal_s *goal );
float ( *BotAvoidGoalTime )( int goalstate, int number );
void ( *BotInitLevelItems )( void );
void ( *BotUpdateEntityItems )( void );
int ( *BotLoadItemWeights )( int goalstate, char *filename );
void ( *BotFreeItemWeights )( int goalstate );
void ( *BotInterbreedGoalFuzzyLogic )( int parent1, int parent2, int child );
void ( *BotSaveGoalFuzzyLogic )( int goalstate, char *filename );
void ( *BotMutateGoalFuzzyLogic )( int goalstate, float range );
int ( *BotAllocGoalState )( int client );
void ( *BotFreeGoalState )( int handle );
//-----------------------------------
// be_ai_move.h
//-----------------------------------
void ( *BotResetMoveState )( int movestate );
void ( *BotMoveToGoal )( struct bot_moveresult_s *result, int movestate, struct bot_goal_s *goal, int travelflags );
int ( *BotMoveInDirection )( int movestate, vec3_t dir, float speed, int type );
void ( *BotResetAvoidReach )( int movestate );
void ( *BotResetLastAvoidReach )( int movestate );
int ( *BotReachabilityArea )( vec3_t origin, int testground );
int ( *BotMovementViewTarget )( int movestate, struct bot_goal_s *goal, int travelflags, float lookahead, vec3_t target );
int ( *BotPredictVisiblePosition )( vec3_t origin, int areanum, struct bot_goal_s *goal, int travelflags, vec3_t target );
int ( *BotAllocMoveState )( void );
void ( *BotFreeMoveState )( int handle );
void ( *BotInitMoveState )( int handle, struct bot_initmove_s *initmove );
// Ridah
void ( *BotInitAvoidReach )( int handle );
// done.
//-----------------------------------
// be_ai_weap.h
//-----------------------------------
int ( *BotChooseBestFightWeapon )( int weaponstate, int *inventory );
void ( *BotGetWeaponInfo )( int weaponstate, int weapon, struct weaponinfo_s *weaponinfo );
int ( *BotLoadWeaponWeights )( int weaponstate, char *filename );
int ( *BotAllocWeaponState )( void );
void ( *BotFreeWeaponState )( int weaponstate );
void ( *BotResetWeaponState )( int weaponstate );
//-----------------------------------
// be_ai_gen.h
//-----------------------------------
int ( *GeneticParentsAndChildSelection )( int numranks, float *ranks, int *parent1, int *parent2, int *child );
} ai_export_t;
//bot AI library imported functions
typedef struct botlib_export_s
{
//Area Awareness System functions
aas_export_t aas;
//Elementary Action functions
ea_export_t ea;
//AI functions
ai_export_t ai;
//setup the bot library, returns BLERR_
int ( *BotLibSetup )( void );
//shutdown the bot library, returns BLERR_
int ( *BotLibShutdown )( void );
//sets a library variable returns BLERR_
int ( *BotLibVarSet )( char *var_name, char *value );
//gets a library variable returns BLERR_
int ( *BotLibVarGet )( char *var_name, char *value, int size );
//sets a C-like define returns BLERR_
int ( *BotLibDefine )( char *string );
//start a frame in the bot library
int ( *BotLibStartFrame )( float time );
//load a new map in the bot library
int ( *BotLibLoadMap )( const char *mapname );
//entity updates
int ( *BotLibUpdateEntity )( int ent, bot_entitystate_t *state );
//just for testing
int ( *Test )( int parm0, char *parm1, vec3_t parm2, vec3_t parm3 );
} botlib_export_t;
//linking of bot library
botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import );
/* Library variables:
name: default: module(s): description:
"basedir" "" l_utils.c Quake2 base directory
"gamedir" "" l_utils.c Quake2 game directory
"cddir" "" l_utils.c Quake2 CD directory
"autolaunchbspc" "0" be_aas_load.c automatically launch (Win)BSPC
"log" "0" l_log.c enable/disable creating a log file
"maxclients" "4" be_interface.c maximum number of clients
"maxentities" "1024" be_interface.c maximum number of entities
"sv_friction" "6" be_aas_move.c ground friction
"sv_stopspeed" "100" be_aas_move.c stop speed
"sv_gravity" "800" be_aas_move.c gravity value
"sv_waterfriction" "1" be_aas_move.c water friction
"sv_watergravity" "400" be_aas_move.c gravity in water
"sv_maxvelocity" "300" be_aas_move.c maximum velocity
"sv_maxwalkvelocity" "300" be_aas_move.c maximum walk velocity
"sv_maxcrouchvelocity" "100" be_aas_move.c maximum crouch velocity
"sv_maxswimvelocity" "150" be_aas_move.c maximum swim velocity
"sv_walkaccelerate" "10" be_aas_move.c walk acceleration
"sv_airaccelerate" "1" be_aas_move.c air acceleration
"sv_swimaccelerate" "4" be_aas_move.c swim acceleration
"sv_maxstep" "18" be_aas_move.c maximum step height
"sv_maxbarrier" "32" be_aas_move.c maximum barrier height
"sv_maxsteepness" "0.7" be_aas_move.c maximum floor steepness
"sv_jumpvel" "270" be_aas_move.c jump z velocity
"sv_maxwaterjump" "20" be_aas_move.c maximum waterjump height
"max_aaslinks" "4096" be_aas_sample.c maximum links in the AAS
"max_bsplinks" "4096" be_aas_bsp.c maximum links in the BSP
"notspawnflags" "2048" be_ai_goal.c entities with these spawnflags will be removed
"itemconfig" "items.c" be_ai_goal.c item configuration file
"weaponconfig" "weapons.c" be_ai_weap.c weapon configuration file
"synfile" "syn.c" be_ai_chat.c file with synonyms
"rndfile" "rnd.c" be_ai_chat.c file with random strings
"matchfile" "match.c" be_ai_chat.c file with match strings
"max_messages" "1024" be_ai_chat.c console message heap size
"max_weaponinfo" "32" be_ai_weap.c maximum number of weapon info
"max_projectileinfo" "32" be_ai_weap.c maximum number of projectile info
"max_iteminfo" "256" be_ai_goal.c maximum number of item info
"max_levelitems" "256" be_ai_goal.c maximum number of level items
"framereachability" "" be_aas_reach.c number of reachabilities to calucate per frame
"forceclustering" "0" be_aas_main.c force recalculation of clusters
"forcereachability" "0" be_aas_main.c force recalculation of reachabilities
"forcewrite" "0" be_aas_main.c force writing of aas file
"nooptimize" "0" be_aas_main.c no aas optimization
"laserhook" "0" be_ai_move.c 0 = CTF hook, 1 = laser hook
*/

911
src/botlib/botlib.vcproj Normal file
View File

@ -0,0 +1,911 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="botlib"
ProjectGUID="{86691FDD-E0C6-4D71-9FFD-E0F30F19AA3E}"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;BOTLIB;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\Release/botlib.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="4"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Release\botlib.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Release/botlib.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;BOTLIB;DEBUG;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
PrecompiledHeaderFile=".\Debug/botlib.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Debug\botlib.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\Debug/botlib.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath="be_aas_bspq3.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_cluster.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_debug.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_entity.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_file.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_main.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_move.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_optimize.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_reach.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_route.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_routealt.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_routetable.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_aas_sample.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_char.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_chat.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_gen.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_goal.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_move.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_weap.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ai_weight.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_ea.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="be_interface.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_crc.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_libvar.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_log.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_memory.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_precomp.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_script.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="l_struct.c"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="aasfile.h"
>
</File>
<File
RelativePath="..\game\be_aas.h"
>
</File>
<File
RelativePath="be_aas_bsp.h"
>
</File>
<File
RelativePath="be_aas_cluster.h"
>
</File>
<File
RelativePath="be_aas_debug.h"
>
</File>
<File
RelativePath="be_aas_def.h"
>
</File>
<File
RelativePath="be_aas_entity.h"
>
</File>
<File
RelativePath="be_aas_file.h"
>
</File>
<File
RelativePath="be_aas_funcs.h"
>
</File>
<File
RelativePath="be_aas_main.h"
>
</File>
<File
RelativePath="be_aas_move.h"
>
</File>
<File
RelativePath="be_aas_optimize.h"
>
</File>
<File
RelativePath="be_aas_reach.h"
>
</File>
<File
RelativePath="be_aas_route.h"
>
</File>
<File
RelativePath="be_aas_routealt.h"
>
</File>
<File
RelativePath="be_aas_routetable.h"
>
</File>
<File
RelativePath="be_aas_sample.h"
>
</File>
<File
RelativePath="..\game\be_ai_char.h"
>
</File>
<File
RelativePath="..\game\be_ai_chat.h"
>
</File>
<File
RelativePath="..\game\be_ai_gen.h"
>
</File>
<File
RelativePath="..\game\be_ai_goal.h"
>
</File>
<File
RelativePath="..\game\be_ai_move.h"
>
</File>
<File
RelativePath="..\game\be_ai_weap.h"
>
</File>
<File
RelativePath="be_ai_weight.h"
>
</File>
<File
RelativePath="..\game\be_ea.h"
>
</File>
<File
RelativePath="be_interface.h"
>
</File>
<File
RelativePath="..\game\botlib.h"
>
</File>
<File
RelativePath="l_crc.h"
>
</File>
<File
RelativePath="l_libvar.h"
>
</File>
<File
RelativePath="l_log.h"
>
</File>
<File
RelativePath="l_memory.h"
>
</File>
<File
RelativePath="l_precomp.h"
>
</File>
<File
RelativePath="l_script.h"
>
</File>
<File
RelativePath="l_struct.h"
>
</File>
<File
RelativePath="l_utils.h"
>
</File>
<File
RelativePath="..\game\q_shared.h"
>
</File>
<File
RelativePath="..\game\surfaceflags.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

155
src/botlib/l_crc.c Normal file
View File

@ -0,0 +1,155 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_crc.c
*
* desc: CRC calculation
*
*
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../game/q_shared.h"
#include "../game/botlib.h"
#include "be_interface.h" //for botimport.Print
// FIXME: byte swap?
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
unsigned short crctable[257] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
0x0000 // because process string allows value 256 through and it was undefined
};
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void CRC_Init( unsigned short *crcvalue ) {
*crcvalue = CRC_INIT_VALUE;
} //end of the function CRC_Init
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void CRC_ProcessByte( unsigned short *crcvalue, byte data ) {
*crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
} //end of the function CRC_ProcessByte
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
unsigned short CRC_Value( unsigned short crcvalue ) {
return crcvalue ^ CRC_XOR_VALUE;
} //end of the function CRC_Value
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
unsigned short CRC_ProcessString( unsigned char *data, int length ) {
unsigned short crcvalue;
int i, ind;
CRC_Init( &crcvalue );
for ( i = 0; i < length; i++ )
{
ind = ( crcvalue >> 8 ) ^ data[i];
if ( ind < 0 || ind > 256 ) {
ind = 0;
}
crcvalue = ( crcvalue << 8 ) ^ crctable[ind];
} //end for
return CRC_Value( crcvalue );
} //end of the function CRC_ProcessString
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void CRC_ContinueProcessString( unsigned short *crc, char *data, int length ) {
int i;
for ( i = 0; i < length; i++ )
{
*crc = ( *crc << 8 ) ^ crctable[( *crc >> 8 ) ^ data[i]];
} //end for
} //end of the function CRC_ProcessString

44
src/botlib/l_crc.h Normal file
View File

@ -0,0 +1,44 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: l_crc.h
// Function: for CRC checks
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-31
// Tab Size: 3
//===========================================================================
typedef unsigned short crc_t;
void CRC_Init( unsigned short *crcvalue );
void CRC_ProcessByte( unsigned short *crcvalue, byte data );
unsigned short CRC_Value( unsigned short crcvalue );
unsigned short CRC_ProcessString( unsigned char *data, int length );
void CRC_ContinueProcessString( unsigned short *crc, char *data, int length );

282
src/botlib/l_libvar.c Normal file
View File

@ -0,0 +1,282 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_libvar.c
*
* desc: bot library variables
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_libvar.h"
//list with library variables
libvar_t *libvarlist;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float LibVarStringValue( char *string ) {
int dotfound = 0;
float value = 0;
while ( *string )
{
if ( *string < '0' || *string > '9' ) {
if ( dotfound || *string != '.' ) {
return 0;
} //end if
else
{
dotfound = 10;
string++;
} //end if
} //end if
if ( dotfound ) {
value = value + (float) ( *string - '0' ) / (float) dotfound;
dotfound *= 10;
} //end if
else
{
value = value * 10.0 + (float) ( *string - '0' );
} //end else
string++;
} //end while
return value;
} //end of the function LibVarStringValue
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
libvar_t *LibVarAlloc( char *var_name ) {
libvar_t *v;
v = (libvar_t *) GetMemory( sizeof( libvar_t ) + strlen( var_name ) + 1 );
memset( v, 0, sizeof( libvar_t ) );
v->name = (char *) v + sizeof( libvar_t );
strcpy( v->name, var_name );
//add the variable in the list
v->next = libvarlist;
libvarlist = v;
return v;
} //end of the function LibVarAlloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LibVarDeAlloc( libvar_t *v ) {
if ( v->string ) {
FreeMemory( v->string );
}
FreeMemory( v );
} //end of the function LibVarDeAlloc
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LibVarDeAllocAll( void ) {
libvar_t *v;
for ( v = libvarlist; v; v = libvarlist )
{
libvarlist = libvarlist->next;
LibVarDeAlloc( v );
} //end for
libvarlist = NULL;
} //end of the function LibVarDeAllocAll
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
libvar_t *LibVarGet( char *var_name ) {
libvar_t *v;
for ( v = libvarlist; v; v = v->next )
{
if ( !Q_stricmp( v->name, var_name ) ) {
return v;
} //end if
} //end for
return NULL;
} //end of the function LibVarGet
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *LibVarGetString( char *var_name ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
return v->string;
} //end if
else
{
return "";
} //end else
} //end of the function LibVarGetString
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float LibVarGetValue( char *var_name ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
return v->value;
} //end if
else
{
return 0;
} //end else
} //end of the function LibVarGetValue
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
libvar_t *LibVar( char *var_name, char *value ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
return v;
}
//create new variable
v = LibVarAlloc( var_name );
//variable string
v->string = (char *) GetMemory( strlen( value ) + 1 );
strcpy( v->string, value );
//the value
v->value = LibVarStringValue( v->string );
//variable is modified
v->modified = qtrue;
//
return v;
} //end of the function LibVar
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *LibVarString( char *var_name, char *value ) {
libvar_t *v;
v = LibVar( var_name, value );
return v->string;
} //end of the function LibVarString
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float LibVarValue( char *var_name, char *value ) {
libvar_t *v;
v = LibVar( var_name, value );
return v->value;
} //end of the function LibVarValue
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LibVarSet( char *var_name, char *value ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
FreeMemory( v->string );
} //end if
else
{
v = LibVarAlloc( var_name );
} //end else
//variable string
v->string = (char *) GetMemory( strlen( value ) + 1 );
strcpy( v->string, value );
//the value
v->value = LibVarStringValue( v->string );
//variable is modified
v->modified = qtrue;
} //end of the function LibVarSet
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean LibVarChanged( char *var_name ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
return v->modified;
} //end if
else
{
return qfalse;
} //end else
} //end of the function LibVarChanged
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LibVarSetNotModified( char *var_name ) {
libvar_t *v;
v = LibVarGet( var_name );
if ( v ) {
v->modified = qfalse;
} //end if
} //end of the function LibVarSetNotModified

69
src/botlib/l_libvar.h Normal file
View File

@ -0,0 +1,69 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_libvar.h
*
* desc: botlib vars
*
*
*****************************************************************************/
//library variable
typedef struct libvar_s
{
char *name;
char *string;
int flags;
qboolean modified; // set each time the cvar is changed
float value;
struct libvar_s *next;
} libvar_t;
//removes all library variables
void LibVarDeAllocAll( void );
//gets the library variable with the given name
libvar_t *LibVarGet( char *var_name );
//gets the string of the library variable with the given name
char *LibVarGetString( char *var_name );
//gets the value of the library variable with the given name
float LibVarGetValue( char *var_name );
//creates the library variable if not existing already and returns it
libvar_t *LibVar( char *var_name, char *value );
//creates the library variable if not existing already and returns the value
float LibVarValue( char *var_name, char *value );
//creates the library variable if not existing already and returns the value string
char *LibVarString( char *var_name, char *value );
//sets the library variable
void LibVarSet( char *var_name, char *value );
//returns true if the library variable has been modified
qboolean LibVarChanged( char *var_name );
//sets the library variable to unmodified
void LibVarSetNotModified( char *var_name );

186
src/botlib/l_log.c Normal file
View File

@ -0,0 +1,186 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_log.c
*
* desc: log file
*
*
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../game/q_shared.h"
#include "../game/botlib.h"
#include "be_interface.h" //for botimport.Print
#include "l_libvar.h"
#define MAX_LOGFILENAMESIZE 1024
typedef struct logfile_s
{
char filename[MAX_LOGFILENAMESIZE];
FILE *fp;
int numwrites;
} logfile_t;
static logfile_t logfile;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_AlwaysOpen( char *filename ) {
if ( !filename || !strlen( filename ) ) {
botimport.Print( PRT_MESSAGE, "openlog <filename>\n" );
return;
} //end if
if ( logfile.fp ) {
botimport.Print( PRT_ERROR, "log file %s is already opened\n", logfile.filename );
return;
} //end if
logfile.fp = fopen( filename, "wb" );
if ( !logfile.fp ) {
botimport.Print( PRT_ERROR, "can't open the log file %s\n", filename );
return;
} //end if
strncpy( logfile.filename, filename, MAX_LOGFILENAMESIZE );
botimport.Print( PRT_MESSAGE, "Opened log %s\n", logfile.filename );
} //end of the function Log_Create
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Open( char *filename ) {
if ( !LibVarValue( "log", "0" ) ) {
return;
}
Log_AlwaysOpen( filename );
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Close( void ) {
if ( !logfile.fp ) {
return;
}
if ( fclose( logfile.fp ) ) {
botimport.Print( PRT_ERROR, "can't close log file %s\n", logfile.filename );
return;
} //end if
logfile.fp = NULL;
botimport.Print( PRT_MESSAGE, "Closed log %s\n", logfile.filename );
} //end of the function Log_Close
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Shutdown( void ) {
if ( logfile.fp ) {
Log_Close();
}
} //end of the function Log_Shutdown
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void QDECL Log_Write( char *fmt, ... ) {
va_list ap;
if ( !logfile.fp ) {
return;
}
va_start( ap, fmt );
vfprintf( logfile.fp, fmt, ap );
va_end( ap );
//fprintf(logfile.fp, "\r\n");
fflush( logfile.fp );
} //end of the function Log_Write
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void QDECL Log_WriteTimeStamped( char *fmt, ... ) {
va_list ap;
if ( !logfile.fp ) {
return;
}
fprintf( logfile.fp, "%d %02d:%02d:%02d:%02d ",
logfile.numwrites,
(int) ( botlibglobals.time / 60 / 60 ),
(int) ( botlibglobals.time / 60 ),
(int) ( botlibglobals.time ),
(int) ( (int) ( botlibglobals.time * 100 ) ) -
( (int) botlibglobals.time ) * 100 );
va_start( ap, fmt );
vfprintf( logfile.fp, fmt, ap );
va_end( ap );
fprintf( logfile.fp, "\r\n" );
logfile.numwrites++;
fflush( logfile.fp );
} //end of the function Log_Write
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
FILE *Log_FilePointer( void ) {
return logfile.fp;
} //end of the function Log_FilePointer
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Flush( void ) {
if ( logfile.fp ) {
fflush( logfile.fp );
}
} //end of the function Log_Flush

54
src/botlib/l_log.h Normal file
View File

@ -0,0 +1,54 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_log.h
*
* desc: log file
*
*
*****************************************************************************/
//open a log file
void Log_Open( char *filename );
//
void Log_AlwaysOpen( char *filename );
//close the current log file
void Log_Close( void );
//close log file if present
void Log_Shutdown( void );
//write to the current opened log file
void QDECL Log_Write( char *fmt, ... );
//write to the current opened log file with a time stamp
void QDECL Log_WriteTimeStamped( char *fmt, ... );
//returns a pointer to the log file
FILE *Log_FilePointer( void );
//flush log file
void Log_Flush( void );

446
src/botlib/l_memory.c Normal file
View File

@ -0,0 +1,446 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_memory.c
*
* desc: memory allocation
*
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "../game/botlib.h"
#include "l_log.h"
#include "be_interface.h"
#ifdef _DEBUG
#define MEMDEBUG
#define MEMORYMANEGER
#endif
#define MEM_ID 0x12345678l
#define HUNK_ID 0x87654321l
int allocatedmemory;
int totalmemorysize;
int numblocks;
#ifdef MEMORYMANEGER
typedef struct memoryblock_s
{
unsigned long int id;
void *ptr;
int size;
#ifdef MEMDEBUG
char *label;
char *file;
int line;
#endif //MEMDEBUG
struct memoryblock_s *prev, *next;
} memoryblock_t;
memoryblock_t *memory;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void LinkMemoryBlock( memoryblock_t *block ) {
block->prev = NULL;
block->next = memory;
if ( memory ) {
memory->prev = block;
}
memory = block;
} //end of the function LinkMemoryBlock
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void UnlinkMemoryBlock( memoryblock_t *block ) {
if ( block->prev ) {
block->prev->next = block->next;
} else { memory = block->next;}
if ( block->next ) {
block->next->prev = block->prev;
}
} //end of the function UnlinkMemoryBlock
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
memoryblock_t *block;
ptr = botimport.GetMemory( size + sizeof( memoryblock_t ) );
block = (memoryblock_t *) ptr;
block->id = MEM_ID;
block->ptr = (char *) ptr + sizeof( memoryblock_t );
block->size = size + sizeof( memoryblock_t );
#ifdef MEMDEBUG
block->label = label;
block->file = file;
block->line = line;
#endif //MEMDEBUG
LinkMemoryBlock( block );
allocatedmemory += block->size;
totalmemorysize += block->size + sizeof( memoryblock_t );
numblocks++;
return block->ptr;
} //end of the function GetMemoryDebug
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetClearedMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetClearedMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
#ifdef MEMDEBUG
ptr = GetMemoryDebug( size, label, file, line );
#else
ptr = GetMemory( size );
#endif //MEMDEBUG
memset( ptr, 0, size );
return ptr;
} //end of the function GetClearedMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetHunkMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetHunkMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
memoryblock_t *block;
ptr = botimport.HunkAlloc( size + sizeof( memoryblock_t ) );
block = (memoryblock_t *) ptr;
block->id = HUNK_ID;
block->ptr = (char *) ptr + sizeof( memoryblock_t );
block->size = size + sizeof( memoryblock_t );
#ifdef MEMDEBUG
block->label = label;
block->file = file;
block->line = line;
#endif //MEMDEBUG
LinkMemoryBlock( block );
allocatedmemory += block->size;
totalmemorysize += block->size + sizeof( memoryblock_t );
numblocks++;
return block->ptr;
} //end of the function GetHunkMemoryDebug
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetClearedHunkMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetClearedHunkMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
#ifdef MEMDEBUG
ptr = GetHunkMemoryDebug( size, label, file, line );
#else
ptr = GetHunkMemory( size );
#endif //MEMDEBUG
memset( ptr, 0, size );
return ptr;
} //end of the function GetClearedHunkMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
memoryblock_t *BlockFromPointer( void *ptr, char *str ) {
memoryblock_t *block;
if ( !ptr ) {
#ifdef MEMDEBUG
//char *crash = (char *) NULL;
//crash[0] = 1;
botimport.Print( PRT_FATAL, "%s: NULL pointer\n", str );
#endif //MEMDEBUG
return NULL;
} //end if
block = ( memoryblock_t * )( (char *) ptr - sizeof( memoryblock_t ) );
if ( block->id != MEM_ID && block->id != HUNK_ID ) {
botimport.Print( PRT_FATAL, "%s: invalid memory block\n", str );
return NULL;
} //end if
if ( block->ptr != ptr ) {
botimport.Print( PRT_FATAL, "%s: memory block pointer invalid\n", str );
return NULL;
} //end if
return block;
} //end of the function BlockFromPointer
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeMemory( void *ptr ) {
memoryblock_t *block;
block = BlockFromPointer( ptr, "FreeMemory" );
if ( !block ) {
return;
}
UnlinkMemoryBlock( block );
allocatedmemory -= block->size;
totalmemorysize -= block->size + sizeof( memoryblock_t );
numblocks--;
//
if ( block->id == MEM_ID ) {
botimport.FreeMemory( block );
} //end if
} //end of the function FreeMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int MemoryByteSize( void *ptr ) {
memoryblock_t *block;
block = BlockFromPointer( ptr, "MemoryByteSize" );
if ( !block ) {
return 0;
}
return block->size;
} //end of the function MemoryByteSize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintUsedMemorySize( void ) {
botimport.Print( PRT_MESSAGE, "total allocated memory: %d KB\n", allocatedmemory >> 10 );
botimport.Print( PRT_MESSAGE, "total botlib memory: %d KB\n", totalmemorysize >> 10 );
botimport.Print( PRT_MESSAGE, "total memory blocks: %d\n", numblocks );
} //end of the function PrintUsedMemorySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintMemoryLabels( void ) {
memoryblock_t *block;
int i;
PrintUsedMemorySize();
i = 0;
Log_Write( "\r\n" );
for ( block = memory; block; block = block->next )
{
#ifdef MEMDEBUG
if ( block->id == HUNK_ID ) {
Log_Write( "%6d, hunk %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label );
} //end if
else
{
Log_Write( "%6d, %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label );
} //end else
#endif //MEMDEBUG
i++;
} //end for
} //end of the function PrintMemoryLabels
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void DumpMemory( void ) {
memoryblock_t *block;
for ( block = memory; block; block = memory )
{
FreeMemory( block->ptr );
} //end for
totalmemorysize = 0;
allocatedmemory = 0;
} //end of the function DumpMemory
#else
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
unsigned long int *memid;
ptr = botimport.GetMemory( size + sizeof( unsigned long int ) );
if ( !ptr ) {
return NULL;
}
memid = (unsigned long int *) ptr;
*memid = MEM_ID;
return (unsigned long int *) ( (char *) ptr + sizeof( unsigned long int ) );
} //end of the function GetMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetClearedMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetClearedMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
#ifdef MEMDEBUG
ptr = GetMemoryDebug( size, label, file, line );
#else
ptr = GetMemory( size );
#endif //MEMDEBUG
memset( ptr, 0, size );
return ptr;
} //end of the function GetClearedMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetHunkMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetHunkMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
unsigned long int *memid;
ptr = botimport.HunkAlloc( size + sizeof( unsigned long int ) );
if ( !ptr ) {
return NULL;
}
memid = (unsigned long int *) ptr;
*memid = HUNK_ID;
return (unsigned long int *) ( (char *) ptr + sizeof( unsigned long int ) );
} //end of the function GetHunkMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifdef MEMDEBUG
void *GetClearedHunkMemoryDebug( unsigned long size, char *label, char *file, int line )
#else
void *GetClearedHunkMemory( unsigned long size )
#endif //MEMDEBUG
{
void *ptr;
#ifdef MEMDEBUG
ptr = GetHunkMemoryDebug( size, label, file, line );
#else
ptr = GetHunkMemory( size );
#endif //MEMDEBUG
memset( ptr, 0, size );
return ptr;
} //end of the function GetClearedHunkMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeMemory( void *ptr ) {
unsigned long int *memid;
memid = (unsigned long int *) ( (char *) ptr - sizeof( unsigned long int ) );
if ( *memid == MEM_ID ) {
botimport.FreeMemory( memid );
} //end if
} //end of the function FreeMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintUsedMemorySize( void ) {
} //end of the function PrintUsedMemorySize
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintMemoryLabels( void ) {
} //end of the function PrintMemoryLabels
#endif

84
src/botlib/l_memory.h Normal file
View File

@ -0,0 +1,84 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_memory.h
*
* desc: memory management
*
*
*****************************************************************************/
#ifdef _DEBUG
#ifndef BSPC
#define MEMDEBUG
#endif
#endif
#ifdef MEMDEBUG
#define GetMemory( size ) GetMemoryDebug( size, # size, __FILE__, __LINE__ );
#define GetClearedMemory( size ) GetClearedMemoryDebug( size, # size, __FILE__, __LINE__ );
//allocate a memory block of the given size
void *GetMemoryDebug( unsigned long size, char *label, char *file, int line );
//allocate a memory block of the given size and clear it
void *GetClearedMemoryDebug( unsigned long size, char *label, char *file, int line );
//
#define GetHunkMemory( size ) GetHunkMemoryDebug( size, # size, __FILE__, __LINE__ );
#define GetClearedHunkMemory( size ) GetClearedHunkMemoryDebug( size, # size, __FILE__, __LINE__ );
//allocate a memory block of the given size
void *GetHunkMemoryDebug( unsigned long size, char *label, char *file, int line );
//allocate a memory block of the given size and clear it
void *GetClearedHunkMemoryDebug( unsigned long size, char *label, char *file, int line );
#else
//allocate a memory block of the given size
void *GetMemory( unsigned long size );
//allocate a memory block of the given size and clear it
void *GetClearedMemory( unsigned long size );
//
#ifdef BSPC
#define GetHunkMemory GetMemory
#define GetClearedHunkMemory GetClearedMemory
#else
//allocate a memory block of the given size
void *GetHunkMemory( unsigned long size );
//allocate a memory block of the given size and clear it
void *GetClearedHunkMemory( unsigned long size );
#endif
#endif
//free the given memory block
void FreeMemory( void *ptr );
//prints the total used memory size
void PrintUsedMemorySize( void );
//print all memory blocks with label
void PrintMemoryLabels( void );
//returns the size of the memory block in bytes
int MemoryByteSize( void *ptr );
//free all allocated memory
void DumpMemory( void );

3229
src/botlib/l_precomp.c Normal file

File diff suppressed because it is too large Load Diff

182
src/botlib/l_precomp.h Normal file
View File

@ -0,0 +1,182 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_precomp.h
*
* desc: pre compiler
*
*
*****************************************************************************/
#ifndef _MAX_PATH
#define MAX_PATH MAX_QPATH
#endif
#ifndef PATH_SEPERATORSTR
#if defined( WIN32 ) | defined( _WIN32 ) | defined( __NT__ ) | defined( __WINDOWS__ ) | defined( __WINDOWS_386__ )
#define PATHSEPERATOR_STR "\\"
#else
#define PATHSEPERATOR_STR "/"
#endif
#endif
#ifndef PATH_SEPERATORCHAR
#if defined( WIN32 ) | defined( _WIN32 ) | defined( __NT__ ) | defined( __WINDOWS__ ) | defined( __WINDOWS_386__ )
#define PATHSEPERATOR_CHAR '\\'
#else
#define PATHSEPERATOR_CHAR '/'
#endif
#endif
#define DEFINE_FIXED 0x0001
#define BUILTIN_LINE 1
#define BUILTIN_FILE 2
#define BUILTIN_DATE 3
#define BUILTIN_TIME 4
#define BUILTIN_STDC 5
#define INDENT_IF 0x0001
#define INDENT_ELSE 0x0002
#define INDENT_ELIF 0x0004
#define INDENT_IFDEF 0x0008
#define INDENT_IFNDEF 0x0010
//macro definitions
typedef struct define_s
{
char *name; //define name
int flags; //define flags
int builtin; // > 0 if builtin define
int numparms; //number of define parameters
token_t *parms; //define parameters
token_t *tokens; //macro tokens (possibly containing parm tokens)
struct define_s *next; //next defined macro in a list
struct define_s *hashnext; //next define in the hash chain
} define_t;
//indents
//used for conditional compilation directives:
//#if, #else, #elif, #ifdef, #ifndef
typedef struct indent_s
{
int type; //indent type
int skip; //true if skipping current indent
script_t *script; //script the indent was in
struct indent_s *next; //next indent on the indent stack
} indent_t;
//source file
typedef struct source_s
{
char filename[_MAX_PATH]; //file name of the script
char includepath[_MAX_PATH]; //path to include files
punctuation_t *punctuations; //punctuations to use
script_t *scriptstack; //stack with scripts of the source
token_t *tokens; //tokens to read first
define_t *defines; //list with macro definitions
define_t **definehash; //hash chain with defines
indent_t *indentstack; //stack with indents
int skip; // > 0 if skipping conditional code
token_t token; //last read token
} source_t;
//read a token from the source
int PC_ReadToken( source_t *source, token_t *token );
//expect a certain token
int PC_ExpectTokenString( source_t *source, char *string );
//expect a certain token type
int PC_ExpectTokenType( source_t *source, int type, int subtype, token_t *token );
//expect a token
int PC_ExpectAnyToken( source_t *source, token_t *token );
//returns true when the token is available
int PC_CheckTokenString( source_t *source, char *string );
//returns true an reads the token when a token with the given type is available
int PC_CheckTokenType( source_t *source, int type, int subtype, token_t *token );
//skip tokens until the given token string is read
int PC_SkipUntilString( source_t *source, char *string );
//unread the last token read from the script
void PC_UnreadLastToken( source_t *source );
//unread the given token
void PC_UnreadToken( source_t *source, token_t *token );
//read a token only if on the same line, lines are concatenated with a slash
int PC_ReadLine( source_t *source, token_t *token );
//returns true if there was a white space in front of the token
int PC_WhiteSpaceBeforeToken( token_t *token );
//add a define to the source
int PC_AddDefine( source_t *source, char *string );
//add a globals define that will be added to all opened sources
int PC_AddGlobalDefine( char *string );
//remove the given global define
int PC_RemoveGlobalDefine( char *name );
//remove all globals defines
void PC_RemoveAllGlobalDefines( void );
//add builtin defines
void PC_AddBuiltinDefines( source_t *source );
//set the source include path
void PC_SetIncludePath( source_t *source, char *path );
//set the punction set
void PC_SetPunctuations( source_t *source, punctuation_t *p );
//set the base folder to load files from
void PC_SetBaseFolder( char *path );
//load a source file
source_t *LoadSourceFile( const char *filename );
//load a source from memory
source_t *LoadSourceMemory( char *ptr, int length, char *name );
//free the given source
void FreeSource( source_t *source );
//print a source error
void QDECL SourceError( source_t *source, char *str, ... );
//print a source warning
void QDECL SourceWarning( source_t *source, char *str, ... );
#ifdef BSPC
// some of BSPC source does include game/q_shared.h and some does not
// we define pc_token_s pc_token_t if needed (yes, it's ugly)
#ifndef __Q_SHARED_H
#define MAX_TOKENLENGTH 1024
typedef struct pc_token_s
{
int type;
int subtype;
int intvalue;
float floatvalue;
char string[MAX_TOKENLENGTH];
} pc_token_t;
#endif //!_Q_SHARED_H
#endif //BSPC
//
int PC_LoadSourceHandle( const char *filename );
int PC_FreeSourceHandle( int handle );
int PC_ReadTokenHandle( int handle, struct pc_token_s *pc_token );
int PC_SourceFileAndLine( int handle, char *filename, int *line );
void PC_CheckOpenSourceHandles( void );

1452
src/botlib/l_script.c Normal file

File diff suppressed because it is too large Load Diff

268
src/botlib/l_script.h Normal file
View File

@ -0,0 +1,268 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_script.h
*
* desc: lexicographical parser
*
*
*****************************************************************************/
// Ridah, can't get it to compile without this
#ifndef QDECL
// for windows fastcall option
#define QDECL
//======================= WIN32 DEFINES =================================
#ifdef WIN32
#undef QDECL
#define QDECL __cdecl
#endif
#endif
// done.
//undef if binary numbers of the form 0b... or 0B... are not allowed
#define BINARYNUMBERS
//undef if not using the token.intvalue and token.floatvalue
#define NUMBERVALUE
//use dollar sign also as punctuation
#define DOLLAR
//maximum token length
#define MAX_TOKEN 1024
//maximum path length
#ifndef _MAX_PATH
// TTimo: used to be MAX_QPATH, which is the game filesystem max len, and not the OS max len
#define _MAX_PATH 1024
#endif
//script flags
#define SCFL_NOERRORS 0x0001
#define SCFL_NOWARNINGS 0x0002
#define SCFL_NOSTRINGWHITESPACES 0x0004
#define SCFL_NOSTRINGESCAPECHARS 0x0008
#define SCFL_PRIMITIVE 0x0010
#define SCFL_NOBINARYNUMBERS 0x0020
#define SCFL_NONUMBERVALUES 0x0040
//token types
#define TT_STRING 1 // string
#define TT_LITERAL 2 // literal
#define TT_NUMBER 3 // number
#define TT_NAME 4 // name
#define TT_PUNCTUATION 5 // punctuation
//string sub type
//---------------
// the length of the string
//literal sub type
//----------------
// the ASCII code of the literal
//number sub type
//---------------
#define TT_DECIMAL 0x0008 // decimal number
#define TT_HEX 0x0100 // hexadecimal number
#define TT_OCTAL 0x0200 // octal number
#ifdef BINARYNUMBERS
#define TT_BINARY 0x0400 // binary number
#endif //BINARYNUMBERS
#define TT_FLOAT 0x0800 // floating point number
#define TT_INTEGER 0x1000 // integer number
#define TT_LONG 0x2000 // long number
#define TT_UNSIGNED 0x4000 // unsigned number
//punctuation sub type
//--------------------
#define P_RSHIFT_ASSIGN 1
#define P_LSHIFT_ASSIGN 2
#define P_PARMS 3
#define P_PRECOMPMERGE 4
#define P_LOGIC_AND 5
#define P_LOGIC_OR 6
#define P_LOGIC_GEQ 7
#define P_LOGIC_LEQ 8
#define P_LOGIC_EQ 9
#define P_LOGIC_UNEQ 10
#define P_MUL_ASSIGN 11
#define P_DIV_ASSIGN 12
#define P_MOD_ASSIGN 13
#define P_ADD_ASSIGN 14
#define P_SUB_ASSIGN 15
#define P_INC 16
#define P_DEC 17
#define P_BIN_AND_ASSIGN 18
#define P_BIN_OR_ASSIGN 19
#define P_BIN_XOR_ASSIGN 20
#define P_RSHIFT 21
#define P_LSHIFT 22
#define P_POINTERREF 23
#define P_CPP1 24
#define P_CPP2 25
#define P_MUL 26
#define P_DIV 27
#define P_MOD 28
#define P_ADD 29
#define P_SUB 30
#define P_ASSIGN 31
#define P_BIN_AND 32
#define P_BIN_OR 33
#define P_BIN_XOR 34
#define P_BIN_NOT 35
#define P_LOGIC_NOT 36
#define P_LOGIC_GREATER 37
#define P_LOGIC_LESS 38
#define P_REF 39
#define P_COMMA 40
#define P_SEMICOLON 41
#define P_COLON 42
#define P_QUESTIONMARK 43
#define P_PARENTHESESOPEN 44
#define P_PARENTHESESCLOSE 45
#define P_BRACEOPEN 46
#define P_BRACECLOSE 47
#define P_SQBRACKETOPEN 48
#define P_SQBRACKETCLOSE 49
#define P_BACKSLASH 50
#define P_PRECOMP 51
#define P_DOLLAR 52
//name sub type
//-------------
// the length of the name
//punctuation
typedef struct punctuation_s
{
char *p; //punctuation character(s)
int n; //punctuation indication
struct punctuation_s *next; //next punctuation
} punctuation_t;
//token
typedef struct token_s
{
char string[MAX_TOKEN]; //available token
int type; //last read token type
int subtype; //last read token sub type
#ifdef NUMBERVALUE
unsigned long int intvalue; //integer value
long double floatvalue; //floating point value
#endif //NUMBERVALUE
char *whitespace_p; //start of white space before token
char *endwhitespace_p; //start of white space before token
int line; //line the token was on
int linescrossed; //lines crossed in white space
struct token_s *next; //next token in chain
} token_t;
//script file
typedef struct script_s
{
char filename[_MAX_PATH]; //file name of the script
char *buffer; //buffer containing the script
char *script_p; //current pointer in the script
char *end_p; //pointer to the end of the script
char *lastscript_p; //script pointer before reading token
char *whitespace_p; //begin of the white space
char *endwhitespace_p; //end of the white space
int length; //length of the script in bytes
int line; //current line in script
int lastline; //line before reading token
int tokenavailable; //set by UnreadLastToken
int flags; //several script flags
punctuation_t *punctuations; //the punctuations used in the script
punctuation_t **punctuationtable;
token_t token; //available token
struct script_s *next; //next script in a chain
} script_t;
//read a token from the script
int PS_ReadToken( script_t *script, token_t *token );
//expect a certain token
int PS_ExpectTokenString( script_t *script, char *string );
//expect a certain token type
int PS_ExpectTokenType( script_t *script, int type, int subtype, token_t *token );
//expect a token
int PS_ExpectAnyToken( script_t *script, token_t *token );
//returns true when the token is available
int PS_CheckTokenString( script_t *script, char *string );
//returns true an reads the token when a token with the given type is available
int PS_CheckTokenType( script_t *script, int type, int subtype, token_t *token );
//skip tokens until the given token string is read
int PS_SkipUntilString( script_t *script, char *string );
//unread the last token read from the script
void PS_UnreadLastToken( script_t *script );
//unread the given token
void PS_UnreadToken( script_t *script, token_t *token );
//returns the next character of the read white space, returns NULL if none
char PS_NextWhiteSpaceChar( script_t *script );
//remove any leading and trailing double quotes from the token
void StripDoubleQuotes( char *string );
//remove any leading and trailing single quotes from the token
void StripSingleQuotes( char *string );
//read a possible signed integer
signed long int ReadSignedInt( script_t *script );
//read a possible signed floating point number
long double ReadSignedFloat( script_t *script );
//set an array with punctuations, NULL restores default C/C++ set
void SetScriptPunctuations( script_t *script, punctuation_t *p );
//set script flags
void SetScriptFlags( script_t *script, int flags );
//get script flags
int GetScriptFlags( script_t *script );
//reset a script
void ResetScript( script_t *script );
//returns true if at the end of the script
int EndOfScript( script_t *script );
//returns a pointer to the punctuation with the given number
char *PunctuationFromNum( script_t *script, int num );
//load a script from the given file at the given offset with the given length
script_t *LoadScriptFile( const char *filename );
//load a script from the given memory with the given length
script_t *LoadScriptMemory( char *ptr, int length, char *name );
//free a script
void FreeScript( script_t *script );
//set the base folder to load files from
void PS_SetBaseFolder( char *path );
//print a script error with filename and line number
void QDECL ScriptError( script_t *script, char *str, ... );
//print a script warning with filename and line number
void QDECL ScriptWarning( script_t *script, char *str, ... );

507
src/botlib/l_struct.c Normal file
View File

@ -0,0 +1,507 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_struct.c
*
* desc: structure reading / writing
*
*
*****************************************************************************/
#ifdef BOTLIB
#include "../game/q_shared.h"
#include "../game/botlib.h" //for the include of be_interface.h
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_utils.h"
#include "be_interface.h"
#endif //BOTLIB
#ifdef BSPC
//include files for usage in the BSP Converter
#include "../bspc/qbsp.h"
#include "../bspc/l_log.h"
#include "../bspc/l_mem.h"
#include "l_precomp.h"
#include "l_struct.h"
#define qtrue true
#define qfalse false
#endif //BSPC
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
fielddef_t *FindField( fielddef_t *defs, char *name ) {
int i;
for ( i = 0; defs[i].name; i++ )
{
if ( !strcmp( defs[i].name, name ) ) {
return &defs[i];
}
} //end for
return NULL;
} //end of the function FindField
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean ReadNumber( source_t *source, fielddef_t *fd, void *p ) {
token_t token;
int negative = qfalse;
long int intval, intmin = 0, intmax = 0;
double floatval;
if ( !PC_ExpectAnyToken( source, &token ) ) {
return 0;
}
//check for minus sign
if ( token.type == TT_PUNCTUATION ) {
if ( fd->type & FT_UNSIGNED ) {
SourceError( source, "expected unsigned value, found %s", token.string );
return 0;
} //end if
//if not a minus sign
if ( strcmp( token.string, "-" ) ) {
SourceError( source, "unexpected punctuation %s", token.string );
return 0;
} //end if
negative = qtrue;
//read the number
if ( !PC_ExpectAnyToken( source, &token ) ) {
return 0;
}
} //end if
//check if it is a number
if ( token.type != TT_NUMBER ) {
SourceError( source, "expected number, found %s", token.string );
return 0;
} //end if
//check for a float value
if ( token.subtype & TT_FLOAT ) {
if ( ( fd->type & FT_TYPE ) != FT_FLOAT ) {
SourceError( source, "unexpected float" );
return 0;
} //end if
floatval = token.floatvalue;
if ( negative ) {
floatval = -floatval;
}
if ( fd->type & FT_BOUNDED ) {
if ( floatval < fd->floatmin || floatval > fd->floatmax ) {
SourceError( source, "float out of range [%f, %f]", fd->floatmin, fd->floatmax );
return 0;
} //end if
} //end if
*(float *) p = (float) floatval;
return 1;
} //end if
//
intval = token.intvalue;
if ( negative ) {
intval = -intval;
}
//check bounds
if ( ( fd->type & FT_TYPE ) == FT_CHAR ) {
if ( fd->type & FT_UNSIGNED ) {
intmin = 0; intmax = 255;
} else {intmin = -128; intmax = 127;}
} //end if
if ( ( fd->type & FT_TYPE ) == FT_INT ) {
if ( fd->type & FT_UNSIGNED ) {
intmin = 0; intmax = 65535;
} else {intmin = -32768; intmax = 32767;}
} //end else if
if ( ( fd->type & FT_TYPE ) == FT_CHAR || ( fd->type & FT_TYPE ) == FT_INT ) {
if ( fd->type & FT_BOUNDED ) {
intmin = Maximum( intmin, fd->floatmin );
intmax = Minimum( intmax, fd->floatmax );
} //end if
if ( intval < intmin || intval > intmax ) {
SourceError( source, "value %d out of range [%d, %d]", intval, intmin, intmax );
return 0;
} //end if
} //end if
else if ( ( fd->type & FT_TYPE ) == FT_FLOAT ) {
if ( fd->type & FT_BOUNDED ) {
if ( intval < fd->floatmin || intval > fd->floatmax ) {
SourceError( source, "value %d out of range [%f, %f]", intval, fd->floatmin, fd->floatmax );
return 0;
} //end if
} //end if
} //end else if
//store the value
if ( ( fd->type & FT_TYPE ) == FT_CHAR ) {
if ( fd->type & FT_UNSIGNED ) {
*(unsigned char *) p = (unsigned char) intval;
} else { *(char *) p = (char) intval;}
} //end if
else if ( ( fd->type & FT_TYPE ) == FT_INT ) {
if ( fd->type & FT_UNSIGNED ) {
*(unsigned int *) p = (unsigned int) intval;
} else { *(int *) p = (int) intval;}
} //end else
else if ( ( fd->type & FT_TYPE ) == FT_FLOAT ) {
*(float *) p = (float) intval;
} //end else
return 1;
} //end of the function ReadNumber
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean ReadChar( source_t *source, fielddef_t *fd, void *p ) {
token_t token;
if ( !PC_ExpectAnyToken( source, &token ) ) {
return 0;
}
//take literals into account
if ( token.type == TT_LITERAL ) {
StripSingleQuotes( token.string );
*(char *) p = token.string[0];
} //end if
else
{
PC_UnreadLastToken( source );
if ( !ReadNumber( source, fd, p ) ) {
return 0;
}
} //end if
return 1;
} //end of the function ReadChar
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int ReadString( source_t *source, fielddef_t *fd, void *p ) {
token_t token;
if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) {
return 0;
}
//remove the double quotes
StripDoubleQuotes( token.string );
//copy the string
strncpy( (char *) p, token.string, MAX_STRINGFIELD );
//make sure the string is closed with a zero
( (char *)p )[MAX_STRINGFIELD - 1] = '\0';
//
return 1;
} //end of the function ReadString
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int ReadStructure( source_t *source, structdef_t *def, char *structure ) {
token_t token;
fielddef_t *fd;
void *p;
int num;
if ( !PC_ExpectTokenString( source, "{" ) ) {
return 0;
}
while ( 1 )
{
if ( !PC_ExpectAnyToken( source, &token ) ) {
return qfalse;
}
//if end of structure
if ( !strcmp( token.string, "}" ) ) {
break;
}
//find the field with the name
fd = FindField( def->fields, token.string );
if ( !fd ) {
SourceError( source, "unknown structure field %s", token.string );
return qfalse;
} //end if
if ( fd->type & FT_ARRAY ) {
num = fd->maxarray;
if ( !PC_ExpectTokenString( source, "{" ) ) {
return qfalse;
}
} //end if
else
{
num = 1;
} //end else
p = ( void * )( structure + fd->offset );
while ( num-- > 0 )
{
if ( fd->type & FT_ARRAY ) {
if ( PC_CheckTokenString( source, "}" ) ) {
break;
}
} //end if
switch ( fd->type & FT_TYPE )
{
case FT_CHAR:
{
if ( !ReadChar( source, fd, p ) ) {
return qfalse;
}
p = (char *) p + sizeof( char );
break;
} //end case
case FT_INT:
{
if ( !ReadNumber( source, fd, p ) ) {
return qfalse;
}
p = (char *) p + sizeof( int );
break;
} //end case
case FT_FLOAT:
{
if ( !ReadNumber( source, fd, p ) ) {
return qfalse;
}
p = (char *) p + sizeof( float );
break;
} //end case
case FT_STRING:
{
if ( !ReadString( source, fd, p ) ) {
return qfalse;
}
p = (char *) p + MAX_STRINGFIELD;
break;
} //end case
case FT_STRUCT:
{
if ( !fd->substruct ) {
SourceError( source, "BUG: no sub structure defined" );
return qfalse;
} //end if
ReadStructure( source, fd->substruct, (char *) p );
p = (char *) p + fd->substruct->size;
break;
} //end case
} //end switch
if ( fd->type & FT_ARRAY ) {
if ( !PC_ExpectAnyToken( source, &token ) ) {
return qfalse;
}
if ( !strcmp( token.string, "}" ) ) {
break;
}
if ( strcmp( token.string, "," ) ) {
SourceError( source, "expected a comma, found %s", token.string );
return qfalse;
} //end if
} //end if
} //end while
} //end while
return qtrue;
} //end of the function ReadStructure
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int WriteIndent( FILE *fp, int indent ) {
while ( indent-- > 0 )
{
if ( fprintf( fp, "\t" ) < 0 ) {
return qfalse;
}
} //end while
return qtrue;
} //end of the function WriteIndent
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int WriteFloat( FILE *fp, float value ) {
char buf[128];
int l;
sprintf( buf, "%f", value );
l = strlen( buf );
//strip any trailing zeros
while ( l-- > 1 )
{
if ( buf[l] != '0' && buf[l] != '.' ) {
break;
}
if ( buf[l] == '.' ) {
buf[l] = 0;
break;
} //end if
buf[l] = 0;
} //end while
//write the float to file
if ( fprintf( fp, "%s", buf ) < 0 ) {
return 0;
}
return 1;
} //end of the function WriteFloat
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int WriteStructWithIndent( FILE *fp, structdef_t *def, char *structure, int indent ) {
int i, num;
void *p;
fielddef_t *fd;
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "{\r\n" ) < 0 ) {
return qfalse;
}
indent++;
for ( i = 0; def->fields[i].name; i++ )
{
fd = &def->fields[i];
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "%s\t", fd->name ) < 0 ) {
return qfalse;
}
p = ( void * )( structure + fd->offset );
if ( fd->type & FT_ARRAY ) {
num = fd->maxarray;
if ( fprintf( fp, "{" ) < 0 ) {
return qfalse;
}
} //end if
else
{
num = 1;
} //end else
while ( num-- > 0 )
{
switch ( fd->type & FT_TYPE )
{
case FT_CHAR:
{
if ( fprintf( fp, "%d", *(char *) p ) < 0 ) {
return qfalse;
}
p = (char *) p + sizeof( char );
break;
} //end case
case FT_INT:
{
if ( fprintf( fp, "%d", *(int *) p ) < 0 ) {
return qfalse;
}
p = (char *) p + sizeof( int );
break;
} //end case
case FT_FLOAT:
{
if ( !WriteFloat( fp, *(float *)p ) ) {
return qfalse;
}
p = (char *) p + sizeof( float );
break;
} //end case
case FT_STRING:
{
if ( fprintf( fp, "\"%s\"", (char *) p ) < 0 ) {
return qfalse;
}
p = (char *) p + MAX_STRINGFIELD;
break;
} //end case
case FT_STRUCT:
{
if ( !WriteStructWithIndent( fp, fd->substruct, structure, indent ) ) {
return qfalse;
}
p = (char *) p + fd->substruct->size;
break;
} //end case
} //end switch
if ( fd->type & FT_ARRAY ) {
if ( num > 0 ) {
if ( fprintf( fp, "," ) < 0 ) {
return qfalse;
}
} //end if
else
{
if ( fprintf( fp, "}" ) < 0 ) {
return qfalse;
}
} //end else
} //end if
} //end while
if ( fprintf( fp, "\r\n" ) < 0 ) {
return qfalse;
}
} //end for
indent--;
if ( !WriteIndent( fp, indent ) ) {
return qfalse;
}
if ( fprintf( fp, "}\r\n" ) < 0 ) {
return qfalse;
}
return qtrue;
} //end of the function WriteStructWithIndent
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int WriteStructure( FILE *fp, structdef_t *def, char *structure ) {
return WriteStructWithIndent( fp, def, structure, 0 );
} //end of the function WriteStructure

81
src/botlib/l_struct.h Normal file
View File

@ -0,0 +1,81 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_struct.h
*
* desc: structure reading/writing
*
*
*****************************************************************************/
#define MAX_STRINGFIELD 80
//field types
#define FT_CHAR 1 // char
#define FT_INT 2 // int
#define FT_FLOAT 3 // float
#define FT_STRING 4 // char [MAX_STRINGFIELD]
#define FT_STRUCT 6 // struct (sub structure)
//type only mask
#define FT_TYPE 0x00FF // only type, clear subtype
//sub types
#define FT_ARRAY 0x0100 // array of type
#define FT_BOUNDED 0x0200 // bounded value
#define FT_UNSIGNED 0x0400
//structure field definition
typedef struct fielddef_s
{
char *name; //name of the field
int offset; //offset in the structure
int type; //type of the field
//type specific fields
int maxarray; //maximum array size
float floatmin, floatmax; //float min and max
struct structdef_s *substruct; //sub structure
} fielddef_t;
//structure definition
typedef struct structdef_s
{
int size;
fielddef_t *fields;
} structdef_t;
//read a structure from a script
int ReadStructure( source_t *source, structdef_t *def, char *structure );
//write a structure to a file
int WriteStructure( FILE *fp, structdef_t *def, char *structure );
//writes indents
int WriteIndent( FILE *fp, int indent );
//writes a float without traling zeros
int WriteFloat( FILE *fp, float value );

41
src/botlib/l_utils.h Normal file
View File

@ -0,0 +1,41 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*****************************************************************************
* name: l_util.h
*
* desc: utils
*
*
*****************************************************************************/
#define Vector2Angles( v,a ) vectoangles( v,a )
#define MAX_PATH MAX_QPATH
#define Maximum( x,y ) ( x > y ? x : y )
#define Minimum( x,y ) ( x < y ? x : y )

91
src/bspc/_files.c Normal file
View File

@ -0,0 +1,91 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: _files.c
// Function:
// Programmer: Mr Elusive
// Last update: 1999-12-02
// Tab Size: 4
//===========================================================================
/*
aas_areamerging.c //AAS area merging
aas_cfg.c //AAS configuration for different games
aas_create.c //AAS creating
aas_edgemelting.c //AAS edge melting
aas_facemerging.c //AAS face merging
aas_file.c //AAS file writing
aas_gsubdiv.c //AAS gravitational and ladder subdivision
aas_map.c //AAS map brush creation
aas_prunenodes.c //AAS node pruning
aas_store.c //AAS file storing
map.c //map file loading and writing
map_hl.c //Half-Life map loading
map_q1.c //Quake1 map loading
map_q2.c //Quake2 map loading
map_q3.c //Quake3 map loading
map_sin.c //Sin map loading
tree.c //BSP tree management + node pruning (*)
brushbsp.c //brush bsp creation (*)
portals.c //BSP portal creation and leaf filling (*)
csg.c //Constructive Solid Geometry brush chopping (*)
leakfile.c //leak file writing (*)
textures.c //Quake2 BSP textures (*)
l_bsp_ent.c //BSP entity parsing
l_bsp_hl.c //Half-Life BSP loading and writing
l_bsp_q1.c //Quake1 BSP loading and writing
l_bsp_q2.c //Quake2 BSP loading and writing
l_bsp_q3.c //Quake2 BSP loading and writing
l_bsp_sin.c //Sin BSP loading and writing
l_cmd.c //cmd library
l_log.c //log file library
l_math.c //math library
l_mem.c //memory management library
l_poly.c //polygon (winding) library
l_script.c //script file parsing library
l_threads.c //multi-threading library
l_utils.c //utility library
l_qfiles.c //loading of quake files
gldraw.c //GL drawing (*)
glfile.c //GL file writing (*)
nodraw.c //no draw module (*)
bspc.c //BSPC Win32 console version
winbspc.c //WinBSPC Win32 GUI version
win32_terminal.c //Win32 terminal output
win32_qfiles.c //Win32 game file management (also .pak .sin)
win32_font.c //Win32 fonts
win32_folder.c //Win32 folder dialogs
*/

424
src/bspc/aas_areamerging.c Normal file
View File

@ -0,0 +1,424 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_areamerging.c
// Function: Merging of Areas
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
#include "aas_store.h"
#define CONVEX_EPSILON 0.3
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_RefreshMergedTree_r( tmp_node_t *tmpnode ) {
tmp_area_t *tmparea;
//if this is a solid leaf
if ( !tmpnode ) {
return NULL;
}
//if this is an area leaf
if ( tmpnode->tmparea ) {
tmparea = tmpnode->tmparea;
while ( tmparea->mergedarea ) tmparea = tmparea->mergedarea;
tmpnode->tmparea = tmparea;
return tmpnode;
} //end if
//do the children recursively
tmpnode->children[0] = AAS_RefreshMergedTree_r( tmpnode->children[0] );
tmpnode->children[1] = AAS_RefreshMergedTree_r( tmpnode->children[1] );
return tmpnode;
} //end of the function AAS_RefreshMergedTree_r
//===========================================================================
// returns true if the two given faces would create a non-convex area at
// the given sides, otherwise false is returned
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int NonConvex( tmp_face_t *face1, tmp_face_t *face2, int side1, int side2 ) {
int i;
winding_t *w1, *w2;
plane_t *plane1, *plane2;
w1 = face1->winding;
w2 = face2->winding;
plane1 = &mapplanes[face1->planenum ^ side1];
plane2 = &mapplanes[face2->planenum ^ side2];
//check if one of the points of face1 is at the back of the plane of face2
for ( i = 0; i < w1->numpoints; i++ )
{
if ( DotProduct( plane2->normal, w1->p[i] ) - plane2->dist < -CONVEX_EPSILON ) {
return true;
}
} //end for
//check if one of the points of face2 is at the back of the plane of face1
for ( i = 0; i < w2->numpoints; i++ )
{
if ( DotProduct( plane1->normal, w2->p[i] ) - plane1->dist < -CONVEX_EPSILON ) {
return true;
}
} //end for
return false;
} //end of the function NonConvex
//===========================================================================
// try to merge the areas at both sides of the given face
//
// Parameter: seperatingface : face that seperates two areas
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TryMergeFaceAreas( tmp_face_t *seperatingface ) {
int side1, side2, area1faceflags, area2faceflags;
tmp_area_t *tmparea1, *tmparea2, *newarea;
tmp_face_t *face1, *face2, *nextface1, *nextface2;
tmparea1 = seperatingface->frontarea;
tmparea2 = seperatingface->backarea;
//areas must have the same presence type
if ( tmparea1->presencetype != tmparea2->presencetype ) {
return false;
}
//areas must have the same area contents
if ( tmparea1->contents != tmparea2->contents ) {
return false;
}
//areas must have the same bsp model inside (or both none)
if ( tmparea1->modelnum != tmparea2->modelnum ) {
return false;
}
area1faceflags = 0;
area2faceflags = 0;
for ( face1 = tmparea1->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = ( face1->frontarea != tmparea1 );
//debug: check if the area belongs to the area
if ( face1->frontarea != tmparea1 &&
face1->backarea != tmparea1 ) {
Error( "face does not belong to area1" );
}
//just continue if the face is seperating the two areas
//NOTE: a result of this is that ground and gap areas can
// be merged if the seperating face is the gap
if ( ( face1->frontarea == tmparea1 &&
face1->backarea == tmparea2 ) ||
( face1->frontarea == tmparea2 &&
face1->backarea == tmparea1 ) ) {
continue;
}
//get area1 face flags
area1faceflags |= face1->faceflags;
if ( AAS_GapFace( face1, side1 ) ) {
area1faceflags |= FACE_GAP;
}
//
for ( face2 = tmparea2->tmpfaces; face2; face2 = face2->next[side2] )
{
side2 = ( face2->frontarea != tmparea2 );
//debug: check if the area belongs to the area
if ( face2->frontarea != tmparea2 &&
face2->backarea != tmparea2 ) {
Error( "face does not belong to area2" );
}
//just continue if the face is seperating the two areas
//NOTE: a result of this is that ground and gap areas can
// be merged if the seperating face is the gap
if ( ( face2->frontarea == tmparea1 &&
face2->backarea == tmparea2 ) ||
( face2->frontarea == tmparea2 &&
face2->backarea == tmparea1 ) ) {
continue;
}
//get area2 face flags
area2faceflags |= face2->faceflags;
if ( AAS_GapFace( face2, side2 ) ) {
area2faceflags |= FACE_GAP;
}
//if the two faces would create a non-convex area
if ( NonConvex( face1, face2, side1, side2 ) ) {
return false;
}
} //end for
} //end for
//if one area has gap faces (that aren't seperating the two areas)
//and the other has ground faces (that aren't seperating the two areas),
//the areas can't be merged
if ( ( ( area1faceflags & FACE_GROUND ) && ( area2faceflags & FACE_GAP ) ) ||
( ( area2faceflags & FACE_GROUND ) && ( area1faceflags & FACE_GAP ) ) ) {
// Log_Print(" can't merge: ground/gap\n");
return false;
} //end if
// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum, numfaces);
// return false;
//
//AAS_CheckArea(tmparea1);
//AAS_CheckArea(tmparea2);
//create the new area
newarea = AAS_AllocTmpArea();
newarea->presencetype = tmparea1->presencetype;
newarea->contents = tmparea1->contents;
newarea->modelnum = tmparea1->modelnum;
newarea->tmpfaces = NULL;
//add all the faces (except the seperating ones) from the first area
//to the new area
for ( face1 = tmparea1->tmpfaces; face1; face1 = nextface1 )
{
side1 = ( face1->frontarea != tmparea1 );
nextface1 = face1->next[side1];
//don't add seperating faces
if ( ( face1->frontarea == tmparea1 &&
face1->backarea == tmparea2 ) ||
( face1->frontarea == tmparea2 &&
face1->backarea == tmparea1 ) ) {
continue;
} //end if
//
AAS_RemoveFaceFromArea( face1, tmparea1 );
AAS_AddFaceSideToArea( face1, side1, newarea );
} //end for
//add all the faces (except the seperating ones) from the second area
//to the new area
for ( face2 = tmparea2->tmpfaces; face2; face2 = nextface2 )
{
side2 = ( face2->frontarea != tmparea2 );
nextface2 = face2->next[side2];
//don't add seperating faces
if ( ( face2->frontarea == tmparea1 &&
face2->backarea == tmparea2 ) ||
( face2->frontarea == tmparea2 &&
face2->backarea == tmparea1 ) ) {
continue;
} //end if
//
AAS_RemoveFaceFromArea( face2, tmparea2 );
AAS_AddFaceSideToArea( face2, side2, newarea );
} //end for
//free all shared faces
for ( face1 = tmparea1->tmpfaces; face1; face1 = nextface1 )
{
side1 = ( face1->frontarea != tmparea1 );
nextface1 = face1->next[side1];
//
AAS_RemoveFaceFromArea( face1, face1->frontarea );
AAS_RemoveFaceFromArea( face1, face1->backarea );
AAS_FreeTmpFace( face1 );
} //end for
//
tmparea1->mergedarea = newarea;
tmparea1->invalid = true;
tmparea2->mergedarea = newarea;
tmparea2->invalid = true;
//
AAS_CheckArea( newarea );
AAS_FlipAreaFaces( newarea );
// Log_Print("merged area %d & %d to %d with %d faces\n", tmparea1->areanum, tmparea2->areanum, newarea->areanum);
return true;
} //end of the function AAS_TryMergeFaceAreas
//===========================================================================
// try to merge areas
// merged areas are added to the end of the convex area list so merging
// will be tried for those areas as well
//
// Parameter: -
// Returns: -
// Changes Globals: tmpaasworld
//===========================================================================
/*
void AAS_MergeAreas(void)
{
int side, nummerges;
tmp_area_t *tmparea, *othertmparea;
tmp_face_t *face;
nummerges = 0;
Log_Write("AAS_MergeAreas\r\n");
qprintf("%6d areas merged", 1);
//first merge grounded areas only
//NOTE: this is useless because the area settings aren't available yet
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
// Log_Print("checking area %d\n", i);
//if the area is invalid
if (tmparea->invalid)
{
// Log_Print(" area invalid\n");
continue;
} //end if
//
// if (!(tmparea->settings->areaflags & AREA_GROUNDED)) continue;
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
//if the face has both a front and back area
if (face->frontarea && face->backarea)
{
//
if (face->frontarea == tmparea) othertmparea = face->backarea;
else othertmparea = face->frontarea;
// if (!(othertmparea->settings->areaflags & AREA_GROUNDED)) continue;
// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
if (AAS_TryMergeFaceAreas(face))
{
qprintf("\r%6d", ++nummerges);
break;
} //end if
} //end if
} //end for
} //end for
//merge all areas
for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
{
// Log_Print("checking area %d\n", i);
//if the area is invalid
if (tmparea->invalid)
{
// Log_Print(" area invalid\n");
continue;
} //end if
//
for (face = tmparea->tmpfaces; face; face = face->next[side])
{
side = (face->frontarea != tmparea);
//if the face has both a front and back area
if (face->frontarea && face->backarea)
{
// Log_Print(" checking area %d with %d\n", face->frontarea, face->backarea);
if (AAS_TryMergeFaceAreas(face))
{
qprintf("\r%6d", ++nummerges);
break;
} //end if
} //end if
} //end for
} //end for
Log_Print("\r%6d areas merged\n", nummerges);
//refresh the merged tree
AAS_RefreshMergedTree_r(tmpaasworld.nodes);
} //end of the function AAS_MergeAreas*/
int AAS_GroundArea( tmp_area_t *tmparea ) {
tmp_face_t *face;
int side;
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
{
side = ( face->frontarea != tmparea );
if ( face->faceflags & FACE_GROUND ) {
return true;
}
} //end for
return false;
} //end of the function AAS_GroundArea
void AAS_MergeAreas( void ) {
int side, nummerges, merges, groundfirst;
tmp_area_t *tmparea, *othertmparea;
tmp_face_t *face;
nummerges = 0;
Log_Write( "AAS_MergeAreas\r\n" );
qprintf( "%6d areas merged", 1 );
//
groundfirst = true;
//for (i = 0; i < 4 || merges; i++)
while ( 1 )
{
//if (i < 2) groundfirst = true;
//else groundfirst = false;
//
merges = 0;
//first merge grounded areas only
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
{
//if the area is invalid
if ( tmparea->invalid ) {
continue;
} //end if
//
if ( groundfirst ) {
if ( !AAS_GroundArea( tmparea ) ) {
continue;
}
} //end if
//
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
{
side = ( face->frontarea != tmparea );
//if the face has both a front and back area
if ( face->frontarea && face->backarea ) {
//
if ( face->frontarea == tmparea ) {
othertmparea = face->backarea;
} else { othertmparea = face->frontarea;}
//
if ( groundfirst ) {
if ( !AAS_GroundArea( othertmparea ) ) {
continue;
}
} //end if
if ( AAS_TryMergeFaceAreas( face ) ) {
qprintf( "\r%6d", ++nummerges );
merges++;
break;
} //end if
} //end if
} //end for
} //end for
if ( !merges ) {
if ( groundfirst ) {
groundfirst = false;
} else { break;}
} //end if
} //end for
qprintf( "\n" );
Log_Write( "%6d areas merged\r\n", nummerges );
//refresh the merged tree
AAS_RefreshMergedTree_r( tmpaasworld.nodes );
} //end of the function AAS_MergeAreas

View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_areamerging.h
// Function: Merging of Areas
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
void AAS_MergeAreas( void );

317
src/bspc/aas_cfg.c Normal file
View File

@ -0,0 +1,317 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: cfg.c
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "float.h"
#include "../botlib/aasfile.h"
#include "aas_store.h"
#include "aas_cfg.h"
#include "../botlib/l_precomp.h"
#include "../botlib/l_struct.h"
#include "../botlib/l_libvar.h"
// TTimo: this is a f*g mess
// I got rid of all occurences except for bspc it seems
// all code *should* be using Q_stricmp
#ifdef BSPC
#define stricmp strcasecmp
#endif
///////////////////////////////////
extern void LibVarSet( char *var_name, char *value );
///////////////////////////////////
//structure field offsets
#define BBOX_OFS( x ) (int)&( ( (aas_bbox_t *)0 )->x )
#define CFG_OFS( x ) (int)&( ( (cfg_t *)0 )->x )
//bounding box definition
fielddef_t bbox_fields[] =
{
{"presencetype", BBOX_OFS( presencetype ), FT_INT},
{"flags", BBOX_OFS( flags ), FT_INT},
{"mins", BBOX_OFS( mins ), FT_FLOAT | FT_ARRAY, 3},
{"maxs", BBOX_OFS( maxs ), FT_FLOAT | FT_ARRAY, 3},
{NULL, 0, 0, 0}
};
fielddef_t cfg_fields[] =
{
{"phys_gravitydirection", CFG_OFS( phys_gravitydirection ), FT_FLOAT | FT_ARRAY, 3},
{"phys_friction", CFG_OFS( phys_friction ), FT_FLOAT},
{"phys_stopspeed", CFG_OFS( phys_stopspeed ), FT_FLOAT},
{"phys_gravity", CFG_OFS( phys_gravity ), FT_FLOAT},
{"phys_waterfriction", CFG_OFS( phys_waterfriction ), FT_FLOAT},
{"phys_watergravity", CFG_OFS( phys_watergravity ), FT_FLOAT},
{"phys_maxvelocity", CFG_OFS( phys_maxvelocity ), FT_FLOAT},
{"phys_maxwalkvelocity", CFG_OFS( phys_maxwalkvelocity ), FT_FLOAT},
{"phys_maxcrouchvelocity", CFG_OFS( phys_maxcrouchvelocity ), FT_FLOAT},
{"phys_maxswimvelocity", CFG_OFS( phys_maxswimvelocity ), FT_FLOAT},
{"phys_walkaccelerate", CFG_OFS( phys_walkaccelerate ), FT_FLOAT},
{"phys_airaccelerate", CFG_OFS( phys_airaccelerate ), FT_FLOAT},
{"phys_swimaccelerate", CFG_OFS( phys_swimaccelerate ), FT_FLOAT},
{"phys_maxstep", CFG_OFS( phys_maxstep ), FT_FLOAT},
{"phys_maxsteepness", CFG_OFS( phys_maxsteepness ), FT_FLOAT},
{"phys_maxwaterjump", CFG_OFS( phys_maxwaterjump ), FT_FLOAT},
{"phys_maxbarrier", CFG_OFS( phys_maxbarrier ), FT_FLOAT},
{"phys_jumpvel", CFG_OFS( phys_jumpvel ), FT_FLOAT},
{"phys_falldelta5", CFG_OFS( phys_falldelta5 ), FT_FLOAT},
{"phys_falldelta10", CFG_OFS( phys_falldelta10 ), FT_FLOAT},
{"rs_waterjump", CFG_OFS( rs_waterjump ), FT_FLOAT},
{"rs_teleport", CFG_OFS( rs_teleport ), FT_FLOAT},
{"rs_barrierjump", CFG_OFS( rs_barrierjump ), FT_FLOAT},
{"rs_startcrouch", CFG_OFS( rs_startcrouch ), FT_FLOAT},
{"rs_startgrapple", CFG_OFS( rs_startgrapple ), FT_FLOAT},
{"rs_startwalkoffledge", CFG_OFS( rs_startwalkoffledge ), FT_FLOAT},
{"rs_startjump", CFG_OFS( rs_startjump ), FT_FLOAT},
{"rs_rocketjump", CFG_OFS( rs_rocketjump ), FT_FLOAT},
{"rs_bfgjump", CFG_OFS( rs_bfgjump ), FT_FLOAT},
{"rs_jumppad", CFG_OFS( rs_jumppad ), FT_FLOAT},
{"rs_aircontrolledjumppad", CFG_OFS( rs_aircontrolledjumppad ), FT_FLOAT},
{"rs_funcbob", CFG_OFS( rs_funcbob ), FT_FLOAT},
{"rs_startelevator", CFG_OFS( rs_startelevator ), FT_FLOAT},
{"rs_falldamage5", CFG_OFS( rs_falldamage5 ), FT_FLOAT},
{"rs_falldamage10", CFG_OFS( rs_falldamage10 ), FT_FLOAT},
{"rs_maxjumpfallheight", CFG_OFS( rs_maxjumpfallheight ), FT_FLOAT},
{"rs_allowladders", CFG_OFS( rs_allowladders ), FT_INT},
{NULL, 0, 0, 0}
};
structdef_t bbox_struct =
{
sizeof( aas_bbox_t ), bbox_fields
};
structdef_t cfg_struct =
{
sizeof( cfg_t ), cfg_fields
};
//global cfg
cfg_t cfg;
#if 0
//===========================================================================
// the default Q3A configuration
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void DefaultCfg( void ) {
int i;
// default all float values to infinite
for ( i = 0; cfg_fields[i].name; i++ )
{
if ( ( cfg_fields[i].type & FT_TYPE ) == FT_FLOAT ) {
*( float * )( ( (char*)&cfg ) + cfg_fields[i].offset ) = FLT_MAX;
}
} //end for
//
cfg.numbboxes = 2;
//bbox 0
cfg.bboxes[0].presencetype = PRESENCE_NORMAL;
cfg.bboxes[0].flags = 0;
cfg.bboxes[0].mins[0] = -18;
cfg.bboxes[0].mins[1] = -18;
cfg.bboxes[0].mins[2] = -24;
cfg.bboxes[0].maxs[0] = 18;
cfg.bboxes[0].maxs[1] = 18;
cfg.bboxes[0].maxs[2] = 48;
//bbox 1
cfg.bboxes[1].presencetype = PRESENCE_CROUCH;
cfg.bboxes[1].flags = 1;
cfg.bboxes[1].mins[0] = -18;
cfg.bboxes[1].mins[1] = -18;
cfg.bboxes[1].mins[2] = -24;
cfg.bboxes[1].maxs[0] = 18;
cfg.bboxes[1].maxs[1] = 18;
cfg.bboxes[1].maxs[2] = 24;
//
cfg.allpresencetypes = PRESENCE_NORMAL | PRESENCE_CROUCH;
cfg.phys_gravitydirection[0] = 0;
cfg.phys_gravitydirection[1] = 0;
cfg.phys_gravitydirection[2] = -1;
cfg.phys_maxsteepness = 0.7;
// cfg.phys_maxbarrier = -999;//32; // RIDAH: this is calculated at run-time now, from the gravity and jump velocity settings
} //end of the function DefaultCfg
#else
//===========================================================================
// the default Q3A configuration
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void DefaultCfg( void ) {
int i;
// default all float values to infinite
for ( i = 0; cfg_fields[i].name; i++ )
{
if ( ( cfg_fields[i].type & FT_TYPE ) == FT_FLOAT ) {
*( float * )( ( (char*)&cfg ) + cfg_fields[i].offset ) = FLT_MAX;
}
} //end for
//
cfg.numbboxes = 2;
//bbox 0
cfg.bboxes[0].presencetype = PRESENCE_NORMAL;
cfg.bboxes[0].flags = 0;
cfg.bboxes[0].mins[0] = -15;
cfg.bboxes[0].mins[1] = -15;
cfg.bboxes[0].mins[2] = -24;
cfg.bboxes[0].maxs[0] = 15;
cfg.bboxes[0].maxs[1] = 15;
cfg.bboxes[0].maxs[2] = 32;
//bbox 1
cfg.bboxes[1].presencetype = PRESENCE_CROUCH;
cfg.bboxes[1].flags = 1;
cfg.bboxes[1].mins[0] = -15;
cfg.bboxes[1].mins[1] = -15;
cfg.bboxes[1].mins[2] = -24;
cfg.bboxes[1].maxs[0] = 15;
cfg.bboxes[1].maxs[1] = 15;
cfg.bboxes[1].maxs[2] = 16;
//
cfg.allpresencetypes = PRESENCE_NORMAL | PRESENCE_CROUCH;
cfg.phys_gravitydirection[0] = 0;
cfg.phys_gravitydirection[1] = 0;
cfg.phys_gravitydirection[2] = -1;
cfg.phys_maxsteepness = 0.7;
// cfg.phys_maxbarrier = -999;//32; // RIDAH: this is calculated at run-time now, from the gravity and jump velocity settings
} //end of the function DefaultCfg
#endif
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char * QDECL va( char *format, ... ) {
va_list argptr;
static char string[2][32000]; // in case va is called by nested functions
static int index = 0;
char *buf;
buf = string[index & 1];
index++;
va_start( argptr, format );
vsprintf( buf, format,argptr );
va_end( argptr );
return buf;
} //end of the function va
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void SetCfgLibVars( void ) {
int i;
float value;
for ( i = 0; cfg_fields[i].name; i++ )
{
if ( ( cfg_fields[i].type & FT_TYPE ) == FT_FLOAT ) {
value = *( float * )( ( (char*)&cfg ) + cfg_fields[i].offset );
if ( value != FLT_MAX ) {
LibVarSet( cfg_fields[i].name, va( "%f", value ) );
} //end if
} //end if
} //end for
} //end of the function SetCfgLibVars
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int LoadCfgFile( char *filename ) {
source_t *source;
token_t token;
int settingsdefined;
source = LoadSourceFile( filename );
if ( !source ) {
Log_Print( "couldn't open cfg file %s\n", filename );
return false;
} //end if
settingsdefined = false;
memset( &cfg, 0, sizeof( cfg_t ) );
while ( PC_ReadToken( source, &token ) )
{
if ( !stricmp( token.string, "bbox" ) ) {
if ( cfg.numbboxes >= AAS_MAX_BBOXES ) {
SourceError( source, "too many bounding box volumes defined" );
} //end if
if ( !ReadStructure( source, &bbox_struct, (char *) &cfg.bboxes[cfg.numbboxes] ) ) {
FreeSource( source );
return false;
} //end if
cfg.allpresencetypes |= cfg.bboxes[cfg.numbboxes].presencetype;
cfg.numbboxes++;
} //end if
else if ( !stricmp( token.string, "settings" ) ) {
if ( settingsdefined ) {
SourceWarning( source, "settings already defined\n" );
} //end if
settingsdefined = true;
if ( !ReadStructure( source, &cfg_struct, (char *) &cfg ) ) {
FreeSource( source );
return false;
} //end if
} //end else if
} //end while
if ( VectorLength( cfg.phys_gravitydirection ) < 0.9 || VectorLength( cfg.phys_gravitydirection ) > 1.1 ) {
SourceError( source, "invalid gravity direction specified" );
} //end if
if ( cfg.numbboxes <= 0 ) {
SourceError( source, "no bounding volumes specified" );
} //end if
FreeSource( source );
SetCfgLibVars();
Log_Print( "using cfg file %s\n", filename );
return true;
} //end of the function LoadCfgFile

89
src/bspc/aas_cfg.h Normal file
View File

@ -0,0 +1,89 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: cfg.h
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#define BBOXFL_GROUNDED 1 //bounding box only valid when on ground
#define BBOXFL_NOTGROUNDED 2 //bounding box only valid when NOT on ground
typedef struct cfg_s
{
int numbboxes; //number of bounding boxes
aas_bbox_t bboxes[AAS_MAX_BBOXES]; //all the bounding boxes
int allpresencetypes; //or of all presence types
// aas settings
vec3_t phys_gravitydirection;
float phys_friction;
float phys_stopspeed;
float phys_gravity;
float phys_waterfriction;
float phys_watergravity;
float phys_maxvelocity;
float phys_maxwalkvelocity;
float phys_maxcrouchvelocity;
float phys_maxswimvelocity;
float phys_walkaccelerate;
float phys_airaccelerate;
float phys_swimaccelerate;
float phys_maxstep;
float phys_maxsteepness;
float phys_maxwaterjump;
float phys_maxbarrier;
float phys_jumpvel;
float phys_falldelta5;
float phys_falldelta10;
float rs_waterjump;
float rs_teleport;
float rs_barrierjump;
float rs_startcrouch;
float rs_startgrapple;
float rs_startwalkoffledge;
float rs_startjump;
float rs_rocketjump;
float rs_bfgjump;
float rs_jumppad;
float rs_aircontrolledjumppad;
float rs_funcbob;
float rs_startelevator;
float rs_falldamage5;
float rs_falldamage10;
float rs_maxjumpfallheight;
qboolean rs_allowladders;
} cfg_t;
extern cfg_t cfg;
void DefaultCfg( void );
int LoadCfgFile( char *filename );

1180
src/bspc/aas_create.c Normal file

File diff suppressed because it is too large Load Diff

153
src/bspc/aas_create.h Normal file
View File

@ -0,0 +1,153 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_create.h
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#define AREA_PORTAL 1
//temporary AAS face
typedef struct tmp_face_s
{
int num; //face number
int planenum; //number of the plane the face is in
winding_t *winding; //winding of the face
struct tmp_area_s *frontarea; //area at the front of the face
struct tmp_area_s *backarea; //area at the back of the face
int faceflags; //flags of this face
int aasfacenum; //the number of the aas face used for this face
//double link list pointers for front and back area
struct tmp_face_s *prev[2], *next[2];
//links in the list with faces
struct tmp_face_s *l_prev, *l_next;
} tmp_face_t;
//temporary AAS area settings
typedef struct tmp_areasettings_s
{
//could also add all kind of statistic fields
int contents; //contents of the area
int modelnum; //bsp model inside this area
int areaflags; //area flags
int presencetype; //how a bot can be present in this area
int numreachableareas; //number of reachable areas from this one
int firstreachablearea; //first reachable area in the reachable area index
// Ridah, steepness
float groundsteepness;
} tmp_areasettings_t;
//temporary AAS area
typedef struct tmp_area_s
{
int areanum; //number of the area
struct tmp_face_s *tmpfaces; //the faces of the area
int presencetype; //presence type of the area
int contents; //area contents
int modelnum; //bsp model inside this area
int invalid; //true if the area is invalid
tmp_areasettings_t *settings; //area settings
struct tmp_area_s *mergedarea; //points to the new area after merging
//when mergedarea != 0 the area has only the
//seperating face of the merged areas
int aasareanum; //number of the aas area created for this tmp area
//links in the list with areas
struct tmp_area_s *l_prev, *l_next;
} tmp_area_t;
//temporary AAS node
typedef struct tmp_node_s
{
int planenum; //node plane number
struct tmp_area_s *tmparea; //points to an area if this node is an area
struct tmp_node_s *children[2]; //child nodes of this node
} tmp_node_t;
#define NODEBUF_SIZE 128
//node buffer
typedef struct tmp_nodebuf_s
{
int numnodes;
struct tmp_nodebuf_s *next;
tmp_node_t nodes[NODEBUF_SIZE];
} tmp_nodebuf_t;
//the whole temorary AAS
typedef struct tmp_aas_s
{
//faces
int numfaces;
int facenum;
tmp_face_t *faces;
//areas
int numareas;
int areanum;
tmp_area_t *areas;
//area settings
int numareasettings;
tmp_areasettings_t *areasettings;
//nodes
int numnodes;
tmp_node_t *nodes;
//node buffer
tmp_nodebuf_t *nodebuffer;
} tmp_aas_t;
extern tmp_aas_t tmpaasworld;
//creates a .AAS file with the given name from an already loaded map
void AAS_Create( char *aasfile );
//adds a face side to an area
void AAS_AddFaceSideToArea( tmp_face_t *tmpface, int side, tmp_area_t *tmparea );
//remvoes a face from an area
void AAS_RemoveFaceFromArea( tmp_face_t *tmpface, tmp_area_t *tmparea );
//allocate a tmp face
tmp_face_t *AAS_AllocTmpFace( void );
//free the tmp face
void AAS_FreeTmpFace( tmp_face_t *tmpface );
//allocate a tmp area
tmp_area_t *AAS_AllocTmpArea( void );
//free a tmp area
void AAS_FreeTmpArea( tmp_area_t *tmparea );
//allocate a tmp node
tmp_node_t *AAS_AllocTmpNode( void );
//free a tmp node
void AAS_FreeTmpNode( tmp_node_t *node );
//checks if an area is ok
void AAS_CheckArea( tmp_area_t *tmparea );
//flips the area faces where needed
void AAS_FlipAreaFaces( tmp_area_t *tmparea );
//returns true if the face is a gap seen from the given side
int AAS_GapFace( tmp_face_t *tmpface, int side );
//returns true if the face is a ground face
int AAS_GroundFace( tmp_face_t *tmpface );

125
src/bspc/aas_edgemelting.c Normal file
View File

@ -0,0 +1,125 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_edgemelting.c
// Function: Melting of Edges
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
//===========================================================================
// try to melt the windings of the two faces
// FIXME: this is buggy
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_MeltFaceWinding( tmp_face_t *face1, tmp_face_t *face2 ) {
int i, n;
int splits = 0;
winding_t *w2, *neww;
plane_t *plane1;
#ifdef DEBUG
if ( !face1->winding ) {
Error( "face1 %d without winding", face1->num );
}
if ( !face2->winding ) {
Error( "face2 %d without winding", face2->num );
}
#endif //DEBUG
w2 = face2->winding;
plane1 = &mapplanes[face1->planenum];
for ( i = 0; i < w2->numpoints; i++ )
{
if ( PointOnWinding( face1->winding, plane1->normal, plane1->dist, w2->p[i], &n ) ) {
neww = AddWindingPoint( face1->winding, w2->p[i], n );
FreeWinding( face1->winding );
face1->winding = neww;
splits++;
} //end if
} //end for
return splits;
} //end of the function AAS_MeltFaceWinding
//===========================================================================
// melt the windings of the area faces
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_MeltFaceWindingsOfArea( tmp_area_t *tmparea ) {
int side1, side2, num_windingsplits = 0;
tmp_face_t *face1, *face2;
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = face1->frontarea != tmparea;
for ( face2 = tmparea->tmpfaces; face2; face2 = face2->next[side2] )
{
side2 = face2->frontarea != tmparea;
if ( face1 == face2 ) {
continue;
}
num_windingsplits += AAS_MeltFaceWinding( face1, face2 );
} //end for
} //end for
return num_windingsplits;
} //end of the function AAS_MeltFaceWindingsOfArea
//===========================================================================
// melt the windings of the faces of all areas
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MeltAreaFaceWindings( void ) {
tmp_area_t *tmparea;
int num_windingsplits = 0;
Log_Write( "AAS_MeltAreaFaceWindings\r\n" );
qprintf( "%6d edges melted", num_windingsplits );
//NOTE: first convex area (zero) is a dummy
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
{
num_windingsplits += AAS_MeltFaceWindingsOfArea( tmparea );
qprintf( "\r%6d", num_windingsplits );
} //end for
qprintf( "\n" );
Log_Write( "%6d edges melted\r\n", num_windingsplits );
} //end of the function AAS_MeltAreaFaceWindings

View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_edgemelting.h
// Function: Melting of Edges
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
void AAS_MeltAreaFaceWindings( void );

312
src/bspc/aas_facemerging.c Normal file
View File

@ -0,0 +1,312 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_facemerging.c
// Function: Merging of Faces
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TryMergeFaces( tmp_face_t *face1, tmp_face_t *face2 ) {
winding_t *neww;
#ifdef DEBUG
if ( !face1->winding ) {
Error( "face1 %d without winding", face1->num );
}
if ( !face2->winding ) {
Error( "face2 %d without winding", face2->num );
}
#endif //DEBUG
//
if ( face1->faceflags != face2->faceflags ) {
return false;
}
//NOTE: if the front or back area is zero this doesn't mean there's
//a real area. It means there's solid at that side of the face
//if both faces have the same front area
if ( face1->frontarea == face2->frontarea ) {
//if both faces have the same back area
if ( face1->backarea == face2->backarea ) {
//if the faces are in the same plane
if ( face1->planenum == face2->planenum ) {
//if they have both a front and a back area (no solid on either side)
if ( face1->frontarea && face1->backarea ) {
neww = MergeWindings( face1->winding, face2->winding,
mapplanes[face1->planenum].normal );
} //end if
else
{
//this function is to be found in l_poly.c
neww = TryMergeWinding( face1->winding, face2->winding,
mapplanes[face1->planenum].normal );
} //end else
if ( neww ) {
FreeWinding( face1->winding );
face1->winding = neww;
if ( face2->frontarea ) {
AAS_RemoveFaceFromArea( face2, face2->frontarea );
}
if ( face2->backarea ) {
AAS_RemoveFaceFromArea( face2, face2->backarea );
}
AAS_FreeTmpFace( face2 );
return true;
} //end if
} //end if
else if ( ( face1->planenum & ~1 ) == ( face2->planenum & ~1 ) ) {
Log_Write( "face %d and %d, same front and back area but flipped planes\r\n",
face1->num, face2->num );
} //end if
} //end if
} //end if
return false;
} //end of the function AAS_TryMergeFaces
/*
int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
{
winding_t *neww;
#ifdef DEBUG
if (!face1->winding) Error("face1 %d without winding", face1->num);
if (!face2->winding) Error("face2 %d without winding", face2->num);
#endif //DEBUG
//if the faces are in the same plane
if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false;
// if (face1->planenum != face2->planenum) return false;
//NOTE: if the front or back area is zero this doesn't mean there's
//a real area. It means there's solid at that side of the face
//if both faces have the same front area
if (face1->frontarea != face2->frontarea ||
face1->backarea != face2->backarea)
{
if (!face1->frontarea || !face1->backarea ||
!face2->frontarea || !face2->backarea) return false;
else if (face1->frontarea != face2->backarea ||
face1->backarea != face2->frontarea) return false;
// return false;
} //end if
//this function is to be found in l_poly.c
neww = TryMergeWinding(face1->winding, face2->winding,
mapplanes[face1->planenum].normal);
if (!neww) return false;
//
FreeWinding(face1->winding);
face1->winding = neww;
//remove face2
if (face2->frontarea)
AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]);
if (face2->backarea)
AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]);
return true;
} //end of the function AAS_TryMergeFaces*/
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergeAreaFaces( void ) {
int num_facemerges = 0;
int side1, side2, restart;
tmp_area_t *tmparea, *lasttmparea;
tmp_face_t *face1, *face2;
Log_Write( "AAS_MergeAreaFaces\r\n" );
qprintf( "%6d face merges", num_facemerges );
//NOTE: first convex area is a dummy
lasttmparea = tmpaasworld.areas;
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next )
{
restart = false;
//
if ( tmparea->invalid ) {
continue;
}
//
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = face1->frontarea != tmparea;
for ( face2 = face1->next[side1]; face2; face2 = face2->next[side2] )
{
side2 = face2->frontarea != tmparea;
//if succesfully merged
if ( AAS_TryMergeFaces( face1, face2 ) ) {
//start over again after merging two faces
restart = true;
num_facemerges++;
qprintf( "\r%6d", num_facemerges );
AAS_CheckArea( tmparea );
break;
} //end if
} //end for
if ( restart ) {
tmparea = lasttmparea;
break;
} //end if
} //end for
lasttmparea = tmparea;
} //end for
qprintf( "\n" );
Log_Write( "%6d face merges\r\n", num_facemerges );
} //end of the function AAS_MergeAreaFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergePlaneFaces( tmp_area_t *tmparea, int planenum ) {
tmp_face_t *face1, *face2, *nextface2;
winding_t *neww;
int side1, side2;
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = face1->frontarea != tmparea;
if ( face1->planenum != planenum ) {
continue;
}
//
for ( face2 = face1->next[side1]; face2; face2 = nextface2 )
{
side2 = face2->frontarea != tmparea;
nextface2 = face2->next[side2];
//
if ( ( face2->planenum & ~1 ) != ( planenum & ~1 ) ) {
continue;
}
//
neww = MergeWindings( face1->winding, face2->winding,
mapplanes[face1->planenum].normal );
FreeWinding( face1->winding );
face1->winding = neww;
if ( face2->frontarea ) {
AAS_RemoveFaceFromArea( face2, face2->frontarea );
}
if ( face2->backarea ) {
AAS_RemoveFaceFromArea( face2, face2->backarea );
}
AAS_FreeTmpFace( face2 );
//
nextface2 = face1->next[side1];
} //end for
} //end for
} //end of the function AAS_MergePlaneFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_CanMergePlaneFaces( tmp_area_t *tmparea, int planenum ) {
tmp_area_t *frontarea, *backarea;
tmp_face_t *face1;
int side1, merge, faceflags = 0; // TTimo: init
frontarea = backarea = NULL;
merge = false;
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = face1->frontarea != tmparea;
if ( ( face1->planenum & ~1 ) != ( planenum & ~1 ) ) {
continue;
}
if ( !frontarea && !backarea ) {
frontarea = face1->frontarea;
backarea = face1->backarea;
faceflags = face1->faceflags;
} //end if
else
{
if ( frontarea != face1->frontarea ) {
return false;
}
if ( backarea != face1->backarea ) {
return false;
}
if ( faceflags != face1->faceflags ) {
return false;
}
merge = true;
} //end else
} //end for
return merge;
} //end of the function AAS_CanMergePlaneFaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_MergeAreaPlaneFaces( void ) {
int num_facemerges = 0;
int side1;
tmp_area_t *tmparea, *nexttmparea;
tmp_face_t *face1;
Log_Write( "AAS_MergePlaneFaces\r\n" );
qprintf( "%6d plane face merges", num_facemerges );
//NOTE: first convex area is a dummy
for ( tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea )
{
nexttmparea = tmparea->l_next;
//
if ( tmparea->invalid ) {
continue;
}
//
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
side1 = face1->frontarea != tmparea;
//
if ( AAS_CanMergePlaneFaces( tmparea, face1->planenum ) ) {
AAS_MergePlaneFaces( tmparea, face1->planenum );
nexttmparea = tmparea;
num_facemerges++;
qprintf( "\r%6d", num_facemerges );
break;
} //end if
} //end for
} //end for
qprintf( "\n" );
Log_Write( "%6d plane face merges\r\n", num_facemerges );
} //end of the function AAS_MergeAreaPlaneFaces

View File

@ -0,0 +1,39 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_facemerging.h
// Function: Merging of Faces
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
void AAS_MergeAreaFaces( void );
void AAS_MergeAreaPlaneFaces( void );

603
src/bspc/aas_file.c Normal file
View File

@ -0,0 +1,603 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_file.c
// Function: AAS file loading and writing
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_file.h"
#include "aas_store.h"
#include "aas_create.h"
#define AAS_Error Error
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SwapAASData( void ) {
int i, j;
//bounding boxes
for ( i = 0; i < ( *aasworld ).numbboxes; i++ )
{
( *aasworld ).bboxes[i].presencetype = LittleLong( ( *aasworld ).bboxes[i].presencetype );
( *aasworld ).bboxes[i].flags = LittleLong( ( *aasworld ).bboxes[i].flags );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).bboxes[i].mins[j] = LittleLong( ( *aasworld ).bboxes[i].mins[j] );
( *aasworld ).bboxes[i].maxs[j] = LittleLong( ( *aasworld ).bboxes[i].maxs[j] );
} //end for
} //end for
//vertexes
for ( i = 0; i < ( *aasworld ).numvertexes; i++ )
{
for ( j = 0; j < 3; j++ )
( *aasworld ).vertexes[i][j] = LittleFloat( ( *aasworld ).vertexes[i][j] );
} //end for
//planes
for ( i = 0; i < ( *aasworld ).numplanes; i++ )
{
for ( j = 0; j < 3; j++ )
( *aasworld ).planes[i].normal[j] = LittleFloat( ( *aasworld ).planes[i].normal[j] );
( *aasworld ).planes[i].dist = LittleFloat( ( *aasworld ).planes[i].dist );
( *aasworld ).planes[i].type = LittleLong( ( *aasworld ).planes[i].type );
} //end for
//edges
for ( i = 0; i < ( *aasworld ).numedges; i++ )
{
( *aasworld ).edges[i].v[0] = LittleLong( ( *aasworld ).edges[i].v[0] );
( *aasworld ).edges[i].v[1] = LittleLong( ( *aasworld ).edges[i].v[1] );
} //end for
//edgeindex
for ( i = 0; i < ( *aasworld ).edgeindexsize; i++ )
{
( *aasworld ).edgeindex[i] = LittleLong( ( *aasworld ).edgeindex[i] );
} //end for
//faces
for ( i = 0; i < ( *aasworld ).numfaces; i++ )
{
( *aasworld ).faces[i].planenum = LittleLong( ( *aasworld ).faces[i].planenum );
( *aasworld ).faces[i].faceflags = LittleLong( ( *aasworld ).faces[i].faceflags );
( *aasworld ).faces[i].numedges = LittleLong( ( *aasworld ).faces[i].numedges );
( *aasworld ).faces[i].firstedge = LittleLong( ( *aasworld ).faces[i].firstedge );
( *aasworld ).faces[i].frontarea = LittleLong( ( *aasworld ).faces[i].frontarea );
( *aasworld ).faces[i].backarea = LittleLong( ( *aasworld ).faces[i].backarea );
} //end for
//face index
for ( i = 0; i < ( *aasworld ).faceindexsize; i++ )
{
( *aasworld ).faceindex[i] = LittleLong( ( *aasworld ).faceindex[i] );
} //end for
//convex areas
for ( i = 0; i < ( *aasworld ).numareas; i++ )
{
( *aasworld ).areas[i].areanum = LittleLong( ( *aasworld ).areas[i].areanum );
( *aasworld ).areas[i].numfaces = LittleLong( ( *aasworld ).areas[i].numfaces );
( *aasworld ).areas[i].firstface = LittleLong( ( *aasworld ).areas[i].firstface );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).areas[i].mins[j] = LittleFloat( ( *aasworld ).areas[i].mins[j] );
( *aasworld ).areas[i].maxs[j] = LittleFloat( ( *aasworld ).areas[i].maxs[j] );
( *aasworld ).areas[i].center[j] = LittleFloat( ( *aasworld ).areas[i].center[j] );
} //end for
} //end for
//area settings
for ( i = 0; i < ( *aasworld ).numareasettings; i++ )
{
( *aasworld ).areasettings[i].contents = LittleLong( ( *aasworld ).areasettings[i].contents );
( *aasworld ).areasettings[i].areaflags = LittleLong( ( *aasworld ).areasettings[i].areaflags );
( *aasworld ).areasettings[i].presencetype = LittleLong( ( *aasworld ).areasettings[i].presencetype );
( *aasworld ).areasettings[i].cluster = LittleLong( ( *aasworld ).areasettings[i].cluster );
( *aasworld ).areasettings[i].clusterareanum = LittleLong( ( *aasworld ).areasettings[i].clusterareanum );
( *aasworld ).areasettings[i].numreachableareas = LittleLong( ( *aasworld ).areasettings[i].numreachableareas );
( *aasworld ).areasettings[i].firstreachablearea = LittleLong( ( *aasworld ).areasettings[i].firstreachablearea );
// Ridah
( *aasworld ).areasettings[i].groundsteepness = LittleFloat( ( *aasworld ).areasettings[i].groundsteepness );
} //end for
//area reachability
for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ )
{
( *aasworld ).reachability[i].areanum = LittleLong( ( *aasworld ).reachability[i].areanum );
( *aasworld ).reachability[i].facenum = LittleLong( ( *aasworld ).reachability[i].facenum );
( *aasworld ).reachability[i].edgenum = LittleLong( ( *aasworld ).reachability[i].edgenum );
for ( j = 0; j < 3; j++ )
{
( *aasworld ).reachability[i].start[j] = LittleFloat( ( *aasworld ).reachability[i].start[j] );
( *aasworld ).reachability[i].end[j] = LittleFloat( ( *aasworld ).reachability[i].end[j] );
} //end for
( *aasworld ).reachability[i].traveltype = LittleLong( ( *aasworld ).reachability[i].traveltype );
( *aasworld ).reachability[i].traveltime = LittleShort( ( *aasworld ).reachability[i].traveltime );
} //end for
//nodes
for ( i = 0; i < ( *aasworld ).numnodes; i++ )
{
( *aasworld ).nodes[i].planenum = LittleLong( ( *aasworld ).nodes[i].planenum );
( *aasworld ).nodes[i].children[0] = LittleLong( ( *aasworld ).nodes[i].children[0] );
( *aasworld ).nodes[i].children[1] = LittleLong( ( *aasworld ).nodes[i].children[1] );
} //end for
//cluster portals
for ( i = 0; i < ( *aasworld ).numportals; i++ )
{
( *aasworld ).portals[i].areanum = LittleLong( ( *aasworld ).portals[i].areanum );
( *aasworld ).portals[i].frontcluster = LittleLong( ( *aasworld ).portals[i].frontcluster );
( *aasworld ).portals[i].backcluster = LittleLong( ( *aasworld ).portals[i].backcluster );
( *aasworld ).portals[i].clusterareanum[0] = LittleLong( ( *aasworld ).portals[i].clusterareanum[0] );
( *aasworld ).portals[i].clusterareanum[1] = LittleLong( ( *aasworld ).portals[i].clusterareanum[1] );
} //end for
//cluster portal index
for ( i = 0; i < ( *aasworld ).portalindexsize; i++ )
{
( *aasworld ).portalindex[i] = LittleLong( ( *aasworld ).portalindex[i] );
} //end for
//cluster
for ( i = 0; i < ( *aasworld ).numclusters; i++ )
{
( *aasworld ).clusters[i].numareas = LittleLong( ( *aasworld ).clusters[i].numareas );
( *aasworld ).clusters[i].numportals = LittleLong( ( *aasworld ).clusters[i].numportals );
( *aasworld ).clusters[i].firstportal = LittleLong( ( *aasworld ).clusters[i].firstportal );
} //end for
} //end of the function AAS_SwapAASData
//===========================================================================
// dump the current loaded aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DumpAASData( void ) {
/*
if ((*aasworld).vertexes) FreeMemory((*aasworld).vertexes);
(*aasworld).vertexes = NULL;
if ((*aasworld).planes) FreeMemory((*aasworld).planes);
(*aasworld).planes = NULL;
if ((*aasworld).edges) FreeMemory((*aasworld).edges);
(*aasworld).edges = NULL;
if ((*aasworld).edgeindex) FreeMemory((*aasworld).edgeindex);
(*aasworld).edgeindex = NULL;
if ((*aasworld).faces) FreeMemory((*aasworld).faces);
(*aasworld).faces = NULL;
if ((*aasworld).faceindex) FreeMemory((*aasworld).faceindex);
(*aasworld).faceindex = NULL;
if ((*aasworld).areas) FreeMemory((*aasworld).areas);
(*aasworld).areas = NULL;
if ((*aasworld).areasettings) FreeMemory((*aasworld).areasettings);
(*aasworld).areasettings = NULL;
if ((*aasworld).reachability) FreeMemory((*aasworld).reachability);
(*aasworld).reachability = NULL;
*/
( *aasworld ).loaded = false;
} //end of the function AAS_DumpAASData
//===========================================================================
// allocate memory and read a lump of a AAS file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_LoadAASLump( FILE *fp, int offset, int length, void *buf ) {
if ( !length ) {
printf( "lump size 0\n" );
return buf;
} //end if
//seek to the data
if ( fseek( fp, offset, SEEK_SET ) ) {
AAS_Error( "can't seek to lump\n" );
AAS_DumpAASData();
fclose( fp );
return 0;
} //end if
//allocate memory
if ( !buf ) {
buf = (void *) GetClearedMemory( length );
}
//read the data
if ( fread( (char *) buf, 1, length, fp ) != length ) {
AAS_Error( "can't read lump\n" );
FreeMemory( buf );
AAS_DumpAASData();
fclose( fp );
return NULL;
} //end if
return buf;
} //end of the function AAS_LoadAASLump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DData( unsigned char *data, int size ) {
int i;
for ( i = 0; i < size; i++ )
{
data[i] ^= (unsigned char) i * 119;
} //end for
} //end of the function AAS_DData
//===========================================================================
// load an aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_LoadAASFile( char *filename, int fpoffset, int fplength ) {
FILE *fp;
aas_header_t header;
int offset, length;
//dump current loaded aas file
AAS_DumpAASData();
//open the file
fp = fopen( filename, "rb" );
if ( !fp ) {
AAS_Error( "can't open %s\n", filename );
return false;
} //end if
//seek to the correct position (in the pak file)
if ( fseek( fp, fpoffset, SEEK_SET ) ) {
AAS_Error( "can't seek to file %s\n" );
fclose( fp );
return false;
} //end if
//read the header
if ( fread( &header, sizeof( aas_header_t ), 1, fp ) != 1 ) {
AAS_Error( "can't read header of file %s\n", filename );
fclose( fp );
return false;
} //end if
//check header identification
header.ident = LittleLong( header.ident );
if ( header.ident != AASID ) {
AAS_Error( "%s is not an AAS file\n", filename );
fclose( fp );
return false;
} //end if
//check the version
header.version = LittleLong( header.version );
if ( header.version != AASVERSION ) {
AAS_Error( "%s is version %i, not %i\n", filename, header.version, AASVERSION );
fclose( fp );
return false;
} //end if
//
if ( header.version == AASVERSION ) {
AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 );
} //end if
( *aasworld ).bspchecksum = LittleLong( header.bspchecksum );
//load the lumps:
//bounding boxes
offset = fpoffset + LittleLong( header.lumps[AASLUMP_BBOXES].fileofs );
length = LittleLong( header.lumps[AASLUMP_BBOXES].filelen );
( *aasworld ).bboxes = (aas_bbox_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).bboxes );
if ( !( *aasworld ).bboxes ) {
return false;
}
( *aasworld ).numbboxes = length / sizeof( aas_bbox_t );
//vertexes
offset = fpoffset + LittleLong( header.lumps[AASLUMP_VERTEXES].fileofs );
length = LittleLong( header.lumps[AASLUMP_VERTEXES].filelen );
( *aasworld ).vertexes = (aas_vertex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).vertexes );
if ( !( *aasworld ).vertexes ) {
return false;
}
( *aasworld ).numvertexes = length / sizeof( aas_vertex_t );
//planes
offset = fpoffset + LittleLong( header.lumps[AASLUMP_PLANES].fileofs );
length = LittleLong( header.lumps[AASLUMP_PLANES].filelen );
( *aasworld ).planes = (aas_plane_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).planes );
if ( !( *aasworld ).planes ) {
return false;
}
( *aasworld ).numplanes = length / sizeof( aas_plane_t );
//edges
offset = fpoffset + LittleLong( header.lumps[AASLUMP_EDGES].fileofs );
length = LittleLong( header.lumps[AASLUMP_EDGES].filelen );
( *aasworld ).edges = (aas_edge_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).edges );
if ( !( *aasworld ).edges ) {
return false;
}
( *aasworld ).numedges = length / sizeof( aas_edge_t );
//edgeindex
offset = fpoffset + LittleLong( header.lumps[AASLUMP_EDGEINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_EDGEINDEX].filelen );
( *aasworld ).edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).edgeindex );
if ( !( *aasworld ).edgeindex ) {
return false;
}
( *aasworld ).edgeindexsize = length / sizeof( aas_edgeindex_t );
//faces
offset = fpoffset + LittleLong( header.lumps[AASLUMP_FACES].fileofs );
length = LittleLong( header.lumps[AASLUMP_FACES].filelen );
( *aasworld ).faces = (aas_face_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).faces );
if ( !( *aasworld ).faces ) {
return false;
}
( *aasworld ).numfaces = length / sizeof( aas_face_t );
//faceindex
offset = fpoffset + LittleLong( header.lumps[AASLUMP_FACEINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_FACEINDEX].filelen );
( *aasworld ).faceindex = (aas_faceindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).faceindex );
if ( !( *aasworld ).faceindex ) {
return false;
}
( *aasworld ).faceindexsize = length / sizeof( int );
//convex areas
offset = fpoffset + LittleLong( header.lumps[AASLUMP_AREAS].fileofs );
length = LittleLong( header.lumps[AASLUMP_AREAS].filelen );
( *aasworld ).areas = (aas_area_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).areas );
if ( !( *aasworld ).areas ) {
return false;
}
( *aasworld ).numareas = length / sizeof( aas_area_t );
//area settings
offset = fpoffset + LittleLong( header.lumps[AASLUMP_AREASETTINGS].fileofs );
length = LittleLong( header.lumps[AASLUMP_AREASETTINGS].filelen );
( *aasworld ).areasettings = (aas_areasettings_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).areasettings );
if ( !( *aasworld ).areasettings ) {
return false;
}
( *aasworld ).numareasettings = length / sizeof( aas_areasettings_t );
//reachability list
offset = fpoffset + LittleLong( header.lumps[AASLUMP_REACHABILITY].fileofs );
length = LittleLong( header.lumps[AASLUMP_REACHABILITY].filelen );
( *aasworld ).reachability = (aas_reachability_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).reachability );
if ( length && !( *aasworld ).reachability ) {
return false;
}
( *aasworld ).reachabilitysize = length / sizeof( aas_reachability_t );
//nodes
offset = fpoffset + LittleLong( header.lumps[AASLUMP_NODES].fileofs );
length = LittleLong( header.lumps[AASLUMP_NODES].filelen );
( *aasworld ).nodes = (aas_node_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).nodes );
if ( !( *aasworld ).nodes ) {
return false;
}
( *aasworld ).numnodes = length / sizeof( aas_node_t );
//cluster portals
offset = fpoffset + LittleLong( header.lumps[AASLUMP_PORTALS].fileofs );
length = LittleLong( header.lumps[AASLUMP_PORTALS].filelen );
( *aasworld ).portals = (aas_portal_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).portals );
if ( length && !( *aasworld ).portals ) {
return false;
}
( *aasworld ).numportals = length / sizeof( aas_portal_t );
//cluster portal index
offset = fpoffset + LittleLong( header.lumps[AASLUMP_PORTALINDEX].fileofs );
length = LittleLong( header.lumps[AASLUMP_PORTALINDEX].filelen );
( *aasworld ).portalindex = (aas_portalindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).portalindex );
if ( length && !( *aasworld ).portalindex ) {
return false;
}
( *aasworld ).portalindexsize = length / sizeof( aas_portalindex_t );
//clusters
offset = fpoffset + LittleLong( header.lumps[AASLUMP_CLUSTERS].fileofs );
length = LittleLong( header.lumps[AASLUMP_CLUSTERS].filelen );
( *aasworld ).clusters = (aas_cluster_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).clusters );
if ( length && !( *aasworld ).clusters ) {
return false;
}
( *aasworld ).numclusters = length / sizeof( aas_cluster_t );
//swap everything
AAS_SwapAASData();
//aas file is loaded
( *aasworld ).loaded = true;
//close the file
fclose( fp );
return true;
} //end of the function AAS_LoadAASFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_WriteAASLump( FILE *fp, aas_header_t *h, int lumpnum, void *data, int length ) {
aas_lump_t *lump;
lump = &h->lumps[lumpnum];
lump->fileofs = LittleLong( ftell( fp ) );
lump->filelen = LittleLong( length );
if ( length > 0 ) {
if ( fwrite( data, length, 1, fp ) < 1 ) {
Log_Print( "error writing lump %s\n", lumpnum );
fclose( fp );
return false;
} //end if
} //end if
return true;
} //end of the function AAS_WriteAASLump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowNumReachabilities( int tt, char *name ) {
int i, num;
num = 0;
for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ )
{
if ( ( ( *aasworld ).reachability[i].traveltype & TRAVELTYPE_MASK ) == tt ) {
num++;
}
} //end for
Log_Print( "%6d %s\n", num, name );
} //end of the function AAS_ShowNumReachabilities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ShowTotals( void ) {
Log_Print( "numvertexes = %d\r\n", ( *aasworld ).numvertexes );
Log_Print( "numplanes = %d\r\n", ( *aasworld ).numplanes );
Log_Print( "numedges = %d\r\n", ( *aasworld ).numedges );
Log_Print( "edgeindexsize = %d\r\n", ( *aasworld ).edgeindexsize );
Log_Print( "numfaces = %d\r\n", ( *aasworld ).numfaces );
Log_Print( "faceindexsize = %d\r\n", ( *aasworld ).faceindexsize );
Log_Print( "numareas = %d\r\n", ( *aasworld ).numareas );
Log_Print( "numareasettings = %d\r\n", ( *aasworld ).numareasettings );
Log_Print( "reachabilitysize = %d\r\n", ( *aasworld ).reachabilitysize );
Log_Print( "numnodes = %d\r\n", ( *aasworld ).numnodes );
Log_Print( "numportals = %d\r\n", ( *aasworld ).numportals );
Log_Print( "portalindexsize = %d\r\n", ( *aasworld ).portalindexsize );
Log_Print( "numclusters = %d\r\n", ( *aasworld ).numclusters );
AAS_ShowNumReachabilities( TRAVEL_WALK, "walk" );
AAS_ShowNumReachabilities( TRAVEL_CROUCH, "crouch" );
AAS_ShowNumReachabilities( TRAVEL_BARRIERJUMP, "barrier jump" );
AAS_ShowNumReachabilities( TRAVEL_JUMP, "jump" );
AAS_ShowNumReachabilities( TRAVEL_LADDER, "ladder" );
AAS_ShowNumReachabilities( TRAVEL_WALKOFFLEDGE, "walk off ledge" );
AAS_ShowNumReachabilities( TRAVEL_SWIM, "swim" );
AAS_ShowNumReachabilities( TRAVEL_WATERJUMP, "water jump" );
AAS_ShowNumReachabilities( TRAVEL_TELEPORT, "teleport" );
AAS_ShowNumReachabilities( TRAVEL_ELEVATOR, "elevator" );
AAS_ShowNumReachabilities( TRAVEL_ROCKETJUMP, "rocket jump" );
AAS_ShowNumReachabilities( TRAVEL_BFGJUMP, "bfg jump" );
AAS_ShowNumReachabilities( TRAVEL_GRAPPLEHOOK, "grapple hook" );
AAS_ShowNumReachabilities( TRAVEL_DOUBLEJUMP, "double jump" );
AAS_ShowNumReachabilities( TRAVEL_RAMPJUMP, "ramp jump" );
AAS_ShowNumReachabilities( TRAVEL_STRAFEJUMP, "strafe jump" );
AAS_ShowNumReachabilities( TRAVEL_JUMPPAD, "jump pad" );
AAS_ShowNumReachabilities( TRAVEL_FUNCBOB, "func bob" );
} //end of the function AAS_ShowTotals
//===========================================================================
// aas data is useless after writing to file because it is byte swapped
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_WriteAASFile( char *filename ) {
aas_header_t header;
FILE *fp;
Log_Print( "writing %s\n", filename );
AAS_ShowTotals();
//swap the aas data
AAS_SwapAASData();
//initialize the file header
memset( &header, 0, sizeof( aas_header_t ) );
header.ident = LittleLong( AASID );
header.version = LittleLong( AASVERSION );
header.bspchecksum = LittleLong( ( *aasworld ).bspchecksum );
//open a new file
fp = fopen( filename, "wb" );
if ( !fp ) {
Log_Print( "error opening %s\n", filename );
return false;
} //end if
//write the header
if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) {
fclose( fp );
return false;
} //end if
//add the data lumps to the file
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_BBOXES, ( *aasworld ).bboxes,
( *aasworld ).numbboxes * sizeof( aas_bbox_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_VERTEXES, ( *aasworld ).vertexes,
( *aasworld ).numvertexes * sizeof( aas_vertex_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PLANES, ( *aasworld ).planes,
( *aasworld ).numplanes * sizeof( aas_plane_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGES, ( *aasworld ).edges,
( *aasworld ).numedges * sizeof( aas_edge_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGEINDEX, ( *aasworld ).edgeindex,
( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACES, ( *aasworld ).faces,
( *aasworld ).numfaces * sizeof( aas_face_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACEINDEX, ( *aasworld ).faceindex,
( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREAS, ( *aasworld ).areas,
( *aasworld ).numareas * sizeof( aas_area_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREASETTINGS, ( *aasworld ).areasettings,
( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_REACHABILITY, ( *aasworld ).reachability,
( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_NODES, ( *aasworld ).nodes,
( *aasworld ).numnodes * sizeof( aas_node_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALS, ( *aasworld ).portals,
( *aasworld ).numportals * sizeof( aas_portal_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALINDEX, ( *aasworld ).portalindex,
( *aasworld ).portalindexsize * sizeof( aas_portalindex_t ) ) ) {
return false;
}
if ( !AAS_WriteAASLump( fp, &header, AASLUMP_CLUSTERS, ( *aasworld ).clusters,
( *aasworld ).numclusters * sizeof( aas_cluster_t ) ) ) {
return false;
}
//rewrite the header with the added lumps
fseek( fp, 0, SEEK_SET );
AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 );
if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) {
fclose( fp );
return false;
} //end if
//close the file
fclose( fp );
return true;
} //end of the function AAS_WriteAASFile

40
src/bspc/aas_file.h Normal file
View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_write.h
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
qboolean AAS_WriteAASFile( char *filename );
qboolean AAS_LoadAASFile( char *filename, int fpoffset, int fplength );

688
src/bspc/aas_gsubdiv.c Normal file
View File

@ -0,0 +1,688 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_gsubdiv.c
// Function: Gravitational Subdivision
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
#include "aas_store.h"
#include "aas_cfg.h"
#define FACECLIP_EPSILON 0.2
#define FACE_EPSILON 1.0
int numgravitationalsubdivisions = 0;
int numladdersubdivisions = 0;
//NOTE: only do gravitational subdivision BEFORE area merging!!!!!!!
// because the bsp tree isn't refreshes like with ladder subdivision
//===========================================================================
// NOTE: the original face is invalid after splitting
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SplitFace( tmp_face_t *face, vec3_t normal, float dist,
tmp_face_t **frontface, tmp_face_t **backface ) {
winding_t *frontw, *backw;
//
*frontface = *backface = NULL;
ClipWindingEpsilon( face->winding, normal, dist, FACECLIP_EPSILON, &frontw, &backw );
#ifdef DEBUG
//
if ( frontw ) {
if ( WindingIsTiny( frontw ) ) {
Log_Write( "AAS_SplitFace: tiny back face\r\n" );
FreeWinding( frontw );
frontw = NULL;
} //end if
} //end if
if ( backw ) {
if ( WindingIsTiny( backw ) ) {
Log_Write( "AAS_SplitFace: tiny back face\r\n" );
FreeWinding( backw );
backw = NULL;
} //end if
} //end if
#endif //DEBUG
//if the winding was split
if ( frontw ) {
//check bounds
( *frontface ) = AAS_AllocTmpFace();
( *frontface )->planenum = face->planenum;
( *frontface )->winding = frontw;
( *frontface )->faceflags = face->faceflags;
} //end if
if ( backw ) {
//check bounds
( *backface ) = AAS_AllocTmpFace();
( *backface )->planenum = face->planenum;
( *backface )->winding = backw;
( *backface )->faceflags = face->faceflags;
} //end if
} //end of the function AAS_SplitFace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
winding_t *AAS_SplitWinding( tmp_area_t *tmparea, int planenum ) {
tmp_face_t *face;
plane_t *plane;
int side;
winding_t *splitwinding;
//
plane = &mapplanes[planenum];
//create a split winding, first base winding for plane
splitwinding = BaseWindingForPlane( plane->normal, plane->dist );
//chop with all the faces of the area
for ( face = tmparea->tmpfaces; face && splitwinding; face = face->next[side] )
{
//side of the face the original area was on
side = face->frontarea != tmparea;
plane = &mapplanes[face->planenum ^ side];
ChopWindingInPlace( &splitwinding, plane->normal, plane->dist, 0 ); // PLANESIDE_EPSILON);
} //end for
return splitwinding;
} //end of the function AAS_SplitWinding
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TestSplitPlane( tmp_area_t *tmparea, vec3_t normal, float dist,
int *facesplits, int *groundsplits, int *epsilonfaces ) {
int j, side, front, back, planenum;
float d, d_front, d_back;
tmp_face_t *face;
winding_t *w;
*facesplits = *groundsplits = *epsilonfaces = 0;
planenum = FindFloatPlane( normal, dist );
w = AAS_SplitWinding( tmparea, planenum );
if ( !w ) {
return false;
}
FreeWinding( w );
//
for ( face = tmparea->tmpfaces; face; face = face->next[side] )
{
//side of the face the area is on
side = face->frontarea != tmparea;
if ( ( face->planenum & ~1 ) == ( planenum & ~1 ) ) {
Log_Print( "AAS_TestSplitPlane: tried face plane as splitter\n" );
return false;
} //end if
w = face->winding;
//reset distance at front and back side of plane
d_front = d_back = 0;
//reset front and back flags
front = back = 0;
for ( j = 0; j < w->numpoints; j++ )
{
d = DotProduct( w->p[j], normal ) - dist;
if ( d > d_front ) {
d_front = d;
}
if ( d < d_back ) {
d_back = d;
}
if ( d > 0.4 ) { // PLANESIDE_EPSILON)
front = 1;
}
if ( d < -0.4 ) { // PLANESIDE_EPSILON)
back = 1;
}
} //end for
//check for an epsilon face
if ( ( d_front > FACECLIP_EPSILON && d_front < FACE_EPSILON )
|| ( d_back < -FACECLIP_EPSILON && d_back > -FACE_EPSILON ) ) {
( *epsilonfaces )++;
} //end if
//if the face has points at both sides of the plane
if ( front && back ) {
( *facesplits )++;
if ( face->faceflags & FACE_GROUND ) {
( *groundsplits )++;
} //end if
} //end if
} //end for
return true;
} //end of the function AAS_TestSplitPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SplitArea( tmp_area_t *tmparea, int planenum, tmp_area_t **frontarea, tmp_area_t **backarea ) {
int side;
tmp_area_t *facefrontarea, *facebackarea, *faceotherarea;
tmp_face_t *face, *frontface, *backface, *splitface, *nextface;
winding_t *splitwinding;
plane_t *splitplane;
/*
#ifdef AW_DEBUG
int facesplits, groundsplits, epsilonface;
Log_Print("\n----------------------\n");
Log_Print("splitting area %d\n", areanum);
Log_Print("with normal = \'%f %f %f\', dist = %f\n", normal[0], normal[1], normal[2], dist);
AAS_TestSplitPlane(areanum, normal, dist,
&facesplits, &groundsplits, &epsilonface);
Log_Print("face splits = %d\nground splits = %d\n", facesplits, groundsplits);
if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //AW_DEBUG*/
//the original area
AAS_FlipAreaFaces( tmparea );
AAS_CheckArea( tmparea );
//
splitplane = &mapplanes[planenum];
/* //create a split winding, first base winding for plane
splitwinding = BaseWindingForPlane(splitplane->normal, splitplane->dist);
//chop with all the faces of the area
for (face = tmparea->tmpfaces; face && splitwinding; face = face->next[side])
{
//side of the face the original area was on
side = face->frontarea != tmparea->areanum;
plane = &mapplanes[face->planenum ^ side];
ChopWindingInPlace(&splitwinding, plane->normal, plane->dist, 0); // PLANESIDE_EPSILON);
} //end for*/
splitwinding = AAS_SplitWinding( tmparea, planenum );
if ( !splitwinding ) {
/*
#ifdef DEBUG
AAS_TestSplitPlane(areanum, normal, dist,
&facesplits, &groundsplits, &epsilonface);
Log_Print("\nface splits = %d\nground splits = %d\n", facesplits, groundsplits);
if (epsilonface) Log_Print("aaahh epsilon face\n");
#endif //DEBUG*/
Error( "AAS_SplitArea: no split winding when splitting area %d\n", tmparea->areanum );
} //end if
//create a split face
splitface = AAS_AllocTmpFace();
//get the map plane
splitface->planenum = planenum;
//store the split winding
splitface->winding = splitwinding;
//the new front area
( *frontarea ) = AAS_AllocTmpArea();
( *frontarea )->presencetype = tmparea->presencetype;
( *frontarea )->contents = tmparea->contents;
( *frontarea )->modelnum = tmparea->modelnum;
( *frontarea )->tmpfaces = NULL;
//the new back area
( *backarea ) = AAS_AllocTmpArea();
( *backarea )->presencetype = tmparea->presencetype;
( *backarea )->contents = tmparea->contents;
( *backarea )->modelnum = tmparea->modelnum;
( *backarea )->tmpfaces = NULL;
//add the split face to the new areas
AAS_AddFaceSideToArea( splitface, 0, ( *frontarea ) );
AAS_AddFaceSideToArea( splitface, 1, ( *backarea ) );
//split all the faces of the original area
for ( face = tmparea->tmpfaces; face; face = nextface )
{
//side of the face the original area was on
side = face->frontarea != tmparea;
//next face of the original area
nextface = face->next[side];
//front area of the face
facefrontarea = face->frontarea;
//back area of the face
facebackarea = face->backarea;
//remove the face from both the front and back areas
if ( facefrontarea ) {
AAS_RemoveFaceFromArea( face, facefrontarea );
}
if ( facebackarea ) {
AAS_RemoveFaceFromArea( face, facebackarea );
}
//split the face
AAS_SplitFace( face, splitplane->normal, splitplane->dist, &frontface, &backface );
//free the original face
AAS_FreeTmpFace( face );
//get the number of the area at the other side of the face
if ( side ) {
faceotherarea = facefrontarea;
} else { faceotherarea = facebackarea;}
//if there is an area at the other side of the original face
if ( faceotherarea ) {
if ( frontface ) {
AAS_AddFaceSideToArea( frontface, !side, faceotherarea );
}
if ( backface ) {
AAS_AddFaceSideToArea( backface, !side, faceotherarea );
}
} //end if
//add the front and back part left after splitting the original face to the new areas
if ( frontface ) {
AAS_AddFaceSideToArea( frontface, side, ( *frontarea ) );
}
if ( backface ) {
AAS_AddFaceSideToArea( backface, side, ( *backarea ) );
}
} //end for
if ( !( *frontarea )->tmpfaces ) {
Log_Print( "AAS_SplitArea: front area without faces\n" );
}
if ( !( *backarea )->tmpfaces ) {
Log_Print( "AAS_SplitArea: back area without faces\n" );
}
tmparea->invalid = true;
/*
#ifdef AW_DEBUG
for (i = 0, face = frontarea->tmpfaces; face; face = face->next[side])
{
side = face->frontarea != frontarea->areanum;
i++;
} //end for
Log_Print("created front area %d with %d faces\n", frontarea->areanum, i);
for (i = 0, face = backarea->tmpfaces; face; face = face->next[side])
{
side = face->frontarea != backarea->areanum;
i++;
} //end for
Log_Print("created back area %d with %d faces\n", backarea->areanum, i);
#endif //AW_DEBUG*/
AAS_FlipAreaFaces( ( *frontarea ) );
AAS_FlipAreaFaces( ( *backarea ) );
//
AAS_CheckArea( ( *frontarea ) );
AAS_CheckArea( ( *backarea ) );
} //end of the function AAS_SplitArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_FindBestAreaSplitPlane( tmp_area_t *tmparea, vec3_t normal, float *dist ) {
int side1, side2;
int foundsplitter, facesplits, groundsplits, epsilonfaces, bestepsilonfaces;
float bestvalue, value;
tmp_face_t *face1, *face2;
vec3_t tmpnormal, invgravity;
float tmpdist;
//get inverse of gravity direction
VectorCopy( cfg.phys_gravitydirection, invgravity );
VectorInverse( invgravity );
foundsplitter = false;
bestvalue = -999999;
bestepsilonfaces = 0;
//
#ifdef AW_DEBUG
Log_Print( "finding split plane for area %d\n", tmparea->areanum );
#endif //AW_DEBUG
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//
if ( WindingIsTiny( face1->winding ) ) {
Log_Write( "gsubdiv: area %d has a tiny winding\r\n", tmparea->areanum );
continue;
} //end if
//if the face isn't a gap or ground there's no split edge
if ( !( face1->faceflags & FACE_GROUND ) && !AAS_GapFace( face1, side1 ) ) {
continue;
}
//
for ( face2 = face1->next[side1]; face2; face2 = face2->next[side2] )
{
//side of the face the area is on
side2 = face2->frontarea != tmparea;
//
if ( WindingIsTiny( face1->winding ) ) {
Log_Write( "gsubdiv: area %d has a tiny winding\r\n", tmparea->areanum );
continue;
} //end if
//if the face isn't a gap or ground there's no split edge
if ( !( face2->faceflags & FACE_GROUND ) && !AAS_GapFace( face2, side2 ) ) {
continue;
}
//only split between gaps and ground
if ( !( ( ( face1->faceflags & FACE_GROUND ) && AAS_GapFace( face2, side2 ) ) ||
( ( face2->faceflags & FACE_GROUND ) && AAS_GapFace( face1, side1 ) ) ) ) {
continue;
}
//find a plane seperating the windings of the faces
if ( !FindPlaneSeperatingWindings( face1->winding, face2->winding, invgravity,
tmpnormal, &tmpdist ) ) {
continue;
}
#ifdef AW_DEBUG
Log_Print( "normal = \'%f %f %f\', dist = %f\n",
tmpnormal[0], tmpnormal[1], tmpnormal[2], tmpdist );
#endif //AW_DEBUG
//get metrics for this vertical plane
if ( !AAS_TestSplitPlane( tmparea, tmpnormal, tmpdist,
&facesplits, &groundsplits, &epsilonfaces ) ) {
continue;
} //end if
#ifdef AW_DEBUG
Log_Print( "face splits = %d\nground splits = %d\n",
facesplits, groundsplits );
#endif //AW_DEBUG
value = 100 - facesplits - 2 * groundsplits;
//avoid epsilon faces
value += epsilonfaces * -1000;
if ( value > bestvalue ) {
VectorCopy( tmpnormal, normal );
*dist = tmpdist;
bestvalue = value;
bestepsilonfaces = epsilonfaces;
foundsplitter = true;
} //end if
} //end for
} //end for
if ( bestepsilonfaces ) {
Log_Write( "found %d epsilon faces trying to split area %d\r\n",
epsilonfaces, tmparea->areanum );
} //end else
return foundsplitter;
} //end of the function AAS_FindBestAreaSplitPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_SubdivideArea_r( tmp_node_t *tmpnode ) {
int planenum;
tmp_area_t *frontarea, *backarea;
tmp_node_t *tmpnode1, *tmpnode2;
vec3_t normal;
float dist;
if ( AAS_FindBestAreaSplitPlane( tmpnode->tmparea, normal, &dist ) ) {
qprintf( "\r%6d", ++numgravitationalsubdivisions );
//
planenum = FindFloatPlane( normal, dist );
//split the area
AAS_SplitArea( tmpnode->tmparea, planenum, &frontarea, &backarea );
//
tmpnode->tmparea = NULL;
tmpnode->planenum = FindFloatPlane( normal, dist );
//
tmpnode1 = AAS_AllocTmpNode();
tmpnode1->planenum = 0;
tmpnode1->tmparea = frontarea;
//
tmpnode2 = AAS_AllocTmpNode();
tmpnode2->planenum = 0;
tmpnode2->tmparea = backarea;
//subdivide the areas created by splitting recursively
tmpnode->children[0] = AAS_SubdivideArea_r( tmpnode1 );
tmpnode->children[1] = AAS_SubdivideArea_r( tmpnode2 );
} //end if
return tmpnode;
} //end of the function AAS_SubdivideArea_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_GravitationalSubdivision_r( tmp_node_t *tmpnode ) {
//if this is a solid leaf
if ( !tmpnode ) {
return NULL;
}
//negative so it's an area
if ( tmpnode->tmparea ) {
return AAS_SubdivideArea_r( tmpnode );
}
//do the children recursively
tmpnode->children[0] = AAS_GravitationalSubdivision_r( tmpnode->children[0] );
tmpnode->children[1] = AAS_GravitationalSubdivision_r( tmpnode->children[1] );
return tmpnode;
} //end of the function AAS_GravitationalSubdivision_r
//===========================================================================
// NOTE: merge faces and melt edges first
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_GravitationalSubdivision( void ) {
Log_Write( "AAS_GravitationalSubdivision\r\n" );
numgravitationalsubdivisions = 0;
qprintf( "%6i gravitational subdivisions", numgravitationalsubdivisions );
//start with the head node
AAS_GravitationalSubdivision_r( tmpaasworld.nodes );
qprintf( "\n" );
Log_Write( "%6i gravitational subdivisions\r\n", numgravitationalsubdivisions );
} //end of the function AAS_GravitationalSubdivision
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_RefreshLadderSubdividedTree_r( tmp_node_t *tmpnode, tmp_area_t *tmparea,
tmp_node_t *tmpnode1, tmp_node_t *tmpnode2, int planenum ) {
//if this is a solid leaf
if ( !tmpnode ) {
return NULL;
}
//negative so it's an area
if ( tmpnode->tmparea ) {
if ( tmpnode->tmparea == tmparea ) {
tmpnode->tmparea = NULL;
tmpnode->planenum = planenum;
tmpnode->children[0] = tmpnode1;
tmpnode->children[1] = tmpnode2;
} //end if
return tmpnode;
} //end if
//do the children recursively
tmpnode->children[0] = AAS_RefreshLadderSubdividedTree_r( tmpnode->children[0],
tmparea, tmpnode1, tmpnode2, planenum );
tmpnode->children[1] = AAS_RefreshLadderSubdividedTree_r( tmpnode->children[1],
tmparea, tmpnode1, tmpnode2, planenum );
return tmpnode;
} //end of the function AAS_RefreshLadderSubdividedTree_r
//===========================================================================
// find an area with ladder faces and ground faces that are not connected
// split the area with a horizontal plane at the lowest vertex of all
// ladder faces in the area
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_LadderSubdivideArea_r( tmp_node_t *tmpnode ) {
int side1, i, planenum;
int foundladderface, foundgroundface;
float dist;
tmp_area_t *tmparea, *frontarea, *backarea;
tmp_face_t *face1;
tmp_node_t *tmpnode1, *tmpnode2;
vec3_t lowestpoint, normal = {0, 0, 1};
plane_t *plane;
winding_t *w;
tmparea = tmpnode->tmparea;
//skip areas with a liquid
if ( tmparea->contents & ( AREACONTENTS_WATER
| AREACONTENTS_LAVA
| AREACONTENTS_SLIME ) ) {
return tmpnode;
}
//must be possible to stand in the area
if ( !( tmparea->presencetype & PRESENCE_NORMAL ) ) {
return tmpnode;
}
//
foundladderface = false;
foundgroundface = false;
lowestpoint[2] = 99999;
//
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//if the face is a ladder face
if ( face1->faceflags & FACE_LADDER ) {
plane = &mapplanes[face1->planenum];
//the ladder face plane should be pretty much vertical
if ( DotProduct( plane->normal, normal ) > -0.1 ) {
foundladderface = true;
//find lowest point
for ( i = 0; i < face1->winding->numpoints; i++ )
{
if ( face1->winding->p[i][2] < lowestpoint[2] ) {
VectorCopy( face1->winding->p[i], lowestpoint );
} //end if
} //end for
} //end if
} //end if
else if ( face1->faceflags & FACE_GROUND ) {
foundgroundface = true;
} //end else if
} //end for
//
if ( ( !foundladderface ) || ( !foundgroundface ) ) {
return tmpnode;
}
//
for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] )
{
//side of the face the area is on
side1 = face1->frontarea != tmparea;
//if the face isn't a ground face
if ( !( face1->faceflags & FACE_GROUND ) ) {
continue;
}
//the ground plane
plane = &mapplanes[face1->planenum];
//get the difference between the ground plane and the lowest point
dist = DotProduct( plane->normal, lowestpoint ) - plane->dist;
//if the lowest point is very near one of the ground planes
if ( dist > -1 && dist < 1 ) {
return tmpnode;
} //end if
} //end for
//
dist = DotProduct( normal, lowestpoint );
planenum = FindFloatPlane( normal, dist );
//
w = AAS_SplitWinding( tmparea, planenum );
if ( !w ) {
return tmpnode;
}
FreeWinding( w );
//split the area with a horizontal plane through the lowest point
qprintf( "\r%6d", ++numladdersubdivisions );
//
AAS_SplitArea( tmparea, planenum, &frontarea, &backarea );
//
tmpnode->tmparea = NULL;
tmpnode->planenum = planenum;
//
tmpnode1 = AAS_AllocTmpNode();
tmpnode1->planenum = 0;
tmpnode1->tmparea = frontarea;
//
tmpnode2 = AAS_AllocTmpNode();
tmpnode2->planenum = 0;
tmpnode2->tmparea = backarea;
//subdivide the areas created by splitting recursively
tmpnode->children[0] = AAS_LadderSubdivideArea_r( tmpnode1 );
tmpnode->children[1] = AAS_LadderSubdivideArea_r( tmpnode2 );
//refresh the tree
AAS_RefreshLadderSubdividedTree_r( tmpaasworld.nodes, tmparea, tmpnode1, tmpnode2, planenum );
//
return tmpnode;
} //end of the function AAS_LadderSubdivideArea_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_LadderSubdivision_r( tmp_node_t *tmpnode ) {
//if this is a solid leaf
if ( !tmpnode ) {
return 0;
}
//negative so it's an area
if ( tmpnode->tmparea ) {
return AAS_LadderSubdivideArea_r( tmpnode );
}
//do the children recursively
tmpnode->children[0] = AAS_LadderSubdivision_r( tmpnode->children[0] );
tmpnode->children[1] = AAS_LadderSubdivision_r( tmpnode->children[1] );
return tmpnode;
} //end of the function AAS_LadderSubdivision_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_LadderSubdivision( void ) {
Log_Write( "AAS_LadderSubdivision\r\n" );
numladdersubdivisions = 0;
qprintf( "%6i ladder subdivisions", numladdersubdivisions );
//start with the head node
AAS_LadderSubdivision_r( tmpaasworld.nodes );
//
qprintf( "\n" );
Log_Write( "%6i ladder subdivisions\r\n", numladdersubdivisions );
} //end of the function AAS_LadderSubdivision

40
src/bspc/aas_gsubdiv.h Normal file
View File

@ -0,0 +1,40 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_gsubdiv.h
// Function: Gravitational subdivision
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
//works with the global tmpaasworld
void AAS_GravitationalSubdivision( void );
void AAS_LadderSubdivision( void );

840
src/bspc/aas_map.c Normal file
View File

@ -0,0 +1,840 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_map.c
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-03
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h" //aas_bbox_t
#include "aas_store.h" //AAS_MAX_BBOXES
#include "aas_cfg.h"
#include "../game/surfaceflags.h"
#define SPAWNFLAG_NOT_EASY 0x00000100
#define SPAWNFLAG_NOT_MEDIUM 0x00000200
#define SPAWNFLAG_NOT_HARD 0x00000400
#define SPAWNFLAG_NOT_DEATHMATCH 0x00000800
#define SPAWNFLAG_NOT_COOP 0x00001000
#define STATE_TOP 0
#define STATE_BOTTOM 1
#define STATE_UP 2
#define STATE_DOWN 3
#define DOOR_START_OPEN 1
#define DOOR_REVERSE 2
#define DOOR_CRUSHER 4
#define DOOR_NOMONSTER 8
#define DOOR_TOGGLE 32
#define DOOR_X_AXIS 64
#define DOOR_Y_AXIS 128
#define BBOX_NORMAL_EPSILON 0.00001
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec_t BoxOriginDistanceFromPlane( vec3_t normal, vec3_t mins, vec3_t maxs, int side ) {
vec3_t v1, v2;
int i;
if ( side ) {
for ( i = 0; i < 3; i++ )
{
if ( normal[i] > BBOX_NORMAL_EPSILON ) {
v1[i] = maxs[i];
} else if ( normal[i] < -BBOX_NORMAL_EPSILON ) {
v1[i] = mins[i];
} else { v1[i] = 0;}
} //end for
} //end if
else
{
for ( i = 0; i < 3; i++ )
{
if ( normal[i] > BBOX_NORMAL_EPSILON ) {
v1[i] = mins[i];
} else if ( normal[i] < -BBOX_NORMAL_EPSILON ) {
v1[i] = maxs[i];
} else { v1[i] = 0;}
} //end for
} //end else
VectorCopy( normal, v2 );
VectorInverse( v2 );
return DotProduct( v1, v2 );
} //end of the function BoxOriginDistanceFromPlane
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
vec_t CapsuleOriginDistanceFromPlane( vec3_t normal, vec3_t mins, vec3_t maxs ) {
float offset_up, offset_down, width, radius;
width = maxs[0] - mins[0];
// if the box is less high then it is wide
if ( maxs[2] - mins[2] < width ) {
width = maxs[2] - mins[2];
}
radius = width * 0.5;
// offset to upper and lower sphere
offset_up = maxs[2] - radius;
offset_down = -mins[2] - radius;
// if normal points upward
if ( normal[2] > 0 ) {
// touches lower sphere first
return normal[2] * offset_down + radius;
} else {
// touched upper sphere first
return -normal[2] * offset_up + radius;
}
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ExpandMapBrush( mapbrush_t *brush, vec3_t mins, vec3_t maxs ) {
int sn;
float dist;
side_t *s;
plane_t *plane;
for ( sn = 0; sn < brush->numsides; sn++ )
{
s = brush->original_sides + sn;
plane = &mapplanes[s->planenum];
dist = plane->dist;
if ( capsule_collision ) {
dist += CapsuleOriginDistanceFromPlane( plane->normal, mins, maxs );
} else {
dist += BoxOriginDistanceFromPlane( plane->normal, mins, maxs, 0 );
}
s->planenum = FindFloatPlane( plane->normal, dist );
//the side isn't a bevel after expanding
s->flags &= ~SFL_BEVEL;
//don't skip the surface
s->surf &= ~SURF_SKIP;
//make sure the texinfo is not TEXINFO_NODE
//when player clip contents brushes are read from the bsp tree
//they have the texinfo field set to TEXINFO_NODE
//s->texinfo = 0;
} //end for
} //end of the function AAS_ExpandMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_SetTexinfo( mapbrush_t *brush ) {
int n;
side_t *side;
if ( brush->contents & ( CONTENTS_LADDER
| CONTENTS_AREAPORTAL
| CONTENTS_CLUSTERPORTAL
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_DONOTENTER
| CONTENTS_DONOTENTER_LARGE
| CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_WINDOW
| CONTENTS_PLAYERCLIP ) ) {
//we just set texinfo to 0 because these brush sides MUST be used as
//bsp splitters textured or not textured
for ( n = 0; n < brush->numsides; n++ )
{
side = brush->original_sides + n;
//side->flags |= SFL_TEXTURED|SFL_VISIBLE;
side->texinfo = 0;
} //end for
} //end if
else
{
//only use brush sides as splitters if they are textured
//texinfo of non-textured sides will be set to TEXINFO_NODE
for ( n = 0; n < brush->numsides; n++ )
{
side = brush->original_sides + n;
//don't use side as splitter (set texinfo to TEXINFO_NODE) if not textured
if ( side->flags & ( SFL_TEXTURED | SFL_BEVEL ) ) {
side->texinfo = 0;
} else { side->texinfo = TEXINFO_NODE;}
} //end for
} //end else
} //end of the function AAS_SetTexinfo
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void FreeBrushWindings( mapbrush_t *brush ) {
int n;
side_t *side;
//
for ( n = 0; n < brush->numsides; n++ )
{
side = brush->original_sides + n;
//
if ( side->winding ) {
FreeWinding( side->winding );
}
} //end for
} //end of the function FreeBrushWindings
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_AddMapBrushSide( mapbrush_t *brush, int planenum ) {
side_t *side;
//
if ( nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES ) {
Error( "MAX_MAPFILE_BRUSHSIDES" );
}
//
side = brush->original_sides + brush->numsides;
side->original = NULL;
side->winding = NULL;
side->contents = brush->contents;
side->flags &= ~( SFL_BEVEL | SFL_VISIBLE );
side->surf = 0;
side->planenum = planenum;
side->texinfo = 0;
//
nummapbrushsides++;
brush->numsides++;
} //end of the function AAS_AddMapBrushSide
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_FixMapBrush( mapbrush_t *brush ) {
int i, j, planenum;
float dist;
winding_t *w;
plane_t *plane, *plane1, *plane2;
side_t *side;
vec3_t normal;
//calculate the brush bounds
ClearBounds( brush->mins, brush->maxs );
for ( i = 0; i < brush->numsides; i++ )
{
plane = &mapplanes[brush->original_sides[i].planenum];
w = BaseWindingForPlane( plane->normal, plane->dist );
for ( j = 0; j < brush->numsides && w; j++ )
{
if ( i == j ) {
continue;
}
//there are no brush bevels marked but who cares :)
if ( brush->original_sides[j].flags & SFL_BEVEL ) {
continue;
}
plane = &mapplanes[brush->original_sides[j].planenum ^ 1];
ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); //CLIP_EPSILON);
} //end for
side = &brush->original_sides[i];
side->winding = w;
if ( w ) {
for ( j = 0; j < w->numpoints; j++ )
{
AddPointToBounds( w->p[j], brush->mins, brush->maxs );
} //end for
} //end if
} //end for
//
for ( i = 0; i < brush->numsides; i++ )
{
for ( j = 0; j < brush->numsides; j++ )
{
if ( i == j ) {
continue;
}
plane1 = &mapplanes[brush->original_sides[i].planenum];
plane2 = &mapplanes[brush->original_sides[j].planenum];
if ( WindingsNonConvex( brush->original_sides[i].winding,
brush->original_sides[j].winding,
plane1->normal, plane2->normal,
plane1->dist, plane2->dist ) ) {
Log_Print( "non convex brush" );
} //end if
} //end for
} //end for
//NOW close the fucking brush!!
for ( i = 0; i < 3; i++ )
{
if ( brush->mins[i] < -MAX_MAP_BOUNDS ) {
VectorClear( normal );
normal[i] = -1;
dist = MAX_MAP_BOUNDS - 10;
planenum = FindFloatPlane( normal, dist );
//
Log_Print( "mins out of range: added extra brush side\n" );
AAS_AddMapBrushSide( brush, planenum );
} //end if
if ( brush->maxs[i] > MAX_MAP_BOUNDS ) {
VectorClear( normal );
normal[i] = 1;
dist = MAX_MAP_BOUNDS - 10;
planenum = FindFloatPlane( normal, dist );
//
Log_Print( "maxs out of range: added extra brush side\n" );
AAS_AddMapBrushSide( brush, planenum );
} //end if
if ( brush->mins[i] > MAX_MAP_BOUNDS || brush->maxs[i] < -MAX_MAP_BOUNDS ) {
Log_Print( "entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum );
} //end if
} //end for
//free all the windings
FreeBrushWindings( brush );
} //end of the function AAS_FixMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean AAS_MakeBrushWindings( mapbrush_t *ob ) {
int i, j;
winding_t *w;
side_t *side;
plane_t *plane, *plane1, *plane2;
ClearBounds( ob->mins, ob->maxs );
for ( i = 0; i < ob->numsides; i++ )
{
plane = &mapplanes[ob->original_sides[i].planenum];
w = BaseWindingForPlane( plane->normal, plane->dist );
for ( j = 0; j < ob->numsides && w; j++ )
{
if ( i == j ) {
continue;
}
if ( ob->original_sides[j].flags & SFL_BEVEL ) {
continue;
}
plane = &mapplanes[ob->original_sides[j].planenum ^ 1];
ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); //CLIP_EPSILON);
}
side = &ob->original_sides[i];
side->winding = w;
if ( w ) {
side->flags |= SFL_VISIBLE;
for ( j = 0; j < w->numpoints; j++ )
AddPointToBounds( w->p[j], ob->mins, ob->maxs );
}
}
//check if the brush is convex
for ( i = 0; i < ob->numsides; i++ )
{
for ( j = 0; j < ob->numsides; j++ )
{
if ( i == j ) {
continue;
}
plane1 = &mapplanes[ob->original_sides[i].planenum];
plane2 = &mapplanes[ob->original_sides[j].planenum];
if ( WindingsNonConvex( ob->original_sides[i].winding,
ob->original_sides[j].winding,
plane1->normal, plane2->normal,
plane1->dist, plane2->dist ) ) {
Log_Print( "non convex brush" );
} //end if
} //end for
} //end for
//check for out of bound brushes
for ( i = 0; i < 3; i++ )
{
//IDBUG: all the indexes into the mins and maxs were zero (not using i)
if ( ob->mins[i] < -MAX_MAP_BOUNDS || ob->maxs[i] > MAX_MAP_BOUNDS ) {
Log_Print( "entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum );
Log_Print( "ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i] );
ob->numsides = 0; //remove the brush
break;
} //end if
if ( ob->mins[i] > MAX_MAP_BOUNDS || ob->maxs[i] < -MAX_MAP_BOUNDS ) {
Log_Print( "entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum );
Log_Print( "ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i] );
ob->numsides = 0; //remove the brush
break;
} //end if
} //end for
return true;
} //end of the function AAS_MakeBrushWindings
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
mapbrush_t *AAS_CopyMapBrush( mapbrush_t *brush, entity_t *mapent ) {
int n;
mapbrush_t *newbrush;
side_t *side, *newside;
if ( nummapbrushes >= MAX_MAPFILE_BRUSHES ) {
Error( "MAX_MAPFILE_BRUSHES" );
}
newbrush = &mapbrushes[nummapbrushes];
newbrush->original_sides = &brushsides[nummapbrushsides];
newbrush->entitynum = brush->entitynum;
newbrush->brushnum = nummapbrushes - mapent->firstbrush;
newbrush->numsides = brush->numsides;
newbrush->contents = brush->contents;
//copy the sides
for ( n = 0; n < brush->numsides; n++ )
{
if ( nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES ) {
Error( "MAX_MAPFILE_BRUSHSIDES" );
}
side = brush->original_sides + n;
newside = newbrush->original_sides + n;
newside->original = NULL;
newside->winding = NULL;
newside->contents = side->contents;
newside->flags = side->flags;
newside->surf = side->surf;
newside->planenum = side->planenum;
newside->texinfo = side->texinfo;
nummapbrushsides++;
} //end for
//
nummapbrushes++;
mapent->numbrushes++;
return newbrush;
} //end of the function AAS_CopyMapBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_AlwaysTriggered( char *targetname ) {
int i;
if ( !strlen( targetname ) ) {
return false;
}
//
for ( i = 0; i < num_entities; i++ )
{
//if the entity will activate the given targetname
if ( !strcmp( targetname, ValueForKey( &entities[i], "target" ) ) ) {
//if this activator is present in deathmatch
if ( !( atoi( ValueForKey( &entities[i], "spawnflags" ) ) & SPAWNFLAG_NOT_DEATHMATCH ) ) {
//if it is a trigger_always entity
if ( !strcmp( "trigger_always", ValueForKey( &entities[i], "classname" ) ) ) {
return true;
} //end if
//check for possible trigger_always entities activating this entity
if ( AAS_AlwaysTriggered( ValueForKey( &entities[i], "targetname" ) ) ) {
return true;
} //end if
} //end if
} //end if
} //end for
return false;
} //end of the function AAS_AlwaysTriggered
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_ValidEntity( entity_t *mapent ) {
int i;
char target[1024];
//all world brushes are used for AAS
if ( mapent == &entities[0] ) {
return true;
} //end if
//some of the func_wall brushes are also used for AAS
else if ( !strcmp( "func_wall", ValueForKey( mapent, "classname" ) ) ) {
//Log_Print("found func_wall entity %d\n", mapent - entities);
//if the func wall is used in deathmatch
//if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
{
//Log_Print("func_wall USED in deathmatch mode %d\n", atoi(ValueForKey(mapent, "spawnflags")));
return true;
} //end if
} //end else if
else if ( !strcmp( "func_door_rotating", ValueForKey( mapent, "classname" ) ) ||
!strcmp( "func_door", ValueForKey( mapent, "classname" ) ) ||
!strcmp( "func_invisible_user", ValueForKey( mapent, "classname" ) ) ) {
//if the func_door_rotating is present in deathmatch
//if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
{
//if the func_door_rotating is always activated in deathmatch
if ( AAS_AlwaysTriggered( ValueForKey( mapent, "targetname" ) ) ) {
//Log_Print("found func_door_rotating in deathmatch\ntargetname %s\n", ValueForKey(mapent, "targetname"));
return true;
} //end if
} //end if
} //end else if
else if ( !strcmp( "trigger_hurt", ValueForKey( mapent, "classname" ) ) ) {
// RF, spawnflag & 1 is for delayed spawn, so ignore it
if ( atoi( ValueForKey( mapent, "spawnflags" ) ) & 1 ) {
return false;
}
//"dmg" is the damage, for instance: "dmg" "666"
return true;
} //end else if
else if ( !strcmp( "trigger_push", ValueForKey( mapent, "classname" ) ) ) {
return true;
} //end else if
else if ( !strcmp( "trigger_multiple", ValueForKey( mapent, "classname" ) ) ) {
//find out if the trigger_multiple is pointing to a target_teleporter
strcpy( target, ValueForKey( mapent, "target" ) );
for ( i = 0; i < num_entities; i++ )
{
//if the entity will activate the given targetname
if ( !strcmp( target, ValueForKey( &entities[i], "targetname" ) ) ) {
if ( !strcmp( "target_teleporter", ValueForKey( &entities[i], "classname" ) ) ) {
return true;
} //end if
} //end if
} //end for
} //end else if
else if ( !strcmp( "trigger_teleport", ValueForKey( mapent, "classname" ) ) ) {
return true;
} //end else if
else if ( !strcmp( "func_tramcar", ValueForKey( mapent, "classname" ) ) ) {
return true;
} //end else if
else if ( !strcmp( "func_invisible_user", ValueForKey( mapent, "classname" ) ) ) {
return true;
}
/*
else if (!strcmp("func_static", ValueForKey(mapent, "classname")))
{
//FIXME: easy/medium/hard/deathmatch specific?
return true;
} //end else if
*/
return false;
} //end of the function AAS_ValidEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_TransformPlane( int planenum, vec3_t origin, vec3_t angles ) {
float newdist, matrix[3][3];
vec3_t normal;
//rotate the node plane
VectorCopy( mapplanes[planenum].normal, normal );
CreateRotationMatrix( angles, matrix );
RotatePoint( normal, matrix );
newdist = mapplanes[planenum].dist + DotProduct( normal, origin );
return FindFloatPlane( normal, newdist );
} //end of the function AAS_TransformPlane
//===========================================================================
// this function sets the func_rotating_door in it's final position
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PositionFuncRotatingBrush( entity_t *mapent, mapbrush_t *brush ) {
int spawnflags, i;
float distance;
vec3_t movedir, angles, pos1, pos2;
side_t *s;
spawnflags = FloatForKey( mapent, "spawnflags" );
VectorClear( movedir );
if ( spawnflags & DOOR_X_AXIS ) {
movedir[2] = 1.0; //roll
} else if ( spawnflags & DOOR_Y_AXIS ) {
movedir[0] = 1.0; //pitch
} else { // Z_AXIS
movedir[1] = 1.0; //yaw
}
// check for reverse rotation
if ( spawnflags & DOOR_REVERSE ) {
VectorInverse( movedir );
}
distance = FloatForKey( mapent, "distance" );
if ( !distance ) {
distance = 90;
}
GetVectorForKey( mapent, "angles", angles );
VectorCopy( angles, pos1 );
VectorMA( angles, -distance, movedir, pos2 );
// if it starts open, switch the positions
if ( spawnflags & DOOR_START_OPEN ) {
VectorCopy( pos2, angles );
VectorCopy( pos1, pos2 );
VectorCopy( angles, pos1 );
VectorInverse( movedir );
} //end if
//
for ( i = 0; i < brush->numsides; i++ )
{
s = &brush->original_sides[i];
s->planenum = AAS_TransformPlane( s->planenum, mapent->origin, pos2 );
} //end for
//
FreeBrushWindings( brush );
AAS_MakeBrushWindings( brush );
AddBrushBevels( brush );
FreeBrushWindings( brush );
} //end of the function AAS_PositionFuncRotatingBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PositionBrush( entity_t *mapent, mapbrush_t *brush ) {
side_t *s;
float newdist;
int i;
char *model;
if ( !strcmp( ValueForKey( mapent, "classname" ), "func_door_rotating" ) ) {
AAS_PositionFuncRotatingBrush( mapent, brush );
} //end if
else
{
if ( mapent->origin[0] || mapent->origin[1] || mapent->origin[2] ) {
for ( i = 0; i < brush->numsides; i++ )
{
s = &brush->original_sides[i];
newdist = mapplanes[s->planenum].dist +
DotProduct( mapplanes[s->planenum].normal, mapent->origin );
s->planenum = FindFloatPlane( mapplanes[s->planenum].normal, newdist );
} //end for
} //end if
// RF, disabled for Wolf, we dont use trigger_hurt for lava
//if it's a trigger hurt
//if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
//{
// //set the lava contents
// brush->contents |= CONTENTS_LAVA;
// //Log_Print("found trigger_hurt brush\n");
//} //end if
//
else if ( !strcmp( "trigger_push", ValueForKey( mapent, "classname" ) ) ) {
//set the jumppad contents
brush->contents = CONTENTS_JUMPPAD;
//Log_Print("found trigger_push brush\n");
} //end if
//
else if ( !strcmp( "trigger_multiple", ValueForKey( mapent, "classname" ) ) ) {
//set teleporter contents
brush->contents = CONTENTS_TELEPORTER;
//Log_Print("found trigger_multiple teleporter brush\n");
} //end if
//
else if ( !strcmp( "trigger_teleport", ValueForKey( mapent, "classname" ) ) ) {
//set teleporter contents
brush->contents = CONTENTS_TELEPORTER;
//Log_Print("found trigger_teleport teleporter brush\n");
} //end if
else if ( !strcmp( "func_door", ValueForKey( mapent, "classname" ) ) ) {
//set mover contents
brush->contents = CONTENTS_MOVER;
//get the model number
model = ValueForKey( mapent, "model" );
brush->modelnum = atoi( model + 1 );
} //end if
else if ( !strcmp( "func_invisible_user", ValueForKey( mapent, "classname" ) ) ) {
//set mover contents
brush->contents = CONTENTS_TRIGGER;
} //end if
} //end else
} //end of the function AAS_PositionBrush
//===========================================================================
// uses the global cfg_t cfg
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_CreateMapBrushes( mapbrush_t *brush, entity_t *mapent, int addbevels ) {
int i;
//side_t *s;
mapbrush_t *bboxbrushes[16];
//if the brushes are not from an entity used for AAS
if ( !AAS_ValidEntity( mapent ) ) {
nummapbrushsides -= brush->numsides;
brush->numsides = 0;
return;
} //end if
//
AAS_PositionBrush( mapent, brush );
//from all normal solid brushes only the textured brush sides will
//be used as bsp splitters, so set the right texinfo reference here
AAS_SetTexinfo( brush );
//remove contents detail flag, otherwise player clip contents won't be
//bsped correctly for AAS!
brush->contents &= ~CONTENTS_DETAIL;
//if the brush has contents area portal it should be the only contents
if ( brush->contents & ( CONTENTS_AREAPORTAL | CONTENTS_CLUSTERPORTAL ) ) {
brush->contents = CONTENTS_CLUSTERPORTAL;
brush->leafnum = -1;
} //end if
//window and playerclip are used for player clipping, make them solid
if ( brush->contents & ( CONTENTS_WINDOW | CONTENTS_PLAYERCLIP ) ) {
//
brush->contents &= ~( CONTENTS_WINDOW | CONTENTS_PLAYERCLIP );
brush->contents |= CONTENTS_SOLID;
brush->leafnum = -1;
} //end if
//
// Rafael TBD: no flag to support CONTENTS_BOTCLIP
/*
if (brush->contents & CONTENTS_BOTCLIP)
{
brush->contents = CONTENTS_SOLID;
brush->leafnum = -1;
} // end if
*/
//
//Log_Write("brush %d contents = ", brush->brushnum);
//PrintContents(brush->contents);
//Log_Write("\r\n");
//if not one of the following brushes then the brush is NOT used for AAS
if ( !( brush->contents & ( CONTENTS_SOLID
| CONTENTS_LADDER
| CONTENTS_CLUSTERPORTAL
| CONTENTS_DONOTENTER
| CONTENTS_DONOTENTER_LARGE
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_MOVER
) ) ) {
nummapbrushsides -= brush->numsides;
brush->numsides = 0;
return;
} //end if
//fix the map brush
//AAS_FixMapBrush(brush);
//if brush bevels should be added (for real map brushes, not bsp map brushes)
if ( addbevels ) {
//NOTE: we first have to get the mins and maxs of the brush before
// creating the brush bevels... the mins and maxs are used to
// create them. so we call MakeBrushWindings to get the mins
// and maxs and then after creating the bevels we free the
// windings because they are created for all sides (including
// bevels) a little later
AAS_MakeBrushWindings( brush );
AddBrushBevels( brush );
FreeBrushWindings( brush );
} //end if
//NOTE: add the brush to the WORLD entity!!!
mapent = &entities[0];
//there's at least one new brush for now
nummapbrushes++;
mapent->numbrushes++;
//liquid brushes are expanded for the maximum possible bounding box
if ( brush->contents & ( CONTENTS_WATER
| CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_TELEPORTER
| CONTENTS_JUMPPAD
| CONTENTS_DONOTENTER
| CONTENTS_DONOTENTER_LARGE
| CONTENTS_MOVER
) ) {
brush->expansionbbox = 0;
//NOTE: the first bounding box is the max
//FIXME: use max bounding box created from all bboxes
AAS_ExpandMapBrush( brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs );
AAS_MakeBrushWindings( brush );
} //end if
//area portal brushes are NOT expanded
else if ( brush->contents & CONTENTS_CLUSTERPORTAL ) {
brush->expansionbbox = 0;
//NOTE: the first bounding box is the max
//FIXME: use max bounding box created from all bboxes
AAS_ExpandMapBrush( brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs );
AAS_MakeBrushWindings( brush );
} //end if
//all solid brushes are expanded for all bounding boxes
else if ( brush->contents & ( CONTENTS_SOLID
| CONTENTS_LADDER
) ) {
//brush for the first bounding box
bboxbrushes[0] = brush;
//make a copy for the other bounding boxes
for ( i = 1; i < cfg.numbboxes; i++ )
{
bboxbrushes[i] = AAS_CopyMapBrush( brush, mapent );
} //end for
//expand every brush for it's bounding box and create windings
for ( i = 0; i < cfg.numbboxes; i++ )
{
AAS_ExpandMapBrush( bboxbrushes[i], cfg.bboxes[i].mins, cfg.bboxes[i].maxs );
bboxbrushes[i]->expansionbbox = cfg.bboxes[i].presencetype;
AAS_MakeBrushWindings( bboxbrushes[i] );
} //end for
} //end else
} //end of the function AAS_CreateMapBrushes

38
src/bspc/aas_map.h Normal file
View File

@ -0,0 +1,38 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_map.h
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
void AAS_CreateMapBrushes( mapbrush_t *brush, entity_t *mapent, int addbevels );

103
src/bspc/aas_prunenodes.c Normal file
View File

@ -0,0 +1,103 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_prunenodes.c
// Function: Prune Nodes
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#include "qbsp.h"
#include "../botlib/aasfile.h"
#include "aas_create.h"
int c_numprunes;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
tmp_node_t *AAS_PruneNodes_r( tmp_node_t *tmpnode ) {
tmp_area_t *tmparea1, *tmparea2;
//if it is a solid leaf
if ( !tmpnode ) {
return NULL;
}
//
if ( tmpnode->tmparea ) {
return tmpnode;
}
//process the children first
tmpnode->children[0] = AAS_PruneNodes_r( tmpnode->children[0] );
tmpnode->children[1] = AAS_PruneNodes_r( tmpnode->children[1] );
//if both children are areas
if ( tmpnode->children[0] && tmpnode->children[1] &&
tmpnode->children[0]->tmparea && tmpnode->children[1]->tmparea ) {
tmparea1 = tmpnode->children[0]->tmparea;
while ( tmparea1->mergedarea ) tmparea1 = tmparea1->mergedarea;
tmparea2 = tmpnode->children[1]->tmparea;
while ( tmparea2->mergedarea ) tmparea2 = tmparea2->mergedarea;
if ( tmparea1 == tmparea2 ) {
c_numprunes++;
tmpnode->tmparea = tmparea1;
tmpnode->planenum = 0;
AAS_FreeTmpNode( tmpnode->children[0] );
AAS_FreeTmpNode( tmpnode->children[1] );
tmpnode->children[0] = NULL;
tmpnode->children[1] = NULL;
return tmpnode;
} //end if
} //end if
//if both solid leafs
if ( !tmpnode->children[0] && !tmpnode->children[1] ) {
c_numprunes++;
AAS_FreeTmpNode( tmpnode );
return NULL;
} //end if
//
return tmpnode;
} //end of the function AAS_PruneNodes_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_PruneNodes( void ) {
Log_Write( "AAS_PruneNodes\r\n" );
AAS_PruneNodes_r( tmpaasworld.nodes );
Log_Print( "%6d nodes pruned\r\n", c_numprunes );
} //end of the function AAS_PruneNodes

39
src/bspc/aas_prunenodes.h Normal file
View File

@ -0,0 +1,39 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_prunenodes.h
// Function: Prune Nodes
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
void AAS_PruneNodes( void );

1124
src/bspc/aas_store.c Normal file

File diff suppressed because it is too large Load Diff

126
src/bspc/aas_store.h Normal file
View File

@ -0,0 +1,126 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
RTCW SP Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//===========================================================================
//
// Name: aas_store.h
// Function:
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
// Last update: 1997-12-04
// Tab Size: 3
//===========================================================================
#define AAS_MAX_BBOXES 5
#define AAS_MAX_VERTEXES 512000
#define AAS_MAX_PLANES 65536
#define AAS_MAX_EDGES 512000
#define AAS_MAX_EDGEINDEXSIZE 512000
#define AAS_MAX_FACES 512000
#define AAS_MAX_FACEINDEXSIZE 512000
#define AAS_MAX_AREAS 65536
#define AAS_MAX_AREASETTINGS 65536
#define AAS_MAX_REACHABILITYSIZE 65536
#define AAS_MAX_NODES 256000
#define AAS_MAX_PORTALS 65536
#define AAS_MAX_PORTALINDEXSIZE 65536
#define AAS_MAX_CLUSTERS 65536
#define BSPCINCLUDE
#include "../botlib/be_aas.h"
#include "../botlib/be_aas_def.h"
/*
typedef struct bspc_aas_s
{
int loaded;
int initialized; //true when AAS has been initialized
int savefile; //set true when file should be saved
//bounding boxes
int numbboxes;
aas_bbox_t *bboxes;
//vertexes
int numvertexes;
aas_vertex_t *vertexes;
//planes
int numplanes;
aas_plane_t *planes;
//edges
int numedges;
aas_edge_t *edges;
//edge index
int edgeindexsize;
aas_edgeindex_t *edgeindex;
//faces
int numfaces;
aas_face_t *faces;
//face index
int faceindexsize;
aas_faceindex_t *faceindex;
//convex areas
int numareas;
aas_area_t *areas;
//convex area settings
int numareasettings;
aas_areasettings_t *areasettings;
//reachablity list
int reachabilitysize;
aas_reachability_t *reachability;
//nodes of the bsp tree
int numnodes;
aas_node_t *nodes;
//cluster portals
int numportals;
aas_portal_t *portals;
//cluster portal index
int portalindexsize;
aas_portalindex_t *portalindex;
//clusters
int numclusters;
aas_cluster_t *clusters;
//
int numreachabilityareas;
float reachabilitytime;
} bspc_aas_t;
extern bspc_aas_t aasworld;
//
*/
// Ridah
extern aas_t aasworlds[1];
extern aas_t *aasworld;
// done.
//stores the AAS file from the temporary AAS
void AAS_StoreFile( char *filename );
//returns a number of the given plane
qboolean AAS_FindPlane( vec3_t normal, float dist, int *planenum );
//allocates the maximum AAS memory for storage
void AAS_AllocMaxAAS( void );
//frees the maximum AAS memory for storage
void AAS_FreeMaxAAS( void );

Some files were not shown because too many files have changed in this diff Show More