as released 2008-04-04

This commit is contained in:
archive 2008-04-04 00:00:00 +00:00
commit 1c7954095a
1986 changed files with 836597 additions and 0 deletions

281
COPYING.txt Normal file
View File

@ -0,0 +1,281 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

3
HW-README.txt Normal file
View File

@ -0,0 +1,3 @@
Exported from SVN revision #726 of spacetrader-gpl/branches/st-legacy
Compile the solution in the libs folder first, then the solution in the code folder.

193
README.txt Normal file
View File

@ -0,0 +1,193 @@
Quake III Arena GPL source release
==================================
This file contains the following sections:
LICENSE
GENERAL NOTES
COMPILING ON WIN32
COMPILING ON GNU/LINUX
COMPILING ON MAC
LICENSE
=======
See COPYING.txt for the GNU GENERAL PUBLIC LICENSE
Some source code in this release is not covered by the GPL:
IO on .zip files using portions of zlib
-----------------------------------------------------------------------------
lines file(s)
4299 code/qcommon/unzip.c
4546 libs/pak/unzip.cpp
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)
299 code/qcommon/md4.c
277 common/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.
checksums are used to validate pak files
standard C library replacement routines
-----------------------------------------------------------------------------
lines file(s)
1324 code/game/bg_lib.c
Copyright (c) 1992, 1993
The Regents of the University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the University of
California, Berkeley and its contributors.
4. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
ADPCM coder/decoder
-----------------------------------------------------------------------------
lines file(s)
330 code/client/snd_adpcm.c
Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
JPEG library
-----------------------------------------------------------------------------
code/jpeg-6
libs/jpeg6
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.
GENERAL NOTES
=============
A short summary of the file layout:
code/ Quake III Arena source code ( renderer, game code, OS layer etc. )
code/bspc bot routes compiler source code
lcc/ the retargetable C compiler ( produces assembly to be turned into qvm bytecode by q3asm )
q3asm/ assembly to qvm bytecode compiler
q3map/ map compiler ( .map -> .bsp ) - this is the version that comes with Q3Radiant 200f
q3radiant/ Q3Radiant map editor build 200f ( common/ and libs/ are support dirs for radiant )
While we made sure we were still able to compile the game on Windows, GNU/Linux and Mac, this build didn't get any kind of extensive testing so it may not work completely right. Whenever an id game is released under GPL, several projects start making the source code more friendly to nowaday's compilers and environements. If you are picking up this release weeks/months/years after we uploaded it, you probably want to look around on the net for cleaned up versions of this codebase as well.
COMPILING ON WIN32
==================
VC7 / Visual C++ 2003 project files are provided:
code/quake3.sln
q3radiant/Radiant.sln
To compile the qvms, you need to run some batch files:
you will need to have lcc.exe q3cpp.exe q3rcc.exe and q3asm.exe in your path
( some precompiled binaries are provided in lcc/bin and code/win32/mod-sdk-setup/bin )
the qvm batch files are in code/game code/cgame code/q3_ui code/ui ..
COMPILING ON GNU/LINUX
==================
the build system using cons, which may be known as scons's perl ancestor now
you don't have to track it down though, the build script is provided in the tree
you will need nasm and gcc 2.95
make sure you have the X Direct Graphics Access and X Video Mode extensions headers for your X11
a typical compile command goes like this:
[..]/code$ ./unix/cons -- gcc=gcc-2.95 g++=g++-2.95
COMPILING ON MAC
================
project file for OSX compile is in code/macosx/Quake3.pbproj

345
code/Rantfile Normal file
View File

@ -0,0 +1,345 @@
#pull some variables out of our environment
var.env %w(CC CPP CFLAGS CPPFLAGS)
#assign some defaults
var[:CC] = 'gcc' unless var[:CC]
var[:CPP] = 'g++' unless var[:CPP]
CFLAGS=' -fno-stack-protector -pipe -Wall -Wno-unused-parameter -Wno-missing-field-initializers -Wno-switch -Wstrict-aliasing=2 -D_REENTRANT -DNO_VM_COMPILED -DHAVE_EXECINFO_H -DDLL_ONLY -DDEVELOPER -DPRINT_CONSOLE_SPAM -m32 -I../libs/glew/include/ -Iunix/'
UI_CFLAGS=' '
CGAME_CFLAGS=' '
GAME_CFLAGS=' '
BOTLIB_CFLAGS='-DBOTLIB'
DEDICATED_CFLAGS='-DDEDICATED'
SQL_CFLAGS=' '
RENDER_CFLAGS='-I../libs/glew/include -O1 -DBUILD_RENDERER '
VORBIS_LIBS='../libs/libvorbis-1.1.2/lib/.libs/libvorbisfile.a ../libs/libvorbis-1.1.2/lib/.libs/libvorbis.a ../libs/libogg-1.1.3/src/.libs/libogg.a'
#OPENAL_LIBS="../libs/openal-0.0.8/src/.libs/libopenal.a"
BASE_DIR='/home/scott/HermitWorks/st-clean/'
if var[:release]
OUTPUT_DIR="release"
DEBUG=false
else
DEBUG=true
OUTPUT_DIR="build"
end
if var[:platform]
platform = var[:platform]
else
platform = RUBY_PLATFORM
end
task :default =>[:install]
case platform
when /powerpc-darwin/
BASE_CFLAGS="#{CFLAGS} -gfull -DMACOS_X -DDEBUG"
SHLIB_CFLAGS="-fPIC -fno-common"
CLIENT_LDFLAGS="-framework Cocoa -framework OpenGL ../libs/glew/lib-osx/libGLEW.dylib"
LIBSDLMAIN=''
ARCH='ppc'
SHLIB_EXT='so'
EXTENSION=''
CLIENT_CFLAGS='-I../libs/glew/include -I../libs/SDL12/include -DUSE_SDL'
DED_PLATFORM_FILES = ['linux_signals.o', 'linux_common.o', 'unix_main.o', 'unix_net.o',
'unix_shared.o', 'vm_ppc.o'
].collect{|file| "#{OUTPUT_DIR}/ded/" + file}
CLIENT_PLATFORM_FILES = ['vm_ppc.o', 'unix_main.o', 'unix_net.o', 'unix_shared.o',
'linux_signals.o', 'linux_common.o', 'linux_snd.o'
].collect{|file| "#{OUTPUT_DIR}/client/" + file}
when /win32/
BASE_CFLAGS="#{CFLAGS} -DNDEBUG -O2 -march=i586 -fomit-frame-pointer -ffast-math -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 -fstrength-reduce -m32 -D_WIN32 "
BASE_CPPFLAGS="#{CFLAGS} -msse2"
BASE_CPPFLAGS << " -DNDEBUG -O2 -march=i586 -fomit-frame-pointer -ffast-math -funroll-loops -falign-loops=2 -falign-jumps=2 -falign-functions=2 -fstrength-reduce "
CLIENT_CFLAGS=''
SHLIB_EXT='dll'
SHLIB_LDFLAGS="-shared"
SHLIB_CFLAGS='-fPIC'
EXTENSION='.exe'
ARCH='x86'
OUTPUT_DIR = OUTPUT_DIR << "-win32"
RENDER_LDFLAGS=" -mglew"
CLIENT_LDFLAGS=' -mwindows -lwsock32 -lgdi32 -lwinmm -lole32 -m32'
CLIENT_PLATFORM_FILES = ['win_gamma.o', 'win_glimp.o', 'win_input.o', 'win_main.o', 'win_net.o', 'win_shared.o', 'win_snd.o', 'win_syscon.o', 'win_wndproc.o', 'win_resource.o'].collect{|file| "#{OUTPUT_DIR}/client/" + file}
var[:CC]='i386-mingw32msvc-gcc'
var[:CPP]='i386-mingw32msvc-g++'
when /i[0-9]86-linux/
BASE_CFLAGS="#{CFLAGS} #{var[:CFLAGS]} -std=gnu99 "
BASE_CFLAGS << " -g -DDEBUG -O0 -D_DEBUG -march=i586 " if DEBUG
BASE_CFLAGS << " -DNDEBUG -O3 -march=i586 " unless DEBUG
BASE_CPPFLAGS="#{CFLAGS} #{var[:CPPFLAGS]} -msse2"
BASE_CPPFLAGS << " -g -DDEBUG -O1 -march=i586 " if DEBUG
BASE_CPPFLAGS << " -DNDEBUG -O3 -march=i586 " unless DEBUG
EXTENSION=''
if var[:CC] == 'icc' then BASE_CFLAGS << ' -wd193 -wd981 -wd1418 -wd1 -wd1419 -wd1469 -wd1682 -wd1684 -wd271 -wd279 -wd424 -wd537 -wd556 -wd1572 -wd188 -wd310 ' end
if var[:CPP] == 'icpc' then BASE_CFLAGS << ' -wd193 -wd981 -wd1418 -wd1 -wd1419 -wd1469 -wd1682 -wd1684 -wd271 -wd279 -wd424 -wd537 -wd556 -wd1572 -wd188 -wd310 ' end
ARCH='i386'
SHLIB_EXT='so'
SHLIB_CFLAGS=''
SHLIB_LDFLAGS='-shared'
DED_PLATFORM_FILES = ['linux_signals.o', 'linux_common.o', 'unix_main.o',
'unix_net.o', 'unix_shared.o', 'vm_x86.o', 'ftol.o', 'snapvector.o',
'matha.o'
].collect{|file| "#{OUTPUT_DIR}/ded/" + file}
CLIENT_PLATFORM_FILES = ['vm_x86.o', 'unix_main.o', 'unix_net.o',
'unix_shared.o', 'linux_signals.o',
'linux_common.o',
'linux_snd.o', 'drm.o',
'ftol.o', 'snapvector.o', 'snd_mixa.o', 'matha.o'
].collect{|file| "#{OUTPUT_DIR}/client/" + file}
CLIENT_CFLAGS="-I../libs/glew/include -DUSE_CODEC_VORBIS " ##{`sdl-config --cflags`.strip}"
CLIENT_LDFLAGS="-L/usr/X11R6/lib -lX11 -lXext -lXxf86vm ../libs/curl-7.15.3/lib/.libs/libcurl.a -lidn -lssl -lGL -ldl -lm ../libs/glew/lib/libGLEW.a -lpng -I/usr/X11R6/include -lpthread "
DEDICATED_LDFLAGS='-ldl ../libs/curl-7.15.3/lib/.libs/libcurl.a -lssl -lidn -lm'
RENDER_LDFLAGS=" ../libs/glew/lib/libGLEW.a -lpng "
LIBSDLMAIN=''
RENDER_CFLAGS << ' -I/usr/X11R6/include '
GECKO_CFLAGS = " -I../libs/gecko-sdk/include " + RENDER_CFLAGS
end
task :install =>[:all] do
sys.cp "#{OUTPUT_DIR}/gameplayer-#{ARCH}#{EXTENSION}", BASE_DIR
# sys.cp "#{OUTPUT_DIR}/st/librender-base#{ARCH}.#{SHLIB_EXT}", BASE_DIR + "/st"
#sys.cp "#{OUTPUT_DIR}/gameplayer-#{ARCH}#{EXTENSION}.#{SHLIB_EXT}", ENV['HOME'] + "/.mozilla/plugins"
#sys.cp "#{OUTPUT_DIR}/gameplayer-ded-#{ARCH}#{EXTENSION}", BASE_DIR
sys.cp "#{OUTPUT_DIR}/st/ui#{ARCH}.#{SHLIB_EXT}", BASE_DIR + "/st"
sys.cp "#{OUTPUT_DIR}/st/game#{ARCH}.#{SHLIB_EXT}", BASE_DIR + "/st"
sys.cp "#{OUTPUT_DIR}/st/cgame#{ARCH}.#{SHLIB_EXT}", BASE_DIR + "/st"
end
task :all =>[:modules, :engine]
task :engine => [
"#{OUTPUT_DIR}/gameplayer-#{ARCH}#{EXTENSION}"]
task :modules => ["#{OUTPUT_DIR}/st/ui#{ARCH}.#{SHLIB_EXT}",
"#{OUTPUT_DIR}/st/cgame#{ARCH}.#{SHLIB_EXT}",
"#{OUTPUT_DIR}/st/game#{ARCH}.#{SHLIB_EXT}",]
#"#{OUTPUT_DIR}/st/librender-base#{ARCH}.#{SHLIB_EXT}"]
UI_FILES = ['ui_atoms.o', 'ui_gameinfo.o', 'ui_main.o', 'ui_players.o',
'ui_syscalls.o', 'ui_shared.o', 'bg_misc.o', 'ui_graph.o',
'q_math.o', 'q_shared.o', 'ui_vote.o', 'ui_spacetrader.o',
'bg_spacetrader.o', 'bg_lib.o', 'ui_solarsystem.o', 'ui_anim.o'
].collect{|file| "#{OUTPUT_DIR}/st/ui/" + file}
CGAME_FILES = ['bg_misc.o', 'bg_pmove.o', 'bg_slidemove.o', 'cg_consolecmds.o',
'cg_draw.o', 'cg_drawtools.o', 'cg_effects.o', 'cg_ents.o',
'cg_event.o', 'cg_info.o', 'cg_localents.o', 'cg_main.o', 'cg_marks.o',
'cg_players.o', 'cg_playerstate.o', 'cg_predict.o', 'cg_ads.o',
'cg_servercmds.o', 'cg_snapshot.o', 'cg_syscalls.o', 'cg_view.o', 'cg_weapons.o',
'q_math.o', 'q_shared.o', 'cg_spacetrader.o', 'bg_spacetrader.o'
].collect{|file| "#{OUTPUT_DIR}/st/cgame/" + file}
GAME_FILES = ['ai_chat.o', 'ai_cmd.o', 'ai_dmnet.o', 'ai_dmq3.o', 'ai_main.o',
'ai_team.o', 'ai_vcmd.o', 'bg_misc.o', 'bg_pmove.o', 'bg_slidemove.o', 'g_active.o',
'g_bot.o', 'g_client.o', 'g_cmds.o', 'g_combat.o', 'g_items.o',
'g_main.o', 'g_mem.o', 'g_misc.o', 'g_missile.o', 'g_mover.o', 'g_session.o',
'g_spawn.o', 'g_svcmds.o', 'g_syscalls.o', 'g_target.o', 'g_team.o',
'g_trigger.o', 'g_utils.o', 'g_weapon.o', 'q_math.o', 'q_shared.o', 'g_spacetrader.o',
'bg_spacetrader.o'
].collect{|file| "#{OUTPUT_DIR}/st/game/" + file}
CORE_FILES = ['sv_bot.o', 'sv_client.o', 'sv_ccmds.o', 'sv_game.o', 'sv_init.o', 'sv_main.o',
'sv_net_chan.o', 'sv_snapshot.o', 'sv_world.o', 'cm_load.o', 'cm_polylib.o',
'cm_test.o', 'cm_trace.o', 'cm_patch.o', 'cmd.o', 'common.o', 'cvar.o', 'files.o',
'md4.o', 'msg.o', 'net_chan.o', 'huffman.o','q_shared.o', 'q_math.o', 'unzip.o',
'vm.o', 'vm_interpreted.o', 'net_http.o', 'cm_fastload.o', 'md5.o', 'rand.o', 'net_irc.o'
]
BOTLIB_FILES = ['be_aas_bspq3.o', 'be_aas_cluster.o', 'be_aas_debug.o', 'be_aas_entity.o',
'be_aas_file.o', 'be_aas_main.o', 'be_aas_move.o', 'be_aas_optimize.o',
'be_aas_reach.o', 'be_aas_route.o', 'be_aas_routealt.o', 'be_aas_sample.o',
'be_ai_char.o', 'be_ai_chat.o', 'be_ai_gen.o', 'be_ai_goal.o', 'be_ai_move.o',
'be_ai_weap.o', 'be_ai_weight.o', 'be_ea.o', 'be_interface.o', 'l_crc.o',
'l_libvar.o', 'l_log.o', 'l_memory.o', 'l_precomp.o', 'l_script.o', 'l_struct.o'
].collect{|file| "#{OUTPUT_DIR}/botlib/" + file}
DEDICATED_FILES = ['null_client.o', 'null_input.o', 'null_snddma.o'
].collect{|file| "#{OUTPUT_DIR}/ded/" + file}
CLIENT_FILES = ['cl_cgame.o', 'cl_cin.o', 'cl_console.o', 'cl_input.o', 'cl_keys.o',
'cl_main.o', 'cl_net_chan.o', 'cl_parse.o', 'cl_scrn.o', 'cl_ui.o', 'cl_text.o',
'snd_dma.o', 'snd_mem.o', 'snd_adpcm.o', 'snd_wavelet.o', 'snd_mix.o',
'snd_codec.o', 'snd_main.o', 'snd_codec_ogg.o'
].collect{|file| "#{OUTPUT_DIR}/client/" + file}
RENDER_FILES = ['tr_backend.o', 'tr_bsp.o', 'tr_lightmapconv.o',
'tr_cmds.o', 'tr_curve.o', 'tr_draw2d.o', 'tr_flares.o',
'tr_font.o', 'tr_image.o', 'tr_image_dds.o', 'tr_init.o',
'tr_light.o', 'tr_main.o', 'tr_marks.o', 'tr_mesh.o',
'tr_model.o', 'tr_noise.o', 'tr_scene.o', 'tr_shade.o',
'tr_shade_calc.o', 'tr_shader.o', 'tr_shadows.o', 'tr_sky.o',
'tr_state.o', 'tr_state-states.o', 'tr_state-states-textures.o',
'tr_surface.o', 'tr_text.o', 'tr_world.o', 'tr_x42.o',
'linux_glimp.o', 'unix_cpuinfo.o', 'tr_x42-load.o',
'tr_shade_programs.o', 'tr_postproc.o', 'tr_x42-sse.o',
'tr_x42-math.o', 'tr_x42-pose.o', 'tr_x42-animverts.o',
'tr_screenshot.o'
].collect{|file| "#{OUTPUT_DIR}/renderer/" + file}
SQL_FILES = ['sql.o', 'sql_create.o', 'sql_delete.o', 'sql_eval.o',
'sql_format.o', 'sql_insert.o', 'sql_msg.o',
'sql_parse.o', 'sql_search.o', 'sql_select.o',
'sql_update.o', 'sql_parser.o', 'sql_strings.o',
'sql_alter.o'
].collect{|file| "#{OUTPUT_DIR}/sql/" + file}
GECKO_FILES = ['entry_unix.o'].collect{|file| "#{OUTPUT_DIR}/gecko/" + file}
FORK_FILES = ["fork_unix.o"].collect{|file| "#{OUTPUT_DIR}/gecko/" + file}
import "c/dependencies", "directedrule"
#add more dirs to the %w( ) section to include the headers in the valid paths
gen C::Dependencies, :search => ['cgame', 'game', 'botlib', 'qcommon', 'ui', 'unix', 'win32', '../ui', 'renderer']
gen Action do source "c_dependencies" end
#generate our output directories
gen Directory, "#{OUTPUT_DIR}/st/game"
gen Directory, "#{OUTPUT_DIR}/st/ui"
gen Directory, "#{OUTPUT_DIR}/st/cgame"
gen Directory, "#{OUTPUT_DIR}/botlib"
gen Directory, "#{OUTPUT_DIR}/renderer"
gen Directory, "#{OUTPUT_DIR}/ded"
gen Directory, "#{OUTPUT_DIR}/client"
gen Directory, "#{OUTPUT_DIR}/sql"
gen Directory, "#{OUTPUT_DIR}/gecko"
#Compile rules for subdirectories
#rule for building targets in build/st/ui
ui_rule = gen DirectedRule, "#{OUTPUT_DIR}/st/ui" => sys["ui","qcommon", "game"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{SHLIB_CFLAGS} #{UI_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/st/cgame
cgame_rule = gen DirectedRule, "#{OUTPUT_DIR}/st/cgame" => sys["ui","qcommon", "game", "cgame"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{SHLIB_CFLAGS} #{CGAME_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/st/game
game_rule = gen DirectedRule, "#{OUTPUT_DIR}/st/game" => sys["game","qcommon"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{SHLIB_CFLAGS} #{GAME_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/botlib
botlib_rule = gen DirectedRule, "#{OUTPUT_DIR}/botlib"=> sys["botlib"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{BOTLIB_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/sql
gecko_rule = gen DirectedRule, "#{OUTPUT_DIR}/gecko"=> sys["gecko"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{GECKO_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/sql
sql_rule = gen DirectedRule, "#{OUTPUT_DIR}/sql"=> sys["sql"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{SQL_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building sql_parser.c
file "sql/sql_parser.c"=>'sql/sql_parser.y' do |t|
sys "../../Tools/Lemon/release/lemon #{t.name}"
end
#rule for building sql_parser.o
file "#{OUTPUT_DIR}/sql/sql_parser.o"=>'sql/sql_parser.c' do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{CLIENT_CFLAGS} -Wno-error -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/ded
dedicated_rule = gen DirectedRule, "#{OUTPUT_DIR}/ded"=> sys["server", "qcommon", "unix", "game", "null"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{DEDICATED_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building targets in build/client
client_rule = gen DirectedRule, "#{OUTPUT_DIR}/client"=>
sys["client","server", "qcommon", "game", "unix", "win32"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{CLIENT_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building nasm files in client dir
nasm_rule = gen DirectedRule, "#{OUTPUT_DIR}/client"=>sys["unix"], :o=>:nasm do |t|
sys "nasm -f elf -o #{t.name} #{t.source}"
end
#rule for building nasm files in ded dir
nasm_rule = gen DirectedRule, "#{OUTPUT_DIR}/ded"=>sys["unix"], :o=>:nasm do |t|
sys "nasm -f elf -o #{t.name} #{t.source}"
end
#rule for building .s files
as_rule = gen DirectedRule, "#{OUTPUT_DIR}/client"=>sys["unix"], :o=>:s do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} -DELF -x assembler-with-cpp -o #{t.name} -c #{t.source}"
end
#rule for building .s files
as_rule = gen DirectedRule, "#{OUTPUT_DIR}/ded"=>sys["unix"], :o=>:s do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} -DELF -x assembler-with-cpp -o #{t.name} -c #{t.source}"
end
#rule for building .s files
as_rule = gen DirectedRule, "#{OUTPUT_DIR}/renderer"=>sys["unix"], :o=>:s do |t|
sys "#{var[:CPP]} #{BASE_CFLAGS} -DELF -x assembler-with-cpp -o #{t.name} -c #{t.source}"
end
#rule for building targets in build/renderer
render_rule = gen DirectedRule, "#{OUTPUT_DIR}/renderer"=> sys["renderer", "unix", "qcommon"], :o => :c do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{SHLIB_CFLAGS} #{RENDER_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for building tr_x32-sse.o
file "#{OUTPUT_DIR}/renderer/tr_x42-sse.o"=>'renderer/tr_x42-sse.c' do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{CLIENT_CFLAGS} #{RENDER_CFLAGS} -msse2 -c -o #{t.name} #{t.source}"
end
#special rule for building client/vm_x86.c
file "#{OUTPUT_DIR}/client/vm_x86.o"=>'qcommon/vm_x86.c' do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{CLIENT_CFLAGS} -Wno-error -c -o #{t.name} #{t.source}"
end
#special rule for building ded/vm_x86.c
file "#{OUTPUT_DIR}/ded/vm_x86.o"=>'qcommon/vm_x86.c' do |t|
sys "#{var[:CC]} #{BASE_CFLAGS} #{CLIENT_CFLAGS} -Wno-error -c -o #{t.name} #{t.source}"
end
#use g++ for win_glimp.cpp
file "#{OUTPUT_DIR}/client/win_glimp.o"=>'win32/win_glimp.cpp' do |t|
sys "#{var[:CPP]} #{BASE_CPPFLAGS} #{CLIENT_CFLAGS} -c -o #{t.name} #{t.source}"
end
#use g++ for win_gamma.cpp
file "#{OUTPUT_DIR}/client/win_gamma.o"=>'win32/win_gamma.cpp' do |t|
sys "#{var[:CPP]} #{BASE_CPPFLAGS} #{CLIENT_CFLAGS} -c -o #{t.name} #{t.source}"
end
#rule for linking the ui lib
file "#{OUTPUT_DIR}/st/ui#{ARCH}.#{SHLIB_EXT}"=>UI_FILES do |t|
sys "#{var[:CC]} #{SHLIB_LDFLAGS} -o #{t.name} #{t.prerequisites.join(' ')}"
end
#rule for linking the cgame lib
file "#{OUTPUT_DIR}/st/cgame#{ARCH}.#{SHLIB_EXT}"=>CGAME_FILES do |t|
sys "#{var[:CC]} #{SHLIB_LDFLAGS} -o #{t.name} #{t.prerequisites.join(' ')}"
end
#rule for linking the game lib
file "#{OUTPUT_DIR}/st/game#{ARCH}.#{SHLIB_EXT}"=>GAME_FILES do |t|
sys "#{var[:CC]} #{SHLIB_LDFLAGS} -o #{t.name} #{t.prerequisites.join(' ')}"
end
#rule for linking the renderer lib
file "#{OUTPUT_DIR}/st/librender-base#{ARCH}.#{SHLIB_EXT}"=>RENDER_FILES do |t|
sys "#{var[:CC]} #{SHLIB_LDFLAGS} -o #{t.name} #{t.prerequisites.join(' ')} #{RENDER_LDFLAGS}"
end
#rule for linking the client/server
file "#{OUTPUT_DIR}/gameplayer-#{ARCH}#{EXTENSION}"=>
CORE_FILES.collect{|file| "#{OUTPUT_DIR}/client/" + file} + CLIENT_FILES + BOTLIB_FILES + CLIENT_PLATFORM_FILES + SQL_FILES + RENDER_FILES do |t|
sys "#{var[:CC]} -o #{t.name} #{t.prerequisites.join(' ')} #{LIBSDLMAIN} #{VORBIS_LIBS} #{CLIENT_LDFLAGS}"
sys.cp t.name, BASE_DIR
end
#rule for linking the server
file "#{OUTPUT_DIR}/gameplayer-ded-#{ARCH}#{EXTENSION}"=>
CORE_FILES.collect{|file| "#{OUTPUT_DIR}/ded/" + file} + BOTLIB_FILES + DEDICATED_FILES + DED_PLATFORM_FILES + SQL_FILES do |t|
sys "#{var[:CC]} -o #{t.name} #{t.prerequisites.join(' ')} #{DEDICATED_LDFLAGS}"
end
#rule for linking the plugin
file "#{OUTPUT_DIR}/gameplayer-#{ARCH}#{EXTENSION}.#{SHLIB_EXT}"=> FORK_FILES do |t| #CORE_FILES.collect{|file| "#{OUTPUT_DIR}/client/" + file} + CLIENT_FILES + BOTLIB_FILES + CLIENT_PLATFORM_FILES + SQL_FILES + RENDER_FILES + GECKO_FILES do |t|
sys "#{var[:CC]} -o #{t.name} #{t.prerequisites.join(' ')} #{SHLIB_LDFLAGS}"
end

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>SpaceTrader</string>
<key>CFBundleIdentifier</key>
<string>com.HermitWorksEntertainment.SpaceTrader</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSMainNibFile</key>
<string>Quake3</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

213
code/SpaceTrader.kdevelop Normal file
View File

@ -0,0 +1,213 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Scott Brooks</author>
<email>scott@hermitworksentertainment.com</email>
<version>1</version>
<projectmanagement>KDevCustomProject</projectmanagement>
<primarylanguage>C</primarylanguage>
<ignoreparts/>
<projectname>SpaceTrader</projectname>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
<defaultencoding/>
</general>
<kdevcustomproject>
<run>
<directoryradio>executable</directoryradio>
<mainprogram>/home/scott/HermitWorks/st-clean/gameplayer-i386</mainprogram>
<programargs/>
<globaldebugarguments>+set r_fullscreen 0 +set in_nograb 1 +set sv_cheats 1 +set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0</globaldebugarguments>
<globalcwd>/home/scott/HermitWorks/st-clean/</globalcwd>
<useglobalprogram>false</useglobalprogram>
<terminal>false</terminal>
<autocompile>false</autocompile>
<autoinstall>false</autoinstall>
<autokdesu>false</autokdesu>
<envvars/>
</run>
<filetypes>
<filetype>*.java</filetype>
<filetype>*.h</filetype>
<filetype>*.H</filetype>
<filetype>*.hh</filetype>
<filetype>*.hxx</filetype>
<filetype>*.hpp</filetype>
<filetype>*.c</filetype>
<filetype>*.C</filetype>
<filetype>*.cc</filetype>
<filetype>*.cpp</filetype>
<filetype>*.c++</filetype>
<filetype>*.cxx</filetype>
<filetype>Makefile</filetype>
<filetype>CMakeLists.txt</filetype>
</filetypes>
<blacklist/>
<build>
<buildtool>make</buildtool>
<builddir/>
</build>
<other>
<prio>0</prio>
<otherbin/>
<defaulttarget/>
<otheroptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</other>
<make>
<abortonerror>true</abortonerror>
<numberofjobs>0</numberofjobs>
<prio>0</prio>
<dontact>false</dontact>
<makebin>rant</makebin>
<defaulttarget/>
<makeoptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</make>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell/>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
<raiseGDBOnStart>false</raiseGDBOnStart>
</general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger>
<kdevdoctreeview>
<ignoretocs>
<toc>ada</toc>
<toc>ada_bugs_gcc</toc>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>libstdc++</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>stl</toc>
<toc>sw</toc>
<toc>w3c-dom-level2-html</toc>
<toc>w3c-svg</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="c" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevcppsupport>
<qt>
<used>false</used>
<version>3</version>
<includestyle>3</includestyle>
<root>/usr/share/qt3/</root>
<designerintegration>EmbeddedKDevDesigner</designerintegration>
<qmake>/usr/bin/qmake-qt3</qmake>
<designer></designer>
<designerpluginpaths/>
</qt>
<codecompletion>
<automaticCodeCompletion>false</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
<completionBoxItemOrder>0</completionBoxItemOrder>
<howEvaluationContextMenu>true</howEvaluationContextMenu>
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
<processPrimaryTypes>true</processPrimaryTypes>
<processFunctionArguments>false</processFunctionArguments>
<preProcessAllHeaders>false</preProcessAllHeaders>
<parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
<alwaysParseInBackground>true</alwaysParseInBackground>
<usePermanentCaching>true</usePermanentCaching>
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
<includePaths>.;</includePaths>
</codecompletion>
<creategettersetter>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
<splitheadersource>
<enabled>false</enabled>
<synchronize>true</synchronize>
<orientation>Vertical</orientation>
</splitheadersource>
<references/>
</kdevcppsupport>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
<kdevfileview>
<groups>
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
</kdevelop>

File diff suppressed because it is too large Load Diff

88
code/SpaceTrader_2005.sln Normal file
View File

@ -0,0 +1,88 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib\botlib_2005.vcproj", "{A410161F-AE9F-485D-A01F-5294891430A6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cgame", "cgame\cgame_2005.vcproj", "{C878E295-CB82-4B40-8ECF-5CE5525466FA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "game", "game\game_2005.vcproj", "{F9EE10DA-2404-4154-B904-F93C936C040A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpaceTrader", "SpaceTrader_2005.vcproj", "{81CB51C4-B434-4E12-B69B-BAEE102F2852}"
ProjectSection(ProjectDependencies) = postProject
{C878E295-CB82-4B40-8ECF-5CE5525466FA} = {C878E295-CB82-4B40-8ECF-5CE5525466FA}
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA} = {3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}
{F9EE10DA-2404-4154-B904-F93C936C040A} = {F9EE10DA-2404-4154-B904-F93C936C040A}
{C7C390EA-69FB-4ED9-886C-C09519268607} = {C7C390EA-69FB-4ED9-886C-C09519268607}
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19} = {A8EAC38E-C7DA-42F8-811D-77FD092B9D19}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ui", "ui\ui_2005.vcproj", "{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine", "engine_2005.vcproj", "{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vms", "vms_2005.vcproj", "{C7C390EA-69FB-4ED9-886C-C09519268607}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "render-base", "renderer\render_2005.vcproj", "{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Final Release|Win32 = Final Release|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A410161F-AE9F-485D-A01F-5294891430A6}.Debug|Win32.ActiveCfg = Debug|Win32
{A410161F-AE9F-485D-A01F-5294891430A6}.Debug|Win32.Build.0 = Debug|Win32
{A410161F-AE9F-485D-A01F-5294891430A6}.Final Release|Win32.ActiveCfg = Final Release|Win32
{A410161F-AE9F-485D-A01F-5294891430A6}.Final Release|Win32.Build.0 = Final Release|Win32
{A410161F-AE9F-485D-A01F-5294891430A6}.Release|Win32.ActiveCfg = Release|Win32
{A410161F-AE9F-485D-A01F-5294891430A6}.Release|Win32.Build.0 = Release|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Debug|Win32.ActiveCfg = Debug|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Debug|Win32.Build.0 = Debug|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Final Release|Win32.ActiveCfg = Final Release|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Final Release|Win32.Build.0 = Final Release|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Release|Win32.ActiveCfg = Release|Win32
{C878E295-CB82-4B40-8ECF-5CE5525466FA}.Release|Win32.Build.0 = Release|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Debug|Win32.ActiveCfg = Debug|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Debug|Win32.Build.0 = Debug|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Final Release|Win32.ActiveCfg = Final Release|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Final Release|Win32.Build.0 = Final Release|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Release|Win32.ActiveCfg = Release|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Release|Win32.Build.0 = Release|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug|Win32.ActiveCfg = Debug|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug|Win32.Build.0 = Debug|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Final Release|Win32.ActiveCfg = Final Release|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Final Release|Win32.Build.0 = Final Release|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Release|Win32.ActiveCfg = Release|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Release|Win32.Build.0 = Release|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Debug|Win32.ActiveCfg = Debug|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Debug|Win32.Build.0 = Debug|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Final Release|Win32.ActiveCfg = Final Release|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Final Release|Win32.Build.0 = Final Release|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Release|Win32.ActiveCfg = Release|Win32
{A8EAC38E-C7DA-42F8-811D-77FD092B9D19}.Release|Win32.Build.0 = Release|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Debug|Win32.ActiveCfg = Debug|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Debug|Win32.Build.0 = Debug|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Final Release|Win32.ActiveCfg = Final Release|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Final Release|Win32.Build.0 = Final Release|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Release|Win32.ActiveCfg = Release|Win32
{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}.Release|Win32.Build.0 = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Debug|Win32.ActiveCfg = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Debug|Win32.Build.0 = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Final Release|Win32.ActiveCfg = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Final Release|Win32.Build.0 = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Release|Win32.ActiveCfg = Release|Win32
{C7C390EA-69FB-4ED9-886C-C09519268607}.Release|Win32.Build.0 = Release|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Debug|Win32.ActiveCfg = Debug|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Debug|Win32.Build.0 = Debug|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Final Release|Win32.ActiveCfg = Final Release|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Final Release|Win32.Build.0 = Final Release|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Release|Win32.ActiveCfg = Release|Win32
{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
AMDCaProjectFile = C:\SpaceTrader\code\quake3-1.32b\code\CodeAnalyst\SpaceTrader_2005.caw
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="SpaceTrader"
ProjectGUID="{81CB51C4-B434-4E12-B69B-BAEE102F2852}"
RootNamespace="SpaceTrader"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)../game"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
Description="Generating Build Info"
CommandLine="svn status -u ./../ &gt; status-info/versions&#x0D;&#x0A;echo $(ConfigurationName) &gt; status-info/build-config&#x0D;&#x0A;echo hostname &gt; status-info/build-machine&#x0D;&#x0A;"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release_TA/SpaceTrader.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="&quot;../libs/libogg-1.1.3/include&quot;;&quot;../libs/oggvorbis-1.1.3/include&quot;;&quot;../libs/curl-7.15.3/include&quot;;&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="DEVELOPER;USE_CODEC_VORBIS;CURL_STATICLIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
RuntimeTypeInfo="false"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib wsock32.lib Iphlpapi.lib ogg_static.lib vorbis_static.lib vorbisfile_static.lib curllib.lib glew_static.lib opengl32.lib libpng.lib zlib.lib"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)..\libs\bin\$(ConfigurationName)&quot;"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
SubSystem="2"
StackReserveSize="524288"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
OutputManifestFile="$(IntDir)\ignored.manifest"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine=""
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)../game"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
Description="Generating Build Info"
CommandLine="echo &quot;DEBUG build, no SVN info included&quot; &gt; status-info/versions&#x0D;&#x0A;echo $(PlatformName) $(ConfigurationName) &gt; status-info/build-config&#x0D;&#x0A;hostname &gt; status-info/build-machine&#x0D;&#x0A;"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug_TA/SpaceTrader.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="&quot;../libs/libogg-1.1.3/include&quot;;&quot;../libs/oggvorbis-1.1.3/include&quot;;&quot;../libs/curl-7.15.3/include&quot;;&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="DEVELOPER;USE_CODEC_VORBIS;CURL_STATICLIB"
RuntimeLibrary="1"
BrowseInformationFile=""
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib wsock32.lib Iphlpapi.lib ogg_static.lib vorbis_static.lib vorbisfile_static.lib curllib.lib glew_static.lib opengl32.lib libpng.lib zlib.lib"
OutputFile="$(OutDir)\$(ProjectName)_debug.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)..\libs\bin\$(ConfigurationName)&quot;"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
SubSystem="2"
StackReserveSize="524288"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
OutputManifestFile="$(IntDir)\ignored.manifest"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine=""
/>
</Configuration>
<Configuration
Name="Final Release|Win32"
OutputDirectory="$(SolutionDir)../game"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
Description="Generating Build Info"
CommandLine="svn status -u ./../ &gt; status-info/versions&#x0D;&#x0A;echo $(ConfigurationName) &gt; status-info/build-config&#x0D;&#x0A;echo hostname &gt; status-info/build-machine&#x0D;&#x0A;"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release_TA/SpaceTrader.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="&quot;../libs/libogg-1.1.3/include&quot;;&quot;../libs/oggvorbis-1.1.3/include&quot;;&quot;../libs/curl-7.15.3/include&quot;;&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="DLL_ONLY;USE_CODEC_VORBIS;CURL_STATICLIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
RuntimeTypeInfo="false"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib wsock32.lib Iphlpapi.lib ogg_static.lib vorbis_static.lib vorbisfile_static.lib curllib.lib glew_static.lib opengl32.lib libpng.lib zlib.lib"
OutputFile="$(OutDir)\$(ProjectName)_final.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="&quot;$(SolutionDir)..\libs\bin\Release&quot;"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
SubSystem="2"
StackReserveSize="524288"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
OutputManifestFile="$(IntDir)\ignored.manifest"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine=""
/>
</Configuration>
</Configurations>
<References>
<ProjectReference
ReferencedProjectIdentifier="{A410161F-AE9F-485D-A01F-5294891430A6}"
RelativePathToProject=".\botlib\botlib_2005.vcproj"
/>
<ProjectReference
ReferencedProjectIdentifier="{3EC20DA3-BBE5-44BD-9C87-1187BF42BFFA}"
RelativePathToProject=".\renderer\render_2005.vcproj"
/>
<ProjectReference
ReferencedProjectIdentifier="{93A31E20-0519-4ACE-8A0A-09FC43DDC6C3}"
RelativePathToProject=".\engine_2005.vcproj"
/>
</References>
<Files>
<Filter
Name="Resource Files"
>
<File
RelativePath=".\win32\game.ico"
>
</File>
<File
RelativePath=".\win32\resource.h"
>
</File>
<File
RelativePath=".\win32\winengine.rc"
>
</File>
<File
RelativePath=".\win32\winquake.rc"
>
</File>
</Filter>
<File
RelativePath=".\status-info\build-config"
>
</File>
<File
RelativePath=".\status-info\build-machine"
>
</File>
<File
RelativePath="..\..\..\..\Documents and Settings\Phill\Desktop\resource.h"
>
</File>
<File
RelativePath=".\status-info\versions"
>
</File>
<File
RelativePath=".\win32\win_entry.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>SpaceTrader_plugin</string>
<key>CFBundleIdentifier</key>
<string>com.hermitworks.ige</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>WBPL</string>
<key>CFBundleSignature</key>
<string>HW</string>
<key>CFBundleVersion</key>
<string>0.101.0</string>
<key>CSResourcesFileMapped</key>
<string>yes</string>
<key>WebPluginDescription</key>
<string>Hermitworks Internet Game Engine</string>
<key>WebPluginMIMETypes</key>
<dict>
<key>application/x-hermitworks</key>
<dict>
<key>WebPluginExtensions</key>
<array>
<string>hwp</string>
</array>
<key>WebPluginTypeDescription</key>
<string>Hermitworks Entertainment Internet Game Engine 0.101.0</string>
</dict>
</dict>
<key>WebPluginName</key>
<string>Hermitworks Internet Game Engine</string>
</dict>
</plist>

268
code/botlib/aasfile.h Normal file
View File

@ -0,0 +1,268 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//NOTE: int = default signed
// default long
#define AASID (('S'<<24)+('A'<<16)+('A'<<8)+'E')
#define AASVERSION_OLD 4
#define AASVERSION 5
//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 //face seperating two areas with liquid
#define FACE_LIQUIDSURFACE 32 //face seperating liquid and air
#define FACE_BRIDGE 64 //can walk over this face if bridge is closed
//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
#define AREACONTENTS_MOVER 1024
#define AREACONTENTS_NOTTEAM1 2048
#define AREACONTENTS_NOTTEAM2 4096
//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
#define AREA_DISABLED 8 //area is disabled for routing when set
#define AREA_BRIDGE 16 //area ontop of a bridge
//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 area
int areaflags; //several area flags
int presencetype; //how a bot can be present in this 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
} 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 an area, often it will also seperate two 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; //area at the front of this face
int backarea; //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;
//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 area
int firstface; //first face in the face index used for the boundary of the area
vec3_t mins; //mins of the area
vec3_t maxs; //maxs of the area
vec3_t center; //'center' of the 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 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 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
the cluster number set to the negative portal number
- edge zero is a dummy
- face zero is a dummy
- area zero is a dummy
- node zero is a dummy
*/

221
code/botlib/be_aas.h Normal file
View File

@ -0,0 +1,221 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_aas.h
*
* desc: Area Awareness System, stuff exported to the AI
*
* $Archive: /source/code/botlib/be_aas.h $
*
*****************************************************************************/
#ifndef MAX_STRINGFIELD
#define MAX_STRINGFIELD 80
#endif
//travel flags
#define TFL_INVALID 0x00000001 //traveling temporary not possible
#define TFL_WALK 0x00000002 //walking
#define TFL_CROUCH 0x00000004 //crouching
#define TFL_BARRIERJUMP 0x00000008 //jumping onto a barrier
#define TFL_JUMP 0x00000010 //jumping
#define TFL_LADDER 0x00000020 //climbing a ladder
#define TFL_WALKOFFLEDGE 0x00000080 //walking of a ledge
#define TFL_SWIM 0x00000100 //swimming
#define TFL_WATERJUMP 0x00000200 //jumping out of the water
#define TFL_TELEPORT 0x00000400 //teleporting
#define TFL_ELEVATOR 0x00000800 //elevator
#define TFL_ROCKETJUMP 0x00001000 //rocket jumping
#define TFL_BFGJUMP 0x00002000 //bfg jumping
#define TFL_GRAPPLEHOOK 0x00004000 //grappling hook
#define TFL_DOUBLEJUMP 0x00008000 //double jump
#define TFL_RAMPJUMP 0x00010000 //ramp jump
#define TFL_STRAFEJUMP 0x00020000 //strafe jump
#define TFL_JUMPPAD 0x00040000 //jump pad
#define TFL_AIR 0x00080000 //travel through air
#define TFL_WATER 0x00100000 //travel through water
#define TFL_SLIME 0x00200000 //travel through slime
#define TFL_LAVA 0x00400000 //travel through lava
#define TFL_DONOTENTER 0x00800000 //travel through donotenter area
#define TFL_FUNCBOB 0x01000000 //func bobbing
#define TFL_FLIGHT 0x02000000 //flight
#define TFL_BRIDGE 0x04000000 //move over a bridge
//
#define TFL_NOTTEAM1 0x08000000 //not team 1
#define TFL_NOTTEAM2 0x10000000 //not team 2
//default travel flags
#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_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 shields; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim;
int torsoAnim;
} aas_entityinfo_t;
// area info
typedef struct aas_areainfo_s
{
int contents;
int flags;
int presencetype;
int cluster;
vec3_t mins;
vec3_t maxs;
vec3_t center;
} aas_areainfo_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
#define SE_HITBOUNDINGBOX 2048 // hit the specified bounding box
#define SE_TOUCHCLUSTERPORTAL 4096 // touching a cluster portal
typedef struct aas_clientmove_s
{
vec3_t endpos; //position at the end of movement prediction
int endarea; //area at 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
int endcontents; //contents at the end of movement prediction
float time; //time predicted ahead
int frames; //number of frames predicted ahead
} aas_clientmove_t;
// alternate route goals
#define ALTROUTEGOAL_ALL 1
#define ALTROUTEGOAL_CLUSTERPORTALS 2
#define ALTROUTEGOAL_VIEWPORTALS 4
typedef struct aas_altroutegoal_s
{
vec3_t origin;
int areanum;
unsigned short starttraveltime;
unsigned short goaltraveltime;
unsigned short extratraveltime;
} aas_altroutegoal_t;
// route prediction stop events
#define RSE_NONE 0
#define RSE_NOROUTE 1 //no route to goal
#define RSE_USETRAVELTYPE 2 //stop as soon as on of the given travel types is used
#define RSE_ENTERCONTENTS 4 //stop when entering the given contents
#define RSE_ENTERAREA 8 //stop when entering the given area
typedef struct aas_predictroute_s
{
vec3_t endpos; //position at the end of movement prediction
int endarea; //area at end of movement prediction
int stopevent; //event that made the prediction stop
int endcontents; //contents at the end of movement prediction
int endtravelflags; //end travel flags
int numareas; //number of areas predicted ahead
int time; //time predicted ahead (in hundreth of a sec)
} aas_predictroute_t;

90
code/botlib/be_aas_bsp.h Normal file
View File

@ -0,0 +1,90 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_bsp.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_bsp.h $
*
*****************************************************************************/
#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);

488
code/botlib/be_aas_bspq3.c Normal file
View File

@ -0,0 +1,488 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_bspq3.c
*
* desc: BSP, Environment Sampling
*
* $Archive: /MissionPack/code/botlib/be_aas_bspq3.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "botlib.h"
#include "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];
} 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)
{
BOTPRINT(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)
{
Com_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)
{
BOTPRINT(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)
{
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
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;
script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE);
bspworld.numentities = 1;
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)
{
BOTPRINT(PRT_MESSAGE, "too many entities in BSP file\n");
break;
} //end if
ent = &bspworld.entities[bspworld.numentities];
bspworld.numentities++;
ent->epairs = NULL;
while(PS_ReadToken(script, &token))
{
if (!strcmp(token.string, "}")) break;
epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t));
epair->next = ent->epairs;
ent->epairs = epair;
if (token.type != TT_STRING)
{
ScriptError(script, "invalid %s\n", token.string);
AAS_FreeBSPEntities();
FreeScript(script);
return;
} //end if
StripDoubleQuotes(token.string);
epair->key = (char *) GetHunkMemory(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 *) GetHunkMemory(strlen(token.string) + 1);
strcpy(epair->value, token.string);
} //end while
if (strcmp(token.string, "}"))
{
ScriptError(script, "missing }\n");
AAS_FreeBSPEntities();
FreeScript(script);
return;
} //end if
} //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;
Com_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);
Com_Memcpy(bspworld.dentdata, botimport.BSPEntityData(), bspworld.entdatasize);
AAS_ParseBSPEntities();
bspworld.loaded = qtrue;
return BLERR_NOERROR;
} //end of the function AAS_LoadBSPFile

1546
code/botlib/be_aas_cluster.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_cluster.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_cluster.h $
*
*****************************************************************************/
#ifdef AASINTERN
//initialize the AAS clustering
void AAS_InitClustering(void);
//
void AAS_SetViewPortalsAsClusterPortals(void);
#endif //AASINTERN

778
code/botlib/be_aas_debug.c Normal file
View File

@ -0,0 +1,778 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_debug.c
*
* desc: AAS debug code
*
* $Archive: /MissionPack/code/botlib/be_aas_debug.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_interface.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
#define MAX_DEBUGLINES 1024
#define MAX_DEBUGPOLYGONS 8192
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
Com_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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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 & TRAVELTYPE_MASK)
{
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
BOTPRINT(PRT_MESSAGE, "%s", str);
#endif
} //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 & TRAVELTYPE_MASK) == TRAVEL_JUMP ||
(reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
{
AAS_HorizontalVelocityForJump(aassettings.phys_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.phys_jumpvel;
//
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 3, 30, 0.1f,
SE_HITGROUND|SE_ENTERWATER|SE_ENTERSLIME|
SE_ENTERLAVA|SE_HITGROUNDDAMAGE, 0, qtrue);
//
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP)
{
AAS_JumpReachRunStart(reach, dir);
AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
} //end if
} //end if
else if ((reach->traveltype & TRAVELTYPE_MASK) == 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.1f,
SE_ENTERWATER|SE_ENTERSLIME|
SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
} //end else if
else if ((reach->traveltype & TRAVELTYPE_MASK) == 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.1f,
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)
{
Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t));
index++;
lasttime = AAS_Time();
AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK);
BOTPRINT(PRT_MESSAGE, "\n");
} //end if
AAS_ShowReachability(&reach);
} //end of the function ShowReachableAreas
void AAS_FloodAreas_r(int areanum, int cluster, int *done)
{
int nextareanum, i, facenum;
aas_area_t *area;
aas_face_t *face;
aas_areasettings_t *settings;
aas_reachability_t *reach;
AAS_ShowAreaPolygons(areanum, 1, qtrue);
//pointer to the convex area
area = &aasworld.areas[areanum];
settings = &aasworld.areasettings[areanum];
//walk through the faces of the area
for (i = 0; i < area->numfaces; i++)
{
facenum = abs(aasworld.faceindex[area->firstface + i]);
face = &aasworld.faces[facenum];
if (face->frontarea == areanum)
nextareanum = face->backarea;
else
nextareanum = face->frontarea;
if (!nextareanum)
continue;
if (done[nextareanum])
continue;
done[nextareanum] = qtrue;
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
continue;
if (AAS_AreaCluster(nextareanum) != cluster)
continue;
AAS_FloodAreas_r(nextareanum, cluster, done);
} //end for
//
for (i = 0; i < settings->numreachableareas; i++)
{
reach = &aasworld.reachability[settings->firstreachablearea + i];
nextareanum = reach->areanum;
if (!nextareanum)
continue;
if (done[nextareanum])
continue;
done[nextareanum] = qtrue;
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
continue;
if (AAS_AreaCluster(nextareanum) != cluster)
continue;
/*
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
{
AAS_DebugLine(reach->start, reach->end, 1);
}
*/
AAS_FloodAreas_r(nextareanum, cluster, done);
}
}
void AAS_FloodAreas(vec3_t origin)
{
int areanum, cluster, *done;
done = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
areanum = AAS_PointAreaNum(origin);
cluster = AAS_AreaCluster(areanum);
AAS_FloodAreas_r(areanum, cluster, done);
}

View File

@ -0,0 +1,63 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_debug.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_debug.h $
*
*****************************************************************************/
//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);

308
code/botlib/be_aas_def.h Normal file
View File

@ -0,0 +1,308 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_def.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_def.h $
*
*****************************************************************************/
//debugging on
#define AAS_DEBUG
#define MAX_CLIENTS 64
#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 CS_SCORES 32
#define CS_MODELS (CS_SCORES+MAX_CLIENTS)
#define CS_SOUNDS (CS_MODELS+MAX_MODELS)
#define DF_AASENTNUMBER(x) (x - aasworld.entities)
#define DF_NUMBERAASENT(x) (&aasworld.entities[x])
#define DF_AASENTCLIENT(x) (x - aasworld.entities - 1)
#define DF_CLIENTAASENT(x) (&aasworld.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
{
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_maxfallheight;
float rs_maxjumpfallheight;
} aas_settings_t;
#define CACHETYPE_PORTAL 0
#define CACHETYPE_AREA 1
//routing cache
typedef struct aas_routingcache_s
{
byte type; //portal or area cache
float time; //last time accessed or updated
int size; //size of the routing cache
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;
struct aas_routingcache_s *time_prev, *time_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;
//areas a reachability goes through
typedef struct aas_reachabilityareas_s
{
int firstarea, numareas;
} aas_reachabilityareas_t;
typedef struct aas_s
{
int loaded; //true when an AAS file is loaded
int is_fast_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 numreachabilityareas;
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];
//travel flags for each area based on contents
int *areacontentstravelflags;
//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;
//cache list sorted on time
aas_routingcache_t *oldestcache; // start of cache list sorted on time
aas_routingcache_t *newestcache; // end of cache list sorted on time
//maximum travel time through portal areas
int *portalmaxtraveltimes;
//areas the reachabilities go through
int *reachabilityareaindex;
aas_reachabilityareas_t *reachabilityareas;
} 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"
#endif //BSPCINCLUDE

438
code/botlib/be_aas_entity.c Normal file
View File

@ -0,0 +1,438 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_entity.c
*
* desc: AAS entities
*
* $Archive: /MissionPack/code/botlib/be_aas_entity.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
#define MASK_SOLID CONTENTS_PLAYERCLIP
//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 (!aasworld.loaded)
{
BOTPRINT(PRT_MESSAGE, "AAS_UpdateEntity: not loaded\n");
return BLERR_NOAASFILE;
} //end if
ent = &aasworld.entities[entnum];
if (!state) {
//unlink the entity
AAS_UnlinkFromAreas(ent->areas);
//unlink the entity from the BSP leaves
AAS_UnlinkFromBSPLeaves(ent->leaves);
//
ent->areas = NULL;
//
ent->leaves = NULL;
return BLERR_NOERROR;
}
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.shields = state->shields;
ent->i.weapon = state->weapon;
ent->i.legsAnim = state->legsAnim;
ent->i.torsoAnim = state->torsoAnim;
//number of the entity
ent->i.number = entnum;
//updated so set valid flag
ent->i.valid = qtrue;
//link everything the first frame
if (aasworld.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
VectorCopy(state->angles, ent->i.angles);
} //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 (!aasworld.initialized)
{
BOTPRINT(PRT_FATAL, "AAS_EntityInfo: aasworld not initialized\n");
Com_Memset(info, 0, sizeof(aas_entityinfo_t));
return;
} //end if
if (entnum < 0 || entnum >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntityInfo: entnum %d out of range\n", entnum);
Com_Memset(info, 0, sizeof(aas_entityinfo_t));
return;
} //end if
Com_Memcpy(info, &aasworld.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 >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntityOrigin: entnum %d out of range\n", entnum);
VectorClear(origin);
return;
} //end if
VectorCopy(aasworld.entities[entnum].i.origin, origin);
} //end of the function AAS_EntityOrigin
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityModelindex(int entnum)
{
if (entnum < 0 || entnum >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntityModelindex: entnum %d out of range\n", entnum);
return 0;
} //end if
return aasworld.entities[entnum].i.modelindex;
} //end of the function AAS_EntityModelindex
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityType(int entnum)
{
if (!aasworld.initialized) return 0;
if (entnum < 0 || entnum >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntityType: entnum %d out of range\n", entnum);
return 0;
} //end if
return aasworld.entities[entnum].i.type;
} //end of the AAS_EntityType
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_EntityModelNum(int entnum)
{
if (!aasworld.initialized) return 0;
if (entnum < 0 || entnum >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntityModelNum: entnum %d out of range\n", entnum);
return 0;
} //end if
return aasworld.entities[entnum].i.modelindex;
} //end of the function AAS_EntityModelNum
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_OriginOfMoverWithModelNum(int modelnum, vec3_t origin)
{
int i;
aas_entity_t *ent;
for (i = 0; i < aasworld.maxentities; i++)
{
ent = &aasworld.entities[i];
if (ent->i.type == ET_MOVER)
{
if (ent->i.modelindex == modelnum)
{
VectorCopy(ent->i.origin, origin);
return qtrue;
} //end if
} //end if
} //end for
return qfalse;
} //end of the function AAS_OriginOfMoverWithModelNum
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_EntitySize(int entnum, vec3_t mins, vec3_t maxs)
{
aas_entity_t *ent;
if (!aasworld.initialized) return;
if (entnum < 0 || entnum >= aasworld.maxentities)
{
BOTPRINT(PRT_FATAL, "AAS_EntitySize: entnum %d out of range\n", entnum);
return;
} //end if
ent = &aasworld.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 = &aasworld.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 < aasworld.maxentities; i++)
{
aasworld.entities[i].areas = NULL;
aasworld.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 < aasworld.maxentities; i++)
{
aasworld.entities[i].i.valid = qfalse;
aasworld.entities[i].i.number = i;
} //end for
} //end of the function AAS_InvalidateEntities
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_UnlinkInvalidEntities(void)
{
int i;
aas_entity_t *ent;
for (i = 0; i < aasworld.maxentities; i++)
{
ent = &aasworld.entities[i];
if (!ent->i.valid)
{
AAS_UnlinkFromAreas( ent->areas );
ent->areas = NULL;
AAS_UnlinkFromBSPLeaves( ent->leaves );
ent->leaves = NULL;
} //end for
} //end for
} //end of the function AAS_UnlinkInvalidEntities
//===========================================================================
//
// 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 < aasworld.maxentities; i++)
{
ent = &aasworld.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 = &aasworld.entities[entnum];
return AAS_BestReachableLinkArea(ent->areas);
} //end of the function AAS_BestReachableEntityArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_NextEntity(int entnum)
{
if (!aasworld.loaded) return 0;
if (entnum < 0) entnum = -1;
while(++entnum < aasworld.maxentities)
{
if (aasworld.entities[entnum].i.valid) return entnum;
} //end while
return 0;
} //end of the function AAS_NextEntity

View File

@ -0,0 +1,64 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_entity.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_entity.h $
*
*****************************************************************************/
#ifdef AASINTERN
//invalidates all entity infos
void AAS_InvalidateEntities(void);
//unlink not updated entities
void AAS_UnlinkInvalidEntities(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_OriginOfMoverWithModelNum(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);

777
code/botlib/be_aas_file.c Normal file
View File

@ -0,0 +1,777 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_file.c
*
* desc: AAS file loading/writing
*
* $Archive: /MissionPack/code/botlib/be_aas_file.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "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;
//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);
} //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)
{
if( aasworld.is_fast_loaded )
{
Com_Memset( &aasworld, 0, sizeof( aasworld ) );
return;
}
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;
BOTPRINT(PRT_MESSAGE, "version = %d\n", AASVERSION);
BOTPRINT(PRT_MESSAGE, "numvertexes = %d\n", aasworld.numvertexes);
BOTPRINT(PRT_MESSAGE, "numplanes = %d\n", aasworld.numplanes);
BOTPRINT(PRT_MESSAGE, "numedges = %d\n", aasworld.numedges);
BOTPRINT(PRT_MESSAGE, "edgeindexsize = %d\n", aasworld.edgeindexsize);
BOTPRINT(PRT_MESSAGE, "numfaces = %d\n", aasworld.numfaces);
BOTPRINT(PRT_MESSAGE, "faceindexsize = %d\n", aasworld.faceindexsize);
BOTPRINT(PRT_MESSAGE, "numareas = %d\n", aasworld.numareas);
BOTPRINT(PRT_MESSAGE, "numareasettings = %d\n", aasworld.numareasettings);
BOTPRINT(PRT_MESSAGE, "reachabilitysize = %d\n", aasworld.reachabilitysize);
BOTPRINT(PRT_MESSAGE, "numnodes = %d\n", aasworld.numnodes);
BOTPRINT(PRT_MESSAGE, "numportals = %d\n", aasworld.numportals);
BOTPRINT(PRT_MESSAGE, "portalindexsize = %d\n", aasworld.portalindexsize);
BOTPRINT(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
BOTPRINT(PRT_MESSAGE, "num grounded areas = %d\n", n);
//
BOTPRINT(PRT_MESSAGE, "planes size %d bytes\n", aasworld.numplanes * sizeof(aas_plane_t));
BOTPRINT(PRT_MESSAGE, "areas size %d bytes\n", aasworld.numareas * sizeof(aas_area_t));
BOTPRINT(PRT_MESSAGE, "areasettings size %d bytes\n", aasworld.numareasettings * sizeof(aas_areasettings_t));
BOTPRINT(PRT_MESSAGE, "nodes size %d bytes\n", aasworld.numnodes * sizeof(aas_node_t));
BOTPRINT(PRT_MESSAGE, "reachability size %d bytes\n", aasworld.reachabilitysize * sizeof(aas_reachability_t));
BOTPRINT(PRT_MESSAGE, "portals size %d bytes\n", aasworld.numportals * sizeof(aas_portal_t));
BOTPRINT(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);
BOTPRINT(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, int size)
{
char *buf;
//
if (!length)
{
//just alloc a dummy
return (char *) GetClearedHunkMemory(size+1);
} //end if
//seek to the data
if (offset != *lastoffset)
{
BOTPRINT(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 NULL;
} //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
int AAS_LoadAASFileFast( void *pAasData, const char *filename )
{
char *buf;
int offset, length;
aas_header_t header;
BOTPRINT( PRT_MESSAGE, "trying to load %s\n", filename );
//dump current loaded aas file
AAS_DumpAASData();
//open the file
//read the header
header = *(aas_header_t*)pAasData;
//check header identification
header.ident = LittleLong(header.ident);
if (header.ident != AASID)
{
AAS_Error("%s is not an AAS file\n", filename);
return BLERR_WRONGAASFILEID;
} //end if
//check the version
header.version = LittleLong(header.version);
//
if (header.version != AASVERSION_OLD && header.version != AASVERSION)
{
AAS_Error("aas file %s is version %i, not %i\n", filename, header.version, AASVERSION);
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( aasworld.bspchecksum != -1 && LittleLong( header.bspchecksum ) != aasworld.bspchecksum )
{
AAS_Error("aas file %s is out of date\n", filename);
return BLERR_WRONGAASFILEVERSION;
} //end if
//load the lumps:
buf = (char*)pAasData;
//bounding boxes
offset = LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
aasworld.bboxes = (aas_bbox_t*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
aasworld.faceindexsize = length / sizeof( aas_faceindex_t );
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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*)(buf + offset);
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;
aasworld.is_fast_loaded = qtrue;
#ifdef AASFILEDEBUG
AAS_FileInfo();
#endif //AASFILEDEBUG
return BLERR_NOERROR;
}
//===========================================================================
// load an aas file
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_LoadAASFile(char *filename)
{
fileHandle_t fp;
aas_header_t header;
int offset, length, lastoffset;
BOTPRINT(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_OLD && 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( aasworld.bspchecksum != -1 && 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, sizeof(aas_bbox_t));
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, sizeof(aas_vertex_t));
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, sizeof(aas_plane_t));
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, sizeof(aas_edge_t));
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, sizeof(aas_edgeindex_t));
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, sizeof(aas_face_t));
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, sizeof(aas_faceindex_t));
aasworld.faceindexsize = length / sizeof(aas_faceindex_t);
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, sizeof(aas_area_t));
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, sizeof(aas_areasettings_t));
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, sizeof(aas_reachability_t));
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, sizeof(aas_node_t));
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, sizeof(aas_portal_t));
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, sizeof(aas_portalindex_t));
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, sizeof(aas_cluster_t));
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;
BOTPRINT(PRT_MESSAGE, "writing %s\n", filename);
//swap the aas data
AAS_SwapAASData();
//initialize the file header
Com_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)
{
BOTPRINT(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);
AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
botimport.FS_Write(&header, sizeof(aas_header_t), fp);
//close the file
botimport.FS_FCloseFile(fp);
return qtrue;
} //end of the function AAS_WriteAASFile

44
code/botlib/be_aas_file.h Normal file
View File

@ -0,0 +1,44 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_file.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_file.h $
*
*****************************************************************************/
#ifdef AASINTERN
//loads the AAS file with the given name
int AAS_LoadAASFile(char *filename);
int AAS_LoadAASFileFast( void *pAasData, const 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

View File

@ -0,0 +1,48 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_funcs.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_funcs.h $
*
*****************************************************************************/
#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"
#endif //BSPCINCLUDE

552
code/botlib/be_aas_main.c Normal file
View File

@ -0,0 +1,552 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_main.c
*
* desc: AAS
*
* $Archive: /MissionPack/code/botlib/be_aas_main.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
aas_t aasworld;
libvar_t *saveroutingcache;
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void QDECL AAS_Error(char *fmt, ...)
{
char str[1024];
va_list arglist;
va_start(arglist, fmt);
vsnprintf(str, sizeof(str), fmt, arglist);
va_end(arglist);
BOTPRINT(PRT_FATAL, str);
} //end of the function AAS_Error
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *AAS_StringFromIndex(char *indexname, char *stringindex[], int numindexes, int index)
{
if (!aasworld.indexessetup)
{
BOTPRINT(PRT_ERROR, "%s: index %d not setup\n", indexname, index);
return "";
} //end if
if (index < 0 || index >= numindexes)
{
BOTPRINT(PRT_ERROR, "%s: index %d out of range\n", indexname, index);
return "";
} //end if
if (!stringindex[index])
{
if (index)
{
BOTPRINT(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)
{
BOTPRINT(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);
} //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);
} //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;
BOTPRINT(PRT_MESSAGE, "AAS initialized.\n");
#ifdef _DEBUG
//create all the routing cache
//AAS_CreateAllRoutingCache();
//
//AAS_RoutingInfo();
#endif
} //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("aasoptimize", "0")) AAS_Optimize();
//save the AAS file
if (AAS_WriteAASFile(aasworld.filename))
{
BOTPRINT(PRT_MESSAGE, "%s written succesfully\n", aasworld.filename);
} //end if
else
{
BOTPRINT(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)
{
aasworld.time = time;
//unlink all entities that were not updated last frame
AAS_UnlinkInvalidEntities();
//invalidate the entities
AAS_InvalidateEntities();
//initialize AAS
AAS_ContinueInit(time);
//
aasworld.frameroutingupdates = 0;
//
if (bot_developer)
{
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
//
if (saveroutingcache->value)
{
AAS_WriteRouteCache();
LibVarSet("saveroutingcache", "0");
} //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
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
{
vec3_t pVec, vec;
VectorSubtract( point, vStart, pVec );
VectorSubtract( vEnd, vStart, vec );
VectorNormalize( vec );
// project onto the directional vector for this segment
VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
} //end of the function AAS_ProjectPointOntoVector
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_LoadFiles( void *pAasData, 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);
if( pAasData )
errnum = AAS_LoadAASFileFast( pAasData, aasfile );
else
errnum = AAS_LoadAASFile(aasfile);
if (errnum != BLERR_NOERROR)
return errnum;
BOTPRINT(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: -
//===========================================================================
int AAS_LoadMap( void *pAasData, const char *mapname )
{
int errnum;
//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( pAasData, mapname );
if (errnum != BLERR_NOERROR)
{
aasworld.loaded = qfalse;
return errnum;
} //end if
//
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();
//everything went ok
return 0;
} //end of the function AAS_LoadMap
//===========================================================================
// called when the library is first loaded
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_Setup(void)
{
aasworld.maxclients = (int) LibVarValue("maxclients", "128");
aasworld.maxentities = (int) LibVarValue("maxentities", "1024");
// as soon as it's set to 1 the routing cache will be saved
saveroutingcache = LibVar("saveroutingcache", "0");
//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)
{
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();
//free the entities
if (aasworld.entities) FreeMemory(aasworld.entities);
//clear the aasworld structure
Com_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
BOTPRINT(PRT_MESSAGE, "AAS shutdown.\n");
} //end of the function AAS_Shutdown
#define AAS_FUDGE 24
void Q_EXTERNAL_CALL AAS_DrawDebugSurface( void (Q_EXTERNAL_CALL *drawPoly)(int color, int numPoints, float *points) ) {
int i;
for (i = 0; i < aasworld.numareas; i++) {
vec3_t v[4];
v[0][0] = aasworld.areas[i].mins[0];
v[0][1] = aasworld.areas[i].mins[1];
v[0][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].mins[0];
v[1][1] = aasworld.areas[i].mins[1];
v[1][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].mins[0];
v[2][1] = aasworld.areas[i].maxs[1];
v[2][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].mins[0];
v[3][1] = aasworld.areas[i].maxs[1];
v[3][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
v[0][0] = aasworld.areas[i].mins[0];
v[0][1] = aasworld.areas[i].mins[1];
v[0][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].maxs[0];
v[1][1] = aasworld.areas[i].mins[1];
v[1][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].maxs[0];
v[2][1] = aasworld.areas[i].maxs[1];
v[2][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].mins[0];
v[3][1] = aasworld.areas[i].maxs[1];
v[3][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
v[0][0] = aasworld.areas[i].mins[0];
v[0][1] = aasworld.areas[i].mins[1];
v[0][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].maxs[0];
v[1][1] = aasworld.areas[i].mins[1];
v[1][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].maxs[0];
v[2][1] = aasworld.areas[i].mins[1];
v[2][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].mins[0];
v[3][1] = aasworld.areas[i].mins[1];
v[3][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
v[0][0] = aasworld.areas[i].maxs[0];
v[0][1] = aasworld.areas[i].mins[1];
v[0][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].maxs[0];
v[1][1] = aasworld.areas[i].maxs[1];
v[1][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].maxs[0];
v[2][1] = aasworld.areas[i].maxs[1];
v[2][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].maxs[0];
v[3][1] = aasworld.areas[i].mins[1];
v[3][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
v[0][0] = aasworld.areas[i].mins[0];
v[0][1] = aasworld.areas[i].mins[1];
v[0][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].mins[0];
v[1][1] = aasworld.areas[i].maxs[1];
v[1][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].maxs[0];
v[2][1] = aasworld.areas[i].maxs[1];
v[2][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].maxs[0];
v[3][1] = aasworld.areas[i].mins[1];
v[3][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
v[0][0] = aasworld.areas[i].mins[0];
v[0][1] = aasworld.areas[i].maxs[1];
v[0][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
v[1][0] = aasworld.areas[i].mins[0];
v[1][1] = aasworld.areas[i].maxs[1];
v[1][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[2][0] = aasworld.areas[i].maxs[0];
v[2][1] = aasworld.areas[i].maxs[1];
v[2][2] = aasworld.areas[i].maxs[2] - AAS_FUDGE;
v[3][0] = aasworld.areas[i].maxs[0];
v[3][1] = aasworld.areas[i].maxs[1];
v[3][2] = aasworld.areas[i].mins[2] - AAS_FUDGE;
drawPoly(0, 4, v[0]);
}
}

62
code/botlib/be_aas_main.h Normal file
View File

@ -0,0 +1,62 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_main.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_main.h $
*
*****************************************************************************/
#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( void *pAasData, 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);
//
void AAS_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj );

1102
code/botlib/be_aas_move.c Normal file

File diff suppressed because it is too large Load Diff

72
code/botlib/be_aas_move.h Normal file
View File

@ -0,0 +1,72 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_move.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_move.h $
*
*****************************************************************************/
#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);
//predict movement until bounding box is hit
int AAS_ClientMovementHitBBox(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,
vec3_t mins, vec3_t maxs, 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);
//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,313 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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
*
* $Archive: /MissionPack/code/botlib/be_aas_optimize.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "l_libvar.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
typedef struct optimized_s
{
//vertexes
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];
Com_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];
Com_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 & TRAVELTYPE_MASK) == 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 & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD) continue;
//NOTE: for TRAVEL_FUNCBOB the facenum and edgenum contain other coded information
if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == 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 :)
BOTPRINT(PRT_MESSAGE, "AAS data optimized.\n");
} //end of the function AAS_Optimize

View File

@ -0,0 +1,34 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_optimize.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_optimize.h $
*
*****************************************************************************/
void AAS_Optimize(void);

4540
code/botlib/be_aas_reach.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_reach.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_reach.h $
*
*****************************************************************************/
#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 best jumppad area from which the bbox at origin is reachable
int AAS_BestReachableFromJumpPadArea(vec3_t origin, vec3_t mins, vec3_t maxs);
//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);

2214
code/botlib/be_aas_route.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_route.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_route.h $
*
*****************************************************************************/
#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_WriteRouteCache(void);
//
void AAS_RoutingInfo(void);
#endif //AASINTERN
//returns the travel flag for the given travel type
int AAS_TravelFlagForType(int traveltype);
//return the travel flag(s) for traveling through this area
int AAS_AreaContentsTravelFlags(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);
//enable or disable an area for routing
int AAS_EnableRoutingArea(int areanum, int enable);
//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);
//predict a route up to a stop event
int AAS_PredictRoute(struct aas_predictroute_s *route, int areanum, vec3_t origin,
int goalareanum, int travelflags, int maxareas, int maxtime,
int stopevent, int stopcontents, int stoptfl, int stopareanum);

View File

@ -0,0 +1,241 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_routealt.c
*
* desc: AAS
*
* $Archive: /MissionPack/code/botlib/be_aas_routealt.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"
#define ENABLE_ALTROUTING
//#define ALTROUTE_DEBUG
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, int startareanum, vec3_t goal, int goalareanum, int travelflags,
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
int type)
{
#ifndef ENABLE_ALTROUTING
return 0;
#else
int i, j, bestareanum;
int numaltroutegoals, nummidrangeareas;
int starttime, goaltime, goaltraveltime;
float dist, bestdist;
vec3_t mid, dir;
#ifdef ALTROUTE_DEBUG
int startmillisecs;
startmillisecs = Sys_MilliSeconds();
#endif
if (!startareanum || !goalareanum)
return 0;
//travel time towards the goal area
goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags);
//clear the midrange areas
Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t));
numaltroutegoals = 0;
//
nummidrangeareas = 0;
//
for (i = 1; i < aasworld.numareas; i++)
{
//
if (!(type & ALTROUTEGOAL_ALL))
{
if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)))
{
if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL)))
{
continue;
} //end if
} //end if
} //end if
//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 > (float) 1.1 * 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 > (float) 0.8 * 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 ALTROUTE_DEBUG
AAS_ShowAreaPolygons(bestareanum, 1, qtrue);
#endif
//don't return more than the maximum alternative route goals
if (numaltroutegoals >= maxaltroutegoals) break;
} //end for
#ifdef ALTROUTE_DEBUG
BOTPRINT(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
} //end of the function AAS_ShutdownAlternativeRouting

View File

@ -0,0 +1,41 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_routealt.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_routealt.h $
*
*****************************************************************************/
#ifdef AASINTERN
void AAS_InitAlternativeRouting(void);
void AAS_ShutdownAlternativeRouting(void);
#endif //AASINTERN
int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
int type);

1395
code/botlib/be_aas_sample.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_aas_sample.h
*
* desc: AAS
*
* $Archive: /source/code/botlib/be_aas_sample.h $
*
*****************************************************************************/
#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 areas the bounding box is in
int AAS_BBoxAreas(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
//return area information
int AAS_AreaInfo( int areanum, aas_areainfo_t *info );
//returns the area the point is in
int AAS_PointAreaNum(vec3_t point);
//
int AAS_PointReachabilityAreaIndex( vec3_t point );
//returns the plane the given face is in
void AAS_FacePlane(int facenum, vec3_t normal, float *dist);

791
code/botlib/be_ai_char.c Normal file
View File

@ -0,0 +1,791 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_char.c
*
* desc: bot characters
*
* $Archive: /MissionPack/code/botlib/be_ai_char.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "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];
float 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)
{
BOTPRINT(PRT_FATAL, "character handle %d out of range\n", handle);
return NULL;
} //end if
if (!botcharacters[handle])
{
BOTPRINT(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)
{
BOTPRINT(PRT_FATAL, "character handle %d out of range\n", handle);
return;
} //end if
if (!botcharacters[handle])
{
BOTPRINT(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
PC_SetBaseFolder(BOTFILESBASEFOLDER);
source = LoadSourceFile(charfile);
if (!source)
{
BOTPRINT(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 == (unsigned long)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, float skill)
{
int handle;
for (handle = 1; handle <= MAX_CLIENTS; handle++)
{
if ( !botcharacters[handle] ) continue;
if ( strcmp( botcharacters[handle]->filename, charfile ) == 0 &&
(skill < 0 || fabs(botcharacters[handle]->skill - skill) < 0.01) )
{
return handle;
} //end if
} //end for
return 0;
} //end of the function BotFindCachedCharacter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadCachedCharacter(char *charfile, float skill, int reload)
{
int handle, cachedhandle, intskill;
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)
{
BOTPRINT(PRT_MESSAGE, "loaded cached skill %f from %s\n", skill, charfile);
return cachedhandle;
} //end if
} //end else
//
intskill = (int) (skill + 0.5);
//try to load the character with the given skill
ch = BotLoadCharacterFromFile(charfile, intskill);
if (ch)
{
botcharacters[handle] = ch;
//
BOTPRINT(PRT_MESSAGE, "loaded skill %d from %s\n", intskill, charfile);
#ifdef _DEBUG
if (bot_developer)
{
BOTPRINT(PRT_MESSAGE, "skill %d loaded in %d msec from %s\n", intskill, Sys_MilliSeconds() - starttime, charfile);
} //end if
#endif //_DEBUG
return handle;
} //end if
//
BOTPRINT(PRT_WARNING, "couldn't find skill %d in %s\n", intskill, charfile);
//
if (!reload)
{
//try to load a cached default character with the given skill
cachedhandle = BotFindCachedCharacter(DEFAULT_CHARACTER, skill);
if (cachedhandle)
{
BOTPRINT(PRT_MESSAGE, "loaded cached default skill %d from %s\n", intskill, charfile);
return cachedhandle;
} //end if
} //end if
//try to load the default character with the given skill
ch = BotLoadCharacterFromFile(DEFAULT_CHARACTER, intskill);
if (ch)
{
botcharacters[handle] = ch;
BOTPRINT(PRT_MESSAGE, "loaded default skill %d from %s\n", intskill, charfile);
return handle;
} //end if
//
if (!reload)
{
//try to load a cached character with any skill
cachedhandle = BotFindCachedCharacter(charfile, -1);
if (cachedhandle)
{
BOTPRINT(PRT_MESSAGE, "loaded cached skill %f 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;
BOTPRINT(PRT_MESSAGE, "loaded skill %f 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)
{
BOTPRINT(PRT_MESSAGE, "loaded cached default skill %f 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;
BOTPRINT(PRT_MESSAGE, "loaded default skill %f from %s\n", ch->skill, charfile);
return handle;
} //end if
//
BOTPRINT(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, float 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, float 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 - ch1->skill) / (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, float skill)
{
int firstskill, secondskill, handle;
//make sure the skill is in the valid range
if (skill < 1.0) skill = 1.0;
else if (skill > 5.0) skill = 5.0;
//skill 1, 4 and 5 should be available in the character files
if (skill == 1.0 || skill == 4.0 || skill == 5.0)
{
return BotLoadCharacterSkill(charfile, skill);
} //end if
//check if there's a cached skill
handle = BotFindCachedCharacter(charfile, skill);
if (handle)
{
BOTPRINT(PRT_MESSAGE, "loaded cached skill %f from %s\n", skill, charfile);
return handle;
} //end if
if (skill < 4.0)
{
//load skill 1 and 4
firstskill = BotLoadCharacterSkill(charfile, 1);
if (!firstskill) return 0;
secondskill = BotLoadCharacterSkill(charfile, 4);
if (!secondskill) return firstskill;
} //end if
else
{
//load skill 4 and 5
firstskill = BotLoadCharacterSkill(charfile, 4);
if (!firstskill) return 0;
secondskill = BotLoadCharacterSkill(charfile, 5);
if (!secondskill) return firstskill;
} //end else
//interpolate between the two skills
handle = BotInterpolateCharacters(firstskill, secondskill, 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)
{
BOTPRINT(PRT_ERROR, "characteristic %d does not exist\n", index);
return qfalse;
} //end if
if (!ch->c[index].type)
{
BOTPRINT(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
{
BOTPRINT(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)
{
BOTPRINT(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
{
BOTPRINT(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)
{
BOTPRINT(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
{
BOTPRINT(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

48
code/botlib/be_ai_char.h Normal file
View File

@ -0,0 +1,48 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_char.h
*
* desc: bot characters
*
* $Archive: /source/code/botlib/be_ai_char.h $
*
*****************************************************************************/
//loads a bot character from a file
int BotLoadCharacter(char *charfile, float skill);
//frees a bot character
void BotFreeCharacter(int character);
//returns a float characteristic
float Characteristic_Float(int character, int index);
//returns a bounded float characteristic
float Characteristic_BFloat(int character, int index, float min, float max);
//returns an integer characteristic
int Characteristic_Integer(int character, int index);
//returns a bounded integer characteristic
int Characteristic_BInteger(int character, int index, int min, int max);
//returns a string characteristic
void Characteristic_String(int character, int index, char *buf, int size);
//free cached bot characters
void BotShutdownCharacters(void);

3030
code/botlib/be_ai_chat.c Normal file

File diff suppressed because it is too large Load Diff

113
code/botlib/be_ai_chat.h Normal file
View File

@ -0,0 +1,113 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_chat.h
*
* desc: char AI
*
* $Archive: /source/code/botlib/be_ai_chat.h $
*
*****************************************************************************/
#define MAX_MESSAGE_SIZE 256
#define MAX_CHATTYPE_NAME 32
#define MAX_MATCHVARIABLES 8
#define CHAT_GENDERLESS 0
#define CHAT_GENDERFEMALE 1
#define CHAT_GENDERMALE 2
#define CHAT_ALL 0
#define CHAT_TEAM 1
#define CHAT_TELL 2
//a console message
typedef struct bot_consolemessage_s
{
int handle;
float time; //message time
int type; //message type
char message[MAX_MESSAGE_SIZE]; //message
struct bot_consolemessage_s *prev, *next; //prev and next in list
} bot_consolemessage_t;
//match variable
typedef struct bot_matchvariable_s
{
char offset;
int length;
} bot_matchvariable_t;
//returned to AI when a match is found
typedef struct bot_match_s
{
char string[MAX_MESSAGE_SIZE];
int type;
int subtype;
bot_matchvariable_t variables[MAX_MATCHVARIABLES];
} bot_match_t;
//setup the chat AI
int BotSetupChatAI(void);
//shutdown the chat AI
void BotShutdownChatAI(void);
//returns the handle to a newly allocated chat state
int BotAllocChatState(void);
//frees the chatstate
void BotFreeChatState(int handle);
//adds a console message to the chat state
void BotQueueConsoleMessage(int chatstate, int type, char *message);
//removes the console message from the chat state
void BotRemoveConsoleMessage(int chatstate, int handle);
//returns the next console message from the state
int BotNextConsoleMessage(int chatstate, bot_consolemessage_t *cm);
//returns the number of console messages currently stored in the state
int BotNumConsoleMessages(int chatstate);
//selects a chat message of the given type
void BotInitialChat(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
//returns the number of initial chat messages of the given type
int BotNumInitialChats(int chatstate, char *type);
//find and select a reply for the given message
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);
//returns the length of the currently selected chat message
int BotChatLength(int chatstate);
//enters the selected chat message
void BotEnterChat(int chatstate, int clientto, int sendto);
//get the chat message ready to be output
void BotGetChatMessage(int chatstate, char *buf, int size);
//checks if the first string contains the second one, returns index into first string or -1 if not found
int StringContains(char *str1, char *str2, int casesensitive);
//finds a match for the given string using the match templates
int BotFindMatch(char *str, bot_match_t *match, unsigned long int context);
//returns a variable from a match
void BotMatchVariable(bot_match_t *match, int variable, char *buf, int size);
//unify all the white spaces in the string
void UnifyWhiteSpaces(char *string);
//replace all the context related synonyms in the string
void BotReplaceSynonyms(char *string, unsigned long int context);
//loads a chat file for the chat state
int BotLoadChatFile(int chatstate, char *chatfile, char *chatname);
//store the gender of the bot in the chat state
void BotSetChatGender(int chatstate, int gender);
//store the bot name in the chat state
void BotSetChatName(int chatstate, char *name, int client);

135
code/botlib/be_ai_gen.c Normal file
View File

@ -0,0 +1,135 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_gen.c
*
* desc: genetic selection
*
* $Archive: /MissionPack/code/botlib/be_ai_gen.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "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)
{
BOTPRINT(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)
{
BOTPRINT(PRT_WARNING, "GeneticParentsAndChildSelection: too few valid bots\n");
*parent1 = *parent2 = *child = 0;
return qfalse;
} //end if
Com_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

33
code/botlib/be_ai_gen.h Normal file
View File

@ -0,0 +1,33 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_gen.h
*
* desc: genetic selection
*
* $Archive: /source/code/botlib/be_ai_gen.h $
*
*****************************************************************************/
int GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child);

1824
code/botlib/be_ai_goal.c Normal file

File diff suppressed because it is too large Load Diff

118
code/botlib/be_ai_goal.h Normal file
View File

@ -0,0 +1,118 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_goal.h
*
* desc: goal AI
*
* $Archive: /source/code/botlib/be_ai_goal.h $
*
*****************************************************************************/
#define MAX_AVOIDGOALS 256
#define MAX_GOALSTACK 8
#define GFL_NONE 0
#define GFL_ITEM 1
#define GFL_ROAM 2
#define GFL_DROPPED 4
//a bot goal
typedef struct bot_goal_s
{
vec3_t origin; //origin of the goal
int areanum; //area number of the goal
vec3_t mins, maxs; //mins and maxs of the goal
int entitynum; //number of the goal entity
int number; //goal number
int flags; //goal flags
int iteminfo; //item information
} bot_goal_t;
//reset the whole goal state, but keep the item weights
void BotResetGoalState(int goalstate);
//reset avoid goals
void BotResetAvoidGoals(int goalstate);
//remove the goal with the given number from the avoid goals
void BotRemoveFromAvoidGoals(int goalstate, int number);
//push a goal onto the goal stack
void BotPushGoal(int goalstate, bot_goal_t *goal);
//pop a goal from the goal stack
void BotPopGoal(int goalstate);
//empty the bot's goal stack
void BotEmptyGoalStack(int goalstate);
//dump the avoid goals
void BotDumpAvoidGoals(int goalstate);
//dump the goal stack
void BotDumpGoalStack(int goalstate);
//get the name name of the goal with the given number
void BotGoalName(int number, char *name, int size);
//get the top goal from the stack
int BotGetTopGoal(int goalstate, bot_goal_t *goal);
//get the second goal on the stack
int BotGetSecondGoal(int goalstate, bot_goal_t *goal);
//choose the best long term goal item for the bot
int BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags);
//choose the best nearby goal item for the bot
//the item may not be further away from the current bot position than maxtime
//also the travel time from the nearby goal towards the long term goal may not
//be larger than the travel time towards the long term goal from the current bot position
int BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags,
bot_goal_t *ltg, float maxtime);
//returns true if the bot touches the goal
int BotTouchingGoal(vec3_t origin, bot_goal_t *goal);
//returns true if the goal should be visible but isn't
int BotItemGoalInVisButNotVisible(int viewer, vec3_t eye, vec3_t viewangles, bot_goal_t *goal);
//search for a goal for the given classname, the index can be used
//as a start point for the search when multiple goals are available with that same classname
int BotGetLevelItemGoal(int index, char *classname, bot_goal_t *goal);
//get the next camp spot in the map
int BotGetNextCampSpotGoal(int num, bot_goal_t *goal);
//get the map location with the given name
int BotGetMapLocationGoal(char *name, bot_goal_t *goal);
//returns the avoid goal time
float BotAvoidGoalTime(int goalstate, int number);
//set the avoid goal time
void BotSetAvoidGoalTime(int goalstate, int number, float avoidtime);
//initializes the items in the level
void BotInitLevelItems(void);
//regularly update dynamic entity items (dropped weapons, flags etc.)
void BotUpdateEntityItems(void);
//interbreed the goal fuzzy logic
void BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child);
//save the goal fuzzy logic to disk
void BotSaveGoalFuzzyLogic(int goalstate, char *filename);
//mutate the goal fuzzy logic
void BotMutateGoalFuzzyLogic(int goalstate, float range);
//loads item weights for the bot
int BotLoadItemWeights(int goalstate, char *filename);
//frees the item weights of the bot
void BotFreeItemWeights(int goalstate);
//returns the handle of a newly allocated goal state
int BotAllocGoalState(int client);
//free the given goal state
void BotFreeGoalState(int handle);
//setup the goal AI
int BotSetupGoalAI(void);
//shut down the goal AI
void BotShutdownGoalAI(void);

3523
code/botlib/be_ai_move.c Normal file

File diff suppressed because it is too large Load Diff

144
code/botlib/be_ai_move.h Normal file
View File

@ -0,0 +1,144 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_move.h
*
* desc: movement AI
*
* $Archive: /source/code/botlib/be_ai_move.h $
*
*****************************************************************************/
//movement types
#define MOVE_WALK 1
#define MOVE_CROUCH 2
#define MOVE_JUMP 4
#define MOVE_GRAPPLE 8
#define MOVE_ROCKETJUMP 16
#define MOVE_BFGJUMP 32
//move flags
#define MFL_BARRIERJUMP 1 //bot is performing a barrier jump
#define MFL_ONGROUND 2 //bot is in the ground
#define MFL_SWIMMING 4 //bot is swimming
#define MFL_AGAINSTLADDER 8 //bot is against a ladder
#define MFL_WATERJUMP 16 //bot is waterjumping
#define MFL_TELEPORTED 32 //bot is being teleported
#define MFL_GRAPPLEPULL 64 //bot is being pulled by the grapple
#define MFL_ACTIVEGRAPPLE 128 //bot is using the grapple hook
#define MFL_GRAPPLERESET 256 //bot has reset the grapple
#define MFL_WALK 512 //bot should walk slowly
// move result flags
#define MOVERESULT_MOVEMENTVIEW 1 //bot uses view for movement
#define MOVERESULT_SWIMVIEW 2 //bot uses view for swimming
#define MOVERESULT_WAITING 4 //bot is waiting for something
#define MOVERESULT_MOVEMENTVIEWSET 8 //bot has set the view in movement code
#define MOVERESULT_MOVEMENTWEAPON 16 //bot uses weapon for movement
#define MOVERESULT_ONTOPOFOBSTACLE 32 //bot is ontop of obstacle
#define MOVERESULT_ONTOPOF_FUNCBOB 64 //bot is ontop of a func_bobbing
#define MOVERESULT_ONTOPOF_ELEVATOR 128 //bot is ontop of an elevator (func_plat)
#define MOVERESULT_BLOCKEDBYAVOIDSPOT 256 //bot is blocked by an avoid spot
//
#define MAX_AVOIDREACH 1
#define MAX_AVOIDSPOTS 32
// avoid spot types
#define AVOID_CLEAR 0 //clear all avoid spots
#define AVOID_ALWAYS 1 //avoid always
#define AVOID_DONTBLOCK 2 //never totally block
// restult types
#define RESULTTYPE_ELEVATORUP 1 //elevator is up
#define RESULTTYPE_WAITFORFUNCBOBBING 2 //waiting for func bobbing to arrive
#define RESULTTYPE_BADGRAPPLEPATH 4 //grapple path is obstructed
#define RESULTTYPE_INSOLIDAREA 8 //stuck in solid area, this is bad
//structure used to initialize the movement state
//the or_moveflags MFL_ONGROUND, MFL_TELEPORTED and MFL_WATERJUMP come from the playerstate
typedef struct bot_initmove_s
{
vec3_t origin; //origin of the bot
vec3_t velocity; //velocity of the bot
vec3_t viewoffset; //view offset
int entitynum; //entity number of the bot
int client; //client number of the bot
float thinktime; //time the bot thinks
int presencetype; //presencetype of the bot
vec3_t viewangles; //view angles of the bot
int or_moveflags; //values ored to the movement flags
} bot_initmove_t;
//NOTE: the ideal_viewangles are only valid if MFL_MOVEMENTVIEW is set
typedef struct bot_moveresult_s
{
int failure; //true if movement failed all together
int type; //failure or blocked type
int blocked; //true if blocked by an entity
int blockentity; //entity blocking the bot
int traveltype; //last executed travel type
int flags; //result flags
int weapon; //weapon used for movement
vec3_t movedir; //movement direction
vec3_t ideal_viewangles; //ideal viewangles for the movement
} bot_moveresult_t;
#define bot_moveresult_t_cleared(x) bot_moveresult_t (x) = {0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, {0, 0, 0}}
// bk001204: from code/botlib/be_ai_move.c
// TTimo 04/12/2001 was moved here to avoid dup defines
typedef struct bot_avoidspot_s
{
vec3_t origin;
float radius;
int type;
} bot_avoidspot_t;
//resets the whole move state
void BotResetMoveState(int movestate);
//moves the bot to the given goal
void BotMoveToGoal(bot_moveresult_t *result, int movestate, bot_goal_t *goal, int travelflags);
//moves the bot in the specified direction using the specified type of movement
int BotMoveInDirection(int movestate, vec3_t dir, float speed, int type);
//reset avoid reachability
void BotResetAvoidReach(int movestate);
//resets the last avoid reachability
void BotResetLastAvoidReach(int movestate);
//returns a reachability area if the origin is in one
int BotReachabilityArea(vec3_t origin, int client);
//view target based on movement
int BotMovementViewTarget(int movestate, bot_goal_t *goal, int travelflags, float lookahead, vec3_t target);
//predict the position of a player based on movement towards a goal
int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target);
//returns the handle of a newly allocated movestate
int BotAllocMoveState(void);
//frees the movestate with the given handle
void BotFreeMoveState(int handle);
//initialize movement state before performing any movement
void BotInitMoveState(int handle, bot_initmove_t *initmove);
//add a spot to avoid (if type == AVOID_CLEAR all spots are removed)
void BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type);
//must be called every map change
void BotSetBrushModelTypes(void);
//setup movement AI
int BotSetupMoveAI(void);
//shutdown movement AI
void BotShutdownMoveAI(void);

544
code/botlib/be_ai_weap.c Normal file
View File

@ -0,0 +1,544 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weap.c
*
* desc: weapon AI
*
* $Archive: /MissionPack/code/botlib/be_ai_weap.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_ai_weight.h" //fuzzy weights
#include "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 // bk001212 - static
static 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
static 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}
};
static structdef_t weaponinfo_struct =
{
sizeof(weaponinfo_t), weaponinfo_fields
};
static 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;
static bot_weaponstate_t *botweaponstates[MAX_CLIENTS+1];
static weaponconfig_t *weaponconfig;
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
int BotValidWeaponNumber(int weaponnum)
{
if (weaponnum <= 0 || weaponnum > weaponconfig->numweapons)
{
BOTPRINT(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)
{
BOTPRINT(PRT_FATAL, "move state handle %d out of range\n", handle);
return NULL;
} //end if
if (!botweaponstates[handle])
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(PRT_ERROR, "max_projectileinfo = %d\n", max_projectileinfo);
max_projectileinfo = 32;
LibVarSet("max_projectileinfo", "32");
} //end if
strncpy(path, filename, MAX_PATH);
PC_SetBaseFolder(BOTFILESBASEFOLDER);
source = LoadSourceFile(path);
if (!source)
{
BOTPRINT(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"))
{
Com_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)
{
BOTPRINT(PRT_ERROR, "weapon info number %d out of range in %s\n", weaponinfo.number, path);
FreeMemory(wc);
FreeSource(source);
return NULL;
} //end if
Com_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)
{
BOTPRINT(PRT_ERROR, "more than %d projectiles defined in %s\n", max_projectileinfo, path);
FreeMemory(wc);
FreeSource(source);
return NULL;
} //end if
Com_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
{
BOTPRINT(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])
{
BOTPRINT(PRT_ERROR, "weapon %d has no name in %s\n", i, path);
FreeMemory(wc);
return NULL;
} //end if
if (!wc->weaponinfo[i].projectile[0])
{
BOTPRINT(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))
{
Com_Memcpy(&wc->weaponinfo[i].proj, &wc->projectileinfo[j], sizeof(projectileinfo_t));
break;
} //end if
} //end for
if (j == wc->numprojectiles)
{
BOTPRINT(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) BOTPRINT(PRT_WARNING, "no weapon info loaded\n");
BOTPRINT(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)
{
BOTPRINT(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;
Com_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;
//Com_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)
{
BOTPRINT(PRT_FATAL, "move state handle %d out of range\n", handle);
return;
} //end if
if (!botweaponstates[handle])
{
BOTPRINT(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)
{
BOTPRINT(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

104
code/botlib/be_ai_weap.h Normal file
View File

@ -0,0 +1,104 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ai_weap.h
*
* desc: weapon AI
*
* $Archive: /source/code/botlib/be_ai_weap.h $
*
*****************************************************************************/
//projectile flags
#define PFL_WINDOWDAMAGE 1 //projectile damages through window
#define PFL_RETURN 2 //set when projectile returns to owner
//weapon flags
#define WFL_FIRERELEASED 1 //set when projectile is fired with key-up event
//damage types
#define DAMAGETYPE_IMPACT 1 //damage on impact
#define DAMAGETYPE_RADIAL 2 //radial damage
#define DAMAGETYPE_VISIBLE 4 //damage to all entities visible to the projectile
typedef struct projectileinfo_s
{
char name[MAX_STRINGFIELD];
char model[MAX_STRINGFIELD];
int flags;
float gravity;
int damage;
float radius;
int visdamage;
int damagetype;
int healthinc;
float push;
float detonation;
float bounce;
float bouncefric;
float bouncestop;
} projectileinfo_t;
typedef struct weaponinfo_s
{
int valid; //true if the weapon info is valid
int number; //number of the weapon
char name[MAX_STRINGFIELD];
char model[MAX_STRINGFIELD];
int level;
int weaponindex;
int flags;
char projectile[MAX_STRINGFIELD];
int numprojectiles;
float hspread;
float vspread;
float speed;
float acceleration;
vec3_t recoil;
vec3_t offset;
vec3_t angleoffset;
float extrazvelocity;
int ammoamount;
int ammoindex;
float activate;
float reload;
float spinup;
float spindown;
projectileinfo_t proj; //pointer to the used projectile
} weaponinfo_t;
//setup the weapon AI
int BotSetupWeaponAI(void);
//shut down the weapon AI
void BotShutdownWeaponAI(void);
//returns the best weapon to fight with
int BotChooseBestFightWeapon(int weaponstate, int *inventory);
//returns the information of the current weapon
void BotGetWeaponInfo(int weaponstate, int weapon, weaponinfo_t *weaponinfo);
//loads the weapon weights
int BotLoadWeaponWeights(int weaponstate, char *filename);
//returns a handle to a newly allocated weapon state
int BotAllocWeaponState(void);
//frees the weapon state
void BotFreeWeaponState(int weaponstate);
//resets the whole weapon state
void BotResetWeaponState(int weaponstate);

913
code/botlib/be_ai_weight.c Normal file
View File

@ -0,0 +1,913 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weight.c
*
* desc: fuzzy logic
*
* $Archive: /MissionPack/code/botlib/be_ai_weight.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "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 )
{
//BOTPRINT( PRT_MESSAGE, "retained %s\n", filename );
return config;
} //end if
} //end for
if( avail == -1 )
{
BOTPRINT( PRT_ERROR, "weightFileList was full trying to load %s\n", filename );
return NULL;
} //end if
} //end if
PC_SetBaseFolder(BOTFILESBASEFOLDER);
source = LoadSourceFile(filename);
if (!source)
{
BOTPRINT(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
BOTPRINT(PRT_MESSAGE, "loaded %s\n", filename);
#ifdef _DEBUG
if (bot_developer)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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)
{
BOTPRINT(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

View File

@ -0,0 +1,84 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_weight.h
*
* desc: fuzzy weights
*
* $Archive: /source/code/botlib/be_ai_weight.h $
*
*****************************************************************************/
#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);

510
code/botlib/be_ea.c Normal file
View File

@ -0,0 +1,510 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ea.c
*
* desc: elementary actions
*
* $Archive: /MissionPack/code/botlib/be_ea.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "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_Tell(int client, int clientto, char *str)
{
botimport.BotClientCommand(client, va("tell %d, %s", clientto, 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_Talk(int client)
{
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= ACTION_TALK;
} //end of the function EA_Talk
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
//No more EA_Use, useable items have been dropped
/*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_Action(int client, int action)
{
bot_input_t *bi;
bi = &botinputs[client];
bi->actionflags |= action;
} //end of function EA_Action
//===========================================================================
//
// 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;
Com_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 *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;
} //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

65
code/botlib/be_ea.h Normal file
View File

@ -0,0 +1,65 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: be_ea.h
*
* desc: elementary actions
*
* $Archive: /source/code/botlib/be_ea.h $
*
*****************************************************************************/
//ClientCommand elementary actions
void EA_Say(int client, char *str);
void EA_SayTeam(int client, char *str);
void EA_Command(int client, char *command );
void EA_Action(int client, int action);
void EA_Crouch(int client);
void EA_Walk(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_Attack(int client);
void EA_Respawn(int client);
void EA_Talk(int client);
void EA_Gesture(int client);
//regular elementary actions
void EA_SelectWeapon(int client, int weapon);
void EA_Jump(int client);
void EA_DelayedJump(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);
//setup and shutdown routines
int EA_Setup(void);
void EA_Shutdown(void);

880
code/botlib/be_interface.c Normal file
View File

@ -0,0 +1,880 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_interface.c // bk010221 - FIXME - DEAD code elimination
*
* desc: bot library interface
*
* $Archive: /MissionPack/code/botlib/be_interface.c $
*
*****************************************************************************/
#include "../qcommon/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 "botlib.h"
#include "be_aas.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"
#include "be_interface.h"
#include "be_ea.h"
#include "be_ai_weight.h"
#include "be_ai_goal.h"
#include "be_ai_move.h"
#include "be_ai_weap.h"
#include "be_ai_chat.h"
#include "be_ai_char.h"
#include "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;
//===========================================================================
//
// several functions used by the exported functions
//
//===========================================================================
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Sys_MilliSeconds(void)
{
return clock() * 1000 / CLOCKS_PER_SEC;
} //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
BOTPRINT(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)
{
BOTPRINT(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)
{
if (!botlibglobals.botlibsetup)
{
BOTPRINT(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");
memset( &botlibglobals, 0, sizeof(botlibglobals) ); // bk001207 - init
//initialize byte swapping (litte endian etc.)
// Swap_Init();
#ifdef _DEBUG
Log_Open("botlib.log");
#endif
//
BOTPRINT(PRT_MESSAGE, "------- BotLib Initialization -------\n");
//
botlibglobals.maxclients = (int) LibVarValue("maxclients", "128");
botlibglobals.maxentities = (int) LibVarValue("maxentities", "1024");
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;
botlibglobals.botlibsetup = qtrue;
return BLERR_NOERROR;
} //end of the function Export_BotLibSetup
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Export_BotLibShutdown(void)
{
if (!BotLibSetup("BotLibShutdown")) return BLERR_LIBRARYNOTSETUP;
#ifndef DEMO
//DumpFileCRCs();
#endif //DEMO
//
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
//shud down aas
AAS_Shutdown();
//shut down bot elemantary actions
EA_Shutdown();
//free all libvars
LibVarDeAllocAll();
//remove all global defines from the pre compiler
PC_RemoveAllGlobalDefines();
//dump all allocated memory
// DumpMemory();
#ifdef _DEBUG
PrintMemoryLabels();
#endif
//shut down library log file
Log_Shutdown();
//
botlibglobals.botlibsetup = qfalse;
// print any files still open
PC_CheckOpenSourceHandles();
//
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( void *pAasData, const char *mapname )
{
#ifdef _DEBUG
int starttime = Sys_MilliSeconds();
#endif
int errnum;
if (!BotLibSetup("BotLoadMap")) return BLERR_LIBRARYNOTSETUP;
//
BOTPRINT(PRT_MESSAGE, "------------ Map Loading ------------\n");
//startup AAS for the current map, model and sound index
errnum = AAS_LoadMap( pAasData, mapname );
if (errnum != BLERR_NOERROR) return errnum;
//initialize the items in the level
BotInitLevelItems(); //be_ai_goal.h
BotSetBrushModelTypes(); //be_ai_move.h
//
BOTPRINT(PRT_MESSAGE, "-------------------------------------\n");
#ifdef _DEBUG
BOTPRINT(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 lastgoalareanum, int lastareanum,
int *avoidreach, float *avoidreachtimes, int *avoidreachtries,
bot_goal_t *goal, int travelflags, int movetravelflags,
struct bot_avoidspot_s *avoidspots, int numavoidspots, int *flags);
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);
void AAS_FloodAreas(vec3_t origin);
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, flood;
// 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;
//Scott: commented out as they were unused.
//vec3_t mins = {-16, -16, -24};
//vec3_t maxs = {16, 16, 32};
// int areas[10], numareas;
//return 0;
if (!aasworld.loaded) return 0;
/*
if (parm0 & 1)
{
AAS_ClearShownPolygons();
AAS_FloodAreas(parm2);
} //end if
return 0;
*/
for (i = 0; i < 2; i++) if (!line[i]) line[i] = botimport.DebugLineCreate();
// AAS_ClearShownDebugLines();
//if (AAS_AgainstLadder(parm2)) BOTPRINT(PRT_MESSAGE, "against ladder\n");
//BotOnGround(parm2, PRESENCE_NORMAL, 1, &newarea, &newarea);
//BOTPRINT(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
BOTPRINT(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)
{
BOTPRINT(PRT_MESSAGE, "origin = %f, %f, %f\n", origin[0], origin[1], origin[2]);
area = newarea;
BOTPRINT(PRT_MESSAGE, "new area %d, cluster %d, presence type %d\n",
area, AAS_AreaCluster(area), AAS_PointPresenceType(origin));
BOTPRINT(PRT_MESSAGE, "area contents: ");
if (aasworld.areasettings[area].contents & AREACONTENTS_WATER)
{
BOTPRINT(PRT_MESSAGE, "water &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_LAVA)
{
BOTPRINT(PRT_MESSAGE, "lava &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_SLIME)
{
BOTPRINT(PRT_MESSAGE, "slime &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_JUMPPAD)
{
BOTPRINT(PRT_MESSAGE, "jump pad &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_CLUSTERPORTAL)
{
BOTPRINT(PRT_MESSAGE, "cluster portal &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_VIEWPORTAL)
{
BOTPRINT(PRT_MESSAGE, "view portal &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_DONOTENTER)
{
BOTPRINT(PRT_MESSAGE, "do not enter &");
} //end if
if (aasworld.areasettings[area].contents & AREACONTENTS_MOVER)
{
BOTPRINT(PRT_MESSAGE, "mover &");
} //end if
if (!aasworld.areasettings[area].contents)
{
BOTPRINT(PRT_MESSAGE, "empty");
} //end if
BOTPRINT(PRT_MESSAGE, "\n");
BOTPRINT(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);
BOTPRINT(PRT_MESSAGE, "num areas = %d, area = %d\n", numareas, areas[0]);
*/
/*
botlibglobals.goalareanum = newarea;
VectorCopy(parm2, botlibglobals.goalorigin);
BOTPRINT(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea);
*/
} //end if
//*
flood = LibVarGetValue("bot_flood");
if (parm0 & 1)
{
if (flood)
{
AAS_ClearShownPolygons();
AAS_ClearShownDebugLines();
AAS_FloodAreas(parm2);
}
else
{
botlibglobals.goalareanum = newarea;
VectorCopy(parm2, botlibglobals.goalorigin);
BOTPRINT(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
origin[0], origin[1], origin[2], newarea);
}
} //end if*/
if (flood)
return 0;
// if (parm0 & BUTTON_USE)
// {
// botlibglobals.runai = !botlibglobals.runai;
// if (botlibglobals.runai) BOTPRINT(PRT_MESSAGE, "started AI\n");
// else BOTPRINT(PRT_MESSAGE, "stopped AI\n");
//* /
/*
goal.areanum = botlibglobals.goalareanum;
reachnum = BotGetReachabilityToGoal(parm2, newarea, 1,
ms.avoidreach, ms.avoidreachtimes,
&goal, TFL_DEFAULT);
if (!reachnum)
{
BOTPRINT(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 & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR)
{
ElevatorBottomCenter(&reach, bottomcenter);
AAS_DrawCross(bottomcenter, 10, LINECOLOR_GREEN);
} //end if
} //end else*/
// BOTPRINT(PRT_MESSAGE, "travel time to goal = %d\n",
// AAS_AreaTravelTimeToGoalArea(area, origin, botlibglobals.goalareanum, TFL_DEFAULT));
// BOTPRINT(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, resultFlags;
bot_goal_t goal;
aas_reachability_t reach;
/*
goal.areanum = botlibglobals.goalareanum;
VectorCopy(botlibglobals.goalorigin, goal.origin);
reachnum = BotGetReachabilityToGoal(origin, newarea,
lastgoalareanum, lastareanum,
avoidreach, avoidreachtimes, avoidreachtries,
&goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
NULL, 0, &resultFlags);
AAS_ReachabilityFromNum(reachnum, &reach);
AAS_ShowReachability(&reach);
*/
int curarea;
vec3_t curorigin;
goal.areanum = botlibglobals.goalareanum;
VectorCopy(botlibglobals.goalorigin, goal.origin);
VectorCopy(origin, curorigin);
curarea = newarea;
for ( i = 0; i < 100; i++ ) {
if ( curarea == goal.areanum ) {
break;
}
reachnum = BotGetReachabilityToGoal(curorigin, curarea,
lastgoalareanum, lastareanum,
avoidreach, avoidreachtimes, avoidreachtries,
&goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
NULL, 0, &resultFlags);
AAS_ReachabilityFromNum(reachnum, &reach);
AAS_ShowReachability(&reach);
VectorCopy(reach.end, origin);
lastareanum = curarea;
curarea = reach.areanum;
}
} //end else
VectorClear(forward);
//BotGapDistance(origin, forward, 0);
/*
if (parm0 & BUTTON_USE)
{
BOTPRINT(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();
BOTPRINT(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();
BOTPRINT(PRT_MESSAGE, "id %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
*/
// TTimo: nested comments are BAD for gcc -Werror, use #if 0 instead..
#if 0
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
#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_PointReachabilityAreaIndex = AAS_PointReachabilityAreaIndex;
aas->AAS_TraceAreas = AAS_TraceAreas;
aas->AAS_BBoxAreas = AAS_BBoxAreas;
aas->AAS_AreaInfo = AAS_AreaInfo;
//--------------------------------------------
// 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;
aas->AAS_EnableRoutingArea = AAS_EnableRoutingArea;
aas->AAS_PredictRoute = AAS_PredictRoute;
//--------------------------------------------
// be_aas_altroute.c
//--------------------------------------------
aas->AAS_AlternativeRouteGoals = AAS_AlternativeRouteGoals;
//--------------------------------------------
// be_aas_move.c
//--------------------------------------------
aas->AAS_Swimming = AAS_Swimming;
aas->AAS_PredictClientMovement = AAS_PredictClientMovement;
}
/*
============
Init_EA_Export
============
*/
static void Init_EA_Export( ea_export_t *ea ) {
//ClientCommand elementary actions
ea->EA_Command = EA_Command;
ea->EA_Say = EA_Say;
ea->EA_SayTeam = EA_SayTeam;
ea->EA_Action = EA_Action;
ea->EA_Gesture = EA_Gesture;
ea->EA_Talk = EA_Talk;
ea->EA_Attack = EA_Attack;
ea->EA_Respawn = EA_Respawn;
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_SelectWeapon = EA_SelectWeapon;
ea->EA_Jump = EA_Jump;
ea->EA_DelayedJump = EA_DelayedJump;
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->BotSetAvoidGoalTime = BotSetAvoidGoalTime;
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;
ai->BotAddAvoidSpot = BotAddAvoidSpot;
//-----------------------------------
// 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) {
assert(import); // bk001129 - this wasn't set for baseq3/
botimport = *import;
assert(botimport.Print); // bk001129 - pars pro toto
Com_Memset( &be_botlib_export, 0, sizeof( be_botlib_export ) );
if ( apiVersion != BOTLIB_API_VERSION ) {
BOTPRINT( 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;
}

View File

@ -0,0 +1,57 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_interface.h
*
* desc: botlib interface
*
* $Archive: /source/code/botlib/be_interface.h $
*
*****************************************************************************/
#define RANDOMIZE //randomize bot behaviour
//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;
extern botlib_globals_t botlibglobals;
extern botlib_import_t botimport;
extern int bot_developer; //true if developer is on
//
int Sys_MilliSeconds(void);

522
code/botlib/botlib.h Normal file
View File

@ -0,0 +1,522 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: botlib.h
*
* desc: bot AI library
*
* $Archive: /source/code/game/botai.h $
*
*****************************************************************************/
#define BOTLIB_API_VERSION 2
struct aas_clientmove_s;
struct aas_entityinfo_s;
struct aas_areainfo_s;
struct aas_altroutegoal_s;
struct aas_predictroute_s;
struct bot_consolemessage_s;
struct bot_match_s;
struct bot_goal_s;
struct bot_moveresult_s;
struct bot_initmove_s;
struct weaponinfo_s;
#ifdef __GNUC__
#define BOTPRINT(...)
#else
//shuts up some unref'd param warnings under VC to do it this way
#define BOTPRINT
#endif
#define BOTFILESBASEFOLDER "botfiles"
//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_INVALIDENTITYNUMBER 2 //invalid entity number
#define BLERR_NOAASFILE 3 //no AAS file available
#define BLERR_CANNOTOPENAASFILE 4 //cannot open AAS file
#define BLERR_WRONGAASFILEID 5 //incorrect AAS file id
#define BLERR_WRONGAASFILEVERSION 6 //incorrect AAS file version
#define BLERR_CANNOTREADAASLUMP 7 //cannot read AAS file lump
#define BLERR_CANNOTLOADICHAT 8 //cannot load initial chats
#define BLERR_CANNOTLOADITEMWEIGHTS 9 //cannot load item weights
#define BLERR_CANNOTLOADITEMCONFIG 10 //cannot load item config
#define BLERR_CANNOTLOADWEAPONWEIGHTS 11 //cannot load weapon weights
#define BLERR_CANNOTLOADWEAPONCONFIG 12 //cannot load weapon config
//action flags
#define ACTION_ATTACK 0x0000001
#define ACTION_GRENADE 0x0000002
#define ACTION_RESPAWN 0x0000008
#define ACTION_JUMP 0x0000010
#define ACTION_MOVEUP 0x0000020
#define ACTION_CROUCH 0x0000080
#define ACTION_MOVEDOWN 0x0000100
#define ACTION_MOVEFORWARD 0x0000200
#define ACTION_MOVEBACK 0x0000800
#define ACTION_MOVELEFT 0x0001000
#define ACTION_MOVERIGHT 0x0002000
#define ACTION_DELAYEDJUMP 0x0008000
#define ACTION_TALK 0x0010000
#define ACTION_GESTURE 0x0020000
#define ACTION_WALK 0x0080000
#define ACTION_AFFIRMATIVE 0x0100000
#define ACTION_NEGATIVE 0x0200000
#define ACTION_GETFLAG 0x0800000
#define ACTION_GUARDBASE 0x1000000
#define ACTION_PATROL 0x2000000
#define ACTION_FOLLOWME 0x8000000
//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
#define 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;
#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 shields; // bit flags
int weapon; // determines weapon and flash model, etc
int legsAnim;
int torsoAnim;
} 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); // allocate from Zone
void (*FreeMemory)(void *ptr); // free memory from Zone
int (*AvailableMemory)(void); // available Zone memory
void *(*HunkAlloc)(int size); // allocate from hunk
//file system access
int (Q_EXTERNAL_CALL *FS_FOpenFile)( const char *qpath, fileHandle_t *file, fsMode_t mode );
int (Q_EXTERNAL_CALL *FS_Read)( void *buffer, int len, fileHandle_t f );
int (Q_EXTERNAL_CALL *FS_Write)( const void *buffer, int len, fileHandle_t f );
void (Q_EXTERNAL_CALL *FS_FCloseFile)( fileHandle_t f );
int (Q_EXTERNAL_CALL *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);
} 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_PointReachabilityAreaIndex)( vec3_t point );
int (*AAS_TraceAreas)(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
int (*AAS_BBoxAreas)(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
int (*AAS_AreaInfo)( int areanum, struct aas_areainfo_s *info );
//--------------------------------------------
// 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);
int (*AAS_EnableRoutingArea)(int areanum, int enable);
int (*AAS_PredictRoute)(struct aas_predictroute_s *route, int areanum, vec3_t origin,
int goalareanum, int travelflags, int maxareas, int maxtime,
int stopevent, int stopcontents, int stoptfl, int stopareanum);
//--------------------------------------------
// be_aas_altroute.c
//--------------------------------------------
int (*AAS_AlternativeRouteGoals)(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
struct aas_altroutegoal_s *altroutegoals, int maxaltroutegoals,
int type);
//--------------------------------------------
// 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);
} aas_export_t;
typedef struct ea_export_s
{
//ClientCommand elementary actions
void (*EA_Command)(int client, char *command );
void (*EA_Say)(int client, char *str);
void (*EA_SayTeam)(int client, char *str);
//
void (*EA_Action)(int client, int action);
void (*EA_Gesture)(int client);
void (*EA_Talk)(int client);
void (*EA_Attack)(int client);
void (*EA_Respawn)(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_Crouch)(int client);
void (*EA_SelectWeapon)(int client, int weapon);
void (*EA_Jump)(int client);
void (*EA_DelayedJump)(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);
} ea_export_t;
typedef struct ai_export_s
{
//-----------------------------------
// be_ai_char.h
//-----------------------------------
int (*BotLoadCharacter)(char *charfile, float 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, int client);
//-----------------------------------
// 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 (*BotSetAvoidGoalTime)(int goalstate, int number, float avoidtime);
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);
void (*BotAddAvoidSpot)(int movestate, vec3_t origin, float radius, int type);
//-----------------------------------
// 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 (*PC_AddGlobalDefine)(char *string);
int (*PC_LoadSourceHandle)(const char *filename);
int (*PC_FreeSourceHandle)(int handle);
int (*PC_ReadTokenHandle)(int handle, pc_token_t *pc_token);
int (*PC_SourceFileAndLine)(int handle, char *filename, int *line);
//start a frame in the bot library
int (*BotLibStartFrame)(float time);
//load a new map in the bot library
int (*BotLibLoadMap)( void *pAasData, 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 base directory
"gamedir" "" l_utils.c game directory
"cddir" "" l_utils.c CD directory
"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
"bot_developer" "0" be_interface.c bot developer mode
"phys_friction" "6" be_aas_move.c ground friction
"phys_stopspeed" "100" be_aas_move.c stop speed
"phys_gravity" "800" be_aas_move.c gravity value
"phys_waterfriction" "1" be_aas_move.c water friction
"phys_watergravity" "400" be_aas_move.c gravity in water
"phys_maxvelocity" "320" be_aas_move.c maximum velocity
"phys_maxwalkvelocity" "320" be_aas_move.c maximum walk velocity
"phys_maxcrouchvelocity" "100" be_aas_move.c maximum crouch velocity
"phys_maxswimvelocity" "150" be_aas_move.c maximum swim velocity
"phys_walkaccelerate" "10" be_aas_move.c walk acceleration
"phys_airaccelerate" "1" be_aas_move.c air acceleration
"phys_swimaccelerate" "4" be_aas_move.c swim acceleration
"phys_maxstep" "18" be_aas_move.c maximum step height
"phys_maxsteepness" "0.7" be_aas_move.c maximum floor steepness
"phys_maxbarrier" "32" be_aas_move.c maximum barrier height
"phys_maxwaterjump" "19" be_aas_move.c maximum waterjump height
"phys_jumpvel" "270" be_aas_move.c jump z velocity
"phys_falldelta5" "40" be_aas_move.c
"phys_falldelta10" "60" be_aas_move.c
"rs_waterjump" "400" be_aas_move.c
"rs_teleport" "50" be_aas_move.c
"rs_barrierjump" "100" be_aas_move.c
"rs_startcrouch" "300" be_aas_move.c
"rs_startgrapple" "500" be_aas_move.c
"rs_startwalkoffledge" "70" be_aas_move.c
"rs_startjump" "300" be_aas_move.c
"rs_rocketjump" "500" be_aas_move.c
"rs_bfgjump" "500" be_aas_move.c
"rs_jumppad" "250" be_aas_move.c
"rs_aircontrolledjumppad" "300" be_aas_move.c
"rs_funcbob" "300" be_aas_move.c
"rs_startelevator" "50" be_aas_move.c
"rs_falldamage5" "300" be_aas_move.c
"rs_falldamage10" "500" be_aas_move.c
"rs_maxjumpfallheight" "450" be_aas_move.c
"max_aaslinks" "4096" be_aas_sample.c maximum links in the AAS
"max_routingcache" "4096" be_aas_route.c maximum routing cache size in KB
"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
"aasoptimize" "0" be_aas_main.c enable aas optimization
"sv_mapChecksum" "0" be_aas_main.c BSP file checksum
"bot_visualizejumppads" "0" be_aas_reach.c visualize jump pads
"bot_reloadcharacters" "0" - reload bot character files
"ai_gametype" "0" be_ai_goal.c game type
"droppedweight" "1000" be_ai_goal.c additional dropped item weight
"weapindex_rocketlauncher" "5" be_ai_move.c rl weapon index for rocket jumping
"weapindex_bfg10k" "9" be_ai_move.c bfg weapon index for bfg jumping
"weapindex_grapple" "10" be_ai_move.c grapple weapon index for grappling
"entitytypemissile" "3" be_ai_move.c ET_MISSILE
"offhandgrapple" "0" be_ai_move.c enable off hand grapple hook
"cmd_grappleon" "grappleon" be_ai_move.c command to activate off hand grapple
"cmd_grappleoff" "grappleoff" be_ai_move.c command to deactivate off hand grapple
"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
"nochat" "0" be_ai_chat.c disable chats
"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
*/

View File

@ -0,0 +1,497 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="botlib"
ProjectGUID="{A410161F-AE9F-485D-A01F-5294891430A6}"
RootNamespace="botlib"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)lib\$(ProjectName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="4"
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"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="BOTLIB"
RuntimeLibrary="1"
BrowseInformationFile=""
WarningLevel="4"
WarnAsError="true"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)lib\$(ProjectName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="4"
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"
AdditionalIncludeDirectories="&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="BOTLIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
RuntimeTypeInfo="false"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Final Release|Win32"
OutputDirectory="$(SolutionDir)lib\$(ProjectName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)obj\$(ProjectName)\$(ConfigurationName)"
ConfigurationType="4"
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"
AdditionalIncludeDirectories="&quot;$(SolutionDir)$(PlatformName)&quot;"
PreprocessorDefinitions="BOTLIB"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
RuntimeTypeInfo="false"
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CallingConvention="1"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<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"
>
</File>
<File
RelativePath="be_aas_cluster.c"
>
</File>
<File
RelativePath="be_aas_debug.c"
>
</File>
<File
RelativePath="be_aas_entity.c"
>
</File>
<File
RelativePath="be_aas_file.c"
>
</File>
<File
RelativePath="be_aas_main.c"
>
</File>
<File
RelativePath="be_aas_move.c"
>
</File>
<File
RelativePath="be_aas_optimize.c"
>
</File>
<File
RelativePath="be_aas_reach.c"
>
</File>
<File
RelativePath="be_aas_route.c"
>
</File>
<File
RelativePath="be_aas_routealt.c"
>
</File>
<File
RelativePath="be_aas_sample.c"
>
</File>
<File
RelativePath="be_ai_char.c"
>
</File>
<File
RelativePath="be_ai_chat.c"
>
</File>
<File
RelativePath="be_ai_gen.c"
>
</File>
<File
RelativePath="be_ai_goal.c"
>
</File>
<File
RelativePath="be_ai_move.c"
>
</File>
<File
RelativePath="be_ai_weap.c"
>
</File>
<File
RelativePath="be_ai_weight.c"
>
</File>
<File
RelativePath="be_ea.c"
>
</File>
<File
RelativePath="be_interface.c"
>
</File>
<File
RelativePath="l_crc.c"
>
</File>
<File
RelativePath="l_libvar.c"
>
</File>
<File
RelativePath="l_log.c"
>
</File>
<File
RelativePath="l_memory.c"
>
</File>
<File
RelativePath="l_precomp.c"
>
</File>
<File
RelativePath="l_script.c"
>
</File>
<File
RelativePath="l_struct.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath="aasfile.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_sample.h"
>
</File>
<File
RelativePath="be_ai_weight.h"
>
</File>
<File
RelativePath="be_interface.h"
>
</File>
<File
RelativePath="..\game\bg_public.h"
>
</File>
<File
RelativePath="..\qcommon\cm_public.h"
>
</File>
<File
RelativePath="..\game\g_public.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="..\qcommon\qcommon.h"
>
</File>
<File
RelativePath="..\qcommon\qfiles.h"
>
</File>
<File
RelativePath="..\server\server.h"
>
</File>
<File
RelativePath="..\game\surfaceflags.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

148
code/botlib/l_crc.c Normal file
View File

@ -0,0 +1,148 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_crc.c
*
* desc: CRC calculation
*
* $Archive: /MissionPack/CODE/botlib/l_crc.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "botlib.h"
#include "be_interface.h" //for BOTPRINT
// 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
static const 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
};
//===========================================================================
//
// 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

30
code/botlib/l_crc.h Normal file
View File

@ -0,0 +1,30 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
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);

295
code/botlib/l_libvar.c Normal file
View File

@ -0,0 +1,295 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_libvar.c
*
* desc: bot library variables
*
* $Archive: /MissionPack/code/botlib/l_libvar.c $
*
*****************************************************************************/
#include "../qcommon/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);
Com_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

64
code/botlib/l_libvar.h Normal file
View File

@ -0,0 +1,64 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_libvar.h
*
* desc: botlib vars
*
* $Archive: /source/code/botlib/l_libvar.h $
*
*****************************************************************************/
//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);

166
code/botlib/l_log.c Normal file
View File

@ -0,0 +1,166 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_log.c
*
* desc: log file
*
* $Archive: /MissionPack/CODE/botlib/l_log.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "botlib.h"
#include "be_interface.h" //for BOTPRINT
#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_Open(char *filename)
{
if (!LibVarValue("log", "0")) return;
if (!filename || !strlen(filename))
{
BOTPRINT(PRT_MESSAGE, "openlog <filename>\n");
return;
} //end if
if (logfile.fp)
{
BOTPRINT(PRT_ERROR, "log file %s is already opened\n", logfile.filename);
return;
} //end if
logfile.fp = fopen(filename, "wb");
if (!logfile.fp)
{
BOTPRINT(PRT_ERROR, "can't open the log file %s\n", filename);
return;
} //end if
strncpy(logfile.filename, filename, MAX_LOGFILENAMESIZE);
BOTPRINT(PRT_MESSAGE, "Opened log %s\n", logfile.filename);
} //end of the function Log_Create
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Log_Close(void)
{
if (!logfile.fp) return;
if (fclose(logfile.fp))
{
BOTPRINT(PRT_ERROR, "can't close log file %s\n", logfile.filename);
return;
} //end if
logfile.fp = NULL;
BOTPRINT(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

47
code/botlib/l_log.h Normal file
View File

@ -0,0 +1,47 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_log.h
*
* desc: log file
*
* $Archive: /source/code/botlib/l_log.h $
*
*****************************************************************************/
//open a log file
void Log_Open(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);

464
code/botlib/l_memory.c Normal file
View File

@ -0,0 +1,464 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_memory.c
*
* desc: memory allocation
*
* $Archive: /MissionPack/code/botlib/l_memory.c $
*
*****************************************************************************/
#include "../qcommon/q_shared.h"
#include "botlib.h"
#include "l_log.h"
#include "be_interface.h"
//#define MEMDEBUG
//#define MEMORYMANEGER
#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;
assert(botimport.GetMemory); // bk001129 - was NULL'ed
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
Com_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
Com_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;
BOTPRINT(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)
{
BOTPRINT(PRT_FATAL, "%s: invalid memory block\n", str);
return NULL;
} //end if
if (block->ptr != ptr)
{
BOTPRINT(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 AvailableMemory(void)
{
return botimport.AvailableMemory();
} //end of the function AvailableMemory
//===========================================================================
//
// 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)
{
BOTPRINT(PRT_MESSAGE, "total allocated memory: %d KB\n", allocatedmemory >> 10);
BOTPRINT(PRT_MESSAGE, "total botlib memory: %d KB\n", totalmemorysize >> 10);
BOTPRINT(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("============= Botlib memory log ==============\r\n");
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
Com_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
Com_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: -
//===========================================================================
int AvailableMemory(void)
{
return botimport.AvailableMemory();
} //end of the function AvailableMemory
//===========================================================================
//
// 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

77
code/botlib/l_memory.h Normal file
View File

@ -0,0 +1,77 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_memory.h
*
* desc: memory management
*
* $Archive: /source/code/botlib/l_memory.h $
*
*****************************************************************************/
//#define MEMDEBUG
#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);
//returns the amount available memory
int AvailableMemory(void);
//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);

3219
code/botlib/l_precomp.c Normal file

File diff suppressed because it is too large Load Diff

181
code/botlib/l_precomp.h Normal file
View File

@ -0,0 +1,181 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_precomp.h
*
* desc: pre compiler
*
* $Archive: /source/code/botlib/l_precomp.h $
*
*****************************************************************************/
#ifndef MAX_PATH
#define MAX_PATH MAX_QPATH
#endif
#ifndef PATH_SEPERATORSTR
#if 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(__NT__)|defined(__WINDOWS__)|defined(__WINDOWS_386__)
#define PATHSEPERATOR_CHAR '\\'
#else
#define PATHSEPERATOR_CHAR '/'
#endif
#endif
#if defined(BSPC) && !defined(QDECL)
#define QDECL
#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[1024]; //file name of the script
char includepath[1024]; //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, pc_token_t *pc_token);
int PC_SourceFileAndLine(int handle, char *filename, int *line);
void PC_CheckOpenSourceHandles(void);

1429
code/botlib/l_script.c Normal file

File diff suppressed because it is too large Load Diff

248
code/botlib/l_script.h Normal file
View File

@ -0,0 +1,248 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_script.h
*
* desc: lexicographical parser
*
* $Archive: /source/code/botlib/l_script.h $
*
*****************************************************************************/
//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
#if defined(BSPC) && !defined(QDECL)
#define QDECL
#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
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[1024]; //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
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, ...);

463
code/botlib/l_struct.c Normal file
View File

@ -0,0 +1,463 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_struct.c
*
* desc: structure reading / writing
*
* $Archive: /MissionPack/CODE/botlib/l_struct.c $
*
*****************************************************************************/
#ifdef BOTLIB
#include "../qcommon/q_shared.h"
#include "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: -
//===========================================================================
const fielddef_t *FindField(const 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, const 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, const 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, const 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, const structdef_t *def, char *structure)
{
token_t token;
const 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;
const 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

76
code/botlib/l_struct.h Normal file
View File

@ -0,0 +1,76 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_struct.h
*
* desc: structure reading/writing
*
* $Archive: /source/code/botlib/l_struct.h $
*
*****************************************************************************/
#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;
const fielddef_t *fields;
} structdef_t;
//read a structure from a script
int ReadStructure(source_t *source, const 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);

38
code/botlib/l_utils.h Normal file
View File

@ -0,0 +1,38 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of the Space Trader source code.
The Space Trader 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 2 of the License,
or (at your option) any later version.
The Space Trader 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 the Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: l_util.h
*
* desc: utils
*
* $Archive: /source/code/botlib/l_util.h $
*
*****************************************************************************/
#define Vector2Angles(v,a) vectoangles(v,a)
#ifndef MAX_PATH
#define MAX_PATH MAX_QPATH
#endif
#define Maximum(x,y) (x > y ? x : y)
#define Minimum(x,y) (x < y ? x : y)

55
code/botlib/lcc.mak Normal file
View File

@ -0,0 +1,55 @@
#
# Makefile for Gladiator Bot library: gladiator.dll
# Intended for LCC-Win32
#
CC=lcc
CFLAGS=-DC_ONLY -o
OBJS= be_aas_bspq2.obj \
be_aas_bsphl.obj \
be_aas_cluster.obj \
be_aas_debug.obj \
be_aas_entity.obj \
be_aas_file.obj \
be_aas_light.obj \
be_aas_main.obj \
be_aas_move.obj \
be_aas_optimize.obj \
be_aas_reach.obj \
be_aas_route.obj \
be_aas_routealt.obj \
be_aas_sample.obj \
be_aas_sound.obj \
be_ai2_dm.obj \
be_ai2_dmnet.obj \
be_ai2_main.obj \
be_ai_char.obj \
be_ai_chat.obj \
be_ai_goal.obj \
be_ai_load.obj \
be_ai_move.obj \
be_ai_weap.obj \
be_ai_weight.obj \
be_ea.obj \
be_interface.obj \
l_crc.obj \
l_libvar.obj \
l_log.obj \
l_memory.obj \
l_precomp.obj \
l_script.obj \
l_struct.obj \
l_utils.obj \
q_shared.obj
all: gladiator.dll
gladiator.dll: $(OBJS)
lcclnk -dll -entry GetBotAPI *.obj botlib.def -o gladiator.dll
clean:
del *.obj gladiator.dll
%.obj: %.c
$(CC) $(CFLAGS) $<

View File

@ -0,0 +1,92 @@
#
# Makefile for Gladiator Bot library: gladiator.so
# Intended for gcc/Linux
#
ARCH=i386
CC=gcc
BASE_CFLAGS=-Dstricmp=strcasecmp
#use these cflags to optimize it
CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
-malign-jumps=2 -malign-functions=2
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-ldl -lm
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
SHLIBLDFLAGS=-shared
DO_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
#############################################################################
# SETUP AND BUILD
# GLADIATOR BOT
#############################################################################
.c.o:
$(DO_CC)
GAME_OBJS = \
be_aas_bsphl.o\
be_aas_bspq2.o\
be_aas_cluster.o\
be_aas_debug.o\
be_aas_entity.o\
be_aas_file.o\
be_aas_light.o\
be_aas_main.o\
be_aas_move.o\
be_aas_optimize.o\
be_aas_reach.o\
be_aas_route.o\
be_aas_routealt.o\
be_aas_sample.o\
be_aas_sound.o\
be_ai2_dmq2.o\
be_ai2_dmhl.o\
be_ai2_dmnet.o\
be_ai2_main.o\
be_ai_char.o\
be_ai_chat.o\
be_ai_goal.o\
be_ai_load.o\
be_ai_move.o\
be_ai_weap.o\
be_ai_weight.o\
be_ea.o\
be_interface.o\
l_crc.o\
l_libvar.o\
l_log.o\
l_memory.o\
l_precomp.o\
l_script.o\
l_struct.o\
l_utils.o\
q_shared.o
glad$(ARCH).$(SHLIBEXT) : $(GAME_OBJS)
$(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS)
#############################################################################
# MISC
#############################################################################
clean:
-rm -f $(GAME_OBJS)
depend:
gcc -MM $(GAME_OBJS:.o=.c)
install:
cp gladiator.so ..
#
# From "make depend"
#

75
code/bspc/Conscript Normal file
View File

@ -0,0 +1,75 @@
# bspc compile
Import qw( BSPC_BASE_CFLAGS BUILD_DIR INSTALL_DIR CC CXX LINK );
@BSPC_FILES = qw(
aas_areamerging.c
aas_cfg.c
aas_create.c
aas_edgemelting.c
aas_facemerging.c
aas_file.c
aas_gsubdiv.c
aas_map.c
aas_prunenodes.c
aas_store.c
be_aas_bspc.c
../botlib/be_aas_bspq3.c
../botlib/be_aas_cluster.c
../botlib/be_aas_move.c
../botlib/be_aas_optimize.c
../botlib/be_aas_reach.c
../botlib/be_aas_sample.c
brushbsp.c
bspc.c
../qcommon/cm_load.c
../qcommon/cm_patch.c
../qcommon/cm_test.c
../qcommon/cm_trace.c
csg.c
glfile.c
l_bsp_ent.c
l_bsp_hl.c
l_bsp_q1.c
l_bsp_q2.c
l_bsp_q3.c
l_bsp_sin.c
l_cmd.c
../botlib/l_libvar.c
l_log.c
l_math.c
l_mem.c
l_poly.c
../botlib/l_precomp.c
l_qfiles.c
../botlib/l_script.c
../botlib/l_struct.c
l_threads.c
l_utils.c
leakfile.c
map.c
map_hl.c
map_q1.c
map_q2.c
map_q3.c
map_sin.c
../qcommon/md4.c
nodraw.c
portals.c
textures.c
tree.c
../qcommon/unzip.c
);
$BSPC_REF = \@BSPC_FILES;
$env = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
CFLAGS => $BSPC_BASE_CFLAGS,
LIBS => '-ldl -lm -lpthread'
);
Program $env 'bspc', @$BSPC_REF;
# this should install to Q3 or something?
Install $env $INSTALL_DIR, 'bspc';

114
code/bspc/Makefile Normal file
View File

@ -0,0 +1,114 @@
#
# Makefile for the BSPC tool for the Gladiator Bot
# Intended for gcc/Linux
#
# TTimo 5/15/2001
# some cleanup .. only used on i386 for GtkRadiant setups AFAIK .. removing the i386 tag
# TODO: the intermediate object files should go into their own directory
# specially for ../botlib and ../qcommon, the compilation flags on those might not be what you expect
#ARCH=i386
CC=gcc
BASE_CFLAGS=-Dstricmp=strcasecmp
#use these cflags to optimize it
CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
-malign-jumps=2 -malign-functions=2 -DLINUX -DBSPC
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
LDFLAGS=-ldl -lm -lpthread
DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
#############################################################################
# SETUP AND BUILD BSPC
#############################################################################
.c.o:
$(DO_CC)
GAME_OBJS = \
_files.o\
aas_areamerging.o\
aas_cfg.o\
aas_create.o\
aas_edgemelting.o\
aas_facemerging.o\
aas_file.o\
aas_gsubdiv.o\
aas_map.o\
aas_prunenodes.o\
aas_store.o\
be_aas_bspc.o\
../botlib/be_aas_bspq3.o\
../botlib/be_aas_cluster.o\
../botlib/be_aas_move.o\
../botlib/be_aas_optimize.o\
../botlib/be_aas_reach.o\
../botlib/be_aas_sample.o\
brushbsp.o\
bspc.o\
../qcommon/cm_load.o\
../qcommon/cm_patch.o\
../qcommon/cm_test.o\
../qcommon/cm_trace.o\
csg.o\
glfile.o\
l_bsp_ent.o\
l_bsp_hl.o\
l_bsp_q1.o\
l_bsp_q2.o\
l_bsp_q3.o\
l_bsp_sin.o\
l_cmd.o\
../botlib/l_libvar.o\
l_log.o\
l_math.o\
l_mem.o\
l_poly.o\
../botlib/l_precomp.o\
l_qfiles.o\
../botlib/l_script.o\
../botlib/l_struct.o\
l_threads.o\
l_utils.o\
leakfile.o\
map.o\
map_hl.o\
map_q1.o\
map_q2.o\
map_q3.o\
map_sin.o\
../qcommon/md4.o\
nodraw.o\
portals.o\
textures.o\
tree.o\
../qcommon/unzip.o
#tetrahedron.o
bspc : $(GAME_OBJS)
$(CC) $(CFLAGS) -o $@ $(GAME_OBJS) $(LDFLAGS)
strip $@
#############################################################################
# MISC
#############################################################################
clean:
-rm -f $(GAME_OBJS)
depend:
gcc -MM $(GAME_OBJS:.o=.c)
#install:
# cp bspci386 ..
#
# From "make depend"
#

63
code/bspc/_files.c Normal file
View File

@ -0,0 +1,63 @@
//===========================================================================
//
// 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
*/

390
code/bspc/aas_areamerging.c Normal file
View File

@ -0,0 +1,390 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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,24 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MergeAreas(void);

252
code/bspc/aas_cfg.c Normal file
View File

@ -0,0 +1,252 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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"
//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},
{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;
//===========================================================================
// 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;
} //end of the function DefaultCfg
//===========================================================================
//
// 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

73
code/bspc/aas_cfg.h Normal file
View File

@ -0,0 +1,73 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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;
} cfg_t;
extern cfg_t cfg;
void DefaultCfg(void);
int LoadCfgFile(char *filename);

1142
code/bspc/aas_create.c Normal file

File diff suppressed because it is too large Load Diff

136
code/bspc/aas_create.h Normal file
View File

@ -0,0 +1,136 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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
} 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);

108
code/bspc/aas_edgemelting.c Normal file
View File

@ -0,0 +1,108 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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,24 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MeltAreaFaceWindings(void);

282
code/bspc/aas_facemerging.c Normal file
View File

@ -0,0 +1,282 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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;
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,24 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_MergeAreaFaces(void);
void AAS_MergeAreaPlaneFaces(void);

549
code/bspc/aas_file.c Normal file
View File

@ -0,0 +1,549 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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);
} //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_OLD && 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

25
code/bspc/aas_file.h Normal file
View File

@ -0,0 +1,25 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
qboolean AAS_WriteAASFile(char *filename);
qboolean AAS_LoadAASFile(char *filename, int fpoffset, int fplength);

656
code/bspc/aas_gsubdiv.c Normal file
View File

@ -0,0 +1,656 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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

25
code/bspc/aas_gsubdiv.h Normal file
View File

@ -0,0 +1,25 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//works with the global tmpaasworld
void AAS_GravitationalSubdivision(void);
void AAS_LadderSubdivision(void);

849
code/bspc/aas_map.c Normal file
View File

@ -0,0 +1,849 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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.0001
//===========================================================================
//
// 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_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 mark_entities[MAX_MAP_ENTITIES];
int AAS_AlwaysTriggered_r(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;
}
// check for possible trigger_always entities activating this entity
if ( mark_entities[i] ) {
Warning( "entity %d, classname %s has recursive targetname %s\n", i,
ValueForKey(&entities[i], "classname"), targetname );
return false;
}
mark_entities[i] = true;
if ( AAS_AlwaysTriggered_r(ValueForKey(&entities[i], "targetname")) ) {
return true;
}
}
}
}
return false;
}
int AAS_AlwaysTriggered(char *targetname) {
memset( mark_entities, 0, sizeof(mark_entities) );
return AAS_AlwaysTriggered_r( targetname );
}
//===========================================================================
//
// 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")))
{
//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")))
{
//"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_static", ValueForKey(mapent, "classname")))
{
//FIXME: easy/medium/hard/deathmatch specific?
return true;
} //end else if
else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
{
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, notteam;
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
//if it's a trigger hurt
if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
{
notteam = FloatForKey(mapent, "bot_notteam");
if ( notteam == 1 ) {
brush->contents |= CONTENTS_NOTTEAM1;
}
else if ( notteam == 2 ) {
brush->contents |= CONTENTS_NOTTEAM2;
}
else {
// always avoid so set lava contents
brush->contents |= CONTENTS_LAVA;
}
} //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
} //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
//
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_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_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

23
code/bspc/aas_map.h Normal file
View File

@ -0,0 +1,23 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels);

View File

@ -0,0 +1,89 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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

View File

@ -0,0 +1,24 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
void AAS_PruneNodes(void);

1082
code/bspc/aas_store.c Normal file

File diff suppressed because it is too large Load Diff

107
code/bspc/aas_store.h Normal file
View File

@ -0,0 +1,107 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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 "../game/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;
//*/
extern aas_t aasworld;
//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);

252
code/bspc/aasfile.h Normal file
View File

@ -0,0 +1,252 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//NOTE: int = default signed
// default long
#define AASID (('S'<<24)+('A'<<16)+('A'<<8)+'E')
#define AASVERSION_OLD 4
#define AASVERSION 5
//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
//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
//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
//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
} 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
*/

292
code/bspc/be_aas_bspc.c Normal file
View File

@ -0,0 +1,292 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../game/q_shared.h"
#include "../bspc/l_log.h"
#include "../bspc/l_qfiles.h"
#include "../botlib/l_memory.h"
#include "../botlib/l_script.h"
#include "../botlib/l_precomp.h"
#include "../botlib/l_struct.h"
#include "../botlib/aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "../botlib/be_aas_def.h"
#include "../qcommon/cm_public.h"
//#define BSPC
extern botlib_import_t botimport;
extern qboolean capsule_collision;
botlib_import_t botimport;
clipHandle_t worldmodel;
void Error (char *error, ...);
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_Error(char *fmt, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, fmt);
vsprintf(text, fmt, argptr);
va_end(argptr);
Error(text);
} //end of the function AAS_Error
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int Sys_MilliSeconds(void)
{
return clock() * 1000 / CLOCKS_PER_SEC;
} //end of the function Sys_MilliSeconds
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_DebugLine(vec3_t start, vec3_t end, int color)
{
} //end of the function AAS_DebugLine
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_ClearShownDebugLines(void)
{
} //end of the function AAS_ClearShownDebugLines
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *BotImport_BSPEntityData(void)
{
return CM_EntityString();
} //end of the function AAS_GetEntityData
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_Trace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
{
trace_t result;
CM_BoxTrace(&result, start, end, mins, maxs, worldmodel, contentmask, capsule_collision);
bsptrace->allsolid = result.allsolid;
bsptrace->contents = result.contents;
VectorCopy(result.endpos, bsptrace->endpos);
bsptrace->ent = result.entityNum;
bsptrace->fraction = result.fraction;
bsptrace->exp_dist = 0;
bsptrace->plane.dist = result.plane.dist;
VectorCopy(result.plane.normal, bsptrace->plane.normal);
bsptrace->plane.signbits = result.plane.signbits;
bsptrace->plane.type = result.plane.type;
bsptrace->sidenum = 0;
bsptrace->startsolid = result.startsolid;
bsptrace->surface.flags = result.surfaceFlags;
} //end of the function BotImport_Trace
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotImport_PointContents(vec3_t p)
{
return CM_PointContents(p, worldmodel);
} //end of the function BotImport_PointContents
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void *BotImport_GetMemory(int size)
{
return GetMemory(size);
} //end of the function BotImport_GetMemory
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_Print(int type, char *fmt, ...)
{
va_list argptr;
char buf[1024];
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
printf(buf);
if (buf[0] != '\r') Log_Write(buf);
va_end(argptr);
} //end of the function BotImport_Print
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotImport_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t outmins, vec3_t outmaxs, vec3_t origin)
{
clipHandle_t h;
vec3_t mins, maxs;
float max;
int i;
h = CM_InlineModel(modelnum);
CM_ModelBounds(h, mins, maxs);
//if the model is rotated
if ((angles[0] || angles[1] || angles[2]))
{ // expand for rotation
max = RadiusFromBounds(mins, maxs);
for (i = 0; i < 3; i++)
{
mins[i] = (mins[i] + maxs[i]) * 0.5 - max;
maxs[i] = (mins[i] + maxs[i]) * 0.5 + max;
} //end for
} //end if
if (outmins) VectorCopy(mins, outmins);
if (outmaxs) VectorCopy(maxs, outmaxs);
if (origin) VectorClear(origin);
} //end of the function BotImport_BSPModelMinsMaxsOrigin
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_DPrintf(char *fmt, ...)
{
va_list argptr;
char buf[1024];
va_start(argptr, fmt);
vsprintf(buf, fmt, argptr);
printf(buf);
if (buf[0] != '\r') Log_Write(buf);
va_end(argptr);
} //end of the function Com_DPrintf
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int COM_Compress( char *data_p ) {
return strlen(data_p);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_Memset (void* dest, const int val, const size_t count) {
memset(dest, val, count);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Com_Memcpy (void* dest, const void* src, const size_t count) {
memcpy(dest, src, count);
}
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_InitBotImport(void)
{
botimport.BSPEntityData = BotImport_BSPEntityData;
botimport.GetMemory = BotImport_GetMemory;
botimport.FreeMemory = FreeMemory;
botimport.Trace = BotImport_Trace;
botimport.PointContents = BotImport_PointContents;
botimport.Print = BotImport_Print;
botimport.BSPModelMinsMaxsOrigin = BotImport_BSPModelMinsMaxsOrigin;
} //end of the function AAS_InitBotImport
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_CalcReachAndClusters(struct quakefile_s *qf)
{
float time;
Log_Print("loading collision map...\n");
//
if (!qf->pakfile[0]) strcpy(qf->pakfile, qf->filename);
//load the map
CM_LoadMap((char *) qf, qfalse, &aasworld.bspchecksum);
//get a handle to the world model
worldmodel = CM_InlineModel(0); // 0 = world, 1 + are bmodels
//initialize bot import structure
AAS_InitBotImport();
//load the BSP entity string
AAS_LoadBSPFile();
//init physics settings
AAS_InitSettings();
//initialize AAS link heap
AAS_InitAASLinkHeap();
//initialize the AAS linked entities for the new map
AAS_InitAASLinkedEntities();
//reset all reachabilities and clusters
aasworld.reachabilitysize = 0;
aasworld.numclusters = 0;
//set all view portals as cluster portals in case we re-calculate the reachabilities and clusters (with -reach)
AAS_SetViewPortalsAsClusterPortals();
//calculate reachabilities
AAS_InitReachability();
time = 0;
while(AAS_ContinueInitReachability(time)) time++;
//calculate clusters
AAS_InitClustering();
} //end of the function AAS_CalcReachAndClusters

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