mirror of
https://github.com/nzp-team/quakec.git
synced 2024-11-24 04:41:16 +00:00
Initial commit
This commit is contained in:
commit
b26ca6a026
58 changed files with 34564 additions and 0 deletions
88
.github/workflows/compile-and-release.yml
vendored
Normal file
88
.github/workflows/compile-and-release.yml
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
name: Compile QuakeC and Publish Release
|
||||
on: [push]
|
||||
jobs:
|
||||
Compile-QC:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Clone Repository
|
||||
working-directory: ./tools
|
||||
run: |
|
||||
sudo -i
|
||||
./qc-compiler-lin.sh
|
||||
echo "QC COMPILE STATUS - ${{ job.status }}."
|
||||
- name: Zip Progs
|
||||
working-directory: ./build
|
||||
run: |
|
||||
zip -r -j pc-nzp-qc.zip pc/*
|
||||
zip -r -j psp-nzp-qc.zip psp/*
|
||||
zip -r -j nx-nzp-qc.zip nx/*
|
||||
zip -r -j vita-nzp-qc.zip vita/*
|
||||
- name: Generate Build Date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d-%H-%M-%S')"
|
||||
- name: Delete Old Release
|
||||
uses: dev-drprasad/delete-tag-and-release@v0.2.0
|
||||
with:
|
||||
delete_release: true
|
||||
tag_name: bleeding-edge
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: bleeding-edge
|
||||
release_name: Automated Release ${{ steps.date.outputs.date }}
|
||||
body: |
|
||||
This is a **bleeding edge** NZ:P QuakeC release, stability is not guarenteed and you may need to grab an updated asset release if this update depends on new models/textures/etc.
|
||||
|
||||
To install:
|
||||
- Grab the .ZIP archive for your desired platform below (*-nzp-qc.zip)
|
||||
- Extract the contents of the .ZIP archive to your nzp folder (Example: copy `progs.dat` and `progs.lno` to `PSP/GAME/nzportable/nzp`).
|
||||
draft: true
|
||||
prerelease: false
|
||||
- name: Upload NX QC
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./build/nx-nzp-qc.zip
|
||||
asset_name: nx-nzp-qc.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload PC QC
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./build/pc-nzp-qc.zip
|
||||
asset_name: pc-nzp-qc.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload PSP QC
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./build/psp-nzp-qc.zip
|
||||
asset_name: psp-nzp-qc.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload VITA QC
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./build/vita-nzp-qc.zip
|
||||
asset_name: vita-nzp-qc.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Publish Release
|
||||
uses: StuYarrow/publish-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
id: ${{ steps.create_release.outputs.id }}
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
build/*
|
||||
bin/fteqcc.log
|
87
LICENSE
Normal file
87
LICENSE
Normal file
|
@ -0,0 +1,87 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
Preamble
|
||||
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification follow.
|
||||
|
||||
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
|
26
README.md
Normal file
26
README.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Nazi Zombies: Portable QuakeC
|
||||
|
||||
## About
|
||||
This is the QuakeC portion of the NZ:P source code. QuakeC is responsible for most game-related code such as weapon logic, ai, and Perks. You can read more about QuakeC on the [Wikipedia page](https://en.wikipedia.org/wiki/QuakeC). NZ:P makes use of CSQC for PC/FTE.
|
||||
|
||||
## Project Structure
|
||||
Here is a brief explanation for each of the (sub)directories in this repository:
|
||||
* `bin`: Command line binaries for [FTEQCC](https://www.fteqcc.org/) + the ini configuration file.
|
||||
* `progs`: `*.src` files, a list of QuakeC source files each platform is dependent on.
|
||||
* `source`:
|
||||
* `client`: FTE-exclusive CSQC, used for the HUD, achievements, and other server->client requests.
|
||||
* `server`: Game code relevant to all platforms, contains most expected logic.
|
||||
* `shared`: Definitions for weapon stats and some utility functions shared by both the `client` and `server`.
|
||||
* `tools`: Build scripts to compile the QuakeC into `.dat` and `.lno` files.
|
||||
|
||||
## Updating
|
||||
While it's usually recommended to stay on the QuakeC version provided with your build of NZ:P, you may want to update it to the current development builds to test new features and changes. To do this, navigate to the [Releases](https://github.com/nzp-team/quakec/releases/tag/bleeding-edge) page and follow the instructions there for downloading and installing.
|
||||
|
||||
## Building (Beginner Friendly)
|
||||
There are no prerequisites or dependancies needed to build QuakeC other than a working Windows or Linux-based machine (MacOS is **not** natively supported, but you can use [WINE](https://www.winehq.org/)).
|
||||
|
||||
Before you can build the NZ:P QuakeC, you must either [download](https://github.com/nzp-team/quakec/archive/refs/heads/main.zip) this repository (easy) or [clone it](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) (for developers).
|
||||
|
||||
To build, simply navigate to the `tools` directory and run the `qc-compiler-*` script for your platform. If unfamiliar with executing shell (`.sh`) scripts on Linux systems, give this [itsFOSS article](https://itsfoss.com/run-shell-script-linux/) a read.
|
||||
|
||||
After having done this, a `build` directory will have been created, and inside of it will be more directories named after every platform. Copy the contents of the platform directories into your `nzp` game directory. (Example: copy `progs.dat` and `progs.lno` from `build/psp` to `PSP/GAME/nzportable/nzp`).
|
BIN
bin/fteqcc-cli-lin
Normal file
BIN
bin/fteqcc-cli-lin
Normal file
Binary file not shown.
BIN
bin/fteqcc-cli-win.exe
Normal file
BIN
bin/fteqcc-cli-win.exe
Normal file
Binary file not shown.
216
bin/fteqcc.ini
Normal file
216
bin/fteqcc.ini
Normal file
|
@ -0,0 +1,216 @@
|
|||
optimisation t default # c = a*b is performed in one operation rather than two, and can
|
||||
# cause older decompilers to fail.
|
||||
optimisation i default # if (!a) was traditionally compiled in two statements. This optimisation
|
||||
# does it in one, but can cause some decompilers to get confused.
|
||||
optimisation p default # In the original qcc, function parameters were specified as a vector
|
||||
# store even for floats. This fixes that.
|
||||
optimisation c default # This optimisation strips out the names of constants (but not strings)
|
||||
# from your progs, resulting in smaller files. It makes decompilers
|
||||
# leave out names or fabricate numerical ones.
|
||||
optimisation cs default # This optimisation strips out the names of string constants from
|
||||
# your progs. However, this can break addons, so don't use it in
|
||||
# those cases.
|
||||
optimisation d default # This will merge definitions of constants which are the same value.
|
||||
# Pay extra attention to assignment to constant warnings.
|
||||
optimisation s default # This will compact the string table that is stored in the progs.
|
||||
# It will be considerably smaller with this.
|
||||
optimisation l default # Strips out local names and definitions. Most decompiles will break
|
||||
# on this.
|
||||
optimisation n default # This strips out the names of functions which are never called.
|
||||
# Doesn't make much of an impact though.
|
||||
optimisation f default # This strips out the filenames of the progs. This can confuse the
|
||||
# really old decompilers, but is nothing to the more recent ones.
|
||||
optimisation u default # Removes the entries of unreferenced variables. Doesn't make a
|
||||
# difference in well maintained code.
|
||||
optimisation r default # Optimises the pr_globals count by overlapping temporaries. In
|
||||
# QC, every multiplication, division or operation in general produces
|
||||
# a temporary variable. This optimisation prevents excess, and in
|
||||
# the case of Hexen2's gamecode, reduces the count by 50k. This
|
||||
# is the most important optimisation, ever.
|
||||
optimisation a default # 5*6 actually emits an operation into the progs. This prevents
|
||||
# that happening, effectivly making the compiler see 30
|
||||
optimisation pf default # Strip out stuff wasted used in function calls and strings to the
|
||||
# precache_file builtin (which is actually a stub in quake).
|
||||
optimisation ro default # Functions ending in a return statement do not need a done statement
|
||||
# at the end of the function. This can confuse some decompilers,
|
||||
# making functions appear larger than they were.
|
||||
optimisation cj default # This optimisation plays an effect mostly with nested if/else statements,
|
||||
# instead of jumping to an unconditional jump statement, it'll jump
|
||||
# to the final destination instead. This will bewilder decompilers.
|
||||
optimisation sf default # Strips out the 'defs' of functions that were only ever called
|
||||
# directly. This does not affect saved games. This can affect FTE_MULTIPROGS.
|
||||
optimisation lo default # Store all locals in a single section of the pr_globals. Vastly
|
||||
# reducing it. This effectivly does the job of overlaptemps.
|
||||
# However, locals are no longer automatically initialised to 0 (and
|
||||
# never were in the case of recursion, but at least then its the
|
||||
# same type).
|
||||
# If locals appear uninitialised, fteqcc will disable this optimisation
|
||||
# for the affected functions, you can optionally get a warning about
|
||||
# these locals using: #pragma warning enable F302
|
||||
optimisation vc default # Where a function is called with just a vector, this causes the
|
||||
# function call to store three floats instead of one vector. This
|
||||
# can save a good number of pr_globals where those vectors contain
|
||||
# many duplicate coordinates but do not match entirly.
|
||||
optimisation cf default # Strip class field names. This will harm debugging and can result
|
||||
# in 'gibberish' names appearing in saved games. Has no effect on
|
||||
# engines other than FTEQW, which will not recognise these anyway.
|
||||
keyword asm true # Disables the 'asm' keyword. Use the writeasm flag to see an example
|
||||
# of the asm.
|
||||
keyword break true # Disables the 'break' keyword.
|
||||
keyword case true # Disables the 'case' keyword.
|
||||
keyword class true # Disables the 'class' keyword.
|
||||
keyword const true # Disables the 'const' keyword.
|
||||
keyword continue true # Disables the 'continue' keyword.
|
||||
keyword default true # Disables the 'default' keyword.
|
||||
keyword entity true # Disables the 'entity' keyword.
|
||||
keyword enum true # Disables the 'enum' keyword.
|
||||
keyword enumflags true # Disables the 'enumflags' keyword.
|
||||
keyword extern true # Disables the 'extern' keyword. Use only on functions inside addons.
|
||||
keyword float true # Disables the 'float' keyword. (Disables the float keyword without
|
||||
# 'local' preceeding it)
|
||||
keyword for true # Disables the 'for' keyword. Syntax: for(assignment; while; increment)
|
||||
# {codeblock;}
|
||||
keyword goto true # Disables the 'goto' keyword.
|
||||
keyword int true # Disables the 'int' keyword.
|
||||
keyword integer true # Disables the 'integer' keyword.
|
||||
keyword noref true # Disables the 'noref' keyword.
|
||||
keyword unused false # Disables the 'unused' keyword. 'unused' means that the variable
|
||||
# is unused, you're aware that its unused, and you'd rather not
|
||||
# know about all the warnings this results in.
|
||||
keyword used false # Disables the 'used' keyword. 'used' means that the variable is
|
||||
# used even if the qcc can't see how - thus preventing it from ever
|
||||
# being stripped.
|
||||
keyword static true # Disables the 'static' keyword. 'static' means that a variable
|
||||
# has altered scope. On globals, the variable is visible only to
|
||||
# the current .qc file. On locals, the variable's value does not
|
||||
# change between calls to the function. On class variables, specifies
|
||||
# that the field is a scoped global instead of a local. On class
|
||||
# functions, specifies that 'this' is expected to be invalid and
|
||||
# that the function will access any memembers via it.
|
||||
keyword nonstatic true # Disables the 'nonstatic' keyword. 'nonstatic' acts upon globals+functions,
|
||||
# reverting the defaultstatic pragma on a per-variable basis. For
|
||||
# use by people who prefer to keep their APIs explicit.
|
||||
keyword ignore false # Disables the 'ignore' keyword. 'ignore' is expected to typically
|
||||
# be hidden behind a 'csqconly' define, and in such a context can
|
||||
# be used to conditionally compile functions a little more gracefully.
|
||||
# The opposite of the 'used' keyword. These variables/functions/members
|
||||
# are ALWAYS stripped, and effectively ignored.
|
||||
keyword nosave true # Disables the 'nosave' keyword.
|
||||
keyword inline true # Disables the 'inline' keyword.
|
||||
keyword strip true # Disables the 'strip' keyword.
|
||||
keyword shared true # Disables the 'shared' keyword.
|
||||
keyword state false # Disables the 'state' keyword.
|
||||
keyword optional true # Disables the 'optional' keyword.
|
||||
keyword inout false # Disables the 'inout' keyword.
|
||||
keyword string true # Disables the 'string' keyword.
|
||||
keyword struct true # Disables the 'struct' keyword.
|
||||
keyword switch true # Disables the 'switch' keyword.
|
||||
keyword thinktime false # Disables the 'thinktime' keyword which is used in HexenC
|
||||
keyword until false # Disables the 'until' keyword which is used in HexenC
|
||||
keyword loop false # Disables the 'loop' keyword which is used in HexenC
|
||||
keyword typedef true # Disables the 'typedef' keyword.
|
||||
keyword union true # Disables the 'union' keyword.
|
||||
keyword var true # Disables the 'var' keyword.
|
||||
keyword vector true # Disables the 'vector' keyword.
|
||||
keyword wrap true # Disables the 'wrap' keyword.
|
||||
keyword weak true # Disables the 'weak' keyword.
|
||||
flag kce true # If you want keywords to NOT be disabled when they a variable by
|
||||
# the same name is defined, check here.
|
||||
flag parms false # if PARM0 PARM1 etc should be defined by the compiler. These are
|
||||
# useful if you make use of the asm keyword for function calls,
|
||||
# or you wish to create your own variable arguments. This is an
|
||||
# easy way to break decompilers.
|
||||
flag autoproto false # Causes compilation to take two passes instead of one. The first
|
||||
# pass, only the definitions are read. The second pass actually
|
||||
# compiles your code. This means you never have to remember to prototype
|
||||
# functions again.
|
||||
flag wasm false # Writes out a qc.asm which contains all your functions but in assembler.
|
||||
# This is a great way to look for bugs in fteqcc, but can also be
|
||||
# used to see exactly what your functions turn into, and thus how
|
||||
# to optimise statements better.
|
||||
flag annotate false # Annotate source code with assembler statements on compile (requires
|
||||
# gui).
|
||||
flag nullemptystr false # Empty string immediates will have the raw value 0 instead of 1.
|
||||
flag ifstring false # Causes if(string) to behave identically to if(string!=) This is
|
||||
# most useful with addons of course, but also has adverse effects
|
||||
# with FRIK_FILE's fgets, where it becomes impossible to determin
|
||||
# the end of the file. In such a case, you can still use asm {IF
|
||||
# string 2;RETURN} to detect eof and leave the function.
|
||||
flag iffloat false # Fixes certain floating point logic.
|
||||
flag ifvector true # Fixes conditional vector logic.
|
||||
flag vectorlogic true # Fixes conditional vector logic.
|
||||
flag brokenarray false # Treat references to arrays as references to the first index of
|
||||
# said array, to replicate an old fteqcc bug.
|
||||
flag rootconstructor false # When enabled, the root constructor should be called first like
|
||||
# in c++.
|
||||
flag acc false # Reacc is a pascall like compiler. It was released before the Quake
|
||||
# source was released. This flag has a few effects. It sorts all
|
||||
# qc files in the current directory into alphabetical order to compile
|
||||
# them. It also allows Reacc global/field distinctions, as well
|
||||
# as allows ¦ as EOF. Whilst case insensitivity and lax type checking
|
||||
# are supported by reacc, they are seperate compiler flags in fteqcc.
|
||||
flag caseinsens false # Causes fteqcc to become case insensitive whilst compiling names.
|
||||
# It's generally not advised to use this as it compiles a little
|
||||
# more slowly and provides little benefit. However, it is required
|
||||
# for full reacc support.
|
||||
flag lax false # Disables many errors (generating warnings instead) when function
|
||||
# calls or operations refer to two normally incompatible types.
|
||||
# This is required for reacc support, and can also allow certain
|
||||
# (evil) mods to compile that were originally written for frikqcc.
|
||||
flag hashonly false # Allows use of only #constant for precompiler constants, allows
|
||||
# certain preqcc using mods to compile
|
||||
flag lo false # This changes the behaviour of your code. It generates additional
|
||||
# if operations to early-out in if statements. With this flag, the
|
||||
# line if (0 && somefunction()) will never call the function. It
|
||||
# can thus be considered an optimisation. However, due to the change
|
||||
# of behaviour, it is not considered so by fteqcc. Note that due
|
||||
# to inprecisions with floats, this flag can cause runaway loop
|
||||
# errors within the player walk and run functions (without iffloat
|
||||
# also enabled). This code is advised:
|
||||
# player_stand1:
|
||||
# if (self.velocity_x || self.velocity_y)
|
||||
# player_run
|
||||
# if (!(self.velocity_x || self.velocity_y))
|
||||
flag msvcstyle false # Generates warning and error messages in a format that msvc understands,
|
||||
# to facilitate ide integration.
|
||||
flag debugmacros false # Print out the contents of macros that are expanded. This can help
|
||||
# look inside macros that are expanded and is especially handy if
|
||||
# people are using preprocessor hacks.
|
||||
flag filetimes false # Recompiles the progs only if the file times are modified.
|
||||
flag fastarrays false # Generates extra instructions inside array handling functions to
|
||||
# detect engine and use extension opcodes only in supporting engines.
|
||||
# Adds a global which is set by the engine if the engine supports
|
||||
# the extra opcodes. Note that this applies to all arrays or none.
|
||||
flag assumeint false # Numerical constants are assumed to be integers, instead of floats.
|
||||
flag subscope false # Restrict the scope of locals to the block they are actually defined
|
||||
# within, as in C.
|
||||
flag verbose false # Lots of extra compiler messages.
|
||||
flag typeexplicit false # All type conversions must be explicit or directly supported by
|
||||
# instruction set.
|
||||
flag noboundchecks false # Disable array index checks, speeding up array access but can result
|
||||
# in your code misbehaving.
|
||||
flag qccx false # WARNING: This syntax makes mods inherantly engine specific.
|
||||
# Do NOT use unless you know what you're doing.This is provided
|
||||
# for compatibility only
|
||||
# Any entity hacks will be unsupported in FTEQW, DP, and others,
|
||||
# resulting in engine crashes if the code in question is executed.
|
||||
flag embedsrc false # Write the sourcecode into the output file.
|
||||
showall off # Show all keyword options in the gui
|
||||
compileonstart off # Recompile on GUI startup
|
||||
log off # Write out a compile log
|
||||
enginebinary fteglqw.exe # Location of the engine binary to run. Change this to something
|
||||
# else to run a different engine, but not all support debugging.
|
||||
basedir ../.. # The base directory of the game that contains your sub directory
|
||||
engineargs "-window -nohome -game game"
|
||||
# The engine commandline to use when debugging. You'll likely want
|
||||
# to ensure this contains -window as well as the appropriate -game
|
||||
# argument.
|
||||
srcfile progs.src # The progs.src file to load to find ordering of other qc files.
|
||||
src # Additional subdir to read qc files from. Typically blank (ie:
|
||||
# the working directory).
|
||||
extramargins off # Enables line number and folding margins.
|
||||
hexen2 off # Enable the extra tweaks needed for compatibility with hexen2 engines.
|
||||
extendedopcodes off # Utilise an extended instruction set, providing support for pointers
|
||||
# and faster arrays and other speedups.
|
||||
parameters # Other additional parameters that are not supported by the gui.
|
||||
# Likely including -DFOO
|
11
progs/fte-client.src
Normal file
11
progs/fte-client.src
Normal file
|
@ -0,0 +1,11 @@
|
|||
../../build/pc/csprogs.dat
|
||||
|
||||
../source/client/defs/fte.qc
|
||||
../source/shared/defs/custom.qc
|
||||
../source/shared/sound_enhanced.qc
|
||||
../source/shared/weapon_defines.qc
|
||||
../source/client/defs/custom.qc
|
||||
../source/client/menu.qc
|
||||
../source/client/achievements.qc
|
||||
../source/client/hud.qc
|
||||
../source/client/main.qc
|
37
progs/fte-server.src
Normal file
37
progs/fte-server.src
Normal file
|
@ -0,0 +1,37 @@
|
|||
../../build/pc/qwprogs.dat
|
||||
|
||||
../source/server/defs/fte.qc
|
||||
../source/shared/defs/custom.qc
|
||||
../source/shared/weapon_defines.qc
|
||||
../source/server/defs/custom.qc
|
||||
../source/server/clientfuncs.qc
|
||||
|
||||
../source/server/dummies/generic.qc
|
||||
../source/server/rounds.qc
|
||||
../source/server/nzdparser.qc
|
||||
../source/server/main.qc
|
||||
../source/server/player.qc
|
||||
../source/server/damage.qc
|
||||
|
||||
../source/server/entities/sub_functions.qc
|
||||
../source/server/entities/sounds.qc
|
||||
../source/server/entities/triggers.qc
|
||||
../source/server/entities/map_entities.qc
|
||||
../source/server/entities/lights.qc
|
||||
../source/server/entities/doors.qc
|
||||
../source/server/entities/window.qc
|
||||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
../source/server/ai/pathfind_code.qc
|
||||
../source/server/ai/ai_core.qc
|
||||
../source/server/ai/fte/waypoints_core.qc
|
||||
../source/server/ai/zombie_core.qc
|
||||
../source/server/ai/crawler_core.qc
|
||||
../source/server/ai/dog_core.qc
|
||||
|
||||
../source/server/items.qc
|
40
progs/nx.src
Normal file
40
progs/nx.src
Normal file
|
@ -0,0 +1,40 @@
|
|||
../../build/nx/progs.dat
|
||||
|
||||
#pragma warning disable Q208
|
||||
|
||||
../source/server/defs/nx.qc
|
||||
../source/shared/defs/custom.qc
|
||||
../source/shared/weapon_defines.qc
|
||||
../source/server/defs/custom.qc
|
||||
../source/server/clientfuncs.qc
|
||||
|
||||
../source/server/dummies/vitanx.qc
|
||||
|
||||
../source/server/dummies/generic.qc
|
||||
../source/server/rounds.qc
|
||||
../source/server/nzdparser.qc
|
||||
../source/server/main.qc
|
||||
../source/server/player.qc
|
||||
../source/server/damage.qc
|
||||
|
||||
../source/server/entities/sub_functions.qc
|
||||
../source/server/entities/sounds.qc
|
||||
../source/server/entities/triggers.qc
|
||||
../source/server/entities/map_entities.qc
|
||||
../source/server/entities/lights.qc
|
||||
../source/server/entities/doors.qc
|
||||
../source/server/entities/window.qc
|
||||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
../source/server/ai/ai_core.qc
|
||||
../source/server/ai/standard/waypoints_func.qc
|
||||
../source/server/ai/standard/waypoints_core.qc
|
||||
../source/server/ai/zombie_core.qc
|
||||
../source/server/ai/crawler_core.qc
|
||||
../source/server/ai/dog_core.qc
|
||||
|
||||
../source/server/items.qc
|
40
progs/psp.src
Normal file
40
progs/psp.src
Normal file
|
@ -0,0 +1,40 @@
|
|||
../../build/psp/progs.dat
|
||||
|
||||
#pragma warning disable Q208
|
||||
|
||||
../source/server/defs/psp.qc
|
||||
../source/shared/defs/custom.qc
|
||||
../source/shared/weapon_defines.qc
|
||||
../source/server/defs/custom.qc
|
||||
../source/server/clientfuncs.qc
|
||||
|
||||
../source/server/psp_specifics.qc
|
||||
|
||||
../source/server/dummies/generic.qc
|
||||
../source/server/rounds.qc
|
||||
../source/server/nzdparser.qc
|
||||
../source/server/main.qc
|
||||
../source/server/player.qc
|
||||
../source/server/damage.qc
|
||||
|
||||
../source/server/entities/sub_functions.qc
|
||||
../source/server/entities/sounds.qc
|
||||
../source/server/entities/triggers.qc
|
||||
../source/server/entities/map_entities.qc
|
||||
../source/server/entities/lights.qc
|
||||
../source/server/entities/doors.qc
|
||||
../source/server/entities/window.qc
|
||||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
../source/server/ai/ai_core.qc
|
||||
../source/server/ai/standard/waypoints_func.qc
|
||||
../source/server/ai/standard/waypoints_core.qc
|
||||
../source/server/ai/zombie_core.qc
|
||||
../source/server/ai/crawler_core.qc
|
||||
../source/server/ai/dog_core.qc
|
||||
|
||||
../source/server/items.qc
|
40
progs/vita.src
Normal file
40
progs/vita.src
Normal file
|
@ -0,0 +1,40 @@
|
|||
../../build/vita/progs.dat
|
||||
|
||||
#pragma warning disable Q208
|
||||
|
||||
../source/server/defs/vita.qc
|
||||
../source/shared/defs/custom.qc
|
||||
../source/shared/weapon_defines.qc
|
||||
../source/server/defs/custom.qc
|
||||
../source/server/clientfuncs.qc
|
||||
|
||||
../source/server/dummies/vitanx.qc
|
||||
|
||||
../source/server/dummies/generic.qc
|
||||
../source/server/rounds.qc
|
||||
../source/server/nzdparser.qc
|
||||
../source/server/main.qc
|
||||
../source/server/player.qc
|
||||
../source/server/damage.qc
|
||||
|
||||
../source/server/entities/sub_functions.qc
|
||||
../source/server/entities/sounds.qc
|
||||
../source/server/entities/triggers.qc
|
||||
../source/server/entities/map_entities.qc
|
||||
../source/server/entities/lights.qc
|
||||
../source/server/entities/doors.qc
|
||||
../source/server/entities/window.qc
|
||||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
../source/server/ai/ai_core.qc
|
||||
../source/server/ai/standard/waypoints_func.qc
|
||||
../source/server/ai/standard/waypoints_core.qc
|
||||
../source/server/ai/zombie_core.qc
|
||||
../source/server/ai/crawler_core.qc
|
||||
../source/server/ai/dog_core.qc
|
||||
|
||||
../source/server/items.qc
|
175
source/client/achievements.qc
Normal file
175
source/client/achievements.qc
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
client/achievements.qc
|
||||
|
||||
main achievement code
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Thanks to everyone who submitted Achievement ideas in 2019!
|
||||
|
||||
- Derped_Crusader
|
||||
- TheSmashers
|
||||
- Chyll
|
||||
- mrFlamist
|
||||
- mario135790
|
||||
- Mission
|
||||
- RedneckHax0r
|
||||
- Revnova
|
||||
- EpicFoxx64
|
||||
- Detwyler_
|
||||
- DisrespectfulOtter
|
||||
- xnick2222x
|
||||
- greg
|
||||
- Omar Alejandro
|
||||
- Cosmicrush
|
||||
- blubs
|
||||
- Bernerd
|
||||
|
||||
*/
|
||||
|
||||
void(float id, string graphic, string name, string description) Achievement_Create =
|
||||
{
|
||||
if (id >= MAX_ACHIEVEMENTS)
|
||||
return;
|
||||
|
||||
achievements[id].img = strcat("gfx/achievement/", graphic, ".tga");
|
||||
achievements[id].name = name;
|
||||
achievements[id].description = description;
|
||||
}
|
||||
|
||||
void() Achievement_Save =
|
||||
{
|
||||
local float file, i;
|
||||
|
||||
// re-write the achievement file
|
||||
file = fopen("ach.dat", FILE_WRITE);
|
||||
for (i = 0; i < MAX_ACHIEVEMENTS; i++) {
|
||||
fputs(file, strcat(ftos(achievements[i].unlocked), "\n"));
|
||||
fputs(file, strcat(ftos(achievements[i].progress), "\n"));
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void() Achievement_Load =
|
||||
{
|
||||
float file, i;
|
||||
string val;
|
||||
|
||||
file = fopen("ach.dat", FILE_READ);
|
||||
|
||||
if (file == -1) {
|
||||
fclose(file);
|
||||
file = fopen("ach.dat", FILE_WRITE);
|
||||
|
||||
for (i = 0; i < MAX_ACHIEVEMENTS * 2; i++) {
|
||||
fputs(file, "0\n");
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
file = fopen("ach.dat", FILE_READ);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_ACHIEVEMENTS; i++) {
|
||||
val = fgets(file);
|
||||
achievements[i].unlocked = stof(val);
|
||||
val = fgets(file);
|
||||
achievements[i].progress = stof(val);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void() Achievement_Init =
|
||||
{
|
||||
Achievement_Create(0, "ready", "Ready..", "Reach Round 5");
|
||||
Achievement_Create(1, "steady", "Steady..", "Reach Round 10");
|
||||
Achievement_Create(2, "go_hell_no", "Go? Hell No...", "Reach Round 15");
|
||||
Achievement_Create(3, "where_legs_go", "Where Did Legs Go?", "Turn a Zombie into a Crawler");
|
||||
Achievement_Create(4, "the_f_bomb", "The F Bomb", "Use the Nuke Power-Up to kill a single Zombie");
|
||||
Achievement_Create(5, "no_perks_no_problem", "No Perks? No Problem", "Survive an entire Round without Perks past Round 15 or higher");
|
||||
Achievement_Create(6, "dipsomaniac", "Dipsomaniac", "Hold all Perk-A-Colas at once in a single Game");
|
||||
Achievement_Create(7, "oops", "Oops!", "Die from fall damage");
|
||||
Achievement_Create(8, "abstinence_program", "Abstinence Program", "Survive to Round 10 without taking any enemy damage");
|
||||
Achievement_Create(9, "pro_gamer_move", "Pro-Gamer Move", "Die on Round 1 with no Ammo remaining");
|
||||
Achievement_Create(10, "spinning_plates", "Spinning Plates", "Keep entry points Barricaded all the way to Round 10");
|
||||
Achievement_Create(11, "unlucky", "Unlucky", "Have the Mystery Box move 10 times");
|
||||
Achievement_Create(12, "the_collector", "The Collector", "Buy every weapon off the wall in a single Game");
|
||||
Achievement_Create(13, "barrels_o_fun", "Barrels o' Fun", "In Nacht der Untoten, kill 15 Zombies with Explosive Barrels");
|
||||
Achievement_Create(14, "its_a_trap", "It's a Trap!", "In Kino der Toten, kill 5 Crawlers with the use of 1 Trap");
|
||||
Achievement_Create(15, "uplink", "Up-Link", "In Kino der Toten, teleport to the Pack-A-Punch 5 times in a single Game");
|
||||
Achievement_Create(16, "undone", "Undone", "Survive a total of 150 Rounds on Nacht der Untoten");
|
||||
Achievement_Create(17, "moviegoer", "Moviegoer", "Play 10 total Matches on Kino der Toten");
|
||||
Achievement_Create(18, "cmere_cupcake", "C'mere, Cupcake!", "Kill yourself with your own Grenade");
|
||||
Achievement_Create(19, "orbital_strike", "Orbital Strike", "Kill 5 Zombies at once, with the Panzerschreck, while in the air");
|
||||
Achievement_Create(20, "long_name", "A House Divided, Multiplied, then Subtracted", "In Nacht der Untoten, reach Round 10 without going upstairs & without fixing Barriers, then go upstairs & allow those Barriers to be Destroyed");
|
||||
Achievement_Create(21, "colt_hearted_killer", "Colt-Hearted Killer", "Reach Round 10 using only the Colt M1911");
|
||||
Achievement_Create(22, "cache_and_carry", "Cannot Cache and Carry", "Collected a Max Ammo power-up whilst already being at fully ammo capacity");
|
||||
Achievement_Create(23, "divide_and_conquer", "Divide and Conquer", "Turn all Zombies into Crawlers in a single Round");
|
||||
Achievement_Create(24, "tough_luck", "Tough Luck!", "Die before reaching Round 5");
|
||||
Achievement_Create(25, "gregg", "All Are One with Gregg!", "???");
|
||||
Achievement_Create(26, "slasher", "Slasher", "Perform 100 total Melee kills");
|
||||
Achievement_Create(27, "made_by_children", "Made by Children", "Get a Zombie stuck for 5 minutes");
|
||||
Achievement_Create(28, "increase_firepower", "Increase your Firepower!", "Use the Pack-A-Punch for the first time");
|
||||
Achievement_Create(29, "kraut_tongue", "Kraut Got Your Tongue?", "Get 25 Headshots");
|
||||
Achievement_Create(30, "mindblowing", "Mindblowing", "Get 250 Headshots");
|
||||
Achievement_Create(31, "thanks_explosions", "Big Thanks to Explosions", "Kill 10 Zombies with a single Grenade");
|
||||
Achievement_Create(32, "mbox_maniac", "Mystery Box Manaic", "Use the Mystery Box 20 times in a single Game");
|
||||
Achievement_Create(33, "instant_help", "Instant Help", "Get 100 total Kills with the Insta-Kill Power-Up");
|
||||
Achievement_Create(34, "blow_the_bank", "Blow the Bank", "Earn 1,000,000 Points");
|
||||
Achievement_Create(35, "why_wait", "..Why Are We Waiting?", "Stand Still for 2 minutes");
|
||||
Achievement_Create(36, "one_clip", "One Clip", "Survive a Round using the MG42 and without Reloading");
|
||||
Achievement_Create(37, "2021", "Twenty-Twenty-One", "Land 20 Headshots, with 20 Bullets, with one Clip");
|
||||
Achievement_Create(38, "warmed_up", "Getting Warmed Up", "Earn 10 Achievements");
|
||||
Achievement_Create(39, "half_way", "About Half-Way", "Earn 20 Achievements");
|
||||
Achievement_Create(40, "75_percent", "I mean.. 75% is Passing", "Earn 30 Achievements");
|
||||
Achievement_Create(41, "over_achiever", "Over-Achiever", "Earn all 42 Achievements");
|
||||
|
||||
Achievement_Load();
|
||||
|
||||
achievement_pages = ceil(MAX_ACHIEVEMENTS/3);
|
||||
current_achievement_page = 1;
|
||||
|
||||
active_achievement = -1;
|
||||
}
|
||||
|
||||
void(float id) Achievement_Unlock =
|
||||
{
|
||||
local float file, i;
|
||||
|
||||
achievements[id].unlocked = 1;
|
||||
|
||||
// tell the HUD to start drawing
|
||||
active_achievement = id;
|
||||
|
||||
Achievement_Save();
|
||||
}
|
||||
|
||||
void(float id, float pg) Achievement_UpdateProgress =
|
||||
{
|
||||
achievements[id].progress = pg;
|
||||
|
||||
Achievement_Save();
|
||||
}
|
219
source/client/defs/custom.qc
Normal file
219
source/client/defs/custom.qc
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
client/defs/custom.qc
|
||||
|
||||
Various globals that are used in this FTEQW example are defined
|
||||
here, they are not used by the engine itself.
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#pragma warning disable Q302
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
vector cursor_pos; /* Current mouse cursor position, updated in csqc_inputevent */
|
||||
float g_width, g_height; /* Globals for screen width and height */
|
||||
|
||||
float walk;
|
||||
|
||||
//Menu stuff
|
||||
float in_menu; //what menu are we in
|
||||
float time_in_menu;
|
||||
|
||||
entity player;
|
||||
entity vmodel;
|
||||
entity v2model;
|
||||
entity mzlflash;
|
||||
entity dummy;
|
||||
|
||||
float weapon;
|
||||
|
||||
float tracercounter;
|
||||
.float rate;
|
||||
.vector targetpos;
|
||||
|
||||
vector vmodel_targetpos;
|
||||
vector v2model_targetpos;
|
||||
vector vmodel_currentpos;
|
||||
vector v2model_currentpos;
|
||||
vector vmodel_velocity;
|
||||
vector v2model_velocity;
|
||||
vector vmodel_avelocity;
|
||||
vector v2model_avelocity;
|
||||
vector vmodel_muzzleoffset;
|
||||
vector v2model_muzzleoffset;
|
||||
|
||||
const float MENU_NONE = 0;
|
||||
const float MENU_MAIN = 1;
|
||||
const float MENU_SINGLE = 2;
|
||||
const float MENU_MULTI = 4;
|
||||
const float MENU_SETTINGS = 8;
|
||||
const float MENU_ABOUT = 16;
|
||||
const float MENU_JOIN = 32;
|
||||
const float MENU_PAUSE = 64;
|
||||
const float MENU_IGS = 128;
|
||||
const float MENU_RES = 256;
|
||||
const float MENU_GSETTINGS = 512;
|
||||
const float MENU_CSETTINGS = 1024;
|
||||
const float MENU_CUSTOMS = 2048;
|
||||
const float MENU_ACHIEVEMENTS = 4096;
|
||||
const float MENU_CONSETTINGS = 8192;
|
||||
const float MENU_AUDSETTINGS = 16384;
|
||||
|
||||
|
||||
float useprint_type;
|
||||
float useprint_weapon;
|
||||
float useprint_cost;
|
||||
float useprint_time;
|
||||
|
||||
string scrolltext;
|
||||
float stext;
|
||||
float scrollopacity;
|
||||
float scrollheight;
|
||||
|
||||
float HUD_Change_time;
|
||||
float Hitmark_time;
|
||||
float crosshair_spread_time;
|
||||
float zoom_2_time;
|
||||
float broadcast_time;
|
||||
float broadcast_type;
|
||||
|
||||
float weaponframetime;
|
||||
float weapon2frametime;
|
||||
float oldweaponframe;
|
||||
float oldweapon2frame;
|
||||
float curweaponframe;
|
||||
float curweapon2frame;
|
||||
float interpolating;
|
||||
float interpolating2;
|
||||
|
||||
|
||||
float rounds;
|
||||
float perks;
|
||||
float rounds_change;
|
||||
|
||||
float playerpoints[4]; // player point holders, player 1 points are index 0, player 2 at 1...
|
||||
float playerkills[4]; // player kill holders, player 1 points are index 0, player 2 at 1...
|
||||
string playernames[4]; // player name holders, player 1 name at index 0, player 2 at 1...
|
||||
float player_count;
|
||||
float score_show;
|
||||
|
||||
#define MAX_ACHIEVEMENTS 42
|
||||
|
||||
var struct achievementlist_t
|
||||
{
|
||||
string img;
|
||||
float unlocked;
|
||||
string name;
|
||||
string description;
|
||||
float progress;
|
||||
} achievements[MAX_ACHIEVEMENTS];
|
||||
|
||||
float active_achievement;
|
||||
float current_achievement_page;
|
||||
float achievement_pages;
|
||||
|
||||
|
||||
float K_LEFTDOWN, K_RIGHTDOWN, K_BACKDOWN, K_FORWARDDOWN;
|
||||
|
||||
#define P_JUG 1
|
||||
#define P_DOUBLE 2
|
||||
#define P_SPEED 4
|
||||
#define P_REVIVE 8
|
||||
#define P_FLOP 16
|
||||
#define P_STAMIN 32
|
||||
|
||||
vector TEXT_LIGHTBLUE = [(2/255), (118/255), (181/255)];
|
||||
vector TEXT_ORANGE = [(235/255), (189/255), 0];
|
||||
vector TEXT_GREEN = [0, (230/255), (34/255)];
|
||||
vector TEXT_RED = [1, 0, 0];
|
||||
|
||||
float fade_time;
|
||||
float fade_type;
|
||||
|
||||
float menu_initialized;
|
||||
|
||||
float customs_interact;
|
||||
|
||||
vector camang; // used for punches
|
||||
|
||||
//world text
|
||||
string chaptertitle;
|
||||
string location;
|
||||
string date;
|
||||
string person;
|
||||
|
||||
//custom hud
|
||||
string huddir;
|
||||
|
||||
//this just cleans up settings a bit..
|
||||
#define S_ENABLED "Enabled"
|
||||
#define S_DISABLED "Disabled"
|
||||
float wasigs;
|
||||
|
||||
//controls
|
||||
#define MAX_BINDS 14
|
||||
|
||||
float editBind[MAX_BINDS];
|
||||
string buttonBind[MAX_BINDS];
|
||||
string tempBind[MAX_BINDS];
|
||||
|
||||
// resolution
|
||||
#define MAX_43 3
|
||||
#define MAX_54 1
|
||||
#define MAX_1610 5
|
||||
#define MAX_169 10
|
||||
#define MAX_219 2
|
||||
float aspectratio;
|
||||
float fullscreenval;
|
||||
float active_swidth;
|
||||
float active_sheight;
|
||||
float screen_width_43[MAX_43];
|
||||
float screen_height_43[MAX_43];
|
||||
float screen_width_54[MAX_54];
|
||||
float screen_height_54[MAX_54];
|
||||
float screen_width_1610[MAX_1610];
|
||||
float screen_height_1610[MAX_1610];
|
||||
float screen_width_169[MAX_169];
|
||||
float screen_height_169[MAX_169];
|
||||
float screen_width_219[MAX_219];
|
||||
float screen_height_219[MAX_219];
|
||||
|
||||
//controller buttons
|
||||
|
||||
/*
|
||||
reference:
|
||||
0: A
|
||||
1: B
|
||||
2: X
|
||||
3: Y
|
||||
4: DPAD UP
|
||||
5: DPAD DOWN
|
||||
6: DPAD LEFT
|
||||
7: DPAD RIGHT
|
||||
|
||||
*/
|
||||
float GPActive[32];
|
||||
|
||||
string build_datetime;
|
||||
#define VERSION_STRING "v1.0"
|
2114
source/client/defs/fte.qc
Normal file
2114
source/client/defs/fte.qc
Normal file
File diff suppressed because it is too large
Load diff
1430
source/client/hud.qc
Normal file
1430
source/client/hud.qc
Normal file
File diff suppressed because it is too large
Load diff
1091
source/client/main.qc
Normal file
1091
source/client/main.qc
Normal file
File diff suppressed because it is too large
Load diff
1932
source/client/menu.qc
Normal file
1932
source/client/menu.qc
Normal file
File diff suppressed because it is too large
Load diff
748
source/server/ai/ai_core.qc
Normal file
748
source/server/ai/ai_core.qc
Normal file
|
@ -0,0 +1,748 @@
|
|||
/*
|
||||
server/ai/ai_core.qc
|
||||
|
||||
ai stuff
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void(float what) play_sound_z;
|
||||
|
||||
void() path_corner_touch =
|
||||
{
|
||||
self.origin_z = self.origin_z + 32;
|
||||
setorigin(self, self.origin);
|
||||
self.classname = "path_corner";
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.solid = SOLID_NOT;
|
||||
self.touch = SUB_Null;
|
||||
setsize(self, '0 0 0 ', '0 0 0');
|
||||
if(!self.target)
|
||||
{
|
||||
if (self.spawnflags & 1)
|
||||
return;
|
||||
bprint(PRINT_HIGH, "path_corner with name: ");
|
||||
bprint(PRINT_HIGH, self.targetname);
|
||||
bprint(PRINT_HIGH, " has no target!\n");
|
||||
}
|
||||
}
|
||||
|
||||
//We want the path corner to drop to the ground and then we set it up 32 units so it's exact
|
||||
void() path_corner =
|
||||
{
|
||||
self.classname = "path_corner_set";
|
||||
self.movetype = MOVETYPE_BOUNCE;
|
||||
self.solid = SOLID_BBOX;
|
||||
self.touch = path_corner_touch;
|
||||
setsize(self, '0 0 0 ', '0 0 0');
|
||||
};
|
||||
|
||||
|
||||
void removeZombie();
|
||||
void() Respawn =
|
||||
{
|
||||
Current_Zombies--;
|
||||
removeZombie();
|
||||
};
|
||||
|
||||
entity(entity blarg) find_new_enemy =
|
||||
{
|
||||
local entity player;
|
||||
local entity closest;
|
||||
local float bestdist;
|
||||
local float dist;
|
||||
bestdist = 10000;
|
||||
closest = 0;
|
||||
|
||||
// FIXME - change to hellhound for old/unreleased Demo map support?
|
||||
if(self.classname == "ai_zombie" || self.classname == "ai_dog") {
|
||||
player = find(world,classname,"monkey");
|
||||
if(player) {
|
||||
return player;
|
||||
}
|
||||
|
||||
player = find(world,classname,"player");
|
||||
///////////////////////////////
|
||||
if(!player) {
|
||||
return world;
|
||||
}
|
||||
//////////////////////////////
|
||||
while(player) {
|
||||
if (player.downed == true) {
|
||||
return world;
|
||||
}
|
||||
|
||||
dist = vlen(self.origin - player.origin);
|
||||
if (dist < bestdist) {
|
||||
closest = player;
|
||||
bestdist = dist;
|
||||
}
|
||||
player = find(player,classname,"player");
|
||||
}
|
||||
return closest;
|
||||
|
||||
}
|
||||
if (self.classname != "wunder")
|
||||
bprint(PRINT_HIGH, "Error: Find_New_Enemy returns world! \n");
|
||||
return world;
|
||||
};
|
||||
|
||||
float() avoid_zombies =
|
||||
{
|
||||
local entity ent;
|
||||
ent = findradius(self.origin,23);//22.67
|
||||
makevectors(self.angles);
|
||||
float left_amount, right_amount;
|
||||
left_amount = right_amount = 0;
|
||||
while(ent)
|
||||
{
|
||||
if(ent.classname == "ai_zombie" && ent != self)
|
||||
{
|
||||
local vector vec_b;
|
||||
local float dot;
|
||||
//vec_b = normalize(self.origin - ent.origin);
|
||||
//dot = v_right * vec_b;
|
||||
//dot = self.angles_y - (dot > 0.5) ? 90 : 270;
|
||||
|
||||
vec_b = (self.origin - ent.origin);
|
||||
dot = (v_right_x * vec_b_x) + (v_right_y * vec_b_y);//dot product
|
||||
if(dot > 0)// on right
|
||||
right_amount++;
|
||||
else// on left
|
||||
left_amount++;
|
||||
}
|
||||
ent = ent.chain;
|
||||
}
|
||||
if(left_amount + right_amount == 0)
|
||||
return 0;
|
||||
|
||||
return (left_amount > right_amount) ? 15 : -15;
|
||||
};
|
||||
|
||||
float() push_away_zombies =
|
||||
{
|
||||
local entity ent;
|
||||
ent = findradius(self.origin,11);
|
||||
float return_value;
|
||||
return_value = 0;
|
||||
while(ent)
|
||||
{
|
||||
if(ent.classname == "ai_zombie" && ent != self)
|
||||
{
|
||||
vector push;
|
||||
push = ent.origin - self.origin;
|
||||
push_z = 0;
|
||||
push = normalize(push) * 10;
|
||||
|
||||
ent.velocity += push;
|
||||
return_value = 1;
|
||||
}
|
||||
ent = ent.chain;
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
void(float dist, vector vec) do_walk_to_vec =
|
||||
{
|
||||
if(dist == 0)
|
||||
return;
|
||||
|
||||
self.ideal_yaw = vectoyaw(vec - self.origin);
|
||||
if(self.outside == false)
|
||||
{
|
||||
push_away_zombies();
|
||||
//self.ideal_yaw += avoid_zombies(); //no longer relevant since our direction doesn't care about our yaw any more
|
||||
}
|
||||
ChangeYaw();
|
||||
vector new_velocity;
|
||||
|
||||
float len;
|
||||
len = vlen(self.origin - vec);
|
||||
|
||||
if(dist > len)//if we're moving past our goal position
|
||||
{
|
||||
dist = len;
|
||||
}
|
||||
//This movement method is moving directly towards the goal, regardless of where our yaw is facing (fixes several issues)
|
||||
new_velocity = normalize(vec - self.origin) * dist * 10;
|
||||
|
||||
new_velocity_z = self.velocity_z;
|
||||
self.velocity = new_velocity;
|
||||
};
|
||||
|
||||
void(float dist) do_walk =
|
||||
{
|
||||
do_walk_to_vec(dist,self.goalentity.origin);
|
||||
};
|
||||
|
||||
void(float dist) walk_to_window =
|
||||
{
|
||||
do_walk_to_vec(dist,self.goalorigin);
|
||||
};
|
||||
|
||||
// unused
|
||||
void(vector org, float scale) interpolateToVector =
|
||||
{
|
||||
self.origin_x += (org_x - self.origin_x) * scale;
|
||||
self.origin_y += (org_y - self.origin_y) * scale;
|
||||
setorigin(self,self.origin);
|
||||
self.zoom = 1;//value to let engine know to not check for collisions
|
||||
}
|
||||
|
||||
float(vector where) nearby =
|
||||
{
|
||||
if(self.classname == "ai_zombie")
|
||||
{
|
||||
float xdist;
|
||||
float ydist;
|
||||
float zdist;
|
||||
xdist = fabs(self.origin_x - where_x);
|
||||
ydist = fabs(self.origin_y - where_y);
|
||||
zdist = fabs(self.origin_z - where_z);
|
||||
|
||||
if(xdist < 4 && ydist < 4)//horizontal distance is fairly close
|
||||
{
|
||||
if(zdist < 50)//vertical distance just has to be arbitrarily close
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*else if(self.classname == "ai_hellhound")
|
||||
{
|
||||
if(vlen(self.origin - what.origin) < 35)
|
||||
{
|
||||
if(vlen(self.origin - what.origin) < 6)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
interpolateToVector(what.origin,0.25);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return 0;
|
||||
};
|
||||
|
||||
void(float dist) Window_Walk =
|
||||
{
|
||||
if(self.reload_delay < time)
|
||||
Respawn();
|
||||
|
||||
if(self.hop_step == 0)//following path corners
|
||||
{
|
||||
if(self.goalentity == world)
|
||||
{
|
||||
if((!self.target) && (self.outside == TRUE))
|
||||
{
|
||||
bprint(PRINT_HIGH, "Error: Outside zombie spawn point has no target.\n");
|
||||
Respawn();
|
||||
}
|
||||
self.goalentity = find(world,targetname, self.target);
|
||||
if(!self.goalentity)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Error: Outside zombie spawn point target does not exist.\n");
|
||||
Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
if(self.goalentity.classname == "path_corner" && nearby(self.goalentity.origin))
|
||||
{
|
||||
if (self.goalentity.spawnflags & 1) //this path corner sets zombie on inside.
|
||||
{
|
||||
self.outside = FALSE;
|
||||
self.goalentity = world;
|
||||
self.enemy = find_new_enemy(self);
|
||||
self.th_walk();
|
||||
return;
|
||||
}
|
||||
self.reload_delay = time + 30;
|
||||
self.goalentity = find(world,targetname,self.goalentity.target);
|
||||
|
||||
//Assumption is that when the zombie is outside, we can always walk from one path_corner to the next in a straight line, any devation should be corrected by the mapper
|
||||
}
|
||||
|
||||
do_walk(dist);
|
||||
|
||||
if(self.goalentity.classname == "window")
|
||||
{
|
||||
if(!self.goalentity.box1owner)
|
||||
{
|
||||
//self.used = WBOX1;
|
||||
self.goalentity.box1owner = self;
|
||||
self.goalorigin = self.goalentity.box1;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
}
|
||||
else if(!self.goalentity.box2owner)
|
||||
{
|
||||
//self.used = WBOX2;
|
||||
self.goalentity.box2owner = self;
|
||||
self.goalorigin = self.goalentity.box2;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
}
|
||||
else if(!self.goalentity.box3owner)
|
||||
{
|
||||
//self.used = WBOX3;
|
||||
self.goalentity.box3owner = self;
|
||||
self.goalorigin = self.goalentity.box3;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
}
|
||||
else if(vlen(self.origin - self.goalentity.origin) < 150)
|
||||
{
|
||||
//we don't claim the idlebox
|
||||
//self.used = WIDLEBOX;
|
||||
self.goalorigin = self.goalentity.idlebox;
|
||||
self.hop_step = 1;
|
||||
self.reload_delay = time + 30;
|
||||
}
|
||||
//else we continue walking to window until we either find one that's good, or we are close enough to chase idle_spot
|
||||
}
|
||||
}
|
||||
else if(self.hop_step == 1)//walking to the window's idle location
|
||||
{
|
||||
if(nearby(self.goalorigin))
|
||||
{
|
||||
self.hop_step = 2;
|
||||
self.reload_delay = time + 30;
|
||||
self.th_idle();
|
||||
}
|
||||
else
|
||||
{
|
||||
walk_to_window(dist);
|
||||
}
|
||||
}
|
||||
else if(self.hop_step == 2)//we're at idle box, waiting for a window attack box to be free...
|
||||
{
|
||||
if(!self.goalentity.box1owner)
|
||||
{
|
||||
//self.used = WBOX1;
|
||||
self.goalentity.box1owner = self;
|
||||
self.goalorigin = self.goalentity.box1;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
self.th_walk();
|
||||
}
|
||||
else if(!self.goalentity.box2owner)
|
||||
{
|
||||
//self.used = WBOX2;
|
||||
self.goalentity.box2owner = self;
|
||||
self.goalorigin = self.goalentity.box2;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
self.th_walk();
|
||||
}
|
||||
else if(!self.goalentity.box3owner)
|
||||
{
|
||||
//self.used = WBOX3;
|
||||
self.goalentity.box3owner = self;
|
||||
self.goalorigin = self.goalentity.box3;
|
||||
self.hop_step = 3;
|
||||
self.reload_delay = time + 30;
|
||||
self.th_walk();
|
||||
}
|
||||
}
|
||||
else if(self.hop_step == 3)//walking to window attack box
|
||||
{
|
||||
if(nearby(self.goalorigin))
|
||||
{
|
||||
self.hop_step = 4;
|
||||
self.reload_delay = time + 30;
|
||||
self.th_idle();
|
||||
}
|
||||
else
|
||||
{
|
||||
walk_to_window(dist);
|
||||
}
|
||||
}
|
||||
else if(self.hop_step == 4)//attacking box
|
||||
{
|
||||
if(self.chase_time < time)
|
||||
{
|
||||
if(self.angles_z != self.goalentity.angles_z)
|
||||
{
|
||||
self.ideal_yaw = self.goalentity.angles_z;
|
||||
ChangeYaw();
|
||||
return;
|
||||
}
|
||||
if(self.goalentity.health > 0)
|
||||
{
|
||||
self.reload_delay = time + 30;
|
||||
self.th_melee();
|
||||
if(rounds <= 5)
|
||||
self.chase_time = time + 1.5;
|
||||
else
|
||||
self.chase_time = time + 0.75;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(self.goalentity.health <= 0)
|
||||
{
|
||||
self.outside = 2;
|
||||
self.chase_time = 0;
|
||||
self.hop_step = 0;
|
||||
}
|
||||
else return;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// kind of a shoddy fix, but essentially what we do to fix
|
||||
// issues with zomb ents colliding with each other during hopping
|
||||
// is make sure we wait a bit longer before freeing the window for
|
||||
// another usage.
|
||||
//
|
||||
void() free_window =
|
||||
{
|
||||
self.usedent = world;
|
||||
}
|
||||
|
||||
void(float dist) Window_Hop =
|
||||
{
|
||||
if(self.hop_step == 0) {
|
||||
if(self.goalentity.box1owner == self) {//we're at center box.
|
||||
self.hop_step = 4;
|
||||
} else {
|
||||
self.hop_step = 1;//wait for box1 to be free so we can claim it and walk to it.
|
||||
self.th_idle();
|
||||
}
|
||||
}
|
||||
if(self.hop_step == 1) {//waiting idly for box1 to be free, when free, we will claim it.
|
||||
if(!self.goalentity.box1owner || self.goalentity.box1owner == self) {
|
||||
self.goalentity.box1owner = self;
|
||||
|
||||
if(self.goalentity.box2owner == self)
|
||||
self.goalentity.box2owner = world;
|
||||
if(self.goalentity.box3owner == self)
|
||||
self.goalentity.box3owner = world;
|
||||
|
||||
//self.used = WBOX1;
|
||||
|
||||
self.goalorigin = self.goalentity.box1;
|
||||
self.hop_step = 2;
|
||||
self.th_walk();
|
||||
}
|
||||
}
|
||||
if(self.hop_step == 2) {//we've claimed it, walk to box1
|
||||
if(nearby(self.goalorigin)) {
|
||||
self.hop_step = 4;
|
||||
self.angles = self.goalentity.angles;
|
||||
} else {
|
||||
walk_to_window(dist);
|
||||
}
|
||||
}
|
||||
|
||||
if(self.hop_step == 4 && self.chase_time < time) {//we're at this step because we already own box1, so don't even check if window is busy...
|
||||
if(!self.goalentity.usedent) {
|
||||
self.hop_step = 5;
|
||||
self.angles = self.goalentity.angles;
|
||||
self.goalentity.box1owner = world;//free box1
|
||||
self.goalentity.usedent = self;//we own the window
|
||||
//don't need to set goalorigin here
|
||||
//self.used = WWINDOW;
|
||||
self.chase_time = 0;
|
||||
self.th_windowhop();
|
||||
return;
|
||||
} else {
|
||||
self.tries++;
|
||||
self.chase_time = time + 0.2;
|
||||
if(self.tries > 10) {
|
||||
// wait enough time before freeing window, to give time for zomb to move.
|
||||
self.goalentity.think = free_window;
|
||||
self.goalentity.nextthink = time + 0.5;
|
||||
//self.goalentity.usedent = world;//free up the window if we've been waiting to hop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(self.hop_step == 6) {
|
||||
self.outside = FALSE;
|
||||
//self.goalentity.usedent = world;//free up the window, we're done hopping it
|
||||
//self.used = 0;
|
||||
self.goalentity.think = free_window;
|
||||
self.goalentity.nextthink = time + 0.5;
|
||||
self.goalentity = world;
|
||||
self.enemy = find_new_enemy(self);
|
||||
//self.th_die();
|
||||
self.th_walk();
|
||||
}
|
||||
}
|
||||
|
||||
float() TryWalkToEnemy =
|
||||
{
|
||||
//was tracebox
|
||||
float TraceResult;
|
||||
TraceResult = tracemove(self.origin,VEC_HULL_MIN,VEC_HULL_MAX,self.enemy.origin,TRUE,self);
|
||||
if(TraceResult == 1) {
|
||||
self.goalentity = self.enemy;
|
||||
self.chase_time = time + 7;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef PC
|
||||
float() SetUpGoalDummy =
|
||||
{
|
||||
self.goaldummy.origin = Get_Waypoint_Near(self);
|
||||
setorigin(self.goaldummy,self.goaldummy.origin);
|
||||
self.goalentity = self.goaldummy;
|
||||
|
||||
if (!self.goalentity)
|
||||
bprint(PRINT_HIGH, "Could not find waypoint for zombie\n");
|
||||
|
||||
return 1; //because we can't actually know if it was good or not... yet
|
||||
};
|
||||
#endif
|
||||
|
||||
void() PathfindToEnemy =
|
||||
{
|
||||
float path_result;
|
||||
float path_failure;
|
||||
|
||||
//just to stop any warns.
|
||||
path_failure = 0;
|
||||
|
||||
#ifndef PC
|
||||
path_result = Do_Pathfind_psp(self, self.enemy);
|
||||
#else
|
||||
path_result = Do_Pathfind(self, self.enemy);
|
||||
#endif
|
||||
|
||||
//FIXME - further test if this can equate to 0 in FTE..
|
||||
if (path_result >= 1) {
|
||||
|
||||
#ifndef PC
|
||||
self.goaldummy.origin = Get_First_Waypoint(self, self.origin, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
setorigin(self.goaldummy, self.goaldummy.origin);
|
||||
path_failure = path_result;
|
||||
#else
|
||||
self.goalway = path_result;
|
||||
setorigin(self.goaldummy,waypoints[self.goalway].org);
|
||||
path_failure = self.goalway;
|
||||
#endif
|
||||
|
||||
self.goalentity = self.goaldummy;
|
||||
self.chase_time = time + 7;
|
||||
|
||||
} else if (path_failure == -1) {
|
||||
self.goalentity = self.enemy;
|
||||
self.chase_time = time + 6;
|
||||
} else {
|
||||
#ifdef PC
|
||||
bprint(PRINT_HIGH, "FirstPathfind Failure\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void() NextPathfindToEnemy {
|
||||
// same as PathfindToEnemy on non-FTE platforms
|
||||
#ifndef PC
|
||||
float path_success;
|
||||
path_success = Do_Pathfind_psp(self,self.enemy);
|
||||
if(path_success ==1) {
|
||||
self.goaldummy.origin = Get_Next_Waypoint(self,self.origin,VEC_HULL_MIN,VEC_HULL_MAX);
|
||||
setorigin(self.goaldummy,self.goaldummy.origin);
|
||||
self.goalentity = self.goaldummy;
|
||||
self.chase_time = time + 7;
|
||||
} else if(path_success == -1){
|
||||
self.goalentity = self.enemy;
|
||||
self.chase_time = time + 6;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, "NextPathfind Failure\n"); // this lags like hell
|
||||
}
|
||||
#else
|
||||
self.way_cur++;
|
||||
|
||||
if (self.way_cur < 40 && self.way_path[self.way_cur] != -1) {
|
||||
self.goalway = self.way_path[self.way_cur];
|
||||
setorigin(self.goaldummy,waypoints[self.goalway-1].org);
|
||||
} else {
|
||||
self.way_cur = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
float(vector start, vector min, vector max, vector end, float nomonsters, entity forent) tracemove
|
||||
{
|
||||
//was tracebox
|
||||
traceline(start,end,nomonsters,forent);
|
||||
|
||||
if(trace_ent == forent || trace_endpos == end) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void(float dist) Inside_Walk = {
|
||||
if(self.enemy_timeout < time || self.enemy == world) {
|
||||
self.enemy_timeout = time + 5;
|
||||
local entity oldEnemy;
|
||||
oldEnemy = self.enemy;
|
||||
self.enemy = find_new_enemy(self);
|
||||
}
|
||||
//================Check for proximity to player ===========
|
||||
if(vlen(self.enemy.origin - self.origin) < 60) {
|
||||
if(self.enemy.classname == "monkey") {
|
||||
self.th_idle();
|
||||
}
|
||||
|
||||
if(self.attack_delay < time) {
|
||||
self.attack_delay = time + 1 + (1 * random());
|
||||
self.th_melee();
|
||||
self.goalentity = self.enemy;
|
||||
self.chase_time = time + 5;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(vlen(self.enemy.origin - self.origin) < 600) {//50 feet
|
||||
if(self.goalentity == self.enemy && self.chase_enemy_time > time) {
|
||||
return;
|
||||
}
|
||||
if(TryWalkToEnemy())
|
||||
{
|
||||
self.chase_enemy_time = time + 0.5;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(self.goalentity == self.enemy) {
|
||||
self.goalentity = self.goaldummy;
|
||||
self.chase_time = 0;
|
||||
}
|
||||
//============= No Target ====================
|
||||
if(self.goalentity == world) {//not sure when this would ever occur... but whatever.
|
||||
self.goalentity = self.goaldummy;
|
||||
}
|
||||
//============ GoalDummy is Target ============
|
||||
if(self.goalentity == self.goaldummy) {
|
||||
if(nearby(self.goaldummy.origin)) {
|
||||
#ifndef PC
|
||||
NextPathfindToEnemy();
|
||||
#else
|
||||
PathfindToEnemy();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(self.chase_time < time) {
|
||||
if(self.goaldummy.origin != world.origin && tracemove(self.origin,VEC_HULL_MIN,VEC_HULL_MAX,self.goalentity.origin,TRUE,self) == 1) {
|
||||
self.chase_time = time + 7;
|
||||
} else {
|
||||
PathfindToEnemy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.float droptime;
|
||||
void(float dist) Zombie_Walk = {
|
||||
//Resetting velocity from last frame (except for vertical)
|
||||
self.velocity_x = 0;
|
||||
self.velocity_y = 0;
|
||||
//self.flags = self.flags | FL_PARTIALGROUND;
|
||||
|
||||
//check_onfire();
|
||||
if (!(self.flags & FL_ONGROUND)) {
|
||||
|
||||
if (!self.droptime) {
|
||||
self.droptime = time + 1;
|
||||
} else if (self.droptime < time) {
|
||||
self.droptime = 0;
|
||||
//bprint(PRINT_HIGH, "not on ground\n");
|
||||
self.th_fall();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(self.outside == TRUE) {
|
||||
//handle special walk case for walking to org
|
||||
Window_Walk(dist);
|
||||
return;
|
||||
}
|
||||
|
||||
if(self.outside == 2) {
|
||||
//play_sound_z(2);
|
||||
Window_Hop(dist);
|
||||
//handle special walk case for walking to org
|
||||
return;
|
||||
}
|
||||
if(self.outside == FALSE) {
|
||||
if(self.goalentity == self.enemy) {
|
||||
if(vlen(self.origin - self.enemy.origin) < 60) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
do_walk(dist);
|
||||
}
|
||||
|
||||
void() Zombie_AI = {
|
||||
//dist = 0;
|
||||
float dist = 0;
|
||||
self.flags = self.flags | FL_PARTIALGROUND;
|
||||
//check_onfire();
|
||||
|
||||
if(self.outside == TRUE) {
|
||||
play_sound_z(2);
|
||||
//self.calc_time = time + (0.3 * random());
|
||||
//Window_Walk(dist);
|
||||
return;
|
||||
} else if(self.outside == 2) {
|
||||
play_sound_z(2);
|
||||
//Window_Hop(0);
|
||||
return;
|
||||
} else if(self.outside == FALSE) {
|
||||
play_sound_z(2);
|
||||
//self.calc_time = time + (0.25 + (0.15 * random()));
|
||||
Inside_Walk(dist);
|
||||
}
|
||||
}
|
||||
|
||||
//This function ensures that only one zombie's ai is done at a time, brings down lag significantly
|
||||
void() Do_Zombie_AI = {
|
||||
local entity z;
|
||||
|
||||
z = find(lastzombie,aistatus,"1");
|
||||
if(z == world) {
|
||||
z = find(world,aistatus,"1");
|
||||
if(z == world) {
|
||||
return;//no zombies alive.
|
||||
}
|
||||
}
|
||||
local entity oself;
|
||||
oself = self;
|
||||
self = z;
|
||||
//if(z.classname == "ai_zombie")//removed because only zombies atm
|
||||
Zombie_AI();
|
||||
self = oself;
|
||||
lastzombie = z;
|
||||
}
|
274
source/server/ai/crawler_core.qc
Normal file
274
source/server/ai/crawler_core.qc
Normal file
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
server/ai/crawler_core.qc
|
||||
|
||||
crawler things
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
//========================= Crawling ===========================
|
||||
void() zombie_crawl1;
|
||||
void() crawlerify1;
|
||||
|
||||
void() Crawler_Walk_Setup
|
||||
{
|
||||
zombie_crawl1();
|
||||
}
|
||||
|
||||
|
||||
void() crawler_footstep
|
||||
{
|
||||
if(self.laststep == 1)
|
||||
{
|
||||
self.laststep = 0;
|
||||
sound(self,CHAN_VOICE,"sounds/zombie/sc0.wav",1,ATTN_NORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.laststep = 1;
|
||||
sound(self,CHAN_VOICE,"sounds/zombie/sc1.wav",1,ATTN_NORM);
|
||||
}
|
||||
}
|
||||
|
||||
//14-28
|
||||
void() zombie_crawl1 =[ 0, zombie_crawl2 ] {Zombie_Walk(2.955);SetZombieHitBox(CRAWLER_BBOX);/*if(freeze_time < time)*/ self.frame = 14;Zombie_Think();};
|
||||
void() zombie_crawl2 =[ 1, zombie_crawl3 ] {Zombie_Walk(3.841); self.frame = 15;Zombie_Think();};
|
||||
void() zombie_crawl3 =[ 2, zombie_crawl4 ] {Zombie_Walk(0.886); self.frame = 16;Zombie_Think();};
|
||||
void() zombie_crawl4 =[ 3, zombie_crawl5 ] {Zombie_Walk(1.871); self.frame = 17;Zombie_Think();};
|
||||
void() zombie_crawl5 =[ 4, zombie_crawl6 ] {Zombie_Walk(3.25); self.frame = 18;Zombie_Think();};
|
||||
void() zombie_crawl6 =[ 5, zombie_crawl7 ] {Zombie_Walk(1.314); self.frame = 19;Zombie_Think();};
|
||||
void() zombie_crawl7 =[ 6, zombie_crawl8 ] {Zombie_Walk(0.908); self.frame = 20;Zombie_Think();crawler_footstep();};//footstep
|
||||
void() zombie_crawl8 =[ 7, zombie_crawl9 ] {Zombie_Walk(0.776); self.frame = 21;Zombie_Think();};
|
||||
void() zombie_crawl9 =[ 8, zombie_crawl10 ] {Zombie_Walk(0.698); self.frame = 22;Zombie_Think();};
|
||||
void() zombie_crawl10 =[ 9, zombie_crawl11 ] {Zombie_Walk(0.641); self.frame = 23;Zombie_Think();};
|
||||
void() zombie_crawl11 =[ 10, zombie_crawl12 ] {Zombie_Walk(0.588); self.frame = 24;Zombie_Think();};
|
||||
void() zombie_crawl12 =[ 11, zombie_crawl13 ] {Zombie_Walk(0.295); self.frame = 25;Zombie_Think();};
|
||||
void() zombie_crawl13 =[ 12, zombie_crawl14 ] {Zombie_Walk(1.182); self.frame = 26;Zombie_Think();};
|
||||
void() zombie_crawl14 =[ 13, zombie_crawl15 ] {Zombie_Walk(0.492); self.frame = 27;Zombie_Think();};
|
||||
void() zombie_crawl15 =[ 14, Crawler_Walk_Setup ] {Zombie_Walk(2.856); self.frame = 28;Zombie_Think();crawler_footstep();};//footstep
|
||||
|
||||
//====================== Zombie To Crawler =======================
|
||||
//0-4
|
||||
void() crawlerify1 =[ 0, crawlerify2 ] {SetZombieHitBox(CRAWLER_BBOX); self.frame = 0;Zombie_Think();};
|
||||
void() crawlerify2 =[ 1, crawlerify3 ] {self.frame = 1;Zombie_Think();};
|
||||
void() crawlerify3 =[ 2, crawlerify4 ] {self.frame = 2;Zombie_Think();};
|
||||
void() crawlerify4 =[ 3, crawlerify5 ] {self.frame = 3;Zombie_Think();crawler_footstep();crawler_footstep();};//hit floor
|
||||
void() crawlerify5 =[ 4, Crawler_Walk_Setup ] {self.frame = 4;Zombie_Think();if(self.health <= 0) self.th_die();};//need to check for death since a grenade will not kill a zombie, only make him a crawler
|
||||
|
||||
//====================== Crawler Idle ==============================
|
||||
//4-13
|
||||
void() crawler_idle1 =[ 0, crawler_idle2 ] {SetZombieHitBox(CRAWLER_BBOX);Zombie_Walk(0); self.frame = 4;Zombie_Think();};
|
||||
void() crawler_idle2 =[ 1, crawler_idle3 ] {Zombie_Walk(0); self.frame = 5;Zombie_Think();};
|
||||
void() crawler_idle3 =[ 2, crawler_idle4 ] {Zombie_Walk(0); self.frame = 6;Zombie_Think();};
|
||||
void() crawler_idle4 =[ 3, crawler_idle5 ] {Zombie_Walk(0); self.frame = 7;Zombie_Think();};
|
||||
void() crawler_idle5 =[ 4, crawler_idle6 ] {Zombie_Walk(0); self.frame = 8;Zombie_Think();};
|
||||
void() crawler_idle6 =[ 5, crawler_idle7 ] {Zombie_Walk(0); self.frame = 9;Zombie_Think();};
|
||||
void() crawler_idle7 =[ 6, crawler_idle8 ] {Zombie_Walk(0); self.frame = 10;Zombie_Think();};
|
||||
void() crawler_idle8 =[ 7, crawler_idle9 ] {Zombie_Walk(0); self.frame = 11;Zombie_Think();};
|
||||
void() crawler_idle9 =[ 8, crawler_idle10 ] {Zombie_Walk(0); self.frame = 12;Zombie_Think();};
|
||||
void() crawler_idle10 =[ 9, crawler_idle1 ] {Zombie_Walk(0); self.frame = 13;Zombie_Think();};
|
||||
//===================== Crawler Attack ===========================
|
||||
//29-36
|
||||
void() crawler_atk1 =[ 0, crawler_atk2] {SetZombieHitBox(CRAWLER_BBOX);self.frame = 29;Zombie_Think();};
|
||||
void() crawler_atk2 =[ 1, crawler_atk3] {self.frame = 30;Zombie_Think();};
|
||||
void() crawler_atk3 =[ 2, crawler_atk4] {self.frame = 31;Zombie_Think();};
|
||||
void() crawler_atk4 =[ 3, crawler_atk5] {self.frame = 32;zombie_attack2();Zombie_Think();};
|
||||
void() crawler_atk5 =[ 4, crawler_atk6] {self.frame = 33;Zombie_Think();};
|
||||
void() crawler_atk6 =[ 5, crawler_atk7] {self.frame = 34;Zombie_Think();};
|
||||
void() crawler_atk7 =[ 6, crawler_atk8] {self.frame = 35;Zombie_Think();};
|
||||
void() crawler_atk8 =[ 7, zombie_decide] {self.frame = 36;Zombie_Think();};
|
||||
|
||||
//====================== Crawler Delay Attack ==============================
|
||||
//4-13
|
||||
|
||||
void(float which) crawler_attack_choose =
|
||||
{
|
||||
self.angles_y = vectoyaw(self.enemy.origin - self.origin);
|
||||
if(which != 1)
|
||||
{
|
||||
if(random() > 0.2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(vlen(self.enemy.origin - self.origin) > 60)//too far, cancel attack
|
||||
{
|
||||
zombie_decide();
|
||||
return;
|
||||
}
|
||||
play_sound_z(1);
|
||||
|
||||
crawler_atk1();
|
||||
};
|
||||
|
||||
|
||||
void() crawler_da1 =[ 0, crawler_da2 ] {SetZombieHitBox(CRAWLER_BBOX);crawler_attack_choose(0); self.frame = 4;Zombie_Think();};
|
||||
void() crawler_da2 =[ 1, crawler_da3 ] {crawler_attack_choose(0); self.frame = 5;Zombie_Think();};
|
||||
void() crawler_da3 =[ 2, crawler_da4 ] {crawler_attack_choose(0); self.frame = 6;Zombie_Think();};
|
||||
void() crawler_da4 =[ 3, crawler_da5 ] {crawler_attack_choose(0); self.frame = 7;Zombie_Think();};
|
||||
void() crawler_da5 =[ 4, crawler_da6 ] {crawler_attack_choose(0); self.frame = 8;Zombie_Think();};
|
||||
void() crawler_da6 =[ 5, crawler_da7 ] {crawler_attack_choose(0); self.frame = 9;Zombie_Think();};
|
||||
void() crawler_da7 =[ 6, crawler_da8 ] {crawler_attack_choose(0); self.frame = 10;Zombie_Think();};
|
||||
void() crawler_da8 =[ 7, crawler_da9 ] {crawler_attack_choose(0); self.frame = 11;Zombie_Think();};
|
||||
void() crawler_da9 =[ 8, crawler_da10 ] {crawler_attack_choose(0); self.frame = 12;Zombie_Think();};
|
||||
void() crawler_da10 =[ 9, crawler_da1 ] {crawler_attack_choose(0); self.frame = 13;Zombie_Think();};
|
||||
|
||||
|
||||
//====================== Crawler Death ============================
|
||||
//37-39
|
||||
void() crawler_die1 =[ 0, crawler_die2] {SetZombieHitBox(CRAWLER_BBOX);self.frame = 37;};
|
||||
void() crawler_die2 =[ 1, crawler_die3] {self.frame = 38;};
|
||||
void() crawler_die3 =[ 2, SUB_Null] {self.iszomb = 0; self.frame = 39;self.nextthink = time + 3;self.think = removeZombie; addmoney(other, 60, true); if (crawler_num > 0) {crawler_num = crawler_num - 1;}};
|
||||
|
||||
//======================== Climb Over Barricade ====================
|
||||
//40-70
|
||||
void() crawler_climbBarricade1 =[ 0, crawler_climbBarricade2] {self.movetype = MOVETYPE_STEP;self.zoom = 1;self.frame = 40;Zombie_Think();};
|
||||
void() crawler_climbBarricade2 =[ 1, crawler_climbBarricade3] {self.frame = 41; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade3 =[ 2, crawler_climbBarricade4] {self.frame = 42; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade4 =[ 3, crawler_climbBarricade5] {self.frame = 43; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade5 =[ 4, crawler_climbBarricade6] {self.frame = 44; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade6 =[ 5, crawler_climbBarricade7] {self.frame = 45; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade7 =[ 6, crawler_climbBarricade8] {self.frame = 46; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade8 =[ 7, crawler_climbBarricade9] {self.frame = 47; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade9 =[ 8, crawler_climbBarricade10] {self.frame = 48; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade10 =[ 9, crawler_climbBarricade11] {self.frame = 49; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade11 =[ 10, crawler_climbBarricade12] {self.frame = 50; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade12 =[ 11, crawler_climbBarricade13] {self.frame = 51; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade13 =[ 12, crawler_climbBarricade14] {self.frame = 52; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade14 =[ 13, crawler_climbBarricade15] {self.frame = 53; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade15 =[ 14, crawler_climbBarricade16] {self.frame = 54; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade16 =[ 15, crawler_climbBarricade17] {self.frame = 55; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade17 =[ 16, crawler_climbBarricade18] {self.frame = 56; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade18 =[ 17, crawler_climbBarricade19] {self.frame = 57; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade19 =[ 18, crawler_climbBarricade20] {self.frame = 58; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade20 =[ 19, crawler_climbBarricade21] {self.frame = 59; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade21 =[ 20, crawler_climbBarricade22] {self.frame = 60; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade22 =[ 21, crawler_climbBarricade23] {self.frame = 61; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade23 =[ 22, crawler_climbBarricade24] {self.frame = 62; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade24 =[ 23, crawler_climbBarricade25] {self.frame = 63; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade25 =[ 24, crawler_climbBarricade26] {self.frame = 64; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade26 =[ 25, crawler_climbBarricade27] {self.frame = 65; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade27 =[ 26, crawler_climbBarricade28] {self.frame = 66; moveforwardalittle(0);Zombie_Think();};
|
||||
void() crawler_climbBarricade28 =[ 27, crawler_climbBarricade29] {self.frame = 67; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade29 =[ 28, crawler_climbBarricade30] {self.frame = 68; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade30 =[ 29, crawler_climbBarricade31] {self.frame = 69; moveforwardalittle(1);Zombie_Think();};
|
||||
void() crawler_climbBarricade31 =[ 30, SUB_Null] {self.frame = 70; self.movetype = MOVETYPE_WALK; self.zoom = 1;self.state = 0;self.hop_step = 6; self.th_walk();Zombie_Think();};
|
||||
|
||||
//======================== Crawler Fall =============================
|
||||
//71 - 77
|
||||
void() crawler_fall1 =[ 0, crawler_fall2] {SetZombieHitBox(CRAWLER_BBOX);self.fall = TRUE;CheckLand();self.frame=71;Zombie_Think();};
|
||||
void() crawler_fall2 =[ 1, crawler_fall3] {self.fall = TRUE;CheckLand();self.frame=72;Zombie_Think();};
|
||||
void() crawler_fall3 =[ 2, crawler_fall4] {self.fall = TRUE;CheckLand();self.frame=73;Zombie_Think();};
|
||||
void() crawler_fall4 =[ 3, crawler_fall5] {self.fall = TRUE;CheckLand();self.frame=74;Zombie_Think();};
|
||||
void() crawler_fall5 =[ 4, crawler_fall6] {self.fall = TRUE;CheckLand();self.frame=75;Zombie_Think();};
|
||||
void() crawler_fall6 =[ 5, crawler_fall7] {self.fall = TRUE;CheckLand();self.frame=76;Zombie_Think();};
|
||||
void() crawler_fall7 =[ 6, crawler_fall1] {self.fall = TRUE;CheckLand();self.frame=77;Zombie_Think();};
|
||||
//======================== Crawler Land ============================
|
||||
//77-86
|
||||
void() crawler_land1 =[ 0, crawler_land2] {SetZombieHitBox(CRAWLER_BBOX);self.frame=77;Zombie_Think();};
|
||||
void() crawler_land2 =[ 1, crawler_land3] {self.frame=78;Zombie_Think();};
|
||||
void() crawler_land3 =[ 2, crawler_land4] {self.frame=79;Zombie_Think();};
|
||||
void() crawler_land4 =[ 3, crawler_land5] {self.frame=80;Zombie_Think();};
|
||||
void() crawler_land5 =[ 4, crawler_land6] {self.frame=81;Zombie_Think();};
|
||||
void() crawler_land6 =[ 5, crawler_land7] {self.frame=82;Zombie_Think();};
|
||||
void() crawler_land7 =[ 6, crawler_land8] {self.frame=83;Zombie_Think();};
|
||||
void() crawler_land8 =[ 7, crawler_land9] {self.frame=84;Zombie_Think();};
|
||||
void() crawler_land9 =[ 8, crawler_land10] {self.frame=85;Zombie_Think();};
|
||||
void() crawler_land10 =[ 9, Crawler_Walk_Setup] {self.frame=86;Zombie_Think();};
|
||||
//======================== Crawler Rip Board =======================
|
||||
//103-126
|
||||
|
||||
void() crawler_rip_board1 =[ 0, crawler_rip_board2] {SetZombieHitBox(CRAWLER_BBOX);self.frame=103;Zombie_Think();};
|
||||
void() crawler_rip_board2 =[ 1, crawler_rip_board3] {self.frame=104;Zombie_Think();};
|
||||
void() crawler_rip_board3 =[ 2, crawler_rip_board4] {self.frame=105;Zombie_Think();};
|
||||
void() crawler_rip_board4 =[ 3, crawler_rip_board5] {self.frame=106;Zombie_Think();};
|
||||
void() crawler_rip_board5 =[ 4, crawler_rip_board6] {self.frame=107;Zombie_Think();};
|
||||
void() crawler_rip_board6 =[ 5, crawler_rip_board7] {self.frame=108;Zombie_Think();};
|
||||
void() crawler_rip_board7 =[ 6, crawler_rip_board8] {self.frame=109;Zombie_Think();};
|
||||
void() crawler_rip_board8 =[ 7, crawler_rip_board9] {self.frame=110;Zombie_Think();};
|
||||
void() crawler_rip_board9 =[ 8, crawler_rip_board10] {self.frame=111;Zombie_Think();};
|
||||
void() crawler_rip_board10 =[ 9, crawler_rip_board11] {self.frame=112;Zombie_Think();};
|
||||
void() crawler_rip_board11 =[ 10, crawler_rip_board12] {self.frame=113;Zombie_Think();};
|
||||
void() crawler_rip_board12 =[ 11, crawler_rip_board13] {self.frame=114;Zombie_Think();};
|
||||
void() crawler_rip_board13 =[ 12, crawler_rip_board14] {self.frame=115;zombie_attack2();};
|
||||
void() crawler_rip_board14 =[ 13, crawler_rip_board15] {self.frame=116;Zombie_Think();};
|
||||
void() crawler_rip_board15 =[ 14, crawler_rip_board16] {self.frame=117;Zombie_Think();};
|
||||
void() crawler_rip_board16 =[ 15, crawler_rip_board17] {self.frame=118;Zombie_Think();};
|
||||
void() crawler_rip_board17 =[ 16, crawler_rip_board18] {self.frame=119;Zombie_Think();};
|
||||
void() crawler_rip_board18 =[ 17, crawler_rip_board19] {self.frame=120;Zombie_Think();};
|
||||
void() crawler_rip_board19 =[ 18, crawler_rip_board20] {self.frame=121;Zombie_Think();};
|
||||
void() crawler_rip_board20 =[ 19, crawler_rip_board21] {self.frame=122;Zombie_Think();};
|
||||
void() crawler_rip_board21 =[ 20, crawler_rip_board22] {self.frame=123;Zombie_Think();};
|
||||
void() crawler_rip_board22 =[ 21, crawler_rip_board23] {self.frame=124;Zombie_Think();};
|
||||
void() crawler_rip_board23 =[ 22, crawler_rip_board24] {self.frame=125;Zombie_Think();};
|
||||
void() crawler_rip_board24 =[ 23, zombie_decide] {self.frame=126;Zombie_Think();};
|
||||
|
||||
void(entity who) makeCrawler =
|
||||
{
|
||||
if(who.state == 1)
|
||||
{
|
||||
who.crawling = 2;
|
||||
return;
|
||||
}
|
||||
who.crawling = 2;//this means we haven't technically initiated it, but we're going to...
|
||||
|
||||
who.th_die = Zombie_Death;
|
||||
who.th_walk = Crawler_Walk_Setup;
|
||||
who.th_melee = zombie_attack;
|
||||
who.th_idle = crawler_idle1;
|
||||
who.th_windowhop = crawler_climbBarricade1;
|
||||
|
||||
who.th_fall = crawler_fall1;
|
||||
who.th_land = crawler_land1;
|
||||
|
||||
//who.th_jump = zombie_jump1;
|
||||
//who.th_grabledge = zombie_grabledge1;
|
||||
//who.th_diewunder = die_wunder1;
|
||||
|
||||
setmodel(who,"models/ai/zcbod.mdl");
|
||||
if(who.head.deadflag)
|
||||
{
|
||||
setmodel(who.head,"models/ai/zchead.mdl");
|
||||
//updateLimb (who, 0, world);
|
||||
}
|
||||
if(who.larm.deadflag)
|
||||
{
|
||||
setmodel(who.larm,"models/ai/zclarm.mdl");
|
||||
//updateLimb (who, 1, world);
|
||||
}
|
||||
if(who.rarm.deadflag)
|
||||
{
|
||||
setmodel(who.rarm,"models/ai/zcrarm.mdl");
|
||||
//updateLimb (who, 2, world);
|
||||
}
|
||||
who.crawling = 1;
|
||||
|
||||
setsize(who,'-8 -8 -32','8 8 -15');
|
||||
|
||||
local entity oself;
|
||||
oself = self;
|
||||
self = who;
|
||||
crawlerify1();
|
||||
self = oself;
|
||||
|
||||
crawler_num = crawler_num + 1;
|
||||
}
|
374
source/server/ai/dog_core.qc
Normal file
374
source/server/ai/dog_core.qc
Normal file
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
server/ai/dog_core.qc
|
||||
|
||||
dog things
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() Dog_Think;
|
||||
void() Dog_Death;
|
||||
|
||||
// DOG RUN
|
||||
// 0-6
|
||||
$frame dogrun1 dogrun2 dogrun3 dogrun4 dogrun5 dogrun6 dogrun7
|
||||
void() dog_runanim =[ $dogrun1, dog_runanim2 ] {Dog_Think();Zombie_Walk(25);self.frame = 0;};
|
||||
void() dog_runanim2 =[ $dogrun2, dog_runanim3 ] {Dog_Think();Zombie_Walk(15);self.frame = 1;};
|
||||
void() dog_runanim3 =[ $dogrun3, dog_runanim4 ] {Dog_Think();Zombie_Walk(15);self.frame = 2;};
|
||||
void() dog_runanim4 =[ $dogrun4, dog_runanim5 ] {Dog_Think();Zombie_Walk(15);self.frame = 3;};
|
||||
void() dog_runanim5 =[ $dogrun5, dog_runanim6 ] {Dog_Think();Zombie_Walk(15);self.frame = 4;};
|
||||
void() dog_runanim6 =[ $dogrun6, dog_runanim7 ] {Dog_Think();Zombie_Walk(15);self.frame = 5;};
|
||||
void() dog_runanim7 =[ $dogrun7, dog_runanim ] {Dog_Think();Zombie_Walk(15);self.frame = 6;};
|
||||
|
||||
// DOG WALK
|
||||
// 7-18
|
||||
$frame dogwalk1 dogwalk2 dogwalk3 dogwalk4 dogwalk5 dogwalk6 dogwalk7 dogwalk8 dogwalk9 dogwalk10 dogwalk11 dogwalk12
|
||||
void() dog_walkanim =[ $dogwalk1, dog_walkanim2 ] {Dog_Think();Zombie_Walk(8);self.frame = 7;};
|
||||
void() dog_walkanim2 =[ $dogwalk2, dog_walkanim3 ] {Dog_Think();Zombie_Walk(8);self.frame = 8;};
|
||||
void() dog_walkanim3 =[ $dogwalk3, dog_walkanim4 ] {Dog_Think();Zombie_Walk(8);self.frame = 9;};
|
||||
void() dog_walkanim4 =[ $dogwalk4, dog_walkanim5 ] {Dog_Think();Zombie_Walk(8);self.frame = 10;};
|
||||
void() dog_walkanim5 =[ $dogwalk5, dog_walkanim6 ] {Dog_Think();Zombie_Walk(8);self.frame = 11;};
|
||||
void() dog_walkanim6 =[ $dogwalk6, dog_walkanim7 ] {Dog_Think();Zombie_Walk(8);self.frame = 12;};
|
||||
void() dog_walkanim7 =[ $dogwalk7, dog_walkanim8 ] {Dog_Think();Zombie_Walk(8);self.frame = 13;};
|
||||
void() dog_walkanim8 =[ $dogwalk8, dog_walkanim9 ] {Dog_Think();Zombie_Walk(8);self.frame = 14;};
|
||||
void() dog_walkanim9 =[ $dogwalk9, dog_walkanim10 ] {Dog_Think();Zombie_Walk(8);self.frame = 15;};
|
||||
void() dog_walkanim10 =[ $dogwalk10, dog_walkanim11 ] {Dog_Think();Zombie_Walk(8);self.frame = 16;};
|
||||
void() dog_walkanim11 =[ $dogwalk11, dog_walkanim12 ] {Dog_Think();Zombie_Walk(8);self.frame = 17;};
|
||||
void() dog_walkanim12 =[ $dogwalk12, dog_walkanim ] {Dog_Think();Zombie_Walk(8);self.frame = 18;};
|
||||
|
||||
// DOG IDLE
|
||||
// 19-24
|
||||
$frame dogstand1 dogstand2 dogstand3 dogstand4 dogstand5 dogstand6
|
||||
void() dog_idleanim =[ $dogstand1, dog_idleanim2 ] {self.frame = 19;};
|
||||
void() dog_idleanim2 =[ $dogstand2, dog_idleanim3 ] {self.frame = 20;};
|
||||
void() dog_idleanim3 =[ $dogstand3, dog_idleanim4 ] {self.frame = 21;};
|
||||
void() dog_idleanim4 =[ $dogstand4, dog_idleanim5 ] {self.frame = 22;};
|
||||
void() dog_idleanim5 =[ $dogstand5, dog_idleanim6 ] {self.frame = 23;};
|
||||
void() dog_idleanim6 =[ $dogstand6, dog_idleanim ] {self.frame = 24;};
|
||||
|
||||
// DOG MELEE
|
||||
// 25-34
|
||||
$frame dogmelee1 dogmelee2 dogmelee3 dogmelee4 dogmelee5 dogmelee6 dogmelee7 dogmelee8 dogmelee9 dogmelee10
|
||||
void() dog_meleeanim =[ $dogmelee1, dog_meleeanim2 ] {Zombie_Walk(0);self.frame = 25;};
|
||||
void() dog_meleeanim2 =[ $dogmelee2, dog_meleeanim3 ] {Zombie_Walk(0);self.frame = 26;};
|
||||
void() dog_meleeanim3 =[ $dogmelee3, dog_meleeanim4 ] {Zombie_Walk(0);self.frame = 27;};
|
||||
void() dog_meleeanim4 =[ $dogmelee4, dog_meleeanim5 ] {Zombie_Walk(0);self.frame = 28;};
|
||||
void() dog_meleeanim5 =[ $dogmelee5, dog_meleeanim6 ] {Zombie_Walk(0);self.frame = 29;};
|
||||
void() dog_meleeanim6 =[ $dogmelee6, dog_meleeanim7 ] {Zombie_Walk(0);zombie_attack2();self.frame = 30;};
|
||||
void() dog_meleeanim7 =[ $dogmelee7, dog_meleeanim8 ] {Zombie_Walk(0);self.frame = 31;};
|
||||
void() dog_meleeanim8 =[ $dogmelee8, dog_meleeanim9 ] {Zombie_Walk(0);self.frame = 32;};
|
||||
void() dog_meleeanim9 =[ $dogmelee9, dog_meleeanim10 ] {Zombie_Walk(0);self.frame = 33;};
|
||||
void() dog_meleeanim10 =[ $dogmelee10, dog_runanim ] {Zombie_Walk(0);self.frame = 34;};
|
||||
|
||||
// DOG DEATH
|
||||
// 35 - 36
|
||||
$frame dogdeath1 dogdeath2
|
||||
void() dog_deathanim =[ $dogdeath1, dog_deathanim2 ] {self.frame = 35;};
|
||||
void() dog_deathanim2 =[ $dogdeath2, SUB_Null ] {self.nextthink = time + 3; self.think = removeZombie; self.frame = 36;};
|
||||
|
||||
// DOG WAFFE DEATH
|
||||
// 37-46
|
||||
$frame dogwunder1 dogwunder2 dogwunder3 dogwunder4 dogwunder5 dogwunder6 dogwunder7 dogwunder8 dogwunder9 dogwunder10
|
||||
void() die_dog_wunder1 =[ $dogwunder1, die_dog_wunder2 ] {Zombie_Walk(0);Zombie_Tesla_Light();self.frame = 37;};
|
||||
void() die_dog_wunder2 =[ $dogwunder2, die_dog_wunder3 ] {Zombie_Walk(0);self.frame = 38;};
|
||||
void() die_dog_wunder3 =[ $dogwunder3, die_dog_wunder4 ] {Zombie_Walk(0);self.frame = 39;};
|
||||
void() die_dog_wunder4 =[ $dogwunder4, die_dog_wunder5 ] {Zombie_Walk(0);self.frame = 40;};
|
||||
void() die_dog_wunder5 =[ $dogwunder5, die_dog_wunder6 ] {Zombie_Walk(0);self.frame = 41;};
|
||||
void() die_dog_wunder6 =[ $dogwunder6, die_dog_wunder7 ] {Zombie_Walk(0);Zombie_Find_Tesla_Target();self.frame = 42;};
|
||||
void() die_dog_wunder7 =[ $dogwunder7, die_dog_wunder8 ] {Zombie_Walk(0);self.frame = 43;};
|
||||
void() die_dog_wunder8 =[ $dogwunder8, die_dog_wunder9 ] {Zombie_Walk(0);self.frame = 44;};
|
||||
void() die_dog_wunder9 =[ $dogwunder9, die_dog_wunder10 ] {Zombie_Walk(0);self.frame = 45;};
|
||||
void() die_dog_wunder10 =[ $dogwunder10, die_dog_wunder10 ] {Zombie_Walk(0);self.frame = 46;self.health = 0; self.th_die();};
|
||||
|
||||
// DOG LIGHTNING SPAWN
|
||||
// 1-13
|
||||
$frame dls1 dls2 dls3 dls4 dls5 dls6 dls7 dls8 dls9 dls10 dls11 dls12 dls13
|
||||
void() dog_lightninganim =[ $dls1, dog_lightninganim2 ] {self.frame = 1;};
|
||||
void() dog_lightninganim2 =[ $dls2, dog_lightninganim3 ] {self.frame = 2;};
|
||||
void() dog_lightninganim3 =[ $dls3, dog_lightninganim4 ] {self.frame = 3;};
|
||||
void() dog_lightninganim4 =[ $dls4, dog_lightninganim5 ] {self.frame = 4;};
|
||||
void() dog_lightninganim5 =[ $dls5, dog_lightninganim6 ] {self.frame = 5;};
|
||||
void() dog_lightninganim6 =[ $dls6, dog_lightninganim7 ] {self.frame = 6;};
|
||||
void() dog_lightninganim7 =[ $dls7, dog_lightninganim8 ] {self.frame = 7;};
|
||||
void() dog_lightninganim8 =[ $dls8, dog_lightninganim9 ] {self.frame = 8;};
|
||||
void() dog_lightninganim9 =[ $dls9, dog_lightninganim10 ] {self.frame = 9;};
|
||||
void() dog_lightninganim10 =[ $dls10, dog_lightninganim11 ] {self.frame = 10;};
|
||||
void() dog_lightninganim11 =[ $dls11, dog_lightninganim12 ] {self.frame = 11;};
|
||||
void() dog_lightninganim12 =[ $dls12, dog_lightninganim13 ] {self.frame = 12;};
|
||||
void() dog_lightninganim13 =[ $dls13, SUB_Null ] {self.frame = 13; remove(self);};
|
||||
|
||||
// DOG EXPLODE SPRITE
|
||||
// 1-5
|
||||
$frame des1 des2 des3 des4 des5 des6
|
||||
void() dog_explodeanim =[ $des1, dog_explodeanim2 ] {self.frame = 1;};
|
||||
void() dog_explodeanim2 =[ $des2, dog_explodeanim3 ] {self.frame = 2;};
|
||||
void() dog_explodeanim3 =[ $des3, dog_explodeanim4 ] {self.frame = 3;};
|
||||
void() dog_explodeanim4 =[ $des4, dog_explodeanim5 ] {self.frame = 4;};
|
||||
void() dog_explodeanim5 =[ $des5, dog_explodeanim6 ] {self.frame = 5;};
|
||||
void() dog_explodeanim6 =[ $des5, SUB_Null ] {remove(self);};
|
||||
|
||||
void() Dog_Walk_Setup =
|
||||
{
|
||||
if (self.walktype == 1)
|
||||
dog_walkanim();
|
||||
else
|
||||
dog_runanim();
|
||||
};
|
||||
|
||||
// decide our walktype based on player distance
|
||||
void() Dog_Think =
|
||||
{
|
||||
// FIXME - crash
|
||||
self.walktype = 2;
|
||||
/*
|
||||
if(vlen(self.enemy.origin - self.origin) < 300)
|
||||
self.walktype = 2;
|
||||
else
|
||||
self.walktype = 1;*/
|
||||
}
|
||||
|
||||
float dogCount;
|
||||
void() Dog_Death =
|
||||
{
|
||||
self.aistatus = "0";
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
|
||||
sound(self,CHAN_WEAPON,"sounds/null.wav",1,ATTN_NORM);
|
||||
|
||||
self.usedent = world;
|
||||
|
||||
self.health = 0;
|
||||
Remaining_Zombies = Remaining_Zombies - 1;
|
||||
dogCount -= 1;
|
||||
|
||||
play_sound_z(3);
|
||||
//Gotta' make sure we set it back down instead of glitching it up, yo'
|
||||
if(self.s_time > 0 && sounds_playing > 0)
|
||||
{
|
||||
sounds_playing --;
|
||||
self.s_time = 0;
|
||||
}
|
||||
|
||||
if (rounds == dogRound)
|
||||
{
|
||||
if (!Remaining_Zombies)
|
||||
Spawn_Powerup(self.origin + '0 0 12', 1);
|
||||
}
|
||||
|
||||
float r = random();
|
||||
|
||||
// explode chance
|
||||
if (r < 0.75) {
|
||||
self.frame = 0;
|
||||
setmodel (self, "models/sprites/explosion.spr");
|
||||
sound (self, CHAN_WEAPON, "sounds/weapons/grenade/explode.wav", 1, ATTN_NORM);
|
||||
dog_explodeanim();
|
||||
} else {
|
||||
dog_deathanim();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void(entity where) spawn_a_dogB =
|
||||
{
|
||||
local entity sdog;//USED FOR WHAT TO SPAWN
|
||||
|
||||
sdog = getFreeZombieEnt(self);
|
||||
if(sdog == world)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sdog.origin = where.origin;
|
||||
sdog.frame = 0;
|
||||
|
||||
sdog.target = where.target;
|
||||
|
||||
sdog.solid = SOLID_CORPSE;
|
||||
sdog.movetype = MOVETYPE_WALK;
|
||||
setmodel(sdog, "models/ai/dog.mdl");
|
||||
sdog.hop_step = 0;
|
||||
sdog.gravity = 1.0;
|
||||
|
||||
sdog.mins = '-8 -8 -32';//-16 16 -32
|
||||
sdog.maxs = '8 8 30';//16 16 40
|
||||
setsize (sdog, sdog.mins, sdog.maxs);
|
||||
|
||||
if(pointcontents(sdog.origin - '0 0 36') == -2)
|
||||
{
|
||||
while(pointcontents (sdog.origin - '0 0 36') == -2)
|
||||
{
|
||||
sdog.origin = sdog.origin + '0 0 1';
|
||||
setorigin(sdog,sdog.origin );
|
||||
}
|
||||
}
|
||||
|
||||
sdog.classname = "ai_dog";
|
||||
sdog.aistatus = "1";
|
||||
setorigin (sdog.goaldummy, '0 0 0');
|
||||
sdog.origin_z = sdog.origin_z + 1;
|
||||
sdog.takedamage = DAMAGE_YES;
|
||||
setorigin(sdog, sdog.origin);
|
||||
sdog.flags = sdog.flags | FL_PARTIALGROUND | FL_MONSTER;
|
||||
|
||||
sdog.spawnflags = where.spawnflags;
|
||||
sdog.spawnflags = sdog.spawnflags | 1;
|
||||
|
||||
sdog.ideal_yaw = sdog.angles_y;
|
||||
sdog.yaw_speed = 20;
|
||||
sdog.health = z_health;
|
||||
sdog.th_die = Dog_Death;
|
||||
sdog.th_walk = Dog_Walk_Setup;
|
||||
sdog.outside = FALSE;
|
||||
sdog.iszomb = 1;
|
||||
|
||||
sdog.th_melee = dog_meleeanim;
|
||||
sdog.th_idle = dog_idleanim;
|
||||
sdog.th_diewunder = die_dog_wunder1;
|
||||
|
||||
SetZombieWalk(sdog);
|
||||
sdog.walktype = 5;
|
||||
|
||||
sdog.reload_delay = 30 + time;//save floats, equals respawn time.
|
||||
local entity old_self;
|
||||
old_self = self;
|
||||
self = sdog;
|
||||
//droptofloor();
|
||||
self.th_walk();
|
||||
self = old_self;
|
||||
};
|
||||
|
||||
void() dogsprite_think =
|
||||
{
|
||||
self.frame++;
|
||||
|
||||
if (self.frame >= 3)
|
||||
self.frame = 0;
|
||||
|
||||
// suicide timer!
|
||||
if(self.ltime < time) {
|
||||
spawn_a_dogB(self.owner);
|
||||
remove(self);
|
||||
}
|
||||
|
||||
self.nextthink = time + 0.05;
|
||||
}
|
||||
|
||||
void(entity where) spawn_dog_lightning =
|
||||
{
|
||||
local entity tempe;
|
||||
local entity doglight;
|
||||
local entity dogsprite;
|
||||
|
||||
// lightning model
|
||||
doglight = spawn();
|
||||
setmodel(doglight, "models/ai/dog_lightning.mdl");
|
||||
setorigin(doglight, where.origin - '0 0 20');
|
||||
tempe = self;
|
||||
self = doglight;
|
||||
dog_lightninganim();
|
||||
self = tempe;
|
||||
|
||||
// lightning sprite
|
||||
dogsprite = spawn();
|
||||
setmodel(dogsprite, "models/sprites/lightning.spr");
|
||||
setorigin(dogsprite, where.origin);
|
||||
dogsprite.owner = where;
|
||||
dogsprite.think = dogsprite_think;
|
||||
dogsprite.nextthink = time + 0.05;
|
||||
dogsprite.ltime = time + 1.3; // we use ltime here to be out remove timer,
|
||||
// since using frames interrupts think()
|
||||
}
|
||||
|
||||
float() spawn_a_dogA =
|
||||
{
|
||||
local float pcount;
|
||||
local entity thing, szombie;
|
||||
local float FAIL;
|
||||
|
||||
FAIL = false;
|
||||
pcount = 0;
|
||||
szombie = getFreeZombieEnt(self);
|
||||
if(szombie == world || dogCount >= (2 * (player_count + 1)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
lastspawn = find(lastspawn, classname, "spawn_dog");
|
||||
while (random() < 0.4)
|
||||
{
|
||||
lastspawn = find(lastspawn, classname, "spawn_dog");
|
||||
}
|
||||
|
||||
while(lastspawn)
|
||||
{
|
||||
thing = findradius(lastspawn.origin, 60);
|
||||
while (thing)
|
||||
{
|
||||
pcount = 0;
|
||||
if (thing.classname == "ai_dog")
|
||||
{
|
||||
pcount = 1;
|
||||
break;
|
||||
}
|
||||
thing = thing.chain;
|
||||
}
|
||||
if (!pcount && random() < 0.6)
|
||||
{
|
||||
//spawn_a_dogB(lastspawn);
|
||||
spawn_dog_lightning(lastspawn);
|
||||
dogCount++;
|
||||
spawn_delay = time + 2;
|
||||
return true;
|
||||
}
|
||||
lastspawn = find(lastspawn, classname, "spawn_dog");
|
||||
}
|
||||
return 0; //no free locations fround
|
||||
};
|
||||
|
||||
void() spawn_dog =
|
||||
{
|
||||
precache_model("models/ai/dog.mdl");
|
||||
precache_model("models/ai/dog_lightning.mdl");
|
||||
precache_model("models/sprites/lightning.spr");
|
||||
precache_model("models/sprites/explosion.spr");
|
||||
|
||||
precache_sound("sounds/rounds/droundend.wav");
|
||||
precache_sound("sounds/rounds/droundstart.wav");
|
||||
|
||||
setsize(self, '0 0 0', '0 0 0');
|
||||
if (self.spawnflags & INACTIVE)
|
||||
{
|
||||
if (cvar("developer"))
|
||||
setmodel(self, "models/player.mdl");
|
||||
self.classname = "spawn_dog_in";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cvar("developer"))
|
||||
setmodel(self, "models/ai/dog.mdl");
|
||||
self.classname = "spawn_dog";
|
||||
}
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
};
|
828
source/server/ai/fte/waypoints_core.qc
Normal file
828
source/server/ai/fte/waypoints_core.qc
Normal file
|
@ -0,0 +1,828 @@
|
|||
/*
|
||||
server/ai/fte/waypoints_core.qc
|
||||
|
||||
pc waypointing
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() creator_way_touch =
|
||||
{
|
||||
if (cvar("waypoint_mode")) {
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
current_way = self;
|
||||
}
|
||||
}
|
||||
|
||||
void () Create_New_Waypoint =
|
||||
{
|
||||
float way_count;
|
||||
float tempf;
|
||||
entity tempe;
|
||||
entity new_way;
|
||||
|
||||
way_count = -1;
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe) {
|
||||
tempf = stof(tempe.waynum);
|
||||
if (tempf > way_count) {
|
||||
way_count = tempf;
|
||||
}
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, self.origin);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.waynum = ftos(way_count + 1);
|
||||
new_way.targetname = strzone(new_way.targetname);
|
||||
bprint (PRINT_HIGH, "Created waypoint ");
|
||||
bprint (PRINT_HIGH, new_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
|
||||
|
||||
void () Make_Special_Waypoint =
|
||||
{
|
||||
if (self.classname != "player" || !active_way) {
|
||||
return;
|
||||
}
|
||||
if (active_way.targetname != "") {//Toggling it back off
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
active_way.targetname = "";
|
||||
bprint (PRINT_HIGH, "Waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, " is no longer a special waypoint\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_way) {
|
||||
if(self.active_door == world) {
|
||||
bprint (PRINT_HIGH, "Error: no door selected!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(self.active_door.wayTarget == "") {
|
||||
bprint (PRINT_HIGH, "Error: Door has no wayTarget value!\n");
|
||||
return;
|
||||
}
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
active_way.targetname = self.active_door.wayTarget;
|
||||
|
||||
bprint (PRINT_HIGH, "special waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, " named ");
|
||||
bprint (PRINT_HIGH, active_way.targetname);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void () Move_Waypoint =
|
||||
{
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
setorigin (active_way, self.origin);
|
||||
bprint (PRINT_HIGH, "Moved waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
}
|
||||
|
||||
void () Select_Waypoint =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
|
||||
entity tempe;
|
||||
|
||||
if (current_way == active_way)
|
||||
active_way = world;
|
||||
else
|
||||
active_way = current_way;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr");
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
if (active_way)
|
||||
{
|
||||
if (active_way.targetname != "")
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
else
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
|
||||
bprint (PRINT_HIGH, "Selected waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
if(active_way.targetname != "")
|
||||
{
|
||||
bprint (PRINT_HIGH, ", special tag ");
|
||||
bprint (PRINT_HIGH, active_way.targetname);
|
||||
}
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
tempe = find (world, waynum, active_way.targets[i]);
|
||||
if (tempe) {
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
} else {
|
||||
active_way.targets[i] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void() Remove_Waypoint =
|
||||
{
|
||||
entity tempe;
|
||||
float i;
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe) {
|
||||
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (tempe.targets[i] == active_way.waynum) {
|
||||
tempe.targets[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
|
||||
bprint(PRINT_HIGH, "Removed waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
remove (active_way);
|
||||
}
|
||||
|
||||
float Waypoint_Linked_To(entity from, entity to) {
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (from.waynum == to.targets[i]) {
|
||||
bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Link (entity from, entity to) {
|
||||
float i;
|
||||
entity tempe;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
tempe = find (world, waynum, from.targets[i]);
|
||||
|
||||
if (tempe == world || tempe == to) {
|
||||
from.targets[i] = to.waynum;
|
||||
bprint(PRINT_HIGH, "Linked waypoint ");
|
||||
bprint(PRINT_HIGH, to.waynum);
|
||||
bprint(PRINT_HIGH, " to ");
|
||||
bprint(PRINT_HIGH, from.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
|
||||
if (to.targetname != "") {
|
||||
setmodel(to, "models/way/last_way_door.spr");
|
||||
} else {
|
||||
setmodel(to, "models/way/last_way.spr");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void () Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
if (Waypoint_Linked_To(current_way, active_way)) {
|
||||
bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
float i;
|
||||
entity tempe;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
#ifdef PC
|
||||
tempe = findfloat (world, waynum, active_way.targets[i]);
|
||||
#else
|
||||
tempe = find (world, waynum, active_way.targets[i]);
|
||||
#endif
|
||||
|
||||
if (tempe == world) {
|
||||
if (Link(active_way, current_way)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bprint(PRINT_HIGH, "no targets remaining!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void() Dual_Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player" || !current_way || !active_way || current_way == active_way) {
|
||||
return;
|
||||
}
|
||||
|
||||
float result1,result2;
|
||||
result1 = Waypoint_Linked_To(current_way,active_way);
|
||||
result2 = Waypoint_Linked_To(active_way,current_way);
|
||||
|
||||
if(result1 && result2) {
|
||||
bprint(PRINT_HIGH, "Both waypoints already linked!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!result1)
|
||||
{
|
||||
if (Link(current_way,active_way)) {
|
||||
bprint(PRINT_HIGH, strcat("Linked waypoint ", strcat(current_way.waynum, strcat(" to ",strcat(active_way.waynum, "\n")))));
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("ERROR: Could not link waypoint ", strcat(current_way.waynum, strcat(" to ", strcat(active_way.waynum, "\n")))));
|
||||
}
|
||||
}
|
||||
if(!result2)
|
||||
{
|
||||
if (Link(active_way,current_way)) {
|
||||
bprint(PRINT_HIGH, strcat("Linked waypoint ", strcat(active_way.waynum, strcat(" to ", strcat(current_way.waynum, "\n")))));
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("ERROR: Could not link waypoint ", strcat(active_way.waynum, strcat(" to ", strcat(current_way.waynum, "\n")))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//alter auto_link_waypoints to iterate through the closest waypoints from closest to furthest
|
||||
// on the innermost loop, we find the next closest waypoint that is further away from the last closest waypoint, and we use that!
|
||||
|
||||
void() Auto_Link_Waypoints =
|
||||
{
|
||||
entity tempe1, tempe2;
|
||||
|
||||
tempe1 = find(world,classname,"waypoint");
|
||||
while(tempe1 != world)
|
||||
{
|
||||
tempe2 = find(world,classname,"waypoint");
|
||||
while(tempe2 != world)
|
||||
{
|
||||
if(tempe1 == tempe2)
|
||||
{
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(tracemove(tempe1.origin,VEC_HULL_MIN,VEC_HULL_MAX,tempe2.origin,TRUE,self))
|
||||
{
|
||||
Link(tempe1,tempe2);
|
||||
}
|
||||
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
}
|
||||
tempe1 = find(tempe1,classname,"waypoint");
|
||||
}
|
||||
}
|
||||
//alter auto_link_waypoints to iterate through the closest waypoints from closest to furthest
|
||||
// on the innermost loop, we find the next closest waypoint that is further away from the last closest waypoint, and we use that!
|
||||
|
||||
void() Remove_Links =
|
||||
{
|
||||
entity tempe;
|
||||
|
||||
tempe = find(world,classname,"waypoint");
|
||||
while(tempe != world)
|
||||
{
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i = i + 1) {
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr");
|
||||
tempe.targets[i] = "";
|
||||
}
|
||||
tempe = find(tempe,classname,"waypoint");
|
||||
}
|
||||
}
|
||||
|
||||
void() Save_Waypoints
|
||||
{
|
||||
float file;
|
||||
string h;
|
||||
float i;
|
||||
entity tempe;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_WRITE);
|
||||
|
||||
dprint (strcat("Saving waypoints ", strcat(h, "\n")));
|
||||
|
||||
local entity dway;
|
||||
//fputs(file, "begin\n");
|
||||
dway = find(world, classname, "waypoint");
|
||||
while (dway)
|
||||
{
|
||||
fputs(file,"waypoint\n");
|
||||
fputs(file,"{\n");
|
||||
fputs(file, strcat(" id: ", strcat(dway.waynum, "\n")));
|
||||
fputs(file, strcat(" origin: ", strcat(vtos(dway.origin), "\n")));
|
||||
if (dway.targetname != "") {
|
||||
fputs(file, strcat(" door: ", strcat(dway.targetname, "\n")));
|
||||
}
|
||||
|
||||
fputs(file, " targets:\n");
|
||||
fputs(file, " [\n");
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (dway.targets[i] != "") {
|
||||
#ifdef PC
|
||||
tempe = findfloat (world, waynum, dway.targets[i]);
|
||||
#else
|
||||
tempe = find (world, waynum, dway.targets[i]);
|
||||
#endif
|
||||
|
||||
if (tempe != world) {
|
||||
fputs(file, strcat(" ", strcat(dway.targets[i], "\n")));
|
||||
} else {
|
||||
tempe = find (world, waynum, dway.targets[i]);
|
||||
if (tempe != world) {
|
||||
fputs(file, strcat(" ", strcat(dway.targets[i], "\n")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs(file, " ]\n");
|
||||
fputs(file,"}\n");
|
||||
|
||||
|
||||
dway = find(dway, classname, "waypoint");
|
||||
if (dway)
|
||||
fputs(file,"\n");
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void (vector here, float which, string special, string trg, string trg2, string trg3, string trg4, string trg5, string trg6, string trg7, string trg8) Create_Waypoint =
|
||||
{
|
||||
entity new_way;
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, here);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.waynum = ftos(which);
|
||||
dprint ("Created waypoint ");
|
||||
dprint (new_way.waynum);
|
||||
dprint ("\n");
|
||||
|
||||
if (special != "")
|
||||
{
|
||||
if (!cvar("waypoint_mode"))
|
||||
new_way.classname = "waypoint_s";
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way_door.spr");
|
||||
new_way.targetname = special;
|
||||
dprint ("Special waypoint ");
|
||||
dprint (new_way.targetname);
|
||||
dprint ("\n");
|
||||
//current_special++;
|
||||
}
|
||||
|
||||
new_way.targets[0] = trg;
|
||||
new_way.targets[1] = trg2;
|
||||
new_way.targets[2] = trg3;
|
||||
new_way.targets[3] = trg4;
|
||||
new_way.targets[4] = trg5;
|
||||
new_way.targets[5] = trg6;
|
||||
new_way.targets[6] = trg7;
|
||||
new_way.targets[7] = trg8;
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
|
||||
float waypoints_loaded;
|
||||
void() Load_Waypoints
|
||||
{
|
||||
float file, point;
|
||||
string h;
|
||||
float targetcount, loop;
|
||||
|
||||
entity new_way;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
new_way = spawn();
|
||||
targetcount = 0;
|
||||
point = 0;
|
||||
loop = 1;
|
||||
while (loop)
|
||||
{
|
||||
string line;
|
||||
line = fgets(file);
|
||||
if not (line) {
|
||||
bprint(PRINT_HIGH, "End of file\n");
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
h = strtrim(line);
|
||||
|
||||
//bprint(PRINT_HIGH, strcat(h, "\n"));
|
||||
if (h == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (point) {
|
||||
case 0:
|
||||
if (h == "waypoint") {
|
||||
new_way = spawn();
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
new_way.model = "models/way/normal_way.spr";
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
point = 1;
|
||||
targetcount = 0;
|
||||
} else if (h == "Waypoint") {
|
||||
bprint(PRINT_HIGH, "Identified .way as legacy..\n");
|
||||
point = 99;
|
||||
Load_Waypoints_Legacy();
|
||||
loop = 0;
|
||||
break;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown point ", strcat(h, "\n")));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (h == "{") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected {\n")));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
tokenize(h);
|
||||
|
||||
string value, variable;
|
||||
variable = strtrim(argv(0));
|
||||
value = strtrim(argv(2));
|
||||
|
||||
//bprint(PRINT_HIGH, strcat(variable, "\n"));
|
||||
|
||||
switch (variable) {
|
||||
case "origin":
|
||||
|
||||
print(strcat(value, "\n"));
|
||||
new_way.origin = stov(value);
|
||||
setorigin(new_way, new_way.origin);
|
||||
break;
|
||||
case "id":
|
||||
new_way.waynum = value;
|
||||
break;
|
||||
case "door":
|
||||
new_way.targetname = value;
|
||||
|
||||
setmodel(new_way, "models/way/normal_way_door.spr");
|
||||
break;
|
||||
case "targets":
|
||||
point = 3;
|
||||
break;
|
||||
case "}":
|
||||
point = 0;
|
||||
break;
|
||||
default:
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(variable, "\n")));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (h == "[") {
|
||||
point = 4;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (targetcount >= MAX_WAY_TARGETS) {
|
||||
bprint(PRINT_HIGH, "Error: Target count too high for waypoint\n");
|
||||
} else if (h == "]") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat(strcat("WAYPOINT TARGET: ", strcat(strcat(ftos(targetcount), " "), h)), "\n"));
|
||||
new_way.targets[targetcount] = h;
|
||||
targetcount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
waypoints_loaded = 1;
|
||||
}
|
||||
|
||||
void() Load_Waypoints_Legacy
|
||||
{
|
||||
float file, which;
|
||||
string h, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8;
|
||||
local vector where;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
dprint("Loading waypoint\n");
|
||||
// the first line is just a comment, ignore it
|
||||
h = fgets(file);
|
||||
if (h != "Waypoint")
|
||||
{
|
||||
bprint(PRINT_HIGH, "Last waypoint\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
h = fgets(file);
|
||||
h = fgets(file);
|
||||
h = substring(h, 9, 20);
|
||||
where = stov(h);
|
||||
|
||||
h = (fgets(file));
|
||||
h = substring(h, 5, 20);
|
||||
which = stof(h);
|
||||
|
||||
h = (fgets(file));
|
||||
special = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg = substring(h, 9, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg2 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg3 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg4 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg5 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg6 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg7 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg8 = substring(h, 10, 20);
|
||||
|
||||
#ifndef PC
|
||||
Create_Waypoint(where, which, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8);
|
||||
#else
|
||||
waypoint_ai waypoint;
|
||||
waypoint = waypoints[which];
|
||||
|
||||
waypoints[which].id = which;
|
||||
waypoints[which].org = where;
|
||||
waypoints[which].targetdoor = special;
|
||||
|
||||
waypoints[which].target_id[0] = stof(trg);
|
||||
waypoints[which].target_id[1] = stof(trg2);
|
||||
waypoints[which].target_id[2] = stof(trg3);
|
||||
waypoints[which].target_id[3] = stof(trg4);
|
||||
waypoints[which].target_id[4] = stof(trg5);
|
||||
waypoints[which].target_id[5] = stof(trg6);
|
||||
waypoints[which].target_id[6] = stof(trg7);
|
||||
waypoints[which].target_id[7] = stof(trg8);
|
||||
#endif
|
||||
|
||||
h = (fgets(file));
|
||||
h = (fgets(file));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VisualizePathfind() {
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
Pathfind(self, stof(active_way.waynum), stof(current_way.waynum));
|
||||
}
|
||||
|
||||
.float waypoint_delay;
|
||||
|
||||
//Waypoint logic functions
|
||||
void () Waypoint_Functions =
|
||||
{
|
||||
// naievil -- archaic
|
||||
/*
|
||||
switch (self.impulse) {
|
||||
case 100:
|
||||
Create_New_Waypoint();
|
||||
break;
|
||||
case 101:
|
||||
Make_Special_Waypoint();
|
||||
break;
|
||||
case 102:
|
||||
Select_Waypoint();
|
||||
break;
|
||||
case 103:
|
||||
Move_Waypoint();
|
||||
break;
|
||||
case 104:
|
||||
Link_Waypoints ();
|
||||
break;
|
||||
case 105:
|
||||
Dual_Link_Waypoints();
|
||||
break;
|
||||
case 106:
|
||||
Save_Waypoints();
|
||||
break;
|
||||
case 107:
|
||||
Load_Waypoints();
|
||||
break;
|
||||
case 108:
|
||||
Load_Waypoints_Legacy();
|
||||
break;
|
||||
case 109:
|
||||
Remove_Waypoint();
|
||||
//VisualizePathfind();
|
||||
break;
|
||||
case 110:
|
||||
Auto_Link_Waypoints();
|
||||
break;
|
||||
case 111:
|
||||
Remove_Links();
|
||||
break;
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
*/
|
||||
|
||||
switch (self.impulse) {
|
||||
case 23:
|
||||
Save_Waypoints();
|
||||
break;
|
||||
case 22:
|
||||
if (!waypoints_loaded)
|
||||
Load_Waypoints();
|
||||
break;
|
||||
case 110:
|
||||
Move_Waypoint();
|
||||
break;
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
|
||||
// Match what we display on the screen
|
||||
if (self.button0 && self.waypoint_delay < time) {
|
||||
Create_New_Waypoint();
|
||||
self.waypoint_delay = time + 1;
|
||||
}
|
||||
|
||||
if (self.button7 && self.waypoint_delay < time) {
|
||||
Select_Waypoint();
|
||||
self.waypoint_delay = time + 0.25;
|
||||
}
|
||||
|
||||
if (self.button8 && self.waypoint_delay < time) {
|
||||
Link_Waypoints ();
|
||||
self.waypoint_delay = time + 0.5;
|
||||
}
|
||||
|
||||
if (self.button6 && self.waypoint_delay < time) {
|
||||
Remove_Waypoint();
|
||||
self.waypoint_delay = time + 0.5;
|
||||
}
|
||||
|
||||
if (self.button5 && self.waypoint_delay < time) {
|
||||
Make_Special_Waypoint();
|
||||
self.waypoint_delay = time + 1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void () Waypoint_Logic =
|
||||
{
|
||||
if (!waypoint_mode) {
|
||||
waypoint_mode = 1;
|
||||
entity zent;
|
||||
|
||||
zent = find (world, classname, "ai_zombie");
|
||||
while (zent)
|
||||
{
|
||||
remove (zent);
|
||||
zent = find (zent, classname, "ai_zombie");
|
||||
}
|
||||
|
||||
zent = find (world, classname, "door_nzp_cost");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "door_nzp_cost");
|
||||
}
|
||||
zent = find (world, classname, "door_nzp");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent.solid = SOLID_NOT;
|
||||
zent = find (zent, classname, "door_nzp");
|
||||
}
|
||||
zent = find (world, classname, "window");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "window");
|
||||
}
|
||||
|
||||
}
|
||||
Waypoint_Functions();
|
||||
};
|
469
source/server/ai/pathfind_code.qc
Normal file
469
source/server/ai/pathfind_code.qc
Normal file
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
server/ai/pathfind_core.qc
|
||||
|
||||
generic waypoint pathfinding
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() Load_Waypoints_Legacy;
|
||||
|
||||
float Distance (vector from, vector to) {
|
||||
return vlen(from - to);
|
||||
}
|
||||
|
||||
float HeuristicCostEstimate (float start_way, float end_way)
|
||||
{
|
||||
//for now we will just look the distance between.
|
||||
return Distance(waypoints[start_way].org, waypoints[end_way].org);
|
||||
}
|
||||
|
||||
void ReconstructPath(entity z, float start_way, float end_way) {
|
||||
|
||||
}
|
||||
|
||||
float open_first;
|
||||
float open;
|
||||
float closed_init;
|
||||
float closed;
|
||||
float closed_first;
|
||||
void SV_WP_ClearSet()
|
||||
{
|
||||
float i;
|
||||
|
||||
for (i = 0; i < MAX_WAYPOINTS; i = i + 1)
|
||||
{
|
||||
waypoints[i].set = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float IsActive(float way) {
|
||||
if (waypoints[way].targetdoor != "") {
|
||||
entity door;
|
||||
|
||||
door = find(world, wayTarget, waypoints[way].targetdoor);
|
||||
|
||||
if (door != world) {
|
||||
if (door.state == STATE_BOTTOM) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SV_WP_SetAdd(float wp, float isopen)
|
||||
{
|
||||
if (isopen)
|
||||
{
|
||||
// we only get added here from none, so no cleanup required
|
||||
// gotta check if last entry was removed before this call
|
||||
if (waypoints[open_first].set == SET_CLOSED)
|
||||
{
|
||||
//Con_Printf("Empty set: %i is new first\n", wp);
|
||||
open_first = wp;
|
||||
waypoints[wp].prev = wp;
|
||||
}
|
||||
else
|
||||
{
|
||||
waypoints[wp].prev = open;
|
||||
waypoints[open].next = wp;
|
||||
}
|
||||
waypoints[wp].next = wp;
|
||||
waypoints[wp].set = SET_OPEN;
|
||||
open = wp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// even if wp is the only one in the set, it doesn't really matter
|
||||
if (wp == open_first)
|
||||
open_first = waypoints[wp].next;
|
||||
if (wp == open)
|
||||
open = waypoints[wp].prev;
|
||||
|
||||
// update links so open set doesn't get fucked
|
||||
waypoints[waypoints[wp].prev].next = waypoints[wp].next;
|
||||
waypoints[waypoints[wp].next].prev = waypoints[wp].prev;
|
||||
|
||||
if (!closed_init)
|
||||
{
|
||||
closed_first = wp;
|
||||
waypoints[wp].prev = wp;
|
||||
closed_init = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
waypoints[closed].next = wp;
|
||||
waypoints[wp].prev = closed;
|
||||
}
|
||||
waypoints[wp].next = wp;
|
||||
waypoints[wp].set = SET_CLOSED;
|
||||
closed = wp;
|
||||
}
|
||||
}
|
||||
|
||||
float Pathfind (entity z, float s_wp, float e_wp) {
|
||||
float current;
|
||||
float i, j;
|
||||
float bestf;
|
||||
|
||||
|
||||
if (s_wp == e_wp) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
SV_WP_ClearSet();
|
||||
|
||||
open_first = s_wp;
|
||||
open = s_wp;
|
||||
waypoints[s_wp].next = s_wp;
|
||||
waypoints[s_wp].prev = s_wp;
|
||||
waypoints[s_wp].set = SET_OPEN;
|
||||
waypoints[s_wp].g = 0;
|
||||
waypoints[s_wp].f = HeuristicCostEstimate(s_wp, e_wp);
|
||||
waypoints[s_wp].step = s_wp;
|
||||
current = s_wp;
|
||||
|
||||
closed_init = false;
|
||||
|
||||
// while openset is not empty
|
||||
while (waypoints[open_first].set == SET_OPEN) {
|
||||
i = open_first;
|
||||
|
||||
bestf = 320000;
|
||||
//print("Current ", ftos(current), "\n");
|
||||
|
||||
// go from first open to last, pick the one with lowest f
|
||||
do {
|
||||
if (waypoints[i].f < bestf) {
|
||||
current = i;
|
||||
bestf = waypoints[i].f;
|
||||
}
|
||||
i = waypoints[i].next;
|
||||
} while (i != open);
|
||||
|
||||
// mark node as visited
|
||||
//print("Removing ", ftos(current), " from open\n");
|
||||
SV_WP_SetAdd(current, false);
|
||||
|
||||
// we found a result, loop back with pathlength
|
||||
if (current == e_wp) {
|
||||
j = i = current;
|
||||
// walk constructed path backwards
|
||||
// keep 2 next steps with us
|
||||
//print("Result\n");
|
||||
//print(ftos(current), "\n");
|
||||
while (waypoints[current].step != current)
|
||||
{
|
||||
j = i;
|
||||
i = current;
|
||||
current = waypoints[current].step;
|
||||
}
|
||||
|
||||
// go to the furthest one on the path that we can actually see
|
||||
|
||||
if (tracemove(waypoints[s_wp].org,VEC_HULL_MIN,VEC_HULL_MAX,waypoints[i].org,TRUE,z))
|
||||
{
|
||||
//VectorCopy(waypoints[i].origin, res);
|
||||
//print("Giving third wp ", ftos(i), "\n");
|
||||
return i;
|
||||
}
|
||||
else if (tracemove(waypoints[s_wp].org,VEC_HULL_MIN,VEC_HULL_MAX,waypoints[j].org,TRUE,z))
|
||||
{
|
||||
//VectorCopy(waypoints[j].origin, res);
|
||||
//print("Giving second wp ", ftos(j), "\n");
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
//VectorCopy(waypoints[current].origin, res);
|
||||
//print("Giving first wp ", ftos(current), "\n");
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check neighbours to add to openset
|
||||
for (j = 0; j < MAX_WAY_TARGETS; j++)
|
||||
{
|
||||
i = waypoints[current].target_id[j];
|
||||
if (waypoints[i].set != SET_CLOSED && i != current && IsActive(i))
|
||||
{
|
||||
bestf = waypoints[current].g + HeuristicCostEstimate(i, current);
|
||||
if (waypoints[i].set == SET_NONE || bestf < waypoints[i].g)
|
||||
{
|
||||
waypoints[i].step = current;
|
||||
waypoints[i].g = bestf;
|
||||
waypoints[i].f = bestf + HeuristicCostEstimate(i, e_wp);
|
||||
|
||||
if (waypoints[i].set == SET_NONE)
|
||||
{
|
||||
//print("Adding ", ftos(i), " into open\n");
|
||||
SV_WP_SetAdd(i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print("Waypointing failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
float Do_Pathfind(entity from, entity to) {
|
||||
|
||||
float i;
|
||||
float TraceResult;
|
||||
|
||||
float dist, best_dist, best, best_target;
|
||||
|
||||
best = 0;
|
||||
best_target = 0;
|
||||
dist = 0;
|
||||
best_dist = 100000000;
|
||||
|
||||
#ifndef PSP
|
||||
for (i = 0; i < MAX_WAYPOINTS; i = i + 1) {
|
||||
if (IsActive(i)) {
|
||||
TraceResult = tracemove (from.origin, VEC_HULL_MIN, VEC_HULL_MAX, waypoints[i].org, TRUE ,from);
|
||||
if (TraceResult) {
|
||||
dist = Distance(waypoints[i].org, from.origin);
|
||||
|
||||
if(dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dist = 0;
|
||||
best_dist = 100000000;
|
||||
|
||||
for (i = 0; i < MAX_WAYPOINTS; i = i + 1) {
|
||||
if (IsActive(i)) {
|
||||
TraceResult = tracemove (to.origin, VEC_HULL_MIN, VEC_HULL_MAX, waypoints[i].org, TRUE ,to);
|
||||
if (TraceResult) {
|
||||
dist = Distance(waypoints[i].org, to.origin);
|
||||
|
||||
if(dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_target = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//print("Starting waypoint: ", ftos(best)," Ending waypoint: ", ftos(best_target), "\n");
|
||||
|
||||
|
||||
|
||||
|
||||
return Pathfind(from, best, best_target);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CalcDistances() {
|
||||
float i, s;
|
||||
|
||||
for (i = 1; i < MAX_WAYPOINTS; i++) {
|
||||
waypoint_ai way;
|
||||
way = waypoints[i];
|
||||
if (way.id > 0) {
|
||||
for (s = 0; s < MAX_WAY_TARGETS; s++) {
|
||||
float targ;
|
||||
targ = way.target_id[s];
|
||||
if (targ > 0) {
|
||||
way.dist[s] = Distance(way.org, waypoints[targ].org);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void creator_way_touch();
|
||||
void LoadWaypointData() {
|
||||
float file, point;
|
||||
string h;
|
||||
float targetcount, loop, waycount;
|
||||
entity new_way;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
float i, s;
|
||||
|
||||
|
||||
#ifndef PSP
|
||||
for (i = 0; i < MAX_WAYPOINTS; i = i + 1) {
|
||||
waypoint_ai way;
|
||||
|
||||
way = waypoints[i];
|
||||
way.org = '0 0 0';
|
||||
way.id = 0;
|
||||
way.g = 0;
|
||||
way.f = 0;
|
||||
way.set = 0;
|
||||
way.targetdoor = "";
|
||||
|
||||
for (s = 0; s < MAX_WAY_TARGETS; s = s + 1) {
|
||||
way.target_id[s] = 0;
|
||||
way.dist[s] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
new_way = spawn();
|
||||
point = 0;
|
||||
waycount = 0;
|
||||
targetcount = 0;
|
||||
loop = 1;
|
||||
while (loop)
|
||||
{
|
||||
string line;
|
||||
line = fgets(file);
|
||||
if not (line) {
|
||||
//bprint(PRINT_HIGH, "End of file\n");
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
h = strtrim(line);
|
||||
|
||||
//print(h, "\n");
|
||||
if (h == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (point) {
|
||||
case 0:
|
||||
if (h == "waypoint") {
|
||||
new_way = spawn();
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
point = 1;
|
||||
targetcount = 0;
|
||||
} else if (h == "Waypoint") {
|
||||
bprint(PRINT_HIGH, "Identified .way as legacy..\n");
|
||||
point = 99;
|
||||
Load_Waypoints_Legacy();
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown point ", strcat(h, "\n")));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (h == "{") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected {\n")));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
tokenize(h);
|
||||
|
||||
string value, variable;
|
||||
variable = strtrim(argv(0));
|
||||
value = strtrim(argv(2));
|
||||
|
||||
switch (variable) {
|
||||
case "origin":
|
||||
setorigin(new_way, stov(value));
|
||||
break;
|
||||
case "id":
|
||||
new_way.waynum = value;
|
||||
break;
|
||||
case "door":
|
||||
new_way.targetname = value;
|
||||
break;
|
||||
case "targets":
|
||||
point = 3;
|
||||
break;
|
||||
case "}":
|
||||
float id = stof(new_way.waynum);
|
||||
waypoint_ai waypoint;
|
||||
waypoint = waypoints[id];
|
||||
|
||||
waypoints[id].id = id;
|
||||
waypoints[id].org = new_way.origin;
|
||||
waypoints[id].targetdoor = new_way.targetname;
|
||||
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
waypoints[id].target_id[i] = stof(new_way.targets[i]);
|
||||
}
|
||||
|
||||
if (!cvar("waypoint_mode")) {
|
||||
remove(new_way);
|
||||
}
|
||||
|
||||
|
||||
point = 0;
|
||||
break;
|
||||
default:
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(variable, "\n")));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (h == "[") {
|
||||
point = 4;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (targetcount >= MAX_WAY_TARGETS) {
|
||||
bprint(PRINT_HIGH, "Error: Target count too high for waypoint\n");
|
||||
} else if (h == "]") {
|
||||
point = 2;
|
||||
} else {
|
||||
new_way.targets[targetcount] = h;
|
||||
targetcount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_way) {
|
||||
if (!cvar("waypoint_mode")) {
|
||||
remove(new_way);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
#ifndef PSP
|
||||
CalcDistances();
|
||||
#endif
|
||||
}
|
117
source/server/ai/standard/waypoints_core.qc
Normal file
117
source/server/ai/standard/waypoints_core.qc
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
server/ai/standard/waypoints_core.qc
|
||||
|
||||
non-pc waypoint impulsing
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
float waypoint_action;
|
||||
|
||||
void () Waypoint_Functions =
|
||||
{
|
||||
switch (self.impulse)
|
||||
{
|
||||
case 15:
|
||||
Make_Special_Waypoint();
|
||||
break;
|
||||
case 10:
|
||||
Move_Waypoint();
|
||||
break;
|
||||
case 18:
|
||||
Remove_Waypoint ();
|
||||
break;
|
||||
case 21:
|
||||
Link_Waypoints ();
|
||||
break;
|
||||
case 20:
|
||||
Dual_Link_Waypoints();
|
||||
break;
|
||||
case 22:
|
||||
Auto_Link_Waypoints();
|
||||
break;
|
||||
case 101:
|
||||
Save_Waypoints();
|
||||
break;
|
||||
case 102:
|
||||
Load_Waypoints();
|
||||
break;
|
||||
}
|
||||
|
||||
if(self.button8 && !self.semi)
|
||||
{
|
||||
self.semi = true;
|
||||
Dual_Link_Waypoints();
|
||||
waypoint_action = waypoint_action + 1;
|
||||
}
|
||||
if (self.button0 && !self.semi)
|
||||
{
|
||||
Create_New_Waypoint();
|
||||
waypoint_action = waypoint_action + 1;
|
||||
self.semi = true;
|
||||
}
|
||||
|
||||
if (self.button7 && !self.semiuse)
|
||||
{
|
||||
Select_Waypoint();
|
||||
waypoint_action = waypoint_action + 1;
|
||||
self.semiuse = true;
|
||||
}
|
||||
|
||||
if(self.button4 && !self.semiuse)
|
||||
{
|
||||
self.semiuse = true;
|
||||
waypoint_action = waypoint_action + 1;
|
||||
Move_Waypoint();
|
||||
}
|
||||
if(self.button6 && !self.semiuse)
|
||||
{
|
||||
Remove_Waypoint ();
|
||||
waypoint_action = waypoint_action + 1;
|
||||
self.semiuse = true;
|
||||
}
|
||||
if(self.button5 && !self.semiuse)
|
||||
{
|
||||
Make_Special_Waypoint();
|
||||
waypoint_action = waypoint_action + 1;
|
||||
self.semiuse = true;
|
||||
}
|
||||
|
||||
if(!self.button0 && !self.button7 && !self.button4 && !self.button5 && !self.button6 && !self.button8)
|
||||
{
|
||||
self.semiuse = false;
|
||||
self.semi = false;
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
};
|
||||
|
||||
void () Waypoint_Logic =
|
||||
{
|
||||
if (waypoint_action > 20) {
|
||||
if (cvar("autosave_waypoint"))
|
||||
Save_Waypoints();
|
||||
waypoint_action = 0;
|
||||
}
|
||||
|
||||
Waypoint_Functions();
|
||||
};
|
907
source/server/ai/standard/waypoints_func.qc
Normal file
907
source/server/ai/standard/waypoints_func.qc
Normal file
|
@ -0,0 +1,907 @@
|
|||
/*
|
||||
server/ai/standard/waypoints_func.qc
|
||||
|
||||
non-pc waypointing
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
//float current_special;
|
||||
entity active_way, current_way;
|
||||
|
||||
|
||||
float (entity way1, entity way2) progs_Link_Waypoints =
|
||||
{
|
||||
|
||||
if (way1 == world)
|
||||
return 0;
|
||||
if (way2 == world)
|
||||
return 0;
|
||||
if (way2 == way1)
|
||||
return 0;
|
||||
|
||||
if(
|
||||
way1.target == way2.waynum ||
|
||||
way1.target2 == way2.waynum ||
|
||||
way1.target3 == way2.waynum ||
|
||||
way1.target4 == way2.waynum ||
|
||||
way1.target5 == way2.waynum ||
|
||||
way1.target6 == way2.waynum ||
|
||||
way1.target7 == way2.waynum ||
|
||||
way1.target8 == way2.waynum
|
||||
)
|
||||
{
|
||||
//bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return 2;//already linked
|
||||
}
|
||||
|
||||
if (way1.target == "")
|
||||
{
|
||||
way1.target = way2.waynum;
|
||||
way1.target = strzone(way1.target);
|
||||
}
|
||||
else if (way1.target2 == "")
|
||||
{
|
||||
way1.target2 = way2.waynum;
|
||||
way1.target2 = strzone(way1.target2);
|
||||
}
|
||||
else if (way1.target3 == "")
|
||||
{
|
||||
way1.target3 = way2.waynum;
|
||||
way1.target3 = strzone(way1.target3);
|
||||
}
|
||||
else if (way1.target4 == "")
|
||||
{
|
||||
way1.target4 = way2.waynum;
|
||||
way1.target4 = strzone(way1.target4);
|
||||
}
|
||||
else if (way1.target5 == "")
|
||||
{
|
||||
way1.target5 = way2.waynum;
|
||||
way1.target5 = strzone(way1.target5);
|
||||
}
|
||||
else if (way1.target6 == "")
|
||||
{
|
||||
way1.target6 = way2.waynum;
|
||||
way1.target6 = strzone(way1.target6);
|
||||
}
|
||||
else if (way1.target7 == "")
|
||||
{
|
||||
way1.target7 = way2.waynum;
|
||||
way1.target7 = strzone(way1.target7);
|
||||
}
|
||||
else if (way1.target8 == "")
|
||||
{
|
||||
way1.target8 = way2.waynum;
|
||||
way1.target8 = strzone(way1.target8);
|
||||
}
|
||||
else
|
||||
{
|
||||
//bprint(PRINT_HIGH, "no targets remaining!\n");
|
||||
return -1;//no targets
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//alter auto_link_waypoints to iterate through the closest waypoints from closest to furthest
|
||||
// on the innermost loop, we find the next closest waypoint that is further away from the last closest waypoint, and we use that!
|
||||
|
||||
void() Auto_Link_Waypoints =
|
||||
{
|
||||
entity tempe1, tempe2;
|
||||
|
||||
tempe1 = find(world,classname,"waypoint");
|
||||
while(tempe1 != world)
|
||||
{
|
||||
tempe2 = find(world,classname,"waypoint");
|
||||
while(tempe2 != world)
|
||||
{
|
||||
if(tempe1 == tempe2)
|
||||
{
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(tracemove(tempe1.origin,VEC_HULL_MIN,VEC_HULL_MAX,tempe2.origin,TRUE,self))
|
||||
{
|
||||
progs_Link_Waypoints(tempe1,tempe2);
|
||||
}
|
||||
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
}
|
||||
tempe1 = find(tempe1,classname,"waypoint");
|
||||
}
|
||||
}
|
||||
|
||||
void() Remove_Waypoint =
|
||||
{
|
||||
entity tempe;
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr"); //restore the original one, shall we
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
|
||||
tempe = find (world, target, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target = "";
|
||||
tempe = find (world, target2, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target2 = "";
|
||||
tempe = find (world, target3, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target3 = "";
|
||||
tempe = find (world, target4, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target4 = "";
|
||||
tempe = find (world, target5, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target5 = "";
|
||||
tempe = find (world, target6, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target6 = "";
|
||||
tempe = find (world, target7, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target7 = "";
|
||||
tempe = find (world, target8, active_way.waynum);
|
||||
if (tempe)
|
||||
tempe.target8 = "";
|
||||
|
||||
|
||||
//if (active_way.targetname != "")
|
||||
// current_special--;
|
||||
|
||||
bprint (PRINT_HIGH, "Removed waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
strunzone (active_way.classname);
|
||||
strunzone (active_way.targetname);
|
||||
strunzone (active_way.waynum);
|
||||
strunzone (active_way.target);
|
||||
strunzone (active_way.target2);
|
||||
strunzone (active_way.target3);
|
||||
strunzone (active_way.target4);
|
||||
strunzone (active_way.target5);
|
||||
strunzone (active_way.target6);
|
||||
strunzone (active_way.target7);
|
||||
strunzone (active_way.target8);
|
||||
remove (active_way);
|
||||
}
|
||||
|
||||
void() creator_way_touch =
|
||||
{
|
||||
if (cvar("waypoint_mode"))
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
|
||||
current_way = self;
|
||||
}
|
||||
}
|
||||
|
||||
void () Create_New_Waypoint =
|
||||
{
|
||||
float way_count;
|
||||
float tempf;
|
||||
entity tempe;
|
||||
entity new_way;
|
||||
string temps;
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, self.origin);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe)
|
||||
{
|
||||
tempf = stof (tempe.waynum);
|
||||
if (tempf > way_count)
|
||||
way_count = tempf;
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
|
||||
temps = ftos(way_count + 1);
|
||||
new_way.waynum = temps;
|
||||
new_way.waynum = strzone(new_way.waynum);
|
||||
new_way.targetname = strzone(new_way.targetname);
|
||||
bprint (PRINT_HIGH, "Created waypoint ");
|
||||
bprint (PRINT_HIGH, new_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
void () Move_Waypoint =
|
||||
{
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
setorigin (active_way, self.origin);
|
||||
bprint(PRINT_HIGH, "Moved waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
|
||||
}
|
||||
|
||||
void() Dual_Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
local float result1,result2;
|
||||
result1 = progs_Link_Waypoints(current_way,active_way);
|
||||
result2 = progs_Link_Waypoints(active_way,current_way);
|
||||
|
||||
if(result1 == 2 && result2 == 2)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Both waypoints already linked!\n");
|
||||
}
|
||||
|
||||
if(result1 == 1)
|
||||
{
|
||||
bprint(PRINT_HIGH, " Linked waypoint ");
|
||||
bprint(PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, " to ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
if(result2 == 1)
|
||||
{
|
||||
bprint(PRINT_HIGH, " Linked waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, " to ");
|
||||
bprint(PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
|
||||
if(result1 == 2 && result2 != 2)//if both are already linked, we only want the simple message above, not detailed one
|
||||
{
|
||||
bprint(PRINT_HIGH, " Waypoint ");
|
||||
bprint(PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, " already linked to ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
if(result2 == 2 && result1 != 2)//if both are already linked, we only want the simple message above, not detailed one
|
||||
{
|
||||
bprint(PRINT_HIGH, " Waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, " already linked to ");
|
||||
bprint(PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
if(result1 == -1)
|
||||
{
|
||||
bprint(PRINT_HIGH, " Waypoint ");
|
||||
bprint(PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, " has no open targets remaining\n");
|
||||
}
|
||||
if(result2 == -1)
|
||||
{
|
||||
bprint(PRINT_HIGH, " Waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, " has no open targets remaining!\n");
|
||||
}
|
||||
if(result1 == 1 && result2 == 1)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Both waypoints linked succesfully!\n");
|
||||
}
|
||||
|
||||
if (current_way.targetname != "")
|
||||
setmodel(current_way, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(current_way, "models/way/last_way.spr");
|
||||
|
||||
if (active_way.targetname != "")
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
else
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
}
|
||||
|
||||
void () Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
if(
|
||||
active_way.target == current_way.waynum ||
|
||||
active_way.target2 == current_way.waynum ||
|
||||
active_way.target3 == current_way.waynum ||
|
||||
active_way.target4 == current_way.waynum ||
|
||||
active_way.target5 == current_way.waynum ||
|
||||
active_way.target6 == current_way.waynum ||
|
||||
active_way.target7 == current_way.waynum ||
|
||||
active_way.target8 == current_way.waynum
|
||||
)
|
||||
{
|
||||
bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_way.target == "")
|
||||
{
|
||||
active_way.target = current_way.waynum;
|
||||
active_way.target = strzone(active_way.target);
|
||||
}
|
||||
else if (active_way.target2 == "")
|
||||
{
|
||||
active_way.target2 = current_way.waynum;
|
||||
active_way.target2 = strzone(active_way.target2);
|
||||
}
|
||||
else if (active_way.target3 == "")
|
||||
{
|
||||
active_way.target3 = current_way.waynum;
|
||||
active_way.target3 = strzone(active_way.target3);
|
||||
}
|
||||
else if (active_way.target4 == "")
|
||||
{
|
||||
active_way.target4 = current_way.waynum;
|
||||
active_way.target4 = strzone(active_way.target4);
|
||||
}
|
||||
else if (active_way.target5 == "")
|
||||
{
|
||||
active_way.target5 = current_way.waynum;
|
||||
active_way.target5 = strzone(active_way.target5);
|
||||
}
|
||||
else if (active_way.target6 == "")
|
||||
{
|
||||
active_way.target6 = current_way.waynum;
|
||||
active_way.target6 = strzone(active_way.target6);
|
||||
}
|
||||
else if (active_way.target7 == "")
|
||||
{
|
||||
active_way.target7 = current_way.waynum;
|
||||
active_way.target7 = strzone(active_way.target7);
|
||||
}
|
||||
else if (active_way.target8)
|
||||
{
|
||||
active_way.target8 = current_way.waynum;
|
||||
active_way.target8 = strzone(active_way.target8);
|
||||
}
|
||||
else
|
||||
{
|
||||
bprint(PRINT_HIGH, "no targets remaining!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bprint(PRINT_HIGH, "Linked waypoint ");
|
||||
bprint (PRINT_HIGH, current_way.waynum);
|
||||
bprint(PRINT_HIGH, " to ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
if (current_way.targetname != "")
|
||||
setmodel(current_way, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(current_way, "models/way/last_way.spr");
|
||||
}
|
||||
void () Select_Waypoint =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
|
||||
entity tempe;
|
||||
|
||||
if (current_way == active_way)
|
||||
active_way = world;
|
||||
else
|
||||
active_way = current_way;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr");
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
if (active_way)
|
||||
{
|
||||
if (active_way.targetname != "")
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
else
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
|
||||
bprint(PRINT_HIGH, "Selected waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
if(active_way.targetname != "")
|
||||
{
|
||||
bprint(PRINT_HIGH, ", special tag ");
|
||||
bprint(PRINT_HIGH, active_way.targetname);
|
||||
}
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
|
||||
if(active_way.target != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target2 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target2);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target2);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target2 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target3 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target3);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, tempe.target3);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target3 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target4 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target4);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target4);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target4 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target5 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target5);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target5);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target5 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target6 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target6);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target6 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target7 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target7);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target7);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target7 = "";
|
||||
}
|
||||
}
|
||||
if(active_way.target8 != "")
|
||||
{
|
||||
tempe = find (world, waynum, active_way.target8);
|
||||
if (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
bprint(PRINT_HIGH, active_way.target8);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
active_way.target8 = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
entity() closestDoor =
|
||||
{
|
||||
local float bestdist,dist;
|
||||
bestdist = 10000;
|
||||
dist = 0;
|
||||
local entity d,best;
|
||||
d = find(world,classname,"door_nzp");
|
||||
while(d)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Door! ");
|
||||
dist = vlen(self.origin - d.pos1);//door origin is world, so use pos1 for start pos
|
||||
bprint(PRINT_HIGH, ftos(bestdist));
|
||||
bprint(PRINT_HIGH, ", ");
|
||||
bprint(PRINT_HIGH, ftos(dist));
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
if(dist < bestdist)
|
||||
{
|
||||
bestdist = dist;
|
||||
best = d;
|
||||
}
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
d = find(d,classname,"door_nzp");
|
||||
}
|
||||
return best;
|
||||
}
|
||||
void () Make_Special_Waypoint =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (active_way.targetname != "")//Toggling it back off
|
||||
{
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
active_way.targetname = "";
|
||||
bprint(PRINT_HIGH, "Waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, " is no longer a special waypoint\n");
|
||||
return;
|
||||
}
|
||||
if (active_way)
|
||||
{
|
||||
strunzone(active_way.targetname);
|
||||
//local entity nearDoor;
|
||||
//nearDoor = closestDoor();
|
||||
if(self.active_door == world)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Error: no door selected!\n");
|
||||
return;
|
||||
}
|
||||
if(self.active_door.wayTarget == "")
|
||||
{
|
||||
bprint(PRINT_HIGH, "Error: Door has no wayTarget value!\n");
|
||||
return;
|
||||
}
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
active_way.targetname = self.active_door.wayTarget;
|
||||
//active_way.targetname = ftos(current_special);
|
||||
//active_way.targetname = strzone(active_way.targetname);
|
||||
//active_way.targetname = strcat("d", active_way.targetname);
|
||||
//active_way.targetname = strzone(active_way.targetname);
|
||||
bprint(PRINT_HIGH, "special waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, " named ");
|
||||
bprint (PRINT_HIGH, active_way.targetname);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
//current_special++;
|
||||
}
|
||||
}
|
||||
|
||||
void (vector here, float which, string special, string trg, string trg2, string trg3, string trg4, string trg5, string trg6, string trg7, string trg8) Create_Waypoint =
|
||||
{
|
||||
entity new_way;
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, here);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
new_way.classname = strzone(new_way.classname);
|
||||
|
||||
new_way.waynum = ftos(which);
|
||||
new_way.waynum = strzone(new_way.waynum);
|
||||
dprint ("Created waypoint ");
|
||||
dprint (new_way.waynum);
|
||||
dprint ("\n");
|
||||
|
||||
if (special != "")
|
||||
{
|
||||
if (!cvar("waypoint_mode"))
|
||||
new_way.classname = "waypoint_s";
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way_door.spr");
|
||||
new_way.targetname = special;
|
||||
new_way.targetname = strzone(new_way.targetname);
|
||||
dprint ("Special waypoint ");
|
||||
dprint (new_way.targetname);
|
||||
dprint ("\n");
|
||||
//current_special++;
|
||||
}
|
||||
if (trg)
|
||||
{
|
||||
new_way.target = trg;
|
||||
new_way.target = strzone(new_way.target);
|
||||
dprint ("Waypoint target ");
|
||||
dprint (new_way.target);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg2)
|
||||
{
|
||||
new_way.target2 = trg2;
|
||||
new_way.target2 = strzone(new_way.target2);
|
||||
dprint ("Waypoint target2 ");
|
||||
dprint (new_way.target2);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg3)
|
||||
{
|
||||
new_way.target3 = trg3;
|
||||
new_way.target3 = strzone(new_way.target3);
|
||||
dprint ("Waypoint target3 ");
|
||||
dprint (new_way.target3);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg4)
|
||||
{
|
||||
new_way.target4 = trg4;
|
||||
new_way.target4 = strzone(new_way.target4);
|
||||
dprint ("Waypoint target4 ");
|
||||
dprint (new_way.target4);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg5)
|
||||
{
|
||||
new_way.target5 = trg5;
|
||||
new_way.target5 = strzone(new_way.target5);
|
||||
dprint ("Waypoint target5 ");
|
||||
dprint (new_way.target5);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg6)
|
||||
{
|
||||
new_way.target6 = trg6;
|
||||
new_way.target6 = strzone(new_way.target6);
|
||||
dprint ("Waypoint target6 ");
|
||||
dprint (new_way.target6);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg7)
|
||||
{
|
||||
new_way.target7 = trg7;
|
||||
new_way.target7 = strzone(new_way.target7);
|
||||
dprint ("Waypoint target7 ");
|
||||
dprint (new_way.target7);
|
||||
dprint ("\n");
|
||||
}
|
||||
if (trg8)
|
||||
{
|
||||
new_way.target8 = trg8;
|
||||
new_way.target8 = strzone(new_way.target8);
|
||||
dprint ("Waypoint target8 ");
|
||||
dprint (new_way.target8);
|
||||
dprint ("\n");
|
||||
}
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
|
||||
string tempstest;
|
||||
void() Save_Waypoints
|
||||
{
|
||||
local float file;
|
||||
string h;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_WRITE);
|
||||
|
||||
local entity dway;
|
||||
//fputs(file, "begin\n");
|
||||
dway = find(world, classname, "waypoint");
|
||||
while (dway)
|
||||
{
|
||||
dprint ("Saving waypoints\n");
|
||||
fputs(file,"Waypoint\n");
|
||||
fputs(file,"{\norigin = ");
|
||||
tempstest = vtos(dway.origin);
|
||||
tempstest = strzone(tempstest);
|
||||
fputs(file,tempstest);
|
||||
strunzone (tempstest);
|
||||
fputs(file,"\nid = ");
|
||||
fputs(file,dway.waynum);
|
||||
fputs(file,"\nspecial = ");
|
||||
fputs(file,dway.targetname);
|
||||
fputs(file,"\ntarget = ");
|
||||
fputs(file,dway.target);
|
||||
fputs(file,"\ntarget2 = ");
|
||||
fputs(file,dway.target2);
|
||||
fputs(file,"\ntarget3 = ");
|
||||
fputs(file,dway.target3);
|
||||
fputs(file,"\ntarget4 = ");
|
||||
fputs(file,dway.target4);
|
||||
fputs(file,"\ntarget5 = ");
|
||||
fputs(file,dway.target5);
|
||||
fputs(file,"\ntarget6 = ");
|
||||
fputs(file,dway.target6);
|
||||
fputs(file,"\ntarget7 = ");
|
||||
fputs(file,dway.target7);
|
||||
fputs(file,"\ntarget8 = ");
|
||||
fputs(file,dway.target8);
|
||||
fputs(file,"\n");
|
||||
fputs(file,"}\n");
|
||||
|
||||
|
||||
dway = find(dway, classname, "waypoint");
|
||||
if (dway)
|
||||
fputs(file,"\n");
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
void() Load_Waypoints
|
||||
{
|
||||
float file, which;
|
||||
string h, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8;
|
||||
local vector where;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
dprint("Loading waypoint\n");
|
||||
// the first line is just a comment, ignore it
|
||||
h = fgets(file);
|
||||
if (h != "Waypoint")
|
||||
{
|
||||
bprint(PRINT_HIGH, "Last waypoint\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
h = fgets(file);
|
||||
h = fgets(file);
|
||||
h = substring(h, 9, 20);
|
||||
where = stov(h);
|
||||
|
||||
h = (fgets(file));
|
||||
h = substring(h, 5, 20);
|
||||
which = stof(h);
|
||||
|
||||
h = (fgets(file));
|
||||
special = substring(h, 10, 20);
|
||||
special = strzone(special);
|
||||
|
||||
h = (fgets(file));
|
||||
trg = substring(h, 9, 20);
|
||||
trg = strzone(trg);
|
||||
|
||||
h = (fgets(file));
|
||||
trg2 = substring(h, 10, 20);
|
||||
trg2 = strzone(trg2);
|
||||
|
||||
h = (fgets(file));
|
||||
trg3 = substring(h, 10, 20);
|
||||
trg3 = strzone(trg3);
|
||||
|
||||
h = (fgets(file));
|
||||
trg4 = substring(h, 10, 20);
|
||||
trg4 = strzone(trg4);
|
||||
|
||||
h = (fgets(file));
|
||||
trg5 = substring(h, 10, 20);
|
||||
trg5 = strzone(trg5);
|
||||
|
||||
h = (fgets(file));
|
||||
trg6 = substring(h, 10, 20);
|
||||
trg6 = strzone(trg6);
|
||||
|
||||
h = (fgets(file));
|
||||
trg7 = substring(h, 10, 20);
|
||||
trg7 = strzone(trg7);
|
||||
|
||||
h = (fgets(file));
|
||||
trg8 = substring(h, 10, 20);
|
||||
trg8 = strzone(trg8);
|
||||
|
||||
Create_Waypoint(where, which, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8);
|
||||
|
||||
strunzone (trg);
|
||||
strunzone (trg2);
|
||||
strunzone (trg3);
|
||||
strunzone (trg4);
|
||||
strunzone (trg5);
|
||||
strunzone (trg6);
|
||||
strunzone (trg7);
|
||||
strunzone (trg8);
|
||||
h = (fgets(file));
|
||||
h = (fgets(file));
|
||||
}
|
||||
}
|
828
source/server/ai/waypoints_core.qc
Normal file
828
source/server/ai/waypoints_core.qc
Normal file
|
@ -0,0 +1,828 @@
|
|||
/*
|
||||
server/ai/pathfind_core.qc
|
||||
|
||||
generic waypoints
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() creator_way_touch =
|
||||
{
|
||||
if (cvar("waypoint_mode")) {
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
current_way = self;
|
||||
}
|
||||
}
|
||||
|
||||
void () Create_New_Waypoint =
|
||||
{
|
||||
float way_count;
|
||||
float tempf;
|
||||
entity tempe;
|
||||
entity new_way;
|
||||
|
||||
way_count = -1;
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe) {
|
||||
tempf = stof(tempe.waynum);
|
||||
if (tempf > way_count) {
|
||||
way_count = tempf;
|
||||
}
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, self.origin);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.waynum = ftos(way_count + 1);
|
||||
new_way.targetname = strzone(new_way.targetname);
|
||||
bprint (PRINT_HIGH, "Created waypoint ");
|
||||
bprint (PRINT_HIGH, new_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
|
||||
|
||||
void () Make_Special_Waypoint =
|
||||
{
|
||||
if (self.classname != "player" || !active_way) {
|
||||
return;
|
||||
}
|
||||
if (active_way.targetname != "") {//Toggling it back off
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
active_way.targetname = "";
|
||||
bprint (PRINT_HIGH, "Waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, " is no longer a special waypoint\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_way) {
|
||||
if(self.active_door == world) {
|
||||
bprint (PRINT_HIGH, "Error: no door selected!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(self.active_door.wayTarget == "") {
|
||||
bprint (PRINT_HIGH, "Error: Door has no wayTarget value!\n");
|
||||
return;
|
||||
}
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
active_way.targetname = self.active_door.wayTarget;
|
||||
|
||||
bprint (PRINT_HIGH, "special waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, " named ");
|
||||
bprint (PRINT_HIGH, active_way.targetname);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void () Move_Waypoint =
|
||||
{
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
setorigin (active_way, self.origin);
|
||||
bprint (PRINT_HIGH, "Moved waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
}
|
||||
|
||||
void () Select_Waypoint =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
|
||||
entity tempe;
|
||||
|
||||
if (current_way == active_way)
|
||||
active_way = world;
|
||||
else
|
||||
active_way = current_way;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe)
|
||||
{
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr");
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
if (active_way)
|
||||
{
|
||||
if (active_way.targetname != "")
|
||||
setmodel(active_way, "models/way/current_way_door.spr");
|
||||
else
|
||||
setmodel(active_way, "models/way/current_way.spr");
|
||||
|
||||
bprint (PRINT_HIGH, "Selected waypoint ");
|
||||
bprint (PRINT_HIGH, active_way.waynum);
|
||||
if(active_way.targetname != "")
|
||||
{
|
||||
bprint (PRINT_HIGH, ", special tag ");
|
||||
bprint (PRINT_HIGH, active_way.targetname);
|
||||
}
|
||||
bprint (PRINT_HIGH, "\n");
|
||||
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
tempe = find (world, waynum, active_way.targets[i]);
|
||||
if (tempe) {
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/last_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/last_way.spr");
|
||||
} else {
|
||||
active_way.targets[i] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void() Remove_Waypoint =
|
||||
{
|
||||
entity tempe;
|
||||
float i;
|
||||
if (!active_way)
|
||||
return;
|
||||
|
||||
tempe = find (world, classname, "waypoint");
|
||||
while (tempe) {
|
||||
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (tempe.targets[i] == active_way.waynum) {
|
||||
tempe.targets[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
tempe = find (tempe, classname, "waypoint");
|
||||
}
|
||||
|
||||
bprint(PRINT_HIGH, "Removed waypoint ");
|
||||
bprint(PRINT_HIGH, active_way.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
remove (active_way);
|
||||
}
|
||||
|
||||
float Waypoint_Linked_To(entity from, entity to) {
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (from.waynum == to.targets[i]) {
|
||||
bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Link (entity from, entity to) {
|
||||
float i;
|
||||
entity tempe;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
tempe = find (world, waynum, from.targets[i]);
|
||||
|
||||
if (tempe == world || tempe == to) {
|
||||
from.targets[i] = to.waynum;
|
||||
bprint(PRINT_HIGH, "Linked waypoint ");
|
||||
bprint(PRINT_HIGH, to.waynum);
|
||||
bprint(PRINT_HIGH, " to ");
|
||||
bprint(PRINT_HIGH, from.waynum);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
|
||||
if (to.targetname != "") {
|
||||
setmodel(to, "models/way/last_way_door.spr");
|
||||
} else {
|
||||
setmodel(to, "models/way/last_way.spr");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void () Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
if (Waypoint_Linked_To(current_way, active_way)) {
|
||||
bprint(PRINT_HIGH, "These waypoints are already linked!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
float i;
|
||||
entity tempe;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
#ifdef PC
|
||||
tempe = findfloat (world, waynum, active_way.targets[i]);
|
||||
#else
|
||||
tempe = find (world, waynum, active_way.targets[i]);
|
||||
#endif
|
||||
|
||||
if (tempe == world) {
|
||||
if (Link(active_way, current_way)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bprint(PRINT_HIGH, "no targets remaining!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void() Dual_Link_Waypoints =
|
||||
{
|
||||
if (self.classname != "player" || !current_way || !active_way || current_way == active_way) {
|
||||
return;
|
||||
}
|
||||
|
||||
float result1,result2;
|
||||
result1 = Waypoint_Linked_To(current_way,active_way);
|
||||
result2 = Waypoint_Linked_To(active_way,current_way);
|
||||
|
||||
if(result1 && result2) {
|
||||
bprint(PRINT_HIGH, "Both waypoints already linked!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!result1)
|
||||
{
|
||||
if (Link(current_way,active_way)) {
|
||||
bprint(PRINT_HIGH, strcat("Linked waypoint ", strcat(current_way.waynum, strcat(" to ",strcat(active_way.waynum, "\n")))));
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("ERROR: Could not link waypoint ", strcat(current_way.waynum, strcat(" to ", strcat(active_way.waynum, "\n")))));
|
||||
}
|
||||
}
|
||||
if(!result2)
|
||||
{
|
||||
if (Link(active_way,current_way)) {
|
||||
bprint(PRINT_HIGH, strcat("Linked waypoint ", strcat(active_way.waynum, strcat(" to ", strcat(current_way.waynum, "\n")))));
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("ERROR: Could not link waypoint ", strcat(active_way.waynum, strcat(" to ", strcat(current_way.waynum, "\n")))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//alter auto_link_waypoints to iterate through the closest waypoints from closest to furthest
|
||||
// on the innermost loop, we find the next closest waypoint that is further away from the last closest waypoint, and we use that!
|
||||
|
||||
void() Auto_Link_Waypoints =
|
||||
{
|
||||
entity tempe1, tempe2;
|
||||
|
||||
tempe1 = find(world,classname,"waypoint");
|
||||
while(tempe1 != world)
|
||||
{
|
||||
tempe2 = find(world,classname,"waypoint");
|
||||
while(tempe2 != world)
|
||||
{
|
||||
if(tempe1 == tempe2)
|
||||
{
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(tracemove(tempe1.origin,VEC_HULL_MIN,VEC_HULL_MAX,tempe2.origin,TRUE,self))
|
||||
{
|
||||
Link(tempe1,tempe2);
|
||||
}
|
||||
|
||||
tempe2 = find(tempe2,classname,"waypoint");
|
||||
}
|
||||
tempe1 = find(tempe1,classname,"waypoint");
|
||||
}
|
||||
}
|
||||
//alter auto_link_waypoints to iterate through the closest waypoints from closest to furthest
|
||||
// on the innermost loop, we find the next closest waypoint that is further away from the last closest waypoint, and we use that!
|
||||
|
||||
void() Remove_Links =
|
||||
{
|
||||
entity tempe;
|
||||
|
||||
tempe = find(world,classname,"waypoint");
|
||||
while(tempe != world)
|
||||
{
|
||||
float i;
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i = i + 1) {
|
||||
if (tempe.targetname != "")
|
||||
setmodel(tempe, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(tempe, "models/way/normal_way.spr");
|
||||
tempe.targets[i] = "";
|
||||
}
|
||||
tempe = find(tempe,classname,"waypoint");
|
||||
}
|
||||
}
|
||||
|
||||
void() Save_Waypoints
|
||||
{
|
||||
float file;
|
||||
string h;
|
||||
float i;
|
||||
entity tempe;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_WRITE);
|
||||
|
||||
dprint (strcat("Saving waypoints ", strcat(h, "\n")));
|
||||
|
||||
local entity dway;
|
||||
//fputs(file, "begin\n");
|
||||
dway = find(world, classname, "waypoint");
|
||||
while (dway)
|
||||
{
|
||||
fputs(file,"waypoint\n");
|
||||
fputs(file,"{\n");
|
||||
fputs(file, strcat(" id: ", strcat(dway.waynum, "\n")));
|
||||
fputs(file, strcat(" origin: ", strcat(vtos(dway.origin), "\n")));
|
||||
if (dway.targetname != "") {
|
||||
fputs(file, strcat(" door: ", strcat(dway.targetname, "\n")));
|
||||
}
|
||||
|
||||
fputs(file, " targets:\n");
|
||||
fputs(file, " [\n");
|
||||
for (i = 0; i < MAX_WAY_TARGETS; i++) {
|
||||
if (dway.targets[i] != "") {
|
||||
#ifdef PC
|
||||
tempe = findfloat (world, waynum, dway.targets[i]);
|
||||
#else
|
||||
tempe = find (world, waynum, dway.targets[i]);
|
||||
#endif
|
||||
|
||||
if (tempe != world) {
|
||||
fputs(file, strcat(" ", strcat(dway.targets[i], "\n")));
|
||||
} else {
|
||||
tempe = find (world, waynum, dway.targets[i]);
|
||||
if (tempe != world) {
|
||||
fputs(file, strcat(" ", strcat(dway.targets[i], "\n")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs(file, " ]\n");
|
||||
fputs(file,"}\n");
|
||||
|
||||
|
||||
dway = find(dway, classname, "waypoint");
|
||||
if (dway)
|
||||
fputs(file,"\n");
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void (vector here, float which, string special, string trg, string trg2, string trg3, string trg4, string trg5, string trg6, string trg7, string trg8) Create_Waypoint =
|
||||
{
|
||||
entity new_way;
|
||||
new_way = spawn();
|
||||
|
||||
setorigin(new_way, here);
|
||||
|
||||
|
||||
//new_way.flags = FL_ITEM;
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.waynum = ftos(which);
|
||||
dprint ("Created waypoint ");
|
||||
dprint (new_way.waynum);
|
||||
dprint ("\n");
|
||||
|
||||
if (special != "")
|
||||
{
|
||||
if (!cvar("waypoint_mode"))
|
||||
new_way.classname = "waypoint_s";
|
||||
if (cvar("waypoint_mode"))
|
||||
setmodel(new_way, "models/way/normal_way_door.spr");
|
||||
new_way.targetname = special;
|
||||
dprint ("Special waypoint ");
|
||||
dprint (new_way.targetname);
|
||||
dprint ("\n");
|
||||
//current_special++;
|
||||
}
|
||||
|
||||
new_way.targets[0] = trg;
|
||||
new_way.targets[1] = trg2;
|
||||
new_way.targets[2] = trg3;
|
||||
new_way.targets[3] = trg4;
|
||||
new_way.targets[4] = trg5;
|
||||
new_way.targets[5] = trg6;
|
||||
new_way.targets[6] = trg7;
|
||||
new_way.targets[7] = trg8;
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
}
|
||||
|
||||
float waypoints_loaded;
|
||||
void() Load_Waypoints
|
||||
{
|
||||
float file, point;
|
||||
string h;
|
||||
float targetcount, loop;
|
||||
|
||||
entity new_way;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
new_way = spawn();
|
||||
targetcount = 0;
|
||||
point = 0;
|
||||
loop = 1;
|
||||
while (loop)
|
||||
{
|
||||
string line;
|
||||
line = fgets(file);
|
||||
if not (line) {
|
||||
bprint(PRINT_HIGH, "End of file\n");
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
h = strtrim(line);
|
||||
|
||||
//bprint(PRINT_HIGH, strcat(h, "\n"));
|
||||
if (h == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (point) {
|
||||
case 0:
|
||||
if (h == "waypoint") {
|
||||
new_way = spawn();
|
||||
new_way.solid = SOLID_TRIGGER;
|
||||
new_way.model = "models/way/normal_way.spr";
|
||||
setmodel(new_way, "models/way/normal_way.spr");
|
||||
new_way.classname = "waypoint";
|
||||
|
||||
new_way.touch = creator_way_touch;
|
||||
point = 1;
|
||||
targetcount = 0;
|
||||
} else if (h == "Waypoint") {
|
||||
bprint(PRINT_HIGH, "Identified .way as legacy..\n");
|
||||
point = 99;
|
||||
Load_Waypoints_Legacy();
|
||||
loop = 0;
|
||||
break;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown point ", strcat(h, "\n")));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (h == "{") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected {\n")));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
tokenize(h);
|
||||
|
||||
string value, variable;
|
||||
variable = strtrim(argv(0));
|
||||
value = strtrim(argv(2));
|
||||
|
||||
//bprint(PRINT_HIGH, strcat(variable, "\n"));
|
||||
|
||||
switch (variable) {
|
||||
case "origin":
|
||||
|
||||
print(strcat(value, "\n"));
|
||||
new_way.origin = stov(value);
|
||||
setorigin(new_way, new_way.origin);
|
||||
break;
|
||||
case "id":
|
||||
new_way.waynum = value;
|
||||
break;
|
||||
case "door":
|
||||
new_way.targetname = value;
|
||||
|
||||
setmodel(new_way, "models/way/normal_way_door.spr");
|
||||
break;
|
||||
case "targets":
|
||||
point = 3;
|
||||
break;
|
||||
case "}":
|
||||
point = 0;
|
||||
break;
|
||||
default:
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(variable, "\n")));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (h == "[") {
|
||||
point = 4;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (targetcount >= MAX_WAY_TARGETS) {
|
||||
bprint(PRINT_HIGH, "Error: Target count too high for waypoint\n");
|
||||
} else if (h == "]") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat(strcat("WAYPOINT TARGET: ", strcat(strcat(ftos(targetcount), " "), h)), "\n"));
|
||||
new_way.targets[targetcount] = h;
|
||||
targetcount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
waypoints_loaded = 1;
|
||||
}
|
||||
|
||||
void() Load_Waypoints_Legacy
|
||||
{
|
||||
float file, which;
|
||||
string h, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8;
|
||||
local vector where;
|
||||
|
||||
h = strcat(mappath, ".way");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
dprint("Error: file not found \n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
dprint("Loading waypoint\n");
|
||||
// the first line is just a comment, ignore it
|
||||
h = fgets(file);
|
||||
if (h != "Waypoint")
|
||||
{
|
||||
bprint(PRINT_HIGH, "Last waypoint\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
h = fgets(file);
|
||||
h = fgets(file);
|
||||
h = substring(h, 9, 20);
|
||||
where = stov(h);
|
||||
|
||||
h = (fgets(file));
|
||||
h = substring(h, 5, 20);
|
||||
which = stof(h);
|
||||
|
||||
h = (fgets(file));
|
||||
special = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg = substring(h, 9, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg2 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg3 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg4 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg5 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg6 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg7 = substring(h, 10, 20);
|
||||
|
||||
h = (fgets(file));
|
||||
trg8 = substring(h, 10, 20);
|
||||
|
||||
#ifndef PC
|
||||
Create_Waypoint(where, which, special, trg, trg2, trg3, trg4, trg5, trg6, trg7, trg8);
|
||||
#else
|
||||
waypoint_ai waypoint;
|
||||
waypoint = waypoints[which];
|
||||
|
||||
waypoints[which].id = which;
|
||||
waypoints[which].org = where;
|
||||
waypoints[which].targetdoor = special;
|
||||
|
||||
waypoints[which].target_id[0] = stof(trg);
|
||||
waypoints[which].target_id[1] = stof(trg2);
|
||||
waypoints[which].target_id[2] = stof(trg3);
|
||||
waypoints[which].target_id[3] = stof(trg4);
|
||||
waypoints[which].target_id[4] = stof(trg5);
|
||||
waypoints[which].target_id[5] = stof(trg6);
|
||||
waypoints[which].target_id[6] = stof(trg7);
|
||||
waypoints[which].target_id[7] = stof(trg8);
|
||||
#endif
|
||||
|
||||
h = (fgets(file));
|
||||
h = (fgets(file));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VisualizePathfind() {
|
||||
if (self.classname != "player")
|
||||
return;
|
||||
if (!current_way)
|
||||
return;
|
||||
if (!active_way)
|
||||
return;
|
||||
if (current_way == active_way)
|
||||
return;
|
||||
|
||||
Pathfind(self, stof(active_way.waynum), stof(current_way.waynum));
|
||||
}
|
||||
|
||||
.float waypoint_delay;
|
||||
|
||||
//Waypoint logic functions
|
||||
void () Waypoint_Functions =
|
||||
{
|
||||
// naievil -- archaic
|
||||
/*
|
||||
switch (self.impulse) {
|
||||
case 100:
|
||||
Create_New_Waypoint();
|
||||
break;
|
||||
case 101:
|
||||
Make_Special_Waypoint();
|
||||
break;
|
||||
case 102:
|
||||
Select_Waypoint();
|
||||
break;
|
||||
case 103:
|
||||
Move_Waypoint();
|
||||
break;
|
||||
case 104:
|
||||
Link_Waypoints ();
|
||||
break;
|
||||
case 105:
|
||||
Dual_Link_Waypoints();
|
||||
break;
|
||||
case 106:
|
||||
Save_Waypoints();
|
||||
break;
|
||||
case 107:
|
||||
Load_Waypoints();
|
||||
break;
|
||||
case 108:
|
||||
Load_Waypoints_Legacy();
|
||||
break;
|
||||
case 109:
|
||||
Remove_Waypoint();
|
||||
//VisualizePathfind();
|
||||
break;
|
||||
case 110:
|
||||
Auto_Link_Waypoints();
|
||||
break;
|
||||
case 111:
|
||||
Remove_Links();
|
||||
break;
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
*/
|
||||
|
||||
switch (self.impulse) {
|
||||
case 23:
|
||||
Save_Waypoints();
|
||||
break;
|
||||
case 22:
|
||||
if (!waypoints_loaded)
|
||||
Load_Waypoints();
|
||||
break;
|
||||
case 110:
|
||||
Move_Waypoint();
|
||||
break;
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
|
||||
// Match what we display on the screen
|
||||
if (self.button0 && self.waypoint_delay < time) {
|
||||
Create_New_Waypoint();
|
||||
self.waypoint_delay = time + 1;
|
||||
}
|
||||
|
||||
if (self.button7 && self.waypoint_delay < time) {
|
||||
Select_Waypoint();
|
||||
self.waypoint_delay = time + 0.25;
|
||||
}
|
||||
|
||||
if (self.button8 && self.waypoint_delay < time) {
|
||||
Link_Waypoints ();
|
||||
self.waypoint_delay = time + 0.5;
|
||||
}
|
||||
|
||||
if (self.button6 && self.waypoint_delay < time) {
|
||||
Remove_Waypoint();
|
||||
self.waypoint_delay = time + 0.5;
|
||||
}
|
||||
|
||||
if (self.button5 && self.waypoint_delay < time) {
|
||||
Make_Special_Waypoint();
|
||||
self.waypoint_delay = time + 1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void () Waypoint_Logic =
|
||||
{
|
||||
if (!waypoint_mode) {
|
||||
waypoint_mode = 1;
|
||||
entity zent;
|
||||
|
||||
zent = find (world, classname, "ai_zombie");
|
||||
while (zent)
|
||||
{
|
||||
remove (zent);
|
||||
zent = find (zent, classname, "ai_zombie");
|
||||
}
|
||||
|
||||
zent = find (world, classname, "door_nzp_cost");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "door_nzp_cost");
|
||||
}
|
||||
zent = find (world, classname, "door_nzp");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent.solid = SOLID_NOT;
|
||||
zent = find (zent, classname, "door_nzp");
|
||||
}
|
||||
zent = find (world, classname, "window");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "window");
|
||||
}
|
||||
|
||||
}
|
||||
Waypoint_Functions();
|
||||
};
|
1679
source/server/ai/zombie_core.qc
Normal file
1679
source/server/ai/zombie_core.qc
Normal file
File diff suppressed because it is too large
Load diff
542
source/server/clientfuncs.qc
Normal file
542
source/server/clientfuncs.qc
Normal file
|
@ -0,0 +1,542 @@
|
|||
/*
|
||||
server/clientfuncs.qc
|
||||
|
||||
used to communicate between server and client
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void SetUpdate(entity client, float type, float val1, float val2, float val3)
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
if (type != 2)
|
||||
{
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_UPDATE);
|
||||
WriteByte(MSG_MULTICAST, type); // UT_HUD
|
||||
WriteByte(MSG_MULTICAST, val1);
|
||||
WriteByte(MSG_MULTICAST, val2);
|
||||
WriteByte(MSG_MULTICAST, val3); // misc flags/vars for later if needed
|
||||
msg_entity = client;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_UPDATE);
|
||||
WriteByte(MSG_MULTICAST, type); // UT_ROUNDS_CHANGE
|
||||
WriteByte(MSG_MULTICAST, val1);
|
||||
WriteByte(MSG_MULTICAST, val2);
|
||||
WriteByte(MSG_MULTICAST, val3); // misc flags/vars for later if needed
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
void(entity to, float type, float cost, float weapon) useprint = {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_USEPRINT);
|
||||
WriteByte(MSG_MULTICAST, type);
|
||||
WriteShort(MSG_MULTICAST, cost);
|
||||
WriteByte(MSG_MULTICAST, weapon);
|
||||
msg_entity = to;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void(vector org) CallExplosion = {
|
||||
#ifndef PC
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
#else
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_EXPLOSION);
|
||||
WriteCoord(MSG_MULTICAST, org_x);
|
||||
WriteCoord(MSG_MULTICAST, org_y);
|
||||
WriteCoord(MSG_MULTICAST, org_z);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NotifyNewRound(float to) {
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_NEWROUND);
|
||||
WriteByte(MSG_MULTICAST, to);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetRound(entity client, float to) {
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_SETROUND);
|
||||
WriteByte(MSG_MULTICAST, to);
|
||||
msg_entity = client;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetPerk(entity client, float to)
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_PERK);
|
||||
WriteLong(MSG_MULTICAST, to);
|
||||
msg_entity = client;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(float to) SwitchWeapon =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_WEAPONCHANGE);
|
||||
WriteByte(MSG_MULTICAST, to);
|
||||
msg_entity = self;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
// hotfix for weapon2models not reseting
|
||||
self.weapon2model = GetWeapon2Model(to);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(string to, float skin) UpdateVmodel =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_UPDATEVMODEL);
|
||||
WriteString(MSG_MULTICAST, to);
|
||||
WriteByte(MSG_MULTICAST, skin);
|
||||
msg_entity = self;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(string to, float skin) UpdateV2model =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_UPDATEV2MODEL);
|
||||
WriteString(MSG_MULTICAST, to);
|
||||
WriteByte(MSG_MULTICAST, skin);
|
||||
msg_entity = self;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(float broadcast_time, float type) BroadcastMessage =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_BROADCAST);
|
||||
WriteByte(MSG_MULTICAST, broadcast_time);
|
||||
WriteByte(MSG_MULTICAST, type);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(float playernum, float points, float am, float kills, string name, entity person) UpdatePlayerPoints =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
if (player_count == 0) {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_POINTUPDATE);
|
||||
WriteByte(MSG_MULTICAST, playernum);
|
||||
WriteLong(MSG_MULTICAST, points);
|
||||
WriteLong(MSG_MULTICAST, am);
|
||||
WriteLong(MSG_MULTICAST, kills);
|
||||
WriteString(MSG_MULTICAST, name);
|
||||
msg_entity = person;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
}
|
||||
else {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_POINTUPDATE);
|
||||
WriteByte(MSG_MULTICAST, playernum);
|
||||
WriteLong(MSG_MULTICAST, points);
|
||||
WriteLong(MSG_MULTICAST, am);
|
||||
WriteLong(MSG_MULTICAST, kills);
|
||||
WriteString(MSG_MULTICAST, name);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(float count) UpdatePlayerCount = {
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
if (count == 0)
|
||||
return;
|
||||
else {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_PLAYERUPDATE);
|
||||
WriteByte(MSG_MULTICAST, count);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(float newtime, float newtype, entity change) PromptLevelChange =
|
||||
{
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_BLACKOUT);
|
||||
WriteByte(MSG_MULTICAST, newtime);
|
||||
WriteByte(MSG_MULTICAST, newtype);
|
||||
msg_entity = change;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void(entity who) UpdatePunchangle =
|
||||
{
|
||||
|
||||
// naievil -- shit logic lol...but result looks clean as fuck...
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_PUNCHANGLE);
|
||||
WriteCoord(MSG_MULTICAST, who.punchangle_x);
|
||||
WriteCoord(MSG_MULTICAST, who.punchangle_y);
|
||||
WriteCoord(MSG_MULTICAST, who.punchangle_z);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
|
||||
vector tempv = who.punchangle;
|
||||
|
||||
if (fabs(who.punchangle_x) > 0.01) {
|
||||
if (who.punchangle_x >= 0.05*tempv_x)
|
||||
who.punchangle_x -= 0.05*tempv_x;
|
||||
else if (who.punchangle_x <= -0.05*tempv_x)
|
||||
who.punchangle_x -= 0.05*tempv_x;
|
||||
else
|
||||
who.punchangle_x = 0;
|
||||
} else
|
||||
who.punchangle_x = 0;
|
||||
|
||||
if (fabs(who.punchangle_y) > 0.01) {
|
||||
if (who.punchangle_y >= 0.05*tempv_y)
|
||||
who.punchangle_y -= 0.05*tempv_y;
|
||||
else if (who.punchangle_y <= -0.05*tempv_y)
|
||||
who.punchangle_y -= 0.05*tempv_y;
|
||||
else
|
||||
who.punchangle_y = 0;
|
||||
} else
|
||||
who.punchangle_y = 0;
|
||||
|
||||
if (fabs(who.punchangle_z) > 0.01) {
|
||||
if (who.punchangle_z >= 0.05*tempv_z)
|
||||
who.punchangle_z -= 0.05*tempv_z;
|
||||
else if (who.punchangle_z <= -0.05*tempv_z)
|
||||
who.punchangle_z -= 0.05*tempv_z;
|
||||
else
|
||||
who.punchangle_z = 0;
|
||||
} else
|
||||
who.punchangle_z = 0;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
void(string h, float h2, entity who) pushHUD = {
|
||||
if (player_count == 0) {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_HUDUPDATE);
|
||||
WriteString(MSG_MULTICAST, h);
|
||||
WriteByte(MSG_MULTICAST, h2);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
} else {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_WEAPONUPDATE);
|
||||
WriteString(MSG_MULTICAST, h);
|
||||
WriteByte(MSG_MULTICAST, h2);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
void (float wepnum, string wepname, string wvmodel, float mag, float reserve, string ads, float min, float max, string flash, float flashsize, string v2, float isd, entity who) sendCustomWeapon = {
|
||||
if (player_count == 0) {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_WEAPONUPDATE);
|
||||
WriteByte(MSG_MULTICAST, wepnum);
|
||||
WriteString(MSG_MULTICAST, wepname);
|
||||
WriteString(MSG_MULTICAST, wvmodel);
|
||||
WriteByte(MSG_MULTICAST, mag);
|
||||
WriteByte(MSG_MULTICAST, reserve);
|
||||
WriteString(MSG_MULTICAST, ads);
|
||||
WriteByte(MSG_MULTICAST, min);
|
||||
WriteByte(MSG_MULTICAST, max);
|
||||
WriteString(MSG_MULTICAST, flash);
|
||||
WriteByte(MSG_MULTICAST, flashsize);
|
||||
WriteString(MSG_MULTICAST, v2);
|
||||
WriteByte(MSG_MULTICAST, isd);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
} else {
|
||||
WriteByte(MSG_ALL, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_ALL, EVENT_WEAPONUPDATE);
|
||||
WriteByte(MSG_ALL, wepnum);
|
||||
WriteString(MSG_ALL, wepname);
|
||||
WriteString(MSG_ALL, wvmodel);
|
||||
WriteByte(MSG_ALL, mag);
|
||||
WriteByte(MSG_ALL, reserve);
|
||||
WriteString(MSG_ALL, ads);
|
||||
WriteByte(MSG_ALL, min);
|
||||
WriteByte(MSG_ALL, max);
|
||||
WriteString(MSG_ALL, flash);
|
||||
WriteByte(MSG_ALL, flashsize);
|
||||
WriteString(MSG_ALL, v2);
|
||||
WriteByte(MSG_ALL, isd);
|
||||
}
|
||||
}
|
||||
|
||||
void(string msg, entity who) ScrollText = {
|
||||
if (player_count == 0) {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_SCROLLTEXT);
|
||||
WriteString(MSG_MULTICAST, msg);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
} else {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_SCROLLTEXT);
|
||||
WriteString(MSG_MULTICAST, msg);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
void(string chaptertitle, string location, string date, string person, entity who) WorldText = {
|
||||
if (player_count == 0) {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_WORLDDATA);
|
||||
WriteString(MSG_MULTICAST, chaptertitle);
|
||||
WriteString(MSG_MULTICAST, location);
|
||||
WriteString(MSG_MULTICAST, date);
|
||||
WriteString(MSG_MULTICAST, person);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
} else {
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_WORLDDATA);
|
||||
WriteString(MSG_MULTICAST, chaptertitle);
|
||||
WriteString(MSG_MULTICAST, location);
|
||||
WriteString(MSG_MULTICAST, date);
|
||||
WriteString(MSG_MULTICAST, person);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NX
|
||||
void (float achievement_id, optional entity who) GiveAchievement =
|
||||
{
|
||||
#ifdef PSP
|
||||
// temp
|
||||
if (achievement_id > 4)
|
||||
return;
|
||||
#endif // PSP
|
||||
|
||||
// this is an achievement specific to an individual
|
||||
if ((who && who != world) || player_count == 0) {
|
||||
if (player_count == 0) who = find(world, classname, "player");
|
||||
#ifdef PSP
|
||||
achievement(who, achievement_id);
|
||||
#else
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_ACHIEVEMENT);
|
||||
WriteByte(MSG_MULTICAST, achievement_id);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
#endif // PSP
|
||||
} else {
|
||||
#ifdef PSP
|
||||
entity players;
|
||||
players = find(world, classname, "player");
|
||||
while(players != world) {
|
||||
achievement(players, achievement_id);
|
||||
players = find(players, classname, "player");
|
||||
}
|
||||
#else
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_ACHIEVEMENT);
|
||||
WriteByte(MSG_MULTICAST, achievement_id);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
#endif // PSP
|
||||
}
|
||||
}
|
||||
|
||||
void (float achievement_id, float progress_value, optional entity who) UpdateAchievementProgress =
|
||||
{
|
||||
#ifdef PSP
|
||||
// temp
|
||||
if (achievement_id > 4)
|
||||
return;
|
||||
#endif // PSP
|
||||
// this is a progress update specific to an individual
|
||||
if ((who && who != world) || player_count == 0) {
|
||||
if (player_count == 0) who = find(world, classname, "player");
|
||||
#ifdef PSP
|
||||
//achievement_progress(who, achievement_id, progress_value);
|
||||
#else
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_ACHIEVEMENTPROGRESS);
|
||||
WriteByte(MSG_MULTICAST, achievement_id);
|
||||
WriteFloat(MSG_MULTICAST, progress_value);
|
||||
msg_entity = who;
|
||||
multicast('0 0 0', MULTICAST_ONE);
|
||||
#endif // PSP
|
||||
} else {
|
||||
#ifdef PSP
|
||||
entity players;
|
||||
players = find(world, classname, "player");
|
||||
while(players != world) {
|
||||
//achievement_progress(players, achievement_id, progress_value);
|
||||
players = find(players, classname, "player");
|
||||
}
|
||||
#else
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EVENT_ACHIEVEMENTPROGRESS);
|
||||
WriteByte(MSG_MULTICAST, achievement_id);
|
||||
WriteFloat(MSG_MULTICAST, progress_value);
|
||||
multicast('0 0 0', MULTICAST_ALL);
|
||||
#endif // PSP
|
||||
}
|
||||
}
|
||||
#endif // NX
|
||||
|
||||
// *****************************************
|
||||
// Unrelated to engine, but custom functions
|
||||
// *****************************************
|
||||
|
||||
float(entity who, entity target) isFacing =
|
||||
{
|
||||
float who_angle = who.angles_y;
|
||||
float target_angle = target.angles_y;
|
||||
|
||||
float difference_angle = target_angle - who_angle;
|
||||
|
||||
#ifdef PSP
|
||||
if (difference_angle < -45) {
|
||||
difference_angle += 360;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 180 = directly facing each other, 30 degree buffer.
|
||||
if (difference_angle <= 210 && difference_angle >= 150)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float() crandom =
|
||||
{
|
||||
return 2*(random() - 0.5);
|
||||
}
|
||||
|
||||
void WeaponSwitch(entity player) {
|
||||
float wep, cmag, cmag2, cammo;
|
||||
|
||||
wep = other.weapon;
|
||||
other.weapon = other.secondaryweapon;
|
||||
other.secondaryweapon = wep;
|
||||
|
||||
cmag = other.currentmag;
|
||||
other.currentmag = other.secondarymag;
|
||||
other.secondarymag = cmag;
|
||||
|
||||
cmag2 = other.currentmag2;
|
||||
other.currentmag2 = other.secondarymag2;
|
||||
other.secondarymag2 = cmag2;
|
||||
|
||||
cammo = other.currentammo;
|
||||
other.currentammo = other.secondaryammo;
|
||||
other.secondaryammo = cammo;
|
||||
|
||||
entity tempe = self;
|
||||
self = player;
|
||||
SwitchWeapon(other.weapon);
|
||||
self = tempe;
|
||||
}
|
||||
|
||||
void(entity person, float expamt, float doublepoint) addmoney =
|
||||
{
|
||||
if (person.classname != "player" || person.downed)
|
||||
return;
|
||||
|
||||
if (expamt > 0 && doublepoint == TRUE && x2_finished > time) {
|
||||
expamt *= 2;
|
||||
person.score += expamt;
|
||||
}
|
||||
|
||||
person.points += expamt;
|
||||
|
||||
UpdatePlayerPoints(person.playernum, person.points, expamt, person.kills, person.netname, person);
|
||||
};
|
570
source/server/damage.qc
Normal file
570
source/server/damage.qc
Normal file
|
@ -0,0 +1,570 @@
|
|||
/*
|
||||
server/clientfuncs.qc
|
||||
|
||||
used for any sort of down, hit, etc that the player or entity
|
||||
experiences
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NX
|
||||
void (float achievement_id, optional entity who) GiveAchievement;
|
||||
#endif // NX
|
||||
|
||||
void() EndGame_Restart =
|
||||
{
|
||||
localcmd("restart");
|
||||
}
|
||||
|
||||
// Fade to black function, creates another think for restart
|
||||
void() EndGame_FadePrompt =
|
||||
{
|
||||
PromptLevelChange(time + 6, 2, self);
|
||||
#ifdef PC
|
||||
self.think = EndGame_Restart;
|
||||
#else
|
||||
self.think = Soft_Restart;
|
||||
#endif
|
||||
self.nextthink = time + 5;
|
||||
}
|
||||
|
||||
//Actual endgame function, all zombies die, music plays
|
||||
void() EndGame =
|
||||
{
|
||||
local entity oldself;
|
||||
local entity who;
|
||||
|
||||
self.health = 0;
|
||||
self.origin = '0 0 0';
|
||||
setorigin (self, self.origin);
|
||||
self.velocity = '0 0 0';
|
||||
sound (self, CHAN_AUTO, "sounds/music/end.wav", 1, ATTN_NORM);
|
||||
|
||||
oldself = self;
|
||||
|
||||
who = find(world,classname,"ai_zombie");
|
||||
while(who != world)
|
||||
{
|
||||
if(who.health)
|
||||
{
|
||||
self = who;
|
||||
self.th_die();
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
who = find(who,classname,"ai_zombie");
|
||||
}
|
||||
|
||||
self.think = EndGame_FadePrompt;
|
||||
self.nextthink = time + 33;
|
||||
}
|
||||
|
||||
// removes revive icon from downed player heads, used as a recursive think function
|
||||
void() remove_revive =
|
||||
{
|
||||
if (self.owner.beingrevived)
|
||||
setmodel (self, "models/sprites/revive_white.spr");
|
||||
else
|
||||
setmodel (self, "models/sprites/revive.spr");
|
||||
|
||||
if (!self.owner.downed || self.owner.isspec)
|
||||
SUB_Remove ();
|
||||
else {
|
||||
self.think = remove_revive;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
// when dead and other players exist and are alive, throw user into spectate mode
|
||||
void() startspectate =
|
||||
{
|
||||
if (!self.downed)
|
||||
return;
|
||||
|
||||
if (self.beingrevived)
|
||||
{
|
||||
self.think = startspectate;
|
||||
self.nextthink = time + 0.1;
|
||||
return;
|
||||
}
|
||||
|
||||
self.downedloop = 0;
|
||||
self.beingrevived = false;
|
||||
self.model = "";
|
||||
setmodel(self, self.model);
|
||||
self.health = 100;
|
||||
self.weaponmodel = "";
|
||||
self.weapon2model = "";
|
||||
self.downed = 0;
|
||||
self.frame = 0;
|
||||
|
||||
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
|
||||
UpdateV2model(self.weapon2model, GetWepSkin(self.weapon));
|
||||
|
||||
SpectatorSpawn();
|
||||
}
|
||||
|
||||
// searches for players that are alive given which clients have which playernumbers
|
||||
// Returns 1 if there IS someone in the world that's not downed
|
||||
float() PollPlayersAlive =
|
||||
{
|
||||
float i, gotalive;
|
||||
entity playerent;
|
||||
|
||||
gotalive = 0;
|
||||
|
||||
for (i = 1; i <= 4; i++)
|
||||
{
|
||||
playerent = findfloat(world, playernum, i);
|
||||
|
||||
if (playerent) {
|
||||
if (!playerent.downed && !playerent.isspec) {
|
||||
gotalive = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gotalive;
|
||||
}
|
||||
|
||||
// Endgamesetup -- think function for setting up the death of everyone
|
||||
void() EndGameSetup =
|
||||
{
|
||||
game_over = true;
|
||||
self.health = 10;
|
||||
self.think = EndGame;
|
||||
self.nextthink = time + 5;
|
||||
self.weapon = 0;
|
||||
self.currentammo = 0;
|
||||
self.currentmag = 0;
|
||||
self.weaponmodel = "";
|
||||
self.weapon2model = "";
|
||||
self.animend = SUB_Null;
|
||||
self.perks = 0;
|
||||
self.isspec = true;
|
||||
SetPerk(self, self.perks);
|
||||
SwitchWeapon(0);
|
||||
addmoney(self, -self.points, 0);
|
||||
addmoney(self, self.score, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// rec_downed is used as a recursive loop where we consistently check to see if ALL players are downed
|
||||
// if they aren't dead, we keep looping until our OWN death (45 seconds, so 450 loops)
|
||||
void() rec_downed =
|
||||
{
|
||||
self.downedloop++;
|
||||
if (self.downedloop == 450) {
|
||||
startspectate();
|
||||
return;
|
||||
}
|
||||
|
||||
float gotalive = PollPlayersAlive();
|
||||
|
||||
if (!gotalive && !self.progress_bar) {
|
||||
EndGameSetup();
|
||||
return;
|
||||
}
|
||||
|
||||
self.think = rec_downed;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
|
||||
void() GetDown =
|
||||
{
|
||||
float startframe;
|
||||
float endframe;
|
||||
local string modelname;
|
||||
|
||||
if (rounds <= 1 && self.currentmag == 0 && self.currentmag2 == 0 && self.currentammo == 0 && self.secondarymag == 0 &&
|
||||
self.secondarymag2 == 0 && self.secondaryammo == 0) {
|
||||
GiveAchievement(9, self);
|
||||
}
|
||||
|
||||
playdown();
|
||||
|
||||
switch(self.stance) {
|
||||
case 2:
|
||||
self.new_ofs_z = self.view_ofs_z - 42;
|
||||
self.stance = 0;
|
||||
break;
|
||||
case 1:
|
||||
self.new_ofs_z = self.view_ofs_z - 24;
|
||||
self.stance = 0;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// remove third weapon
|
||||
self.thirdweapon = 0;
|
||||
|
||||
self.velocity = '-80 0 -80'; // Stop any old movement
|
||||
self.zoom = 0;
|
||||
self.downed = true;
|
||||
self.dive_delay = 0;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
|
||||
float gotalive = PollPlayersAlive();
|
||||
|
||||
if ((coop && !gotalive) || (!coop && !(self.perks & P_REVIVE))) {
|
||||
EndGameSetup();
|
||||
return;
|
||||
} else {
|
||||
self.health = 19;
|
||||
}
|
||||
|
||||
if ((self.perks & P_REVIVE) && !coop) {
|
||||
self.progress_bar = 10 + time;
|
||||
self.progress_bar_time = 10;
|
||||
self.progress_bar_percent = 1;
|
||||
self.downed = true;
|
||||
}
|
||||
|
||||
self.points = 10*rint((self.points*0.95)/10);
|
||||
addmoney(self, 0, true); // used to call a broadcast
|
||||
BroadcastMessage(time + 3, 2);
|
||||
|
||||
self.perks = 0;
|
||||
self.weaponbk = self.weapon;
|
||||
self.currentammobk = self.currentammo;
|
||||
self.currentmagbk = self.currentmag;
|
||||
self.currentmagbk2 = self.currentmag2;
|
||||
|
||||
if (self.weapon == W_BIATCH || self.secondaryweapon == W_BIATCH || self.progress_bar_percent > 0) {
|
||||
self.weapon = W_BIATCH;
|
||||
self.currentammo = 12;
|
||||
self.currentmag = 6;
|
||||
self.currentmag2 = 6;
|
||||
} else {
|
||||
self.weapon = W_COLT;
|
||||
self.currentammo = 16;
|
||||
self.currentmag = 8;
|
||||
}
|
||||
|
||||
modelname = GetWeaponModel(self.weapon, 0);
|
||||
self.weaponmodel = modelname;
|
||||
SwitchWeapon(self.weapon);
|
||||
|
||||
startframe = GetFrame(self.weapon,TAKE_OUT_START);
|
||||
endframe = GetFrame(self.weapon,TAKE_OUT_END);
|
||||
Set_W_Frame (startframe, endframe, 0, 0, 0, SUB_Null, modelname, false, S_BOTH);
|
||||
|
||||
local entity revive;
|
||||
|
||||
revive = spawn ();
|
||||
revive.owner = self;
|
||||
revive.movetype = MOVETYPE_NONE;
|
||||
revive.solid = SOLID_NOT;
|
||||
revive.think = remove_revive;
|
||||
revive.nextthink = time + 0.1;
|
||||
|
||||
setmodel (revive, "models/sprites/revive.spr");
|
||||
revive.origin = self.origin + VEC_VIEW_OFS;
|
||||
setorigin (revive, revive.origin);
|
||||
|
||||
SetPerk(self, 0);
|
||||
|
||||
self.think = rec_downed;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
|
||||
void () GetUp =
|
||||
{
|
||||
local string modelname;
|
||||
float startframe;
|
||||
float endframe;
|
||||
|
||||
playgetup(); // animation
|
||||
|
||||
self.new_ofs_z = self.view_ofs_z + 42;
|
||||
self.stance = 2;
|
||||
self.health = 100;
|
||||
self.downedloop = 0; // used for death timing vs endgame
|
||||
self.downed = 0;
|
||||
self.classname = "player";
|
||||
if (self.weaponbk)
|
||||
{
|
||||
self.weapon = self.weaponbk;
|
||||
self.currentammo = self.currentammobk;
|
||||
self.currentmag = self.currentmagbk;
|
||||
self.currentmag2 = self.currentmagbk2;
|
||||
}
|
||||
modelname = GetWeaponModel(self.weapon, 0);
|
||||
self.weaponmodel = modelname;
|
||||
SwitchWeapon(self.weapon);
|
||||
self.weapon2model = GetWeapon2Model(self.weapon);
|
||||
self.movetype = MOVETYPE_WALK;
|
||||
|
||||
startframe = GetFrame(self.weapon,TAKE_OUT_START);
|
||||
endframe = GetFrame(self.weapon,TAKE_OUT_END);
|
||||
Set_W_Frame (startframe, endframe, 0, 0, 0, SUB_Null, modelname, false, S_BOTH);
|
||||
|
||||
};
|
||||
|
||||
// poll checking whether to see if our revive invoke is active
|
||||
void(entity ent) CheckRevive =
|
||||
{
|
||||
if (self.invoke_revive) {
|
||||
GetUp();
|
||||
self.invoke_revive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void(entity attacker, float d_style) DieHandler =
|
||||
{
|
||||
float t;
|
||||
|
||||
t = random();
|
||||
|
||||
if (self.classname == "ai_zombie" || self.classname == "ai_dog") {
|
||||
self.th_die();
|
||||
}
|
||||
|
||||
if (attacker.classname == "player") {
|
||||
attacker.kills++;
|
||||
if (d_style == S_HEADSHOT) {
|
||||
addmoney(attacker, 100, true);
|
||||
total_powerup_points = total_powerup_points + 100;
|
||||
attacker.headshots++;
|
||||
} else if (d_style == S_NORMAL) {
|
||||
addmoney(attacker, 60, true);
|
||||
total_powerup_points = total_powerup_points + 60;
|
||||
}
|
||||
else if (d_style == S_KNIFE){
|
||||
addmoney(attacker, 130, true);
|
||||
total_powerup_points = total_powerup_points + 130;
|
||||
} else if (d_style == S_TESLA) {
|
||||
addmoney(attacker, 50, true);
|
||||
total_powerup_points = total_powerup_points + 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void(entity victim,entity attacker, float damage, float d_style) DamageHandler = {
|
||||
// don't do any attacking during nuke delay
|
||||
if (d_style == S_ZOMBIE && nuke_powerup_active > time)
|
||||
return;
|
||||
|
||||
// Abstinence Program
|
||||
victim.ach_tracker_abst = 1;
|
||||
|
||||
entity old_self;
|
||||
if (victim.classname == "ai_zombie" || victim.classname == "ai_dog") {
|
||||
|
||||
if (attacker.classname == "player" && (victim.health - damage)> 0) {
|
||||
addmoney(attacker, 10, 1);
|
||||
}
|
||||
|
||||
victim.health = victim.health - damage;
|
||||
|
||||
if (d_style == S_EXPLOSIVE) {
|
||||
if (victim.health < z_health*0.5)
|
||||
{
|
||||
if (victim.crawling != TRUE && !(victim.health <= 0) && crawler_num < 5 && victim.classname != "ai_dog")
|
||||
{
|
||||
makeCrawler(victim);
|
||||
#ifndef NX
|
||||
GiveAchievement(3, attacker);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attacker.classname == "player" && (victim.health - damage) > 0)
|
||||
addmoney(attacker, 10, 1);
|
||||
}
|
||||
}
|
||||
// MOTO - explosives seem to work fine without, but with will cause counter and QC errors..
|
||||
//else
|
||||
// victim.th_die();
|
||||
|
||||
if (victim.health <= 0)
|
||||
addmoney(attacker, 60, 1);
|
||||
}
|
||||
|
||||
if (victim.health <= 0 || instakill_finished) {
|
||||
old_self = self;
|
||||
self = victim;
|
||||
DieHandler(attacker, d_style);
|
||||
self = old_self;
|
||||
}
|
||||
} else if (victim.classname == "player" && !victim.downed) {
|
||||
|
||||
if (victim.flags & FL_GODMODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (victim.perks & P_JUG)
|
||||
damage = ceil(damage*0.5);
|
||||
|
||||
victim.health = victim.health - damage;
|
||||
victim.health_delay = time + 2;
|
||||
|
||||
// shake the camera on impact
|
||||
local vector distance;
|
||||
distance = attacker.angles - victim.angles;
|
||||
|
||||
// just to prevent radical punchangles
|
||||
while(distance_x > 10 || distance_x < -10) {
|
||||
distance_x /= 2;
|
||||
}
|
||||
while(distance_y > 10 || distance_y < -10) {
|
||||
distance_y /= 2;
|
||||
}
|
||||
|
||||
// apply
|
||||
victim.punchangle_x = distance_x;
|
||||
victim.punchangle_y = distance_y;
|
||||
|
||||
// play hurt sound
|
||||
sound (self, CHAN_AUTO, "sounds/player/pain4.wav", 1, ATTN_NORM);
|
||||
|
||||
if (victim.health <= 20)
|
||||
{
|
||||
old_self = self;
|
||||
self = victim;
|
||||
GetDown();
|
||||
self = old_self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CanDamage
|
||||
|
||||
Returns true if the inflictor can directly damage the target. Used for
|
||||
explosions and melee attacks.
|
||||
============
|
||||
*/
|
||||
float(entity targ, entity inflictor) CanDamage =
|
||||
{
|
||||
if (targ.flags == FL_GODMODE)
|
||||
return FALSE;
|
||||
// bmodels need special checking because their origin is 0,0,0
|
||||
if (targ.movetype == MOVETYPE_PUSH)
|
||||
{
|
||||
traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
if (trace_ent == targ)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
traceline(inflictor.origin, targ.origin, TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
|
||||
if (trace_fraction == 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
void(entity inflictor, entity attacker, float damage2, float mindamage, float radius) DamgageExplode =
|
||||
{
|
||||
float final_damage;
|
||||
entity ent;
|
||||
|
||||
float multi, r;
|
||||
ent = findradius(inflictor.origin, radius);
|
||||
|
||||
while (ent != world)
|
||||
{
|
||||
if(ent.classname == "player")
|
||||
{
|
||||
if (ent.perks & P_FLOP)
|
||||
final_damage = 0;
|
||||
else
|
||||
{
|
||||
final_damage = radius - vlen(inflictor.origin - ent.origin);
|
||||
|
||||
if(final_damage < 0)
|
||||
continue;
|
||||
|
||||
if (final_damage > radius * 0.6)
|
||||
final_damage = 100;
|
||||
|
||||
if (final_damage < other.health)
|
||||
{
|
||||
addmoney(self, 10, 0);
|
||||
}
|
||||
else if (final_damage > other.health)
|
||||
{
|
||||
addmoney(self, 60, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
final_damage /= radius;
|
||||
final_damage *= 60;
|
||||
}
|
||||
DamageHandler (attacker, attacker, final_damage, S_EXPLOSIVE);
|
||||
}
|
||||
}
|
||||
else if (ent.takedamage && ent.classname != "ai_zombie_head" && ent.classname != "ai_zombie_larm" && ent.classname != "ai_zombie_rarm")
|
||||
{
|
||||
// verify we aren't doin anything with a bmodel
|
||||
if (ent.solid == SOLID_BSP || ent.movetype == MOVETYPE_PUSH)
|
||||
return;
|
||||
|
||||
if (mapname == "ndu" && ent.classname == "ai_zombie" && inflictor.classname == "explosive_barrel") {
|
||||
ach_tracker_barr++;
|
||||
|
||||
if (ach_tracker_barr >= 15) {
|
||||
GiveAchievement(13);
|
||||
}
|
||||
}
|
||||
|
||||
r = rounds;
|
||||
multi = 1.07;
|
||||
while(r > 0)
|
||||
{
|
||||
multi *= 1.05;
|
||||
r --;
|
||||
}
|
||||
|
||||
if (mindamage == 75)
|
||||
final_damage = (200 * multi) + 185;
|
||||
else
|
||||
final_damage = (mindamage + damage2)/2;
|
||||
|
||||
if (final_damage > 0)
|
||||
{
|
||||
/* ndaekill = true; */
|
||||
if (CanDamage (ent, inflictor))
|
||||
DamageHandler (ent, attacker, final_damage, S_EXPLOSIVE);
|
||||
/* kill = false; */
|
||||
}
|
||||
}
|
||||
ent = ent.chain;
|
||||
}
|
||||
};
|
501
source/server/defs/custom.qc
Normal file
501
source/server/defs/custom.qc
Normal file
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
server/defs/custom.qc
|
||||
|
||||
put custom server-only globals and fields here
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
#pragma target FTE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define FL_JUMPRELEASED 4096
|
||||
|
||||
// achievement tracking
|
||||
.float ach_tracker_npnp;
|
||||
.float ach_tracker_abst;
|
||||
float ach_tracker_spin;
|
||||
float ach_tracker_luck;
|
||||
.float ach_tracker_coll;
|
||||
float ach_tracker_col2;
|
||||
float ach_tracker_barr;
|
||||
|
||||
float framecount;
|
||||
float deathmatch;
|
||||
float coop;
|
||||
.vector oldvelocity;
|
||||
.float lastsound_time;
|
||||
.float isspec;
|
||||
string mappath;
|
||||
.float playernum;
|
||||
.float ads_toggle;
|
||||
float player_count;
|
||||
entity pl1;
|
||||
.string fog; // used for hacking in changing fog from world.fog for legacy maps
|
||||
|
||||
entity local_client;
|
||||
.float stance;
|
||||
.float stancereset;
|
||||
.float changestance;
|
||||
.vector new_ofs;
|
||||
|
||||
//money
|
||||
.float points;
|
||||
.float cost;
|
||||
.float cost2;
|
||||
void(entity person, float expamt , float doublepoint) addmoney;
|
||||
|
||||
//stats
|
||||
.float score;
|
||||
.float kills;
|
||||
.float headshots;
|
||||
#ifdef PC
|
||||
.float facingenemy;
|
||||
#endif
|
||||
|
||||
//doors
|
||||
.float state;
|
||||
#define STATE_TOP 0
|
||||
#define STATE_BOTTOM 1
|
||||
#define STATE_UP 2
|
||||
#define STATE_DOWN 3
|
||||
.float /*worldtype,*/ delay, wait, lip, /*light_lev,*/ speed, style/*, skill*/;
|
||||
|
||||
entity activator;
|
||||
.float requirespower;
|
||||
|
||||
//player funcs
|
||||
#ifdef PC
|
||||
.float zoom;
|
||||
#endif
|
||||
|
||||
float sprint_max_time = 4.0;
|
||||
.float sprinting;
|
||||
.float weaponskin;
|
||||
.float secondaryweaponskin;
|
||||
.float thirdweaponskin;
|
||||
.float stamina;
|
||||
.float sprint_timer;
|
||||
.float sprint_duration;
|
||||
.float sprint_timer_stopped;
|
||||
.float sprint_start_time;
|
||||
.float sprint_stop_time;
|
||||
.float sprint_rest_time;
|
||||
void() W_SprintStop;
|
||||
.float into_sprint;
|
||||
.float dive;
|
||||
.float dive_delay;
|
||||
.float damagetimer;
|
||||
.vector movement;
|
||||
|
||||
//Weaponsystem defines
|
||||
void SwitchWeapon(float to);
|
||||
void GetUp();
|
||||
void Weapon_Logic();
|
||||
.float downed;
|
||||
.float fire_delay;
|
||||
.float fire_delay2;
|
||||
.float reload_delay;
|
||||
.float reload_delay2;
|
||||
.float switch_delay;
|
||||
.float health_delay;
|
||||
.float progress_bar;
|
||||
.float progress_bar_time;
|
||||
.float progress_bar_percent;
|
||||
.float weaponbk;
|
||||
.float currentmag;
|
||||
.float currentmag2;
|
||||
.float currentmagbk;
|
||||
.float currentmagbk2;
|
||||
.float currentammobk;
|
||||
.float secondaryammo;
|
||||
.float thirdammo;
|
||||
.float semi;
|
||||
.float semi2;
|
||||
.float semiuse;
|
||||
.float semiswitch;
|
||||
.float semireload;
|
||||
.float secondarymag;
|
||||
.float secondarymag2;
|
||||
.float secondaryweapon;
|
||||
.float thirdmag;
|
||||
.float thirdmag2;
|
||||
.float thirdweapon;
|
||||
.float NeedLoad;
|
||||
.string weapon2model;
|
||||
.float weapon2frame;
|
||||
.float reloadinterupted;
|
||||
.float hitcount;
|
||||
.float weaponnum; // 0 for weapon one, 1 for second weapon...we invert value for easy comparison, a third gun would need to be hardwired
|
||||
|
||||
//Reviving
|
||||
.float invoke_revive;
|
||||
.float reviving;
|
||||
.float revived;
|
||||
.float beingrevived;
|
||||
.float downedloop;
|
||||
|
||||
#define S_LEFT 0
|
||||
#define S_RIGHT 1
|
||||
#define S_BOTH 2
|
||||
|
||||
//Knife
|
||||
.float semiknife;
|
||||
.float knife_delay;
|
||||
.float bowie;
|
||||
|
||||
//Grenades
|
||||
.float grenades;
|
||||
.float pri_grenade_state;
|
||||
.float bk_nade;
|
||||
.float grenade_delay;
|
||||
.float secondary_grenades;
|
||||
.float primary_grenades;
|
||||
.float throw_delay;
|
||||
|
||||
//weapon frames
|
||||
void Set_W_Frame (float startframe, float endframe, float duration, float funccalledin, float animtype, void(optional float t) endanimfunc, string set_model, float dontstartnew, float side);
|
||||
.float weapon_animduration;
|
||||
.float weapon2_animduration;
|
||||
.float weapon_anim_type;
|
||||
.float weapon2_anim_type;
|
||||
.float anim_weapon_time;
|
||||
.float anim_weapon2_time;
|
||||
.float weaponframe_end;
|
||||
.float weapon2frame_end;
|
||||
.float callfuncat;
|
||||
.float callfuncat2;
|
||||
.float new_anim_stop;
|
||||
.float new_anim2_stop;
|
||||
.float anim_reversed;
|
||||
.float anim2_reversed;
|
||||
.void() animend;
|
||||
.void(optional float t) animend2;
|
||||
|
||||
//Null functions
|
||||
void() SUB_Null = {};
|
||||
void() SUB_Null2 = {};
|
||||
|
||||
#define VEC_HULL_MIN '-16 -16 -32'
|
||||
#define VEC_HULL_MAX '16 16 40'
|
||||
#define VEC_HULL2_MIN '-32 -32 -24'
|
||||
#define VEC_HULL2_MAX '32 32 64'
|
||||
|
||||
#define VEC_VIEW_OFS '0 0 32'
|
||||
|
||||
#ifdef PSP
|
||||
#define MAX_ZOMB 12
|
||||
#else
|
||||
#define MAX_ZOMB 24
|
||||
#endif
|
||||
|
||||
vector trace_plane_normal;
|
||||
|
||||
|
||||
// AI definitions
|
||||
//Used for global one-zombie-at-a-time type ai
|
||||
void Do_Zombie_AI();
|
||||
.string aistatus;
|
||||
entity lastzombie;
|
||||
float zombie_spawn_delay; // time before spawning, in seconds.
|
||||
float zombie_spawn_timer; // the actual timer for spawn delay
|
||||
//Other AI definitions
|
||||
.vector box1, box2, box3;//used for windows and zombies
|
||||
.vector idlebox;
|
||||
.vector hop_spot;//used for windows (zombies hop to these)
|
||||
.vector goalorigin;
|
||||
.float teslacount;
|
||||
.float iszomb;
|
||||
.float onfire;
|
||||
.entity firer;
|
||||
float crawler_num;
|
||||
//==== Reference Vars ====
|
||||
#define WWINDOW 1
|
||||
#define WBOX1 2
|
||||
#define WBOX2 4
|
||||
#define WBOX3 8
|
||||
#define WIDLEBOX 16
|
||||
//========================
|
||||
|
||||
//we're using usedent for who is currently hopping the window
|
||||
//Used for windows to keep track of what zombies are at windows
|
||||
.entity box1owner, box2owner, box3owner;
|
||||
|
||||
.entity usedent;
|
||||
//.float used;//used for the window boxes//not anymore
|
||||
.float outside;//used for knowing if a zomibe has hopped window yet
|
||||
.float chase_enemy_time;
|
||||
.float chase_time;
|
||||
.float enemy_timeout;
|
||||
//.float pathing;
|
||||
.float calc_time; //used as a delay thing (so zombie ai doesn't run 100% of the time
|
||||
.string target2;
|
||||
.string target3;
|
||||
.string target4;
|
||||
.string target5;
|
||||
.string target6;
|
||||
.string target7;
|
||||
.string target8;
|
||||
.string wayTarget;
|
||||
.entity active_door;//Set in waypoint mode
|
||||
.string targetname;//the name of an entitys
|
||||
entity lastspawn;//last spawn point used by spawning code
|
||||
.entity goaldummy; //Used to store the origin of the zombies target
|
||||
.float goalway; //Used to store the origin of the zombies target
|
||||
.float walktype;//decides animations and moving speeds for zombies
|
||||
.void() th_walk;
|
||||
//.void() th_run;
|
||||
.void() th_die;
|
||||
.void() th_melee;
|
||||
.void() th_idle;
|
||||
.void() th_windowhop;
|
||||
.void() th_diewunder;
|
||||
|
||||
.void() th_fall;
|
||||
.void() th_falling;
|
||||
.void() th_land;
|
||||
|
||||
.void() th_jump;
|
||||
.void() th_grabledge;
|
||||
.float tries;
|
||||
.float hop_step;//KEEPS TRACK OF WHERE WE ARE ON THE HOPPING PART
|
||||
|
||||
float INACTIVE = 1;
|
||||
|
||||
float tracemove(vector start, vector min, vector max, vector end, float nomonsters, entity forent);
|
||||
|
||||
.float way_path[40];
|
||||
.float way_cur;
|
||||
|
||||
.float sound_time;
|
||||
.float s_time;
|
||||
float sounds_playing;
|
||||
|
||||
.float fall;
|
||||
//.vector lastOrg;//Zombie's last origin, for checking stuckness
|
||||
//.float OrgStuckCount;
|
||||
.float crawling;
|
||||
|
||||
.float washit;
|
||||
.float hitamount;
|
||||
|
||||
.float laststep;
|
||||
void(entity who) makeCrawler;
|
||||
.float state;//used to delay making a crawler, ex) when zombie is rising from ground or climbing over barrier, turn zombie into a crawler afterwards
|
||||
|
||||
void() spawnAllZombEnts;
|
||||
void() set_z_health;
|
||||
float() spawn_a_zombieA;
|
||||
float gotdog;
|
||||
float dogRound;
|
||||
float dogWave;
|
||||
float z_health;
|
||||
.float bleedingtime;
|
||||
.float time_to_die;
|
||||
|
||||
|
||||
float crandom();
|
||||
|
||||
|
||||
// Door
|
||||
.string killtarget;
|
||||
.void() think1;
|
||||
.vector finaldest;
|
||||
.vector pos1, pos2/*, mangle*/;
|
||||
.vector finalangle;
|
||||
.float distance;
|
||||
.float sequence;
|
||||
.entity active_door;
|
||||
.string door_model_target;
|
||||
.string door_model_name;
|
||||
|
||||
//Perk and Power system
|
||||
float isPowerOn;
|
||||
.float isBuying; // naievil -- used for checking if a perk is being consumed, limits glitching
|
||||
.float perks;
|
||||
.float perk_delay;
|
||||
.float revivesoda;
|
||||
.float collected;
|
||||
|
||||
.float boxstatus;
|
||||
.entity boxweapon;
|
||||
.float spins;
|
||||
.float papState;
|
||||
float BoxWeapons[25];
|
||||
entity boxLocations[32];
|
||||
float boxCount;
|
||||
vector boxOrigin;
|
||||
|
||||
#ifndef PSP
|
||||
//powerups
|
||||
.float x2_icon;
|
||||
.float insta_icon;
|
||||
#endif
|
||||
.string powerup_vo;
|
||||
float instakill_finished;
|
||||
float insta_blink;
|
||||
float x2_finished;
|
||||
float x2_blink;
|
||||
float total_windows_down;
|
||||
float total_powerup_points;
|
||||
float powerup_activate;
|
||||
float nuke_powerup_active;
|
||||
float nuke_powerups_activated;
|
||||
float nuke_powerup_spawndelay;
|
||||
|
||||
//rounds
|
||||
float roundinit;
|
||||
float roundtype;
|
||||
float Current_Zombies;
|
||||
float Total_Zombies;
|
||||
float Remaining_Zombies;
|
||||
float Delay_Time;
|
||||
float spawn_time;
|
||||
float round_changetime;
|
||||
float game_over;
|
||||
float blink_return;
|
||||
float delay_at_round;
|
||||
float spawn_delay;
|
||||
float maxreward;
|
||||
float totalreward;
|
||||
float totalpowerups;
|
||||
float sounds_playing;
|
||||
|
||||
float rounds;
|
||||
float rounds_change;
|
||||
|
||||
//Waypoints
|
||||
void () Waypoint_Logic;
|
||||
entity current_way;
|
||||
float waypoint_mode;
|
||||
entity active_way;
|
||||
|
||||
#define MAX_WAY_TARGETS 10
|
||||
.string waynum;
|
||||
.string targets[MAX_WAY_TARGETS];
|
||||
|
||||
|
||||
//pathfinds
|
||||
#define MAX_WAYPOINTS 256 //max waypoints
|
||||
void LoadWaypointData();
|
||||
typedef struct
|
||||
{
|
||||
vector org;
|
||||
float id;
|
||||
float g, f;
|
||||
float next, prev;
|
||||
float step;
|
||||
float target_id [MAX_WAY_TARGETS]; // Targets array number
|
||||
string targetdoor; //special tag is required for the closed waypoints
|
||||
float dist [MAX_WAY_TARGETS]; // Distance to the next waypoints
|
||||
float set;
|
||||
} waypoint_ai;
|
||||
|
||||
#define SET_NONE 0
|
||||
#define SET_OPEN 1
|
||||
#define SET_CLOSED 2
|
||||
|
||||
#ifdef PC
|
||||
waypoint_ai waypoints[MAX_WAYPOINTS];
|
||||
|
||||
// fog
|
||||
string world_fog;
|
||||
|
||||
// lights
|
||||
#define EF_PURPLELIGHT 256 // fte already has some effect styles defined...
|
||||
#endif
|
||||
|
||||
#define UT_HUD 1
|
||||
#define UT_ROUNDS_CHANGE 2
|
||||
#define UT_HM 3
|
||||
#define UT_ZOOM2 4
|
||||
#define UT_CROSSHAIR 5
|
||||
|
||||
//Misc patch definitions
|
||||
.string teddyremovetarget;
|
||||
|
||||
.float oldz; // used for fall damage that does not truly work correctly
|
||||
|
||||
.float sprint_delay;
|
||||
|
||||
//soft restart stuff for doors
|
||||
.string oldmodel;
|
||||
.vector oldorigin;
|
||||
.float oldstate;
|
||||
.float state;
|
||||
.float isopen;
|
||||
|
||||
//world
|
||||
.string chaptertitle;
|
||||
.string location;
|
||||
.string date;
|
||||
.string person;
|
||||
.string song;
|
||||
|
||||
//altered game elements
|
||||
float G_STARTPOINTS;
|
||||
float G_STARTROUND;
|
||||
float G_PRONEPOINTS;
|
||||
float G_STARTWEAPON[3];
|
||||
float G_WORLDTEXT;
|
||||
float G_PERKS;
|
||||
float G_PERKPOWER;
|
||||
|
||||
//song easter egg
|
||||
float sndTriggerCnt;
|
||||
float sndActivCnt;
|
||||
.float activated;
|
||||
|
||||
//teleporter
|
||||
.entity tele_target;
|
||||
.float mode;
|
||||
.float cooldown;
|
||||
.float isLinked;
|
||||
.float waitLink;
|
||||
.float tpTimer;
|
||||
.float isTimed;
|
||||
.entity host;
|
||||
|
||||
// GIBBING
|
||||
#ifdef PC
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
.entity head;
|
||||
.vector bbmins, bbmaxs;
|
||||
.float currentHitBoxSetup;
|
||||
#endif
|
||||
|
||||
// PC Fog force
|
||||
.float PC_fog;
|
||||
|
||||
// hl stuff
|
||||
#ifdef PC
|
||||
.float rendermode;
|
||||
.float renderamt;
|
||||
.vector rendercolor;
|
||||
#endif
|
1667
source/server/defs/fte.qc
Normal file
1667
source/server/defs/fte.qc
Normal file
File diff suppressed because it is too large
Load diff
666
source/server/defs/nx.qc
Normal file
666
source/server/defs/nx.qc
Normal file
|
@ -0,0 +1,666 @@
|
|||
/*
|
||||
defs.qc
|
||||
|
||||
global definitions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SOURCE FOR GLOBALVARS_T C STRUCTURE
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define NX
|
||||
|
||||
//
|
||||
// system globals
|
||||
//
|
||||
entity self;
|
||||
entity other;
|
||||
entity world;
|
||||
float time;
|
||||
float frametime;
|
||||
float force_retouch;
|
||||
string mapname;
|
||||
float deathmatch;
|
||||
float coop;
|
||||
float teamplay;
|
||||
float serverflags;
|
||||
float rounds;
|
||||
float rounds_change;
|
||||
float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
|
||||
vector v_forward, v_up, v_right;
|
||||
float trace_allsolid;
|
||||
float trace_startsolid;
|
||||
float trace_fraction;
|
||||
vector trace_endpos;
|
||||
vector trace_plane_normal;
|
||||
float trace_plane_dist;
|
||||
entity trace_ent;
|
||||
float trace_inopen;
|
||||
float trace_inwater;
|
||||
entity msg_entity; // destination of single entity writes
|
||||
void() main; // only for testing
|
||||
void() StartFrame;
|
||||
void() EndFrame;
|
||||
void() PlayerPreThink;
|
||||
void() PlayerPostThink;
|
||||
void() ClientKill;
|
||||
void() ClientConnect;
|
||||
void() PutClientInServer;
|
||||
void() ClientDisconnect;
|
||||
void() SetNewParms;
|
||||
void() SetChangeParms;
|
||||
void end_sys_globals;
|
||||
|
||||
|
||||
.float modelindex;
|
||||
.vector absmin, absmax;
|
||||
.float ltime;
|
||||
.float movetype;
|
||||
.float solid;
|
||||
.vector origin;
|
||||
.vector oldorigin;
|
||||
.vector velocity;
|
||||
.vector angles;
|
||||
.vector avelocity;
|
||||
.vector punchangle;
|
||||
.string classname;
|
||||
.string model;
|
||||
.float frame;
|
||||
.float skin;
|
||||
.float effects;
|
||||
.vector mins, maxs;
|
||||
.vector size;
|
||||
.void() touch;
|
||||
.void() use;
|
||||
.void() think;
|
||||
.void() blocked;
|
||||
.float nextthink;
|
||||
.entity groundentity;
|
||||
.float health;
|
||||
.float points;
|
||||
.float kills;
|
||||
.float weapon;
|
||||
.string weaponmodel;
|
||||
.string weapon2model;
|
||||
.float weaponframe;
|
||||
.float weapon2frame;
|
||||
.float currentammo;
|
||||
.float currentmag;
|
||||
.float zoom;
|
||||
.float weaponskin;
|
||||
.float weapon2skin;
|
||||
.float primary_grenades;
|
||||
.float secondary_grenades;
|
||||
.float grenades;
|
||||
.float perks;
|
||||
.float takedamage;
|
||||
.entity chain;
|
||||
.float deadflag;
|
||||
.vector view_ofs;
|
||||
.float button0;
|
||||
.float button1;
|
||||
.float button2;
|
||||
.float button3;
|
||||
.float button4;
|
||||
.float button5;
|
||||
.float button6;
|
||||
.float button7;
|
||||
.float button8;
|
||||
.float impulse;
|
||||
.float fixangle;
|
||||
.vector v_angle;
|
||||
.float idealpitch; // Naievil -- new
|
||||
.string netname;
|
||||
.entity enemy;
|
||||
.float flags;
|
||||
.float colormap;
|
||||
.float team;
|
||||
.float max_health;
|
||||
.float teleport_time;
|
||||
.float armortype;
|
||||
.float armorvalue;
|
||||
.float waterlevel;
|
||||
.float watertype;
|
||||
.float ideal_yaw;
|
||||
.float yaw_speed;
|
||||
.entity aiment;
|
||||
.entity head;
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
.entity goalentity;
|
||||
.float spawnflags;
|
||||
.string target;
|
||||
.string targetname;
|
||||
.float dmg_take;
|
||||
.float dmg_save;
|
||||
.float progress_bar;
|
||||
.entity dmg_inflictor;
|
||||
.entity owner;
|
||||
.vector movedir;
|
||||
.string message;
|
||||
.float sounds;
|
||||
.string noise, noise1, noise2, noise3;
|
||||
.float x2_icon;
|
||||
.float insta_icon;
|
||||
.string Weapon_Name_Touch;
|
||||
.vector ADS_Offset;
|
||||
.vector Flash_Offset;
|
||||
.float Flash_Size;
|
||||
.float currentmag2;
|
||||
.float maxspeed;
|
||||
.float renderGrayscale;
|
||||
void end_sys_fields;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
VARS NOT REFERENCED BY C CODE
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// constants
|
||||
//
|
||||
|
||||
float FALSE = 0;
|
||||
float TRUE = 1;
|
||||
|
||||
// edict.flags
|
||||
float FL_FLY = 1;
|
||||
float FL_SWIM = 2;
|
||||
float FL_CLIENT = 8; // set for all client edicts
|
||||
float FL_INWATER = 16; // for enter / leave water splash
|
||||
float FL_MONSTER = 32;
|
||||
float FL_GODMODE = 64; // player cheat
|
||||
float FL_NOTARGET = 128; // player cheat
|
||||
float FL_ITEM = 256; // extra wide size for bonus items
|
||||
float FL_ONGROUND = 512; // standing on something
|
||||
float FL_PARTIALGROUND = 1024; // not all corners are valid
|
||||
float FL_WATERJUMP = 2048; // player jumping out of water
|
||||
float FL_JUMPRELEASED = 4096; // for jump debouncing
|
||||
|
||||
// edict.movetype values
|
||||
float MOVETYPE_NONE = 0; // never moves
|
||||
//float MOVETYPE_ANGLENOCLIP = 1;
|
||||
//float MOVETYPE_ANGLECLIP = 2;
|
||||
float MOVETYPE_WALK = 3; // players only
|
||||
float MOVETYPE_STEP = 4; // discrete, not real time unless fall
|
||||
float MOVETYPE_FLY = 5;
|
||||
float MOVETYPE_TOSS = 6; // gravity
|
||||
float MOVETYPE_PUSH = 7; // no clip to world, push and crush
|
||||
float MOVETYPE_NOCLIP = 8;
|
||||
float MOVETYPE_FLYMISSILE = 9; // fly with extra size against monsters
|
||||
float MOVETYPE_BOUNCE = 10;
|
||||
float MOVETYPE_BOUNCEMISSILE = 11; // bounce with extra size
|
||||
|
||||
// edict.solid values
|
||||
float SOLID_NOT = 0; // no interaction with other objects
|
||||
float SOLID_TRIGGER = 1; // touch on edge, but not blocking
|
||||
float SOLID_BBOX = 2; // touch on edge, block
|
||||
float SOLID_SLIDEBOX = 3; // touch on edge, but not an onground
|
||||
float SOLID_BSP = 4; // bsp clip, touch on edge, block
|
||||
|
||||
float DEAD_NO = 0;
|
||||
float DEAD_DYING = 1;
|
||||
float DEAD_DEAD = 2;
|
||||
float DEAD_RESPAWNABLE = 3;
|
||||
|
||||
// takedamage values
|
||||
float DAMAGE_NO = 0;
|
||||
float DAMAGE_YES = 1;
|
||||
float DAMAGE_AIM = 2;
|
||||
|
||||
// point content values
|
||||
float CONTENT_EMPTY = -1;
|
||||
float CONTENT_SOLID = -2;
|
||||
float CONTENT_WATER = -3;
|
||||
float CONTENT_SLIME = -4;
|
||||
float CONTENT_LAVA = -5;
|
||||
float CONTENT_SKY = -6;
|
||||
|
||||
float STATE_TOP = 0;
|
||||
float STATE_BOTTOM = 1;
|
||||
float STATE_UP = 2;
|
||||
float STATE_DOWN = 3;
|
||||
|
||||
vector VEC_ORIGIN = '0 0 0';
|
||||
|
||||
// protocol bytes
|
||||
float SVC_TEMPENTITY = 23;
|
||||
float SVC_KILLEDMONSTER = 27;
|
||||
float SVC_FOUNDSECRET = 28;
|
||||
float SVC_INTERMISSION = 30;
|
||||
float SVC_FINALE = 31;
|
||||
float SVC_CDTRACK = 32;
|
||||
float SVC_SELLSCREEN = 33;
|
||||
float SVC_SMALLKICK = 34;
|
||||
float SVC_BIGKICK = 35;
|
||||
float SVC_MUZZLEFLASH = 39;
|
||||
|
||||
// sound channels
|
||||
// channel 0 never willingly overrides
|
||||
// other channels (1-7) allways override a playing sound on that channel
|
||||
float CHAN_AUTO = 0;
|
||||
float CHAN_WEAPON = 1;
|
||||
float CHAN_VOICE = 2;
|
||||
float CHAN_ITEM = 3;
|
||||
float CHAN_BODY = 4;
|
||||
float CHAN_NO_PHS_ADD = 8; // ie: CHAN_BODY+CHAN_NO_PHS_ADD
|
||||
|
||||
float ATTN_NONE = 0;
|
||||
float ATTN_NORM = 1;
|
||||
float ATTN_IDLE = 2;
|
||||
float ATTN_STATIC = 3;
|
||||
|
||||
// entity effects
|
||||
#define EF_BLUE 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_RED 8
|
||||
#define EF_ORANGELIGHT 16
|
||||
#define EF_GREEN 32
|
||||
#define EF_LIGHT 64
|
||||
#define EF_NODRAW 128
|
||||
#define EF_BRIGHTFIELD 256
|
||||
#define EF_FULLBRIGHT 512
|
||||
#define EF_DARKLIGHT 1024
|
||||
#define EF_DARKFIELD 2048
|
||||
#define EF_PURPLELIGHT 4096
|
||||
#define EF_RAYRED 8196
|
||||
#define EF_RAYGREEN 16384
|
||||
|
||||
// messages
|
||||
float MSG_BROADCAST = 0; // unreliable to all
|
||||
float MSG_ONE = 1; // reliable to one (msg_entity)
|
||||
float MSG_ALL = 2; // reliable to all
|
||||
float MSG_INIT = 3; // write to the init string
|
||||
float MSG_MULTICAST = 4; // for multicast() call
|
||||
|
||||
// message levels
|
||||
float PRINT_LOW = 0; // pickup messages
|
||||
float PRINT_MEDIUM = 1; // death messages
|
||||
float PRINT_HIGH = 2; // critical messages
|
||||
float PRINT_CHAT = 3; // also goes to chat console
|
||||
|
||||
// multicast sets
|
||||
float MULTICAST_ALL = 0; // every client
|
||||
float MULTICAST_PHS = 1; // within hearing
|
||||
float MULTICAST_PVS = 2; // within sight
|
||||
float MULTICAST_ALL_R = 3; // every client, reliable
|
||||
float MULTICAST_PHS_R = 4; // within hearing, reliable
|
||||
float MULTICAST_PVS_R = 5; // within sight, reliable
|
||||
|
||||
|
||||
|
||||
|
||||
//================================================
|
||||
|
||||
//
|
||||
// globals
|
||||
//
|
||||
string string_null; // null string, nothing should be held here
|
||||
entity activator; // the entity that activated a trigger or brush
|
||||
float framecount;
|
||||
|
||||
//
|
||||
// cvars checked each frame
|
||||
//
|
||||
float teamplay;
|
||||
float deathmatch;
|
||||
|
||||
//================================================
|
||||
|
||||
//
|
||||
// world fields (FIXME: make globals)
|
||||
//
|
||||
.string wad;
|
||||
.string map;
|
||||
.float worldtype; // 0=medieval 1=metal 2=base
|
||||
|
||||
//================================================
|
||||
|
||||
.string killtarget;
|
||||
|
||||
//
|
||||
// quakeed fields
|
||||
//
|
||||
.float light_lev; // not used by game, but parsed by light util
|
||||
.float style;
|
||||
|
||||
|
||||
//
|
||||
// monster ai
|
||||
//
|
||||
.void() th_stand;
|
||||
.void() th_walk;
|
||||
.void() th_run;
|
||||
.void() th_missile;
|
||||
.void() th_melee;
|
||||
.void(entity attacker, float damage) th_pain;
|
||||
.void() th_die;
|
||||
|
||||
.entity oldenemy; // mad at this player before taking damage
|
||||
|
||||
.float speed;
|
||||
|
||||
.float lefty;
|
||||
|
||||
.float search_time;
|
||||
.float attack_state;
|
||||
|
||||
float AS_STRAIGHT = 1;
|
||||
float AS_SLIDING = 2;
|
||||
float AS_MELEE = 3;
|
||||
float AS_MISSILE = 4;
|
||||
|
||||
//
|
||||
// player only fields
|
||||
//
|
||||
.float voided;
|
||||
.float walkframe;
|
||||
|
||||
// Zoid Additions
|
||||
.float gravity; // Gravity Multiplier (0 to 1.0)
|
||||
|
||||
|
||||
|
||||
.float attack_finished;
|
||||
.float pain_finished;
|
||||
|
||||
.float invincible_finished;
|
||||
.float invisible_finished;
|
||||
.float super_damage_finished;
|
||||
.float radsuit_finished;
|
||||
|
||||
.float invincible_time, invincible_sound;
|
||||
.float invisible_time, invisible_sound;
|
||||
.float super_time, super_sound;
|
||||
.float rad_time;
|
||||
.float fly_sound;
|
||||
|
||||
.float axhitme;
|
||||
|
||||
.float show_hostile; // set to time+0.2 whenever a client fires a
|
||||
// weapon or takes damage. Used to alert
|
||||
// monsters that otherwise would let the player go
|
||||
.float jump_flag; // player jump flag
|
||||
.float swim_flag; // player swimming sound flag
|
||||
.float air_finished; // when time > air_finished, start drowning
|
||||
.float bubble_count; // keeps track of the number of bubbles
|
||||
.string deathtype; // keeps track of how the player died
|
||||
|
||||
//
|
||||
// object stuff
|
||||
//
|
||||
.string mdl;
|
||||
.vector mangle; // angle at start
|
||||
|
||||
.vector oldorigin; // only used by secret door
|
||||
|
||||
.float t_length, t_width;
|
||||
|
||||
|
||||
//
|
||||
// doors, etc
|
||||
//
|
||||
.vector dest, dest1, dest2;
|
||||
.float wait; // time from firing to restarting
|
||||
.float delay; // time from activation to firing
|
||||
.entity trigger_field; // door's trigger entity
|
||||
.string noise4;
|
||||
|
||||
//
|
||||
// monsters
|
||||
//
|
||||
.float pausetime;
|
||||
.entity movetarget;
|
||||
|
||||
|
||||
//
|
||||
// doors
|
||||
//
|
||||
.float aflag;
|
||||
.float dmg; // damage done by door when hit
|
||||
|
||||
//
|
||||
// misc
|
||||
//
|
||||
.float cnt; // misc flag
|
||||
|
||||
//
|
||||
// subs
|
||||
//
|
||||
.void() think1;
|
||||
.vector finaldest, finalangle;
|
||||
|
||||
//
|
||||
// triggers
|
||||
//
|
||||
.float count; // for counting triggers
|
||||
|
||||
|
||||
//
|
||||
// plats / doors / buttons
|
||||
//
|
||||
.float lip;
|
||||
.float state;
|
||||
.vector pos1, pos2; // top and bottom positions
|
||||
.float height;
|
||||
|
||||
//
|
||||
// sounds
|
||||
//
|
||||
.float waitmin, waitmax;
|
||||
.float distance;
|
||||
.float volume;
|
||||
|
||||
.float sprintflag;
|
||||
|
||||
//
|
||||
// builtin functions
|
||||
//
|
||||
|
||||
void(vector ang) makevectors = #1; // sets v_forward, etc globals
|
||||
void(entity e, vector o) setorigin = #2;
|
||||
void(entity e, string m) setmodel = #3; // set movetype and solid first
|
||||
void(entity e, vector min, vector max) setsize = #4;
|
||||
|
||||
void() break = #6;
|
||||
float() random = #7; // returns 0 - 1
|
||||
void(entity e, float chan, string samp, float vol, float atten) sound = #8;
|
||||
vector(vector v) normalize = #9;
|
||||
void(string e) error = #10;
|
||||
void(string e) objerror = #11;
|
||||
float(vector v) vlen = #12;
|
||||
float(vector v) vectoyaw = #13;
|
||||
entity() spawn = #14;
|
||||
void(entity e) remove = #15;
|
||||
void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
|
||||
entity() checkclient = #17; // returns a client to look for
|
||||
entity(entity start, .string fld, string match) find = #18;
|
||||
string(string s) precache_sound = #19;
|
||||
string(string s) precache_model = #20;
|
||||
void(entity client, string s)stuffcmd = #21;
|
||||
entity(vector org, float rad) findradius = #22;
|
||||
void(float level, string s) bprint = #23;
|
||||
void(entity client, float level, string s) sprint = #24;
|
||||
void(string s) dprint = #25;
|
||||
string(float f) ftos = #26;
|
||||
string(vector v) vtos = #27;
|
||||
void() coredump = #28; // prints all edicts
|
||||
void() traceon = #29; // turns statment trace on
|
||||
void() traceoff = #30;
|
||||
void(entity e) eprint = #31; // prints an entire edict
|
||||
float(float yaw, float dist) walkmove = #32; // returns TRUE or FALSE
|
||||
float(entity zombie, float which, entity limb) updateLimb = #33;
|
||||
float(float yaw, float dist) droptofloor = #34; // TRUE if landed on floor
|
||||
void(float style, string value) lightstyle = #35;
|
||||
float(float v) rint = #36; // round to nearest int
|
||||
float(float v) floor = #37; // largest integer <= v
|
||||
float(float v) ceil = #38; // smallest integer >= v
|
||||
float(entity e) checkbottom = #40; // true if self is on ground
|
||||
float(vector v) pointcontents = #41; // returns a CONTENT_*
|
||||
float(float f) fabs = #43;
|
||||
vector(entity e, float speed) aim = #44; // returns the shooting vector
|
||||
float(string s) cvar = #45; // return cvar.value
|
||||
void(string s) localcmd = #46; // put string into local que
|
||||
entity(entity e) nextent = #47; // for looping through all ents
|
||||
void() ChangeYaw = #49; // turn towards self.ideal_yaw
|
||||
vector(vector v) vectoangles = #51;
|
||||
void(float to, float f) WriteByte = #52;
|
||||
void(float to, float f) WriteChar = #53;
|
||||
void(float to, float f) WriteShort = #54;
|
||||
void(float to, float f) WriteLong = #55;
|
||||
void(float to, float f) WriteCoord = #56;
|
||||
void(float to, float f) WriteAngle = #57;
|
||||
void(float to, string s) WriteString = #58;
|
||||
void(float to, entity s) WriteEntity = #59;
|
||||
void(float step) movetogoal = #67;
|
||||
string(string s) precache_file = #68; // no effect except for -copy
|
||||
void(entity e) makestatic = #69;
|
||||
void(string s) changelevel = #70;
|
||||
void(string var, string val) cvar_set = #72; // sets cvar.value
|
||||
void(entity client, string s) centerprint = #73; // sprint, but in middle
|
||||
void(vector pos, string samp, float vol, float atten) ambientsound = #74;
|
||||
string(string s) precache_model2 = #75; // registered version only
|
||||
string(string s) precache_sound2 = #76; // registered version only
|
||||
string(string s) precache_file2 = #77; // registered version only
|
||||
void(entity e) setspawnparms = #78; // set parm1... to the
|
||||
void(entity killer, entity killee) logfrag = #79; // add to stats
|
||||
string(entity e, string key) infokey = #80; // get a key value (world = serverinfo)
|
||||
float(string s) stof = #81; // convert string to float
|
||||
void(vector where, float set) multicast = #82;
|
||||
vector(entity what) Get_Waypoint_Near = #83;
|
||||
float(entity zombie, entity target) Do_Pathfind_psp = #84;
|
||||
void(string s) Open_Waypoint = #85;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_Next_Waypoint = #86;
|
||||
void(entity client, float type, float cost, float weapon) useprint = #87;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_First_Waypoint = #88;
|
||||
entity (entity start, .float field, float match) findfloat = #98;
|
||||
|
||||
// New NZP custom ones
|
||||
float(string filename, float mode) fopen = #110;
|
||||
void(float fhandle) fclose = #111;
|
||||
string(float fhandle) fgets = #112;
|
||||
void(float fhandle, string s) fputs = #113;
|
||||
float(string s) strlen = #114;
|
||||
string(string s1, string s2) strcat = #115;
|
||||
string(string s, float start, float length) substring = #116;
|
||||
vector(string s) stov = #117;
|
||||
string(string s) strzone = #118;
|
||||
string(string s) strunzone = #119;
|
||||
string(string s) strtrim = #120;
|
||||
float(string s) tokenize = #130; // Was #441
|
||||
string(float num) argv = #131; // Was #442
|
||||
|
||||
float(entity targ, entity inflictor) CanDamage;
|
||||
|
||||
|
||||
#define FILE_READ 0
|
||||
#define FILE_APPEND 1
|
||||
#define FILE_WRITE 2
|
||||
#define SVC_WEAPONFIRE 35
|
||||
#define SVC_HITMARK 36
|
||||
#define SVC_LIMBUPDATE 51 // naievil -- keep me
|
||||
#define SVC_BSPDECAL 50 // naievil -- keep me
|
||||
#define SVC_ACHIEVEMENT 52
|
||||
|
||||
#define VEC_ORIGIN '0 0 0'
|
||||
|
||||
//Standard Quake View Offset
|
||||
//vector VEC_VIEW_OFS = '0 0 22';
|
||||
|
||||
//Half Life View Offset is 64
|
||||
//64 units above ground, for our purposes it's, 64 - (how low bounding box goes)
|
||||
vector VEC_VIEW_OFS = '0 0 32';
|
||||
|
||||
//Standard Quake Hull
|
||||
//vector VEC_HULL_MIN = '-16 -16 -24';
|
||||
//vector VEC_HULL_MAX = '16 16 32';
|
||||
|
||||
//Half Life 1 Hull Sizes ADDED BY BLUBS, COMMENTED ORIGINAL QUAKE BBOX SIZS OUT
|
||||
#define VEC_HULL_MIN '-16 -16 -32'
|
||||
#define VEC_HULL_MAX '16 16 40'
|
||||
|
||||
#define VEC_HULL2_MIN '-32 -32 -24'
|
||||
#define VEC_HULL2_MAX '32 32 64'
|
||||
|
||||
.string fog;
|
||||
//string world_fog;
|
||||
|
||||
.float button3;
|
||||
.float button4;
|
||||
.float button5;
|
||||
.float button6;
|
||||
.float button7;
|
||||
.float button8;
|
||||
|
||||
.float x2_icon; // double points icon
|
||||
.float insta_icon;
|
||||
.vector Flash_Offset;
|
||||
.float Flash_Size;
|
||||
.string Weapon_Name;
|
||||
|
||||
.float currentHitBoxSetup;
|
||||
.vector bbmins, bbmaxs; // Used for zombie hitboxes
|
||||
|
||||
.entity head;
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
|
||||
#define SOLID_CORPSE 5 // bsp clip, touch on edge, block
|
||||
#define TE_EXPLOSION 3
|
||||
#define TE_GUNSHOT 2
|
||||
entity windows[32];
|
||||
float wincnt;
|
||||
|
||||
.float recoil_delay;
|
||||
|
||||
float pow(float base, float n) = {
|
||||
float temp = base;
|
||||
if (n == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
while (n > 0) {
|
||||
temp = temp * base;
|
||||
n = n - 1;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
void enableGrayscale(void) = {
|
||||
self.renderGrayscale = 1;
|
||||
}
|
||||
|
||||
void disableGrayscale(void) = {
|
||||
self.renderGrayscale = 0;
|
||||
}
|
541
source/server/defs/psp.qc
Normal file
541
source/server/defs/psp.qc
Normal file
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
+----+
|
||||
|Defs|
|
||||
+----+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
|
||||
| Scratch Http://www.admdev.com/scratch |
|
||||
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
|
||||
| This contains necessary definitions from the original V1.06 defs.qc file. |
|
||||
| This includes some basic constants, the built in function definitions, and |
|
||||
| some variable's used by the Quake Engine internally. |
|
||||
| Certain lines in this file are hardcoded into Quake engine, and -must- be |
|
||||
| present and unchanged, in the order they are shown. Otherwise Quake will |
|
||||
| refuse to run. |
|
||||
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
|
||||
*/
|
||||
|
||||
#define PSP
|
||||
|
||||
// These lines CANNOT be altered/moved
|
||||
entity self;
|
||||
entity other;
|
||||
entity world;
|
||||
float time;
|
||||
float frametime;
|
||||
float force_retouch; // force all entities to touch triggers
|
||||
string mapname;
|
||||
float deathmatch;
|
||||
float coop;
|
||||
float teamplay;
|
||||
float serverflags; // propagated from level to level, used to
|
||||
float rounds;
|
||||
float rounds_change;
|
||||
float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
|
||||
vector v_forward, v_up, v_right; // set by makevectors()
|
||||
float trace_allsolid;
|
||||
float trace_startsolid;
|
||||
float trace_fraction;
|
||||
vector trace_endpos;
|
||||
vector trace_plane_normal;
|
||||
float trace_plane_dist;
|
||||
entity trace_ent;
|
||||
float trace_inopen;
|
||||
float trace_inwater;
|
||||
|
||||
entity msg_entity; // destination of single entity writes
|
||||
void() main; // only for testing
|
||||
void() StartFrame;
|
||||
void() EndFrame;
|
||||
void() PlayerPreThink;
|
||||
void() PlayerPostThink;
|
||||
void() ClientKill;
|
||||
void() ClientConnect;
|
||||
void() PutClientInServer; // call after setting the parm1... parms
|
||||
void() ClientDisconnect;
|
||||
void() SetNewParms; // called when a client first connects to
|
||||
void() SetChangeParms; // call to set parms for self so they can
|
||||
void() ParseClientCommand; // special command calls
|
||||
string CMD_STRING;
|
||||
void() Soft_Restart;
|
||||
void end_sys_globals; // flag for structure dumping
|
||||
|
||||
.float modelindex; // *** model index in the precached list
|
||||
.vector absmin, absmax; // *** origin + mins / maxs
|
||||
.float ltime; // local time for entity
|
||||
.float movetype;
|
||||
.float solid;
|
||||
.vector origin; // ***
|
||||
.vector oldorigin; // ***
|
||||
.vector velocity;
|
||||
.vector angles;
|
||||
.vector avelocity;
|
||||
.vector punchangle; // temp angle adjust from damage or recoil
|
||||
.string classname; // spawn function
|
||||
.string model;
|
||||
.float frame;
|
||||
.float skin;
|
||||
.float iframetime;
|
||||
.float effects;
|
||||
.vector mins, maxs; // bounding box extents reletive to origin
|
||||
.vector size; // maxs - mins
|
||||
.void() touch;
|
||||
.void() use;
|
||||
.void() think;
|
||||
.void() blocked; // for doors or plats, called when can't push other
|
||||
.float nextthink;
|
||||
.entity groundentity;
|
||||
.float health;
|
||||
.float points;
|
||||
.float kills;
|
||||
.float weapon; // one of the W_COLT, etc flags
|
||||
.string weaponmodel;
|
||||
.string weapon2model;
|
||||
.float weaponframe;
|
||||
.float weapon2frame;
|
||||
.float currentammo;
|
||||
.float currentmag;
|
||||
.float zoom;
|
||||
.float weaponskin;
|
||||
.float weapon2skin;
|
||||
.float primary_grenades;
|
||||
.float secondary_grenades;
|
||||
.float grenades;
|
||||
.float perks; // bit flags
|
||||
.float takedamage;
|
||||
.entity chain;
|
||||
.float deadflag;
|
||||
.vector view_ofs; // add to origin to get eye point
|
||||
.float button0; //
|
||||
.float button1; //
|
||||
.float button2; //
|
||||
.float button3; //
|
||||
.float button4; //
|
||||
.float button5; //
|
||||
.float button6; //
|
||||
.float button7; //
|
||||
.float button8; //
|
||||
.float impulse; // weapon changes
|
||||
.float fixangle;
|
||||
.vector v_angle; // view / targeting angle for players
|
||||
.float idealpitch; // calculated pitch angle for lookup up slopes
|
||||
.string netname;
|
||||
.entity enemy;
|
||||
.float flags;
|
||||
.float colormap;
|
||||
.float team;
|
||||
.float max_health; // players maximum health is stored here
|
||||
.float teleport_time; // don't back up
|
||||
.float waterlevel; // 0 = not in, 1 = feet, 2 = wast, 3 = eyes
|
||||
.float watertype; // a contents value
|
||||
.float ideal_yaw;
|
||||
.float yaw_speed;
|
||||
.entity aiment;
|
||||
.entity head;
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
.entity goalentity; // a movetarget or an enemy
|
||||
//.entity goalorigin; // a movetarget location
|
||||
.float spawnflags;
|
||||
.string target;
|
||||
.string targetname;
|
||||
.float bleed_out;
|
||||
.float progress_bar;
|
||||
.entity dmg_inflictor;
|
||||
.entity owner; // who launched a missile
|
||||
.vector movedir; // mostly for doors, but also used for waterjump
|
||||
.string message; // trigger messages
|
||||
.float sounds; // either a cd track number or sound number
|
||||
.string noise, noise1, noise2, noise3; // contains names of wavs to play
|
||||
.float x2_icon; // double points icon
|
||||
.float insta_icon;
|
||||
.vector ADS_Offset;
|
||||
.vector Flash_Offset;
|
||||
.float Flash_Size;
|
||||
.string Weapon_Name;
|
||||
.string Weapon_Name_Touch;
|
||||
.float currentmag2;
|
||||
.float maxspeed;
|
||||
.float facingenemy;
|
||||
void end_sys_fields; // flag for structure dumping
|
||||
// End. Lines below this MAY be altered, to some extent
|
||||
|
||||
// Built In functions
|
||||
void(vector ang) makevectors = #1; // sets v_forward, etc globals
|
||||
void(entity e, vector o) setorigin = #2;
|
||||
void(entity e, string m) setmodel = #3; // set movetype and solid first
|
||||
void(entity e, vector min, vector max) setsize = #4;
|
||||
void() break = #6;
|
||||
float() random = #7; // returns 0 - 1
|
||||
void(entity e, float chan, string samp, float vol, float atten) sound = #8;
|
||||
vector(vector v) normalize = #9;
|
||||
void(string e) error = #10;
|
||||
void(string e) objerror = #11;
|
||||
float(vector v) vlen = #12;
|
||||
float(vector v) vectoyaw = #13;
|
||||
entity() spawn = #14;
|
||||
void(entity e) remove = #15;
|
||||
void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
|
||||
entity() checkclient = #17; // returns a client to look for
|
||||
entity(entity start, .string fld, string match) find = #18;
|
||||
string(string s) precache_sound = #19;
|
||||
string(string s) precache_model = #20;
|
||||
void(entity client, string s)stuffcmd = #21;
|
||||
entity(vector org, float rad) findradius = #22;
|
||||
void(string s) dprint = #25;
|
||||
string(float f) ftos = #26;
|
||||
string(vector v) vtos = #27;
|
||||
void() coredump = #28; // prints all edicts
|
||||
void() traceon = #29; // turns statment trace on
|
||||
void() traceoff = #30;
|
||||
void(entity e) eprint = #31; // prints an entire edict
|
||||
float(float yaw, float dist) walkmove = #32; // returns TRUE or FALSE
|
||||
float(entity zombie, float which, entity limb) updateLimb = #33;
|
||||
float(float yaw, float dist) droptofloor = #34; // TRUE if landed on floor
|
||||
void(float style, string value) lightstyle = #35;
|
||||
float(float v) rint = #36; // round to nearest int
|
||||
float(float v) floor = #37; // largest integer <= v
|
||||
float(float v) ceil = #38; // smallest integer >= v
|
||||
float(entity e) checkbottom = #40; // true if self is on ground
|
||||
float(vector v) pointcontents = #41; // returns a CONTENT_*
|
||||
float(float f) fabs = #43;
|
||||
vector(entity e, float speed) aim = #44; // returns the shooting vector
|
||||
float(string s) cvar = #45; // return cvar.value
|
||||
void(string s) localcmd = #46; // put string into local que
|
||||
entity(entity e) nextent = #47; // for looping through all ents
|
||||
void() ChangeYaw = #49; // turn towards self.ideal_yaw
|
||||
float(string name) getSoundLen = #50;
|
||||
vector(vector v) vectoangles = #51;
|
||||
void(float to, float f) WriteByte = #52;
|
||||
void(float to, float f) WriteChar = #53;
|
||||
void(float to, float f) WriteShort = #54;
|
||||
void(float to, float f) WriteLong = #55;
|
||||
void(float to, float f) WriteCoord = #56;
|
||||
void(float to, float f) WriteAngle = #57;
|
||||
void(float to, string s) WriteString = #58;
|
||||
void(float to, entity s) WriteEntity = #59;
|
||||
string(entity s) etos = #65;
|
||||
void(float step) movetogoal = #67;
|
||||
string(string s) precache_file = #68; // no effect except for -copy
|
||||
void(entity e) makestatic = #69;
|
||||
void(string s) changelevel = #70;
|
||||
void(float step, vector origin) movetoorigin = #71;
|
||||
void(string var, string val) cvar_set = #72; // sets cvar.value
|
||||
void(entity client, string s) centerprint = #73; // sprint, but in middle
|
||||
void(entity client, string s, string s) centerprint2 = #73;
|
||||
void(entity client, string s, string s, string s) centerprint3 = #73;
|
||||
void(entity client, string s, string s, string s, string s) centerprint4 = #73;
|
||||
void(entity client, string s, string s, string s, string s, string s) centerprint5 = #73;
|
||||
void(entity client, string s, string s, string s, string s, string s, string s) centerprint6 = #73;
|
||||
void(entity client, string s, string s, string s, string s, string s, string s, string s) centerprint7 = #73;
|
||||
void(vector pos, string samp, float vol, float atten) ambientsound = #74;
|
||||
string(string s) precache_model2 = #75; // registered version only
|
||||
string(string s) precache_sound2 = #76; // registered version only
|
||||
string(string s) precache_file2 = #77; // registered version only
|
||||
void(entity e) setspawnparms = #78; // set parm1... to the
|
||||
void(vector start, vector min, vector max, vector end, float nomonsters, entity forent) tracebox = #90;
|
||||
float(vector start, vector min, vector max, vector end, float nomonsters, entity forent) tracemove = #99;
|
||||
entity (entity start, .float field, float match) findfloat = #98;
|
||||
float(string s) stof = #81; // 2001-09-20 QuakeC string manipulation by FrikaC
|
||||
vector(entity what) Get_Waypoint_Near = #83;
|
||||
float(entity zombie, entity target) Do_Pathfind_psp = #84;
|
||||
void(string s) Open_Waypoint = #85;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_Next_Waypoint = #86;
|
||||
void(entity client, float type, float cost, float weapon) useprint = #87;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_First_Waypoint = #88;
|
||||
void(string s) Close_Waypoint = #89;
|
||||
|
||||
void(entity plr, float achievement) achievement = #79;
|
||||
|
||||
void(string trackname) songegg = #500;
|
||||
void() nzp_maxammo = #501;
|
||||
/*
|
||||
type 0 = clear
|
||||
type 1 = buy door
|
||||
type 2 = buy debris
|
||||
type 3 = Buy ammo
|
||||
type 4 = buy weapon
|
||||
type 5 = repair window
|
||||
type 6 = use box
|
||||
type 7 = use trap
|
||||
type 8 = require power
|
||||
*/
|
||||
|
||||
|
||||
// 2001-09-20 QuakeC file access by FrikaC start
|
||||
float(string filename, float mode) fopen = #110;
|
||||
void(float fhandle) fclose = #111;
|
||||
string(float fhandle) fgets = #112;
|
||||
void(float fhandle, string s) fputs = #113;
|
||||
// 2001-09-20 QuakeC file access by FrikaC end
|
||||
|
||||
// 2001-09-20 QuakeC string manipulation by FrikaC start
|
||||
float(string s) strlen = #114;
|
||||
string(string s1, string s2) strcat = #115;
|
||||
string(string s, float start, float length) substring = #116;
|
||||
vector(string s) stov = #117;
|
||||
string(string s) strzone = #118;
|
||||
string(string s) strunzone = #119;
|
||||
string(string s) strtrim = #120;
|
||||
// 2001-09-20 QuakeC string manipulation by FrikaC end
|
||||
|
||||
// 2001-11-15 DarkPlaces general builtin functions by Lord Havoc start
|
||||
float(string s) tokenize = #441;
|
||||
string(float num) argv = #442;
|
||||
// 2001-11-15 DarkPlaces general builtin functions by Lord Havoc end
|
||||
|
||||
//
|
||||
// constants
|
||||
//
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
// edict.flags
|
||||
#define FL_FLY 1
|
||||
#define FL_SWIM 2
|
||||
#define FL_CLIENT 8 // set for all client edicts
|
||||
#define FL_INWATER 16 // for enter / leave water splash
|
||||
#define FL_MONSTER 32
|
||||
#define FL_GODMODE 64 // player cheat
|
||||
#define FL_NOTARGET 128 // player cheat
|
||||
#define FL_ITEM 256 // extra wide size for bonus items
|
||||
#define FL_ONGROUND 512 // standing on something
|
||||
#define FL_PARTIALGROUND 1024 // not all corners are valid
|
||||
#define FL_WATERJUMP 2048 // player jumping out of water
|
||||
//#define FL_JUMPRELEASED 4096 // for jump debouncing
|
||||
|
||||
// edict.movetype values
|
||||
#define MOVETYPE_NONE 0 // never moves
|
||||
#define MOVETYPE_ANGLENOCLIP 1
|
||||
#define MOVETYPE_ANGLECLIP 2
|
||||
#define MOVETYPE_WALK 3 // players only
|
||||
#define MOVETYPE_STEP 4 // discrete, not real time unless fall
|
||||
#define MOVETYPE_FLY 5
|
||||
#define MOVETYPE_TOSS 6 // gravity
|
||||
#define MOVETYPE_PUSH 7 // no clip to world, push and crush
|
||||
#define MOVETYPE_NOCLIP 8
|
||||
#define MOVETYPE_FLYMISSILE 9 // fly with extra size against monsters
|
||||
#define MOVETYPE_BOUNCE 10
|
||||
#define MOVETYPE_BOUNCEMISSILE 11 // bounce with extra size
|
||||
#define MOVETYPE_FOLLOW 12
|
||||
|
||||
// edict.solid values
|
||||
#define SOLID_NOT 0 // no interaction with other objects
|
||||
#define SOLID_TRIGGER 1 // touch on edge, but not blocking
|
||||
#define SOLID_BBOX 2 // touch on edge, block
|
||||
#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
|
||||
#define SOLID_BSP 4 // bsp clip, touch on edge, block
|
||||
#define SOLID_CORPSE 5 // bsp clip, touch on edge, block
|
||||
|
||||
// range values
|
||||
#define RANGE_MELEE 0
|
||||
#define RANGE_NEAR 1
|
||||
#define RANGE_MID 2
|
||||
#define RANGE_FAR 3
|
||||
|
||||
// deadflag values
|
||||
|
||||
#define DEAD_NO 0
|
||||
#define DEAD_DYING 1
|
||||
#define DEAD_DEAD 2
|
||||
#define DEAD_RESPAWNABLE 3
|
||||
|
||||
// takedamage values
|
||||
|
||||
#define DAMAGE_NO 0
|
||||
#define DAMAGE_YES 1
|
||||
#define DAMAGE_AIM 2
|
||||
#define DAMAGE_NOMARKER 3
|
||||
|
||||
/*.void() th_stand;
|
||||
.void() th_walk;
|
||||
.void() th_run;
|
||||
.void(entity attacker, float damage) th_pain;*/
|
||||
.void() th_die;
|
||||
//.void() th_missile;
|
||||
.void() th_melee;
|
||||
|
||||
// point content values
|
||||
|
||||
#define CONTENT_EMPTY -1
|
||||
#define CONTENT_SOLID -2
|
||||
#define CONTENT_WATER -3
|
||||
#define CONTENT_SLIME -4
|
||||
#define CONTENT_LAVA -5
|
||||
#define CONTENT_SKY -6
|
||||
|
||||
|
||||
#define VEC_ORIGIN '0 0 0'
|
||||
|
||||
//Standard Quake View Offset
|
||||
//vector VEC_VIEW_OFS = '0 0 22';
|
||||
|
||||
//Half Life View Offset is 64
|
||||
//64 units above ground, for our purposes it's, 64 - (how low bounding box goes)
|
||||
//vector VEC_VIEW_OFS = '0 0 32';
|
||||
|
||||
//Standard Quake Hull
|
||||
//vector VEC_HULL_MIN = '-16 -16 -24';
|
||||
//vector VEC_HULL_MAX = '16 16 32';
|
||||
|
||||
//Half Life 1 Hull Sizes ADDED BY BLUBS, COMMENTED ORIGINAL QUAKE BBOX SIZS OUT
|
||||
#define VEC_HULL_MIN '-16 -16 -32'
|
||||
#define VEC_HULL_MAX '16 16 40'
|
||||
|
||||
#define VEC_HULL2_MIN '-32 -32 -24'
|
||||
#define VEC_HULL2_MAX '32 32 64'
|
||||
|
||||
// protocol bytes
|
||||
#define SVC_BAD 0
|
||||
#define SVC_NOP 1
|
||||
#define SVC_DISCONNECT 2
|
||||
#define SVC_UPDATESTAT 3
|
||||
#define SVC_VERSION 4
|
||||
#define SVC_SETVIEW 5
|
||||
#define SVC_SOUND 6
|
||||
#define SVC_TIME 7
|
||||
#define SVC_PRINT 8
|
||||
#define SVC_STUFFTEXT 9
|
||||
#define SVC_SETANGLE 10
|
||||
#define SVC_SERVERINFO 11
|
||||
#define SVC_LIGHTSTYLE 12
|
||||
#define SVC_UPDATENAME 13
|
||||
#define SVC_UPDATEPOINTS 14
|
||||
#define SVC_CLIENTDATA 15
|
||||
#define SVC_STOPSOUND 16
|
||||
#define SVC_PARTICLE 18
|
||||
#define SVC_DAMAGE 19
|
||||
#define SVC_SPAWNSTATIC 20
|
||||
#define SVC_SPAWNBINARY 21
|
||||
#define SVC_SPAWNBASELINE 22
|
||||
#define SVC_TEMPENTITY 23
|
||||
#define SVC_SETPAUSE 24
|
||||
#define SVC_SIGNONNUM 25
|
||||
#define SVC_CENTERPRINT 26
|
||||
#define SVC_SPAWNSTATICSOUND 29 // 1998-08-08 Complete SVC list by Zhenga
|
||||
#define SVC_INTERMISSION 30
|
||||
#define SVC_FINALE 31
|
||||
#define SVC_CDTRACK 32
|
||||
#define SVC_SELLSCREEN 33
|
||||
#define SVC_CUTSCENE 34 // 1998-08-08 Complete SVC list by Zhenga
|
||||
#define SVC_WEAPONFIRE 35
|
||||
#define SVC_HITMARK 36
|
||||
#define SVC_USEPRINT 38
|
||||
|
||||
#define TE_SPIKE 0
|
||||
#define TE_SUPERSPIKE 1
|
||||
#define TE_GUNSHOT 2
|
||||
#define TE_EXPLOSION 3
|
||||
#define TE_TAREXPLOSION 4
|
||||
#define TE_LIGHTNING1 5
|
||||
#define TE_LIGHTNING2 6
|
||||
#define TE_WIZSPIKE 7
|
||||
#define TE_KNIGHTSPIKE 8
|
||||
#define TE_LIGHTNING3 9
|
||||
#define TE_LAVASPLASH 10
|
||||
#define TE_TELEPORT 11
|
||||
#define TE_RAYSPLASHGREEN 14
|
||||
#define TE_RAYSPLASHRED 15
|
||||
|
||||
// sound channels
|
||||
// channel 0 never willingly overrides
|
||||
// other channels (1-7) allways override a playing sound on that channel
|
||||
#define CHAN_AUTO 0
|
||||
#define CHAN_WEAPON 1
|
||||
#define CHAN_VOICE 2
|
||||
#define CHAN_ITEM 3
|
||||
#define CHAN_BODY 4
|
||||
//Player uses channel 5 for all weapon reload sfx
|
||||
|
||||
#define ATTN_NONE 0
|
||||
#define ATTN_NORM 1
|
||||
#define ATTN_IDLE 2
|
||||
#define ATTN_STATIC 3
|
||||
|
||||
// update types
|
||||
|
||||
#define UPDATE_GENERAL 0
|
||||
#define UPDATE_STATIC 1
|
||||
#define UPDATE_BINARY 2
|
||||
#define UPDATE_TEMP 3
|
||||
|
||||
// entity effects
|
||||
|
||||
#define EF_BLUE 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_RED 8
|
||||
#define EF_ORANGELIGHT 16
|
||||
#define EF_GREEN 32
|
||||
#define EF_LIGHT 64
|
||||
#define EF_NODRAW 128
|
||||
#define EF_BRIGHTFIELD 256
|
||||
#define EF_FULLBRIGHT 512
|
||||
#define EF_DARKLIGHT 1024
|
||||
#define EF_DARKFIELD 2048
|
||||
#define EF_PURPLELIGHT 4096
|
||||
#define EF_RAYRED 8196
|
||||
#define EF_RAYGREEN 16384
|
||||
|
||||
// messages
|
||||
#define MSG_BROADCAST 0 // unreliable to all
|
||||
#define MSG_ONE 1 // reliable to one (msg_entity)
|
||||
#define MSG_ALL 2 // reliable to all
|
||||
#define MSG_INIT 3 // write to the init string
|
||||
|
||||
#define AS_STRAIGHT 1
|
||||
#define AS_SLIDING 2
|
||||
#define AS_MELEE 3
|
||||
#define AS_MISSILE 4
|
||||
|
||||
// Quake assumes these are defined.
|
||||
|
||||
//.string wad, map;
|
||||
.float /*worldtype,*/ delay, wait, lip, /*light_lev,*/ speed, style/*, skill*/;
|
||||
.string killtarget;
|
||||
.void() think1;
|
||||
.vector finaldest;
|
||||
.vector pos1, pos2/*, mangle*/;
|
||||
|
||||
void(vector o, vector d, float color, float count) particle = #48;// start a particle effect
|
||||
void(string s) bprint_psp = #23;
|
||||
void(entity client, string s) sprint_psp = #24;
|
||||
// End
|
||||
|
||||
void(string s) println = {bprint_psp(s);} //just when brain decided to think this is c
|
||||
void(float ignore, string s) bprint = {bprint_psp(s);};
|
||||
void(entity client, float type, string s) sprint = {sprint_psp(client, s);};
|
||||
void(string s) print = {bprint_psp(s);};
|
||||
|
||||
//doors
|
||||
.float state;
|
||||
#define STATE_TOP 0
|
||||
#define STATE_BOTTOM 1
|
||||
#define STATE_UP 2
|
||||
#define STATE_DOWN 3
|
||||
|
||||
string mappath;
|
||||
#define PRINT_HIGH 0
|
||||
|
||||
.float isspec;
|
||||
|
||||
#define FILE_READ 0
|
||||
#define FILE_APPEND 1
|
||||
#define FILE_WRITE 2
|
||||
|
||||
#define MOVE_HITMODEL 0 // must be different for this engine!
|
||||
|
||||
.float recoil_delay;
|
||||
.float gravity;
|
||||
|
||||
.float renderamt;
|
||||
.float rendermode;
|
||||
.vector rendercolor;
|
||||
.string mapversion;
|
||||
.float ammo;
|
||||
|
||||
void(string com) SV_ParseClientCommand;
|
||||
|
||||
.float currentHitBoxSetup;
|
||||
.vector bbmins, bbmaxs; // Used for zombie hitboxes
|
||||
|
||||
.float achievements;
|
668
source/server/defs/vita.qc
Normal file
668
source/server/defs/vita.qc
Normal file
|
@ -0,0 +1,668 @@
|
|||
/*
|
||||
defs.qc
|
||||
|
||||
global definitions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SOURCE FOR GLOBALVARS_T C STRUCTURE
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define NX
|
||||
#define VITA
|
||||
|
||||
//
|
||||
// system globals
|
||||
//
|
||||
entity self;
|
||||
entity other;
|
||||
entity world;
|
||||
float time;
|
||||
float frametime;
|
||||
float force_retouch;
|
||||
string mapname;
|
||||
float deathmatch;
|
||||
float coop;
|
||||
float teamplay;
|
||||
float serverflags;
|
||||
float rounds;
|
||||
float rounds_change;
|
||||
float parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
|
||||
vector v_forward, v_up, v_right;
|
||||
float trace_allsolid;
|
||||
float trace_startsolid;
|
||||
float trace_fraction;
|
||||
vector trace_endpos;
|
||||
vector trace_plane_normal;
|
||||
float trace_plane_dist;
|
||||
entity trace_ent;
|
||||
float trace_inopen;
|
||||
float trace_inwater;
|
||||
entity msg_entity; // destination of single entity writes
|
||||
void() main; // only for testing
|
||||
void() StartFrame;
|
||||
void() EndFrame;
|
||||
void() PlayerPreThink;
|
||||
void() PlayerPostThink;
|
||||
void() ClientKill;
|
||||
void() ClientConnect;
|
||||
void() PutClientInServer;
|
||||
void() ClientDisconnect;
|
||||
void() SetNewParms;
|
||||
void() SetChangeParms;
|
||||
void end_sys_globals;
|
||||
|
||||
|
||||
.float modelindex;
|
||||
.vector absmin, absmax;
|
||||
.float ltime;
|
||||
.float movetype;
|
||||
.float solid;
|
||||
.vector origin;
|
||||
.vector oldorigin;
|
||||
.vector velocity;
|
||||
.vector angles;
|
||||
.vector avelocity;
|
||||
.vector punchangle;
|
||||
.string classname;
|
||||
.string model;
|
||||
.float frame;
|
||||
.float skin;
|
||||
.float effects;
|
||||
.vector mins, maxs;
|
||||
.vector size;
|
||||
.void() touch;
|
||||
.void() use;
|
||||
.void() think;
|
||||
.void() blocked;
|
||||
.float nextthink;
|
||||
.entity groundentity;
|
||||
.float health;
|
||||
.float points;
|
||||
.float kills;
|
||||
.float weapon;
|
||||
.string weaponmodel;
|
||||
.string weapon2model;
|
||||
.float weaponframe;
|
||||
.float weapon2frame;
|
||||
.float currentammo;
|
||||
.float currentmag;
|
||||
.float zoom;
|
||||
.float weaponskin;
|
||||
.float weapon2skin;
|
||||
.float primary_grenades;
|
||||
.float secondary_grenades;
|
||||
.float grenades;
|
||||
.float perks;
|
||||
.float takedamage;
|
||||
.entity chain;
|
||||
.float deadflag;
|
||||
.vector view_ofs;
|
||||
.float button0;
|
||||
.float button1;
|
||||
.float button2;
|
||||
.float button3;
|
||||
.float button4;
|
||||
.float button5;
|
||||
.float button6;
|
||||
.float button7;
|
||||
.float button8;
|
||||
.float impulse;
|
||||
.float fixangle;
|
||||
.vector v_angle;
|
||||
.float idealpitch; // Naievil -- new
|
||||
.string netname;
|
||||
.entity enemy;
|
||||
.float flags;
|
||||
.float colormap;
|
||||
.float team;
|
||||
.float max_health;
|
||||
.float teleport_time;
|
||||
.float armortype;
|
||||
.float armorvalue;
|
||||
.float waterlevel;
|
||||
.float watertype;
|
||||
.float ideal_yaw;
|
||||
.float yaw_speed;
|
||||
.entity aiment;
|
||||
.entity head;
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
.entity goalentity;
|
||||
.float spawnflags;
|
||||
.string target;
|
||||
.string targetname;
|
||||
.float dmg_take;
|
||||
.float dmg_save;
|
||||
.float progress_bar;
|
||||
.entity dmg_inflictor;
|
||||
.entity owner;
|
||||
.vector movedir;
|
||||
.string message;
|
||||
.float sounds;
|
||||
.string noise, noise1, noise2, noise3;
|
||||
.float x2_icon;
|
||||
.float insta_icon;
|
||||
.string Weapon_Name_Touch;
|
||||
.vector ADS_Offset;
|
||||
.vector Flash_Offset;
|
||||
.float Flash_Size;
|
||||
.float currentmag2;
|
||||
.float maxspeed;
|
||||
.float renderGrayscale;
|
||||
void end_sys_fields;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
VARS NOT REFERENCED BY C CODE
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// constants
|
||||
//
|
||||
|
||||
float FALSE = 0;
|
||||
float TRUE = 1;
|
||||
|
||||
// edict.flags
|
||||
float FL_FLY = 1;
|
||||
float FL_SWIM = 2;
|
||||
float FL_CLIENT = 8; // set for all client edicts
|
||||
float FL_INWATER = 16; // for enter / leave water splash
|
||||
float FL_MONSTER = 32;
|
||||
float FL_GODMODE = 64; // player cheat
|
||||
float FL_NOTARGET = 128; // player cheat
|
||||
float FL_ITEM = 256; // extra wide size for bonus items
|
||||
float FL_ONGROUND = 512; // standing on something
|
||||
float FL_PARTIALGROUND = 1024; // not all corners are valid
|
||||
float FL_WATERJUMP = 2048; // player jumping out of water
|
||||
float FL_JUMPRELEASED = 4096; // for jump debouncing
|
||||
|
||||
// edict.movetype values
|
||||
float MOVETYPE_NONE = 0; // never moves
|
||||
//float MOVETYPE_ANGLENOCLIP = 1;
|
||||
//float MOVETYPE_ANGLECLIP = 2;
|
||||
float MOVETYPE_WALK = 3; // players only
|
||||
float MOVETYPE_STEP = 4; // discrete, not real time unless fall
|
||||
float MOVETYPE_FLY = 5;
|
||||
float MOVETYPE_TOSS = 6; // gravity
|
||||
float MOVETYPE_PUSH = 7; // no clip to world, push and crush
|
||||
float MOVETYPE_NOCLIP = 8;
|
||||
float MOVETYPE_FLYMISSILE = 9; // fly with extra size against monsters
|
||||
float MOVETYPE_BOUNCE = 10;
|
||||
float MOVETYPE_BOUNCEMISSILE = 11; // bounce with extra size
|
||||
|
||||
// edict.solid values
|
||||
float SOLID_NOT = 0; // no interaction with other objects
|
||||
float SOLID_TRIGGER = 1; // touch on edge, but not blocking
|
||||
float SOLID_BBOX = 2; // touch on edge, block
|
||||
float SOLID_SLIDEBOX = 3; // touch on edge, but not an onground
|
||||
float SOLID_BSP = 4; // bsp clip, touch on edge, block
|
||||
|
||||
float DEAD_NO = 0;
|
||||
float DEAD_DYING = 1;
|
||||
float DEAD_DEAD = 2;
|
||||
float DEAD_RESPAWNABLE = 3;
|
||||
|
||||
// takedamage values
|
||||
float DAMAGE_NO = 0;
|
||||
float DAMAGE_YES = 1;
|
||||
float DAMAGE_AIM = 2;
|
||||
|
||||
// point content values
|
||||
float CONTENT_EMPTY = -1;
|
||||
float CONTENT_SOLID = -2;
|
||||
float CONTENT_WATER = -3;
|
||||
float CONTENT_SLIME = -4;
|
||||
float CONTENT_LAVA = -5;
|
||||
float CONTENT_SKY = -6;
|
||||
|
||||
float STATE_TOP = 0;
|
||||
float STATE_BOTTOM = 1;
|
||||
float STATE_UP = 2;
|
||||
float STATE_DOWN = 3;
|
||||
|
||||
vector VEC_ORIGIN = '0 0 0';
|
||||
|
||||
// protocol bytes
|
||||
float SVC_TEMPENTITY = 23;
|
||||
float SVC_KILLEDMONSTER = 27;
|
||||
float SVC_FOUNDSECRET = 28;
|
||||
float SVC_INTERMISSION = 30;
|
||||
float SVC_FINALE = 31;
|
||||
float SVC_CDTRACK = 32;
|
||||
float SVC_SELLSCREEN = 33;
|
||||
float SVC_SMALLKICK = 34;
|
||||
float SVC_BIGKICK = 35;
|
||||
float SVC_MUZZLEFLASH = 39;
|
||||
|
||||
// sound channels
|
||||
// channel 0 never willingly overrides
|
||||
// other channels (1-7) allways override a playing sound on that channel
|
||||
float CHAN_AUTO = 0;
|
||||
float CHAN_WEAPON = 1;
|
||||
float CHAN_VOICE = 2;
|
||||
float CHAN_ITEM = 3;
|
||||
float CHAN_BODY = 4;
|
||||
float CHAN_NO_PHS_ADD = 8; // ie: CHAN_BODY+CHAN_NO_PHS_ADD
|
||||
|
||||
float ATTN_NONE = 0;
|
||||
float ATTN_NORM = 1;
|
||||
float ATTN_IDLE = 2;
|
||||
float ATTN_STATIC = 3;
|
||||
|
||||
// entity effects
|
||||
#define EF_BLUE 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_RED 8
|
||||
#define EF_ORANGELIGHT 16
|
||||
#define EF_GREEN 32
|
||||
#define EF_LIGHT 64
|
||||
#define EF_NODRAW 128
|
||||
#define EF_BRIGHTFIELD 256
|
||||
#define EF_FULLBRIGHT 512
|
||||
#define EF_DARKLIGHT 1024
|
||||
#define EF_DARKFIELD 2048
|
||||
#define EF_PURPLELIGHT 4096
|
||||
#define EF_RAYRED 8196
|
||||
#define EF_RAYGREEN 16384
|
||||
|
||||
// messages
|
||||
float MSG_BROADCAST = 0; // unreliable to all
|
||||
float MSG_ONE = 1; // reliable to one (msg_entity)
|
||||
float MSG_ALL = 2; // reliable to all
|
||||
float MSG_INIT = 3; // write to the init string
|
||||
float MSG_MULTICAST = 4; // for multicast() call
|
||||
|
||||
// message levels
|
||||
float PRINT_LOW = 0; // pickup messages
|
||||
float PRINT_MEDIUM = 1; // death messages
|
||||
float PRINT_HIGH = 2; // critical messages
|
||||
float PRINT_CHAT = 3; // also goes to chat console
|
||||
|
||||
// multicast sets
|
||||
float MULTICAST_ALL = 0; // every client
|
||||
float MULTICAST_PHS = 1; // within hearing
|
||||
float MULTICAST_PVS = 2; // within sight
|
||||
float MULTICAST_ALL_R = 3; // every client, reliable
|
||||
float MULTICAST_PHS_R = 4; // within hearing, reliable
|
||||
float MULTICAST_PVS_R = 5; // within sight, reliable
|
||||
|
||||
|
||||
|
||||
|
||||
//================================================
|
||||
|
||||
//
|
||||
// globals
|
||||
//
|
||||
string string_null; // null string, nothing should be held here
|
||||
entity activator; // the entity that activated a trigger or brush
|
||||
float framecount;
|
||||
|
||||
//
|
||||
// cvars checked each frame
|
||||
//
|
||||
float teamplay;
|
||||
float deathmatch;
|
||||
|
||||
//================================================
|
||||
|
||||
//
|
||||
// world fields (FIXME: make globals)
|
||||
//
|
||||
.string wad;
|
||||
.string map;
|
||||
.float worldtype; // 0=medieval 1=metal 2=base
|
||||
|
||||
//================================================
|
||||
|
||||
.string killtarget;
|
||||
|
||||
//
|
||||
// quakeed fields
|
||||
//
|
||||
.float light_lev; // not used by game, but parsed by light util
|
||||
.float style;
|
||||
|
||||
|
||||
//
|
||||
// monster ai
|
||||
//
|
||||
.void() th_stand;
|
||||
.void() th_walk;
|
||||
.void() th_run;
|
||||
.void() th_missile;
|
||||
.void() th_melee;
|
||||
.void(entity attacker, float damage) th_pain;
|
||||
.void() th_die;
|
||||
|
||||
.entity oldenemy; // mad at this player before taking damage
|
||||
|
||||
.float speed;
|
||||
|
||||
.float lefty;
|
||||
|
||||
.float search_time;
|
||||
.float attack_state;
|
||||
|
||||
float AS_STRAIGHT = 1;
|
||||
float AS_SLIDING = 2;
|
||||
float AS_MELEE = 3;
|
||||
float AS_MISSILE = 4;
|
||||
|
||||
//
|
||||
// player only fields
|
||||
//
|
||||
.float voided;
|
||||
.float walkframe;
|
||||
|
||||
// Zoid Additions
|
||||
.float gravity; // Gravity Multiplier (0 to 1.0)
|
||||
|
||||
|
||||
|
||||
.float attack_finished;
|
||||
.float pain_finished;
|
||||
|
||||
.float invincible_finished;
|
||||
.float invisible_finished;
|
||||
.float super_damage_finished;
|
||||
.float radsuit_finished;
|
||||
|
||||
.float invincible_time, invincible_sound;
|
||||
.float invisible_time, invisible_sound;
|
||||
.float super_time, super_sound;
|
||||
.float rad_time;
|
||||
.float fly_sound;
|
||||
|
||||
.float axhitme;
|
||||
|
||||
.float show_hostile; // set to time+0.2 whenever a client fires a
|
||||
// weapon or takes damage. Used to alert
|
||||
// monsters that otherwise would let the player go
|
||||
.float jump_flag; // player jump flag
|
||||
.float swim_flag; // player swimming sound flag
|
||||
.float air_finished; // when time > air_finished, start drowning
|
||||
.float bubble_count; // keeps track of the number of bubbles
|
||||
.string deathtype; // keeps track of how the player died
|
||||
|
||||
//
|
||||
// object stuff
|
||||
//
|
||||
.string mdl;
|
||||
.vector mangle; // angle at start
|
||||
|
||||
.vector oldorigin; // only used by secret door
|
||||
|
||||
.float t_length, t_width;
|
||||
|
||||
|
||||
//
|
||||
// doors, etc
|
||||
//
|
||||
.vector dest, dest1, dest2;
|
||||
.float wait; // time from firing to restarting
|
||||
.float delay; // time from activation to firing
|
||||
.entity trigger_field; // door's trigger entity
|
||||
.string noise4;
|
||||
|
||||
//
|
||||
// monsters
|
||||
//
|
||||
.float pausetime;
|
||||
.entity movetarget;
|
||||
|
||||
|
||||
//
|
||||
// doors
|
||||
//
|
||||
.float aflag;
|
||||
.float dmg; // damage done by door when hit
|
||||
|
||||
//
|
||||
// misc
|
||||
//
|
||||
.float cnt; // misc flag
|
||||
|
||||
//
|
||||
// subs
|
||||
//
|
||||
.void() think1;
|
||||
.vector finaldest, finalangle;
|
||||
|
||||
//
|
||||
// triggers
|
||||
//
|
||||
.float count; // for counting triggers
|
||||
|
||||
|
||||
//
|
||||
// plats / doors / buttons
|
||||
//
|
||||
.float lip;
|
||||
.float state;
|
||||
.vector pos1, pos2; // top and bottom positions
|
||||
.float height;
|
||||
|
||||
//
|
||||
// sounds
|
||||
//
|
||||
.float waitmin, waitmax;
|
||||
.float distance;
|
||||
.float volume;
|
||||
|
||||
.float sprintflag;
|
||||
|
||||
//
|
||||
// builtin functions
|
||||
//
|
||||
|
||||
void(vector ang) makevectors = #1; // sets v_forward, etc globals
|
||||
void(entity e, vector o) setorigin = #2;
|
||||
void(entity e, string m) setmodel = #3; // set movetype and solid first
|
||||
void(entity e, vector min, vector max) setsize = #4;
|
||||
|
||||
void() break = #6;
|
||||
float() random = #7; // returns 0 - 1
|
||||
void(entity e, float chan, string samp, float vol, float atten) sound = #8;
|
||||
vector(vector v) normalize = #9;
|
||||
void(string e) error = #10;
|
||||
void(string e) objerror = #11;
|
||||
float(vector v) vlen = #12;
|
||||
float(vector v) vectoyaw = #13;
|
||||
entity() spawn = #14;
|
||||
void(entity e) remove = #15;
|
||||
void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
|
||||
entity() checkclient = #17; // returns a client to look for
|
||||
entity(entity start, .string fld, string match) find = #18;
|
||||
string(string s) precache_sound = #19;
|
||||
string(string s) precache_model = #20;
|
||||
void(entity client, string s)stuffcmd = #21;
|
||||
entity(vector org, float rad) findradius = #22;
|
||||
void(float level, string s) bprint = #23;
|
||||
void(entity client, float level, string s) sprint = #24;
|
||||
void(string s) dprint = #25;
|
||||
string(float f) ftos = #26;
|
||||
string(vector v) vtos = #27;
|
||||
void() coredump = #28; // prints all edicts
|
||||
void() traceon = #29; // turns statment trace on
|
||||
void() traceoff = #30;
|
||||
void(entity e) eprint = #31; // prints an entire edict
|
||||
float(float yaw, float dist) walkmove = #32; // returns TRUE or FALSE
|
||||
float(entity zombie, float which, entity limb) updateLimb = #33;
|
||||
float(float yaw, float dist) droptofloor = #34; // TRUE if landed on floor
|
||||
void(float style, string value) lightstyle = #35;
|
||||
float(float v) rint = #36; // round to nearest int
|
||||
float(float v) floor = #37; // largest integer <= v
|
||||
float(float v) ceil = #38; // smallest integer >= v
|
||||
float(entity e) checkbottom = #40; // true if self is on ground
|
||||
float(vector v) pointcontents = #41; // returns a CONTENT_*
|
||||
float(float f) fabs = #43;
|
||||
vector(entity e, float speed) aim = #44; // returns the shooting vector
|
||||
float(string s) cvar = #45; // return cvar.value
|
||||
void(string s) localcmd = #46; // put string into local que
|
||||
entity(entity e) nextent = #47; // for looping through all ents
|
||||
void() ChangeYaw = #49; // turn towards self.ideal_yaw
|
||||
vector(vector v) vectoangles = #51;
|
||||
void(float to, float f) WriteByte = #52;
|
||||
void(float to, float f) WriteChar = #53;
|
||||
void(float to, float f) WriteShort = #54;
|
||||
void(float to, float f) WriteLong = #55;
|
||||
void(float to, float f) WriteCoord = #56;
|
||||
void(float to, float f) WriteAngle = #57;
|
||||
void(float to, string s) WriteString = #58;
|
||||
void(float to, entity s) WriteEntity = #59;
|
||||
void(float step) movetogoal = #67;
|
||||
string(string s) precache_file = #68; // no effect except for -copy
|
||||
void(entity e) makestatic = #69;
|
||||
void(string s) changelevel = #70;
|
||||
void(string var, string val) cvar_set = #72; // sets cvar.value
|
||||
void(entity client, string s) centerprint = #73; // sprint, but in middle
|
||||
void(vector pos, string samp, float vol, float atten) ambientsound = #74;
|
||||
string(string s) precache_model2 = #75; // registered version only
|
||||
string(string s) precache_sound2 = #76; // registered version only
|
||||
string(string s) precache_file2 = #77; // registered version only
|
||||
void(entity e) setspawnparms = #78; // set parm1... to the
|
||||
void(entity killer, entity killee) logfrag = #79; // add to stats
|
||||
string(entity e, string key) infokey = #80; // get a key value (world = serverinfo)
|
||||
float(string s) stof = #81; // convert string to float
|
||||
void(vector where, float set) multicast = #82;
|
||||
vector(entity what) Get_Waypoint_Near = #83;
|
||||
float(entity zombie, entity target) Do_Pathfind_psp = #84;
|
||||
void(string s) Open_Waypoint = #85;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_Next_Waypoint = #86;
|
||||
void(entity client, float type, float cost, float weapon) useprint = #87;
|
||||
vector(entity zombie,vector start,vector min, vector max) Get_First_Waypoint = #88;
|
||||
entity (entity start, .float field, float match) findfloat = #98;
|
||||
|
||||
// New NZP custom ones
|
||||
float(string filename, float mode) fopen = #110;
|
||||
void(float fhandle) fclose = #111;
|
||||
string(float fhandle) fgets = #112;
|
||||
void(float fhandle, string s) fputs = #113;
|
||||
float(string s) strlen = #114;
|
||||
string(string s1, string s2) strcat = #115;
|
||||
string(string s, float start, float length) substring = #116;
|
||||
vector(string s) stov = #117;
|
||||
string(string s) strzone = #118;
|
||||
string(string s) strunzone = #119;
|
||||
string(string s) strtrim = #120;
|
||||
float(string s) tokenize = #130; // Was #441
|
||||
string(float num) argv = #131; // Was #442
|
||||
void(float intensity_small, float intensity_large, float duration) rumble = #132;
|
||||
|
||||
float(entity targ, entity inflictor) CanDamage;
|
||||
|
||||
|
||||
#define FILE_READ 0
|
||||
#define FILE_APPEND 1
|
||||
#define FILE_WRITE 2
|
||||
#define SVC_WEAPONFIRE 35
|
||||
#define SVC_HITMARK 36
|
||||
#define SVC_LIMBUPDATE 51 // naievil -- keep me
|
||||
#define SVC_BSPDECAL 50 // naievil -- keep me
|
||||
#define SVC_ACHIEVEMENT 52
|
||||
|
||||
#define VEC_ORIGIN '0 0 0'
|
||||
|
||||
//Standard Quake View Offset
|
||||
//vector VEC_VIEW_OFS = '0 0 22';
|
||||
|
||||
//Half Life View Offset is 64
|
||||
//64 units above ground, for our purposes it's, 64 - (how low bounding box goes)
|
||||
vector VEC_VIEW_OFS = '0 0 32';
|
||||
|
||||
//Standard Quake Hull
|
||||
//vector VEC_HULL_MIN = '-16 -16 -24';
|
||||
//vector VEC_HULL_MAX = '16 16 32';
|
||||
|
||||
//Half Life 1 Hull Sizes ADDED BY BLUBS, COMMENTED ORIGINAL QUAKE BBOX SIZS OUT
|
||||
#define VEC_HULL_MIN '-16 -16 -32'
|
||||
#define VEC_HULL_MAX '16 16 40'
|
||||
|
||||
#define VEC_HULL2_MIN '-32 -32 -24'
|
||||
#define VEC_HULL2_MAX '32 32 64'
|
||||
|
||||
.string fog;
|
||||
//string world_fog;
|
||||
|
||||
.float button3;
|
||||
.float button4;
|
||||
.float button5;
|
||||
.float button6;
|
||||
.float button7;
|
||||
.float button8;
|
||||
|
||||
.float x2_icon; // double points icon
|
||||
.float insta_icon;
|
||||
.vector Flash_Offset;
|
||||
.float Flash_Size;
|
||||
.string Weapon_Name;
|
||||
|
||||
.float currentHitBoxSetup;
|
||||
.vector bbmins, bbmaxs; // Used for zombie hitboxes
|
||||
|
||||
.entity head;
|
||||
.entity larm;
|
||||
.entity rarm;
|
||||
|
||||
#define SOLID_CORPSE 5 // bsp clip, touch on edge, block
|
||||
#define TE_EXPLOSION 3
|
||||
#define TE_GUNSHOT 2
|
||||
entity windows[32];
|
||||
float wincnt;
|
||||
|
||||
.float recoil_delay;
|
||||
|
||||
float pow(float base, float n) = {
|
||||
float temp = base;
|
||||
if (n == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
while (n > 0) {
|
||||
temp = temp * base;
|
||||
n = n - 1;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
void enableGrayscale(void) = {
|
||||
self.renderGrayscale = 1;
|
||||
}
|
||||
|
||||
void disableGrayscale(void) = {
|
||||
self.renderGrayscale = 0;
|
||||
}
|
89
source/server/dummies/generic.qc
Normal file
89
source/server/dummies/generic.qc
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
server/dummies/generic.qc
|
||||
|
||||
generic (all platform) dummys
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
// Triggers
|
||||
void() trigger_relay = {remove(self);};
|
||||
void() trigger_changelevel = {remove(self);};
|
||||
void() trigger_counter = {remove(self);};
|
||||
void() trigger_secret = {remove(self);};
|
||||
void() trigger_setskill = {remove(self);};
|
||||
void() trigger_monsterjump = {remove(self);};
|
||||
void() trigger_onlyregistered = {remove(self);};
|
||||
void() trigger_push = {remove(self);};
|
||||
void() trigger_hurt = {remove(self);};
|
||||
// Player Starts
|
||||
void() info_player_start = {};
|
||||
void() info_player_start2 = {};
|
||||
void() info_player_deathmatch = {};
|
||||
void() info_player_coop = {};
|
||||
void() info_player_tank = {};
|
||||
void() info_player_nikolai = {};
|
||||
void() info_player_doctor = {};
|
||||
void() info_player_takeo = {};
|
||||
|
||||
void() zapper1 = {remove(self);};
|
||||
void() zapper2 = {remove(self);};
|
||||
void() item_switch = {remove(self);};
|
||||
void() zap_light = {remove(self);};
|
||||
void() info_end = {remove(self);};
|
||||
|
||||
//// beta removal
|
||||
void() monster_dog = {remove(self);};
|
||||
void() item_pap = {remove(self);};
|
||||
//void() item_juggernog = {remove(self);};
|
||||
//void() item_flopper = {remove(self);};
|
||||
//void() item_douple = {remove(self);};
|
||||
//void() item_speed = {remove(self);};
|
||||
//void() item_revive = {remove(self);};
|
||||
void() palm_tree_closed = {remove(self);};
|
||||
void() func_model = {remove(self);};
|
||||
void() wooden_crate = {remove(self);};
|
||||
|
||||
void() change_frame;
|
||||
void() change_frame2 =
|
||||
{
|
||||
self.frame++;
|
||||
self.think = change_frame;
|
||||
self.nextthink = time + 1;
|
||||
}
|
||||
void() change_frame =
|
||||
{
|
||||
self.frame++;
|
||||
self.think = change_frame2;
|
||||
self.nextthink = time + 1;
|
||||
}
|
||||
|
||||
#ifdef PSP
|
||||
void LoadWaypointData() = {};
|
||||
#endif
|
||||
|
||||
// Old Demo defs
|
||||
.float fogdogs;
|
||||
.float MaxRange;
|
||||
void() trigger_teleport = {remove(self);};
|
||||
void() tigger_mainframe = {remove(self);}; //lol this typo is in their old fgd too, apparently.
|
||||
void() trigger_teleport_area = {remove(self);};
|
157
source/server/dummies/vitanx.qc
Normal file
157
source/server/dummies/vitanx.qc
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
server/dummies/generic.qc
|
||||
|
||||
dummys for vita and nx
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
// Dummys that should be here
|
||||
void GiveAchievement(float achievement_id, optional entity who) = {};
|
||||
void print(string s) = {};
|
||||
|
||||
float tracemove(vector start, vector min, vector max, vector end, float nomonsters, entity forent) = {return 0;};
|
||||
|
||||
void(vector o, vector d, float color, float count) particle = {};
|
||||
|
||||
#define MOVE_HITMODEL 0
|
||||
|
||||
void() LoadWaypointData = {};
|
||||
|
||||
void() Soft_Restart = {
|
||||
/*
|
||||
entity who, oldself, doors, box, revive, endgame;
|
||||
self = find(world,classname,"player");
|
||||
oldself = self;
|
||||
|
||||
//remove all zombies
|
||||
who = find(world,classname,"ai_zombie");
|
||||
while(who != world)
|
||||
{
|
||||
if(who.health)
|
||||
{
|
||||
self = who;
|
||||
self.th_die();
|
||||
remove(self); //so dead bodies don't remain
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
who = find(who,classname,"ai_zombie");
|
||||
}
|
||||
|
||||
//repair all windows
|
||||
for(float i = 0; i < wincnt; i++) {
|
||||
if (windows[i].health != -10) {
|
||||
windows[i].health = 6;
|
||||
windows[i].frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//close doors
|
||||
doors = findfloat(world, isopen, 1);
|
||||
while (doors) {
|
||||
if (doors.isopen)
|
||||
reclose_door(doors);
|
||||
doors = findfloat(world, isopen, 1);
|
||||
}
|
||||
|
||||
//revert mystery box
|
||||
box = find(world, classname, "mystery");
|
||||
if (box) {
|
||||
box.boxstatus = 0;
|
||||
box.frame = 0;
|
||||
box.goaldummy.frame = 0;
|
||||
boxCount = 0;
|
||||
box.origin = boxOrigin;
|
||||
//self = box;
|
||||
|
||||
if (box.boxweapon)
|
||||
remove(box.boxweapon);
|
||||
|
||||
//mystery_box();
|
||||
//self = oldself;
|
||||
}
|
||||
|
||||
//reset quick revive
|
||||
revive = find(world, classname, "perk_revive");
|
||||
if (revive) {
|
||||
setmodel(revive, "models/machines/quick_revive.mdl");
|
||||
oldself.revivesoda = 0;
|
||||
}
|
||||
|
||||
//reset buyable ending
|
||||
endgame = find(world, classname, "func_ending");
|
||||
if (endgame) {
|
||||
endgame.activated = false;
|
||||
}
|
||||
|
||||
//reset teleporters
|
||||
local entity tp;
|
||||
tp = find(world, classname, "func_teleporter_entrance");
|
||||
|
||||
if (tp) {
|
||||
tp.activated = false;
|
||||
tp.isLinked = false;
|
||||
tp.cooldown = false;
|
||||
tp.waitLink = false;
|
||||
tp.think = SUB_Null;
|
||||
}
|
||||
|
||||
local entity power;
|
||||
power = find(world, classname, "power_switch");
|
||||
if(power) {
|
||||
isPowerOn = false;
|
||||
power.frame = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
self = oldself;
|
||||
self.downed = 0;
|
||||
game_over = false;
|
||||
rounds = 0;
|
||||
self.score = 0;
|
||||
self.points = 0;
|
||||
self.secondaryweapon = 0;
|
||||
InitRounds();
|
||||
self.isspec = false;
|
||||
PutClientInServer();
|
||||
*/
|
||||
}
|
||||
|
||||
void () CL_SendWeaponFire =
|
||||
{
|
||||
float return_time;
|
||||
vector Wep_Recoil;
|
||||
|
||||
Wep_Recoil = GetWeaponRecoil(self.weapon);
|
||||
|
||||
msg_entity = self;
|
||||
WriteByte(MSG_ONE, SVC_WEAPONFIRE);
|
||||
return_time = getWeaponRecoilReturn(self.weapon);
|
||||
WriteLong(MSG_ONE, return_time);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_x);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_y);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_z);
|
||||
//self.punchangle = Wep_Recoil;
|
||||
self.recoil_delay = 60/return_time + time;
|
||||
}
|
696
source/server/entities/doors.qc
Normal file
696
source/server/entities/doors.qc
Normal file
|
@ -0,0 +1,696 @@
|
|||
/*
|
||||
server/entities/doors.qc
|
||||
|
||||
Doors are similar to buttons, but can spawn a fat trigger field
|
||||
around them to open without a touch, and they link together to
|
||||
form simultanious double/quad doors.
|
||||
|
||||
Door.owner is the master door. If there is only one door, it
|
||||
points to itself. If multiple doors, all will point to a single
|
||||
one.
|
||||
|
||||
Door.enemy chains from the master door through all doors linked
|
||||
in the chain.
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
code for show that you need money EDITASAP
|
||||
*/
|
||||
float DOOR_START_OPEN = 1;
|
||||
float DOOR_DONT_LINK = 4;
|
||||
float DOOR_DEBRIS = 8;
|
||||
float DOOR_SILVER_KEY = 16;
|
||||
float DOOR_TOGGLE = 32;
|
||||
float DOOR_POWER = 64;
|
||||
|
||||
entity activator;
|
||||
.float delay;
|
||||
.string killtarget;
|
||||
.void() think1;
|
||||
.vector finaldest;
|
||||
.float dmg;
|
||||
.entity trigger_field;
|
||||
.float wait;
|
||||
.float speed;
|
||||
.vector pos1;
|
||||
.vector pos2;
|
||||
string string_null;
|
||||
.float cost;
|
||||
.float attack_delay;
|
||||
.float lip;
|
||||
|
||||
void() print_need_power =
|
||||
{
|
||||
if(other.classname == "player" && !other.downed)
|
||||
{
|
||||
/*if (self.owner.message)
|
||||
centerprint(other, self.owner.message);
|
||||
else
|
||||
centerprint(other, "Power must be activated first");*/
|
||||
|
||||
useprint (other, 8, 0, 0);
|
||||
}
|
||||
|
||||
};
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
THINK FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() door_go_down;
|
||||
void() door_go_up;
|
||||
|
||||
void() door_blocked =
|
||||
{
|
||||
DamageHandler (other, self, self.dmg, S_NORMAL);
|
||||
|
||||
// if a door has a negative wait, it would never come back if blocked,
|
||||
// so let it just squash the object to death real fast
|
||||
if (self.wait >= 0)
|
||||
{
|
||||
if (self.state == STATE_DOWN)
|
||||
door_go_up ();
|
||||
else
|
||||
door_go_down ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void() door_hit_top =
|
||||
{
|
||||
self.state = STATE_TOP;
|
||||
if ((self.classname == "door_nzp_cost" || self.classname == "door_nzp" || self.classname == "door_open"))
|
||||
{
|
||||
//remove (self.owner.trigger_field); //moto - what does this do lol
|
||||
if (!(self.spawnflags & 128))
|
||||
setmodel(self, "");
|
||||
|
||||
self.isopen = 1;
|
||||
return;//so we dont have to reopen doors
|
||||
}
|
||||
if (self.spawnflags & DOOR_TOGGLE)
|
||||
return; // don't come down automatically
|
||||
self.think = door_go_down;
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
};
|
||||
|
||||
void() door_hit_bottom =
|
||||
{
|
||||
self.state = STATE_BOTTOM;
|
||||
};
|
||||
|
||||
void() door_go_down =
|
||||
{
|
||||
if ((self.classname == "door_nzp_cost" || self.classname == "door_nzp" || self.classname == "door_open"))
|
||||
{
|
||||
if (!(self.spawnflags & 128))
|
||||
setmodel(self, "");
|
||||
self.isopen = 1;
|
||||
return;//so we dont have to reopen doors
|
||||
}
|
||||
if (self.max_health)
|
||||
{
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.health = self.max_health;
|
||||
}
|
||||
|
||||
self.state = STATE_DOWN;
|
||||
|
||||
if (self.spawnflags & 256)
|
||||
SUB_CalcAngleMove(self.pos1, self.speed, door_hit_bottom);
|
||||
else
|
||||
SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
|
||||
};
|
||||
|
||||
void() door_go_up =
|
||||
{
|
||||
if (self.state == STATE_UP)
|
||||
return; // allready going up
|
||||
|
||||
if (self.state == STATE_TOP)
|
||||
{ // reset top wait time
|
||||
self.nextthink = self.ltime + self.wait;
|
||||
return;
|
||||
}
|
||||
|
||||
self.state = STATE_UP;
|
||||
|
||||
if (self.spawnflags & 256)
|
||||
SUB_CalcAngleMove(self.pos2, self.speed, door_hit_top);
|
||||
else
|
||||
SUB_CalcMove (self.pos2, self.speed, door_hit_top);
|
||||
|
||||
#ifndef PC
|
||||
Open_Waypoint(self.wayTarget);
|
||||
#endif
|
||||
SUB_UseTargets();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
ACTIVATION FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void() door_fire =
|
||||
{
|
||||
local entity oself;
|
||||
local entity starte;
|
||||
|
||||
if (isPowerOn == FALSE)
|
||||
{
|
||||
if (self.spawnflags & DOOR_POWER )
|
||||
{
|
||||
if(other.classname == "player" && !other.downed)
|
||||
{
|
||||
/*if (self.message)
|
||||
centerprint(other, self.message);
|
||||
else
|
||||
centerprint(other, "Power must be activated first");*/
|
||||
useprint (other, 8, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.message = string_null; // no more message
|
||||
oself = self;
|
||||
|
||||
if (self.door_model_target)
|
||||
{
|
||||
entity tempe = find(world, classname, "func_door_model");
|
||||
if (tempe != world) {
|
||||
///door_model_name, self.door_model_target
|
||||
if (tempe.door_model_name == self.door_model_target) {
|
||||
setmodel(tempe, "");
|
||||
remove(tempe);
|
||||
} else {
|
||||
bprint(PRINT_HIGH, "Could not find door_model_name: ");
|
||||
bprint(PRINT_HIGH, self.door_model_target);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.spawnflags & DOOR_TOGGLE)
|
||||
{
|
||||
if (self.state == STATE_UP || self.state == STATE_TOP)
|
||||
{
|
||||
starte = self;
|
||||
do
|
||||
{
|
||||
door_go_down ();
|
||||
self = self.enemy;
|
||||
} while ( (self != starte) && (self != world) );
|
||||
self = oself;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// trigger all paired doors
|
||||
starte = self;
|
||||
do
|
||||
{
|
||||
door_go_up ();
|
||||
//self.isopen = true;
|
||||
self = self.enemy;
|
||||
} while ( (self != starte) && (self != world) );
|
||||
self = oself;
|
||||
|
||||
SUB_UseTargets();
|
||||
};
|
||||
|
||||
void() cost_door =
|
||||
{
|
||||
if (self.state == STATE_TOP || self.state == STATE_UP)
|
||||
return;
|
||||
|
||||
if (isPowerOn == FALSE)
|
||||
{
|
||||
if (self.spawnflags & DOOR_POWER )
|
||||
{
|
||||
if(other.classname == "player" && !other.downed)
|
||||
{
|
||||
/*if (self.message)
|
||||
centerprint(other, self.message);
|
||||
else
|
||||
centerprint(other, "Power must be activated first");*/
|
||||
useprint (other, 8, 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (other.button7)
|
||||
{
|
||||
if (other.points >= self.cost)
|
||||
{
|
||||
door_fire();
|
||||
sound(self, 0,"sounds/misc/ching.wav", 1, 1);
|
||||
sound(self, CHAN_ITEM,"sounds/misc/buy.wav", 1, 1);
|
||||
switch(self.sounds)
|
||||
{
|
||||
case 1:
|
||||
sound(self, CHAN_ITEM,"sounds/misc/wood_door.wav", 1, 1);
|
||||
break;
|
||||
case 2:
|
||||
sound(self, CHAN_ITEM,"sounds/misc/debris.wav", 1, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
addmoney(other, self.cost*-1, 0);
|
||||
self.solid = SOLID_NOT;
|
||||
//centerprint (other, "");
|
||||
//useprint (other, 0, 0, 0);
|
||||
//other.total_bought = other.total_bought + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(other.classname == "player" && !other.downed)
|
||||
{
|
||||
centerprint (other, "You do not have enough points\n");
|
||||
other.semiuse = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!other.button7)
|
||||
{
|
||||
if(other.classname == "player" && !other.downed)
|
||||
{
|
||||
/*if (!self.message)
|
||||
centerprint3(other, "press use to open door for ", b = ftos (self.cost), " points\n");
|
||||
else
|
||||
centerprint (other, self.message);*/
|
||||
if (self.spawnflags & DOOR_DEBRIS)
|
||||
useprint (other, 2, self.cost, 0);
|
||||
else
|
||||
useprint (other, 1, self.cost, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
void() door_use =
|
||||
{
|
||||
local entity oself;
|
||||
|
||||
oself = self;
|
||||
self = self.owner;
|
||||
if (self.cost)
|
||||
cost_door();
|
||||
else
|
||||
door_fire ();
|
||||
self = oself;
|
||||
};
|
||||
|
||||
|
||||
void() door_trigger_touch =
|
||||
{
|
||||
if(other.classname != "player")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(cvar("waypoint_mode"))
|
||||
{
|
||||
if(other.active_door != self.owner)
|
||||
{
|
||||
bprint(PRINT_HIGH, "Current Door for special waypoints set to ");
|
||||
bprint(PRINT_HIGH, self.owner.wayTarget);
|
||||
bprint(PRINT_HIGH, "\n");
|
||||
other.active_door = self.owner;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (other.health <= 20)
|
||||
return;
|
||||
|
||||
activator = other;
|
||||
|
||||
self = self.owner;
|
||||
door_use ();
|
||||
};
|
||||
|
||||
|
||||
void() door_killed =
|
||||
{
|
||||
local entity oself;
|
||||
|
||||
oself = self;
|
||||
self = self.owner;
|
||||
self.health = self.max_health;
|
||||
self.takedamage = DAMAGE_NO; // will be reset upon return
|
||||
door_use ();
|
||||
self = oself;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
door_touch
|
||||
|
||||
Prints messages and opens key doors
|
||||
================
|
||||
*/
|
||||
void() door_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
if (other.button7)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (self.owner.message != "")
|
||||
{
|
||||
centerprint (other, self.owner.message);
|
||||
}
|
||||
|
||||
if (isPowerOn == FALSE)
|
||||
{
|
||||
if (self.owner.spawnflags & DOOR_POWER)
|
||||
{
|
||||
self.touch = print_need_power;
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.touch = SUB_Null;
|
||||
if (self.enemy)
|
||||
self.enemy.touch = SUB_Null; // get paired door
|
||||
door_use ();
|
||||
};
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
SPAWNING FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
entity(vector fmins, vector fmaxs) spawn_field =
|
||||
{
|
||||
local entity trigger;
|
||||
local vector t1, t2;
|
||||
|
||||
trigger = spawn();
|
||||
trigger.movetype = MOVETYPE_NONE;
|
||||
trigger.solid = SOLID_TRIGGER;
|
||||
trigger.owner = self;
|
||||
trigger.touch = door_trigger_touch;
|
||||
setorigin(trigger, self.origin);
|
||||
|
||||
t1 = fmins;
|
||||
t2 = fmaxs;
|
||||
setsize (trigger, t1/* - '15 15 8'*/, t2/* + '15 15 8'*/);
|
||||
return (trigger);
|
||||
};
|
||||
|
||||
|
||||
float (entity e1, entity e2) EntitiesTouching =
|
||||
{
|
||||
if (e1.mins_x > e2.maxs_x)
|
||||
return FALSE;
|
||||
if (e1.mins_y > e2.maxs_y)
|
||||
return FALSE;
|
||||
if (e1.mins_z > e2.maxs_z)
|
||||
return FALSE;
|
||||
if (e1.maxs_x < e2.mins_x)
|
||||
return FALSE;
|
||||
if (e1.maxs_y < e2.mins_y)
|
||||
return FALSE;
|
||||
if (e1.maxs_z < e2.mins_z)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
/*
|
||||
=============
|
||||
LinkDoors
|
||||
|
||||
|
||||
=============
|
||||
*/
|
||||
void() LinkDoors =
|
||||
{
|
||||
local entity t, starte;
|
||||
local vector cmins, cmaxs;
|
||||
|
||||
if (self.enemy)
|
||||
return; // already linked by another door
|
||||
if (self.spawnflags & 4)
|
||||
{
|
||||
self.owner = self.enemy = self;
|
||||
return; // don't want to link this door
|
||||
}
|
||||
|
||||
cmins = self.mins;
|
||||
cmaxs = self.maxs;
|
||||
|
||||
starte = self;
|
||||
t = self;
|
||||
|
||||
do
|
||||
{
|
||||
self.owner = starte; // master door
|
||||
|
||||
if (self.health)
|
||||
starte.health = self.health;
|
||||
if (self.targetname)
|
||||
starte.targetname = self.targetname;
|
||||
if (self.message != "")
|
||||
starte.message = self.message;
|
||||
|
||||
t = find (t, classname, self.classname);
|
||||
if (!t)
|
||||
{
|
||||
self.enemy = starte; // make the chain a loop
|
||||
|
||||
// shootable, fired, or key doors just needed the owner/enemy links,
|
||||
// they don't spawn a field
|
||||
|
||||
self = self.owner;
|
||||
|
||||
if (self.health)
|
||||
return;
|
||||
if (self.targetname)
|
||||
return;
|
||||
|
||||
self.owner.trigger_field = spawn_field(cmins, cmaxs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (EntitiesTouching(self,t))
|
||||
{
|
||||
if (t.enemy)
|
||||
objerror ("cross connected doors");
|
||||
|
||||
self.enemy = t;
|
||||
self = t;
|
||||
|
||||
if (t.mins_x < cmins_x)
|
||||
cmins_x = t.mins_x;
|
||||
if (t.mins_y < cmins_y)
|
||||
cmins_y = t.mins_y;
|
||||
if (t.mins_z < cmins_z)
|
||||
cmins_z = t.mins_z;
|
||||
if (t.maxs_x > cmaxs_x)
|
||||
cmaxs_x = t.maxs_x;
|
||||
if (t.maxs_y > cmaxs_y)
|
||||
cmaxs_y = t.maxs_y;
|
||||
if (t.maxs_z > cmaxs_z)
|
||||
cmaxs_z = t.maxs_z;
|
||||
}
|
||||
} while (1 );
|
||||
};
|
||||
|
||||
/*
|
||||
=====================
|
||||
SPECIAL DOORS
|
||||
thease doors can be opened by money or when power is on
|
||||
=====================
|
||||
*/
|
||||
|
||||
void() func_door_model =
|
||||
{
|
||||
place_model();
|
||||
}
|
||||
|
||||
void() func_door =
|
||||
|
||||
{
|
||||
|
||||
SetMovedir ();
|
||||
|
||||
self.max_health = self.health;
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
setorigin (self, self.origin);
|
||||
setmodel (self, self.model);
|
||||
self.classname = "door";
|
||||
|
||||
self.blocked = door_blocked;
|
||||
self.use = door_use;
|
||||
|
||||
|
||||
|
||||
if (!self.speed)
|
||||
self.speed = 100;
|
||||
if (!self.wait)
|
||||
self.wait = 3;
|
||||
if (!self.lip)
|
||||
self.lip = 8;
|
||||
if (!self.dmg)
|
||||
self.dmg = 2;
|
||||
|
||||
self.pos1 = self.origin;
|
||||
self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
|
||||
|
||||
// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
|
||||
// but spawn in the open position
|
||||
if (self.spawnflags & DOOR_START_OPEN)
|
||||
{
|
||||
setorigin (self, self.pos2);
|
||||
self.pos2 = self.pos1;
|
||||
self.pos1 = self.origin;
|
||||
}
|
||||
|
||||
self.state = STATE_BOTTOM;
|
||||
|
||||
if (self.health)
|
||||
{
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_die = door_killed;
|
||||
}
|
||||
|
||||
self.touch = door_touch;
|
||||
|
||||
// LinkDoors can't be done until all of the doors have been spawned, so
|
||||
// the sizes can be detected properly.
|
||||
self.think = LinkDoors;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
||||
|
||||
void() func_door_nzp =
|
||||
{
|
||||
#ifdef PSP
|
||||
if (!self.renderamt)
|
||||
self.renderamt = 255;
|
||||
|
||||
if (!self.rendermode)
|
||||
self.rendermode = 4;
|
||||
|
||||
if (!self.rendercolor)
|
||||
self.rendercolor = '0 0 0';
|
||||
|
||||
if (!self.mapversion)
|
||||
self.mapversion = 0;
|
||||
|
||||
if (!self.ammo)
|
||||
self.ammo = 0; //thease are just here because they can be sp there is no error message. serve no real purpose
|
||||
#endif
|
||||
|
||||
// naievil (FIXME) ^^^^ hl rendermodes, mapversion
|
||||
makevectors(self.angles);
|
||||
SetMovedir ();
|
||||
|
||||
self.target2 = self.target;
|
||||
self.target3 = self.target;
|
||||
self.target4 = self.target;
|
||||
self.target5 = self.target;
|
||||
self.target6 = self.target;
|
||||
self.target7 = self.target;
|
||||
self.target8 = self.target;
|
||||
|
||||
self.max_health = self.health;
|
||||
self.solid = SOLID_BSP;
|
||||
self.movetype = MOVETYPE_PUSH;
|
||||
self.oldmodel = self.model;
|
||||
self.oldorigin = self.origin;
|
||||
self.oldstate = self.state;
|
||||
setorigin (self, self.origin);
|
||||
setmodel (self, self.model);
|
||||
|
||||
self.blocked = door_blocked;
|
||||
self.use = door_use;
|
||||
|
||||
if (self.cost)
|
||||
{
|
||||
self.classname = "door_nzp_cost";
|
||||
// total_buy = total_buy +1;
|
||||
}
|
||||
else
|
||||
self.classname = "door_nzp";
|
||||
|
||||
if (!self.speed)
|
||||
self.speed = 100;
|
||||
if (!self.wait)
|
||||
self.wait = 3;
|
||||
if (!self.lip)
|
||||
self.lip = 8;
|
||||
if (!self.dmg)
|
||||
self.dmg = 2;
|
||||
|
||||
// only rotate on the Y axis.. potentially change?
|
||||
if (self.spawnflags & 256) {
|
||||
self.pos1 = self.angles;
|
||||
self.pos2 = self.pos1;
|
||||
self.pos2_y = self.pos1_y + self.distance;
|
||||
} else {
|
||||
self.pos1 = self.origin;
|
||||
self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
|
||||
}
|
||||
|
||||
// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
|
||||
// but spawn in the open position
|
||||
if (self.spawnflags & DOOR_START_OPEN)
|
||||
{
|
||||
setorigin (self, self.pos2);
|
||||
self.pos2 = self.pos1;
|
||||
self.pos1 = self.origin;
|
||||
}
|
||||
|
||||
self.state = STATE_BOTTOM;
|
||||
|
||||
if (self.health)
|
||||
{
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.th_die = door_killed;
|
||||
}
|
||||
|
||||
|
||||
self.touch = door_touch;
|
||||
|
||||
// LinkDoors can't be done until all of the doors have been spawned, so
|
||||
// the sizes can be detected properly.
|
||||
self.think = LinkDoors;
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
};
|
118
source/server/entities/lights.qc
Normal file
118
source/server/entities/lights.qc
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
server/entities/lights.qc
|
||||
|
||||
Spawns and handles Quake's lights and torches
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
float START_OFF = 1; // Light on/off spawnflag
|
||||
void() Light_setup; // Definition from Lights.qc
|
||||
|
||||
void(string modelname) Precache_Set = // Precache model, and set myself to it
|
||||
{
|
||||
precache_model(modelname);
|
||||
setmodel(self, modelname);
|
||||
};
|
||||
|
||||
|
||||
void() light = // Basic Light
|
||||
{
|
||||
Light_setup(); // Setup Light
|
||||
}
|
||||
|
||||
void() light_fluoro = // Light with hum ambient
|
||||
{
|
||||
Light_setup(); // Setup Light
|
||||
};
|
||||
|
||||
void() light_environment = // Basic Light
|
||||
{
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
}
|
||||
|
||||
void() light_fluorospark = // Light with buzz ambient
|
||||
{
|
||||
Light_setup(); // Setup Light
|
||||
};
|
||||
|
||||
void() light_globe = // Light with visible globe
|
||||
{
|
||||
Precache_Set("progs/s_light.spr"); // Set model
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
}
|
||||
|
||||
void() light_torch_small_walltorch = // Light with visible wall torch
|
||||
{
|
||||
Precache_Set("progs/flame.mdl"); // Set model
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
};
|
||||
|
||||
void() light_flame_small_yellow = // Light with small flame & fire sound
|
||||
{
|
||||
Precache_Set("progs/flame2.mdl"); // Set model
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
};
|
||||
|
||||
void() light_flame_large_yellow = // Light with larger flame & fire sound
|
||||
{
|
||||
Precache_Set("progs/flame2.mdl"); // Set model
|
||||
self.frame = 1; // Switch to second frame (large)
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
};
|
||||
|
||||
void() light_flame_small_white = // Light with small flame & fire sound
|
||||
{
|
||||
Precache_Set("progs/flame2.mdl"); // Set model
|
||||
makestatic(self); // Static entity. Never changes.
|
||||
};
|
||||
|
||||
void() Light_setup = // Set light on or off, as per spawnflags
|
||||
{
|
||||
if (self.style < 32) {
|
||||
return;
|
||||
} // Dont switch other styles.
|
||||
|
||||
if (self.spawnflags & START_OFF)
|
||||
lightstyle(self.style, "a"); // If light starts off, set it off.
|
||||
else
|
||||
lightstyle(self.style, "m"); // If light starts ON, turn in ON. Simple :)
|
||||
}
|
||||
|
||||
void() LightStyles_setup =
|
||||
{
|
||||
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
|
||||
|
||||
lightstyle(0,"m"); // Style 0: Normal
|
||||
lightstyle(1,"mmnmmommommnonmmonqnmmo"); // Style 1: Flicker
|
||||
lightstyle(2,"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); // Style 2: Slow Strong Pulse
|
||||
lightstyle(3,"mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); // Style 3: Candle
|
||||
lightstyle(4,"mamamamamama"); // Style 4: Fast Strobe
|
||||
lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj"); // Style 5: Gentle Pulse
|
||||
lightstyle(6,"nmonqnmomnmomomno"); // Style 6: Flicker 2
|
||||
lightstyle(7,"mmmaaaabcdefgmmmmaaaammmaamm"); // Style 7: Candle 2
|
||||
lightstyle(8,"mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); // Style 8: Candle 3
|
||||
lightstyle(9,"aaaaaaaazzzzzzzz"); // Style 9: Slow Strobe
|
||||
lightstyle(10,"mmamammmmammamamaaamammma"); // Style 10: Fluro
|
||||
lightstyle(11,"abcdefghijklmnopqrrqponmlkjihgfedcba"); // Style 11: Slow Pulse (no black)
|
||||
};
|
||||
|
2068
source/server/entities/machines.qc
Normal file
2068
source/server/entities/machines.qc
Normal file
File diff suppressed because it is too large
Load diff
1151
source/server/entities/map_entities.qc
Normal file
1151
source/server/entities/map_entities.qc
Normal file
File diff suppressed because it is too large
Load diff
576
source/server/entities/powerups.qc
Normal file
576
source/server/entities/powerups.qc
Normal file
|
@ -0,0 +1,576 @@
|
|||
/*
|
||||
server/entities/powerups.qc
|
||||
|
||||
powerup logic
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
.float zombie_drop_id;
|
||||
.float flashtime;
|
||||
.float flash_step;
|
||||
|
||||
// the powerup's model
|
||||
string(float type) getPowerupModel =
|
||||
{
|
||||
switch(type) {
|
||||
case 1: return "models/pu/maxammo!.mdl"; break;
|
||||
case 2: return "models/pu/x2!.mdl"; break;
|
||||
case 3: return "models/pu/instakill!.mdl"; break;
|
||||
case 4: return "models/pu/nuke!.mdl"; break;
|
||||
case 5: return "models/pu/carpenter!.mdl"; break;
|
||||
case 6: return "models/pu/perkbottle!.mdl"; break;
|
||||
default: return ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
// the powerup's pick up voice clip
|
||||
string(float type) getPowerupVO =
|
||||
{
|
||||
switch(type) {
|
||||
case 1: return "sounds/pu/maxammo.wav"; break;
|
||||
case 2: return "sounds/pu/double_points.wav"; break;
|
||||
case 3: return "sounds/pu/insta_kill.wav"; break;
|
||||
case 4: return "sounds/pu/nuke.wav"; break;
|
||||
case 5: return "sounds/pu/carpenter.wav"; break;
|
||||
default: return ""; break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void() maxammo =
|
||||
{
|
||||
entity tempe, temp;
|
||||
|
||||
tempe = find (world, classname, "player");
|
||||
while (tempe)
|
||||
{
|
||||
if (!tempe.downed)
|
||||
{
|
||||
if (tempe.weapon)
|
||||
{
|
||||
tempe.currentammo = getWeaponAmmo(tempe.weapon);
|
||||
if (!tempe.currentmag)
|
||||
{
|
||||
temp = self;
|
||||
self = tempe;
|
||||
W_Reload(S_BOTH);
|
||||
self = temp;
|
||||
}
|
||||
}
|
||||
if (tempe.secondaryweapon)
|
||||
tempe.secondaryammo = getWeaponAmmo(tempe.secondaryweapon);
|
||||
|
||||
tempe.primary_grenades = 4;
|
||||
|
||||
if (tempe.grenades & 2)
|
||||
tempe.secondary_grenades = 2;
|
||||
}
|
||||
#ifdef PC
|
||||
ScrollText("MAX AMMO!", tempe);
|
||||
#endif
|
||||
#ifdef PSP
|
||||
nzp_maxammo();
|
||||
#endif
|
||||
|
||||
tempe = find (tempe, classname, "player");
|
||||
}
|
||||
}
|
||||
|
||||
void() nuke_finalize =
|
||||
{
|
||||
entity players;
|
||||
|
||||
// give 'The F Bomb'
|
||||
#ifndef NX
|
||||
if (self.kills == 1) {
|
||||
GiveAchievement(4);
|
||||
}
|
||||
#endif
|
||||
|
||||
// award points
|
||||
players = find(world,classname,"player");
|
||||
while(players)
|
||||
{
|
||||
addmoney(players, 400*nuke_powerups_activated, 1);
|
||||
players = find(players,classname,"player");
|
||||
}
|
||||
|
||||
nuke_powerup_active = false;
|
||||
}
|
||||
|
||||
void() do_nuke_kill =
|
||||
{
|
||||
// back up ourselves
|
||||
entity oldself;
|
||||
oldself = self;
|
||||
|
||||
// switch to goaldummy, is goaldummy world?
|
||||
if (self.goaldummy == world) {
|
||||
nuke_finalize();
|
||||
remove(self);
|
||||
return;
|
||||
} else {
|
||||
self = self.goaldummy;
|
||||
}
|
||||
|
||||
// kill a target
|
||||
self.th_die();
|
||||
|
||||
// restore self
|
||||
self = oldself;
|
||||
|
||||
// increment kills
|
||||
self.kills++;
|
||||
|
||||
// find new target
|
||||
self.goaldummy = findfloat(self.goaldummy, iszomb, 1);
|
||||
|
||||
self.nextthink = (rint((random() * 6) + 1)/10) + time; // random number from 0.1 to 0.7
|
||||
}
|
||||
|
||||
void() nuke =
|
||||
{
|
||||
// if there's already one active, just increment the point multiplier
|
||||
if (nuke_powerup_active == true) {
|
||||
nuke_powerups_activated++;
|
||||
return;
|
||||
}
|
||||
|
||||
// mark nuke as being active, to prevent zombie damage and spawning.
|
||||
nuke_powerup_active = true;
|
||||
nuke_powerup_spawndelay = time + 3;
|
||||
nuke_powerups_activated = 1;
|
||||
|
||||
// create our watcher entity
|
||||
entity nuke_watcher;
|
||||
nuke_watcher = spawn();
|
||||
nuke_watcher.goaldummy = findfloat(world, iszomb, 1);
|
||||
|
||||
nuke_watcher.think = do_nuke_kill;
|
||||
nuke_watcher.nextthink = (rint((random() * 6) + 1)/10) + time; // random number from 0.1 to 0.7
|
||||
}
|
||||
|
||||
void() carpenter =
|
||||
{
|
||||
local entity oldself;
|
||||
local entity who;
|
||||
oldself = self;
|
||||
|
||||
who = find(world,classname,"window");
|
||||
while(who != world)
|
||||
{
|
||||
if(who.health < 6 && who.health != -10)//-10 is for boardless windows
|
||||
{
|
||||
self = who;
|
||||
window_carpenter_1 ();
|
||||
who.health = 6;
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
who = find(who,classname,"window");
|
||||
}
|
||||
|
||||
who = find(world,classname,"player");
|
||||
while(who)
|
||||
{
|
||||
addmoney(who, 200, 1);
|
||||
|
||||
who = find(who,classname,"player");
|
||||
}
|
||||
total_windows_down = 0;
|
||||
}
|
||||
|
||||
void(entity who) give_perkdrop_logic =
|
||||
{
|
||||
// Return here if we already have all of the Perks
|
||||
if ((who.perks & P_REVIVE) && (who.perks & P_JUG) && (who.perks & P_SPEED) && (who.perks & P_DOUBLE) &&
|
||||
(who.perks & P_FLOP) && (who.perks & P_STAMIN) && (who.perks & P_DEAD) && (who.perks & P_MULE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
local float perk;
|
||||
perk = 0;
|
||||
|
||||
while(perk == 0) {
|
||||
local float num;
|
||||
num = rint((random() * 7)) + 1;
|
||||
|
||||
switch(num) {
|
||||
case 1:
|
||||
if (!(who.perks & P_JUG)) {
|
||||
perk = 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!(who.perks & P_DOUBLE)) {
|
||||
perk = 2;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!(who.perks & P_SPEED)) {
|
||||
perk = 4;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (!(who.perks & P_REVIVE)) {
|
||||
perk = 8;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (!(who.perks & P_FLOP)) {
|
||||
perk = 16;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (!(who.perks & P_STAMIN)) {
|
||||
perk = 32;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (!(who.perks & P_DEAD)) {
|
||||
perk = 64;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (!(who.perks & P_MULE)) {
|
||||
perk = 128;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
who.perks = who.perks | perk;
|
||||
}
|
||||
SetPerk(who, who.perks);
|
||||
}
|
||||
|
||||
void() give_perk =
|
||||
{
|
||||
// Individual Power-Up
|
||||
if (self.style == 1) {
|
||||
give_perkdrop_logic(other);
|
||||
}
|
||||
// OUR Power-Up
|
||||
else {
|
||||
local entity who;
|
||||
who = find(world, classname, "player");
|
||||
|
||||
while(who) {
|
||||
give_perkdrop_logic(who);
|
||||
who = find(who, classname, "player");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void() powerup_flash =
|
||||
{
|
||||
if(self.flash_step == 0)
|
||||
{
|
||||
self.flash_step = 1;
|
||||
self.flashtime = time + 3;
|
||||
self.nextthink = time + 0.6;
|
||||
}
|
||||
else if(self.flash_step == 1)
|
||||
{
|
||||
self.nextthink = time + 0.6;
|
||||
|
||||
if(self.flashtime < time)
|
||||
{
|
||||
self.flash_step = 2;
|
||||
self.nextthink = time + 0.3;
|
||||
self.flashtime = time + 3;
|
||||
}
|
||||
|
||||
}
|
||||
else if(self.flash_step == 2)
|
||||
{
|
||||
self.nextthink = time + 0.3;
|
||||
|
||||
if(self.flashtime < time)
|
||||
{
|
||||
self.flash_step = 3;
|
||||
self.nextthink = time + 0.15;
|
||||
self.flashtime = time + 3;
|
||||
}
|
||||
|
||||
}
|
||||
else if(self.flash_step == 3)
|
||||
{
|
||||
self.nextthink = time + 0.15;
|
||||
if(self.flashtime < time)
|
||||
{
|
||||
// moto - we used to setmodel blank here too, but it caused errors with the sprite.
|
||||
remove(self.owner);
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(self.model == "") {
|
||||
setmodel(self, getPowerupModel(self.zombie_drop_id));
|
||||
} else {
|
||||
setmodel(self,"");
|
||||
}
|
||||
};
|
||||
|
||||
void() powerup_play_sound =
|
||||
{
|
||||
// play the VO clip if its not the perk bottle
|
||||
if (self.zombie_drop_id != 6)
|
||||
sound(self, CHAN_VOICE, self.powerup_vo, 1, ATTN_NONE);
|
||||
|
||||
// finally, remove the (invisible/inactive) powerup.
|
||||
remove(self);
|
||||
}
|
||||
|
||||
void() powerup_touch =
|
||||
{
|
||||
local float t;
|
||||
|
||||
t = random();
|
||||
|
||||
if(other.classname == "player")
|
||||
{
|
||||
// pickup sound
|
||||
sound(self.owner,CHAN_VOICE,"sounds/pu/pickup.wav",1,ATTN_NONE);
|
||||
|
||||
// add a slight delay before VO play
|
||||
self.think = powerup_play_sound;
|
||||
self.nextthink = time + 1;
|
||||
|
||||
// hide powerup until we remove (after sound)
|
||||
setmodel(self, "");
|
||||
self.effects = 0;
|
||||
self.touch = SUB_Null;
|
||||
remove(self.owner);
|
||||
|
||||
// slight screen flash
|
||||
stuffcmd(other, "bf\n");
|
||||
|
||||
// powerup effects
|
||||
switch(self.zombie_drop_id) {
|
||||
// max ammo
|
||||
case 1:
|
||||
maxammo();
|
||||
break;
|
||||
// double points
|
||||
case 2:
|
||||
x2_finished = time + 30;
|
||||
other.x2_icon = true;
|
||||
break;
|
||||
// insta kill
|
||||
case 3:
|
||||
instakill_finished = time + 30;
|
||||
other.insta_icon = true;
|
||||
break;
|
||||
// nuke
|
||||
case 4:
|
||||
nuke();
|
||||
break;
|
||||
// carpenter
|
||||
case 5:
|
||||
carpenter();
|
||||
break;
|
||||
// free perk
|
||||
case 6:
|
||||
give_perk();
|
||||
break;
|
||||
// broken!
|
||||
default:
|
||||
centerprint(other, strcat("INVALID POWER-UP ID: ", ftos(self.zombie_drop_id)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() sparkle_think =
|
||||
{
|
||||
local float f;
|
||||
f = self.frame;
|
||||
local float r;
|
||||
while(f == self.frame)
|
||||
{
|
||||
r = random();
|
||||
r = ((r > 0.2) ? 1 : 0) + ((r > 0.4) ? 1 : 0) + ((r > 0.6) ? 1 : 0) + ((r > 0.8) ? 1 : 0);
|
||||
f = r;
|
||||
}
|
||||
self.frame = f;
|
||||
|
||||
self.think = sparkle_think;
|
||||
self.nextthink = time + 0.1;
|
||||
|
||||
if(self.calc_time <= time)
|
||||
{
|
||||
sound(self,CHAN_VOICE,"sounds/pu/powerup.wav",0.6,ATTN_NORM);
|
||||
self.calc_time = time + 2.998;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// GetPowerupID()
|
||||
// Returns a powerup id, checks if the game allows for
|
||||
// one and if requirements for said powerup are met.
|
||||
//
|
||||
float() GetPowerupID =
|
||||
{
|
||||
float found;
|
||||
float carpenter_able;
|
||||
float perk_able;
|
||||
float id;
|
||||
|
||||
id = carpenter_able = perk_able = 0;
|
||||
|
||||
// Check if we can get a carpenter or a free perk drop
|
||||
if (total_windows_down >= 5)
|
||||
carpenter_able = true;
|
||||
if (rounds >= 15)
|
||||
perk_able = true;
|
||||
|
||||
float total_powerups = 5; // nuke, insta, 2x, maxammo, carpenter, free perk
|
||||
|
||||
// Start ID loop
|
||||
found = false;
|
||||
while(found == false) {
|
||||
float t = random();
|
||||
|
||||
// loop through all IDs
|
||||
for (float i = 0; i < total_powerups + 1; i++) {
|
||||
// check if the ID we got was viable
|
||||
if (t > (i/total_powerups)) {
|
||||
switch(i) {
|
||||
case 1:
|
||||
found = true;
|
||||
id = i;
|
||||
break;
|
||||
case 2:
|
||||
found = true;
|
||||
id = i;
|
||||
break;
|
||||
case 3:
|
||||
found = true;
|
||||
id = i;
|
||||
break;
|
||||
case 4:
|
||||
found = true;
|
||||
id = i;
|
||||
break;
|
||||
case 5:
|
||||
if (carpenter_able) {
|
||||
found = true;
|
||||
id = i;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
/*if (perk_able) {
|
||||
found = true;
|
||||
id = i;
|
||||
}*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
float last_pu;
|
||||
void(vector where, float type) Spawn_Powerup =
|
||||
{
|
||||
entity new_powerup;
|
||||
float id;
|
||||
|
||||
new_powerup = spawn();
|
||||
new_powerup.origin = where;
|
||||
setorigin(new_powerup, new_powerup.origin);
|
||||
new_powerup.solid = SOLID_TRIGGER;
|
||||
new_powerup.classname = "item_powerup";
|
||||
|
||||
|
||||
setsize (new_powerup, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
new_powerup.movetype = MOVETYPE_NONE;
|
||||
Light_Green(new_powerup);
|
||||
|
||||
//=================== Sparkle Effects =====================
|
||||
|
||||
entity twlt_Sparkle;
|
||||
twlt_Sparkle = spawn();
|
||||
new_powerup.owner = twlt_Sparkle; //just a reference so power up can delete the sparkle later on
|
||||
|
||||
setorigin(twlt_Sparkle,where);
|
||||
#ifndef PC
|
||||
setmodel(twlt_Sparkle,"models/sprites/sprkle.spr");
|
||||
#endif
|
||||
twlt_Sparkle.think = sparkle_think;
|
||||
twlt_Sparkle.nextthink = time + 0.1;
|
||||
sound(twlt_Sparkle,CHAN_VOICE,"sounds/pu/powerup.wav",0.6,ATTN_NORM);
|
||||
|
||||
sound(new_powerup,CHAN_AUTO,"sounds/pu/drop.wav",1,ATTN_NONE);
|
||||
|
||||
//========================================================
|
||||
|
||||
// Specific Power-Ups (for dogs)
|
||||
if (type) {
|
||||
setmodel(new_powerup, getPowerupModel(type));
|
||||
new_powerup.zombie_drop_id = type;
|
||||
new_powerup.powerup_vo = getPowerupVO(type);
|
||||
} else {
|
||||
// Grab a powerup ID
|
||||
id = GetPowerupID();
|
||||
|
||||
// Should perk drops be individual?
|
||||
if (id == 6) {
|
||||
// Yes!
|
||||
if (random() > (1/2)) {
|
||||
// Set Style and make light Blue to symbolize it is an individual drop
|
||||
// TODO: Make a sprite too??
|
||||
new_powerup.style = 1;
|
||||
Light_None(new_powerup);
|
||||
Light_Blue(new_powerup);
|
||||
}
|
||||
// No!
|
||||
else {
|
||||
// failsafe
|
||||
new_powerup.style = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, assign the id and model to our id.
|
||||
setmodel(new_powerup, getPowerupModel(id));
|
||||
new_powerup.zombie_drop_id = id;
|
||||
new_powerup.powerup_vo = getPowerupVO(id);
|
||||
}
|
||||
|
||||
last_pu = new_powerup.zombie_drop_id;
|
||||
new_powerup.touch = powerup_touch;
|
||||
|
||||
new_powerup.think = powerup_flash;
|
||||
new_powerup.nextthink = time + 21;
|
||||
totalpowerups++;
|
||||
}
|
131
source/server/entities/sounds.qc
Normal file
131
source/server/entities/sounds.qc
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
server/entities/sounds.qc
|
||||
|
||||
Sound Entities for Maps
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#define AMBIENT_SOUND_STATIC 0 // medium radius attenuation
|
||||
#define AMBIENT_SOUND_EVERYWHERE 1
|
||||
#define AMBIENT_SOUND_SMALLRADIUS 2
|
||||
#define AMBIENT_SOUND_MEDIUMRADIUS 4
|
||||
#define AMBIENT_SOUND_LARGERADIUS 8
|
||||
#define AMBIENT_SOUND_START_SILENT 16
|
||||
#define AMBIENT_SOUND_NOT_LOOPING 32
|
||||
|
||||
void() ambient_use =
|
||||
{
|
||||
// volume can only be between 0 - 1 in quake (maybe FTE supports higher.. not sure)
|
||||
if (self.health > 1)
|
||||
self.health = 1;
|
||||
|
||||
if (self.team == 1) {
|
||||
if (self.spawnflags & AMBIENT_SOUND_NOT_LOOPING) {
|
||||
sound(self, CHAN_VOICE, self.message, self.health, self.stance);
|
||||
|
||||
}
|
||||
else {
|
||||
sound(self, CHAN_VOICE, self.message, self.health, self.stance);
|
||||
ambientsound(self.origin, self.message, self.health, self.stance);
|
||||
}
|
||||
self.team = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.spawnflags & AMBIENT_SOUND_NOT_LOOPING) {
|
||||
sound (self, CHAN_VOICE, self.message, 0, self.stance);
|
||||
}
|
||||
else {
|
||||
sound (self, CHAN_VOICE, self.message, 0, self.stance);
|
||||
ambientsound (self.origin, self.message, 0, self.stance);
|
||||
}
|
||||
self.team = 1;
|
||||
}
|
||||
|
||||
self.use = SUB_Null;
|
||||
};
|
||||
|
||||
void () ambient_generic =
|
||||
{
|
||||
local string link;
|
||||
|
||||
// moto - FIXME: typically this is set to upper-case but NX and PSP lack strtoupper(); assume lower-case!
|
||||
link = self.message;
|
||||
|
||||
if (link == "nolink") {
|
||||
if (substring(self.message, 0, 1) == "*")
|
||||
self.message = substring(self.message , 1, strlen(self.message));
|
||||
|
||||
|
||||
if (substring(self.message , 0, 1) == "!" || substring(self.message , 0, 1) == "*") {
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
else
|
||||
precache_sound(self.message);
|
||||
}
|
||||
else {
|
||||
// append sounds/ if absent
|
||||
if (substring(self.message, 0, 7) != "sounds/")
|
||||
self.message = strcat("sounds/", self.message);
|
||||
|
||||
// always assume .wav extension..
|
||||
precache_sound(self.message);
|
||||
}
|
||||
|
||||
if (self.spawnflags & AMBIENT_SOUND_SMALLRADIUS)
|
||||
self.stance = ATTN_IDLE;
|
||||
else if (self.spawnflags & AMBIENT_SOUND_MEDIUMRADIUS)
|
||||
self.stance = ATTN_STATIC;
|
||||
else if (self.spawnflags & AMBIENT_SOUND_LARGERADIUS)
|
||||
self.stance = ATTN_NORM;
|
||||
else if (self.spawnflags & AMBIENT_SOUND_EVERYWHERE)
|
||||
self.stance = ATTN_NONE;
|
||||
else
|
||||
self.stance = ATTN_STATIC;
|
||||
|
||||
|
||||
if (self.health == 0) // final vol
|
||||
self.health = 1;
|
||||
|
||||
if (self.spawnflags & AMBIENT_SOUND_START_SILENT)
|
||||
self.team = 1;
|
||||
else
|
||||
ambientsound(self.origin, self.message, self.health, self.stance);
|
||||
|
||||
self.use = ambient_use;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// ambient_bgm() conversion
|
||||
//
|
||||
void() ambient_bgm =
|
||||
{
|
||||
// play everywhere
|
||||
self.spawnflags = 1;
|
||||
// sound to loop
|
||||
self.message = self.noise2;
|
||||
// call ambient_generic()
|
||||
ambient_generic();
|
||||
}
|
367
source/server/entities/sub_functions.qc
Normal file
367
source/server/entities/sub_functions.qc
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
server/entities/sub_functions.qc
|
||||
|
||||
entity/server utility subroutines
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
==============================
|
||||
SUB_UseTargets
|
||||
|
||||
the global "activator" should be set to the entity that initiated the firing.
|
||||
|
||||
If self.delay is set, a DelayedUse entity will be created that will actually
|
||||
do the SUB_UseTargets after that many seconds have passed.
|
||||
|
||||
Centerprints any self.message to the activator.
|
||||
|
||||
Removes all entities with a targetname that match self.killtarget,
|
||||
and removes them, so some events can remove other triggers.
|
||||
|
||||
Search for (string)targetname in all entities that
|
||||
match (string)self.target and call their .use function
|
||||
|
||||
==============================
|
||||
*/
|
||||
void() SUB_UseTargets;
|
||||
void(vector tdest, float tspeed, void() func) SUB_CalcMove;
|
||||
void() SUB_CalcMoveDone;
|
||||
void() DelayThink =
|
||||
{
|
||||
activator = self.enemy;
|
||||
SUB_UseTargets ();
|
||||
remove(self);
|
||||
};
|
||||
|
||||
void() SUB_UseTargets =
|
||||
{
|
||||
local entity t, stemp, otemp, act;
|
||||
float tempcount, temptotal, breakthis;
|
||||
string tempstring;
|
||||
|
||||
tempstring = "";
|
||||
temptotal = 0;
|
||||
tempcount = 0;
|
||||
breakthis = false;
|
||||
if (self.target2)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target3)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target4)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target5)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target6)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target7)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target8)
|
||||
tempcount = tempcount + 1;
|
||||
|
||||
while(tempcount > temptotal)
|
||||
{
|
||||
temptotal = temptotal + 1;
|
||||
if (temptotal == 1)
|
||||
tempstring = self.target;
|
||||
if (temptotal == 2)
|
||||
tempstring = self.target2;
|
||||
if (temptotal == 3)
|
||||
tempstring = self.target3;
|
||||
if (temptotal == 4)
|
||||
tempstring = self.target4;
|
||||
if (temptotal == 5)
|
||||
tempstring = self.target5;
|
||||
if (temptotal == 6)
|
||||
tempstring = self.target6;
|
||||
if (temptotal == 7)
|
||||
tempstring = self.target7;
|
||||
if (temptotal == 8)
|
||||
tempstring = self.target8;
|
||||
//
|
||||
// check for a delay
|
||||
//
|
||||
if (self.delay)
|
||||
{
|
||||
// create a temp object to fire at a later time
|
||||
t = spawn();
|
||||
t.classname = "DelayedUse";
|
||||
t.nextthink = time + self.delay;
|
||||
t.think = DelayThink;
|
||||
t.enemy = activator;
|
||||
t.message = self.message;
|
||||
t.killtarget = self.killtarget;
|
||||
t.target = self.target;
|
||||
t.target2 = self.target2;
|
||||
t.target3 = self.target3;
|
||||
t.target4 = self.target4;
|
||||
t.target5 = self.target5;
|
||||
t.target6 = self.target6;
|
||||
t.target7 = self.target7;
|
||||
t.target8 = self.target8;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// print the message
|
||||
//
|
||||
if (activator.classname == "player" && self.message != "")
|
||||
{
|
||||
centerprint (activator, self.message);
|
||||
}
|
||||
|
||||
//
|
||||
// kill the killtagets
|
||||
//
|
||||
if (self.killtarget)
|
||||
{
|
||||
t = world;
|
||||
do
|
||||
{
|
||||
t = find (t, targetname, self.killtarget);
|
||||
if (!t)
|
||||
breakthis = true;
|
||||
remove (t);
|
||||
} while (!breakthis);
|
||||
}
|
||||
|
||||
//
|
||||
// fire targets
|
||||
//
|
||||
if (tempstring)
|
||||
{
|
||||
act = activator;
|
||||
t = find (world, targetname, tempstring);
|
||||
breakthis = 0;
|
||||
while (!breakthis)
|
||||
{
|
||||
if (!t)
|
||||
{
|
||||
breakthis = true;
|
||||
}
|
||||
stemp = self;
|
||||
otemp = other;
|
||||
self = t;
|
||||
other = stemp;
|
||||
if (t.classname == "spawn_zombie_in")
|
||||
{
|
||||
t.classname = "spawn_zombie";
|
||||
}
|
||||
if (t.classname == "waypoint_s")
|
||||
{
|
||||
t.classname = "waypoint_s";
|
||||
}
|
||||
if (t.classname == "spawn_dog_in")
|
||||
t.classname = "spawn_dog";
|
||||
if (self.use != SUB_Null)
|
||||
{
|
||||
if (self.use)
|
||||
self.use();
|
||||
}
|
||||
self = stemp;
|
||||
other = otemp;
|
||||
activator = act;
|
||||
t = find (t, targetname, tempstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
=============
|
||||
SUB_CalcAngleMove
|
||||
|
||||
calculate self.avelocity and self.nextthink to reach destangle from
|
||||
self.angles rotating
|
||||
|
||||
The calling function should make sure self.think is valid
|
||||
===============
|
||||
*/
|
||||
void SUB_CalcAngleMove (vector destangle, float tspeed, void() func);
|
||||
void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt =
|
||||
{
|
||||
local entity stemp;
|
||||
stemp = self;
|
||||
self = ent;
|
||||
SUB_CalcAngleMove (destangle, tspeed, func);
|
||||
self = stemp;
|
||||
};
|
||||
|
||||
void SUB_CalcAngleMoveDone (void)
|
||||
{
|
||||
// After rotating, set angle to exact final angle
|
||||
self.angles = self.finalangle;
|
||||
self.avelocity = '0 0 0';
|
||||
self.nextthink = -1;
|
||||
if (self.think1)
|
||||
self.think1 ();
|
||||
}
|
||||
|
||||
void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
|
||||
{
|
||||
vector delta;
|
||||
float traveltime;
|
||||
|
||||
if (!tspeed)
|
||||
objerror ("No speed is defined!");
|
||||
|
||||
delta = destangle - self.angles;
|
||||
traveltime = vlen (delta) / tspeed;
|
||||
|
||||
self.avelocity = delta * (1 / traveltime);
|
||||
|
||||
self.think1 = func;
|
||||
self.finalangle = destangle;
|
||||
|
||||
self.think = SUB_CalcAngleMoveDone;
|
||||
self.nextthink = self.ltime + traveltime;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SUB_CalcMove
|
||||
|
||||
calculate self.velocity and self.nextthink to reach dest from
|
||||
self.origin traveling at speed
|
||||
===============
|
||||
*/
|
||||
void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt =
|
||||
{
|
||||
local entity stemp;
|
||||
stemp = self;
|
||||
self = ent;
|
||||
|
||||
SUB_CalcMove (tdest, tspeed, func);
|
||||
self = stemp;
|
||||
};
|
||||
|
||||
void(vector tdest, float tspeed, void() func) SUB_CalcMove =
|
||||
{
|
||||
local vector vdestdelta;
|
||||
local float len, traveltime;
|
||||
|
||||
if (!tspeed)
|
||||
objerror("No speed is defined!");
|
||||
|
||||
self.think1 = func;
|
||||
self.finaldest = tdest;
|
||||
self.think = SUB_CalcMoveDone;
|
||||
|
||||
if (tdest == self.origin)
|
||||
{
|
||||
self.velocity = '0 0 0';
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
return;
|
||||
}
|
||||
|
||||
// set destdelta to the vector needed to move
|
||||
vdestdelta = tdest - self.origin;
|
||||
|
||||
// calculate length of vector
|
||||
len = vlen (vdestdelta);
|
||||
|
||||
// divide by speed to get time to reach dest
|
||||
traveltime = len / tspeed;
|
||||
|
||||
if (traveltime < 0.1)
|
||||
{
|
||||
self.velocity = '0 0 0';
|
||||
self.nextthink = self.ltime + 0.1;
|
||||
return;
|
||||
}
|
||||
|
||||
// set nextthink to trigger a think when dest is reached
|
||||
self.nextthink = self.ltime + traveltime;
|
||||
|
||||
// scale the destdelta vector by the time spent traveling to get velocity
|
||||
self.velocity = vdestdelta * (1/traveltime); // qcc won't take vec/float
|
||||
};
|
||||
|
||||
/*
|
||||
============
|
||||
After moving, set origin to exact final destination
|
||||
============
|
||||
*/
|
||||
void() SUB_CalcMoveDone =
|
||||
{
|
||||
setorigin(self, self.finaldest);
|
||||
self.velocity = '0 0 0';
|
||||
self.nextthink = -1;
|
||||
if (self.think1)
|
||||
self.think1();
|
||||
};
|
||||
|
||||
|
||||
#ifdef PC
|
||||
//
|
||||
// HalfLife_DoRender()
|
||||
// Adds some support for HL rendermodes to FTE, made by
|
||||
// autonomous1 for 'quakelife'
|
||||
//
|
||||
|
||||
// Do *some* of the half-life render stuff.
|
||||
void () HalfLife_DoRender =
|
||||
{
|
||||
local vector osize, omins, omaxs, oabsmin, oabsmax;
|
||||
|
||||
if (self.rendercolor != '0 0 0') {} // ADDME
|
||||
|
||||
if (self.rendermode > 0)
|
||||
if (self.renderamt > 0) {
|
||||
self.alpha = self.renderamt/255;
|
||||
if (self.alpha == 0)
|
||||
self.alpha = .01;
|
||||
}
|
||||
else {
|
||||
self.rendermode = 2;
|
||||
}
|
||||
|
||||
if (self.rendermode == 2) {
|
||||
self.alpha = self.renderamt/255;
|
||||
if (self.alpha == 0) {
|
||||
//self.alpha = 0.01;
|
||||
osize = self.size;
|
||||
omins = self.mins;
|
||||
omaxs = self.maxs;
|
||||
oabsmin = self.absmin;
|
||||
oabsmax = self.absmax;
|
||||
|
||||
if (self.solid == SOLID_BSP) {
|
||||
|
||||
self.solid = SOLID_BBOX;
|
||||
}
|
||||
|
||||
//setmodel(self, string_null);
|
||||
self.size = osize;
|
||||
self.mins = omins;
|
||||
self.maxs = omaxs;
|
||||
self.absmin = oabsmin;
|
||||
self.absmax = oabsmax;
|
||||
//setorigin(self, self.origin);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
344
source/server/entities/triggers.qc
Normal file
344
source/server/entities/triggers.qc
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
server/entities/triggers.qc
|
||||
|
||||
Misc. Trigger functions
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#define SPAWNFLAG_NOMESSAGE 1
|
||||
#define SPAWNFLAG_NOTOUCH 1
|
||||
|
||||
// the wait time has passed, so set back up for another activation
|
||||
void() multi_wait =
|
||||
{
|
||||
if (self.max_health)
|
||||
{
|
||||
self.health = self.max_health;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.solid = SOLID_BBOX;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// the trigger was just touched/killed/used
|
||||
// self.enemy should be set to the activator so it can be held through a delay
|
||||
// so wait for the delay time before firing
|
||||
void() multi_trigger =
|
||||
{
|
||||
if (self.nextthink > time)
|
||||
{
|
||||
return; // already been triggered
|
||||
}
|
||||
|
||||
if (self.noise)
|
||||
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
||||
|
||||
// don't trigger again until reset
|
||||
self.takedamage = DAMAGE_NO;
|
||||
|
||||
activator = self.enemy;
|
||||
|
||||
SUB_UseTargets();
|
||||
|
||||
if (self.wait > 0)
|
||||
{
|
||||
self.think = multi_wait;
|
||||
self.nextthink = time + self.wait;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't just remove(self) here, because this is a touch function
|
||||
// called while C code is looping through area links...
|
||||
self.touch = SUB_Null;
|
||||
self.nextthink = time + 0.1;
|
||||
self.think = SUB_Remove;
|
||||
}
|
||||
};
|
||||
|
||||
void() multi_killed =
|
||||
{
|
||||
// motolegacy - FIXME
|
||||
//self.enemy = damage_attacker;
|
||||
multi_trigger();
|
||||
};
|
||||
|
||||
void() multi_use =
|
||||
{
|
||||
self.enemy = activator;
|
||||
multi_trigger();
|
||||
};
|
||||
|
||||
void() multi_touch =
|
||||
{
|
||||
if (other.classname != "player")
|
||||
return;
|
||||
|
||||
// if the trigger has an angles field, check player's facing direction
|
||||
if (self.movedir != '0 0 0')
|
||||
{
|
||||
makevectors (other.angles);
|
||||
if (v_forward * self.movedir < 0)
|
||||
return; // not facing the right way
|
||||
}
|
||||
|
||||
self.enemy = other;
|
||||
multi_trigger();
|
||||
};
|
||||
|
||||
void() SetMovedir =
|
||||
{
|
||||
if (self.angles == '0 -1 0')
|
||||
self.movedir = '0 0 1';
|
||||
else if (self.angles == '0 -2 0')
|
||||
self.movedir = '0 0 -1';
|
||||
else
|
||||
{
|
||||
makevectors (self.angles);
|
||||
self.movedir = v_forward;
|
||||
}
|
||||
|
||||
self.angles = '0 0 0';
|
||||
};
|
||||
|
||||
void() InitTrigger =
|
||||
{
|
||||
// trigger angles are used for one-way touches. An angle of 0 is assumed
|
||||
// to mean no restrictions, so use a yaw of 360 instead.
|
||||
if (self.angles != '0 0 0')
|
||||
SetMovedir ();
|
||||
self.solid = SOLID_TRIGGER;
|
||||
setmodel (self, self.model); // set size and link into world
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.modelindex = 0;
|
||||
self.model = "";
|
||||
};
|
||||
|
||||
#ifndef PSP
|
||||
entity last_act_trigger;
|
||||
void() trigger_activator_touch =
|
||||
{
|
||||
other.cost = other.cost +1; //hack, we can only touch one of thease at the time
|
||||
if (other.classname != "player" || last_act_trigger == self || other.cost > 1)
|
||||
return;
|
||||
last_act_trigger = self;
|
||||
|
||||
entity t;
|
||||
float tempcount, temptotal,breakthis;
|
||||
string tempstring;
|
||||
temptotal = 0;
|
||||
breakthis = 0;
|
||||
tempcount = 1;
|
||||
tempstring = "";
|
||||
t = world;
|
||||
do
|
||||
{
|
||||
t = find (t, classname, "spawn_zombie");
|
||||
if (!t)
|
||||
{
|
||||
breakthis = 1;
|
||||
}
|
||||
if (t.classname == "spawn_zombie")
|
||||
{
|
||||
t.classname = "spawn_zombie_away";
|
||||
/*if (cvar("developer"))
|
||||
setmodel(t, "progs/player.mdl");*/
|
||||
}
|
||||
} while (!breakthis);
|
||||
|
||||
if (self.target2)
|
||||
tempcount =+ 1;
|
||||
if (self.target3)
|
||||
tempcount =+ 1;
|
||||
if (self.target4)
|
||||
tempcount =+ 1;
|
||||
if (self.target5)
|
||||
tempcount =+ 1;
|
||||
if (self.target6)
|
||||
tempcount =+ 1;
|
||||
if (self.target7)
|
||||
tempcount =+ 1;
|
||||
if (self.target8)
|
||||
tempcount =+ 1;
|
||||
if (self.target2)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target3)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target4)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target5)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target6)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target7)
|
||||
tempcount = tempcount + 1;
|
||||
if (self.target8)
|
||||
tempcount = tempcount + 1;
|
||||
|
||||
while(tempcount > temptotal)
|
||||
{
|
||||
temptotal = temptotal + 1;
|
||||
if (temptotal == 1)
|
||||
tempstring = self.target;
|
||||
if (temptotal == 2)
|
||||
tempstring = self.target2;
|
||||
if (temptotal == 3)
|
||||
tempstring = self.target3;
|
||||
if (temptotal == 4)
|
||||
tempstring = self.target4;
|
||||
if (temptotal == 5)
|
||||
tempstring = self.target5;
|
||||
if (temptotal == 6)
|
||||
tempstring = self.target6;
|
||||
if (temptotal == 7)
|
||||
tempstring = self.target7;
|
||||
if (temptotal == 8)
|
||||
tempstring = self.target8;
|
||||
if (tempstring)
|
||||
{
|
||||
t = find (world, targetname, tempstring);
|
||||
breakthis = 0;
|
||||
while (!breakthis)
|
||||
{
|
||||
if (!t)
|
||||
{
|
||||
breakthis = true;
|
||||
}
|
||||
if (t.classname == "spawn_zombie_away")
|
||||
{
|
||||
t.classname = "spawn_zombie";
|
||||
/*if (cvar("developer"))
|
||||
setmodel(t, "progs/ai/zfull.mdl");*/
|
||||
}
|
||||
t = find (t, targetname, tempstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void() trigger_activator =
|
||||
{
|
||||
InitTrigger ();
|
||||
self.touch = trigger_activator_touch;
|
||||
}
|
||||
#endif
|
||||
|
||||
void() use_wall_weapon =
|
||||
{
|
||||
if (self.enemy)
|
||||
return;
|
||||
entity newent;
|
||||
|
||||
newent = spawn();
|
||||
|
||||
newent.movetype = MOVETYPE_NONE; // so it doesn't get pushed by anything
|
||||
newent.solid=SOLID_NOT;
|
||||
newent.classname = "wall_weapon";
|
||||
setorigin(newent, self.origin);
|
||||
setmodel (newent, GetWeaponModel(self.sequence + 1, 1));
|
||||
setsize (newent, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
newent.angles = self.angles;
|
||||
|
||||
self.enemy = newent;
|
||||
}
|
||||
|
||||
void() weapon_wall =
|
||||
{
|
||||
precache_model ("models/misc/chalk.mdl");
|
||||
|
||||
setmodel (self, "models/misc/chalk.mdl");
|
||||
self.skin = 0;
|
||||
setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
||||
|
||||
self.frame = self.sequence;
|
||||
self.use = use_wall_weapon;
|
||||
self.classname = "weapon_wall";
|
||||
//self.effects = EF_WEPLIGHT;
|
||||
}
|
||||
|
||||
/* ===================
|
||||
Custom Teddy Triggers
|
||||
===================*/
|
||||
|
||||
void() teddy_react =
|
||||
{
|
||||
local entity t;
|
||||
if (self.spawnflags & 1) {
|
||||
t = find (world, teddyremovetarget, self.target);
|
||||
|
||||
if (t)
|
||||
remove(t);
|
||||
}
|
||||
|
||||
remove(self); //this was present in the patch, i like it.
|
||||
}
|
||||
|
||||
/*
|
||||
Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
|
||||
If "delay" is set, the trigger waits some time after activating before firing.
|
||||
"wait" : Seconds between triggerings. (.2 default)
|
||||
If notouch is set, the trigger is only fired by other entities, not by touching.
|
||||
NOTOUCH has been obsoleted by trigger_relay!
|
||||
set "message" to text string
|
||||
*/
|
||||
void() trigger_multiple =
|
||||
{
|
||||
if (!self.wait)
|
||||
self.wait = 0.2;
|
||||
|
||||
self.use = multi_use;
|
||||
|
||||
InitTrigger ();
|
||||
|
||||
if(self.health)
|
||||
{
|
||||
if (self.spawnflags & SPAWNFLAG_NOTOUCH)
|
||||
objerror("health and notouch don't make sense\n");
|
||||
self.max_health = self.health;
|
||||
self.th_die = multi_killed;
|
||||
self.takedamage = DAMAGE_YES;
|
||||
self.solid = SOLID_BBOX;
|
||||
setorigin(self, self.origin); // make sure it links into the world
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(self.spawnflags & SPAWNFLAG_NOTOUCH))
|
||||
{
|
||||
self.touch = multi_touch;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching
|
||||
"targetname". If "health" is set, the trigger must be killed to activate.
|
||||
If notouch is set, the trigger is only fired by other entities, not by touching.
|
||||
if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
|
||||
if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0.
|
||||
set "message" to text string
|
||||
*/
|
||||
void() trigger_once =
|
||||
{
|
||||
self.wait = -1;
|
||||
|
||||
trigger_multiple();
|
||||
}
|
379
source/server/entities/window.qc
Normal file
379
source/server/entities/window.qc
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
server/entities/window.qc
|
||||
|
||||
barricades
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
.float rebuild_time;
|
||||
|
||||
void() spawn_boxes =
|
||||
{
|
||||
makevectors(self.angles);
|
||||
|
||||
self.box1 = self.origin + (v_forward * -30) + (v_up * -32);
|
||||
self.box2 = self.box1 + (v_right * 30);
|
||||
self.box3 = self.box1 + (v_right * -30);
|
||||
self.idlebox = self.box1 + (v_forward * -30);
|
||||
|
||||
self.hop_spot = self.origin + v_forward * 40;
|
||||
self.hop_spot_z -= 30;//We want this to be a little bit above the ground still
|
||||
};
|
||||
|
||||
void() screen_shake =
|
||||
{
|
||||
local float r,s,zoom_factor;
|
||||
r = crandom();
|
||||
s = random();
|
||||
if (self.enemy.zoom == 2 || self.enemy.zoom == 1)
|
||||
zoom_factor = 0.5;
|
||||
else
|
||||
zoom_factor = 1;
|
||||
|
||||
#ifdef PSP
|
||||
self.enemy.punchangle_y = r * 8 * zoom_factor;
|
||||
self.enemy.punchangle_x = (4 + (s * 4)) * zoom_factor;
|
||||
#else
|
||||
self.enemy.punchangle_y = r * 4 * zoom_factor;
|
||||
self.enemy.punchangle_x = (4 + (s * 2)) * zoom_factor;
|
||||
#endif
|
||||
};
|
||||
|
||||
void() Window_repaired =
|
||||
{
|
||||
if (maxreward > totalreward)
|
||||
{
|
||||
sound(self, 0,"sounds/misc/ching.wav", 1, 0);
|
||||
addmoney(self.enemy, 10, 1);
|
||||
totalreward = totalreward + 10;
|
||||
}
|
||||
screen_shake();
|
||||
self.enemy = world;
|
||||
};
|
||||
|
||||
void() Barricade_hit_window =
|
||||
{
|
||||
sound(self, 0, self.oldmodel, 1, 0);
|
||||
}
|
||||
|
||||
void(void() next) checkForSpeed = {
|
||||
if (!(other.perks & P_SPEED))
|
||||
return;
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////// ANIMATIONS
|
||||
//0-6
|
||||
//7-13
|
||||
//14-20
|
||||
//21-27
|
||||
//28-34
|
||||
//35-41
|
||||
void() window_anim1_1 =[ 1, window_anim1_2 ] {self.frame = 0;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_2 =[ 2, window_anim1_3 ] {self.frame = 1;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_3 =[ 3, window_anim1_4 ] {self.frame = 2;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_4 =[ 4, window_anim1_5 ] {self.frame = 3;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_5 =[ 5, window_anim1_6 ] {self.frame = 4;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_6 =[ 6, window_anim1_7 ] {self.frame = 5;self.nextthink = time + 0.05;};
|
||||
void() window_anim1_7 =[ 7, SUB_Null ] {self.frame = 6;self.nextthink = time + 0.05;};
|
||||
|
||||
void() window_anim2_1 =[ 1, window_anim2_2 ] {self.frame = 7;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_2 =[ 2, window_anim2_3 ] {self.frame = 8;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_3 =[ 3, window_anim2_4 ] {self.frame = 9;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_4 =[ 4, window_anim2_5 ] {self.frame = 10;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_5 =[ 5, window_anim2_6 ] {self.frame = 11;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_6 =[ 6, window_anim2_7 ] {self.frame = 12;self.nextthink = time + 0.05;};
|
||||
void() window_anim2_7 =[ 7, SUB_Null ] {self.frame = 13;self.nextthink = time + 0.05;};
|
||||
|
||||
void() window_anim3_1 =[ 1, window_anim3_2 ] {self.frame = 14;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_2 =[ 2, window_anim3_3 ] {self.frame = 15;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_3 =[ 3, window_anim3_4 ] {self.frame = 16;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_4 =[ 4, window_anim3_5 ] {self.frame = 17;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_5 =[ 5, window_anim3_6 ] {self.frame = 18;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_6 =[ 6, window_anim3_7 ] {self.frame = 19;self.nextthink = time + 0.05;};
|
||||
void() window_anim3_7 =[ 7, SUB_Null ] {self.frame = 20;self.nextthink = time + 0.05;};
|
||||
|
||||
void() window_anim4_1 =[ 1, window_anim4_2 ] {self.frame = 21;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_2 =[ 2, window_anim4_3 ] {self.frame = 22;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_3 =[ 3, window_anim4_4 ] {self.frame = 23;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_4 =[ 4, window_anim4_5 ] {self.frame = 24;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_5 =[ 5, window_anim4_6 ] {self.frame = 25;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_6 =[ 6, window_anim4_7 ] {self.frame = 26;self.nextthink = time + 0.05;};
|
||||
void() window_anim4_7 =[ 7, SUB_Null ] {self.frame = 27;self.nextthink = time + 0.05;};
|
||||
|
||||
void() window_anim5_1 =[ 1, window_anim5_2 ] {self.frame = 28;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_2 =[ 2, window_anim5_3 ] {self.frame = 29;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_3 =[ 3, window_anim5_4 ] {self.frame = 30;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_4 =[ 4, window_anim5_5 ] {self.frame = 31;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_5 =[ 5, window_anim5_6 ] {self.frame = 32;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_6 =[ 6, window_anim5_7 ] {self.frame = 33;self.nextthink = time + 0.05;};
|
||||
void() window_anim5_7 =[ 7, SUB_Null ] {self.frame = 34;self.nextthink = time + 0.05;};
|
||||
|
||||
void() window_anim6_1 =[ 1, window_anim6_2 ] {self.frame = 35;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_2 =[ 2, window_anim6_3 ] {self.frame = 36;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_3 =[ 3, window_anim6_4 ] {self.frame = 37;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_4 =[ 4, window_anim6_5 ] {self.frame = 38;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_5 =[ 5, window_anim6_6 ] {self.frame = 39;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_6 =[ 6, window_anim6_7 ] {self.frame = 40;self.nextthink = time + 0.05;};
|
||||
void() window_anim6_7 =[ 7, SUB_Null ] {self.frame = 41;self.nextthink = time + 0.05;};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//speed cola repair
|
||||
//81-88
|
||||
void() window_srepair1_1 =[ 1, window_srepair1_2 ] {self.frame = 81;};
|
||||
void() window_srepair1_2 =[ 2, window_srepair1_4 ] {self.frame = 84;};
|
||||
void() window_srepair1_4 =[ 3, window_srepair1_5 ] {self.frame = 87;Barricade_hit_window();};
|
||||
void() window_srepair1_5 =[ 4, SUB_Null ] {self.frame = 88; Window_repaired();};
|
||||
//73-80
|
||||
void() window_srepair2_1 =[ 1, window_srepair2_2 ] {self.frame = 73;};
|
||||
void() window_srepair2_2 =[ 2, window_srepair2_4 ] {self.frame = 75;};
|
||||
void() window_srepair2_4 =[ 3, window_srepair2_5 ] {self.frame = 79;Barricade_hit_window();};
|
||||
void() window_srepair2_5 =[ 4, SUB_Null ] {self.frame = 80; Window_repaired();};
|
||||
//65-72
|
||||
void() window_srepair3_1 =[ 1, window_srepair3_2 ] {self.frame = 65;};
|
||||
void() window_srepair3_2 =[ 2, window_srepair3_4 ] {self.frame = 67;};
|
||||
void() window_srepair3_4 =[ 3, window_srepair3_5 ] {self.frame = 71;Barricade_hit_window();};
|
||||
void() window_srepair3_5 =[ 4, SUB_Null ] {self.frame = 72; Window_repaired();};
|
||||
//57-64
|
||||
void() window_srepair4_1 =[ 1, window_srepair4_2 ] {self.frame = 57;};
|
||||
void() window_srepair4_2 =[ 2, window_srepair4_4 ] {self.frame = 69;};
|
||||
void() window_srepair4_4 =[ 3, window_srepair4_5 ] {self.frame = 63;Barricade_hit_window();};
|
||||
void() window_srepair4_5 =[ 4, SUB_Null ] {self.frame = 64; Window_repaired();};
|
||||
//49-56
|
||||
void() window_srepair5_1 =[ 1, window_srepair5_2 ] {self.frame = 49;};
|
||||
void() window_srepair5_2 =[ 2, window_srepair5_4 ] {self.frame = 51;};
|
||||
void() window_srepair5_4 =[ 3, window_srepair5_5 ] {self.frame = 55;Barricade_hit_window();};
|
||||
void() window_srepair5_5 =[ 4, SUB_Null ] {self.frame = 56; Window_repaired();};
|
||||
//41-48
|
||||
void() window_srepair6_1 =[ 1, window_srepair6_2 ] {self.frame = 41;};
|
||||
void() window_srepair6_2 =[ 2, window_srepair6_4 ] {self.frame = 43;};
|
||||
void() window_srepair6_4 =[ 3, window_srepair6_5 ] {self.frame = 47;Barricade_hit_window();};
|
||||
void() window_srepair6_5 =[ 4, SUB_Null ] {self.frame = 48; Window_repaired();};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void() window_repair1_1 =[ 1, window_repair1_2 ] {self.frame = 81;};
|
||||
void() window_repair1_2 =[ 2, window_repair1_3 ] {self.frame = 82;};
|
||||
void() window_repair1_3 =[ 3, window_repair1_4 ] {self.frame = 83;};
|
||||
void() window_repair1_4 =[ 4, window_repair1_5 ] {self.frame = 84;};
|
||||
void() window_repair1_5 =[ 5, window_repair1_6 ] {self.frame = 85;};
|
||||
void() window_repair1_6 =[ 6, window_repair1_7 ] {self.frame = 86;};
|
||||
void() window_repair1_7 =[ 7, window_repair1_8 ] {self.frame = 87;Barricade_hit_window();};
|
||||
void() window_repair1_8 =[ 8, SUB_Null ] {self.frame = 88; Window_repaired();};
|
||||
|
||||
void() window_repair2_1 =[ 1, window_repair2_2 ] {self.frame = 73;};
|
||||
void() window_repair2_2 =[ 2, window_repair2_3 ] {self.frame = 74;};
|
||||
void() window_repair2_3 =[ 3, window_repair2_4 ] {self.frame = 75;};
|
||||
void() window_repair2_4 =[ 4, window_repair2_5 ] {self.frame = 76;};
|
||||
void() window_repair2_5 =[ 5, window_repair2_6 ] {self.frame = 77;};
|
||||
void() window_repair2_6 =[ 6, window_repair2_7 ] {self.frame = 78;};
|
||||
void() window_repair2_7 =[ 7, window_repair2_8 ] {self.frame = 79;Barricade_hit_window();};
|
||||
void() window_repair2_8 =[ 8, SUB_Null ] {self.frame = 80; Window_repaired();};
|
||||
|
||||
void() window_repair3_1 =[ 1, window_repair3_2 ] {self.frame = 65;};
|
||||
void() window_repair3_2 =[ 2, window_repair3_3 ] {self.frame = 66;};
|
||||
void() window_repair3_3 =[ 3, window_repair3_4 ] {self.frame = 67;};
|
||||
void() window_repair3_4 =[ 4, window_repair3_5 ] {self.frame = 68;};
|
||||
void() window_repair3_5 =[ 5, window_repair3_6 ] {self.frame = 69;};
|
||||
void() window_repair3_6 =[ 6, window_repair3_7 ] {self.frame = 70;};
|
||||
void() window_repair3_7 =[ 7, window_repair3_8 ] {self.frame = 71;Barricade_hit_window();};
|
||||
void() window_repair3_8 =[ 8, SUB_Null ] {self.frame = 72; Window_repaired();};
|
||||
|
||||
void() window_repair4_1 =[ 1, window_repair4_2 ] {self.frame = 57;};
|
||||
void() window_repair4_2 =[ 2, window_repair4_3 ] {self.frame = 58;};
|
||||
void() window_repair4_3 =[ 3, window_repair4_4 ] {self.frame = 59;};
|
||||
void() window_repair4_4 =[ 4, window_repair4_5 ] {self.frame = 60;};
|
||||
void() window_repair4_5 =[ 5, window_repair4_6 ] {self.frame = 61;};
|
||||
void() window_repair4_6 =[ 6, window_repair4_7 ] {self.frame = 62;};
|
||||
void() window_repair4_7 =[ 7, window_repair4_8 ] {self.frame = 63;Barricade_hit_window();};
|
||||
void() window_repair4_8 =[ 8, SUB_Null ] {self.frame = 64; Window_repaired();};
|
||||
|
||||
void() window_repair5_1 =[ 1, window_repair5_2 ] {self.frame = 49;};
|
||||
void() window_repair5_2 =[ 2, window_repair5_3 ] {self.frame = 50;};
|
||||
void() window_repair5_3 =[ 3, window_repair5_4 ] {self.frame = 51;};
|
||||
void() window_repair5_4 =[ 4, window_repair5_5 ] {self.frame = 52;};
|
||||
void() window_repair5_5 =[ 5, window_repair5_6 ] {self.frame = 53;};
|
||||
void() window_repair5_6 =[ 6, window_repair5_7 ] {self.frame = 54;};
|
||||
void() window_repair5_7 =[ 7, window_repair5_8 ] {self.frame = 55;Barricade_hit_window();};
|
||||
void() window_repair5_8 =[ 8, SUB_Null ] {self.frame = 56; Window_repaired();};
|
||||
|
||||
void() window_repair6_1 =[ 1, window_repair6_2 ] {self.frame = 41;};
|
||||
void() window_repair6_2 =[ 2, window_repair6_3 ] {self.frame = 42;};
|
||||
void() window_repair6_3 =[ 3, window_repair6_4 ] {self.frame = 43;};
|
||||
void() window_repair6_4 =[ 4, window_repair6_5 ] {self.frame = 44;};
|
||||
void() window_repair6_5 =[ 5, window_repair6_6 ] {self.frame = 45;};
|
||||
void() window_repair6_6 =[ 6, window_repair6_7 ] {self.frame = 46;};
|
||||
void() window_repair6_7 =[ 7, window_repair6_8 ] {self.frame = 47;Barricade_hit_window();};
|
||||
void() window_repair6_8 =[ 8, SUB_Null ] {self.frame = 48; Window_repaired();};
|
||||
|
||||
void() window_carpenter_1 =[ 1, window_carpenter_2 ] {self.frame = 47;sound(self, 0, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_2 =[ 2, window_carpenter_3 ] {self.frame = 48;};
|
||||
void() window_carpenter_3 =[ 3, window_carpenter_4 ] {self.frame = 55;sound(self, 1, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_4 =[ 4, window_carpenter_5 ] {self.frame = 56;};
|
||||
void() window_carpenter_5 =[ 5, window_carpenter_6 ] {self.frame = 63;sound(self, 2, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_6 =[ 6, window_carpenter_7 ] {self.frame = 64;};
|
||||
void() window_carpenter_7 =[ 7, window_carpenter_8 ] {self.frame = 71;sound(self, 0, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_8 =[ 8, window_carpenter_9 ] {self.frame = 72;};
|
||||
void() window_carpenter_9 =[ 7, window_carpenter_10 ] {self.frame = 79;sound(self, 1, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_10 =[ 8, window_carpenter_11 ] {self.frame = 80;};
|
||||
void() window_carpenter_11 =[ 7, window_carpenter_12 ] {self.frame = 87;sound(self, 2, self.oldmodel, 1, 1);};
|
||||
void() window_carpenter_12 =[ 8, SUB_Null ] {self.frame = 88;};
|
||||
|
||||
|
||||
void() Window_Damage =
|
||||
{
|
||||
if(self.health == 0)
|
||||
return;
|
||||
|
||||
sound(self, CHAN_VOICE, self.aistatus, 1, 0);
|
||||
|
||||
self.health = self.health - 1;
|
||||
|
||||
if(self.health == 5)
|
||||
{
|
||||
window_anim1_1();
|
||||
total_windows_down = total_windows_down + 1;
|
||||
}
|
||||
else if(self.health == 4)
|
||||
window_anim2_1();
|
||||
else if(self.health == 3)
|
||||
window_anim3_1();
|
||||
else if(self.health == 2)
|
||||
window_anim4_1();
|
||||
else if(self.health == 1)
|
||||
window_anim5_1();
|
||||
else if(self.health == 0)
|
||||
window_anim6_1();
|
||||
|
||||
ach_tracker_spin = 1;
|
||||
};
|
||||
|
||||
void() Rebuild_Anims =
|
||||
{
|
||||
if(self.health == 5)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair1_1();
|
||||
else
|
||||
window_repair1_1();
|
||||
|
||||
total_windows_down = total_windows_down - 1;
|
||||
}
|
||||
else if(self.health == 4)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair2_1();
|
||||
else
|
||||
window_repair2_1();
|
||||
}
|
||||
else if(self.health == 3)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair3_1();
|
||||
else
|
||||
window_repair3_1();
|
||||
}
|
||||
else if(self.health == 2)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair4_1();
|
||||
else
|
||||
window_repair4_1();
|
||||
}
|
||||
else if(self.health == 1)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair5_1();
|
||||
else
|
||||
window_repair5_1();
|
||||
}
|
||||
else if(self.health == 0)
|
||||
{
|
||||
if (other.perks & P_SPEED)
|
||||
window_srepair6_1();
|
||||
else
|
||||
window_repair6_1();
|
||||
}
|
||||
};
|
||||
void() window_touch =
|
||||
{
|
||||
if(other.classname == "player" && !other.downed && self.health != -10)
|
||||
{
|
||||
if(self.health < 6)
|
||||
{
|
||||
useprint (other, 5, 0, 0);
|
||||
|
||||
if(other.button7)
|
||||
{
|
||||
if(self.rebuild_time < time)
|
||||
{
|
||||
self.enemy = other;
|
||||
Rebuild_Anims();
|
||||
self.health = self.health + 1;
|
||||
|
||||
self.rebuild_time = time + 0.75;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void() item_barricade =
|
||||
{
|
||||
if (self.spawnflags & 1) {
|
||||
self.health = -10; // Window is deactivated, to only hop over it
|
||||
} else {
|
||||
if (!self.model)
|
||||
self.model = "models/misc/window.mdl";
|
||||
if (!self.oldmodel)
|
||||
self.oldmodel = "sounds/misc/barricade.wav";
|
||||
if (!self.aistatus)
|
||||
self.aistatus = "sounds/misc/barricade_destroy.wav";
|
||||
|
||||
precache_model(self.model);
|
||||
precache_sound(self.oldmodel);
|
||||
precache_sound(self.aistatus);
|
||||
}
|
||||
|
||||
self.classname = "window";
|
||||
self.touch = window_touch;
|
||||
self.solid = SOLID_TRIGGER;
|
||||
|
||||
if (self.health != -10) {
|
||||
self.health = 6;
|
||||
setmodel(self, self.model);
|
||||
}
|
||||
|
||||
setsize(self, '-20 -20 -64', '20 20 16');
|
||||
setorigin(self, self.origin);
|
||||
spawn_boxes();
|
||||
|
||||
#ifndef PC
|
||||
windows[wincnt] = self;
|
||||
wincnt++;
|
||||
#endif
|
||||
};
|
||||
|
||||
void() item_cover = {item_barricade();};
|
3
source/server/items.qc
Normal file
3
source/server/items.qc
Normal file
|
@ -0,0 +1,3 @@
|
|||
//
|
||||
// Items.qc - all the definitions for item spawn functions as well as other functions related to them
|
||||
//
|
521
source/server/main.qc
Normal file
521
source/server/main.qc
Normal file
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
server/main.qc
|
||||
|
||||
mostly functions that will be called from the engine and are
|
||||
expected to exist
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() LightStyles_setup;
|
||||
void() SUB_Remove = {remove(self);}
|
||||
|
||||
//called when starting server/loading the map
|
||||
void() main =
|
||||
{
|
||||
localcmd("echo Server starting...\n");
|
||||
}
|
||||
|
||||
//called for each frame that QC runs
|
||||
float zombie_cleaned_w;
|
||||
void() StartFrame =
|
||||
{
|
||||
deathmatch = cvar("deathmatch");
|
||||
//coop = cvar("coop");
|
||||
framecount = framecount + 1;
|
||||
|
||||
if (waypoint_mode) {
|
||||
if (!zombie_cleaned_w) {
|
||||
entity zent;
|
||||
zent = find (world, classname, "ai_zombie");
|
||||
while (zent)
|
||||
{
|
||||
/*
|
||||
if (zent.head)
|
||||
remove (zent.head);
|
||||
if (zent.larm)
|
||||
remove (zent.larm);
|
||||
if (zent.rarm)
|
||||
remove (zent.rarm);
|
||||
*/
|
||||
remove (zent);
|
||||
zent = find (zent, classname, "ai_zombie");
|
||||
}
|
||||
zombie_cleaned_w = true;
|
||||
|
||||
zent = find (world, classname, "waypoint");
|
||||
while (zent)
|
||||
{
|
||||
if (zent.targetname)
|
||||
setmodel(zent, "models/way/normal_way_door.spr");
|
||||
else
|
||||
setmodel(zent, "models/way/normal_way.spr");
|
||||
zent = find (zent, classname, "waypoint");
|
||||
}
|
||||
zent = find (world, classname, "door_nzp_cost");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "door_nzp_cost");
|
||||
}
|
||||
zent = find (world, classname, "door_nzp");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent.solid = SOLID_NOT;
|
||||
zent = find (zent, classname, "door_nzp");
|
||||
}
|
||||
zent = find (world, classname, "window");
|
||||
while (zent)
|
||||
{
|
||||
zent.solid = SOLID_NOT;
|
||||
zent.touch = SUB_Null;
|
||||
zent = find (zent, classname, "window");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (roundinit) {
|
||||
Round_Core();
|
||||
Do_Zombie_AI ();
|
||||
} else {
|
||||
|
||||
entity SpawnedIn;
|
||||
SpawnedIn = find(world, classname, "player");
|
||||
|
||||
if (SpawnedIn) {
|
||||
entity getdog = find(world, classname, "spawn_dog");
|
||||
if (getdog)
|
||||
gotdog = 1;
|
||||
else
|
||||
gotdog = 0;
|
||||
|
||||
updateDogRound();
|
||||
InitRounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
string(string s) precache_model = #20;
|
||||
|
||||
void() precaches =
|
||||
{
|
||||
precache_model ("models/player.mdl");
|
||||
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
if (world.song != "")
|
||||
precache_sound (world.song);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Models
|
||||
//
|
||||
|
||||
// sprites
|
||||
precache_model ("models/sprites/revive.spr");
|
||||
precache_model ("models/sprites/revive_white.spr");
|
||||
precache_model ("models/sprites/sprkle.spr");
|
||||
precache_model ("models/sprites/lightning.spr");
|
||||
precache_model ("models/way/current_way.spr");
|
||||
precache_model ("models/way/current_way_door.spr");
|
||||
precache_model ("models/way/last_way.spr");
|
||||
precache_model ("models/way/last_way_door.spr");
|
||||
precache_model ("models/way/normal_way.spr");
|
||||
precache_model ("models/way/normal_way_door.spr");
|
||||
precache_model ("models/way/way_jump.spr");
|
||||
precache_model ("models/way/way_land.spr");
|
||||
|
||||
// zombie
|
||||
precache_model ("models/ai/zfull.mdl");
|
||||
precache_model ("models/ai/zlarm.mdl");
|
||||
precache_model ("models/ai/zrarm.mdl");
|
||||
precache_model ("models/ai/zbod.mdl");
|
||||
precache_model ("models/ai/zhead.mdl");
|
||||
|
||||
// zombie crawler
|
||||
precache_model ("models/ai/zcfull.mdl");
|
||||
precache_model ("models/ai/zcbod.mdl");
|
||||
precache_model ("models/ai/zclarm.mdl");
|
||||
precache_model ("models/ai/zcrarm.mdl");
|
||||
precache_model ("models/ai/zchead.mdl");
|
||||
|
||||
// powerups
|
||||
precache_model ("models/pu/maxammo!.mdl");
|
||||
precache_model ("models/pu/x2!.mdl");
|
||||
precache_model ("models/pu/instakill!.mdl");
|
||||
precache_model ("models/pu/nuke!.mdl");
|
||||
precache_model ("models/pu/carpenter!.mdl");
|
||||
precache_model ("models/pu/perkbottle!.mdl");
|
||||
|
||||
// start weapons
|
||||
precache_model ("models/weapons/m1911/v_colt.mdl");
|
||||
precache_model ("models/weapons/m1911/g_colt.mdl");
|
||||
precache_model ("models/weapons/knife/v_knife.mdl");
|
||||
precache_model ("models/weapons/grenade/v_grenade.mdl");
|
||||
precache_model ("models/weapons/grenade/g_grenade.mdl");
|
||||
precache_model ("models/weapons/grenade/g_betty.mdl");
|
||||
precache_model ("models/weapons/grenade/v_betty.mdl");
|
||||
precache_model ("models/weapons/morphine/v_morphine.mdl");
|
||||
|
||||
//
|
||||
// Sounds
|
||||
//
|
||||
|
||||
// player-made
|
||||
precache_sound("sounds/player/footstep1.wav");
|
||||
precache_sound("sounds/player/footstep2.wav");
|
||||
precache_sound("sounds/player/footstep3.wav");
|
||||
precache_sound("sounds/player/footstep4.wav");
|
||||
precache_sound("sounds/player/footstep5.wav");
|
||||
precache_sound("sounds/player/jump.wav");
|
||||
precache_sound("sounds/player/land.wav");
|
||||
precache_sound("sounds/player/pain4.wav");
|
||||
|
||||
// weapons
|
||||
precache_sound("sounds/weapons/colt/magin.wav");
|
||||
precache_sound("sounds/weapons/colt/magout.wav");
|
||||
precache_sound("sounds/weapons/colt/shoot.wav");
|
||||
precache_sound("sounds/weapons/colt/slide.wav");
|
||||
precache_sound("sounds/weapons/papfire.wav");
|
||||
|
||||
// grenade
|
||||
precache_sound("sounds/weapons/grenade/prime.wav");
|
||||
precache_sound("sounds/weapons/grenade/throw.wav");
|
||||
precache_sound("sounds/weapons/grenade/explode.wav");
|
||||
|
||||
// melee
|
||||
precache_sound("sounds/weapons/knife/knife_hitbod.wav");
|
||||
precache_sound("sounds/weapons/knife/knife.wav");
|
||||
precache_sound("sounds/weapons/knife/knife_hit.wav");
|
||||
|
||||
// tunes
|
||||
precache_sound("sounds/rounds/eround.wav");
|
||||
precache_sound("sounds/rounds/nround.wav");
|
||||
precache_sound("sounds/rounds/splash.wav");
|
||||
precache_sound("sounds/music/end.wav");
|
||||
|
||||
// misc
|
||||
precache_sound("sounds/misc/buy.wav");
|
||||
precache_sound("sounds/misc/wood_door.wav");
|
||||
precache_sound("sounds/misc/debris.wav");
|
||||
precache_sound("sounds/misc/denybuy.wav");
|
||||
precache_sound("sounds/misc/what.wav");
|
||||
|
||||
// power-ups
|
||||
precache_sound ("sounds/pu/pickup.wav");
|
||||
precache_sound ("sounds/pu/carpenter.wav");
|
||||
precache_sound ("sounds/pu/maxammo.wav");
|
||||
precache_sound ("sounds/pu/double_points.wav");
|
||||
precache_sound ("sounds/pu/insta_kill.wav");
|
||||
precache_sound ("sounds/pu/nuke.wav");
|
||||
precache_sound ("sounds/pu/byebye.wav");
|
||||
precache_sound ("sounds/pu/powerup.wav");
|
||||
precache_sound ("sounds/pu/drop.wav");
|
||||
|
||||
// zombie walk
|
||||
precache_sound ("sounds/zombie/w0.wav");
|
||||
precache_sound ("sounds/zombie/w1.wav");
|
||||
precache_sound ("sounds/zombie/w2.wav");
|
||||
precache_sound ("sounds/zombie/w3.wav");
|
||||
precache_sound ("sounds/zombie/w4.wav");
|
||||
precache_sound ("sounds/zombie/w5.wav");
|
||||
precache_sound ("sounds/zombie/w6.wav");
|
||||
precache_sound ("sounds/zombie/w7.wav");
|
||||
precache_sound ("sounds/zombie/w8.wav");
|
||||
precache_sound ("sounds/zombie/w9.wav");
|
||||
|
||||
// zombie run
|
||||
precache_sound ("sounds/zombie/r0.wav");
|
||||
precache_sound ("sounds/zombie/r1.wav");
|
||||
precache_sound ("sounds/zombie/r2.wav");
|
||||
precache_sound ("sounds/zombie/r3.wav");
|
||||
precache_sound ("sounds/zombie/r4.wav");
|
||||
precache_sound ("sounds/zombie/r5.wav");
|
||||
precache_sound ("sounds/zombie/r6.wav");
|
||||
precache_sound ("sounds/zombie/r7.wav");
|
||||
precache_sound ("sounds/zombie/r8.wav");
|
||||
precache_sound ("sounds/zombie/r9.wav");
|
||||
|
||||
// zombie swipe
|
||||
precache_sound ("sounds/zombie/a0.wav");
|
||||
precache_sound ("sounds/zombie/a1.wav");
|
||||
precache_sound ("sounds/zombie/a2.wav");
|
||||
precache_sound ("sounds/zombie/a3.wav");
|
||||
precache_sound ("sounds/zombie/a4.wav");
|
||||
precache_sound ("sounds/zombie/a5.wav");
|
||||
precache_sound ("sounds/zombie/a6.wav");
|
||||
precache_sound ("sounds/zombie/a7.wav");
|
||||
|
||||
// zombie death
|
||||
precache_sound ("sounds/zombie/d0.wav");
|
||||
precache_sound ("sounds/zombie/d1.wav");
|
||||
precache_sound ("sounds/zombie/d2.wav");
|
||||
precache_sound ("sounds/zombie/d3.wav");
|
||||
precache_sound ("sounds/zombie/d4.wav");
|
||||
precache_sound ("sounds/zombie/d5.wav");
|
||||
precache_sound ("sounds/zombie/d6.wav");
|
||||
precache_sound ("sounds/zombie/d7.wav");
|
||||
|
||||
// zombie taunt
|
||||
precache_sound ("sounds/zombie/t0.wav");
|
||||
precache_sound ("sounds/zombie/t1.wav");
|
||||
precache_sound ("sounds/zombie/t2.wav");
|
||||
precache_sound ("sounds/zombie/t3.wav");
|
||||
precache_sound ("sounds/zombie/t4.wav");
|
||||
|
||||
// zombie footsteps
|
||||
precache_sound ("sounds/zombie/s0.wav");
|
||||
precache_sound ("sounds/zombie/s1.wav");
|
||||
precache_sound ("sounds/zombie/sc0.wav");
|
||||
precache_sound ("sounds/zombie/sc1.wav");
|
||||
|
||||
// null
|
||||
precache_sound("sounds/null.wav");
|
||||
|
||||
#ifdef PC
|
||||
// Moto -- FIXME: compile FTE to remove this engine sound request
|
||||
precache_sound ("demon/dland2.wav");
|
||||
#endif
|
||||
}
|
||||
|
||||
//called when map loaded
|
||||
void() worldspawn =
|
||||
{
|
||||
precaches();
|
||||
LightStyles_setup();
|
||||
|
||||
#ifdef PC
|
||||
clientstat(STAT_CURRENTMAG, EV_FLOAT, currentmag);
|
||||
clientstat(STAT_CURRENTMAG2, EV_FLOAT, currentmag2);
|
||||
clientstat(STAT_POINTS, EV_FLOAT, points);
|
||||
clientstat(STAT_WEAPON2FRAME, EV_FLOAT, weapon2frame);
|
||||
clientstat(STAT_WEAPON2MODEL, EV_STRING, weapon2model);
|
||||
clientstat(STAT_GRENADES, EV_FLOAT, primary_grenades);
|
||||
clientstat(STAT_SECGRENADES, EV_FLOAT, secondary_grenades);
|
||||
clientstat(STAT_PROGRESSBAR, EV_FLOAT, progress_bar_percent);
|
||||
clientstat(STAT_WEAPONDURATION, EV_FLOAT, weapon_animduration);
|
||||
clientstat(STAT_WEAPON2DURATION, EV_FLOAT, weapon2_animduration);
|
||||
clientstat(STAT_WEAPONZOOM, EV_FLOAT, zoom);
|
||||
clientstat(STAT_INSTA, EV_FLOAT, insta_icon);
|
||||
clientstat(STAT_X2, EV_FLOAT, x2_icon);
|
||||
clientstat(STAT_SPECTATING, EV_FLOAT, isspec);
|
||||
clientstat(STAT_PLAYERNUM, EV_FLOAT, playernum); // literally useless but will be kept in case
|
||||
clientstat(STAT_PLAYERSTANCE, EV_FLOAT, stance);
|
||||
clientstat(STAT_FACINGENEMY, EV_FLOAT, facingenemy);
|
||||
clientstat(STAT_VIEWZOOM, EV_FLOAT, viewzoom);
|
||||
#endif
|
||||
|
||||
mappath = strcat("maps/", mapname);
|
||||
mappath = strzone(mappath);
|
||||
|
||||
LoadWaypointData();
|
||||
|
||||
//set game elements
|
||||
G_STARTPOINTS = 500;
|
||||
G_STARTROUND = 1;
|
||||
G_PRONEPOINTS = 0;
|
||||
G_STARTWEAPON[0] = W_COLT;
|
||||
G_STARTWEAPON[1] = 8;
|
||||
G_STARTWEAPON[2] = 32;
|
||||
G_WORLDTEXT = 1;
|
||||
G_PERKS = 0;
|
||||
G_PERKPOWER = 0;
|
||||
load_nzd();
|
||||
|
||||
}
|
||||
|
||||
void() SpectatorConnect =
|
||||
{
|
||||
bprint(PRINT_HIGH, self.netname);
|
||||
bprint(PRINT_HIGH, " has joined the spectators.\n");
|
||||
}
|
||||
|
||||
void() RelinkZombies =
|
||||
{
|
||||
entity ent,ent2;
|
||||
local float i;
|
||||
local vector min, max;
|
||||
|
||||
|
||||
//warn
|
||||
ent = ent2 = world;
|
||||
|
||||
while ((ent = find (ent, classname, "ai_zombie")))
|
||||
{
|
||||
if(ent.currentHitBoxSetup == 0)//empty bbox, we don't care to update
|
||||
continue;
|
||||
|
||||
makevectors (ent.angles);
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
if(i == 0)
|
||||
ent2 = ent.head;
|
||||
if(i == 1)
|
||||
ent2 = ent.larm;
|
||||
if(i == 2)
|
||||
ent2 = ent.rarm;
|
||||
|
||||
|
||||
if (ent2)
|
||||
{
|
||||
//setorigin (ent.head, ent.origin + v_right * ent.head.view_ofs_x + v_forward * ent.head.view_ofs_y + v_up * ent.head.view_ofs_z);
|
||||
setorigin (ent2, ent.origin);
|
||||
//fixme, move angles set and frame set to below the continue, we only want to update origin (maybe angles too?)
|
||||
ent2.angles = ent.angles;
|
||||
|
||||
if(ent2.deadflag)
|
||||
ent2.frame = ent.frame;
|
||||
|
||||
//if(OnlyOrigin)
|
||||
// continue;
|
||||
|
||||
min = ent2.bbmins + (v_right * ent2.view_ofs_x) + (v_forward * ent2.view_ofs_y) + (v_up * ent2.view_ofs_z);
|
||||
max = ent2.bbmaxs + (v_right * ent2.view_ofs_x) + (v_forward * ent2.view_ofs_y) + (v_up * ent2.view_ofs_z);
|
||||
|
||||
if(min_x > max_x) { min_x += max_x; max_x = min_x - max_x; min_x -= max_x; }
|
||||
if(min_y > max_y) { min_y += max_y; max_y = min_y - max_y; min_y -= max_y; }
|
||||
if(min_z > max_z) { min_z += max_z; max_z = min_z - max_z; min_z -= max_z; }
|
||||
|
||||
setsize(ent2,min,max);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void() EndFrame =
|
||||
{
|
||||
RelinkZombies();
|
||||
};
|
||||
|
||||
//
|
||||
// a large switch statement to convert asset paths made for
|
||||
// older versions of nzp to the new standard
|
||||
// TODO: add strlower or similar to all platforms.
|
||||
//
|
||||
string(string asset) convert_old_asset_path =
|
||||
{
|
||||
switch(asset) {
|
||||
case "progs/Sprites/lamp_glow.spr":
|
||||
return "models/sprites/lamp_glow.spr";
|
||||
case "progs/Sprites/lamp_glow2.spr":
|
||||
return "models/sprites/lamp_glow2.spr";
|
||||
case "progs/Sprites/lamp_glow3.spr":
|
||||
return "models/sprites/lamp_glow.spr";
|
||||
case "progs/Props/Kino_boxes2.mdl":
|
||||
case "progs/props/kino_boxes2.mdl":
|
||||
return "models/props/Kino_boxes2.mdl";
|
||||
case "progs/props/kino_boxes3.mdl":
|
||||
return "models/props/Kino_boxes3.mdl";
|
||||
case "progs/Props/Kino_boxes4.mdl":
|
||||
case "progs/props/kino_boxes4.mdl":
|
||||
return "models/props/Kino_boxes4.mdl";
|
||||
case "progs/props/Kino_box.mdl":
|
||||
case "progs/props/kino_box.mdl":
|
||||
case "progs/Props/Kino_box.mdl":
|
||||
return "models/props/Kino_box.mdl";
|
||||
case "progs/Props/table_dinner.mdl":
|
||||
return "models/props/table_dinner.mdl";
|
||||
case "progs/Props/table_sq.mdl":
|
||||
return "models/props/table_sq.mdl";
|
||||
case "progs/Props/Kino_table.mdl":
|
||||
case "progs/props/kino_table.mdl":
|
||||
return "models/props/Kino_table.mdl";
|
||||
case "progs/props/kino_couch.mdl":
|
||||
return "models/props/kino_couch.mdl";
|
||||
case "progs/Props/metal_chair.mdl":
|
||||
return "models/props/metal_chair.mdl";
|
||||
case "progs/Props/sandbags.mdl":
|
||||
case "progs/props/sandbags.mdl":
|
||||
return "models/props/sandbags.mdl";
|
||||
case "progs/Props/shelf.mdl":
|
||||
case "progs/props/shelf.mdl":
|
||||
return "models/props/shelf.mdl";
|
||||
case "progs/Props/dummy.mdl":
|
||||
case "progs/props/dummy.mdl":
|
||||
return "models/props/dummy.mdl";
|
||||
case "progs/props/stand.mdl":
|
||||
return "models/props/stand.mdl";
|
||||
case "progs/Props/radio.mdl":
|
||||
return "models/props/radio.mdl";
|
||||
case "progs/Props/radiator.mdl":
|
||||
return "models/props/radiator.mdl";
|
||||
case "progs/Props/lamp_ndu.mdl":
|
||||
case "progs/props/lamp_ndu.mdl":
|
||||
return "models/props/lamp_ndu.mdl";
|
||||
case "progs/Props/piano.mdl":
|
||||
return "models/props/piano.mdl";
|
||||
case "progs/props/teleporter.mdl":
|
||||
return "models/props/teleporter.mdl";
|
||||
case "progs/props/chandelier.mdl":
|
||||
return "models/props/chandelier.mdl";
|
||||
case "progs/props/vanity_table.mdl":
|
||||
return "models/props/vanity_table.mdl";
|
||||
case "progs/props/trash_con.mdl":
|
||||
return "models/props/trash_con.mdl";
|
||||
case "progs/props/kino_chairset.mdl":
|
||||
return "models/props/kino_chairset.mdl";
|
||||
case "progs/props/Kino_lounge.mdl":
|
||||
return "models/props/Kino_lounge.mdl";
|
||||
case "progs/props/kino_stageprop.mdl":
|
||||
return "models/props/kino_stageprop.mdl";
|
||||
case "progs/props/mainframe_pad.mdl":
|
||||
return "models/props/mainframe_pad.mdl";
|
||||
case "progs/Gmodels/g_mp40.mdl":
|
||||
case "progs/gmodels/g_mp40.mdl":
|
||||
return "models/weapons/mp40/g_mp40.mdl";
|
||||
case "progs/gmodels/g_thomp.mdl":
|
||||
return "models/weapons/thomp/g_thomp.mdl";
|
||||
case "progs/Gmodels/g_betty.mdl":
|
||||
case "progs/gmodels/g_betty.mdl":
|
||||
return "models/weapons/grenade/g_betty.mdl";
|
||||
case "progs/GModels/g_fg.mdl":
|
||||
return "models/weapons/fg/g_fg.mdl";
|
||||
case "progs/gmodels/g_m1.mdl":
|
||||
return "models/weapons/garand/g_m1.mdl";
|
||||
case "progs/gmodels/g_trench.mdl":
|
||||
return "models/weapons/trench/g_trench.mdl";
|
||||
case "progs/gmodels/g_bar.mdl":
|
||||
return "models/weapons/bar/g_bar.mdl";
|
||||
case "progs/gmodels/g_grenade.mdl":
|
||||
return "models/weapons/grenade/g_grenade.mdl";
|
||||
case "progs/gmodels/g_gewehr.mdl":
|
||||
return "models/weapons/gewehr/g_gewehr.mdl";
|
||||
case "progs/gmodels/g_bowie.mdl":
|
||||
return "models/weapons/knife/g_bowie.mdl";
|
||||
case "progs/gmodels/g_type.mdl":
|
||||
return "models/weapons/type/g_type.mdl";
|
||||
case "progs/gmodels/g_stg.mdl":
|
||||
return "models/weapons/stg/g_stg.mdl";
|
||||
case "models/misc/lightning.spr":
|
||||
return "models/sprites/lightning.spr";
|
||||
default: return asset;
|
||||
}
|
||||
|
||||
return asset;
|
||||
};
|
378
source/server/nzdparser.qc
Normal file
378
source/server/nzdparser.qc
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
server/nzdparser.qc
|
||||
|
||||
parses NZData files for map variety
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
//custom weapon search
|
||||
void(string weaponFile) nzd_defineweapon = {
|
||||
float f, p, l, fnum, wepnum, framenum, fsnd;
|
||||
string line;
|
||||
|
||||
fnum = 0;
|
||||
framenum = 0;
|
||||
fsnd = 0;
|
||||
|
||||
line = strcat(strcat("data/maps/", weaponFile), ".cw");
|
||||
f = fopen(line, FILE_READ);
|
||||
|
||||
if (f == -1) { //no custom weapons
|
||||
return;
|
||||
}
|
||||
wepnum = currentWeaponTracker - 1;
|
||||
p = 0;
|
||||
l = 1;
|
||||
|
||||
while(l) {
|
||||
string li;
|
||||
li = fgets(f);
|
||||
|
||||
if not (li) {
|
||||
l = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
line = strtrim(li);
|
||||
|
||||
if (line == "")
|
||||
continue;
|
||||
|
||||
switch(p) {
|
||||
case 0:
|
||||
wepnum += 1;
|
||||
currentWeaponTracker = wepnum;
|
||||
if (line == "weapon")
|
||||
p = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (line == "{")
|
||||
p = 2;
|
||||
else
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(line, " expected {\n")));
|
||||
break;
|
||||
case 2:
|
||||
tokenize(line);
|
||||
|
||||
string v, vari;
|
||||
vari = strtrim(argv(0));
|
||||
v = strtrim(argv(2));
|
||||
|
||||
switch(vari) {
|
||||
case "name":
|
||||
CustomWeapons[wepnum].name = v;
|
||||
break;
|
||||
case "mag":
|
||||
CustomWeapons[wepnum].magSize = stof(v);
|
||||
break;
|
||||
case "reserve":
|
||||
CustomWeapons[wepnum].reserveSize = stof(v);
|
||||
break;
|
||||
case "vmodel":
|
||||
CustomWeapons[wepnum].vmodel = v;
|
||||
break;
|
||||
case "vmodel2":
|
||||
CustomWeapons[wepnum].vmodel2 = v;
|
||||
break;
|
||||
case "gmodel":
|
||||
CustomWeapons[wepnum].gmodel = v;
|
||||
break;
|
||||
case "ads":
|
||||
CustomWeapons[wepnum].adsofs = stov(v);
|
||||
break;
|
||||
case "firetype":
|
||||
CustomWeapons[wepnum].firetype = stof(v);
|
||||
break;
|
||||
case "ispap":
|
||||
CustomWeapons[wepnum].ispap = stof(v);
|
||||
break;
|
||||
case "nonpap":
|
||||
CustomWeapons[wepnum].nonpap = stof(v);
|
||||
break;
|
||||
case "pap":
|
||||
CustomWeapons[wepnum].papWpn = stof(v);
|
||||
break;
|
||||
case "dmg":
|
||||
CustomWeapons[wepnum].damage = stof(v);
|
||||
break;
|
||||
case "shotcount":
|
||||
CustomWeapons[wepnum].shotcount = stof(v);
|
||||
break;
|
||||
case "bodypen":
|
||||
CustomWeapons[wepnum].bodypen = stof(v);
|
||||
break;
|
||||
case "penetration":
|
||||
CustomWeapons[wepnum].penetration = stof(v);
|
||||
break;
|
||||
case "spread":
|
||||
CustomWeapons[wepnum].spread = stof(v);
|
||||
break;
|
||||
case "fdelay":
|
||||
CustomWeapons[wepnum].fdelay = stof(v);
|
||||
break;
|
||||
case "rdelay":
|
||||
CustomWeapons[wepnum].rdelay = stof(v);
|
||||
break;
|
||||
case "walkspeed":
|
||||
CustomWeapons[wepnum].walkspeed = stof(v);
|
||||
break;
|
||||
case "firesound":
|
||||
CustomWeapons[wepnum].firesound = v;
|
||||
break;
|
||||
case "skin":
|
||||
CustomWeapons[wepnum].skin = stof(v);
|
||||
break;
|
||||
case "recoil":
|
||||
CustomWeapons[wepnum].recoil = stof(v);
|
||||
break;
|
||||
case "crossmin":
|
||||
CustomWeapons[wepnum].crossmin = stof(v);
|
||||
break;
|
||||
case "crossmax":
|
||||
CustomWeapons[wepnum].crossmax = stof(v);
|
||||
break;
|
||||
case "lowmag":
|
||||
CustomWeapons[wepnum].lowmag = stof(v);
|
||||
break;
|
||||
case "lowreserve":
|
||||
CustomWeapons[wepnum].lowreserve = stof(v);
|
||||
break;
|
||||
case "flash":
|
||||
CustomWeapons[wepnum].flash = stov(v);
|
||||
break;
|
||||
case "flashsize":
|
||||
CustomWeapons[wepnum].flashsize = stof(v);
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
/*sendCustomWeapon(wepnum, CustomWeapons[wepnum].name, CustomWeapons[wepnum].magSize,
|
||||
CustomWeapons[wepnum].reserveSize, CustomWeapons[wepnum].vmodel, CustomWeapons[wepnum].vmodel2,
|
||||
CustomWeapons[wepnum].gmodel, CustomWeapons[wepnum].isDual, CustomWeapons[wepnum].firetype,
|
||||
CustomWeapons[wepnum].nonpap, CustomWeapons[wepnum].pap, CustomWeapons[wepnum].ispap,
|
||||
CustomWeapons[wepnum].damage, CustomWeapons[wepnum].shotcount, CustomWeapons[wepnum].bodypen,
|
||||
CustomWeapons[wepnum].penetration, CustomWeapons[wepnum].spread, CustomWeapons[wepnum].fdelay,
|
||||
CustomWeapons[wepnum].rdelay, CustomWeapons[wepnum].walkspeed, CustomWeapons[wepnum].firesound,
|
||||
CustomWeapons[wepnum].skin, CustomWeapons[wepnum].recoil, CustomWeapons[wepnum].crossmin,
|
||||
CustomWeapons[wepnum].crossmax, CustomWeapons[wepnum].lowmag, CustomWeapons[wepnum].lowreserve,
|
||||
CustomWeapons[wepnum].flash, CustomWeapons[wepnum].flashsize, CustomWeapons[wepnum].papWpn,
|
||||
CustomWeapons[wepnum].adsofs);*/
|
||||
#endif
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if (line == "[") {
|
||||
p = 4;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(line, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (line == "]") {
|
||||
p = 2;
|
||||
} else {
|
||||
switch(wepnum) {
|
||||
/*case 0: W_C1FRAMES[fnum] = stof(line); break;
|
||||
case 1: W_C2FRAMES[fnum] = stof(line); break;
|
||||
case 2: W_C3FRAMES[fnum] = stof(line); break;
|
||||
case 3: W_C4FRAMES[fnum] = stof(line); break;*/
|
||||
}
|
||||
fnum++;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (line == "[") {
|
||||
p = 6;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(line, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (line == "]") {
|
||||
p = 2;
|
||||
} else {
|
||||
switch(wepnum) {
|
||||
/*case 0: W_C1XSNDFRAME[framenum] = stof(line); break;
|
||||
case 1: W_C2XSNDFRAME[framenum] = stof(line); break;
|
||||
case 2: W_C3XSNDFRAME[framenum] = stof(line); break;
|
||||
case 3: W_C4XSNDFRAME[framenum] = stof(line); break;*/
|
||||
}
|
||||
framenum++;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (line == "[") {
|
||||
p = 8;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(line, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (line == "]") {
|
||||
p = 2;
|
||||
} else {
|
||||
switch(wepnum) {
|
||||
/*case 0: W_C1XTRASND[fsnd] = line; break;
|
||||
case 1: W_C2XTRASND[fsnd] = line; break;
|
||||
case 2: W_C3XTRASND[fsnd] = line; break;
|
||||
case 3: W_C4XTRASND[fsnd] = line; break;*/
|
||||
}
|
||||
fsnd++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
//basically copying the waypoint code.. yikes
|
||||
void() load_nzd = {
|
||||
|
||||
#ifndef NX
|
||||
float file, point;
|
||||
string h;
|
||||
float loop;
|
||||
float wepdata = 0;
|
||||
|
||||
h = strcat(mappath, ".nzd");
|
||||
file = fopen (h, FILE_READ);
|
||||
|
||||
if (file == -1)
|
||||
{
|
||||
if (cvar("developer"))
|
||||
dprint(".NZD file not found, using default settings..\n");
|
||||
return;
|
||||
}
|
||||
|
||||
point = 0;
|
||||
loop = 1;
|
||||
|
||||
while(loop) {
|
||||
string line;
|
||||
line = fgets(file);
|
||||
if not (line) {
|
||||
bprint(PRINT_HIGH, "End of file\n");
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
h = strtrim(line);
|
||||
|
||||
//print(h, "\n");
|
||||
if (h == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (point) {
|
||||
case 0:
|
||||
//switch-ception!
|
||||
switch(h) {
|
||||
case "mech": point = 1; break;
|
||||
default: bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, "\n")));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (h == "{") {
|
||||
point = 2;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected {\n")));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
tokenize(h);
|
||||
|
||||
string value, variable;
|
||||
variable = strtrim(argv(0));
|
||||
value = strtrim(argv(2));
|
||||
switch (variable) {
|
||||
case "proneperkpoints":
|
||||
G_PRONEPOINTS = stof(value);
|
||||
break;
|
||||
case "spawnpoints":
|
||||
G_STARTPOINTS = stof(value);
|
||||
break;
|
||||
case "round":
|
||||
G_STARTROUND = stof(value);
|
||||
break;
|
||||
case "worldtext":
|
||||
G_WORLDTEXT = stof(value);
|
||||
break;
|
||||
case "perkpower":
|
||||
G_PERKPOWER = stof(value);
|
||||
break;
|
||||
case "includeweapon":
|
||||
nzd_defineweapon(value);
|
||||
break;
|
||||
case "hud":
|
||||
G_HUD = value;
|
||||
break;
|
||||
case "hudhor":
|
||||
G_HUDHOR = stof(value);
|
||||
break;
|
||||
case "wep":
|
||||
point = 3;
|
||||
break;
|
||||
case "perk":
|
||||
point = 5;
|
||||
break;
|
||||
case "}":
|
||||
loop = 0;
|
||||
break;
|
||||
default:
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected }\n")));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (h == "[") {
|
||||
point = 4;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (h == "]") {
|
||||
point = 2;
|
||||
} else {
|
||||
G_STARTWEAPON[wepdata] = stof(h);
|
||||
wepdata++;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (h == "[") {
|
||||
point = 6;
|
||||
} else {
|
||||
bprint(PRINT_HIGH, strcat("Error: unknown variable ", strcat(h, " expected [\n")));
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (h == "]") {
|
||||
point = 2;
|
||||
} else {
|
||||
G_PERKS = G_PERKS | stof(h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
#endif
|
||||
}
|
810
source/server/player.qc
Normal file
810
source/server/player.qc
Normal file
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
server/nzdparser.qc
|
||||
|
||||
Various stuff done for the player, including per-frame functions
|
||||
like PlayerPreThink and PlayerPostThink, also client specific
|
||||
stuff like PutClientInServer etc.
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void(entity e) Light_None;
|
||||
|
||||
// player animations
|
||||
|
||||
void() playdown =[ 1, playdown1 ] {self.frame = 32;}
|
||||
void() playdown1 =[ 2, playdown2 ] {self.frame = 33;}
|
||||
void() playdown2 =[ 2, playdown3 ] {self.frame = 34;}
|
||||
void() playdown3 =[ 2, playdown4 ] {self.frame = 35;}
|
||||
void() playdown4 =[ 2, playdown5 ] {self.frame = 36;}
|
||||
void() playdown5 =[ 2, playdown5 ] {self.frame = 37;}
|
||||
//
|
||||
void() playreload =[ 1, playreload1 ] {self.frame = 11;}
|
||||
void() playreload1 =[ 2, playreload2 ] {self.frame = 12;}
|
||||
void() playreload2 =[ 3, playreload3 ] {self.frame = 13;}
|
||||
void() playreload3 =[ 4, playreload4 ] {self.frame = 14;}
|
||||
void() playreload4 =[ 5, playreload5 ] {self.frame = 15;}
|
||||
void() playreload5 =[ 6, playreload6 ] {self.frame = 16;}
|
||||
void() playreload6 =[ 7, playreload7 ] {self.frame = 17;}
|
||||
void() playreload7 =[ 8, playreload8 ] {self.frame = 18;}
|
||||
void() playreload8 =[ 9, playreload9 ] {self.frame = 19;}
|
||||
void() playreload9 =[ 10, playreload10 ] {self.frame = 20;}
|
||||
void() playreload10 =[ 11, playreload11 ] {self.frame = 21;}
|
||||
void() playreload11 =[ 12, playreload12 ] {self.frame = 22;}
|
||||
void() playreload12 =[ 13, playreload13 ] {self.frame = 23;}
|
||||
void() playreload13 =[ 14, playreload13 ] {self.frame = 24;}
|
||||
//
|
||||
void() playdownfire =[ 1, playdownfire1 ] {self.frame = 38;}
|
||||
void() playdownfire1 =[ 2, playdownfire1 ] {self.frame = 39;}
|
||||
//
|
||||
void() playaim =[ 1, playaim1 ] {self.frame = 8;} // naievil -- player aimin anim
|
||||
void() playaim1 =[ 2, playaim1 ] {self.frame = 9;} // naievil -- second player aimin anim
|
||||
//
|
||||
void() playout =[ 1, playout1 ] {self.frame = 10;} // naievil -- player aim out anim
|
||||
void() playout1 =[ 2, playout1 ] {self.frame = 11;} // naievil -- second player aim out anim
|
||||
//
|
||||
void() playrun1 =[ 1, playrun2 ] {self.frame = 25;}
|
||||
void() playrun2 =[ 2, playrun3 ] {self.frame = 26;}
|
||||
void() playrun3 =[ 3, playrun4 ] {self.frame = 27;}
|
||||
void() playrun4 =[ 4, playrun5 ] {self.frame = 28;}
|
||||
void() playrun5 =[ 5, playrun6 ] {self.frame = 29;}
|
||||
void() playrun6 =[ 6, playrun7 ] {self.frame = 30;}
|
||||
void() playrun7 =[ 7, playrun8 ] {self.frame = 31;}
|
||||
void() playrun8 =[ 8, playrun9 ] {self.frame = 25;}
|
||||
void() playrun9 =[ 9, playrun10 ] {self.frame = 26;}
|
||||
void() playrun10 =[ 10, playrun11 ] {self.frame = 27;}
|
||||
void() playrun11 =[ 11, playrun12 ] {self.frame = 28;}
|
||||
void() playrun12 =[ 12, playrun13 ] {self.frame = 29;}
|
||||
void() playrun13 =[ 13, playrun14 ] {self.frame = 30;}
|
||||
void() playrun14 =[ 14, playrun15 ] {self.frame = 25;}
|
||||
void() playrun15 =[ 15, playrun16 ] {self.frame = 26;}
|
||||
void() playrun16 =[ 16, playrun17 ] {self.frame = 27;}
|
||||
void() playrun17 =[ 17, playrun18 ] {self.frame = 28;}
|
||||
void() playrun18 =[ 18, playrun19 ] {self.frame = 29;}
|
||||
void() playrun19 =[ 19, playrun20 ] {self.frame = 30;}
|
||||
void() playrun20 =[ 20, playrun21 ] {self.frame = 31;}
|
||||
void() playrun21 =[ 21, playrun22 ] {self.frame = 25;}
|
||||
void() playrun22 =[ 22, playrun23 ] {self.frame = 26;}
|
||||
void() playrun23 =[ 23, playrun24 ] {self.frame = 27;}
|
||||
void() playrun24 =[ 24, playrun25 ] {self.frame = 28;}
|
||||
void() playrun25 =[ 25, playrun26 ] {self.frame = 29;}
|
||||
void() playrun26 =[ 26, playrun27 ] {self.frame = 30;}
|
||||
void() playrun27 =[ 27, playrun28 ] {self.frame = 25;}
|
||||
void() playrun28 =[ 28, playrun29 ] {self.frame = 26;}
|
||||
void() playrun29 =[ 29, playrun30 ] {self.frame = 27;}
|
||||
void() playrun30 =[ 30, playrun31 ] {self.frame = 28;}
|
||||
void() playrun31 =[ 31, playrun32 ] {self.frame = 29;}
|
||||
void() playrun32 =[ 32, playrun33 ] {self.frame = 30;}
|
||||
void() playrun33 =[ 33, playrun33 ] {self.frame = 31;}
|
||||
//
|
||||
void() playwalk =[ 1, playwalk1 ] {if (self.velocity) { self.frame = 0; }}
|
||||
void() playwalk1 =[ 2, playwalk2 ] {if (self.velocity) { self.frame = 1; }}
|
||||
void() playwalk2 =[ 3, playwalk3 ] {if (self.velocity) { self.frame = 2; }}
|
||||
void() playwalk3 =[ 4, playwalk4 ] {if (self.velocity) { self.frame = 3; }}
|
||||
void() playwalk4 =[ 5, playwalk5 ] {if (self.velocity) { self.frame = 4; }}
|
||||
void() playwalk5 =[ 6, playwalk6 ] {if (self.velocity) { self.frame = 5; }}
|
||||
void() playwalk6 =[ 7, playwalk7 ] {if (self.velocity) { self.frame = 6; }}
|
||||
void() playwalk7 =[ 8, playwalk8 ] {if (self.velocity) { self.frame = 7; }}
|
||||
void() playwalk8 =[ 9, playwalk8 ] {if (self.velocity) { self.frame = 8; }}
|
||||
//
|
||||
void() playgetup =[ 1, playgetup1 ] {self.frame = 38;}
|
||||
void() playgetup1 =[ 2, playgetup2 ] {self.frame = 39;}
|
||||
void() playgetup2 =[ 3, playgetup3 ] {self.frame = 40;}
|
||||
void() playgetup3 =[ 4, playgetup4 ] {self.frame = 41;}
|
||||
void() playgetup4 =[ 5, playgetup5 ] {self.frame = 42;}
|
||||
void() playgetup5 =[ 6, playgetup6 ] {self.frame = 43;}
|
||||
void() playgetup6 =[ 7, playgetup7 ] {self.frame = 44;}
|
||||
void() playgetup7 =[ 8, playgetup8 ] {self.frame = 45;}
|
||||
void() playgetup8 =[ 9, playgetup9 ] {self.frame = 46;}
|
||||
void() playgetup9 =[ 10, playgetup10 ] {self.frame = 47;}
|
||||
void() playgetup10 =[ 11, playgetup10 ] {self.frame = 48;}
|
||||
|
||||
#define forward 0
|
||||
#define backward 1
|
||||
#define left 2
|
||||
#define right 3
|
||||
#define all_move -1
|
||||
float(float dir) checkMovement =
|
||||
{
|
||||
makevectors(self.movement);
|
||||
string a = vtos(self.movement);
|
||||
float x, y;
|
||||
|
||||
tokenize(a);
|
||||
x = stof(argv(0));
|
||||
y = stof(argv(1));
|
||||
|
||||
switch(dir) {
|
||||
case forward:
|
||||
if (x > 0)
|
||||
return 1;
|
||||
break;
|
||||
case backward:
|
||||
if (x < 0)
|
||||
return 1;
|
||||
break;
|
||||
case right:
|
||||
if (y > 0)
|
||||
return 1;
|
||||
break;
|
||||
case left:
|
||||
if (y < 0)
|
||||
return 1;
|
||||
break;
|
||||
case all_move:
|
||||
if (x || y)
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void() PlayerJump =
|
||||
{
|
||||
if (!(self.flags & FL_ONGROUND)
|
||||
|| !(self.flags & FL_JUMPRELEASED)
|
||||
|| self.downed
|
||||
|| self.dive ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
|
||||
sound(self, CHAN_VOICE, "sounds/player/jump.wav", 1, 1.75);
|
||||
|
||||
if (self.button2)
|
||||
self.button2 = 0;
|
||||
|
||||
self.oldz = self.origin_z;
|
||||
|
||||
self.velocity_z = 230;
|
||||
}
|
||||
|
||||
void(float override) JumpCheck =
|
||||
{
|
||||
#ifndef PC
|
||||
override = 0;
|
||||
#endif
|
||||
|
||||
if(self.button2 || override) {
|
||||
if (self.downed)
|
||||
return;
|
||||
|
||||
if (self.stance == 2) {
|
||||
// naievil -- stop sprinting if we jump, which is a real mechanic from the game that we never implemented
|
||||
if (self.sprinting) {
|
||||
W_SprintStop();
|
||||
}
|
||||
PlayerJump();
|
||||
} else if (self.view_ofs_z == self.new_ofs_z && (self.flags & FL_ONGROUND)) {
|
||||
switch(self.stance) {
|
||||
case 0:
|
||||
self.new_ofs_z = self.view_ofs_z + 42;
|
||||
self.stance = 2;
|
||||
break;
|
||||
case 1:
|
||||
self.new_ofs_z = self.view_ofs_z + 24;
|
||||
self.stance = 2;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
self.flags = self.flags | FL_JUMPRELEASED;
|
||||
}
|
||||
|
||||
void() PlayerPreThink =
|
||||
{
|
||||
if (self.downed) {
|
||||
self.maxspeed = 30;
|
||||
} else {
|
||||
self.maxspeed = 175;
|
||||
if (self.sprinting) {
|
||||
#ifdef PC
|
||||
if (self.viewzoom > 0.9)
|
||||
self.viewzoom -= 0.015;
|
||||
else if (self.viewzoom < 0.9)
|
||||
self.viewzoom = 0.9;
|
||||
|
||||
// viewbob when running
|
||||
self.punchangle_x = 1*sin(time*15);
|
||||
#endif
|
||||
playrun1();
|
||||
self.maxspeed *= 1.66;
|
||||
} else if (!self.sprinting && !self.zoom) {
|
||||
#ifdef PC
|
||||
if (self.viewzoom < 1)
|
||||
self.viewzoom += 0.015;
|
||||
else
|
||||
self.viewzoom = 1;
|
||||
|
||||
if (checkMovement(-1))
|
||||
self.punchangle_x = 0.25*sin(time*15);
|
||||
#endif
|
||||
} else if (self.zoom != 3) {
|
||||
self.maxspeed *= 0.5;
|
||||
} if (self.damagetimer > time) {
|
||||
self.maxspeed *= 0.5;
|
||||
}
|
||||
|
||||
switch(self.stance) {
|
||||
case 1:
|
||||
self.maxspeed *= 0.5;
|
||||
break;
|
||||
case 0:
|
||||
self.maxspeed *= 0.25;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
if (checkMovement(backward)) {
|
||||
self.maxspeed *= 0.7;
|
||||
} else if (checkMovement(left) || checkMovement(right)) {
|
||||
self.maxspeed *= 0.8;
|
||||
}
|
||||
#endif
|
||||
|
||||
self.maxspeed *= GetWeaponWalkSpeed(self.perks, self.weapon);
|
||||
}
|
||||
if(self.isspec != 0 && !self.downed)
|
||||
{
|
||||
if(self.button0)
|
||||
{
|
||||
self.aiment = find(self.aiment, classname, "player");
|
||||
if(self.aiment != world)
|
||||
{
|
||||
sprint(self, PRINT_HIGH, "Now spectating ");
|
||||
sprint(self, PRINT_HIGH, self.aiment.netname);
|
||||
sprint(self, PRINT_HIGH, "\n");
|
||||
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprint(self, PRINT_HIGH, "Freefly spectate\n");
|
||||
self.movetype = MOVETYPE_FLY;
|
||||
}
|
||||
}
|
||||
if(self.aiment != world)
|
||||
{
|
||||
self.origin = self.aiment.origin;
|
||||
self.angles = self.aiment.v_angle;
|
||||
self.velocity = self.aiment.velocity;
|
||||
self.fixangle = TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cvar("waypoint_mode")) {
|
||||
Waypoint_Logic();
|
||||
} else {
|
||||
Weapon_Logic();
|
||||
}
|
||||
|
||||
JumpCheck(0);
|
||||
|
||||
// refuel/cool m2
|
||||
if (self.ltime < time) {
|
||||
if (self.currentmag == 0 && !self.cooldown) {
|
||||
self.cooldown = true;
|
||||
}
|
||||
|
||||
if (self.cooldown && self.currentmag > 20)
|
||||
self.cooldown = false;
|
||||
|
||||
if (self.weapon == W_M2 || self.weapon == W_FIW && self.currentmag < getWeaponMag(self.weapon))
|
||||
self.currentmag += 1;
|
||||
|
||||
self.ltime = time + 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
void() PlayerPostThink =
|
||||
{
|
||||
if(self.isspec)
|
||||
return;
|
||||
|
||||
//landsound
|
||||
if((self.oldvelocity_z < -10) && (self.flags & FL_ONGROUND))
|
||||
{
|
||||
if(self.oldvelocity_z < -270)
|
||||
sound(self, CHAN_BODY, "sounds/player/land.wav", 1, 1.75);
|
||||
self.lastsound_time = time - 0.15;
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
//footsteps
|
||||
if((vlen(self.velocity) > 100) &&(( time - self.lastsound_time > 0.4) || (time - self.lastsound_time > 0.3 && self.sprinting)) && (self.flags & FL_ONGROUND))
|
||||
{
|
||||
local float movelen = vlen(input_movevalues);
|
||||
if(movelen > 300)
|
||||
{
|
||||
if (!self.sprinting)
|
||||
playwalk();
|
||||
|
||||
local float ran = random();
|
||||
if(ran > 0.8)
|
||||
sound(self, CHAN_BODY, "sounds/player/footstep1.wav", 0.8, 2.5);
|
||||
else if(ran > 0.6)
|
||||
sound(self, CHAN_BODY, "sounds/player/footstep2.wav", 0.8, 2.5);
|
||||
else if(ran > 0.4)
|
||||
sound(self, CHAN_BODY, "sounds/player/footstep3.wav", 0.8, 2.5);
|
||||
else if(ran > 0.2)
|
||||
sound(self, CHAN_BODY, "sounds/player/footstep4.wav", 0.8, 2.5);
|
||||
else
|
||||
sound(self, CHAN_BODY, "sounds/player/footstep5.wav", 0.8, 2.5);
|
||||
self.lastsound_time = time;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (self.health_delay < time && self.health != self.max_health && !self.downed)
|
||||
{
|
||||
self.health = self.health + 5;
|
||||
if (self.max_health < self.health)
|
||||
self.health = self.max_health;
|
||||
}
|
||||
|
||||
if (self.progress_bar) {
|
||||
if (self.progress_bar < time) {
|
||||
if (self.downed)
|
||||
GetUp();
|
||||
|
||||
if (self.reviving)
|
||||
self.revived = 1;
|
||||
|
||||
self.progress_bar = 0;
|
||||
self.progress_bar_time = 0;
|
||||
self.progress_bar_percent = 0;
|
||||
|
||||
|
||||
} else {
|
||||
float remaining = self.progress_bar - time;
|
||||
self.progress_bar_percent = invertfloat((remaining / self.progress_bar_time));
|
||||
}
|
||||
}
|
||||
|
||||
if (self.sprinting) {
|
||||
self.sprint_timer = self.sprint_duration + (time - self.sprint_start_time);
|
||||
|
||||
#ifndef PC
|
||||
if (!self.velocity || self.stance != 2) {
|
||||
W_SprintStop();
|
||||
}
|
||||
#else
|
||||
if (!self.velocity || !checkMovement(0) || self.stance != 2) { //moto (FIXME) -- move me!
|
||||
W_SprintStop();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (self.perks & P_STAMIN) {
|
||||
if (self.sprint_timer > sprint_max_time * 2) {
|
||||
W_SprintStop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.sprint_timer > sprint_max_time) {
|
||||
W_SprintStop();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (self.sprint_duration > 0.0) {
|
||||
self.sprint_rest_time = (time - self.sprint_stop_time);
|
||||
}
|
||||
|
||||
self.oldvelocity = self.velocity;
|
||||
|
||||
// Perform a traceline to keep track of entities directly
|
||||
// in front of the player.
|
||||
#ifndef NX
|
||||
vector source;
|
||||
|
||||
makevectors (self.v_angle);
|
||||
source = self.origin + self.view_ofs;
|
||||
|
||||
traceline (source, source + v_forward*800*1.2, 0, self);
|
||||
|
||||
// use .head here to avoid expanding ent struct
|
||||
self.head = trace_ent;
|
||||
|
||||
// check whether we're looking at an entity separately to communicate
|
||||
// with the client more reasonably
|
||||
if (trace_ent.classname == "ai_zombie" || trace_ent.classname == "ai_zombie_head"
|
||||
|| trace_ent.classname == "ai_zombie_rarm" ||trace_ent.classname == "ai_zombie_larm"
|
||||
|| trace_ent.classname == "ai_dog")
|
||||
self.facingenemy = true;
|
||||
else
|
||||
self.facingenemy = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
void() ClientKill = {};
|
||||
|
||||
//called when a client connects to the server
|
||||
void() ClientConnect =
|
||||
{
|
||||
#ifdef PC
|
||||
// Maintain old FGD values and just convert them to new ones
|
||||
//
|
||||
if (world.fog) {
|
||||
// Force fog on PC
|
||||
if (!world.PC_fog) {
|
||||
// Don't execute more than once
|
||||
if (!world_fog) {
|
||||
string fog_start_end, fog_R, fog_B, fog_G;
|
||||
|
||||
// Tokenize our fog
|
||||
tokenize(world.fog);
|
||||
|
||||
// Get values and transmute it a bit if necessary
|
||||
// Originally: start | end | R | G | B
|
||||
fog_start_end = ftos(((stof(argv(0))) / stof(argv(1))) / 3.5);
|
||||
|
||||
fog_R = ftos(stof(argv(2))/255);
|
||||
fog_G = ftos(stof(argv(3))/255);
|
||||
fog_B = ftos(stof(argv(4))/255);
|
||||
|
||||
// Restore into our world.fog
|
||||
world_fog = strcat(fog_start_end, " ", fog_R, " ", fog_G, " ", fog_B);
|
||||
}
|
||||
localcmd(strcat("fog ", world_fog));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(cvar("developer") || player_count > 1) {
|
||||
bprint(PRINT_HIGH, self.netname); //print player name
|
||||
bprint(PRINT_HIGH, " connected.\n");
|
||||
}
|
||||
};
|
||||
|
||||
void() PollPlayerPoints =
|
||||
{
|
||||
float i, breakpoint;
|
||||
entity pollent;
|
||||
breakpoint = 0;
|
||||
|
||||
for (i = 1; i <= 4 && !breakpoint; i++)
|
||||
{
|
||||
pollent = findfloat(world, playernum, i);
|
||||
|
||||
if (pollent == world) {
|
||||
breakpoint = 1;
|
||||
break;
|
||||
}
|
||||
UpdatePlayerPoints(i, pollent.points, pollent.kills, 0, pollent.netname, pollent);
|
||||
}
|
||||
}
|
||||
|
||||
void() PlayerSpawn =
|
||||
{
|
||||
local entity spawnpoint;
|
||||
local_client = self;
|
||||
|
||||
spawnpoint = find(world, classname, "info_player_start");
|
||||
|
||||
self.isspec = FALSE;
|
||||
self.classname = "player";
|
||||
self.solid = SOLID_BBOX;
|
||||
setmodel(self, "models/player.mdl");
|
||||
self.movetype = MOVETYPE_WALK;
|
||||
self.max_health = self.health = 100;
|
||||
|
||||
//custom weapon stuff (we want to put this here so we can send the info to the client with an entity)
|
||||
// DISGUSTING.
|
||||
//nzd_defineweapon(self);
|
||||
|
||||
//centerprint(self, CustomWeapons[0].vmodel);
|
||||
|
||||
entity who = find(world,classname,"player");
|
||||
while(who != self && !self.playernum)
|
||||
{
|
||||
if(who)
|
||||
{
|
||||
coop = 1;
|
||||
player_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(player_count) {
|
||||
default: spawnpoint = find(world, classname, "info_player_start"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 1: spawnpoint = find(world, classname, "info_player_nikolai"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 2: spawnpoint = find(world, classname, "info_player_takeo"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 3: spawnpoint = find(world, classname, "info_player_doctor"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
}
|
||||
|
||||
if (self.playernum) {
|
||||
switch(self.playernum) {
|
||||
default: spawnpoint = find(world, classname, "info_player_start"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 1: spawnpoint = find(world, classname, "info_player_nikolai"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 2: spawnpoint = find(world, classname, "info_player_takeo"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
case 3: spawnpoint = find(world, classname, "info_player_doctor"); if (!spawnpoint) {spawnpoint = find(world, classname, "info_player_start");} break;
|
||||
}
|
||||
}
|
||||
|
||||
self.origin = spawnpoint.origin + [0,0,1];
|
||||
self.angles = spawnpoint.angles;
|
||||
self.fixangle = TRUE;
|
||||
setsize(self, [-16, -16, -32], [16, 16, 40]);
|
||||
self.view_ofs = VEC_VIEW_OFS; // naievil -- set view_ofs to 32 to maintain half life (64) sizes
|
||||
self.stance = 2;
|
||||
self.new_ofs_z = self.view_ofs_z;
|
||||
self.oldz = self.origin_z;
|
||||
|
||||
self.currentammo = G_STARTWEAPON[2];
|
||||
self.currentmag = G_STARTWEAPON[1];
|
||||
self.weapon = G_STARTWEAPON[0];
|
||||
self.grenades = self.grenades | 1; // add frag grenades to player inventory
|
||||
|
||||
if (rounds)
|
||||
self.primary_grenades = 2;
|
||||
else
|
||||
self.primary_grenades = 0; // start off without grenades
|
||||
|
||||
self.pri_grenade_state = 0; // defines that frag grenades are for player first, not betty
|
||||
self.secondary_grenades = -1; // shows that we both don't have betties AND shouldn't draw the image onscreen
|
||||
|
||||
if (!self.points)
|
||||
addmoney(self, G_STARTPOINTS, 0);
|
||||
|
||||
self.weaponmodel = GetWeaponModel(self.weapon, 0);// Give weapon model
|
||||
self.weapon2model = GetWeapon2Model(self.weapon);
|
||||
|
||||
SwitchWeapon(self.weapon);
|
||||
|
||||
self.stamina = 3;
|
||||
self.reviving = 0;
|
||||
self.weaponnum = 0;
|
||||
self.perks = G_PERKS;
|
||||
SetPerk(self, self.perks);
|
||||
|
||||
//self.zoom = 1; // This is to fix an aimin bug for the kar scope
|
||||
|
||||
if (!self.playernum) {
|
||||
self.playernum = player_count + 1;
|
||||
if (self.playernum == 1)
|
||||
pl1 = self;
|
||||
}
|
||||
|
||||
if (rounds < 1) {
|
||||
sound(self, CHAN_AUTO, "sounds/rounds/splash.wav", 1, ATTN_NONE);
|
||||
}
|
||||
|
||||
PromptLevelChange(self.nextthink + 3, 1, self);
|
||||
UpdatePlayerCount(player_count);
|
||||
|
||||
#ifdef PC
|
||||
PollPlayerPoints();
|
||||
UpdateV2model("", 0);
|
||||
stuffcmd(self, "cl_gunx 8;cl_guny 16;cl_gunz 25\n");
|
||||
SetRound(self, G_STARTROUND);
|
||||
self.viewzoom = 1;
|
||||
self.weapon_animduration = getWeaponDelay(self.weapon, FIRE);
|
||||
|
||||
if (G_WORLDTEXT)
|
||||
WorldText(world.chaptertitle, world.location, world.date, world.person, self);
|
||||
#else
|
||||
self.Weapon_Name = GetWeaponName(self.weapon);
|
||||
self.Flash_Offset = GetWeaponFlash_Offset(self.weapon);
|
||||
self.Flash_Size = GetWeaponFlash_Size(self.weapon);
|
||||
#endif
|
||||
|
||||
if (G_STARTROUND != 1) {
|
||||
rounds = G_STARTROUND - 1;
|
||||
}
|
||||
|
||||
#ifndef PSP
|
||||
//pushHUD(G_HUD, G_HUDHOR, self); //FIXME - breaks mp!
|
||||
#endif
|
||||
};
|
||||
|
||||
void() SpectatorSpawn =
|
||||
{
|
||||
local entity spawnpoint;
|
||||
spawnpoint = find(world, classname, "info_player_start");
|
||||
|
||||
self.isspec = TRUE;
|
||||
self.classname = "spectator";
|
||||
self.solid = SOLID_NOT;
|
||||
setmodel(self, "");
|
||||
self.movetype = MOVETYPE_FLY;
|
||||
self.origin = spawnpoint.origin + [0,0,1];
|
||||
self.fixangle = TRUE;
|
||||
setsize(self, [-16, -16, -24], [16, 16, 32]);
|
||||
self.view_ofs = '0 0 22';
|
||||
self.aiment = world;
|
||||
};
|
||||
|
||||
//called when a client loads a map
|
||||
void() PutClientInServer =
|
||||
{
|
||||
if(cvar("developer") || player_count > 1) {
|
||||
bprint(PRINT_HIGH, self.netname);
|
||||
bprint(PRINT_HIGH, " has joined the game.\n");
|
||||
}
|
||||
|
||||
if (spawn_time > time || !rounds)
|
||||
PlayerSpawn();
|
||||
// TEMPORARY
|
||||
#ifdef PC
|
||||
else
|
||||
SpectatorSpawn();
|
||||
#endif
|
||||
};
|
||||
|
||||
//called when client disconnects from the server
|
||||
void() ClientDisconnect =
|
||||
{
|
||||
bprint(PRINT_HIGH, self.netname);
|
||||
bprint(PRINT_HIGH, " has left the game.\n");
|
||||
player_count--;
|
||||
UpdatePlayerCount(player_count);
|
||||
};
|
||||
|
||||
|
||||
void() SetNewParms =
|
||||
{
|
||||
};
|
||||
|
||||
void() SetChangeParms =
|
||||
{
|
||||
};
|
||||
|
||||
void(string com) SV_ParseClientCommand =
|
||||
{
|
||||
|
||||
if(com == "joingame")
|
||||
{
|
||||
if(self.isspec)
|
||||
{
|
||||
bprint(PRINT_HIGH, self.netname);
|
||||
bprint(PRINT_HIGH, " has joined the game.\n");
|
||||
PlayerSpawn();
|
||||
}
|
||||
else
|
||||
sprint(self, PRINT_HIGH, "You're already in game!\n");
|
||||
}
|
||||
else if(com == "specgame")
|
||||
{
|
||||
if(self.isspec)
|
||||
return;
|
||||
else
|
||||
{
|
||||
coop = 1;
|
||||
|
||||
/*SpectatorSpawn();
|
||||
bprint(PRINT_HIGH, self.netname); //print player name
|
||||
bprint(PRINT_HIGH, " has joined the spectators.\n");*/
|
||||
|
||||
PlayerSpawn();
|
||||
}
|
||||
}
|
||||
else if(com == "pause")
|
||||
{
|
||||
static float paused;
|
||||
paused = !paused;
|
||||
#ifdef PC
|
||||
setpause(paused);
|
||||
#endif
|
||||
}
|
||||
else if (com == "noclip")
|
||||
{
|
||||
#ifndef PC
|
||||
entity benis = self;
|
||||
other = find(world, classname, "player");
|
||||
self = other;
|
||||
#endif
|
||||
|
||||
if (self.movetype == MOVETYPE_WALK)
|
||||
self.movetype = MOVETYPE_NOCLIP;
|
||||
else
|
||||
self.movetype = MOVETYPE_WALK;
|
||||
|
||||
#ifndef PC
|
||||
localcmd(com);
|
||||
self = benis;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenize(com);
|
||||
|
||||
switch(argv(0))
|
||||
{
|
||||
case "give":
|
||||
entity tempe = self;
|
||||
other = find(world, classname, "player");
|
||||
self = other;
|
||||
|
||||
float wep = stof(argv(1));
|
||||
|
||||
if (wep) {
|
||||
if (!self.secondaryweapon) {
|
||||
WeaponSwitch(self);
|
||||
}
|
||||
|
||||
float startframe, endframe;
|
||||
string modelname;
|
||||
|
||||
self.weapon = wep;
|
||||
self.currentammo = getWeaponAmmo(wep);
|
||||
self.currentmag = getWeaponMag(wep);
|
||||
if (IsDualWeapon(wep)) {
|
||||
self.currentmag2 = self.currentmag;
|
||||
}
|
||||
|
||||
self.weaponskin = GetWepSkin(self.weapon);
|
||||
|
||||
startframe = GetFrame(self.weapon,TAKE_OUT_START);
|
||||
endframe = GetFrame(self.weapon,TAKE_OUT_END);
|
||||
modelname = GetWeaponModel(wep, 0);
|
||||
|
||||
SwitchWeapon(wep);
|
||||
|
||||
Set_W_Frame (startframe, endframe, 0, 0, 0, SUB_Null, modelname, false, S_BOTH);
|
||||
|
||||
self.reload_delay2 = self.fire_delay2 = self.reload_delay = self.fire_delay = 0;
|
||||
|
||||
#ifndef PC
|
||||
self.Weapon_Name = GetWeaponName(self.weapon);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case "god":
|
||||
if (!(self.flags & FL_GODMODE))
|
||||
self.flags = self.flags | FL_GODMODE;
|
||||
else
|
||||
self.flags = self.flags & (~FL_GODMODE);
|
||||
break;
|
||||
case "nextround":
|
||||
rounds++;
|
||||
break;
|
||||
case "prevround":
|
||||
rounds--;
|
||||
break;
|
||||
case "addmoney":
|
||||
entity tempe1 = self;
|
||||
other = find(world, classname, "player");
|
||||
self = other;
|
||||
|
||||
addmoney(self, stof(argv(1)), 1);
|
||||
|
||||
self = tempe1;
|
||||
break;
|
||||
default:
|
||||
#ifndef PC
|
||||
bprint(PRINT_HIGH, "Command not found in QC\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef PC
|
||||
void() SV_RunClientCommand =
|
||||
{
|
||||
runstandardplayerphysics(self);
|
||||
}
|
||||
#endif
|
183
source/server/psp_specifics.qc
Normal file
183
source/server/psp_specifics.qc
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
server/psp_specifics.qc
|
||||
|
||||
stuff only for psp, remove later
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() Do_Zombie_A = {};
|
||||
void() func_door_nzp;
|
||||
void() mystery_box;
|
||||
|
||||
entity windows[32];
|
||||
float wincnt;
|
||||
|
||||
void () CL_SendWeaponFire =
|
||||
{
|
||||
float return_time;
|
||||
vector Wep_Recoil;
|
||||
|
||||
Wep_Recoil = GetWeaponRecoil(self.weapon);
|
||||
|
||||
msg_entity = self;
|
||||
WriteByte(MSG_ONE, SVC_WEAPONFIRE);
|
||||
return_time = getWeaponRecoilReturn(self.weapon);
|
||||
WriteLong(MSG_ONE, return_time);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_x);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_y);
|
||||
WriteCoord (MSG_ONE, Wep_Recoil_z);
|
||||
//self.punchangle = Wep_Recoil;
|
||||
self.recoil_delay = 60/return_time + time;
|
||||
}
|
||||
|
||||
void() trigger_activator = {};
|
||||
|
||||
void() ParseClientCommand = {SV_ParseClientCommand(CMD_STRING);}
|
||||
|
||||
void() PutClientInServer;
|
||||
void() InitRounds;
|
||||
|
||||
//moto -- put this here because it keeps soft_restart somewhat clean..
|
||||
void(entity door) reclose_door = {
|
||||
entity oldself;
|
||||
oldself = self;
|
||||
|
||||
self = door;
|
||||
setmodel(self, self.oldmodel);
|
||||
self.solid = SOLID_BSP;
|
||||
setorigin(self, self.oldorigin);
|
||||
self.isopen = 0;
|
||||
func_door_nzp();
|
||||
|
||||
//Close_Waypoint(self.wayTarget);
|
||||
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
void() Soft_Restart = {
|
||||
entity who, oldself, doors, box, revive, endgame;
|
||||
self = find(world,classname,"player");
|
||||
oldself = self;
|
||||
|
||||
//remove all zombies
|
||||
who = find(world,classname,"ai_zombie");
|
||||
while(who != world)
|
||||
{
|
||||
if(who.health)
|
||||
{
|
||||
self = who;
|
||||
self.th_die();
|
||||
|
||||
// hide bodies
|
||||
setmodel(self, "");
|
||||
if (self.head)
|
||||
setmodel(self.head, "");
|
||||
if (self.larm)
|
||||
setmodel(self.larm, "");
|
||||
if (self.rarm)
|
||||
setmodel(self.rarm, "");
|
||||
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
who = find(who,classname,"ai_zombie");
|
||||
}
|
||||
|
||||
//repair all windows
|
||||
for(float i = 0; i < wincnt; i++) {
|
||||
if (windows[i].health != -10) {
|
||||
windows[i].health = 6;
|
||||
windows[i].frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//close doors
|
||||
doors = findfloat(world, isopen, 1);
|
||||
while (doors) {
|
||||
if (doors.isopen)
|
||||
reclose_door(doors);
|
||||
doors = findfloat(world, isopen, 1);
|
||||
}
|
||||
|
||||
//revert mystery box
|
||||
box = find(world, classname, "mystery");
|
||||
if (box) {
|
||||
box.boxstatus = 0;
|
||||
box.frame = 0;
|
||||
box.goaldummy.frame = 0;
|
||||
boxCount = 0;
|
||||
box.origin = boxOrigin;
|
||||
//self = box;
|
||||
|
||||
if (box.boxweapon)
|
||||
remove(box.boxweapon);
|
||||
|
||||
//mystery_box();
|
||||
//self = oldself;
|
||||
}
|
||||
|
||||
//reset quick revive
|
||||
revive = find(world, classname, "perk_revive");
|
||||
if (revive) {
|
||||
setmodel(revive, revive.model);
|
||||
oldself.revivesoda = 0;
|
||||
}
|
||||
|
||||
//reset buyable ending
|
||||
endgame = find(world, classname, "func_ending");
|
||||
if (endgame) {
|
||||
endgame.activated = false;
|
||||
}
|
||||
|
||||
//reset teleporters
|
||||
local entity tp;
|
||||
tp = find(world, classname, "func_teleporter_entrance");
|
||||
|
||||
if (tp) {
|
||||
tp.activated = false;
|
||||
tp.isLinked = false;
|
||||
tp.cooldown = false;
|
||||
tp.waitLink = false;
|
||||
tp.think = SUB_Null;
|
||||
}
|
||||
|
||||
local entity power;
|
||||
power = find(world, classname, "power_switch");
|
||||
if(power) {
|
||||
isPowerOn = false;
|
||||
power.frame = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
self = oldself;
|
||||
self.downed = 0;
|
||||
game_over = false;
|
||||
rounds = 0;
|
||||
self.score = 0;
|
||||
self.points = 0;
|
||||
self.secondaryweapon = 0;
|
||||
InitRounds();
|
||||
self.isspec = false;
|
||||
PutClientInServer();
|
||||
}
|
340
source/server/rounds.qc
Normal file
340
source/server/rounds.qc
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
server/rounds.qc
|
||||
|
||||
wave logic
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
float() spawn_a_dogA;
|
||||
|
||||
void() Spawn_Enemy =
|
||||
{
|
||||
// temporarily prevent spawning
|
||||
if (nuke_powerup_spawndelay > time)
|
||||
return;
|
||||
|
||||
if (roundtype == 1)
|
||||
{
|
||||
if (spawn_a_zombieA())
|
||||
{
|
||||
Current_Zombies = Current_Zombies + 1;
|
||||
}
|
||||
}
|
||||
else if (roundtype == 2)
|
||||
{
|
||||
if (spawn_a_dogA())
|
||||
{
|
||||
Current_Zombies = Current_Zombies + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float(float a, float b) qc_max =
|
||||
{
|
||||
if (a < b)
|
||||
return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
float() getZombieTotal = {
|
||||
if (roundtype == 1) {
|
||||
float count, multiplier, plrcnt;
|
||||
count = 24;
|
||||
plrcnt = player_count + 1;
|
||||
|
||||
multiplier = qc_max(rounds/5, 1);
|
||||
|
||||
if (rounds >= 10)
|
||||
multiplier *= rounds * 0.15;
|
||||
|
||||
if (plrcnt == 1)
|
||||
count += rint((0.5 * 6) * multiplier);
|
||||
else
|
||||
count += rint((plrcnt * 6) * multiplier);
|
||||
|
||||
if (rounds < 2)
|
||||
count = floor(count * 0.25);
|
||||
else if (rounds < 3)
|
||||
count = floor(count * 0.30);
|
||||
else if (rounds < 4)
|
||||
count = floor(count * 0.50);
|
||||
else if (rounds < 5)
|
||||
count = floor(count * 0.70);
|
||||
else if (rounds < 6)
|
||||
count = floor(count * 0.90);
|
||||
|
||||
return count;
|
||||
} else { //dogs
|
||||
// 2 waves
|
||||
if (rounds <= 14)
|
||||
return 6 * (player_count + 1);
|
||||
|
||||
return 8 * (player_count + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void(string s) playSoundAtPlayers =
|
||||
{
|
||||
local entity p;
|
||||
p = find(world,classname,"player");
|
||||
while(p)
|
||||
{
|
||||
sound(p,CHAN_AUTO,s,1,ATTN_NONE);
|
||||
p = find(p,classname,"player");
|
||||
}
|
||||
}
|
||||
|
||||
void() updateDogRound =
|
||||
{
|
||||
float r = random();
|
||||
|
||||
if (r < 0.33) {
|
||||
dogRound = rounds + 5;
|
||||
} else if (r < 0.66) {
|
||||
dogRound = rounds + 6;
|
||||
} else {
|
||||
dogRound = rounds + 7;
|
||||
}
|
||||
}
|
||||
|
||||
void() EndRound =
|
||||
{
|
||||
rounds_change = 4;
|
||||
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
|
||||
if (gotdog && rounds == dogRound) {
|
||||
playSoundAtPlayers("sounds/rounds/droundend.wav");
|
||||
dogWave = false;
|
||||
} else {
|
||||
playSoundAtPlayers("sounds/rounds/eround.wav");
|
||||
}
|
||||
round_changetime = time + 5;
|
||||
|
||||
// No Perks? No Problem & Abstinence Program
|
||||
if (rounds >= 10) {
|
||||
entity players;
|
||||
players = find(world, classname, "player");
|
||||
|
||||
while(players != world) {
|
||||
if (players.ach_tracker_npnp == 0) {
|
||||
GiveAchievement(5, players);
|
||||
}
|
||||
if (players.ach_tracker_abst == 0) {
|
||||
GiveAchievement(8, players);
|
||||
}
|
||||
players.ach_tracker_npnp = 0;
|
||||
players = find(players, classname, "player");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void() PlayerSpawn;
|
||||
|
||||
void() NewRound =
|
||||
{
|
||||
entity who = find(world,classname,"spectator");
|
||||
while(who != world)
|
||||
{
|
||||
if(who.isspec)
|
||||
{
|
||||
self = who;
|
||||
PlayerSpawn();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entity tempe;
|
||||
round_changetime = 0;
|
||||
spawn_time = time + 5;
|
||||
sounds_playing = 0;//just in case it ever somehow glitches
|
||||
if (delay_at_round > 0.08)
|
||||
{
|
||||
delay_at_round = delay_at_round*0.95;
|
||||
if (delay_at_round < 0.08)
|
||||
delay_at_round = 0.08;
|
||||
}
|
||||
if (rounds != 0)
|
||||
{
|
||||
if (gotdog && rounds == (dogRound - 1)) {
|
||||
playSoundAtPlayers("sounds/rounds/droundstart.wav");
|
||||
dogWave = true;
|
||||
} else {
|
||||
playSoundAtPlayers("sounds/rounds/nround.wav");
|
||||
}
|
||||
rounds_change = 6;
|
||||
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
|
||||
blink_return = time + 2;
|
||||
}
|
||||
|
||||
// if we just had a dog round, set the next
|
||||
if (gotdog && rounds == dogRound) {
|
||||
updateDogRound();
|
||||
}
|
||||
|
||||
rounds = rounds + 1;
|
||||
|
||||
NotifyNewRound(rounds);
|
||||
tempe = find(world, classname, "player");
|
||||
while (tempe)
|
||||
{
|
||||
if(tempe.grenades & 1)
|
||||
{
|
||||
tempe.primary_grenades = tempe.primary_grenades + 2;
|
||||
if (tempe.primary_grenades > 4)
|
||||
tempe.primary_grenades = 4;
|
||||
}
|
||||
|
||||
if(tempe.grenades & 2)
|
||||
{
|
||||
tempe.secondary_grenades = tempe.secondary_grenades + 2;
|
||||
if (tempe.secondary_grenades > 2)
|
||||
tempe.secondary_grenades = 2;
|
||||
}
|
||||
tempe = find(tempe, classname, "player");
|
||||
}
|
||||
|
||||
set_z_health();
|
||||
|
||||
maxreward = 50 * rounds;
|
||||
if (maxreward > 500)
|
||||
maxreward = 500;
|
||||
|
||||
totalreward = 0;
|
||||
Current_Zombies = 0;
|
||||
spawn_delay = 0;
|
||||
totalpowerups = 0;
|
||||
powerup_activate = powerup_activate*1.14;
|
||||
|
||||
if (rounds == dogRound && gotdog) {
|
||||
roundtype = 2;
|
||||
localcmd("fog 0.25\n");
|
||||
} else {
|
||||
roundtype = 1;
|
||||
|
||||
if (world.fog) {
|
||||
#ifdef PSP
|
||||
localcmd(strcat("fog ", world.fog));
|
||||
#else
|
||||
#ifdef PC
|
||||
localcmd(strcat("fog ", world_fog));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Remaining_Zombies = Total_Zombies = getZombieTotal();
|
||||
|
||||
#ifndef NX
|
||||
switch(rounds) {
|
||||
case 5: GiveAchievement(0); break;
|
||||
case 10: GiveAchievement(1); break;
|
||||
case 15: GiveAchievement(2); break;
|
||||
default: break;
|
||||
}
|
||||
#endif // NX
|
||||
|
||||
// Set up delay for zombie spawning
|
||||
local float spawndelay;
|
||||
|
||||
spawndelay = zombie_spawn_delay;
|
||||
|
||||
if (spawndelay > 0.08) {
|
||||
zombie_spawn_delay *= 0.95;
|
||||
} else {
|
||||
zombie_spawn_delay = 0.08;
|
||||
}
|
||||
|
||||
// 2 seconds by default
|
||||
if (rounds == 1)
|
||||
zombie_spawn_delay = 2;
|
||||
|
||||
// Actually start the timer
|
||||
zombie_spawn_timer = 2 + time;
|
||||
|
||||
if (rounds >= 10 && ach_tracker_spin == 0) {
|
||||
GiveAchievement(10);
|
||||
}
|
||||
}
|
||||
void() Round_Core =
|
||||
{
|
||||
if (game_over)
|
||||
return;
|
||||
|
||||
if (round_changetime <= (time + 2) && !rounds && round_changetime) {
|
||||
rounds_change = 2;
|
||||
}
|
||||
|
||||
if (round_changetime <= (time + 2) && rounds && round_changetime) {
|
||||
rounds_change = 5;
|
||||
}
|
||||
|
||||
if (blink_return && blink_return < time && rounds_change == 6)
|
||||
{
|
||||
blink_return = time + 3;
|
||||
rounds_change = 7;
|
||||
}
|
||||
if (blink_return && blink_return < time && rounds_change == 7)
|
||||
{
|
||||
blink_return = 0;
|
||||
rounds_change = 0;
|
||||
}
|
||||
if (round_changetime >= time)
|
||||
return;
|
||||
if (round_changetime)
|
||||
{
|
||||
roundtype = 1;
|
||||
|
||||
NewRound();
|
||||
return;
|
||||
}
|
||||
if (Total_Zombies > Current_Zombies && spawn_time < time)
|
||||
{
|
||||
Spawn_Enemy();
|
||||
}
|
||||
if (Remaining_Zombies < 1 && !Delay_Time)
|
||||
{
|
||||
Delay_Time = time + 2;
|
||||
rounds_change = 3;
|
||||
}
|
||||
else if (Delay_Time && Delay_Time < time)
|
||||
{
|
||||
Delay_Time = 0;
|
||||
EndRound();
|
||||
}
|
||||
|
||||
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
|
||||
}
|
||||
|
||||
void() InitRounds =
|
||||
{
|
||||
roundtype = 1;
|
||||
delay_at_round = 2/0.95;
|
||||
totalpowerups = 0;
|
||||
powerup_activate = 2000/1.14;
|
||||
spawnAllZombEnts();
|
||||
round_changetime = time + 3.5;
|
||||
rounds_change = 1;
|
||||
roundinit = 1;
|
||||
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
|
||||
}
|
233
source/server/weapons/frames_core.qc
Normal file
233
source/server/weapons/frames_core.qc
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
server/weapons/frames_core.qc
|
||||
|
||||
advanced viewmodel frame iteration
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
void() ContinueRun =
|
||||
{
|
||||
float startframe;
|
||||
float endframe;
|
||||
string modelname;
|
||||
startframe = GetFrame(self.weapon,SPRINT_START);
|
||||
endframe = GetFrame(self.weapon,SPRINT_END);
|
||||
if(!startframe && !endframe)
|
||||
{
|
||||
startframe = GetFrame(self.weapon,SPRINT_IN_END);
|
||||
endframe = GetFrame(self.weapon,SPRINT_IN_END);
|
||||
}
|
||||
if (!self.downed) {
|
||||
modelname = GetWeaponModel(self.weapon, 0);
|
||||
} else
|
||||
modelname = "";
|
||||
Set_W_Frame (startframe, endframe, 0, 0, SPRINT, ContinueRun, modelname, false, S_BOTH);
|
||||
}
|
||||
|
||||
|
||||
void () W2_Frame_Update =
|
||||
{
|
||||
local void temp(optional float t);
|
||||
|
||||
// note: call whenever weapon frames are called!
|
||||
|
||||
if (self.anim_weapon2_time > time)
|
||||
return; //don't call every frame, if it is the animations will play too fast
|
||||
|
||||
#ifndef PC
|
||||
if (self.weapon == W_KAR_SCOPE || self.weapon == W_HEADCRACKER) {
|
||||
self.weapon2frame = self.weaponframe;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
self.anim_weapon2_time = time + self.weapon2_animduration;
|
||||
|
||||
if (self.weapon2frame != self.weapon2frame_end && !self.anim2_reversed)
|
||||
{ // continue an animation
|
||||
if (self.anim2_reversed) {
|
||||
self.weapon2frame = self.weapon2frame - 1;
|
||||
} else {
|
||||
self.weapon2frame = self.weapon2frame + 1;
|
||||
}
|
||||
|
||||
if (self.callfuncat2)
|
||||
{
|
||||
if (self.weapon2frame == self.callfuncat2)
|
||||
{
|
||||
if (self.animend2)
|
||||
{
|
||||
temp = self.animend2;
|
||||
self.animend2 = SUB_Null2;
|
||||
if (temp)
|
||||
temp(S_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayWeaponSound(self.weapon, self.weapon2_anim_type, FALSE, self.weapon2frame);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.weapon2frame = self.weapon2frame_end = self.weapon2frame = GetFrame(self.weapon,BASE_FRAME);
|
||||
self.new_anim2_stop = FALSE;
|
||||
self.weapon2_anim_type = 0;
|
||||
self.weapon2_animduration = 0;
|
||||
self.callfuncat2 = 0;
|
||||
temp = self.animend2;
|
||||
self.animend2 = SUB_Null;
|
||||
if (temp)
|
||||
temp(S_LEFT);
|
||||
}
|
||||
};
|
||||
void () W_Frame_Update =
|
||||
{
|
||||
local void temp(optional float t);
|
||||
|
||||
// note: call whenever weapon frames are called!
|
||||
if (self.anim_weapon_time > time)
|
||||
return; //don't call every frame, if it is the animations will play too fast
|
||||
|
||||
W2_Frame_Update();
|
||||
|
||||
self.anim_weapon_time = time + self.weapon_animduration;
|
||||
|
||||
|
||||
|
||||
if (self.weaponframe != self.weaponframe_end && !self.anim_reversed)
|
||||
{ // continue an animation
|
||||
|
||||
if (self.anim_reversed) {
|
||||
self.weaponframe = self.weaponframe - 1;
|
||||
} else {
|
||||
self.weaponframe = self.weaponframe + 1;
|
||||
}
|
||||
|
||||
if (self.weaponmodel == "models/weapons/kar/v_kar.mdl" && (self.weapon == W_KAR_SCOPE || self.weapon == W_HEADCRACKER))
|
||||
{
|
||||
self.weapon2model = "models/weapons/kar/v_karscope.mdl";
|
||||
self.weapon2frame = self.weaponframe;
|
||||
//self.weapon2skin = self.weaponskin;
|
||||
}
|
||||
else if (self.weaponmodel == "progs/VModels/v_knife.mdl" || self.weaponmodel == "models/machines/v_perk.mdl") {
|
||||
self.weapon2model = "";
|
||||
UpdateV2model(self.weapon2model, 0);
|
||||
}
|
||||
|
||||
if (self.callfuncat)
|
||||
{
|
||||
if (self.weaponframe == self.callfuncat)
|
||||
{
|
||||
if (self.animend)
|
||||
{
|
||||
temp = self.animend;
|
||||
self.animend = SUB_Null;
|
||||
if (temp)
|
||||
temp(S_RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayWeaponSound(self.weapon, self.weapon_anim_type, FALSE, self.weaponframe);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.weaponframe_end = self.weaponframe = GetFrame(self.weapon,BASE_FRAME);
|
||||
self.new_anim_stop = FALSE;
|
||||
self.weapon_anim_type = 0;
|
||||
self.weapon_animduration = 0;
|
||||
self.callfuncat = 0;
|
||||
temp = self.animend;
|
||||
self.animend = SUB_Null;
|
||||
if (temp)
|
||||
temp(S_RIGHT);
|
||||
}
|
||||
};
|
||||
|
||||
void Set_W_Frame (float startframe, float endframe, float duration, float funccalledin, float animtype, void(optional float t) endanimfunc, string set_model, float dontstartnew, float side) =
|
||||
{
|
||||
float math, reversed;
|
||||
|
||||
if (startframe >= endframe) {
|
||||
reversed = true;
|
||||
} else {
|
||||
reversed = false;
|
||||
}
|
||||
|
||||
math = 0;
|
||||
if (duration) {
|
||||
math = duration / (fabs(endframe - startframe) + 1);
|
||||
} else {
|
||||
math = 0.1;
|
||||
}
|
||||
|
||||
if (side == S_RIGHT || side == S_BOTH) {
|
||||
self.weaponframe = startframe;
|
||||
self.weaponframe_end = endframe;
|
||||
self.animend = endanimfunc;
|
||||
self.callfuncat = funccalledin;
|
||||
self.weapon_anim_type = animtype;
|
||||
self.new_anim_stop = dontstartnew;
|
||||
self.weapon_animduration = math;
|
||||
self.anim_reversed = reversed;
|
||||
}
|
||||
if (side == S_LEFT || side == S_BOTH) {
|
||||
self.weapon2frame = startframe;
|
||||
self.weapon2frame_end = endframe;
|
||||
self.weapon2_anim_type = animtype;
|
||||
self.new_anim2_stop = dontstartnew;
|
||||
self.weapon2_animduration = math;
|
||||
self.anim2_reversed = reversed;
|
||||
|
||||
if (side != S_BOTH) {
|
||||
self.animend2 = endanimfunc;
|
||||
self.callfuncat2 = funccalledin;
|
||||
}
|
||||
}
|
||||
|
||||
if ((startframe != endframe) && !(self.zoom == 2)) { // naievil -- latter used for checkhold
|
||||
if (side == S_LEFT) {
|
||||
self.weapon2model = set_model;
|
||||
UpdateV2model(self.weapon2model, GetWepSkin(self.weapon));
|
||||
} else {
|
||||
self.weaponmodel = set_model;
|
||||
|
||||
if (set_model != "models/machines/v_perk.mdl")
|
||||
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
|
||||
else
|
||||
UpdateVmodel(self.weaponmodel, self.weaponskin);
|
||||
|
||||
|
||||
if (set_model == "progs/VModels/v_nade.mdl" || set_model == "progs/VModels/v_betty.mdl") {
|
||||
self.weapon2model = "";
|
||||
UpdateV2model(self.weapon2model, 0);
|
||||
} else if (self.weapon == W_KAR_SCOPE) {
|
||||
self.weapon2model = "models/weapons/kar/v_karscope.mdl";
|
||||
UpdateV2model(self.weapon2model, 0);
|
||||
} else if (IsDualWeapon(self.weapon)) {
|
||||
self.weapon2model = GetLeftWeaponModel(self.weapon);
|
||||
UpdateV2model(self.weapon2model, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2526
source/server/weapons/weapon_core.qc
Normal file
2526
source/server/weapons/weapon_core.qc
Normal file
File diff suppressed because it is too large
Load diff
221
source/shared/defs/custom.qc
Normal file
221
source/shared/defs/custom.qc
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
shared/defs/custom.qc
|
||||
|
||||
shared definitions
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
const float EVENT_WEAPONCHANGE = 9;
|
||||
const float EVENT_PISTOLFIRE = 10;
|
||||
const float EVENT_USEPRINT = 11;
|
||||
const float EVENT_NEWROUND = 12;
|
||||
const float EVENT_SETROUND = 13;
|
||||
const float EVENT_UPDATEVMODEL = 20;
|
||||
const float EVENT_UPDATEV2MODEL = 21;
|
||||
const float EVENT_PERK = 22;
|
||||
const float EVENT_UPDATE = 23;
|
||||
const float EVENT_BROADCAST = 24;
|
||||
const float EVENT_POINTUPDATE = 25;
|
||||
const float EVENT_BLACKOUT = 26;
|
||||
const float EVENT_PUNCHANGLE = 27;
|
||||
const float EVENT_SCROLLTEXT = 28;
|
||||
const float EVENT_WORLDDATA = 29;
|
||||
const float EVENT_ACHIEVEMENT = 30;
|
||||
const float EVENT_PLAYERUPDATE = 31;
|
||||
const float EVENT_WEAPONUPDATE = 32;
|
||||
const float EVENT_HUDUPDATE = 33;
|
||||
const float EVENT_EXPLOSION = 34;
|
||||
const float EVENT_BLOOD = 35;
|
||||
const float EVENT_ACHIEVEMENTPROGRESS = 36;
|
||||
|
||||
// Define our PC version if we don't have NX or PSP
|
||||
#ifndef NX
|
||||
#ifndef PSP
|
||||
#define PC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//nzp weapon defines
|
||||
//id list
|
||||
#define W_NOWEP 0
|
||||
#define W_COLT 1
|
||||
#define W_KAR 2
|
||||
#define W_THOMPSON 3
|
||||
#define W_357 4
|
||||
#define W_BAR 5
|
||||
#define W_BK 6
|
||||
#define W_BROWNING 7
|
||||
#define W_DB 8
|
||||
#define W_FG 9
|
||||
#define W_GEWEHR 10
|
||||
#define W_KAR_SCOPE 11
|
||||
#define W_M1 12
|
||||
#define W_M1A1 13
|
||||
#define W_M2 14
|
||||
#define W_MP40 15
|
||||
#define W_MG 16
|
||||
#define W_PANZER 17
|
||||
#define W_PPSH 18
|
||||
#define W_PTRS 19
|
||||
#define W_RAY 20
|
||||
#define W_SAWNOFF 21
|
||||
#define W_STG 22
|
||||
#define W_TRENCH 23
|
||||
#define W_TYPE 24
|
||||
#define W_BOWIE 25
|
||||
#define W_GRENADE 26
|
||||
#define W_BETTY 27
|
||||
#define W_BIATCH 28
|
||||
#define W_KILLU 29 //357
|
||||
#define W_COMPRESSOR 30 // Gewehr
|
||||
#define W_M1000 31 //garand
|
||||
//#define W_KOLLIDER 32
|
||||
#define W_PORTER 33 // Ray
|
||||
#define W_WIDDER 34 // M1A1
|
||||
#define W_FIW 35 //upgraded flamethrower
|
||||
#define W_ARMAGEDDON 36 //Kar
|
||||
#define W_WUNDER 37
|
||||
#define W_GIBS 38 // thompson
|
||||
#define W_SAMURAI 39 //Type
|
||||
#define W_AFTERBURNER 40 //mp40
|
||||
#define W_SPATZ 41 // stg
|
||||
#define W_SNUFF 42 // sawn off
|
||||
#define W_BORE 43 // double barrel
|
||||
#define W_IMPELLER 44 //fg
|
||||
#define W_BARRACUDA 45 //mg42
|
||||
#define W_ACCELERATOR 46 //M1919 browning
|
||||
#define W_GUT 47 //trench
|
||||
#define W_REAPER 48 //ppsh
|
||||
#define W_HEADCRACKER 49 //scoped kar
|
||||
#define W_LONGINUS 50 //panzer
|
||||
#define W_PENETRATOR 51 //ptrs
|
||||
#define W_WIDOW 52 //bar
|
||||
//#define W_KRAUS 53 //ballistic
|
||||
#define W_MP5 54
|
||||
#define W_M14 55
|
||||
|
||||
#define W_TESLA 56
|
||||
#define W_DG3 57
|
||||
|
||||
//Custom Weapons
|
||||
//FIXME - use array?
|
||||
#define W_CUSTOM1 70
|
||||
#define W_CUSTOM2 71
|
||||
#define W_CUSTOM3 72
|
||||
#define W_CUSTOM4 73
|
||||
|
||||
|
||||
#define BASE_FRAME 1
|
||||
#define FIRE_START 2
|
||||
#define FIRE_END 3
|
||||
#define RELOAD_START 4
|
||||
#define RELOAD_END 5
|
||||
#define SPRINT_IN_START 12
|
||||
#define SPRINT_IN_END 13
|
||||
#define SPRINT_START 10
|
||||
#define SPRINT_END 11
|
||||
#define SPRINT_OUT_START 14
|
||||
#define SPRINT_OUT_END 15
|
||||
#define TAKE_OUT_START 16
|
||||
#define TAKE_OUT_END 17
|
||||
#define PUT_OUT_START 18
|
||||
#define PUT_OUT_END 19
|
||||
#define RELOAD_CANCEL 20
|
||||
#define AIM_IN_START 30
|
||||
#define AIM_IN_END 31
|
||||
#define AIM_LOOP 33
|
||||
#define AIM_OUT_START 34
|
||||
#define AIM_OUT_END 35
|
||||
#define AIM_FIRE_START 36
|
||||
#define AIM_FIRE_END 37
|
||||
|
||||
//Animation types
|
||||
#define RELOAD 1
|
||||
#define GRENADE 2
|
||||
#define FIRE 3
|
||||
#define SWITCHWEP 4
|
||||
#define KNIFE 5
|
||||
#define ZOOM 6
|
||||
#define SPRINT 7
|
||||
#define PERK 8
|
||||
#define KNIFE2 9
|
||||
#define REVIVE 10
|
||||
|
||||
#define S_HEADSHOT 1
|
||||
#define S_KNIFE 2
|
||||
#define S_NORMAL 3
|
||||
#define S_ZOMBIE 4
|
||||
#define S_EXPLOSIVE 5
|
||||
#define S_ZAPPER 6
|
||||
#define S_TESLA 7
|
||||
|
||||
//Perk types
|
||||
#define P_JUG 1
|
||||
#define P_DOUBLE 2
|
||||
#define P_SPEED 4
|
||||
#define P_REVIVE 8
|
||||
#define P_FLOP 16
|
||||
#define P_STAMIN 32
|
||||
#define P_DEAD 64
|
||||
#define P_MULE 128
|
||||
|
||||
#define STAT_VIEWZOOM 21
|
||||
|
||||
#define STAT_CURRENTMAG 50
|
||||
#define STAT_CURRENTMAG2 51
|
||||
#define STAT_POINTS 52
|
||||
#define STAT_WEAPON2FRAME 53
|
||||
#define STAT_WEAPON2MODEL 54
|
||||
#define STAT_GRENADES 55
|
||||
#define STAT_SECGRENADES 56
|
||||
#define STAT_PROGRESSBAR 57
|
||||
#define STAT_WEAPONDURATION 58
|
||||
#define STAT_WEAPON2DURATION 59
|
||||
#define STAT_WEAPONZOOM 60
|
||||
#define STAT_INSTA 61
|
||||
#define STAT_X2 62
|
||||
#define STAT_SPECTATING 63
|
||||
#define STAT_PLAYERNUM 64
|
||||
#define STAT_PLAYERSTANCE 65
|
||||
#define STAT_FACINGENEMY 66
|
||||
|
||||
//
|
||||
// invert float takes in float value between 0 and 1, inverts position
|
||||
// eg: 0.1 returns 0.9, 0.34 returns 0.66
|
||||
float invertfloat(float input) {
|
||||
|
||||
if (input <= 0 || input >= 1)
|
||||
return input; // out of boundaries
|
||||
|
||||
return (1 - input);
|
||||
}
|
||||
|
||||
//elements
|
||||
#ifndef NX
|
||||
string G_HUD;
|
||||
float G_HUDHOR;
|
||||
#endif
|
||||
|
||||
// custom weapon defs
|
||||
// now 90% slimmed down
|
||||
float currentWeaponTracker;
|
52
source/shared/sound_enhanced.qc
Normal file
52
source/shared/sound_enhanced.qc
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
shared/sound_enhanced.qc
|
||||
|
||||
mainly serves as a QC middleground for sound to adjust volume per
|
||||
channel.
|
||||
|
||||
Copyright (C) 2021 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#define CHAN_MUSIC 1
|
||||
#define CHAN_SFX 2
|
||||
|
||||
#ifndef PSP
|
||||
#ifndef NX
|
||||
void(string soundname, optional float channel, optional float volume) localsound_enhanced =
|
||||
{
|
||||
if (!volume)
|
||||
volume = 1;
|
||||
|
||||
switch(channel) {
|
||||
case 1: volume *= cvar("snd_channel1volume"); break;
|
||||
case 2: volume *= cvar("snd_channel2volume"); break;
|
||||
case 3: volume *= cvar("snd_channel3volume"); break;
|
||||
case 4: volume *= cvar("snd_channel4volume"); break;
|
||||
case 5: volume *= cvar("snd_channel5volume"); break;
|
||||
case 6: volume *= cvar("snd_channel6volume"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
localsound(soundname, channel, volume);
|
||||
}
|
||||
#endif
|
||||
#endif
|
4219
source/shared/weapon_defines.qc
Normal file
4219
source/shared/weapon_defines.qc
Normal file
File diff suppressed because it is too large
Load diff
36
tools/qc-compiler-lin.sh
Normal file
36
tools/qc-compiler-lin.sh
Normal file
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cd ../
|
||||
# create build directories
|
||||
mkdir -p build/{pc,psp,nx,vita}
|
||||
cd bin/
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo " compiling FTE CCQC "
|
||||
echo "===================="
|
||||
echo ""
|
||||
./fteqcc-cli-lin -srcfile ../progs/fte-client.src
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo " compiling FTE SSQC "
|
||||
echo "===================="
|
||||
echo ""
|
||||
./fteqcc-cli-lin -srcfile ../progs/fte-server.src
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo " compiling PSP QC "
|
||||
echo "===================="
|
||||
echo ""
|
||||
./fteqcc-cli-lin -srcfile ../progs/psp.src
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo " compiling NX-QS QC "
|
||||
echo "===================="
|
||||
echo ""
|
||||
./fteqcc-cli-lin -srcfile ../progs/nx.src
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo " compiling VITA QC "
|
||||
echo "===================="
|
||||
echo ""
|
||||
./fteqcc-cli-lin -srcfile ../progs/vita.src
|
39
tools/qc-compiler-win.bat
Normal file
39
tools/qc-compiler-win.bat
Normal file
|
@ -0,0 +1,39 @@
|
|||
@ECHO OFF
|
||||
CD ../
|
||||
REM ****** create build directories ******
|
||||
MKDIR build\pc\ 2>nul
|
||||
MKDIR build\psp\ 2>nul
|
||||
MKDIR build\nx\ 2>nul
|
||||
MKDIR build\vita\ 2>nul
|
||||
CD bin/
|
||||
echo.
|
||||
echo ====================
|
||||
echo compiling FTE CCQC
|
||||
echo ====================
|
||||
echo.
|
||||
fteqcc-cli-win.exe -srcfile ../progs/fte-client.src
|
||||
echo.
|
||||
echo ====================
|
||||
echo compiling FTE SSQC
|
||||
echo ====================
|
||||
echo.
|
||||
fteqcc-cli-win.exe -srcfile ../progs/fte-server.src
|
||||
echo.
|
||||
echo ====================
|
||||
echo compiling PSP QC
|
||||
echo ====================
|
||||
echo.
|
||||
fteqcc-cli-win.exe -srcfile ../progs/psp.src
|
||||
echo.
|
||||
echo ====================
|
||||
echo compiling NX-QS QC
|
||||
echo ====================
|
||||
echo.
|
||||
fteqcc-cli-win.exe -srcfile ../progs/nx.src
|
||||
echo.
|
||||
echo ====================
|
||||
echo compiling VITA QC
|
||||
echo ====================
|
||||
echo.
|
||||
fteqcc-cli-win.exe -srcfile ../progs/vita.src
|
||||
pause
|
Loading…
Reference in a new issue