pax_global_header00006660000000000000000000000064147732006610014520gustar00rootroot0000000000000052 comment=71d4b88ddfc66e2274a9a2719d7f9e979e09f67e rogue-ROGUE_2_13/000077500000000000000000000000001477320066100136105ustar00rootroot00000000000000rogue-ROGUE_2_13/.github/000077500000000000000000000000001477320066100151505ustar00rootroot00000000000000rogue-ROGUE_2_13/.github/workflows/000077500000000000000000000000001477320066100172055ustar00rootroot00000000000000rogue-ROGUE_2_13/.github/workflows/linux_aarch64.yml000066400000000000000000000027221477320066100224020ustar00rootroot00000000000000name: Testbuild for Linux (aarch64) run-name: testbuild_linux_aarch64 on: push: branches: - 'master' pull_request: types: - edited - opened - synchronize concurrency: # Cancel concurrent workflows for the same PR or commit hash. group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} cancel-in-progress: true jobs: build_ubuntu_arm: runs-on: ubuntu-22.04-arm strategy: fail-fast: false matrix: include: - env: ubuntu steps: - name: Check out repository code uses: actions/checkout@v4 - name: Build run: | # Public runners come with 4 CPUs. make -j4 - name: Create testbuild package run: | # Create release directory tree mkdir -p publish/quake2-rogue-linux_aarch64-${{github.sha}}/misc/docs # Copy release assets cp -r release/* publish/quake2-rogue-linux_aarch64-${{github.sha}}/ # Copy misc assets cp -r stuff/mapfixes publish/quake2-rogue-linux_aarch64-${{github.sha}}/misc cp LICENSE publish/quake2-rogue-linux_aarch64-${{github.sha}}/misc/docs/LICENSE.txt cp README.md publish/quake2-rogue-linux_aarch64-${{github.sha}}/misc/docs/README.txt - name: Upload testbuild package uses: actions/upload-artifact@v4 with: name: quake2-rogue-linux_aarch64-${{github.sha}} path: publish/ if-no-files-found: error rogue-ROGUE_2_13/.github/workflows/linux_x86_64.yml000066400000000000000000000027111477320066100221060ustar00rootroot00000000000000name: Testbuild for Linux (x86_64) run-name: testbuild_linux_x86_64 on: push: branches: - 'master' pull_request: types: - edited - opened - synchronize concurrency: # Cancel concurrent workflows for the same PR or commit hash. group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} cancel-in-progress: true jobs: build_ubuntu_x86_64: runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - env: ubuntu steps: - name: Check out repository code uses: actions/checkout@v4 - name: Build run: | # Public runners come with 4 CPUs. make -j4 - name: Create testbuild package run: | # Create release directory tree mkdir -p publish/quake2-rogue-linux_x86_64-${{github.sha}}/misc/docs # Copy release assets cp -r release/* publish/quake2-rogue-linux_x86_64-${{github.sha}}/ # Copy misc assets cp -r stuff/mapfixes publish/quake2-rogue-linux_x86_64-${{github.sha}}/misc cp LICENSE publish/quake2-rogue-linux_x86_64-${{github.sha}}/misc/docs/LICENSE.txt cp README.md publish/quake2-rogue-linux_x86_64-${{github.sha}}/misc/docs/README.txt - name: Upload testbuild package uses: actions/upload-artifact@v4 with: name: quake2-rogue-linux_x86_64-${{github.sha}} path: publish/ if-no-files-found: error rogue-ROGUE_2_13/.github/workflows/macos.yml000066400000000000000000000027611477320066100210400ustar00rootroot00000000000000name: Testbuild for MacOS run-name: testbuild_macos on: push: branches: - 'master' pull_request: types: - edited - opened - synchronize concurrency: # Cancel concurrent workflows for the same PR or commit hash. group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} cancel-in-progress: true jobs: build_macos_aarch64: runs-on: macos-latest strategy: fail-fast: false matrix: include: - env: macos steps: - name: Install build dependencies run: | brew update brew install make - name: Check out repository code uses: actions/checkout@v4 - name: Build run: | # Public runners come with 3 CPUs. gmake -j3 - name: Create testbuild package run: | # Create release directory tree mkdir -p publish/quake2-rogue-macos-${{github.sha}}/misc/docs # Copy release assets cp -r release/* publish/quake2-rogue-macos-${{github.sha}}/ # Copy misc assets cp -r stuff/mapfixes publish/quake2-rogue-macos-${{github.sha}}/misc cp LICENSE publish/quake2-rogue-macos-${{github.sha}}/misc/docs/LICENSE.txt cp README.md publish/quake2-rogue-macos-${{github.sha}}/misc/docs/README.txt - name: Upload testbuild package uses: actions/upload-artifact@v4 with: name: quake2-rogue-macos-${{github.sha}} path: publish/ if-no-files-found: error rogue-ROGUE_2_13/.github/workflows/win32.yml000066400000000000000000000032631477320066100206760ustar00rootroot00000000000000name: Testbuild for Win32 run-name: testbuild_win32 on: push: branches: - 'master' pull_request: types: - edited - opened - synchronize concurrency: # Cancel concurrent workflows for the same PR or commit hash. group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} cancel-in-progress: true jobs: build_mingw_x86_32: runs-on: windows-latest strategy: fail-fast: false matrix: include: - { sys: mingw32, env: i686 } steps: - uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.sys}} update: true install: >- git make mingw-w64-${{matrix.env}}-gcc mingw-w64-${{matrix.env}}-make - name: Check out repository code uses: actions/checkout@v4 - name: Build shell: msys2 {0} run: | # Public runners come with 4 CPUs. make -j4 - name: Create testbuild package shell: msys2 {0} run: | # Create release directory tree mkdir -p publish/quake2-rogue-win32-${{github.sha}}/misc/docs # Copy release assets cp -r release/* publish/quake2-rogue-win32-${{github.sha}}/ # Copy misc assets cp -r stuff/mapfixes publish/quake2-rogue-win32-${{github.sha}}/misc cp LICENSE publish/quake2-rogue-win32-${{github.sha}}/misc/docs/LICENSE.txt cp README.md publish/quake2-rogue-win32-${{github.sha}}/misc/docs/README.txt - name: Upload testbuild package uses: actions/upload-artifact@v4 with: name: quake2-rogue-win32-${{github.sha}} path: publish/ if-no-files-found: error rogue-ROGUE_2_13/.github/workflows/win64.yml000066400000000000000000000032651477320066100207050ustar00rootroot00000000000000name: Testbuild for Win64 run-name: testbuild_win64 on: push: branches: - 'master' pull_request: types: - edited - opened - synchronize concurrency: # Cancel concurrent workflows for the same PR or commit hash. group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} cancel-in-progress: true jobs: build_mingw_x86_64: runs-on: windows-latest strategy: fail-fast: false matrix: include: - { sys: mingw64, env: x86_64 } steps: - uses: msys2/setup-msys2@v2 with: msystem: ${{matrix.sys}} update: true install: >- git make mingw-w64-${{matrix.env}}-gcc mingw-w64-${{matrix.env}}-make - name: Check out repository code uses: actions/checkout@v4 - name: Build shell: msys2 {0} run: | # Public runners come with 4 CPUs. make -j4 - name: Create testbuild package shell: msys2 {0} run: | # Create release directory tree mkdir -p publish/quake2-rogue-win64-${{github.sha}}/misc/docs # Copy release assets cp -r release/* publish/quake2-rogue-win64-${{github.sha}}/ # Copy misc assets cp -r stuff/mapfixes publish/quake2-rogue-win64-${{github.sha}}/misc cp LICENSE publish/quake2-rogue-win64-${{github.sha}}/misc/docs/LICENSE.txt cp README.md publish/quake2-rogue-win64-${{github.sha}}/misc/docs/README.txt - name: Upload testbuild package uses: actions/upload-artifact@v4 with: name: quake2-rogue-win64-${{github.sha}} path: publish/ if-no-files-found: error rogue-ROGUE_2_13/.gitignore000066400000000000000000000000211477320066100155710ustar00rootroot00000000000000/build/ /release/rogue-ROGUE_2_13/CHANGELOG000066400000000000000000000125351477320066100150300ustar00rootroot00000000000000Ground Zero 2.12 to 2.13 - Add weapon preview to the `cycleweap` command (by protocultor) - Fix leaking temporary spawnflags into entities spawned mid-level. (by BjossiAlfreds) Ground Zero 2.11 to 2.12 - Implement `g_quick_weap`. If set to 1, both weapprev and weapnext commands will count how many times they have been called, making possible to skip weapons by quickly tapping one of these keys. (by protocultor) - Work around naggy help icons. (by BjossiAlfreds) - Implement `g_monsterfootsteps` (by 0lvin) Ground Zero 2.10 to 2.11 - Relicense under GPL2. - Fix Entity used itself in rbase1 and other minor fixes. (by BjossiAlfreds) - Some fixes for rsewer1. (by BjossiAlfreds) - Fix minor AI glitches with turrets (by BjossiAlfreds) - Fixed nagging help message in rhangar2. (by BjossiAlfreds) - Fixed gunner grenade duck code running twice. (by BjossiAlfreds) - Fixed wrong Tank muzzle flash. (by BjossiAlfreds) - Implement `g_swap_speed`. This allows to skip frames of "putting down weapon" and "raising weapon" animations, speeding them up. (by protocultor) - Several fixes to makron (by BjossiAlfreds) - Fixed stand-ground gladiators not attacking at certain range. (by BjossiAlfreds) - Fixed monsters seeing players during intermissions. (by BjossiAlfreds) Ground Zero 2.09 to 2.10 - Implement faster weapon switching with the new 'cycleweap' command. (by protocultor). - Fixes pusher delta yaw manipulation. This fixes the infamous bug were a player standing on a blocked elevator gets turned around (by skuller). - Fix several coop related bugs with the powercubes. (by BjossiAlfreds) - A way better fix for dead bodies obstructing elevators or falling through the worldmodel. (by BjossiAlfreds) - Fix items already in water playing a splash sound at level start. (by BjossiAlfreds) Ground Zero 2.08 to 2.09 - Refine the 'g_footstep' cvar to match Quake II itself. - Implement 'g_machinegun_norecoil'. The cvar is cheat protected. (by De-Seppe) - Update the entity files for rmine1, rsewer2 and rware2, fixing some smaller map bugs. (by BjossiAlfreds and Dremor8484) - Fix soldiers never showing their pain skins as long as they're alive. (by BjossiAlfreds) - Implement the 'prefweap' command to select a weapon by priority. (by protocultor) Ground Zero 2.07 to 2.08 - Fix wrong sound for some items when activated. (by BjossiAlfreds) - Port the 'aimfix' cvar. (by Mitchell Richters) - Port the 'coop_pickup_weapons' and 'coop_elevator_delay' cvars. - Fix a long standing crash occuring when exploding projectiles like grenates or rockets generate sound targets and a least one monster starts moving to one of that targets. - Add a cvar `g_footsteps` to control the generation of footstep sound. - Move several hard coded map fixes to entity files. Add newly discovered mapfixes to the entity files. (by BjossiAlfreds) - Fix several subtile gameplay and entity handling bug. (by BjossiAlfreds) Ground Zero 2.06 to 2.07 - Several fixes for subtile bugs (by BjossiAlfreds) Ground Zero 2.05 to 2.06 - New commands: 'listentities' allows listing of entities. 'teleport' teleports the player to the given coordinates. - A lot of fixes for subtle, long standing AI and game play bugs. (by BjossiAlfreds) - Fix problem found by PVS studio. (analysis by demoth and fixes by BjossiAlfreds) - Add back Ground Zero specific monster behaviors, lost during initial merge in 2008. (by BjossiAlfreds) Ground Zero 2.04 to 2.05 - Fix the parasite not attacking the player in some situations. - Small bugfixes and better support the the current version of the Windows build environment. Ground Zero 2.03 to 2.04 - Fix a lot of potential crashes. (reported by Maarakate) - Fix monsters running in place. - Fix monsters not recognizing the player under some circumstances. - Fix monsters getting stuck when resurrected by a medic. Ground Zero 2.02 to 2.03 - Make gibs and debris SOLID_BBOX so they move on entities. - Switch from an arch whitelist to an "all archs are supported" approach. Ground Zero 2.01 to 2.02 - Added CMake as an optional build system. - Fix bug with high velocities in vents in 32bit builds. Ground Zero 2.00 to 2.01 - Coop bugfixes Ground Zero 1.07 to 2.00 - Cleanup of the whole source, nearly every line was audited and touched. - Add sanity checks to all function. - Fix all known bugs. - Merge all missing changes from baseq2. Ground Zero 1.06 to 1.07 - Port 'Ground Zero' to Mac OS X. Ground Zero 1.05 to 1.06 - Port 'Ground Zero' to Windows. - Use randk() instead of rand(), a better PNRG. - Fix some potential problems found by scan-build. Ground Zero 1.04 to 1.05 - Port new savegame system from baseq2 - Reorder files to reflect the new structure of baseq2 Ground Zero 1.03 to 1.04: - Fix a crash when a proxy mine is attached to a flying enemy - Fix a crash in coop when multible rockets are in flight (by caedes) - Reformat the console output Ground Zero 1.03RC3 to 1.03: - Just version number change Ground Zero 1.03RC2 to 1.03RC3: - Saner CFLAGS - Do not show the gun symbol when fov is bigger than 91 and cl_gun is set to 2 Ground Zero 1.03RC to 1.03RC2: - Slightly better performance (~10 FPS) Ground Zero 1.02 to 1.03RC: - Fix a rare crash with the Proxy Mine Launcher (reported by E. Müller) - Tesla Coils explode when touching lava or slime (reported by ogrish_freak [at] gmail [dot] com) Ground Zero 1.01 to 1.02: - Added License - Added Readme rogue-ROGUE_2_13/CMakeLists.txt000066400000000000000000000102371477320066100163530ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0) # Print a message that using the Makefiles is recommended. message(NOTICE: " The CMakeLists.txt is unmaintained. Use the Makefile if possible.") # Enforce "Debug" as standard build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif(NOT CMAKE_BUILD_TYPE) # CMake project configuration project(yquake2-rogue) # Enforce compiler flags (GCC / Clang compatible, yquake2 # won't build with another compiler anyways) # -Wall -> More warnings # -fno-strict-aliasing -> Quake 2 is far away from strict aliasing # -fwrapv -> Make signed integer overflows defined set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fno-strict-aliasing -fwrapv") # Use -O2 as maximum optimization level. -O3 has it's problems with yquake2. string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Operating system add_definitions(-DYQ2OSTYPE="${CMAKE_SYSTEM_NAME}") # Architecture string string(REGEX REPLACE "amd64" "x86_64" YQ2_ARCH "${CMAKE_SYSTEM_PROCESSOR}") string(REGEX REPLACE "i.86" "i386" YQ2_ARCH "${YQ2_ARCH}") string(REGEX REPLACE "^arm.*" "arm" YQ2_ARCH "${YQ2_ARCH}") add_definitions(-DYQ2ARCH="${YQ2_ARCH}") # Linker Flags if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") list(APPEND RogueLinkerFlags "-lm") else() list(APPEND RogueLinkerFlags "-lm -rdynamic") endif() set(Rogue-Source src/dm/ball.c src/dm/tag.c src/monster/berserker/berserker.c src/monster/boss2/boss2.c src/monster/boss3/boss3.c src/monster/boss3/boss31.c src/monster/boss3/boss32.c src/monster/brain/brain.c src/monster/carrier/carrier.c src/monster/chick/chick.c src/monster/flipper/flipper.c src/monster/float/float.c src/monster/flyer/flyer.c src/monster/gladiator/gladiator.c src/monster/gunner/gunner.c src/monster/hover/hover.c src/monster/infantry/infantry.c src/monster/insane/insane.c src/monster/medic/medic.c src/monster/misc/move.c src/monster/mutant/mutant.c src/monster/parasite/parasite.c src/monster/soldier/soldier.c src/monster/stalker/stalker.c src/monster/supertank/supertank.c src/monster/tank/tank.c src/monster/turret/turret.c src/monster/widow/widow.c src/monster/widow/widow2.c src/player/client.c src/player/hud.c src/player/trail.c src/player/view.c src/player/weapon.c src/savegame/savegame.c src/shared/flash.c src/shared/rand.c src/shared/shared.c src/g_ai.c src/g_chase.c src/g_cmds.c src/g_combat.c src/g_func.c src/g_items.c src/g_main.c src/g_misc.c src/g_monster.c src/g_newai.c src/g_newdm.c src/g_newfnc.c src/g_newtarg.c src/g_newtrig.c src/g_newweap.c src/g_phys.c src/g_spawn.c src/g_sphere.c src/g_svcmds.c src/g_target.c src/g_trigger.c src/g_turret.c src/g_utils.c src/g_weapon.c ) set(Rogue-Header src/header/game.h src/header/local.h src/header/shared.h src/monster/berserker/berserker.h src/monster/boss2/boss2.h src/monster/boss3/boss31.h src/monster/boss3/boss32.h src/monster/brain/brain.h src/monster/carrier/carrier.h src/monster/chick/chick.h src/monster/flipper/flipper.h src/monster/float/float.h src/monster/flyer/flyer.h src/monster/gladiator/gladiator.h src/monster/gunner/gunner.h src/monster/hover/hover.h src/monster/infantry/infantry.h src/monster/insane/insane.h src/monster/medic/medic.h src/monster/misc/player.h src/monster/mutant/mutant.h src/monster/parasite/parasite.h src/monster/soldier/soldier.h src/monster/stalker/stalker.h src/monster/supertank/supertank.h src/monster/tank/tank.h src/monster/turret/turret.h src/monster/widow/widow.h src/monster/widow/widow2.h src/savegame/tables/clientfields.h src/savegame/tables/fields.h src/savegame/tables/gamefunc_decs.h src/savegame/tables/gamefunc_list.h src/savegame/tables/gamemmove_decs.h src/savegame/tables/gamemmove_list.h src/savegame/tables/levelfields.h ) # Build the rogue dynamic library add_library(game SHARED ${Rogue-Source} ${Rogue-Header}) set_target_properties(game PROPERTIES PREFIX "" LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release ) target_link_libraries(game ${RogueLinkerFlags}) rogue-ROGUE_2_13/LICENSE000066400000000000000000000431101477320066100146140ustar00rootroot00000000000000 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. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. rogue-ROGUE_2_13/Makefile000066400000000000000000000175071477320066100152620ustar00rootroot00000000000000# ----------------------------------------------------- # # Makefile for the rogue game module for Quake II # # # # Just type "make" to compile the # # - Ground Zero Game (game.so) # # # # Dependencies: # # - None, but you need a Quake II to play. # # While in theory every client should work # # Yamagi Quake II is recommended. # # # # Platforms: # # - FreeBSD # # - Linux # # - Mac OS X # # - OpenBSD # # - Windows # # ----------------------------------------------------- # # Detect the OS ifdef SystemRoot YQ2_OSTYPE ?= Windows else YQ2_OSTYPE ?= $(shell uname -s) endif # Special case for MinGW ifneq (,$(findstring MINGW,$(YQ2_OSTYPE))) YQ2_OSTYPE := Windows endif # Detect the architecture ifeq ($(YQ2_OSTYPE), Windows) ifdef MINGW_CHOST ifeq ($(MINGW_CHOST), x86_64-w64-mingw32) YQ2_ARCH ?= x86_64 else # i686-w64-mingw32 YQ2_ARCH ?= i386 endif else # windows, but MINGW_CHOST not defined ifdef PROCESSOR_ARCHITEW6432 # 64 bit Windows YQ2_ARCH ?= $(PROCESSOR_ARCHITEW6432) else # 32 bit Windows YQ2_ARCH ?= $(PROCESSOR_ARCHITECTURE) endif endif # windows but MINGW_CHOST not defined else ifneq ($(YQ2_OSTYPE), Darwin) # Normalize some abiguous YQ2_ARCH strings YQ2_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/arm64/aarch64/' -e 's/^arm.*/arm/') else YQ2_ARCH ?= $(shell uname -m) endif endif # On Windows / MinGW $(CC) is undefined by default. ifeq ($(YQ2_OSTYPE),Windows) CC ?= gcc endif # Detect the compiler ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) COMPILER := clang COMPILERVER := $(shell $(CC) -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/') else ifeq ($(shell $(CC) -v 2>&1 | grep -c -E "(gcc version|gcc-Version)"), 1) COMPILER := gcc COMPILERVER := $(shell $(CC) -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/') else COMPILER := unknown endif # ---------- # Base CFLAGS. These may be overridden by the environment. # Highest supported optimizations are -O2, higher levels # will likely break this crappy code. ifdef DEBUG CFLAGS ?= -O0 -g -Wall -pipe else CFLAGS ?= -O2 -Wall -pipe -fomit-frame-pointer endif # Always needed are: # -fno-strict-aliasing since the source doesn't comply # with strict aliasing rules and it's next to impossible # to get it there... # -fwrapv for defined integer wrapping. MSVC6 did this # and the game code requires it. override CFLAGS += -fno-strict-aliasing -fwrapv # -MMD to generate header dependencies. Unsupported by # the Clang shipped with OS X. ifneq ($(YQ2_OSTYPE), Darwin) override CFLAGS += -MMD endif # OS X architecture. ifeq ($(YQ2_OSTYPE), Darwin) override CFLAGS += -arch $(YQ2_ARCH) endif # ---------- # Switch of some annoying warnings. ifeq ($(COMPILER), clang) # -Wno-missing-braces because otherwise clang complains # about totally valid 'vec3_t bla = {0}' constructs. CFLAGS += -Wno-missing-braces else ifeq ($(COMPILER), gcc) # GCC 8.0 or higher. ifeq ($(shell test $(COMPILERVER) -ge 80000; echo $$?),0) # -Wno-format-truncation and -Wno-format-overflow # because GCC spams about 50 false positives. CFLAGS += -Wno-format-truncation -Wno-format-overflow endif endif # ---------- # Defines the operating system and architecture override CFLAGS += -DYQ2OSTYPE=\"$(YQ2_OSTYPE)\" -DYQ2ARCH=\"$(YQ2_ARCH)\" # ---------- # For reproduceable builds, look here for details: # https://reproducible-builds.org/specs/source-date-epoch/ ifdef SOURCE_DATE_EPOCH CFLAGS += -DBUILD_DATE=\"$(shell date --utc --date="@${SOURCE_DATE_EPOCH}" +"%b %_d %Y" | sed -e 's/ /\\ /g')\" endif # ---------- # Using the default x87 float math on 32bit x86 causes rounding trouble # -ffloat-store could work around that, but the better solution is to # just enforce SSE - every x86 CPU since Pentium3 supports that # and this should even improve the performance on old CPUs ifeq ($(YQ2_ARCH), i386) override CFLAGS += -msse -mfpmath=sse endif # Force SSE math on x86_64. All sane compilers should do this # anyway, just to protect us from broken Linux distros. ifeq ($(YQ2_ARCH), x86_64) override CFLAGS += -mfpmath=sse endif # ---------- # Base LDFLAGS. LDFLAGS ?= # It's a shared library. override LDFLAGS += -shared # Required libaries ifeq ($(YQ2_OSTYPE), Darwin) override LDFLAGS += -arch $(YQ2_ARCH) else ifeq ($(YQ2_OSTYPE), Windows) override LDFLAGS += -static-libgcc else override LDFLAGS += -lm endif # ---------- # Builds everything all: rogue # ---------- # When make is invoked by "make VERBOSE=1" print # the compiler and linker commands. ifdef VERBOSE Q := else Q := @ endif # ---------- # Phony targets .PHONY : all clean rogue # ---------- # Cleanup clean: @echo "===> CLEAN" ${Q}rm -Rf build release # ---------- # The rogue game ifeq ($(YQ2_OSTYPE), Windows) rogue: @echo "===> Building game.dll" ${Q}mkdir -p release $(MAKE) release/game.dll else ifeq ($(YQ2_OSTYPE), Darwin) rogue: @echo "===> Building game.dylib" ${Q}mkdir -p release $(MAKE) release/game.dylib else rogue: @echo "===> Building game.so" ${Q}mkdir -p release $(MAKE) release/game.so release/game.so : CFLAGS += -fPIC endif build/%.o: %.c @echo "===> CC $<" ${Q}mkdir -p $(@D) ${Q}$(CC) -c $(CFLAGS) -o $@ $< # ---------- ROGUE_OBJS_ = \ src/g_ai.o \ src/g_chase.o \ src/g_cmds.o \ src/g_combat.o \ src/g_func.o \ src/g_items.o \ src/g_main.o \ src/g_misc.o \ src/g_monster.o \ src/g_newai.o \ src/g_newdm.o \ src/g_newfnc.o \ src/g_newtarg.o \ src/g_newtrig.o \ src/g_newweap.o \ src/g_phys.o \ src/g_spawn.o \ src/g_sphere.o \ src/g_svcmds.o \ src/g_target.o \ src/g_trigger.o \ src/g_turret.o \ src/g_utils.o \ src/g_weapon.o \ src/dm/ball.o \ src/dm/tag.o \ src/monster/berserker/berserker.o \ src/monster/boss2/boss2.o \ src/monster/boss3/boss3.o \ src/monster/boss3/boss31.o \ src/monster/boss3/boss32.o \ src/monster/brain/brain.o \ src/monster/carrier/carrier.o \ src/monster/chick/chick.o \ src/monster/flipper/flipper.o \ src/monster/float/float.o \ src/monster/flyer/flyer.o \ src/monster/gladiator/gladiator.o \ src/monster/gunner/gunner.o \ src/monster/hover/hover.o \ src/monster/infantry/infantry.o \ src/monster/insane/insane.o \ src/monster/medic/medic.o \ src/monster/misc/move.o \ src/monster/mutant/mutant.o \ src/monster/parasite/parasite.o \ src/monster/soldier/soldier.o \ src/monster/stalker/stalker.o \ src/monster/supertank/supertank.o \ src/monster/tank/tank.o \ src/monster/turret/turret.o \ src/monster/widow/widow.o \ src/monster/widow/widow2.o \ src/player/client.o \ src/player/hud.o \ src/player/trail.o \ src/player/view.o \ src/player/weapon.o \ src/savegame/savegame.o \ src/shared/flash.o \ src/shared/rand.o \ src/shared/shared.o # ---------- # Rewrite paths to our object directory ROGUE_OBJS = $(patsubst %,build/%,$(ROGUE_OBJS_)) # ---------- # Generate header dependencies ROGUE_DEPS= $(ROGUE_OBJS:.o=.d) # ---------- # Suck header dependencies in -include $(ROGUE_DEPS) # ---------- ifeq ($(YQ2_OSTYPE), Windows) release/game.dll : $(ROGUE_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(ROGUE_OBJS) $(LDFLAGS) else ifeq ($(YQ2_OSTYPE), Darwin) release/game.dylib : $(ROGUE_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(ROGUE_OBJS) $(LDFLAGS) else release/game.so : $(ROGUE_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(ROGUE_OBJS) $(LDFLAGS) endif # ---------- rogue-ROGUE_2_13/README.md000066400000000000000000000043461477320066100150760ustar00rootroot00000000000000# Ground Zero for Yamagi Quake II Ground Zero for Yamagi Quake II is a bugfixed version of the second official missionpack released for Quake II. It's based upon the Quake II SDK source code and licensed under GPL version 2: * [LICENSE](https://github.com/yquake2/rogue/blob/master/LICENSE) Hundreds of bugs were fixed and some convenience features added. The missionpack is intended to be used with Yamagi Quake II, but it's also fully backward compatible with the last Quake II pointrelease 3.20 and may work with other source ports. Officially supported operating systems are: * FreeBSD * Linux * Windows Beside theses Ground Zero for Yamagi Quake II has community support for MacOS and most other unixoid operating systems, including NetBSD, OpenBSD and Solaris. ## Development Ground Zero for Yamagi Quake II is a community driven project and lives from community involvement. Please report bugs in our issue tracker: * [Issue Tracker](https://github.com/yquake2/rogue/issues) We are always open to code contributions, no matter if they are small bugfixes or bigger features. However, Yamagi Quake II is a conservative project with big focus on stability and backward compatibility. We don't accept breaking changes. When in doubt please open an issue and ask if a contribution in welcome before putting too much work into it. Open a pull request to submit code: * [Pull Requests](https://github.com/yquake2/rogue/pulls) Also have a look at our contributors guide: * [Contributors Guide](https://github.com/yquake2/yquake2/blob/master/doc/080_contributing.md) ## Documentation Yamagi Quake II has rather extensive documentation covering all relevant areas from installation and configuration to package building. Have a look at the documentation index: * [Documentation Index](https://github.com/yquake2/yquake2/blob/master/doc/010_index.md) ## Releases Ground Zero for Yamagi Quake II releases at an irregular schedule. The official releases with source code tarballs and prebuild Windows binaries can be found at the homepage: * [Homepage](https://www.yamagi.org/quake2/) Our CI builds **unsupported** Linux, MacOS and Windows binaries at every commit. The artifacts can be found here: * [Github Actions](https://github.com/yquake2/rogue/actions) rogue-ROGUE_2_13/src/000077500000000000000000000000001477320066100143775ustar00rootroot00000000000000rogue-ROGUE_2_13/src/dm/000077500000000000000000000000001477320066100147775ustar00rootroot00000000000000rogue-ROGUE_2_13/src/dm/ball.c000066400000000000000000000341371477320066100160650ustar00rootroot00000000000000/* ======================================================================= * * Deathmatch ball. * * ======================================================================= */ #include "../header/local.h" #define DBALL_GOAL_TEAM1 0x0001 #define DBALL_GOAL_TEAM2 0x0002 #define DBALL_SPEED_ONEWAY 1 edict_t *dball_ball_entity = NULL; int dball_ball_startpt_count; int dball_team1_goalscore; int dball_team2_goalscore; cvar_t *dball_team1_skin; cvar_t *dball_team2_skin; cvar_t *goallimit; extern void EndDMLevel(void); extern void ClientUserinfoChanged(edict_t *ent, char *userinfo); extern void SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles); extern float PlayersRangeFromSpot(edict_t *spot); void DBall_BallDie(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void DBall_BallRespawn(edict_t *self); int DBall_CheckDMRules(void) { if (goallimit && goallimit->value) { if (dball_team1_goalscore >= goallimit->value) { gi.bprintf(PRINT_HIGH, "Team 1 Wins.\n"); } else if (dball_team2_goalscore >= goallimit->value) { gi.bprintf(PRINT_HIGH, "Team 2 Wins.\n"); } else { return 0; } EndDMLevel(); return 1; } return 0; } void DBall_ClientBegin(edict_t *ent) { int team1, team2, unassigned; edict_t *other; char *p; static char value[512]; int j; team1 = 0; team2 = 0; unassigned = 0; if (!ent) { return; } for (j = 1; j <= game.maxclients; j++) { other = &g_edicts[j]; if (!other->inuse) { continue; } if (!other->client) { continue; } if (other == ent) /* don't count the new player */ { continue; } strcpy(value, Info_ValueForKey(other->client->pers.userinfo, "skin")); p = strchr(value, '/'); if (p) { if (!strcmp(dball_team1_skin->string, value)) { team1++; } else if (!strcmp(dball_team2_skin->string, value)) { team2++; } else { unassigned++; } } else { unassigned++; } } if (team1 > team2) { gi.dprintf("assigned to team 2\n"); Info_SetValueForKey(ent->client->pers.userinfo, "skin", dball_team2_skin->string); } else { gi.dprintf("assigned to team 1\n"); Info_SetValueForKey(ent->client->pers.userinfo, "skin", dball_team1_skin->string); } ClientUserinfoChanged(ent, ent->client->pers.userinfo); if (unassigned) { gi.dprintf("%d unassigned players present!\n", unassigned); } } void DBall_SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles) { edict_t *bestspot; float bestdistance, bestplayerdistance; edict_t *spot; char *spottype; char skin[512]; if (!ent) { return; } strcpy(skin, Info_ValueForKey(ent->client->pers.userinfo, "skin")); if (!strcmp(dball_team1_skin->string, skin)) { spottype = "dm_dball_team1_start"; } else if (!strcmp(dball_team2_skin->string, skin)) { spottype = "dm_dball_team2_start"; } else { spottype = "info_player_deathmatch"; } spot = NULL; bestspot = NULL; bestdistance = 0; while ((spot = G_Find(spot, FOFS(classname), spottype)) != NULL) { bestplayerdistance = PlayersRangeFromSpot(spot); if (bestplayerdistance > bestdistance) { bestspot = spot; bestdistance = bestplayerdistance; } } if (bestspot) { VectorCopy(bestspot->s.origin, origin); origin[2] += 9; VectorCopy(bestspot->s.angles, angles); return; } /* if we didn't find an appropriate spawnpoint, just call the standard one. */ SelectSpawnPoint(ent, origin, angles); } void DBall_GameInit(void) { sv_stopspeed->value = 0; dball_team1_goalscore = 0; dball_team2_goalscore = 0; dmflags->value = (int)dmflags->value | DF_NO_MINES | DF_NO_NUKES | DF_NO_STACK_DOUBLE | DF_NO_FRIENDLY_FIRE | DF_SKINTEAMS; dball_team1_skin = gi.cvar("dball_team1_skin", "male/ctf_r", 0); dball_team2_skin = gi.cvar("dball_team2_skin", "male/ctf_b", 0); goallimit = gi.cvar("goallimit", "0", 0); } void DBall_PostInitSetup(void) { edict_t *e; e = NULL; /* turn teleporter destinations nonsolid. */ while ((e = (G_Find(e, FOFS(classname), "misc_teleporter_dest")))) { e->solid = SOLID_NOT; gi.linkentity(e); } /* count the ball start points */ dball_ball_startpt_count = 0; e = NULL; while ((e = (G_Find(e, FOFS(classname), "dm_dball_ball_start")))) { dball_ball_startpt_count++; } if (dball_ball_startpt_count == 0) { gi.dprintf("No Deathball start points!\n"); } } int DBall_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod) { if (!targ || !attacker) { return 0; } /* cut player -> ball damage to 1 */ if (targ == dball_ball_entity) { return 1; } /* damage player -> player is halved */ if (attacker != dball_ball_entity) { return damage / 2; } return damage; } int DBall_ChangeKnockback(edict_t *targ, edict_t *attacker, int knockback, int mod) { if (!targ || !attacker) { return 0; } if (targ != dball_ball_entity) { return knockback; } if (knockback < 1) { if (mod == MOD_ROCKET) /* rocket */ { knockback = 70; } else if (mod == MOD_BFG_EFFECT) /* bfg */ { knockback = 90; } else { gi.dprintf("zero knockback, mod %d\n", mod); } } else { switch (mod) { case MOD_BLASTER: knockback *= 3; break; case MOD_SHOTGUN: knockback = (knockback * 3) / 8; break; case MOD_SSHOTGUN: knockback = knockback / 3; break; case MOD_HYPERBLASTER: knockback *= 4; break; case MOD_GRENADE: case MOD_HANDGRENADE: case MOD_PROX: case MOD_G_SPLASH: case MOD_HG_SPLASH: case MOD_HELD_GRENADE: case MOD_TRACKER: case MOD_DISINTEGRATOR: knockback /= 2; break; case MOD_R_SPLASH: case MOD_MACHINEGUN: knockback = (knockback * 3) / 2; break; case MOD_RAILGUN: case MOD_HEATBEAM: knockback /= 3; break; } } return knockback; } void DBall_GoalTouch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { int team_score; int scorechange; int j; char value[512]; char *p; edict_t *ent; if (!self || !other) { return; } if (other != dball_ball_entity) { return; } self->health = self->max_health; /* determine which team scored, and bump the team score */ if (self->spawnflags & DBALL_GOAL_TEAM1) { dball_team1_goalscore += self->wait; team_score = 1; } else { dball_team2_goalscore += self->wait; team_score = 2; } /* bump the score for everyone on the correct team. */ for (j = 1; j <= game.maxclients; j++) { ent = &g_edicts[j]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (ent == other->enemy) { scorechange = self->wait + 5; } else { scorechange = self->wait; } strcpy(value, Info_ValueForKey(ent->client->pers.userinfo, "skin")); p = strchr(value, '/'); if (p) { if (!strcmp(dball_team1_skin->string, value)) { if (team_score == 1) { ent->client->resp.score += scorechange; } else if (other->enemy == ent) { ent->client->resp.score -= scorechange; } } else if (!strcmp(dball_team2_skin->string, value)) { if (team_score == 2) { ent->client->resp.score += scorechange; } else if (other->enemy == ent) { ent->client->resp.score -= scorechange; } } else { gi.dprintf("unassigned player!!!!\n"); } } } if (other->enemy) { gi.dprintf("score for team %d by %s\n", team_score, other->enemy->client->pers.netname); } else { gi.dprintf("score for team %d by someone\n", team_score); } DBall_BallDie(other, other->enemy, other->enemy, 0, vec3_origin); G_UseTargets(self, other); } edict_t * PickBallStart(edict_t *ent) { int which, current; edict_t *e; if (!ent) { return NULL; } which = ceil(random() * dball_ball_startpt_count); e = NULL; current = 0; while ((e = (G_Find(e, FOFS(classname), "dm_dball_ball_start")))) { current++; if (current == which) { return e; } } if (current == 0) { gi.dprintf("No ball start points found!\n"); } return G_Find(NULL, FOFS(classname), "dm_dball_ball_start"); } void DBall_BallTouch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t dir; float dot; float speed; if (!ent || !other) { return; } if (other->takedamage == DAMAGE_NO) { return; } /* hit a player */ if (other->client) { if (ent->velocity[0] || ent->velocity[1] || ent->velocity[2]) { speed = VectorLength(ent->velocity); VectorSubtract(ent->s.origin, other->s.origin, dir); dot = DotProduct(dir, ent->velocity); if (dot > 0.7) { T_Damage(other, ent, ent, vec3_origin, ent->s.origin, vec3_origin, speed / 10, speed / 10, 0, MOD_DBALL_CRUSH); } } } } void DBall_BallPain(edict_t *self, edict_t *other, float kick, int damage) { if (!self || !other) { return; } self->enemy = other; self->health = self->max_health; } void DBall_BallDie(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point) { if (!self) { return; } /* do the splash effect */ gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DBALL_GOAL); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); VectorClear(self->s.angles); VectorClear(self->velocity); VectorClear(self->avelocity); /* make it invisible and desolid until respawn time */ self->solid = SOLID_NOT; self->think = DBall_BallRespawn; self->nextthink = level.time + 2; gi.linkentity(self); } void DBall_BallRespawn(edict_t *self) { edict_t *start; if (!self) { return; } /* do the splash effect */ gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DBALL_GOAL); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); /* move the ball and stop it */ start = PickBallStart(self); if (start) { VectorCopy(start->s.origin, self->s.origin); VectorCopy(start->s.origin, self->s.old_origin); } VectorClear(self->s.angles); VectorClear(self->velocity); VectorClear(self->avelocity); self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/objects/dball/tris.md2"); self->s.event = EV_PLAYER_TELEPORT; self->groundentity = NULL; /* kill anything at the destination */ KillBox(self); gi.linkentity(self); } void DBall_SpeedTouch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { float dot; vec3_t vel; if (!self || !other) { return; } if (other != dball_ball_entity) { return; } if (self->timestamp >= level.time) { return; } if (VectorLength(other->velocity) < 1) { return; } if (self->spawnflags & DBALL_SPEED_ONEWAY) { VectorCopy(other->velocity, vel); VectorNormalize(vel); dot = DotProduct(vel, self->movedir); if (dot < 0.8) { return; } } self->timestamp = level.time + self->delay; VectorScale(other->velocity, self->speed, other->velocity); } void SP_dm_dball_ball(edict_t *self) { if (!self) { return; } if (!(deathmatch->value)) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } dball_ball_entity = self; self->s.modelindex = gi.modelindex("models/objects/dball/tris.md2"); VectorSet(self->mins, -32, -32, -32); VectorSet(self->maxs, 32, 32, 32); self->solid = SOLID_BBOX; self->movetype = MOVETYPE_NEWTOSS; self->clipmask = MASK_MONSTERSOLID; self->takedamage = DAMAGE_YES; self->mass = 50; self->health = 50000; self->max_health = 50000; self->pain = DBall_BallPain; self->die = DBall_BallDie; self->touch = DBall_BallTouch; gi.linkentity(self); } /* * QUAKED dm_dball_team1_start (1 .5 .5) (-16 -16 -24) (16 16 32) * Deathball team 1 start point */ void SP_dm_dball_team1_start(edict_t *self) { if (!self) { return; } if (!deathmatch->value) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } } /* * QUAKED dm_dball_team2_start (1 .5 .5) (-16 -16 -24) (16 16 32) * Deathball team 2 start point */ void SP_dm_dball_team2_start(edict_t *self) { if (!self) { return; } if (!deathmatch->value) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } } /* * QUAKED dm_dball_ball_start (1 .5 .5) (-48 -48 -48) (48 48 48) * Deathball ball start point */ void SP_dm_dball_ball_start(edict_t *self) { if (!self) { return; } if (!deathmatch->value) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } } /* * QUAKED dm_dball_speed_change (1 .5 .5) ? ONEWAY * Deathball ball speed changing field. * * speed: multiplier for speed (.5 = half, 2 = double, etc) (default = double) * angle: used with ONEWAY so speed change is only one way. * delay: time between speed changes (default: 0.2 sec) */ void SP_dm_dball_speed_change(edict_t *self) { if (!self) { return; } if (!deathmatch->value) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } if (!self->speed) { self->speed = 2; } if (!self->delay) { self->delay = 0.2; } self->touch = DBall_SpeedTouch; self->solid = SOLID_TRIGGER; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } else { VectorSet(self->movedir, 1, 0, 0); } gi.setmodel(self, self->model); gi.linkentity(self); } /* * QUAKED dm_dball_goal (1 .5 .5) ? TEAM1 TEAM2 * Deathball goal * * Team1/Team2 - beneficiary of this goal. when the ball enters this goal, the beneficiary team will score. * * "wait": score to be given for this goal (default 10) player gets score+5. */ void SP_dm_dball_goal(edict_t *self) { if (!self) { return; } if (!(deathmatch->value)) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } if (!self->wait) { self->wait = 10; } self->touch = DBall_GoalTouch; self->solid = SOLID_TRIGGER; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } gi.setmodel(self, self->model); gi.linkentity(self); } rogue-ROGUE_2_13/src/dm/tag.c000066400000000000000000000143551477320066100157260ustar00rootroot00000000000000/* ======================================================================= * * Deathmatch tag. * * ======================================================================= */ #include "../header/local.h" extern edict_t *SelectFarthestDeathmatchSpawnPoint(void); extern void SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles); void SP_dm_tag_token(edict_t *self); edict_t *tag_token; edict_t *tag_owner; int tag_count; void Tag_PlayerDeath(edict_t *targ, edict_t *inflictor /* unused */, edict_t *attacker /* unused */) { if (tag_token && targ && (targ == tag_owner)) { Tag_DropToken(targ, FindItem("Tag Token")); tag_owner = NULL; tag_count = 0; } } void Tag_KillItBonus(edict_t *self) { edict_t *armor; if (!self) { return; } /* if the player is hurt, boost them up to max. */ if (self->health < self->max_health) { self->health += 200; if (self->health > self->max_health) { self->health = self->max_health; } } /* give the player a body armor */ armor = G_Spawn(); armor->spawnflags |= DROPPED_ITEM; armor->item = FindItem("Body Armor"); Touch_Item(armor, self, NULL, NULL); if (armor->inuse) { G_FreeEdict(armor); } } void Tag_PlayerDisconnect(edict_t *self) { if (tag_token && self && (self == tag_owner)) { Tag_DropToken(self, FindItem("Tag Token")); tag_owner = NULL; tag_count = 0; } } void Tag_Score(edict_t *attacker, edict_t *victim, int scoreChange) { gitem_t *quad; int mod; if (!attacker || !victim) { return; } mod = meansOfDeath & ~MOD_FRIENDLY_FIRE; if (tag_token && tag_owner) { /* owner killed somone else */ if ((scoreChange > 0) && (tag_owner == attacker)) { scoreChange = 3; tag_count++; if (tag_count == 5) { quad = FindItem("Quad Damage"); attacker->client->pers.inventory[ITEM_INDEX(quad)]++; quad->use(attacker, quad); tag_count = 0; } } /* owner got killed. 5 points and switch owners */ else if ((tag_owner == victim) && (tag_owner != attacker)) { scoreChange = 5; if ((mod == MOD_HUNTER_SPHERE) || (mod == MOD_DOPPLE_EXPLODE) || (mod == MOD_DOPPLE_VENGEANCE) || (mod == MOD_DOPPLE_HUNTER) || (attacker->health <= 0)) { Tag_DropToken(tag_owner, FindItem("Tag Token")); tag_owner = NULL; tag_count = 0; } else { Tag_KillItBonus(attacker); tag_owner = attacker; tag_count = 0; } } } attacker->client->resp.score += scoreChange; } qboolean Tag_PickupToken(edict_t *ent, edict_t *other) { if (gamerules && (gamerules->value != 2)) { return false; } if (!ent || !other) { return false; } /* sanity checking is good. */ if (tag_token != ent) { tag_token = ent; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; tag_owner = other; tag_count = 0; Tag_KillItBonus(other); return true; } void Tag_Respawn(edict_t *ent) { edict_t *spot; if (!ent) { return; } spot = SelectFarthestDeathmatchSpawnPoint(); if (spot == NULL) { ent->nextthink = level.time + 1; return; } VectorCopy(spot->s.origin, ent->s.origin); gi.linkentity(ent); } void Tag_MakeTouchable(edict_t *ent) { if (!ent) { return; } ent->touch = Touch_Item; tag_token->think = Tag_Respawn; /* check here to see if it's in lava or slime. if so, do a respawn sooner */ if (gi.pointcontents(ent->s.origin) & (CONTENTS_LAVA | CONTENTS_SLIME)) { tag_token->nextthink = level.time + 3; } else { tag_token->nextthink = level.time + 30; } } void Tag_DropToken(edict_t *ent, gitem_t *item) { trace_t trace; vec3_t forward, right; vec3_t offset; if (!ent || !item) { return; } /* reset the score count for next player */ tag_count = 0; tag_owner = NULL; tag_token = G_Spawn(); tag_token->classname = item->classname; tag_token->item = item; tag_token->spawnflags = DROPPED_ITEM; tag_token->s.effects = EF_ROTATE | EF_TAGTRAIL; tag_token->s.renderfx = RF_GLOW; VectorSet(tag_token->mins, -15, -15, -15); VectorSet(tag_token->maxs, 15, 15, 15); gi.setmodel(tag_token, tag_token->item->world_model); tag_token->solid = SOLID_TRIGGER; tag_token->movetype = MOVETYPE_TOSS; tag_token->touch = NULL; tag_token->owner = ent; AngleVectors(ent->client->v_angle, forward, right, NULL); VectorSet(offset, 24, 0, -16); G_ProjectSource(ent->s.origin, offset, forward, right, tag_token->s.origin); trace = gi.trace(ent->s.origin, tag_token->mins, tag_token->maxs, tag_token->s.origin, ent, CONTENTS_SOLID); VectorCopy(trace.endpos, tag_token->s.origin); VectorScale(forward, 100, tag_token->velocity); tag_token->velocity[2] = 300; tag_token->think = Tag_MakeTouchable; tag_token->nextthink = level.time + 1; gi.linkentity(tag_token); ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); } void Tag_PlayerEffects(edict_t *ent) { if (!ent) { return; } if (ent == tag_owner) { ent->s.effects |= EF_TAGTRAIL; } } void Tag_DogTag(edict_t *ent, edict_t *killer /* unused */, char **pic) { if (!ent || !pic) { return; } if (ent == tag_owner) { (*pic) = "tag3"; } } int Tag_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod) { if (!targ || !attacker) { return 0; } if ((targ != tag_owner) && (attacker != tag_owner)) { return damage * 3 / 4; } return damage; } void Tag_GameInit(void) { tag_token = NULL; tag_owner = NULL; tag_count = 0; } void Tag_PostInitSetup(void) { edict_t *e; vec3_t origin, angles; /* automatic spawning of tag token if one is not present on map. */ e = G_Find(NULL, FOFS(classname), "dm_tag_token"); if (e == NULL) { e = G_Spawn(); e->classname = "dm_tag_token"; SelectSpawnPoint(e, origin, angles); VectorCopy(origin, e->s.origin); VectorCopy(origin, e->s.old_origin); VectorCopy(angles, e->s.angles); SP_dm_tag_token(e); } } /* * QUAKED dm_tag_token (.3 .3 1) (-16 -16 -16) (16 16 16) * The tag token for deathmatch tag games. */ void SP_dm_tag_token(edict_t *self) { if (!self) { return; } if (!(deathmatch->value)) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != 2)) { G_FreeEdict(self); return; } /* store the tag token edict pointer for later use. */ tag_token = self; tag_count = 0; self->classname = "dm_tag_token"; self->model = "models/items/tagtoken/tris.md2"; self->count = 1; SpawnItem(self, FindItem("Tag Token")); } rogue-ROGUE_2_13/src/g_ai.c000066400000000000000000001020071477320066100154420ustar00rootroot00000000000000/* ======================================================================= * * The basic AI functions like enemy detection, attacking and so on. * * ======================================================================= */ #include "header/local.h" extern cvar_t *maxclients; int enemy_range; float enemy_yaw; qboolean ai_checkattack(edict_t *self, float dist); qboolean enemy_infront; qboolean enemy_vis; qboolean FindTarget(edict_t *self); /* ========================================================================== */ /* * Called once each frame to set level.sight_client * to the player to be checked for in findtarget. * If all clients are either dead or in notarget, * sight_client will be null. * In coop games, sight_client will cycle * between the clients. */ void AI_SetSightClient(void) { edict_t *ent; int start, check; if (level.sight_client == NULL) { start = 1; } else { start = level.sight_client - g_edicts; } check = start; while (1) { check++; if (check > game.maxclients) { check = 1; } ent = &g_edicts[check]; if (ent->inuse && (ent->health > 0) && !(ent->flags & (FL_NOTARGET | FL_DISGUISED))) { level.sight_client = ent; return; /* got one */ } if (check == start) { level.sight_client = NULL; return; /* nobody to see */ } } } /* * Move the specified distance at current facing. */ void ai_move(edict_t *self, float dist) { if (!self) { return; } M_walkmove(self, self->s.angles[YAW], dist); } /* * * Used for standing around and looking * for players Distance is for slight * position adjustments needed by the * animations */ void ai_stand(edict_t *self, float dist) { vec3_t v; qboolean retval; if (!self) { return; } if (dist) { M_walkmove(self, self->s.angles[YAW], dist); } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { if (self->enemy) { VectorSubtract(self->enemy->s.origin, self->s.origin, v); self->ideal_yaw = vectoyaw(v); if ((self->s.angles[YAW] != self->ideal_yaw) && self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND) { self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); self->monsterinfo.run(self); } if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } /* find out if we're going to be shooting */ retval = ai_checkattack(self, 0); /* record sightings of player */ if ((self->enemy) && (self->enemy->inuse) && (visible(self, self->enemy))) { self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); self->monsterinfo.trail_time = level.time; self->monsterinfo.blind_fire_delay = 0; } /* check retval to make sure we're not blindfiring */ else if (!retval) { FindTarget(self); return; } } else { FindTarget(self); } return; } if (FindTarget(self)) { return; } if (level.time > self->monsterinfo.pausetime) { self->monsterinfo.walk(self); return; } if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time)) { if (self->monsterinfo.idle_time) { self->monsterinfo.idle(self); self->monsterinfo.idle_time = level.time + 15 + random() * 15; } else { self->monsterinfo.idle_time = level.time + random() * 15; } } } /* * The monster is walking it's beat */ void ai_walk(edict_t *self, float dist) { M_MoveToGoal(self, dist); if (!self) { return; } /* check for noticing a player */ if (FindTarget(self)) { return; } if ((self->monsterinfo.search) && (level.time > self->monsterinfo.idle_time)) { if (self->monsterinfo.idle_time) { self->monsterinfo.search(self); self->monsterinfo.idle_time = level.time + 15 + random() * 15; } else { self->monsterinfo.idle_time = level.time + random() * 15; } } } /* * Turns towards target and advances * Use this call with a distnace of 0 * to replace ai_face */ void ai_charge(edict_t *self, float dist) { vec3_t v; float ofs; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } if (visible(self, self->enemy)) { VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); } if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { VectorSubtract(self->enemy->s.origin, self->s.origin, v); self->ideal_yaw = vectoyaw(v); } M_ChangeYaw(self); if (dist) { if (self->monsterinfo.aiflags & AI_CHARGING) { M_MoveToGoal(self, dist); return; } /* circle strafe support */ if (self->monsterinfo.attack_state == AS_SLIDING) { /* if we're fighting a tesla, NEVER circle strafe */ if ((self->enemy) && (self->enemy->classname) && (!strcmp(self->enemy->classname, "tesla"))) { ofs = 0; } else if (self->monsterinfo.lefty) { ofs = 90; } else { ofs = -90; } if (M_walkmove(self, self->ideal_yaw + ofs, dist)) { return; } self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; M_walkmove(self, self->ideal_yaw - ofs, dist); } else { M_walkmove(self, self->s.angles[YAW], dist); } } } /* * Don't move, but turn towards * ideal_yaw. Distance is for * slight position adjustments * needed by the animations */ void ai_turn(edict_t *self, float dist) { if (!self) { return; } if (dist) { M_walkmove(self, self->s.angles[YAW], dist); } if (FindTarget(self)) { return; } if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } } /* ========================================================================== */ /* * .enemy * Will be world if not currently angry at anyone. * * .movetarget * The next path spot to walk toward. If .enemy, ignore .movetarget. * When an enemy is killed, the monster will try to return to it's path. * * .hunt_time * Set to time + something when the player is in sight, but movement straight for * him is blocked. This causes the monster to use wall following code for * movement direction instead of sighting on the player. * * .ideal_yaw * A yaw angle of the intended direction, which will be turned towards at up * to 45 deg / state. If the enemy is in view and hunt_time is not active, * this will be the exact line towards the enemy. * * .pausetime * A monster will leave it's stand state and head towards it's .movetarget when * time > .pausetime. */ /* ========================================================================== */ /* * returns the range catagorization of an entity reletive to self * 0 melee range, will become hostile even if back is turned * 1 visibility and infront, or visibility and show hostile * 2 infront and show hostile * 3 only triggered by damage */ int range(edict_t *self, edict_t *other) { vec3_t v; float len; if (!self || !other) { return 0; } VectorSubtract(self->s.origin, other->s.origin, v); len = VectorLength(v); if (len < MELEE_DISTANCE) { return RANGE_MELEE; } if (len < 500) { return RANGE_NEAR; } if (len < 1000) { return RANGE_MID; } return RANGE_FAR; } /* * returns 1 if the entity is visible * to self, even if not infront */ qboolean visible(edict_t *self, edict_t *other) { vec3_t spot1; vec3_t spot2; trace_t trace; if (!self || !other) { return false; } VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(other->s.origin, spot2); spot2[2] += other->viewheight; trace = gi.trace(spot1, vec3_origin, vec3_origin, spot2, self, MASK_OPAQUE); if ((trace.fraction == 1.0) || (trace.ent == other)) { return true; } return false; } /* * returns 1 if the entity is in * front (in sight) of self */ qboolean infront(edict_t *self, edict_t *other) { vec3_t vec; float dot; vec3_t forward; if (!self || !other) { return false; } AngleVectors(self->s.angles, forward, NULL, NULL); VectorSubtract(other->s.origin, self->s.origin, vec); VectorNormalize(vec); dot = DotProduct(vec, forward); if (dot > 0.3) { return true; } return false; } /* ============================================================================ */ void HuntTarget(edict_t *self) { vec3_t vec; if (!self) { return; } self->goalentity = self->enemy; if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.stand(self); } else if (self->monsterinfo.run) { self->monsterinfo.run(self); } if(visible(self, self->enemy)) { VectorSubtract(self->enemy->s.origin, self->s.origin, vec); } self->ideal_yaw = vectoyaw(vec); /* wait a while before first attack */ if (!(self->monsterinfo.aiflags & AI_STAND_GROUND)) { AttackFinished(self, 1); } } void FoundTarget(edict_t *self) { if (!self|| !self->enemy || !self->enemy->inuse) { return; } /* let other monsters see this monster for a while */ if (self->enemy->client) { if (self->enemy->flags & FL_DISGUISED) { self->enemy->flags &= ~FL_DISGUISED; } level.sight_entity = self; level.sight_entity_framenum = level.framenum; level.sight_entity->light_level = 128; } self->show_hostile = level.time + 1; /* wake up other monsters */ VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.trail_time = level.time; VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); self->monsterinfo.blind_fire_delay = 0; if (!self->combattarget) { HuntTarget(self); return; } self->goalentity = self->movetarget = G_PickTarget(self->combattarget); if (!self->movetarget) { self->goalentity = self->movetarget = self->enemy; HuntTarget(self); gi.dprintf("%s at %s, combattarget %s not found\n", self->classname, vtos(self->s.origin), self->combattarget); return; } /* clear out our combattarget, these are a one shot deal */ self->combattarget = NULL; self->monsterinfo.aiflags |= AI_COMBAT_POINT; /* clear the targetname, that point is ours! */ self->movetarget->targetname = NULL; self->monsterinfo.pausetime = 0; /* run for it */ self->monsterinfo.run(self); } /* * Self is currently not attacking anything, * so try to find a target * * Returns TRUE if an enemy was sighted * * When a player fires a missile, the point * of impact becomes a fakeplayer so that * monsters that see the impact will respond * as if they had seen the player. * * To avoid spending too much time, only * a single client (or fakeclient) is * checked each frame. This means multi * player games will have slightly * slower noticing monsters. */ qboolean FindTarget(edict_t *self) { edict_t *client; qboolean heardit; int r; if (!self) { return false; } if (self->monsterinfo.aiflags & AI_GOOD_GUY) { return false; } /* if we're going to a combat point, just proceed */ if (self->monsterinfo.aiflags & AI_COMBAT_POINT) { return false; } /* if the first spawnflag bit is set, the monster will only wake up on really seeing the player, not another monster getting angry or hearing something */ heardit = false; if ((level.sight_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & 1)) { client = level.sight_entity; if (client->enemy == self->enemy) { return false; } } else if (level.disguise_violation_framenum > level.framenum) { client = level.disguise_violator; } else if (level.sound_entity_framenum >= (level.framenum - 1)) { client = level.sound_entity; heardit = true; } else if (!(self->enemy) && (level.sound2_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & 1)) { client = level.sound2_entity; heardit = true; } else { client = level.sight_client; } /* if the entity went away, forget it */ if (!client || !client->inuse || (client->client && level.intermissiontime)) { return false; } if (client == self->enemy) { return true; } if ((self->monsterinfo.aiflags & AI_HINT_PATH) && (coop) && (coop->value)) { heardit = false; } if (client->client) { if (client->flags & FL_NOTARGET) { return false; } } else if (client->svflags & SVF_MONSTER) { if (!client->enemy) { return false; } if (client->enemy->flags & FL_NOTARGET) { return false; } } else if (heardit) { if ((client->owner) && (client->owner->flags & FL_NOTARGET)) { return false; } } else { return false; } if (!heardit) { r = range(self, client); if (r == RANGE_FAR) { return false; } /* is client in an spot too dark to be seen? */ if (client->light_level <= 5) { return false; } if (!visible(self, client)) { return false; } if (r == RANGE_NEAR) { if ((client->show_hostile < level.time) && !infront(self, client)) { return false; } } else if (r == RANGE_MID) { if (!infront(self, client)) { return false; } } self->enemy = client; if (strcmp(self->enemy->classname, "player_noise") != 0) { self->monsterinfo.aiflags &= ~AI_SOUND_TARGET; if (!self->enemy->client) { self->enemy = self->enemy->enemy; if (!self->enemy->client) { self->enemy = NULL; return false; } } } } else /* heardit */ { vec3_t temp; if (self->spawnflags & 1) { if (!visible(self, client)) { return false; } } else { if (!gi.inPHS(self->s.origin, client->s.origin)) { return false; } } VectorSubtract(client->s.origin, self->s.origin, temp); if (VectorLength(temp) > 1000) /* too far to hear */ { return false; } /* check area portals - if they are different and not connected then we can't hear it */ if (client->areanum != self->areanum) { if (!gi.AreasConnected(self->areanum, client->areanum)) { return false; } } self->ideal_yaw = vectoyaw(temp); if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } /* hunt the sound for a bit; hopefully find the real player */ self->monsterinfo.aiflags |= AI_SOUND_TARGET; self->enemy = client; } /* if we got an enemy, we need to bail out of hint paths, so take over here */ if (self->monsterinfo.aiflags & AI_HINT_PATH) { /* this calls foundtarget for us */ hintpath_stop(self); } else { FoundTarget(self); } if (!(self->monsterinfo.aiflags & AI_SOUND_TARGET) && (self->monsterinfo.sight)) { self->monsterinfo.sight(self, self->enemy); } return true; } /* ============================================================================= */ qboolean FacingIdeal(edict_t *self) { float delta; if (!self) { return false; } delta = anglemod(self->s.angles[YAW] - self->ideal_yaw); if ((delta > 45) && (delta < 315)) { return false; } return true; } /* ============================================================================= */ qboolean M_CheckAttack(edict_t *self) { vec3_t spot1, spot2; float chance; trace_t tr; if (!self || !self->enemy || !self->enemy->inuse) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_WINDOW); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* we want them to go ahead and shoot at info_notnulls if they can. */ if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0)) { /* if we can't see our target, and we're not blocked by a monster, go into blind fire if available */ if ((!(tr.ent->svflags & SVF_MONSTER)) && (!visible(self, self->enemy))) { if ((self->monsterinfo.blindfire) && (self->monsterinfo.blind_fire_delay <= 20.0)) { if (level.time < self->monsterinfo.attack_finished) { return false; } if (level.time < (self->monsterinfo.trail_time + self->monsterinfo.blind_fire_delay)) { /* wait for our time */ return false; } else { /* make sure we're not going to shoot a monster */ tr = gi.trace(spot1, NULL, NULL, self->monsterinfo.blind_fire_target, self, CONTENTS_MONSTER); if (tr.allsolid || tr.startsolid || ((tr.fraction < 1.0) && (tr.ent != self->enemy))) { return false; } self->monsterinfo.attack_state = AS_BLIND; return true; } } } return false; } } } /* melee attack */ if (enemy_range == RANGE_MELEE) { /* don't always melee in easy mode */ if ((skill->value == SKILL_EASY) && (rand() & 3)) { /* fix for melee only monsters & strafing */ self->monsterinfo.attack_state = AS_STRAIGHT; return false; } if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } /* missile attack */ if (!self->monsterinfo.attack) { /* fix for melee only monsters & strafing */ self->monsterinfo.attack_state = AS_STRAIGHT; return false; } if (level.time < self->monsterinfo.attack_finished) { return false; } if (enemy_range == RANGE_FAR) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.1; } else if (enemy_range == RANGE_MID) { chance = 0.02; } else { return false; } if (skill->value == SKILL_EASY) { chance *= 0.5; } else if (skill->value >= SKILL_HARD) { chance *= 2; } /* go ahead and shoot every time if it's a info_notnull */ if ((random() < chance) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; self->monsterinfo.attack_finished = level.time + 2 * random(); return true; } /* daedalus should strafe more.. this can be done here or in a customized check_attack code for the hover. */ if (self->flags & FL_FLY) { /* originally, just 0.3 */ float strafe_chance; if (!(strcmp(self->classname, "monster_daedalus"))) { strafe_chance = 0.8; } else { strafe_chance = 0.6; } /* if enemy is tesla, never strafe */ if ((self->enemy->classname) && (!strcmp(self->enemy->classname, "tesla"))) { strafe_chance = 0; } if (random() < strafe_chance) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } else { /* do we want the monsters strafing? */ if (random() < 0.4) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } return false; } /* * Turn and close until within an * angle to launch a melee attack */ void ai_run_melee(edict_t *self) { if (!self) { return; } self->ideal_yaw = enemy_yaw; if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } if (FacingIdeal(self)) { if (self->monsterinfo.melee) { self->monsterinfo.melee(self); self->monsterinfo.attack_state = AS_STRAIGHT; } } } /* * Turn in place until within an * angle to launch a missile attack */ void ai_run_missile(edict_t *self) { if (!self) { return; } self->ideal_yaw = enemy_yaw; if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } if (FacingIdeal(self)) { if (self->monsterinfo.attack) { self->monsterinfo.attack(self); if ((self->monsterinfo.attack_state == AS_MISSILE) || (self->monsterinfo.attack_state == AS_BLIND)) { self->monsterinfo.attack_state = AS_STRAIGHT; } } } } /* * Strafe sideways, but stay at * aproximately the same range */ void ai_run_slide(edict_t *self, float distance) { float ofs; float angle; if (!self) { return; } self->ideal_yaw = enemy_yaw; angle = 90; if (self->monsterinfo.lefty) { ofs = angle; } else { ofs = -angle; } if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } /* clamp maximum sideways move for non flyers to make them look less jerky */ if (!(self->flags & FL_FLY)) { distance = min(distance, 8.0); } if (M_walkmove(self, self->ideal_yaw + ofs, distance)) { return; } /* if we're dodging, give up on it and go straight */ if (self->monsterinfo.aiflags & AI_DODGING) { monster_done_dodge(self); self->monsterinfo.attack_state = AS_STRAIGHT; return; } self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; if (M_walkmove(self, self->ideal_yaw - ofs, distance)) { return; } /* if we're dodging, give up on it and go straight */ if (self->monsterinfo.aiflags & AI_DODGING) { monster_done_dodge(self); } /* the move failed, so signal the caller (ai_run) to try going straight */ self->monsterinfo.attack_state = AS_STRAIGHT; } /* * Decides if we're going to attack * or do something else used by * ai_run and ai_stand */ static qboolean hesDeadJim(const edict_t *self) { const edict_t *enemy = self->enemy; if (!enemy || !enemy->inuse) { return true; } if (self->monsterinfo.aiflags & AI_MEDIC) { return (enemy->health > 0); } if (enemy->client && level.intermissiontime) { return true; } if (self->monsterinfo.aiflags & AI_BRUTAL) { return (enemy->health <= -80); } return (enemy->health <= 0); } qboolean ai_checkattack(edict_t *self, float dist) { vec3_t temp; qboolean retval; if (!self) { enemy_vis = false; return false; } /* this causes monsters to run blindly to the combat point w/o firing */ if (self->goalentity) { if (self->monsterinfo.aiflags & AI_COMBAT_POINT) { return false; } if ((self->monsterinfo.aiflags & AI_SOUND_TARGET) && !visible(self, self->goalentity)) { if ((level.time - self->enemy->last_sound_time) > 5.0) { if (self->goalentity == self->enemy) { if (self->movetarget) { self->goalentity = self->movetarget; } else { self->goalentity = NULL; } } self->monsterinfo.aiflags &= ~AI_SOUND_TARGET; if (self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND) { self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); } } else { self->show_hostile = level.time + 1; return false; } } } enemy_vis = false; /* see if the enemy is dead */ if (hesDeadJim(self)) { self->enemy = NULL; self->monsterinfo.aiflags &= ~AI_MEDIC; if (self->oldenemy && (self->oldenemy->health > 0)) { self->enemy = self->oldenemy; self->oldenemy = NULL; HuntTarget(self); } else if (self->monsterinfo.last_player_enemy && (self->monsterinfo.last_player_enemy->health > 0)) { self->enemy = self->monsterinfo.last_player_enemy; self->oldenemy = NULL; self->monsterinfo.last_player_enemy = NULL; HuntTarget(self); } else { if (self->movetarget) { self->goalentity = self->movetarget; self->monsterinfo.walk(self); } else { /* we need the pausetime otherwise the stand code will just revert to walking with no target and the monsters will wonder around aimlessly trying to hunt the world entity */ self->monsterinfo.pausetime = level.time + 100000000; self->monsterinfo.stand(self); } return true; } } self->show_hostile = level.time + 1; /* wake up other monsters */ /* check knowledge of enemy */ enemy_vis = visible(self, self->enemy); if (enemy_vis) { self->monsterinfo.search_time = level.time + 5; VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; self->monsterinfo.trail_time = level.time; VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); self->monsterinfo.blind_fire_delay = 0; } if (coop && coop->value && (self->monsterinfo.search_time < level.time)) { if (FindTarget(self)) { return true; } } if (self->enemy) { enemy_infront = infront(self, self->enemy); enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw(temp); } retval = self->monsterinfo.checkattack(self); if (retval) { if (self->monsterinfo.attack_state == AS_MISSILE) { ai_run_missile(self); return true; } if (self->monsterinfo.attack_state == AS_MELEE) { ai_run_melee(self); return true; } /* added so monsters can shoot blind */ if (self->monsterinfo.attack_state == AS_BLIND) { ai_run_missile(self); return true; } /* if enemy is not currently visible, we will never attack */ if (!enemy_vis) { return false; } } return retval; } /* * The monster has an enemy * it is trying to kill */ void ai_run(edict_t *self, float dist) { vec3_t v; edict_t *tempgoal; edict_t *save; qboolean new; edict_t *marker; float d1, d2; trace_t tr; vec3_t v_forward, v_right; float left, center, right; vec3_t left_target, right_target; qboolean retval; qboolean alreadyMoved = false; qboolean gotcha = false; edict_t *realEnemy; if (!self) { return; } /* if we're going to a combat point, just proceed */ if (self->monsterinfo.aiflags & AI_COMBAT_POINT) { M_MoveToGoal(self, dist); return; } if (self->monsterinfo.aiflags & AI_DUCKED) { self->monsterinfo.aiflags &= ~AI_DUCKED; } if (self->maxs[2] != self->monsterinfo.base_height) { monster_duck_up(self); } /* if we're currently looking for a hint path */ if (self->monsterinfo.aiflags & AI_HINT_PATH) { M_MoveToGoal(self, dist); if (!self->inuse) { return; } /* first off, make sure we're looking for the player, not a noise he made */ if (self->enemy) { if (self->enemy->inuse) { if (strcmp(self->enemy->classname, "player_noise") != 0) { realEnemy = self->enemy; } else if (self->enemy->owner) { realEnemy = self->enemy->owner; } else /* uh oh, can't figure out enemy, bail */ { self->enemy = NULL; hintpath_stop(self); return; } } else { self->enemy = NULL; hintpath_stop(self); return; } } else { hintpath_stop(self); return; } if (visible(self, realEnemy)) { gotcha = true; } else if (coop->value) { FindTarget(self); } /* if we see the player, stop following hintpaths. */ if (gotcha) { /* disconnect from hintpaths and start looking normally for players. */ hintpath_stop(self); } return; } if (self->monsterinfo.aiflags & AI_SOUND_TARGET) { /* paranoia checking */ if (self->enemy) { VectorSubtract(self->s.origin, self->enemy->s.origin, v); } if ((!self->enemy) || (VectorLength(v) < 64)) { self->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_TEMP_STAND_GROUND); self->monsterinfo.stand(self); return; } M_MoveToGoal(self, dist); /* prevent double moves for sound_targets */ alreadyMoved = true; if (!self->inuse) { return; } if (!FindTarget(self)) { return; } } retval = ai_checkattack(self, dist); /* don't strafe if we can't see our enemy */ if ((!enemy_vis) && (self->monsterinfo.attack_state == AS_SLIDING)) { self->monsterinfo.attack_state = AS_STRAIGHT; } /* unless we're dodging (dodging out of view looks smart) */ if (self->monsterinfo.aiflags & AI_DODGING) { self->monsterinfo.attack_state = AS_SLIDING; } if (self->monsterinfo.attack_state == AS_SLIDING) { /* protect against double moves */ if (!alreadyMoved) { ai_run_slide(self, dist); } /* we're using attack_state as the return value out of ai_run_slide to indicate whether or not the move succeeded. If the move succeeded, and we're still sliding, we're done in here (since we've had our chance to shoot in ai_checkattack, and have moved). if the move failed, our state is as_straight, and it will be taken care of below */ if ((!retval) && (self->monsterinfo.attack_state == AS_SLIDING)) { return; } } else if (self->monsterinfo.aiflags & AI_CHARGING) { self->ideal_yaw = enemy_yaw; if (!(self->monsterinfo.aiflags & AI_MANUAL_STEERING)) { M_ChangeYaw(self); } } if (retval) { if ((dist != 0) && (!alreadyMoved) && (self->monsterinfo.attack_state == AS_STRAIGHT) && (!(self->monsterinfo.aiflags & AI_STAND_GROUND))) { M_MoveToGoal(self, dist); } if ((self->enemy) && (self->enemy->inuse) && (enemy_vis)) { self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.trail_time = level.time; VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); self->monsterinfo.blind_fire_delay = 0; } return; } if ((self->enemy) && (self->enemy->inuse) && (enemy_vis)) { /* check for alreadyMoved */ if (!alreadyMoved) { M_MoveToGoal(self, dist); } if (!self->inuse) { return; } self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.trail_time = level.time; VectorCopy(self->enemy->s.origin, self->monsterinfo.blind_fire_target); self->monsterinfo.blind_fire_delay = 0; return; } if ((self->monsterinfo.trail_time + 5) <= level.time) { /* and we haven't checked for valid hint paths in the last 10 seconds */ if ((self->monsterinfo.last_hint_time + 10) <= level.time) { /* check for hint_paths. */ self->monsterinfo.last_hint_time = level.time; if (monsterlost_checkhint(self)) { return; } } } if ((self->monsterinfo.search_time) && (level.time > (self->monsterinfo.search_time + 20))) { /* double move protection */ if (!alreadyMoved) { M_MoveToGoal(self, dist); } self->monsterinfo.search_time = 0; return; } tempgoal = G_SpawnOptional(); if (!tempgoal) { M_MoveToGoal(self, dist); return; } save = self->goalentity; self->goalentity = tempgoal; new = false; if (!(self->monsterinfo.aiflags & AI_LOST_SIGHT)) { /* just lost sight of the player, decide where to go first */ self->monsterinfo.aiflags |= (AI_LOST_SIGHT | AI_PURSUIT_LAST_SEEN); self->monsterinfo.aiflags &= ~(AI_PURSUE_NEXT | AI_PURSUE_TEMP); new = true; } if (self->monsterinfo.aiflags & AI_PURSUE_NEXT) { self->monsterinfo.aiflags &= ~AI_PURSUE_NEXT; /* give ourself more time since we got this far */ self->monsterinfo.search_time = level.time + 5; if (self->monsterinfo.aiflags & AI_PURSUE_TEMP) { self->monsterinfo.aiflags &= ~AI_PURSUE_TEMP; marker = NULL; VectorCopy(self->monsterinfo.saved_goal, self->monsterinfo.last_sighting); new = true; } else if (self->monsterinfo.aiflags & AI_PURSUIT_LAST_SEEN) { self->monsterinfo.aiflags &= ~AI_PURSUIT_LAST_SEEN; marker = PlayerTrail_PickFirst(self); } else { marker = PlayerTrail_PickNext(self); } if (marker) { VectorCopy(marker->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.trail_time = marker->timestamp; self->s.angles[YAW] = self->ideal_yaw = marker->s.angles[YAW]; new = true; } } VectorSubtract(self->s.origin, self->monsterinfo.last_sighting, v); d1 = VectorLength(v); if (d1 <= dist) { self->monsterinfo.aiflags |= AI_PURSUE_NEXT; dist = d1; } VectorCopy(self->monsterinfo.last_sighting, self->goalentity->s.origin); if (new) { tr = gi.trace(self->s.origin, self->mins, self->maxs, self->monsterinfo.last_sighting, self, MASK_PLAYERSOLID); if (tr.fraction < 1) { VectorSubtract(self->goalentity->s.origin, self->s.origin, v); d1 = VectorLength(v); center = tr.fraction; d2 = d1 * ((center + 1) / 2); self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); AngleVectors(self->s.angles, v_forward, v_right, NULL); VectorSet(v, d2, -16, 0); G_ProjectSource(self->s.origin, v, v_forward, v_right, left_target); tr = gi.trace(self->s.origin, self->mins, self->maxs, left_target, self, MASK_PLAYERSOLID); left = tr.fraction; VectorSet(v, d2, 16, 0); G_ProjectSource(self->s.origin, v, v_forward, v_right, right_target); tr = gi.trace(self->s.origin, self->mins, self->maxs, right_target, self, MASK_PLAYERSOLID); right = tr.fraction; center = (d1 * center) / d2; if ((left >= center) && (left > right)) { if (left < 1) { VectorSet(v, d2 * left * 0.5, -16, 0); G_ProjectSource(self->s.origin, v, v_forward, v_right, left_target); } VectorCopy(self->monsterinfo.last_sighting, self->monsterinfo.saved_goal); self->monsterinfo.aiflags |= AI_PURSUE_TEMP; VectorCopy(left_target, self->goalentity->s.origin); VectorCopy(left_target, self->monsterinfo.last_sighting); VectorSubtract(self->goalentity->s.origin, self->s.origin, v); self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); } else if ((right >= center) && (right > left)) { if (right < 1) { VectorSet(v, d2 * right * 0.5, 16, 0); G_ProjectSource(self->s.origin, v, v_forward, v_right, right_target); } VectorCopy(self->monsterinfo.last_sighting, self->monsterinfo.saved_goal); self->monsterinfo.aiflags |= AI_PURSUE_TEMP; VectorCopy(right_target, self->goalentity->s.origin); VectorCopy(right_target, self->monsterinfo.last_sighting); VectorSubtract(self->goalentity->s.origin, self->s.origin, v); self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v); } } } M_MoveToGoal(self, dist); if (!self->inuse) { return; } G_FreeEdict(tempgoal); self->goalentity = save; } rogue-ROGUE_2_13/src/g_chase.c000066400000000000000000000073621477320066100161440ustar00rootroot00000000000000/* * ======================================================================= * * Chase cam. Only used in multiplayer mode. * * ======================================================================= */ #include "header/local.h" void UpdateChaseCam(edict_t *ent) { vec3_t o, ownerv, goal; edict_t *targ; vec3_t forward, right; trace_t trace; int i; vec3_t angles; if (!ent) { return; } /* is our chase target gone? */ if (!ent->client->chase_target->inuse || ent->client->chase_target->client->resp.spectator) { edict_t *old = ent->client->chase_target; ChaseNext(ent); if (ent->client->chase_target == old) { ent->client->chase_target = NULL; ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; return; } } targ = ent->client->chase_target; VectorCopy(targ->s.origin, ownerv); ownerv[2] += targ->viewheight; VectorCopy(targ->client->v_angle, angles); if (angles[PITCH] > 56) { angles[PITCH] = 56; } AngleVectors(angles, forward, right, NULL); VectorNormalize(forward); VectorMA(ownerv, -30, forward, o); if (o[2] < targ->s.origin[2] + 20) { o[2] = targ->s.origin[2] + 20; } /* jump animation lifts */ if (!targ->groundentity) { o[2] += 16; } trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID); VectorCopy(trace.endpos, goal); VectorMA(goal, 2, forward, goal); /* pad for floors and ceilings */ VectorCopy(goal, o); o[2] += 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] -= 6; } VectorCopy(goal, o); o[2] -= 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] += 6; } if (targ->deadflag) { ent->client->ps.pmove.pm_type = PM_DEAD; } else { ent->client->ps.pmove.pm_type = PM_FREEZE; } VectorCopy(goal, ent->s.origin); for (i = 0; i < 3; i++) { ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT( targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]); } if (targ->deadflag) { ent->client->ps.viewangles[ROLL] = 40; ent->client->ps.viewangles[PITCH] = -15; ent->client->ps.viewangles[YAW] = targ->client->killer_yaw; } else { VectorCopy(targ->client->v_angle, ent->client->ps.viewangles); VectorCopy(targ->client->v_angle, ent->client->v_angle); } ent->viewheight = 0; ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; gi.linkentity(ent); } void ChaseNext(edict_t *ent) { int i; edict_t *e; if (!ent) { return; } if (!ent->client->chase_target) { return; } i = ent->client->chase_target - g_edicts; do { i++; if (i > maxclients->value) { i = 1; } e = g_edicts + i; if (!e->inuse) { continue; } if (!e->client->resp.spectator) { break; } } while (e != ent->client->chase_target); ent->client->chase_target = e; ent->client->update_chase = true; } void ChasePrev(edict_t *ent) { int i; edict_t *e; if (!ent) { return; } if (!ent->client->chase_target) { return; } i = ent->client->chase_target - g_edicts; do { i--; if (i < 1) { i = maxclients->value; } e = g_edicts + i; if (!e->inuse) { continue; } if (!e->client->resp.spectator) { break; } } while (e != ent->client->chase_target); ent->client->chase_target = e; ent->client->update_chase = true; } void GetChaseTarget(edict_t *ent) { int i; edict_t *other; if (!ent) { return; } for (i = 1; i <= maxclients->value; i++) { other = g_edicts + i; if (other->inuse && !other->client->resp.spectator) { ent->client->chase_target = other; ent->client->update_chase = true; UpdateChaseCam(ent); return; } } gi.centerprintf(ent, "No other players to chase."); } rogue-ROGUE_2_13/src/g_cmds.c000066400000000000000000000711411477320066100160030ustar00rootroot00000000000000/* ======================================================================= * * Game command processing. * * ======================================================================= */ #include "header/local.h" #include "monster/misc/player.h" static char * ClientTeam(edict_t *ent, char* value) { char *p; value[0] = 0; if (!ent) { return value; } if (!ent->client) { return value; } strcpy(value, Info_ValueForKey(ent->client->pers.userinfo, "skin")); p = strchr(value, '/'); if (!p) { return value; } if ((int)(dmflags->value) & DF_MODELTEAMS) { *p = 0; return value; } return ++p; } qboolean OnSameTeam(edict_t *ent1, edict_t *ent2) { char ent1Team[512]; char ent2Team[512]; if (!ent1 || !ent2) { return false; } if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) { return false; } ClientTeam(ent1, ent1Team); ClientTeam(ent2, ent2Team); if (ent1Team[0] != '\0' && strcmp(ent1Team, ent2Team) == 0) { return true; } return false; } void SelectNextItem(edict_t *ent, int itflags) { gclient_t *cl; int i, index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (cl->chase_target) { ChaseNext(ent); return; } /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { index = (cl->pers.selected_item + i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & itflags)) { continue; } cl->pers.selected_item = index; return; } cl->pers.selected_item = -1; } void SelectPrevItem(edict_t *ent, int itflags) { gclient_t *cl; int i, index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (cl->chase_target) { ChasePrev(ent); return; } /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { index = (cl->pers.selected_item + MAX_ITEMS - i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use) { continue; } if (!(it->flags & itflags)) { continue; } cl->pers.selected_item = index; return; } cl->pers.selected_item = -1; } void ValidateSelectedItem(edict_t *ent) { gclient_t *cl; if (!ent) { return; } cl = ent->client; if (cl->pers.inventory[cl->pers.selected_item]) { return; /* valid */ } SelectNextItem(ent, -1); } /* ================================================================================= */ /* * Give items to a client */ void Cmd_Give_f(edict_t *ent) { char *name; gitem_t *it; int index; int i; qboolean give_all; edict_t *it_ent; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } name = gi.args(); if (Q_stricmp(name, "all") == 0) { give_all = true; } else { give_all = false; } if (give_all || (Q_stricmp(gi.argv(1), "health") == 0)) { if (gi.argc() == 3) { ent->health = atoi(gi.argv(2)); ent->health = ent->health < 1 ? 1 : ent->health; } else { ent->health = ent->max_health; } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "weapons") == 0)) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (!(it->flags & IT_WEAPON)) { continue; } ent->client->pers.inventory[i] += 1; } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "ammo") == 0)) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (!(it->flags & IT_AMMO)) { continue; } Add_Ammo(ent, it, 1000); } if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "armor") == 0)) { gitem_armor_t *info; it = FindItem("Jacket Armor"); ent->client->pers.inventory[ITEM_INDEX(it)] = 0; it = FindItem("Combat Armor"); ent->client->pers.inventory[ITEM_INDEX(it)] = 0; it = FindItem("Body Armor"); info = (gitem_armor_t *)it->info; ent->client->pers.inventory[ITEM_INDEX(it)] = info->max_count; if (!give_all) { return; } } if (give_all || (Q_stricmp(name, "Power Shield") == 0)) { it = FindItem("Power Shield"); it_ent = G_Spawn(); it_ent->classname = it->classname; SpawnItem(it_ent, it); Touch_Item(it_ent, ent, NULL, NULL); if (it_ent->inuse) { G_FreeEdict(it_ent); } if (!give_all) { return; } } if (give_all) { for (i = 0; i < game.num_items; i++) { it = itemlist + i; if (!it->pickup) { continue; } if (it->flags & IT_NOT_GIVEABLE) { continue; } if (it->flags & (IT_ARMOR | IT_WEAPON | IT_AMMO)) { continue; } ent->client->pers.inventory[i] = 1; } return; } it = FindItem(name); if (!it) { name = gi.argv(1); it = FindItem(name); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item\n"); return; } } if (!it->pickup) { gi.cprintf(ent, PRINT_HIGH, "non-pickup item\n"); return; } if (it->flags & IT_NOT_GIVEABLE) { gi.dprintf("item cannot be given\n"); return; } index = ITEM_INDEX(it); if (it->flags & IT_AMMO) { if (gi.argc() == 3) { ent->client->pers.inventory[index] = atoi(gi.argv(2)); } else { ent->client->pers.inventory[index] += it->quantity; } } else { it_ent = G_Spawn(); it_ent->classname = it->classname; SpawnItem(it_ent, it); /* since some items don't actually spawn when you say to .. */ if (!it_ent->inuse) { return; } Touch_Item(it_ent, ent, NULL, NULL); if (it_ent->inuse) { G_FreeEdict(it_ent); } } } /* * Sets client to godmode */ void Cmd_God_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent->flags ^= FL_GODMODE; if (!(ent->flags & FL_GODMODE)) { msg = "godmode OFF\n"; } else { msg = "godmode ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } /* * Sets client to notarget */ void Cmd_Notarget_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent->flags ^= FL_NOTARGET; if (!(ent->flags & FL_NOTARGET)) { msg = "notarget OFF\n"; } else { msg = "notarget ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } void Cmd_Noclip_f(edict_t *ent) { char *msg; if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (ent->movetype == MOVETYPE_NOCLIP) { ent->movetype = MOVETYPE_WALK; msg = "noclip OFF\n"; } else { ent->movetype = MOVETYPE_NOCLIP; msg = "noclip ON\n"; } gi.cprintf(ent, PRINT_HIGH, msg); } /* * Use an inventory item */ void Cmd_Use_f(edict_t *ent) { int index; gitem_t *it; char *s; if (!ent) { return; } s = gi.args(); it = FindItem(s); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item: %s\n", s); return; } if (!it->use) { gi.cprintf(ent, PRINT_HIGH, "Item is not usable.\n"); return; } index = ITEM_INDEX(it); if (!ent->client->pers.inventory[index]) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", s); return; } it->use(ent, it); } /* * Drop an inventory item */ void Cmd_Drop_f(edict_t *ent) { int index; gitem_t *it; char *s; if (!ent) { return; } s = gi.args(); it = FindItem(s); if (!it) { gi.cprintf(ent, PRINT_HIGH, "unknown item: %s\n", s); return; } if (!it->drop) { gi.cprintf(ent, PRINT_HIGH, "Item is not dropable.\n"); return; } index = ITEM_INDEX(it); if (!ent->client->pers.inventory[index]) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", s); return; } it->drop(ent, it); } void Cmd_Score_f(edict_t *ent) { if (!ent) { return; } ent->client->showinventory = false; ent->client->showhelp = false; if (!deathmatch->value && !coop->value) { return; } if (ent->client->showscores) { ent->client->showscores = false; return; } ent->client->showscores = true; DeathmatchScoreboardMessage(ent, ent->enemy); gi.unicast(ent, true); } void Cmd_Help_f(edict_t *ent) { if (!ent) { return; } /* this is for backwards compatability */ if (deathmatch->value) { Cmd_Score_f(ent); return; } ent->client->showinventory = false; ent->client->showscores = false; if (ent->client->showhelp) { ent->client->showhelp = false; return; } ent->client->showhelp = true; ent->client->pers.helpchanged = 0; HelpComputerMessage(ent); gi.unicast(ent, true); } void Cmd_Inven_f(edict_t *ent) { gclient_t *cl; if (!ent) { return; } cl = ent->client; cl->showscores = false; cl->showhelp = false; if (cl->showinventory) { cl->showinventory = false; return; } cl->showinventory = true; InventoryMessage(ent); gi.unicast(ent, true); } void Cmd_InvUse_f(edict_t *ent) { gitem_t *it; if (!ent) { return; } ValidateSelectedItem(ent); if (ent->client->pers.selected_item == -1) { gi.cprintf(ent, PRINT_HIGH, "No item to use.\n"); return; } it = &itemlist[ent->client->pers.selected_item]; if (!it->use) { gi.cprintf(ent, PRINT_HIGH, "Item is not usable.\n"); return; } it->use(ent, it); } void Cmd_WeapPrev_f(edict_t *ent) { gclient_t *cl; int i, index; gitem_t *it; int selected_weapon; if (!ent) { return; } cl = ent->client; if (g_quick_weap->value && cl->newweapon) { it = cl->newweapon; } else if (cl->pers.weapon) { it = cl->pers.weapon; } else { return; } selected_weapon = ITEM_INDEX(it); /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { /* prevent scrolling through ALL weapons */ index = (selected_weapon + MAX_ITEMS - i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use || !(it->flags & IT_WEAPON)) { continue; } it->use(ent, it); /* prevent scrolling through ALL weapons */ if (cl->newweapon == it) { if (g_quick_weap->value) { cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(cl->newweapon->icon); cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(cl->newweapon); cl->pickup_msg_time = level.time + 0.9f; } return; } } } void Cmd_WeapNext_f(edict_t *ent) { gclient_t *cl; int i, index; gitem_t *it; int selected_weapon; if (!ent) { return; } cl = ent->client; if (g_quick_weap->value && cl->newweapon) { it = cl->newweapon; } else if (cl->pers.weapon) { it = cl->pers.weapon; } else { return; } selected_weapon = ITEM_INDEX(it); /* scan for the next valid one */ for (i = 1; i <= MAX_ITEMS; i++) { /* prevent scrolling through ALL weapons */ index = (selected_weapon + i) % MAX_ITEMS; if (!cl->pers.inventory[index]) { continue; } it = &itemlist[index]; if (!it->use || !(it->flags & IT_WEAPON)) { continue; } it->use(ent, it); /* prevent scrolling through ALL weapons */ if (cl->newweapon == it) { if (g_quick_weap->value) { cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(cl->newweapon->icon); cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(cl->newweapon); cl->pickup_msg_time = level.time + 0.9f; } return; } } } void Cmd_WeapLast_f(edict_t *ent) { gclient_t *cl; int index; gitem_t *it; if (!ent) { return; } cl = ent->client; if (!cl->pers.weapon || !cl->pers.lastweapon) { return; } index = ITEM_INDEX(cl->pers.lastweapon); if (!cl->pers.inventory[index]) { return; } it = &itemlist[index]; if (!it->use) { return; } if (!(it->flags & IT_WEAPON)) { return; } it->use(ent, it); } void Cmd_InvDrop_f(edict_t *ent) { gitem_t *it; if (!ent) { return; } ValidateSelectedItem(ent); if (ent->client->pers.selected_item == -1) { gi.cprintf(ent, PRINT_HIGH, "No item to drop.\n"); return; } it = &itemlist[ent->client->pers.selected_item]; if (!it->drop) { gi.cprintf(ent, PRINT_HIGH, "Item is not dropable.\n"); return; } it->drop(ent, it); } void Cmd_Kill_f(edict_t *ent) { if (!ent) { return; } if ((level.time - ent->client->respawn_time) < 5) { return; } ent->flags &= ~FL_GODMODE; ent->health = 0; meansOfDeath = MOD_SUICIDE; /* make sure no trackers are still hurting us. */ if (ent->client->tracker_pain_framenum) { RemoveAttackingPainDaemons(ent); } if (ent->client->owned_sphere) { G_FreeEdict(ent->client->owned_sphere); ent->client->owned_sphere = NULL; } player_die(ent, ent, ent, 100000, vec3_origin); } void Cmd_PutAway_f(edict_t *ent) { if (!ent) { return; } ent->client->showscores = false; ent->client->showhelp = false; ent->client->showinventory = false; } int PlayerSort(void const *a, void const *b) { int anum, bnum; if (!a || !b) { return 0; } anum = *(int *)a; bnum = *(int *)b; anum = game.clients[anum].ps.stats[STAT_FRAGS]; bnum = game.clients[bnum].ps.stats[STAT_FRAGS]; if (anum < bnum) { return -1; } if (anum > bnum) { return 1; } return 0; } void Cmd_Players_f(edict_t *ent) { int i; int count; char small[64]; char large[1280]; int index[256]; if (!ent) { return; } count = 0; for (i = 0; i < maxclients->value; i++) { if (game.clients[i].pers.connected) { index[count] = i; count++; } } /* sort by frags */ qsort(index, count, sizeof(index[0]), PlayerSort); /* print information */ large[0] = 0; for (i = 0; i < count; i++) { Com_sprintf(small, sizeof(small), "%3i %s\n", game.clients[index[i]].ps.stats[STAT_FRAGS], game.clients[index[i]].pers.netname); if (strlen(small) + strlen(large) > sizeof(large) - 100) { /* can't print all of them in one packet */ strcat(large, "...\n"); break; } strcat(large, small); } gi.cprintf(ent, PRINT_HIGH, "%s\n%i players\n", large, count); } void Cmd_Wave_f(edict_t *ent) { int i; if (!ent) { return; } i = atoi(gi.argv(1)); /* can't wave when ducked */ if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { return; } if (ent->client->anim_priority > ANIM_WAVE) { return; } ent->client->anim_priority = ANIM_WAVE; switch (i) { case 0: gi.cprintf(ent, PRINT_HIGH, "flipoff\n"); ent->s.frame = FRAME_flip01 - 1; ent->client->anim_end = FRAME_flip12; break; case 1: gi.cprintf(ent, PRINT_HIGH, "salute\n"); ent->s.frame = FRAME_salute01 - 1; ent->client->anim_end = FRAME_salute11; break; case 2: gi.cprintf(ent, PRINT_HIGH, "taunt\n"); ent->s.frame = FRAME_taunt01 - 1; ent->client->anim_end = FRAME_taunt17; break; case 3: gi.cprintf(ent, PRINT_HIGH, "wave\n"); ent->s.frame = FRAME_wave01 - 1; ent->client->anim_end = FRAME_wave11; break; case 4: default: gi.cprintf(ent, PRINT_HIGH, "point\n"); ent->s.frame = FRAME_point01 - 1; ent->client->anim_end = FRAME_point12; break; } } static qboolean flooded(edict_t *ent) { gclient_t *cl; int i; int num_msgs; int mx; if (!ent) { return false; } if (!deathmatch->value && !coop->value) { return false; } num_msgs = flood_msgs->value; if (num_msgs <= 0) { return false; } cl = ent->client; mx = sizeof(cl->flood_when) / sizeof(cl->flood_when[0]); if (num_msgs > mx) { gi.dprintf("flood_msgs lowered to max: 10\n"); num_msgs = mx; gi.cvar_forceset("flood_msgs", "10"); } if (level.time < cl->flood_locktill) { gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n", (int)(cl->flood_locktill - level.time)); return true; } i = (cl->flood_whenhead - num_msgs) + 1; if (i < 0) { i += mx; } if (cl->flood_when[i] && (level.time - cl->flood_when[i]) < flood_persecond->value) { cl->flood_locktill = level.time + flood_waitdelay->value; gi.cprintf(ent, PRINT_CHAT, "Flood protection: You can't talk for %d seconds.\n", (int)flood_waitdelay->value); return true; } cl->flood_whenhead = (cl->flood_whenhead + 1) % mx; cl->flood_when[cl->flood_whenhead] = level.time; return false; } void Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) { int j; edict_t *other; char *p; char text[2048]; if (!ent) { return; } if ((gi.argc() < 2) && !arg0) { return; } if (flooded(ent)) { return; } if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) { team = false; } if (team) { Com_sprintf(text, sizeof(text), "(%s): ", ent->client->pers.netname); } else { Com_sprintf(text, sizeof(text), "%s: ", ent->client->pers.netname); } if (arg0) { strcat(text, gi.argv(0)); strcat(text, " "); strcat(text, gi.args()); } else { p = gi.args(); if (*p == '"') { p++; p[strlen(p) - 1] = 0; } strcat(text, p); } /* don't let text be too long for malicious reasons */ if (strlen(text) > 150) { text[150] = 0; } strcat(text, "\n"); if (dedicated->value) { gi.cprintf(NULL, PRINT_CHAT, "%s", text); } for (j = 1; j <= game.maxclients; j++) { other = &g_edicts[j]; if (!other->inuse) { continue; } if (!other->client) { continue; } if (team) { if (!OnSameTeam(ent, other)) { continue; } } gi.cprintf(other, PRINT_CHAT, "%s", text); } } void Cmd_Ent_Count_f(edict_t *ent) { int x; edict_t *e; if (!ent) { return; } x = 0; for (e = g_edicts; e < &g_edicts[globals.num_edicts]; e++) { if (e->inuse) { x++; } } gi.dprintf("%d entites active\n", x); } void Cmd_PlayerList_f(edict_t *ent) { int i, text_len; char st[80]; char text[1400]; edict_t *e2; if (!ent) { return; } /* connect time, ping, score, name */ *text = '\0'; for (i = 0, e2 = g_edicts + 1; i < maxclients->value; i++, e2++) { if (!e2->inuse) { continue; } Com_sprintf(st, sizeof(st), "%02d:%02d %4d %3d %s%s\n", (level.framenum - e2->client->resp.enterframe) / 600, ((level.framenum - e2->client->resp.enterframe) % 600) / 10, e2->client->ping, e2->client->resp.score, e2->client->pers.netname, e2->client->resp.spectator ? " (spectator)" : ""); text_len = strlen(text); if ((text_len + strlen(st)) > (sizeof(text) - 50)) { snprintf(text + text_len, sizeof(text) - text_len, "And more...\n"); gi.cprintf(ent, PRINT_HIGH, "%s", text); return; } strcat(text, st); } gi.cprintf(ent, PRINT_HIGH, "%s", text); } void Cmd_Teleport_f(edict_t *ent) { if (!ent) { return; } if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (gi.argc() != 4) { gi.cprintf(ent, PRINT_HIGH, "Usage: teleport x y z\n"); return; } /* Unlink it to prevent unwanted interactions with other entities. This works because linkentity() uses the first available slot and the player is always at postion 0. */ gi.unlinkentity(ent); /* Set new position */ ent->s.origin[0] = atof(gi.argv(1)); ent->s.origin[1] = atof(gi.argv(2)); ent->s.origin[2] = atof(gi.argv(3)) + 10.0; /* Remove velocity and keep the entity briefly in place to give the server and clients time to catch up. */ VectorClear(ent->velocity); ent->client->ps.pmove.pm_time = 20; ent->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; /* Remove viewangles. They'll be recalculated by the client at the next frame. */ VectorClear(ent->s.angles); VectorClear(ent->client->ps.viewangles); VectorClear(ent->client->v_angle); /* Telefrag everything that's in the target location. */ KillBox(ent); /* And link it back in. */ gi.linkentity(ent); } void Cmd_ListEntities_f(edict_t *ent) { if ((deathmatch->value || coop->value) && !sv_cheats->value) { gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } if (gi.argc() < 2) { gi.cprintf(ent, PRINT_HIGH, "Usage: listentities \n"); return; } /* What to print? */ qboolean all = false; qboolean ammo = false; qboolean items = false; qboolean keys = false; qboolean monsters = false; qboolean weapons = false; for (int i = 1; i < gi.argc(); i++) { const char *arg = gi.argv(i); if (Q_stricmp(arg, "all") == 0) { all = true; } else if (Q_stricmp(arg, "ammo") == 0) { ammo = true; } else if (Q_stricmp(arg, "items") == 0) { items = true; } else if (Q_stricmp(arg, "keys") == 0) { keys = true; } else if (Q_stricmp(arg, "monsters") == 0) { monsters = true; } else if (Q_stricmp(arg, "weapons") == 0) { weapons = true; } else { gi.cprintf(ent, PRINT_HIGH, "Usage: listentities \n"); } } /* Print what's requested. */ for (int i = 0; i < globals.num_edicts; i++) { edict_t *cur = &g_edicts[i]; qboolean print = false; /* Ensure that the entity is valid. */ if (!cur->classname) { continue; } if (all) { print = true; } else { if (ammo) { if (strncmp(cur->classname, "ammo_", 5) == 0) { print = true; } } if (items) { if (strncmp(cur->classname, "item_", 5) == 0) { print = true; } } if (keys) { if (strncmp(cur->classname, "key_", 4) == 0) { print = true; } } if (monsters) { if (strncmp(cur->classname, "monster_", 8) == 0) { print = true; } } if (weapons) { if (strncmp(cur->classname, "weapon_", 7) == 0) { print = true; } } } if (print) { /* We use dprintf() because cprintf() may flood the server... */ gi.dprintf("%s: %f %f %f\n", cur->classname, cur->s.origin[0], cur->s.origin[1], cur->s.origin[2]); } } } static int get_ammo_usage(gitem_t *weap) { if (!weap) { return 0; } /* handles grenades and tesla which only use 1 ammo per shot */ /* have to check this because they don't store their ammo usage in weap->quantity */ if (weap->flags & IT_AMMO) { return 1; } /* weapons store their ammo usage in the quantity field */ return weap->quantity; } static gitem_t * cycle_weapon(edict_t *ent) { gclient_t *cl; gitem_t *noammo_fallback; gitem_t *noweap_fallback; gitem_t *weap; gitem_t *ammo; int i; int start; int num_weaps; const char *weapname = NULL; if (!ent) { return NULL; } cl = ent->client; if (!cl) { return NULL; } num_weaps = gi.argc(); /* find where we want to start the search for the next eligible weapon */ if (cl->newweapon) { weapname = cl->newweapon->classname; } else if (cl->pers.weapon) { weapname = cl->pers.weapon->classname; } if (weapname) { for (i = 1; i < num_weaps; i++) { if (Q_stricmp(weapname, gi.argv(i)) == 0) { break; } } i++; if (i >= num_weaps) { i = 1; } } else { i = 1; } start = i; noammo_fallback = NULL; noweap_fallback = NULL; /* find the first eligible weapon in the list we can switch to */ do { weap = FindItemByClassname(gi.argv(i)); if (weap && weap != cl->pers.weapon && (weap->flags & IT_WEAPON) && weap->use) { if (cl->pers.inventory[ITEM_INDEX(weap)] > 0) { if (weap->ammo) { ammo = FindItem(weap->ammo); if (ammo) { if (cl->pers.inventory[ITEM_INDEX(ammo)] >= get_ammo_usage(weap)) { return weap; } if (!noammo_fallback) { noammo_fallback = weap; } } } else { return weap; } } else if (!noweap_fallback) { noweap_fallback = weap; } } i++; if (i >= num_weaps) { i = 1; } } while (i != start); /* if no weapon was found, the fallbacks will be used for printing the appropriate error message to the console */ if (noammo_fallback) { return noammo_fallback; } return noweap_fallback; } void Cmd_CycleWeap_f(edict_t *ent) { gitem_t *weap; gclient_t *cl; int num_weaps; if (!ent) { return; } num_weaps = gi.argc(); if (num_weaps <= 1) { gi.cprintf(ent, PRINT_HIGH, "Usage: cycleweap classname1 classname2 .. classnameN\n"); return; } weap = cycle_weapon(ent); if (!weap) return; cl = ent->client; if (cl->pers.inventory[ITEM_INDEX(weap)] <= 0) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", weap->pickup_name); return; } weap->use(ent, weap); if (num_weaps > 3 && cl->newweapon == weap) { cl->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(weap->icon); cl->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(weap); cl->pickup_msg_time = level.time + 0.7f; } } static gitem_t * preferred_weapon(edict_t *ent) { gclient_t *cl; gitem_t *noammo_fallback; gitem_t *noweap_fallback; gitem_t *weap; gitem_t *ammo; int i; int num_weaps; if (!ent) { return NULL; } cl = ent->client; if (!cl) { return NULL; } num_weaps = gi.argc(); noammo_fallback = NULL; noweap_fallback = NULL; /* find the first eligible weapon in the list we can switch to */ for (i = 1; i < num_weaps; i++) { weap = FindItemByClassname(gi.argv(i)); if (weap && (weap->flags & IT_WEAPON) && weap->use) { if (cl->pers.inventory[ITEM_INDEX(weap)] > 0) { if (weap->ammo) { ammo = FindItem(weap->ammo); if (ammo) { if (cl->pers.inventory[ITEM_INDEX(ammo)] >= get_ammo_usage(weap)) { return weap; } if (!noammo_fallback) { noammo_fallback = weap; } } } else { return weap; } } else if (!noweap_fallback) { noweap_fallback = weap; } } } /* if no weapon was found, the fallbacks will be used for printing the appropriate error message to the console */ if (noammo_fallback) { return noammo_fallback; } return noweap_fallback; } void Cmd_PrefWeap_f(edict_t *ent) { gitem_t *weap; if (!ent) { return; } if (gi.argc() <= 1) { gi.cprintf(ent, PRINT_HIGH, "Usage: prefweap classname1 classname2 .. classnameN\n"); return; } weap = preferred_weapon(ent); if (weap) { if (ent->client->pers.inventory[ITEM_INDEX(weap)] <= 0) { gi.cprintf(ent, PRINT_HIGH, "Out of item: %s\n", weap->pickup_name); } else { weap->use(ent, weap); } } } void ClientCommand(edict_t *ent) { char *cmd; if (!ent) { return; } if (!ent->client) { return; /* not fully in game yet */ } cmd = gi.argv(0); if (Q_stricmp(cmd, "players") == 0) { Cmd_Players_f(ent); return; } if (Q_stricmp(cmd, "say") == 0) { Cmd_Say_f(ent, false, false); return; } if (Q_stricmp(cmd, "say_team") == 0) { Cmd_Say_f(ent, true, false); return; } if (Q_stricmp(cmd, "score") == 0) { Cmd_Score_f(ent); return; } if (Q_stricmp(cmd, "help") == 0) { Cmd_Help_f(ent); return; } if (level.intermissiontime) { return; } if (Q_stricmp(cmd, "use") == 0) { Cmd_Use_f(ent); } else if (Q_stricmp(cmd, "drop") == 0) { Cmd_Drop_f(ent); } else if (Q_stricmp(cmd, "give") == 0) { Cmd_Give_f(ent); } else if (Q_stricmp(cmd, "god") == 0) { Cmd_God_f(ent); } else if (Q_stricmp(cmd, "notarget") == 0) { Cmd_Notarget_f(ent); } else if (Q_stricmp(cmd, "noclip") == 0) { Cmd_Noclip_f(ent); } else if (Q_stricmp(cmd, "inven") == 0) { Cmd_Inven_f(ent); } else if (Q_stricmp(cmd, "invnext") == 0) { SelectNextItem(ent, -1); } else if (Q_stricmp(cmd, "invprev") == 0) { SelectPrevItem(ent, -1); } else if (Q_stricmp(cmd, "invnextw") == 0) { SelectNextItem(ent, IT_WEAPON); } else if (Q_stricmp(cmd, "invprevw") == 0) { SelectPrevItem(ent, IT_WEAPON); } else if (Q_stricmp(cmd, "invnextp") == 0) { SelectNextItem(ent, IT_POWERUP); } else if (Q_stricmp(cmd, "invprevp") == 0) { SelectPrevItem(ent, IT_POWERUP); } else if (Q_stricmp(cmd, "invuse") == 0) { Cmd_InvUse_f(ent); } else if (Q_stricmp(cmd, "invdrop") == 0) { Cmd_InvDrop_f(ent); } else if (Q_stricmp(cmd, "weapprev") == 0) { Cmd_WeapPrev_f(ent); } else if (Q_stricmp(cmd, "weapnext") == 0) { Cmd_WeapNext_f(ent); } else if (Q_stricmp(cmd, "weaplast") == 0) { Cmd_WeapLast_f(ent); } else if (Q_stricmp(cmd, "kill") == 0) { Cmd_Kill_f(ent); } else if (Q_stricmp(cmd, "putaway") == 0) { Cmd_PutAway_f(ent); } else if (Q_stricmp(cmd, "wave") == 0) { Cmd_Wave_f(ent); } else if (Q_stricmp(cmd, "playerlist") == 0) { Cmd_PlayerList_f(ent); } else if (Q_stricmp(cmd, "entcount") == 0) { Cmd_Ent_Count_f(ent); } else if (Q_stricmp(cmd, "disguise") == 0) { ent->flags |= FL_DISGUISED; } else if (Q_stricmp(cmd, "teleport") == 0) { Cmd_Teleport_f(ent); } else if (Q_stricmp(cmd, "listentities") == 0) { Cmd_ListEntities_f(ent); } else if (Q_stricmp(cmd, "cycleweap") == 0) { Cmd_CycleWeap_f(ent); } else if (Q_stricmp(cmd, "prefweap") == 0) { Cmd_PrefWeap_f(ent); } else /* anything that doesn't match a command will be a chat */ { Cmd_Say_f(ent, false, true); } } rogue-ROGUE_2_13/src/g_combat.c000066400000000000000000000540741477320066100163300ustar00rootroot00000000000000/* * ======================================================================= * * Combat code like damage, death and so on. * * ======================================================================= */ #include "header/local.h" void M_SetEffects(edict_t *self); /* * clean up heal targets for medic */ void cleanupHealTarget(edict_t *ent) { if (!ent) { return; } ent->monsterinfo.healer = NULL; ent->takedamage = DAMAGE_YES; ent->monsterinfo.aiflags &= ~AI_RESURRECTING; M_SetEffects(ent); } /* * Returns true if the inflictor can directly damage the * target. Used for explosions and melee attacks. */ qboolean CanDamage(edict_t *targ, edict_t *inflictor) { vec3_t dest; trace_t trace; if (!targ || !inflictor) { return false; } /* bmodels need special checking because their origin is 0,0,0 */ if (targ->movetype == MOVETYPE_PUSH) { VectorAdd(targ->absmin, targ->absmax, dest); VectorScale(dest, 0.5, dest); trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } if (trace.ent == targ) { return true; } return false; } trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } VectorCopy(targ->s.origin, dest); dest[0] += 15.0; dest[1] += 15.0; trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } VectorCopy(targ->s.origin, dest); dest[0] += 15.0; dest[1] -= 15.0; trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } VectorCopy(targ->s.origin, dest); dest[0] -= 15.0; dest[1] += 15.0; trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } VectorCopy(targ->s.origin, dest); dest[0] -= 15.0; dest[1] -= 15.0; trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); if (trace.fraction == 1.0) { return true; } return false; } void Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { if (!targ || !inflictor || !attacker) { return; } /* Reset AI flag for being ducked. This fixes a corner case were the monster is ressurected by a medic and get's stuck in the next frame for mmove_t not matching the AI state. */ if (targ->monsterinfo.aiflags & AI_DUCKED) { targ->monsterinfo.aiflags &= ~AI_DUCKED; } if (targ->monsterinfo.aiflags & AI_MEDIC) { if (targ->enemy) { cleanupHealTarget(targ->enemy); } /* clean up self */ targ->monsterinfo.aiflags &= ~AI_MEDIC; targ->enemy = attacker; } else { targ->enemy = attacker; } if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) { /* free up slot for spawned monster if it's spawned */ if (targ->monsterinfo.aiflags & AI_SPAWNED_CARRIER) { if (targ->monsterinfo.commander && targ->monsterinfo.commander->inuse && !strcmp(targ->monsterinfo.commander->classname, "monster_carrier")) { targ->monsterinfo.commander->monsterinfo.monster_slots++; } } if (targ->monsterinfo.aiflags & AI_SPAWNED_MEDIC_C) { if (targ->monsterinfo.commander) { if (targ->monsterinfo.commander->inuse && !strcmp(targ->monsterinfo.commander->classname, "monster_medic_commander")) { targ->monsterinfo.commander->monsterinfo.monster_slots++; } } } if (targ->monsterinfo.aiflags & AI_SPAWNED_WIDOW) { /* need to check this because we can have variable numbers of coop players */ if (targ->monsterinfo.commander && targ->monsterinfo.commander->inuse && !strncmp(targ->monsterinfo.commander->classname, "monster_widow", 13)) { if (targ->monsterinfo.commander->monsterinfo.monster_used > 0) { targ->monsterinfo.commander->monsterinfo.monster_used--; } } } if ((!(targ->monsterinfo.aiflags & AI_GOOD_GUY)) && (!(targ->monsterinfo.aiflags & AI_DO_NOT_COUNT))) { level.killed_monsters++; if (coop->value && attacker->client) { attacker->client->resp.score++; } } } if ((targ->movetype == MOVETYPE_PUSH) || (targ->movetype == MOVETYPE_STOP) || (targ->movetype == MOVETYPE_NONE)) { targ->die(targ, inflictor, attacker, damage, point); return; } if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) { targ->touch = NULL; monster_death_use(targ); } targ->die(targ, inflictor, attacker, damage, point); } void SpawnDamage(int type, vec3_t origin, vec3_t normal, int damage) { gi.WriteByte(svc_temp_entity); gi.WriteByte(type); gi.WritePosition(origin); gi.WriteDir(normal); gi.multicast(origin, MULTICAST_PVS); } /* * ============ * T_Damage * * targ entity that is being damaged * inflictor entity that is causing the damage * attacker entity that caused the inflictor to damage targ * example: targ=monster, inflictor=rocket, attacker=player * * dir direction of the attack * point point at which the damage is being inflicted * normal normal vector from that point * damage amount of damage being inflicted * knockback force to be applied against targ as a result of the damage * * dflags these flags are used to control how T_Damage works * DAMAGE_RADIUS damage was indirect (from a nearby explosion) * DAMAGE_NO_ARMOR armor does not protect from this damage * DAMAGE_ENERGY damage is from an energy based weapon * DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles * DAMAGE_BULLET damage is from a bullet (used for ricochets) * DAMAGE_NO_PROTECTION kills godmode, armor, everything * ============ */ int CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, int damage, int dflags) { gclient_t *client; int save; int power_armor_type; int index = 0; int damagePerCell; int pa_te_type; int power = 0; int power_used; if (!ent) { return 0; } if (!damage) { return 0; } client = ent->client; if (dflags & (DAMAGE_NO_ARMOR | DAMAGE_NO_POWER_ARMOR)) { return 0; } if (client) { power_armor_type = PowerArmorType(ent); if (power_armor_type != POWER_ARMOR_NONE) { index = ITEM_INDEX(FindItem("Cells")); power = client->pers.inventory[index]; } } else if (ent->svflags & SVF_MONSTER) { power_armor_type = ent->monsterinfo.power_armor_type; power = ent->monsterinfo.power_armor_power; } else { return 0; } if (power_armor_type == POWER_ARMOR_NONE) { return 0; } if (!power) { return 0; } if (power_armor_type == POWER_ARMOR_SCREEN) { vec3_t vec; float dot; vec3_t forward; /* only works if damage point is in front */ AngleVectors(ent->s.angles, forward, NULL, NULL); VectorSubtract(point, ent->s.origin, vec); VectorNormalize(vec); dot = DotProduct(vec, forward); if (dot <= 0.3) { return 0; } damagePerCell = 1; pa_te_type = TE_SCREEN_SPARKS; damage = damage / 3; } else { damagePerCell = 2; pa_te_type = TE_SHIELD_SPARKS; damage = (2 * damage) / 3; } /* etf rifle */ if (dflags & DAMAGE_NO_REG_ARMOR) { save = (power * damagePerCell) / 2; } else { save = power * damagePerCell; } if (!save) { return 0; } if (save > damage) { save = damage; } SpawnDamage(pa_te_type, point, normal, save); ent->powerarmor_time = level.time + 0.2; if (dflags & DAMAGE_NO_REG_ARMOR) { power_used = (save / damagePerCell) * 2; } else { power_used = save / damagePerCell; } if (client) { client->pers.inventory[index] -= power_used; } else { ent->monsterinfo.power_armor_power -= power_used; } return save; } int CheckArmor(edict_t *ent, vec3_t point, vec3_t normal, int damage, int te_sparks, int dflags) { gclient_t *client; int save; int index; gitem_t *armor; if (!ent) { return 0; } if (!damage) { return 0; } client = ent->client; if (!client) { return 0; } if (dflags & (DAMAGE_NO_ARMOR | DAMAGE_NO_REG_ARMOR)) { return 0; } index = ArmorIndex(ent); if (!index) { return 0; } armor = GetItemByIndex(index); if (dflags & DAMAGE_ENERGY) { save = ceil(((gitem_armor_t *)armor->info)->energy_protection * damage); } else { save = ceil(((gitem_armor_t *)armor->info)->normal_protection * damage); } if (save >= client->pers.inventory[index]) { save = client->pers.inventory[index]; } if (!save) { return 0; } client->pers.inventory[index] -= save; SpawnDamage(te_sparks, point, normal, save); return save; } void M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor) { qboolean new_tesla; if (!targ || !attacker || !inflictor) { return; } if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER)) { return; } /* logic for tesla - if you are hit by a tesla, and can't see who you should be mad at (attacker) attack the tesla also, target the tesla if it's a "new" tesla */ if (!strcmp(inflictor->classname, "tesla")) { new_tesla = MarkTeslaArea(targ, inflictor); if (new_tesla || !targ->enemy) { TargetTesla(targ, inflictor); } return; } if ((attacker == targ) || (attacker == targ->enemy)) { return; } /* if we are a good guy monster and our attacker is a player or another good guy, do not get mad at them */ if (targ->monsterinfo.aiflags & AI_GOOD_GUY) { if (attacker->client || (attacker->monsterinfo.aiflags & AI_GOOD_GUY)) { return; } } /* if we're currently mad at something a target_anger made us mad at, ignore damage */ if (targ->enemy && targ->monsterinfo.aiflags & AI_TARGET_ANGER) { float percentHealth; /* make sure whatever we were pissed at is still around. */ if (targ->enemy->inuse) { percentHealth = (float)(targ->health) / (float)(targ->max_health); if (percentHealth > 0.33) { return; } } /* remove the target anger flag */ targ->monsterinfo.aiflags &= ~AI_TARGET_ANGER; } /* if we're healing someone, do like above and try to stay with them */ if ((targ->enemy) && (targ->monsterinfo.aiflags & AI_MEDIC)) { float percentHealth; percentHealth = (float)(targ->health) / (float)(targ->max_health); /* ignore it some of the time */ if (targ->enemy->inuse && (percentHealth > 0.25)) { return; } /* remove the medic flag */ targ->monsterinfo.aiflags &= ~AI_MEDIC; cleanupHealTarget(targ->enemy); } /* if attacker is a client, get mad at them because he's good and we're not */ if (attacker->client) { targ->monsterinfo.aiflags &= ~AI_SOUND_TARGET; /* this can only happen in coop (both new and old enemies are clients) only switch if can't see the current enemy */ if (targ->enemy && targ->enemy->client) { if (visible(targ, targ->enemy)) { targ->oldenemy = attacker; return; } targ->oldenemy = targ->enemy; } targ->enemy = attacker; if (!(targ->monsterinfo.aiflags & AI_DUCKED)) { FoundTarget(targ); } return; } if (((targ->flags & (FL_FLY | FL_SWIM)) == (attacker->flags & (FL_FLY | FL_SWIM))) && (strcmp(targ->classname, attacker->classname) != 0) && !(attacker->monsterinfo.aiflags & AI_IGNORE_SHOTS) && !(targ->monsterinfo.aiflags & AI_IGNORE_SHOTS)) { if (targ->enemy && targ->enemy->client) { targ->oldenemy = targ->enemy; } targ->enemy = attacker; if (!(targ->monsterinfo.aiflags & AI_DUCKED)) { FoundTarget(targ); } } /* if they *meant* to shoot us, then shoot back */ else if (attacker->enemy == targ) { if (targ->enemy && targ->enemy->client) { targ->oldenemy = targ->enemy; } targ->enemy = attacker; if (!(targ->monsterinfo.aiflags & AI_DUCKED)) { FoundTarget(targ); } } /* otherwise get mad at whoever they are mad at (help our buddy) unless it is us! */ else if (attacker->enemy) { if (targ->enemy && targ->enemy->client) { targ->oldenemy = targ->enemy; } targ->enemy = attacker->enemy; if (!(targ->monsterinfo.aiflags & AI_DUCKED)) { FoundTarget(targ); } } } qboolean CheckTeamDamage(edict_t *targ, edict_t *attacker) { return false; } static void apply_knockback(edict_t *targ, vec3_t dir, float knockback, float scale) { vec3_t kvel; float mass; if (!knockback) { return; } mass = (targ->mass < 50) ? 50.0f : (float)targ->mass; VectorNormalize2(dir, kvel); VectorScale(kvel, scale * (knockback / mass), kvel); VectorAdd(targ->velocity, kvel, targ->velocity); } void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) { gclient_t *client; int take; int save; int asave; int psave; int te_sparks; int sphere_notified; if (!targ || !inflictor || !attacker) { return; } if (!targ->takedamage) { return; } sphere_notified = false; /* friendly fire avoidance. If enabled you can't hurt teammates (but you can hurt yourself) knockback still occurs */ if ((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value)) { if (OnSameTeam(targ, attacker)) { /* nukes kill everyone */ if (((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE) && (mod != MOD_NUKE)) { damage = 0; } else { mod |= MOD_FRIENDLY_FIRE; } } } meansOfDeath = mod; /* allow the deathmatch game to change values */ if (deathmatch->value && gamerules && gamerules->value) { if (DMGame.ChangeDamage) { damage = DMGame.ChangeDamage(targ, attacker, damage, mod); } if (DMGame.ChangeKnockback) { knockback = DMGame.ChangeKnockback(targ, attacker, knockback, mod); } if (!damage) { return; } } /* easy mode takes half damage */ if ((skill->value == SKILL_EASY) && (deathmatch->value == 0) && targ->client) { damage *= 0.5; if (!damage) { damage = 1; } } client = targ->client; /* defender sphere takes half damage */ if ((client) && (client->owned_sphere) && (client->owned_sphere->spawnflags == 1)) { damage *= 0.5; if (!damage) { damage = 1; } } if (dflags & DAMAGE_BULLET) { te_sparks = TE_BULLET_SPARKS; } else { te_sparks = TE_SPARKS; } /* bonus damage for suprising a monster */ if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) && (attacker->client) && (!targ->enemy) && (targ->health > 0)) { damage *= 2; } if (targ->flags & FL_NO_KNOCKBACK) { knockback = 0; } /* figure momentum add */ if (!(dflags & DAMAGE_NO_KNOCKBACK) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP)) { apply_knockback (targ, dir, knockback, ((client && attacker == targ) ? 1600.0f : 500.0f)); } take = damage; save = 0; /* check for godmode */ if ((targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION)) { take = 0; save = damage; SpawnDamage(te_sparks, point, normal, save); } /* check for invincibility */ if ((client && (client->invincible_framenum > level.framenum)) && !(dflags & DAMAGE_NO_PROTECTION)) { if (targ->pain_debounce_time < level.time) { gi.sound(targ, CHAN_ITEM, gi.soundindex( "items/protect4.wav"), 1, ATTN_NORM, 0); targ->pain_debounce_time = level.time + 2; } take = 0; save = damage; } /* check for monster invincibility */ if (((targ->svflags & SVF_MONSTER) && (targ->monsterinfo.invincible_framenum > level.framenum)) && !(dflags & DAMAGE_NO_PROTECTION)) { if (targ->pain_debounce_time < level.time) { gi.sound(targ, CHAN_ITEM, gi.soundindex( "items/protect4.wav"), 1, ATTN_NORM, 0); targ->pain_debounce_time = level.time + 2; } take = 0; save = damage; } psave = CheckPowerArmor(targ, point, normal, take, dflags); take -= psave; asave = CheckArmor(targ, point, normal, take, te_sparks, dflags); take -= asave; /* treat cheat/powerup savings the same as armor */ asave += save; /* this option will do damage both to the armor and person. originally for DPU rounds */ if (dflags & DAMAGE_DESTROY_ARMOR) { if (!(targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION) && !(client && (client->invincible_framenum > level.framenum))) { take = damage; } } /* do the damage */ if (take) { /* need more blood for chainfist. */ if (targ->flags & FL_MECHANICAL) { SpawnDamage(TE_ELECTRIC_SPARKS, point, normal, take); } else if ((targ->svflags & SVF_MONSTER) || (client)) { if (mod == MOD_CHAINFIST) { SpawnDamage(TE_MOREBLOOD, point, normal, 255); } else { SpawnDamage(TE_BLOOD, point, normal, take); } } else { SpawnDamage(te_sparks, point, normal, take); } targ->health = targ->health - take; /* spheres need to know who to shoot at */ if (client && client->owned_sphere) { sphere_notified = true; if (client->owned_sphere->pain) { client->owned_sphere->pain(client->owned_sphere, attacker, 0, 0); } } if (targ->health <= 0) { if ((targ->svflags & SVF_MONSTER) || (client)) { targ->flags |= FL_NO_KNOCKBACK; } Killed(targ, inflictor, attacker, take, point); return; } } /* spheres need to know who to shoot at */ if (!sphere_notified) { if (client && client->owned_sphere) { if (client->owned_sphere->pain) { client->owned_sphere->pain(client->owned_sphere, attacker, 0, 0); } } } if (targ->svflags & SVF_MONSTER) { M_ReactToDamage(targ, attacker, inflictor); if (!(targ->monsterinfo.aiflags & AI_DUCKED) && (take)) { targ->pain(targ, attacker, knockback, take); /* nightmare mode monsters don't go into pain frames often */ if (skill->value == SKILL_HARDPLUS) { targ->pain_debounce_time = level.time + 5; } } } else if (client) { if (!(targ->flags & FL_GODMODE) && (take)) { targ->pain(targ, attacker, knockback, take); } } else if (take) { if (targ->pain) { targ->pain(targ, attacker, knockback, take); } } /* add to the damage inflicted on a player this frame the total will be turned into screen blends and view angle kicks at the end of the frame */ if (client) { client->damage_parmor += psave; client->damage_armor += asave; client->damage_blood += take; client->damage_knockback += knockback; VectorCopy(point, client->damage_from); } } void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; if (!inflictor || !attacker) { return; } while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) { if (ent == ignore) { continue; } if (!ent->takedamage) { continue; } VectorAdd(ent->mins, ent->maxs, v); VectorMA(ent->s.origin, 0.5, v, v); VectorSubtract(inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength(v); if (ent == attacker) { points = points * 0.5; } if (points > 0) { if (CanDamage(ent, inflictor)) { VectorSubtract(ent->s.origin, inflictor->s.origin, dir); T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } } } } void T_RadiusNukeDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; float len; float killzone, killzone2; trace_t tr; float dist; killzone = radius; killzone2 = radius * 2.0; if (!inflictor || !attacker || !ignore) { return; } while ((ent = findradius(ent, inflictor->s.origin, killzone2)) != NULL) { /* ignore nobody */ if (ent == ignore) { continue; } if (!ent->takedamage) { continue; } if (!ent->inuse) { continue; } if (!(ent->client || (ent->svflags & SVF_MONSTER) || (ent->svflags & SVF_DAMAGEABLE))) { continue; } VectorAdd(ent->mins, ent->maxs, v); VectorMA(ent->s.origin, 0.5, v, v); VectorSubtract(inflictor->s.origin, v, v); len = VectorLength(v); if (len <= killzone) { if (ent->client) { ent->flags |= FL_NOGIB; } points = 10000; } else if (len <= killzone2) { points = (damage / killzone) * (killzone2 - len); } else { points = 0; } if (points > 0) { if (ent->client) { ent->client->nuke_framenum = level.framenum + 20; } VectorSubtract(ent->s.origin, inflictor->s.origin, dir); T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } } /* skip the worldspawn */ ent = g_edicts + 1; /* cycle through players */ while (ent) { if ((ent->client) && (ent->client->nuke_framenum != level.framenum + 20) && (ent->inuse)) { tr = gi.trace(inflictor->s.origin, NULL, NULL, ent->s.origin, inflictor, MASK_SOLID); if (tr.fraction == 1.0) { ent->client->nuke_framenum = level.framenum + 20; } else { dist = realrange(ent, inflictor); if (dist < 2048) { ent->client->nuke_framenum = max(ent->client->nuke_framenum, level.framenum + 15); } else { ent->client->nuke_framenum = max(ent->client->nuke_framenum, level.framenum + 10); } } ent++; } else { ent = NULL; } } } /* * Like T_RadiusDamage, but ignores * anything with classname=ignoreClass */ void T_RadiusClassDamage(edict_t *inflictor, edict_t *attacker, float damage, char *ignoreClass, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; if (!inflictor || !attacker || !ignoreClass) { return; } while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) { if (ent->classname && !strcmp(ent->classname, ignoreClass)) { continue; } if (!ent->takedamage) { continue; } VectorAdd(ent->mins, ent->maxs, v); VectorMA(ent->s.origin, 0.5, v, v); VectorSubtract(inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength(v); if (ent == attacker) { points = points * 0.5; } if (points > 0) { if (CanDamage(ent, inflictor)) { VectorSubtract(ent->s.origin, inflictor->s.origin, dir); T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } } } } rogue-ROGUE_2_13/src/g_func.c000066400000000000000000002212201477320066100160030ustar00rootroot00000000000000/* * ======================================================================= * * Level functions. Platforms, buttons, dooors and so on. * * ======================================================================= */ #include "header/local.h" #define PLAT_LOW_TRIGGER 1 #define PLAT2_TOGGLE 2 #define PLAT2_TOP 4 #define PLAT2_TRIGGER_TOP 8 #define PLAT2_TRIGGER_BOTTOM 16 #define PLAT2_BOX_LIFT 32 #define STATE_TOP 0 #define STATE_BOTTOM 1 #define STATE_UP 2 #define STATE_DOWN 3 #define DOOR_START_OPEN 1 #define DOOR_REVERSE 2 #define DOOR_CRUSHER 4 #define DOOR_NOMONSTER 8 #define DOOR_TOGGLE 32 #define DOOR_X_AXIS 64 #define DOOR_Y_AXIS 128 #define DOOR_INACTIVE 8192 #define AccelerationDistance(target, rate) (target * ((target / rate) + 1) / 2) #define PLAT2_CALLED 1 #define PLAT2_MOVING 2 #define PLAT2_WAITING 4 #define TRAIN_START_ON 1 #define TRAIN_TOGGLE 2 #define TRAIN_BLOCK_STOPS 4 #define SECRET_ALWAYS_SHOOT 1 #define SECRET_1ST_LEFT 2 #define SECRET_1ST_DOWN 4 void door_secret_move1(edict_t *self); void door_secret_move2(edict_t *self); void door_secret_move3(edict_t *self); void door_secret_move4(edict_t *self); void door_secret_move5(edict_t *self); void door_secret_move6(edict_t *self); void door_secret_done(edict_t *self); void train_next(edict_t *self); void door_go_down(edict_t *self); void plat2_go_down(edict_t *ent); void plat2_go_up(edict_t *ent); void plat2_spawn_danger_area(edict_t *ent); void plat2_kill_danger_area(edict_t *ent); void Think_AccelMove(edict_t *ent); void plat_go_down(edict_t *ent); /* * ========================================================= * * PLATS * * movement options: * * linear * smooth start, hard stop * smooth start, smooth stop * * start * end * acceleration * speed * deceleration * begin sound * end sound * target fired when reaching end * wait at end * * object characteristics that use move segments * --------------------------------------------- * movetype_push, or movetype_stop * action when touched * action when blocked * action when used * disabled? * auto trigger spawning * * * ========================================================= */ /* Support routines for movement (changes in origin using velocity) */ void Move_Done(edict_t *ent) { if (!ent) { return; } VectorClear(ent->velocity); ent->moveinfo.endfunc(ent); } void Move_Final(edict_t *ent) { if (!ent) { return; } if (ent->moveinfo.remaining_distance == 0) { Move_Done(ent); return; } VectorScale(ent->moveinfo.dir, ent->moveinfo.remaining_distance / FRAMETIME, ent->velocity); ent->think = Move_Done; ent->nextthink = level.time + FRAMETIME; } void Move_Begin(edict_t *ent) { if (!ent) { return; } float frames; if ((ent->moveinfo.speed * FRAMETIME) >= ent->moveinfo.remaining_distance) { Move_Final(ent); return; } VectorScale(ent->moveinfo.dir, ent->moveinfo.speed, ent->velocity); frames = floor( (ent->moveinfo.remaining_distance / ent->moveinfo.speed) / FRAMETIME); ent->moveinfo.remaining_distance -= frames * ent->moveinfo.speed * FRAMETIME; ent->nextthink = level.time + (frames * FRAMETIME); ent->think = Move_Final; } void Move_Calc(edict_t *ent, vec3_t dest, void (*func)(edict_t *)) { if (!ent || !func) { return; } VectorClear(ent->velocity); VectorSubtract(dest, ent->s.origin, ent->moveinfo.dir); ent->moveinfo.remaining_distance = VectorNormalize(ent->moveinfo.dir); ent->moveinfo.endfunc = func; if ((ent->moveinfo.speed == ent->moveinfo.accel) && (ent->moveinfo.speed == ent->moveinfo.decel)) { if (level.current_entity == ((ent->flags & FL_TEAMSLAVE) ? ent->teammaster : ent)) { Move_Begin(ent); } else { ent->nextthink = level.time + FRAMETIME; ent->think = Move_Begin; } } else { /* accelerative */ ent->moveinfo.current_speed = 0; ent->think = Think_AccelMove; ent->nextthink = level.time + FRAMETIME; } } /* Support routines for angular movement (changes in angle using avelocity) */ void AngleMove_Done(edict_t *ent) { if (!ent) { return; } VectorClear(ent->avelocity); ent->moveinfo.endfunc(ent); } void AngleMove_Final(edict_t *ent) { vec3_t move; if (!ent) { return; } if (ent->moveinfo.state == STATE_UP) { VectorSubtract(ent->moveinfo.end_angles, ent->s.angles, move); } else { VectorSubtract(ent->moveinfo.start_angles, ent->s.angles, move); } if (VectorCompare(move, vec3_origin)) { AngleMove_Done(ent); return; } VectorScale(move, 1.0 / FRAMETIME, ent->avelocity); ent->think = AngleMove_Done; ent->nextthink = level.time + FRAMETIME; } void AngleMove_Begin(edict_t *ent) { vec3_t destdelta; float len; float traveltime; float frames; if (!ent) { return; } /* accelerate as needed */ if (ent->moveinfo.speed < ent->speed) { ent->moveinfo.speed += ent->accel; if (ent->moveinfo.speed > ent->speed) { ent->moveinfo.speed = ent->speed; } } /* set destdelta to the vector needed to move */ if (ent->moveinfo.state == STATE_UP) { VectorSubtract(ent->moveinfo.end_angles, ent->s.angles, destdelta); } else { VectorSubtract(ent->moveinfo.start_angles, ent->s.angles, destdelta); } /* calculate length of vector */ len = VectorLength(destdelta); /* divide by speed to get time to reach dest */ traveltime = len / ent->moveinfo.speed; if (traveltime < FRAMETIME) { AngleMove_Final(ent); return; } frames = floor(traveltime / FRAMETIME); /* scale the destdelta vector by the time spent traveling to get velocity */ VectorScale(destdelta, 1.0 / traveltime, ent->avelocity); /* if we're done accelerating, act as a normal rotation */ if (ent->moveinfo.speed >= ent->speed) { /* set nextthink to trigger a think when dest is reached */ ent->nextthink = level.time + frames * FRAMETIME; ent->think = AngleMove_Final; } else { ent->nextthink = level.time + FRAMETIME; ent->think = AngleMove_Begin; } } void AngleMove_Calc(edict_t *ent, void (*func)(edict_t *)) { if (!ent || !func) { return; } VectorClear(ent->avelocity); ent->moveinfo.endfunc = func; /* if we're supposed to accelerate, this will tell anglemove_begin to do so */ if (ent->accel != ent->speed) { ent->moveinfo.speed = 0; } if (level.current_entity == ((ent->flags & FL_TEAMSLAVE) ? ent->teammaster : ent)) { AngleMove_Begin(ent); } else { ent->nextthink = level.time + FRAMETIME; ent->think = AngleMove_Begin; } } /* * The team has completed a frame of movement, so * change the speed for the next frame */ void plat_CalcAcceleratedMove(moveinfo_t *moveinfo) { float accel_dist; float decel_dist; if (!moveinfo) { return; } moveinfo->move_speed = moveinfo->speed; if (moveinfo->remaining_distance < moveinfo->accel) { moveinfo->current_speed = moveinfo->remaining_distance; return; } accel_dist = AccelerationDistance(moveinfo->speed, moveinfo->accel); decel_dist = AccelerationDistance(moveinfo->speed, moveinfo->decel); if ((moveinfo->remaining_distance - accel_dist - decel_dist) < 0) { float f; f = (moveinfo->accel + moveinfo->decel) / (moveinfo->accel * moveinfo->decel); moveinfo->move_speed = (-2 + sqrt(4 - 4 * f * (-2 * moveinfo->remaining_distance))) / (2 * f); decel_dist = AccelerationDistance(moveinfo->move_speed, moveinfo->decel); } moveinfo->decel_distance = decel_dist; } void plat_Accelerate(moveinfo_t *moveinfo) { if (!moveinfo) { return; } /* are we decelerating? */ if (moveinfo->remaining_distance <= moveinfo->decel_distance) { if (moveinfo->remaining_distance < moveinfo->decel_distance) { if (moveinfo->next_speed) { moveinfo->current_speed = moveinfo->next_speed; moveinfo->next_speed = 0; return; } if (moveinfo->current_speed > moveinfo->decel) { moveinfo->current_speed -= moveinfo->decel; } } return; } /* are we at full speed and need to start decelerating during this move? */ if (moveinfo->current_speed == moveinfo->move_speed) { if ((moveinfo->remaining_distance - moveinfo->current_speed) < moveinfo->decel_distance) { float p1_distance; float p2_distance; float distance; p1_distance = moveinfo->remaining_distance - moveinfo->decel_distance; p2_distance = moveinfo->move_speed * (1.0 - (p1_distance / moveinfo->move_speed)); distance = p1_distance + p2_distance; moveinfo->current_speed = moveinfo->move_speed; moveinfo->next_speed = moveinfo->move_speed - moveinfo->decel * (p2_distance / distance); return; } } /* are we accelerating? */ if (moveinfo->current_speed < moveinfo->speed) { float old_speed; float p1_distance; float p1_speed; float p2_distance; float distance; old_speed = moveinfo->current_speed; /* figure simple acceleration up to move_speed */ moveinfo->current_speed += moveinfo->accel; if (moveinfo->current_speed > moveinfo->speed) { moveinfo->current_speed = moveinfo->speed; } /* are we accelerating throughout this entire move? */ if ((moveinfo->remaining_distance - moveinfo->current_speed) >= moveinfo->decel_distance) { return; } /* during this move we will accelrate from current_speed to move_speed and cross over the decel_distance; figure the average speed for the entire move */ p1_distance = moveinfo->remaining_distance - moveinfo->decel_distance; p1_speed = (old_speed + moveinfo->move_speed) / 2.0; p2_distance = moveinfo->move_speed * (1.0 - (p1_distance / p1_speed)); distance = p1_distance + p2_distance; moveinfo->current_speed = (p1_speed * (p1_distance / distance)) + (moveinfo->move_speed * (p2_distance / distance)); moveinfo->next_speed = moveinfo->move_speed - moveinfo->decel * (p2_distance / distance); return; } /* we are at constant velocity (move_speed) */ return; } void Think_AccelMove(edict_t *ent) { if (!ent) { return; } ent->moveinfo.remaining_distance -= ent->moveinfo.current_speed; plat_CalcAcceleratedMove(&ent->moveinfo); plat_Accelerate(&ent->moveinfo); /* will the entire move complete on next frame? */ if (ent->moveinfo.remaining_distance <= ent->moveinfo.current_speed) { Move_Final(ent); return; } VectorScale(ent->moveinfo.dir, ent->moveinfo.current_speed * 10, ent->velocity); ent->nextthink = level.time + FRAMETIME; ent->think = Think_AccelMove; } void plat_hit_top(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_end) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); } ent->s.sound = 0; } ent->moveinfo.state = STATE_TOP; ent->think = plat_go_down; ent->nextthink = level.time + 3; } void plat_hit_bottom(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_end) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); } ent->s.sound = 0; } ent->moveinfo.state = STATE_BOTTOM; plat2_kill_danger_area(ent); } void plat_go_down(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_start) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); } ent->s.sound = ent->moveinfo.sound_middle; } ent->moveinfo.state = STATE_DOWN; Move_Calc(ent, ent->moveinfo.end_origin, plat_hit_bottom); } void plat_go_up(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_start) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); } ent->s.sound = ent->moveinfo.sound_middle; } ent->moveinfo.state = STATE_UP; Move_Calc(ent, ent->moveinfo.start_origin, plat_hit_top); plat2_spawn_danger_area(ent); } void plat_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); /* if it's still there, nuke it */ if (other->inuse) { /* Hack for entity without it's origin near the model */ VectorMA(other->absmin, 0.5, other->size, other->s.origin); BecomeExplosion1(other); } return; } /* gib dead things */ if (other->health < 1) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100, 1, 0, MOD_CRUSH); } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); if (self->moveinfo.state == STATE_UP) { plat_go_down(self); } else if (self->moveinfo.state == STATE_DOWN) { plat_go_up(self); } } void Use_Plat(edict_t *ent, edict_t *other, edict_t *activator /* unused */) { if (!ent || !other) { return; } /* if a monster is using us, then allow the activity when stopped. */ if (other->svflags & SVF_MONSTER) { if (ent->moveinfo.state == STATE_TOP) { plat_go_down(ent); } else if (ent->moveinfo.state == STATE_BOTTOM) { plat_go_up(ent); } return; } if (ent->think) { return; /* already down */ } plat_go_down(ent); } void wait_and_change_think(edict_t* ent) { void (*afterwaitfunc)(edict_t *) = ent->moveinfo.endfunc; ent->moveinfo.endfunc = NULL; afterwaitfunc(ent); } /* * In coop mode, this waits for coop_elevator_delay seconds * before calling afterwaitfunc(ent); otherwise it just calls * afterwaitfunc(ent); */ static void wait_and_change(edict_t* ent, void (*afterwaitfunc)(edict_t *)) { float waittime = coop_elevator_delay->value; if (coop->value && waittime > 0.0f) { if(ent->nextthink == 0) { ent->moveinfo.endfunc = afterwaitfunc; ent->think = wait_and_change_think; ent->nextthink = level.time + waittime; } } else { afterwaitfunc(ent); } } void Touch_Plat_Center(edict_t *ent, edict_t *other, cplane_t *plane /* unsed */, csurface_t *surf /* unused */) { if (!ent || !other) { return; } if (!other->client) { return; } if (other->health <= 0) { return; } ent = ent->enemy; /* now point at the plat, not the trigger */ if (ent->moveinfo.state == STATE_BOTTOM) { wait_and_change(ent, plat_go_up); } else if (ent->moveinfo.state == STATE_TOP) { ent->nextthink = level.time + 1; /* the player is still on the plat, so delay going down */ } } edict_t * plat_spawn_inside_trigger(edict_t *ent) { edict_t *trigger; vec3_t tmin, tmax; if (!ent) { return NULL; } /* middle trigger */ trigger = G_Spawn(); trigger->touch = Touch_Plat_Center; trigger->movetype = MOVETYPE_NONE; trigger->solid = SOLID_TRIGGER; trigger->enemy = ent; tmin[0] = ent->mins[0] + 25; tmin[1] = ent->mins[1] + 25; tmax[0] = ent->maxs[0] - 25; tmax[1] = ent->maxs[1] - 25; tmax[2] = ent->maxs[2] + 8; tmin[2] = tmax[2] - (ent->pos1[2] - ent->pos2[2] + st.lip); if (ent->spawnflags & PLAT_LOW_TRIGGER) { tmax[2] = tmin[2] + 8; } if (tmax[0] - tmin[0] <= 0) { tmin[0] = (ent->mins[0] + ent->maxs[0]) * 0.5; tmax[0] = tmin[0] + 1; } if (tmax[1] - tmin[1] <= 0) { tmin[1] = (ent->mins[1] + ent->maxs[1]) * 0.5; tmax[1] = tmin[1] + 1; } VectorCopy(tmin, trigger->mins); VectorCopy(tmax, trigger->maxs); gi.linkentity(trigger); return trigger; } /* * QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER * * speed -> default 150 * * Plats are always drawn in the extended position, * so they will light correctly. * * If the plat is the target of another trigger or button, * it will start out disabled in the extended position until * it is trigger, when it will lower and become a normal plat. * * "speed" overrides default 200. * "accel" overrides default 500 * "lip" overrides default 8 pixel lip * * If the "height" key is set, that will determine the amount * the plat moves, instead of being implicitly determoveinfoned * by the model's height. * * Set "sounds" to one of the following: * 1) base fast * 2) chain slow */ void SP_func_plat(edict_t *ent) { if (!ent) { return; } VectorClear(ent->s.angles); ent->solid = SOLID_BSP; ent->movetype = MOVETYPE_PUSH; gi.setmodel(ent, ent->model); ent->blocked = plat_blocked; if (!ent->speed) { ent->speed = 20; } else { ent->speed *= 0.1; } if (!ent->accel) { ent->accel = 5; } else { ent->accel *= 0.1; } if (!ent->decel) { ent->decel = 5; } else { ent->decel *= 0.1; } if (!ent->dmg) { ent->dmg = 2; } if (!st.lip) { st.lip = 8; } /* pos1 is the top position, pos2 is the bottom */ VectorCopy(ent->s.origin, ent->pos1); VectorCopy(ent->s.origin, ent->pos2); if (st.height) { ent->pos2[2] -= st.height; } else { ent->pos2[2] -= (ent->maxs[2] - ent->mins[2]) - st.lip; } ent->use = Use_Plat; plat_spawn_inside_trigger(ent); /* the "start moving" trigger */ if (ent->targetname) { ent->moveinfo.state = STATE_UP; } else { VectorCopy(ent->pos2, ent->s.origin); gi.linkentity(ent); ent->moveinfo.state = STATE_BOTTOM; } ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy(ent->pos1, ent->moveinfo.start_origin); VectorCopy(ent->s.angles, ent->moveinfo.start_angles); VectorCopy(ent->pos2, ent->moveinfo.end_origin); VectorCopy(ent->s.angles, ent->moveinfo.end_angles); ent->moveinfo.sound_start = gi.soundindex("plats/pt1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("plats/pt1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("plats/pt1_end.wav"); } void plat2_spawn_danger_area(edict_t *ent) { if (!ent) { return; } vec3_t mins, maxs; VectorCopy(ent->mins, mins); VectorCopy(ent->maxs, maxs); maxs[2] = ent->mins[2] + 64; SpawnBadArea(mins, maxs, 0, ent); } void plat2_kill_danger_area(edict_t *ent) { edict_t *t; if (!ent) { return; } t = NULL; while ((t = G_Find(t, FOFS(classname), "bad_area"))) { if (t->owner == ent) { G_FreeEdict(t); } } } void plat2_hit_top(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_end) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); } ent->s.sound = 0; } ent->moveinfo.state = STATE_TOP; if (ent->plat2flags & PLAT2_CALLED) { ent->plat2flags = PLAT2_WAITING; if (!(ent->spawnflags & PLAT2_TOGGLE)) { ent->think = plat2_go_down; ent->nextthink = level.time + 5.0; } if (deathmatch->value) { ent->last_move_time = level.time - 1.0; } else { ent->last_move_time = level.time - 2.0; } } else if (!(ent->spawnflags & PLAT2_TOP) && !(ent->spawnflags & PLAT2_TOGGLE)) { ent->plat2flags = 0; ent->think = plat2_go_down; ent->nextthink = level.time + 2.0; ent->last_move_time = level.time; } else { ent->plat2flags = 0; ent->last_move_time = level.time; } G_UseTargets(ent, ent); } void plat2_hit_bottom(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_end) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_end, 1, ATTN_STATIC, 0); } ent->s.sound = 0; } ent->moveinfo.state = STATE_BOTTOM; if (ent->plat2flags & PLAT2_CALLED) { ent->plat2flags = PLAT2_WAITING; if (!(ent->spawnflags & PLAT2_TOGGLE)) { ent->think = plat2_go_up; ent->nextthink = level.time + 5.0; } if (deathmatch->value) { ent->last_move_time = level.time - 1.0; } else { ent->last_move_time = level.time - 2.0; } } else if ((ent->spawnflags & PLAT2_TOP) && !(ent->spawnflags & PLAT2_TOGGLE)) { ent->plat2flags = 0; ent->think = plat2_go_up; ent->nextthink = level.time + 2.0; ent->last_move_time = level.time; } else { ent->plat2flags = 0; ent->last_move_time = level.time; } plat2_kill_danger_area(ent); G_UseTargets(ent, ent); } void plat2_go_down(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_start) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); } ent->s.sound = ent->moveinfo.sound_middle; } ent->moveinfo.state = STATE_DOWN; ent->plat2flags |= PLAT2_MOVING; Move_Calc(ent, ent->moveinfo.end_origin, plat2_hit_bottom); } void plat2_go_up(edict_t *ent) { if (!ent) { return; } if (!(ent->flags & FL_TEAMSLAVE)) { if (ent->moveinfo.sound_start) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, ent->moveinfo.sound_start, 1, ATTN_STATIC, 0); } ent->s.sound = ent->moveinfo.sound_middle; } ent->moveinfo.state = STATE_UP; ent->plat2flags |= PLAT2_MOVING; plat2_spawn_danger_area(ent); Move_Calc(ent, ent->moveinfo.start_origin, plat2_hit_top); } void plat2_operate(edict_t *ent, edict_t *other) { int otherState; float pauseTime; float platCenter; edict_t *trigger; if (!ent || !other) { return; } trigger = ent; ent = ent->enemy; /* now point at the plat, not the trigger */ if (ent->plat2flags & PLAT2_MOVING) { return; } if ((ent->last_move_time + 2) > level.time) { return; } platCenter = (trigger->absmin[2] + trigger->absmax[2]) / 2; if (ent->moveinfo.state == STATE_TOP) { otherState = STATE_TOP; if (ent->spawnflags & PLAT2_BOX_LIFT) { if (platCenter > other->s.origin[2]) { otherState = STATE_BOTTOM; } } else { if (trigger->absmax[2] > other->s.origin[2]) { otherState = STATE_BOTTOM; } } } else { otherState = STATE_BOTTOM; if (other->s.origin[2] > platCenter) { otherState = STATE_TOP; } } ent->plat2flags = PLAT2_MOVING; if (deathmatch->value) { pauseTime = 0.3; } else { pauseTime = 0.5; } if (ent->moveinfo.state != otherState) { ent->plat2flags |= PLAT2_CALLED; pauseTime = 0.1; } ent->last_move_time = level.time; if (ent->moveinfo.state == STATE_BOTTOM) { ent->think = plat2_go_up; ent->nextthink = level.time + pauseTime; } else { ent->think = plat2_go_down; ent->nextthink = level.time + pauseTime; } } void Touch_Plat_Center2(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!ent || !other) { return; } /* this requires monsters to actively trigger plats, not just step on them. */ if (other->health <= 0) { return; } /* don't let non-monsters activate plat2s */ if ((!(other->svflags & SVF_MONSTER)) && (!other->client)) { return; } plat2_operate(ent, other); } void plat2_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); /* if it's still there, nuke it */ if (other->inuse) { BecomeExplosion1(other); } return; } /* gib dead things */ if (other->health < 1) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100, 1, 0, MOD_CRUSH); } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); if (self->moveinfo.state == STATE_UP) { plat2_go_down(self); } else if (self->moveinfo.state == STATE_DOWN) { plat2_go_up(self); } } void Use_Plat2(edict_t *ent, edict_t *other /* unused */, edict_t *activator) { edict_t *trigger; int i; if (!ent || !activator) { return; } if (ent->moveinfo.state > STATE_BOTTOM) { return; } if ((ent->last_move_time + 2) > level.time) { return; } for (i = 1, trigger = g_edicts + 1; i < globals.num_edicts; i++, trigger++) { if (!trigger->inuse) { continue; } if (trigger->touch == Touch_Plat_Center2) { if (trigger->enemy == ent) { plat2_operate(trigger, activator); return; } } } } void plat2_activate(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { edict_t *trigger; if (!ent) { return; } ent->use = Use_Plat2; trigger = plat_spawn_inside_trigger(ent); /* the "start moving" trigger */ trigger->maxs[0] += 10; trigger->maxs[1] += 10; trigger->mins[0] -= 10; trigger->mins[1] -= 10; gi.linkentity(trigger); trigger->touch = Touch_Plat_Center2; /* Override trigger touch function */ plat2_go_down(ent); } /* QUAKED func_plat2 (0 .5 .8) ? PLAT_LOW_TRIGGER PLAT2_TOGGLE PLAT2_TOP PLAT2_TRIGGER_TOP PLAT2_TRIGGER_BOTTOM BOX_LIFT * speed default 150 * * PLAT_LOW_TRIGGER - creates a short trigger field at the bottom * PLAT2_TOGGLE - plat will not return to default position. * PLAT2_TOP - plat's default position will the the top. * PLAT2_TRIGGER_TOP - plat will trigger it's targets each time it hits top * PLAT2_TRIGGER_BOTTOM - plat will trigger it's targets each time it hits bottom * BOX_LIFT - this indicates that the lift is a box, rather than just a platform * * Plats are always drawn in the extended position, so they will light correctly. * * If the plat is the target of another trigger or button, it will start out * disabled in the extended position until it is trigger, when it will lower * and become a normal plat. * * "speed" overrides default 200. * "accel" overrides default 500 * "lip" no default * * If the "height" key is set, that will determine the amount the plat moves, * instead of being implicitly determoveinfoned by the model's height. * */ void SP_func_plat2(edict_t *ent) { edict_t *trigger; if (!ent) { return; } VectorClear(ent->s.angles); ent->solid = SOLID_BSP; ent->movetype = MOVETYPE_PUSH; gi.setmodel(ent, ent->model); ent->blocked = plat2_blocked; if (!ent->speed) { ent->speed = 20; } else { ent->speed *= 0.1; } if (!ent->accel) { ent->accel = 5; } else { ent->accel *= 0.1; } if (!ent->decel) { ent->decel = 5; } else { ent->decel *= 0.1; } if (deathmatch->value) { ent->speed *= 2; ent->accel *= 2; ent->decel *= 2; } /* Added to kill things it's being blocked by */ if (!ent->dmg) { ent->dmg = 2; } /* pos1 is the top position, pos2 is the bottom */ VectorCopy(ent->s.origin, ent->pos1); VectorCopy(ent->s.origin, ent->pos2); if (st.height) { ent->pos2[2] -= (st.height - st.lip); } else { ent->pos2[2] -= (ent->maxs[2] - ent->mins[2]) - st.lip; } ent->moveinfo.state = STATE_TOP; if (ent->targetname) { ent->use = plat2_activate; } else { ent->use = Use_Plat2; trigger = plat_spawn_inside_trigger(ent); /* the "start moving" trigger */ trigger->maxs[0] += 10; trigger->maxs[1] += 10; trigger->mins[0] -= 10; trigger->mins[1] -= 10; gi.linkentity(trigger); trigger->touch = Touch_Plat_Center2; /* Override trigger touch function */ if (!(ent->spawnflags & PLAT2_TOP)) { VectorCopy(ent->pos2, ent->s.origin); ent->moveinfo.state = STATE_BOTTOM; } } gi.linkentity(ent); ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy(ent->pos1, ent->moveinfo.start_origin); VectorCopy(ent->s.angles, ent->moveinfo.start_angles); VectorCopy(ent->pos2, ent->moveinfo.end_origin); VectorCopy(ent->s.angles, ent->moveinfo.end_angles); ent->moveinfo.sound_start = gi.soundindex("plats/pt1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("plats/pt1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("plats/pt1_end.wav"); } /* ==================================================================== */ /* QUAKED func_rotating (0 .5 .8) ? START_ON REVERSE X_AXIS Y_AXIS TOUCH_PAIN STOP ANIMATED ANIMATED_FAST EAST MED HARD DM COOP ACCEL * * You need to have an origin brush as part of this entity. The center * of that brush will bethe point around which it is rotated. It will * rotate around the Z axis by default. You can check either the * X_AXIS or Y_AXIS box to change that. * * func_rotating will use it's targets when it stops and starts. * * "speed" determines how fast it moves; default value is 100. * "dmg" damage to inflict when blocked (2 default) * "accel" if specified, is how much the rotation speed will increase per .1sec. * * REVERSE will cause the it to rotate in the opposite direction. * STOP mean it will stop moving instead of pushing entities * ACCEL means it will accelerate to it's final speed and decelerate when shutting down. */ void rotating_accel(edict_t *self) { float current_speed; if (!self) { return; } current_speed = VectorLength(self->avelocity); if (current_speed >= (self->speed - self->accel)) /* done */ { VectorScale(self->movedir, self->speed, self->avelocity); G_UseTargets(self, self); } else { current_speed += self->accel; VectorScale(self->movedir, current_speed, self->avelocity); self->think = rotating_accel; self->nextthink = level.time + FRAMETIME; } } void rotating_decel(edict_t *self) { float current_speed; if (!self) { return; } current_speed = VectorLength(self->avelocity); if (current_speed <= self->decel) /* done */ { VectorClear(self->avelocity); G_UseTargets(self, self); self->touch = NULL; } else { current_speed -= self->decel; VectorScale(self->movedir, current_speed, self->avelocity); self->think = rotating_decel; self->nextthink = level.time + FRAMETIME; } } void rotating_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); } void rotating_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (self->avelocity[0] || self->avelocity[1] || self->avelocity[2]) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); } } void rotating_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (!VectorCompare(self->avelocity, vec3_origin)) { self->s.sound = 0; if (self->spawnflags & 8192) /* Decelerate */ { rotating_decel(self); } else { VectorClear(self->avelocity); G_UseTargets(self, self); self->touch = NULL; } } else { self->s.sound = self->moveinfo.sound_middle; if (self->spawnflags & 8192) /* accelerate */ { rotating_accel(self); } else { VectorScale(self->movedir, self->speed, self->avelocity); G_UseTargets(self, self); } if (self->spawnflags & 16) { self->touch = rotating_touch; } } } void SP_func_rotating(edict_t *ent) { if (!ent) { return; } ent->solid = SOLID_BSP; if (ent->spawnflags & 32) { ent->movetype = MOVETYPE_STOP; } else { ent->movetype = MOVETYPE_PUSH; } /* set the axis of rotation */ VectorClear(ent->movedir); if (ent->spawnflags & 4) { ent->movedir[2] = 1.0; } else if (ent->spawnflags & 8) { ent->movedir[0] = 1.0; } else /* Z_AXIS */ { ent->movedir[1] = 1.0; } /* check for reverse rotation */ if (ent->spawnflags & 2) { VectorNegate(ent->movedir, ent->movedir); } if (!ent->speed) { ent->speed = 100; } if (!ent->dmg) { ent->dmg = 2; } ent->use = rotating_use; ent->blocked = rotating_blocked; if (ent->spawnflags & 1) { ent->use(ent, NULL, NULL); } if (ent->spawnflags & 64) { ent->s.effects |= EF_ANIM_ALL; } if (ent->spawnflags & 128) { ent->s.effects |= EF_ANIM_ALLFAST; } if (ent->spawnflags & 8192) /* Accelerate / Decelerate */ { if (!ent->accel) { ent->accel = 1; } else if (ent->accel > ent->speed) { ent->accel = ent->speed; } if (!ent->decel) { ent->decel = 1; } else if (ent->decel > ent->speed) { ent->decel = ent->speed; } } gi.setmodel(ent, ent->model); gi.linkentity(ent); } /* ==================================================================== */ /* BUTTONS */ /* * QUAKED func_button (0 .5 .8) ? * * When a button is touched, it moves some distance * in the direction of it's angle, triggers all of it's * targets, waits some time, then returns to it's original * position where it can be triggered again. * * "angle" determines the opening direction * "target" all entities with a matching targetname will be used * "speed" override the default 40 speed * "wait" override the default 1 second wait (-1 = never return) * "lip" override the default 4 pixel lip remaining at end of move * "health" if set, the button must be killed instead of touched * "sounds" * 1) silent * 2) steam metal * 3) wooden clunk * 4) metallic click * 5) in-out */ void button_done(edict_t *self) { if (!self) { return; } self->moveinfo.state = STATE_BOTTOM; self->s.effects &= ~EF_ANIM23; self->s.effects |= EF_ANIM01; } void button_return(edict_t *self) { if (!self) { return; } self->moveinfo.state = STATE_DOWN; Move_Calc(self, self->moveinfo.start_origin, button_done); self->s.frame = 0; if (self->health) { self->takedamage = DAMAGE_YES; } } void button_wait(edict_t *self) { if (!self) { return; } self->moveinfo.state = STATE_TOP; self->s.effects &= ~EF_ANIM01; self->s.effects |= EF_ANIM23; G_UseTargets(self, self->activator); self->s.frame = 1; if (self->moveinfo.wait >= 0) { self->nextthink = level.time + self->moveinfo.wait; self->think = button_return; } } void button_fire(edict_t *self) { if (!self) { return; } if ((self->moveinfo.state == STATE_UP) || (self->moveinfo.state == STATE_TOP)) { return; } self->moveinfo.state = STATE_UP; if (self->moveinfo.sound_start && !(self->flags & FL_TEAMSLAVE)) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); } Move_Calc(self, self->moveinfo.end_origin, button_wait); } void button_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->activator = activator; button_fire(self); } void button_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (!other->client) { return; } if (other->health <= 0) { return; } self->activator = other; button_fire(self); } void button_killed(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage /* unused */, vec3_t point /* unused */) { if (!self || !attacker) { return; } self->activator = attacker; self->health = self->max_health; self->takedamage = DAMAGE_NO; button_fire(self); } void SP_func_button(edict_t *ent) { vec3_t abs_movedir; float dist; if (!ent) { return; } G_SetMovedir(ent->s.angles, ent->movedir); ent->movetype = MOVETYPE_STOP; ent->solid = SOLID_BSP; gi.setmodel(ent, ent->model); if (ent->sounds != 1) { ent->moveinfo.sound_start = gi.soundindex("switches/butn2.wav"); } if (!ent->speed) { ent->speed = 40; } if (!ent->accel) { ent->accel = ent->speed; } if (!ent->decel) { ent->decel = ent->speed; } if (!ent->wait) { ent->wait = 3; } if (!st.lip) { st.lip = 4; } VectorCopy(ent->s.origin, ent->pos1); abs_movedir[0] = fabs(ent->movedir[0]); abs_movedir[1] = fabs(ent->movedir[1]); abs_movedir[2] = fabs(ent->movedir[2]); dist = abs_movedir[0] * ent->size[0] + abs_movedir[1] * ent->size[1] + abs_movedir[2] * ent->size[2] - st.lip; VectorMA(ent->pos1, dist, ent->movedir, ent->pos2); ent->use = button_use; ent->s.effects |= EF_ANIM01; if (ent->health) { ent->max_health = ent->health; ent->die = button_killed; ent->takedamage = DAMAGE_YES; } else if (!ent->targetname) { ent->touch = button_touch; } ent->moveinfo.state = STATE_BOTTOM; ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy(ent->pos1, ent->moveinfo.start_origin); VectorCopy(ent->s.angles, ent->moveinfo.start_angles); VectorCopy(ent->pos2, ent->moveinfo.end_origin); VectorCopy(ent->s.angles, ent->moveinfo.end_angles); gi.linkentity(ent); } /* ==================================================================== */ /* * DOORS * * spawn a trigger surrounding the entire team * unless it is already targeted by another */ /* * QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER NOMONSTER ANIMATED TOGGLE ANIMATED_FAST * * TOGGLE wait in both the start and end states for a trigger event. * START_OPEN the door to moves to its destination when spawned, and operate in reverse. * It is used to temporarily or permanently close off an area when triggered * (not useful for touch or takedamage doors). * NOMONSTER monsters will not trigger this door * * "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet * "angle" determines the opening direction * "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. * "health" if set, door must be shot open * "speed" movement speed (100 default) * "wait" wait before returning (3 default, -1 = never return) * "lip" lip remaining at end of move (8 default) * "dmg" damage to inflict when blocked (2 default) * "sounds" * 1) silent * 2) light * 3) medium * 4) heavy */ void door_use_areaportals(edict_t *self, qboolean open) { edict_t *t = NULL; if (!self) { return; } if (!self->target) { return; } while ((t = G_Find(t, FOFS(targetname), self->target))) { if (Q_stricmp(t->classname, "func_areaportal") == 0) { gi.SetAreaPortalState(t->style, open); } } } void door_hit_top(edict_t *self) { if (!self) { return; } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_end) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); } self->s.sound = 0; } self->moveinfo.state = STATE_TOP; if (self->spawnflags & DOOR_TOGGLE) { return; } if (self->moveinfo.wait >= 0) { self->think = door_go_down; self->nextthink = level.time + self->moveinfo.wait; } } void door_hit_bottom(edict_t *self) { if (!self) { return; } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_end) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); } self->s.sound = 0; } self->moveinfo.state = STATE_BOTTOM; door_use_areaportals(self, false); } void door_go_down(edict_t *self) { if (!self) { return; } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_start) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); } self->s.sound = self->moveinfo.sound_middle; } if (self->max_health) { self->takedamage = DAMAGE_YES; self->health = self->max_health; } self->moveinfo.state = STATE_DOWN; if (strcmp(self->classname, "func_door") == 0) { Move_Calc(self, self->moveinfo.start_origin, door_hit_bottom); } else if (strcmp(self->classname, "func_door_rotating") == 0) { AngleMove_Calc(self, door_hit_bottom); } } void door_go_up(edict_t *self, edict_t *activator) { if (!self) { return; } if (self->moveinfo.state == STATE_UP) { return; /* already going up */ } if (self->moveinfo.state == STATE_TOP) { /* reset top wait time */ if (self->moveinfo.wait >= 0) { self->nextthink = level.time + self->moveinfo.wait; } return; } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_start) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); } self->s.sound = self->moveinfo.sound_middle; } self->moveinfo.state = STATE_UP; if (strcmp(self->classname, "func_door") == 0) { Move_Calc(self, self->moveinfo.end_origin, door_hit_top); } else if (strcmp(self->classname, "func_door_rotating") == 0) { AngleMove_Calc(self, door_hit_top); } G_UseTargets(self, activator); door_use_areaportals(self, true); } void smart_water_go_up(edict_t *self) { float distance; edict_t *lowestPlayer; edict_t *ent; float lowestPlayerPt; int i; if (!self) { return; } if (self->moveinfo.state == STATE_TOP) { /* reset top wait time */ if (self->moveinfo.wait >= 0) { self->nextthink = level.time + self->moveinfo.wait; } return; } if (self->health) { if (self->absmax[2] >= self->health) { VectorClear(self->velocity); self->nextthink = 0; self->moveinfo.state = STATE_TOP; return; } } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_start) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); } self->s.sound = self->moveinfo.sound_middle; } /* find the lowest player point. */ lowestPlayerPt = 999999; lowestPlayer = NULL; for (i = 0; i < game.maxclients; i++) { ent = &g_edicts[1 + i]; /* don't count dead or unused player slots */ if ((ent->inuse) && (ent->health > 0)) { if (ent->absmin[2] < lowestPlayerPt) { lowestPlayerPt = ent->absmin[2]; lowestPlayer = ent; } } } if (!lowestPlayer) { return; } distance = lowestPlayerPt - self->absmax[2]; /* for the calculations, make sure we intend to go up at least a little. */ if (distance < self->accel) { distance = 100; self->moveinfo.speed = 5; } else { self->moveinfo.speed = distance / self->accel; } if (self->moveinfo.speed < 5) { self->moveinfo.speed = 5; } else if (self->moveinfo.speed > self->speed) { self->moveinfo.speed = self->speed; } /* should this allow any movement other than straight up? */ VectorSet(self->moveinfo.dir, 0, 0, 1); VectorScale(self->moveinfo.dir, self->moveinfo.speed, self->velocity); self->moveinfo.remaining_distance = distance; if (self->moveinfo.state != STATE_UP) { G_UseTargets(self, lowestPlayer); door_use_areaportals(self, true); self->moveinfo.state = STATE_UP; } self->think = smart_water_go_up; self->nextthink = level.time + FRAMETIME; } void door_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { edict_t *ent; vec3_t center; if (!self) { return; } if (self->flags & FL_TEAMSLAVE) { return; } if (self->spawnflags & DOOR_TOGGLE) { if ((self->moveinfo.state == STATE_UP) || (self->moveinfo.state == STATE_TOP)) { /* trigger all paired doors */ for (ent = self; ent; ent = ent->teamchain) { ent->message = NULL; ent->touch = NULL; door_go_down(ent); } return; } } /* smart water is different */ VectorAdd(self->mins, self->maxs, center); VectorScale(center, 0.5, center); if ((gi.pointcontents(center) & MASK_WATER) && self->spawnflags & 2) { self->message = NULL; self->touch = NULL; self->enemy = activator; smart_water_go_up(self); return; } /* trigger all paired doors */ for (ent = self; ent; ent = ent->teamchain) { ent->message = NULL; ent->touch = NULL; door_go_up(ent, activator); } } void Touch_DoorTrigger(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (other->health <= 0) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { return; } if ((self->owner->spawnflags & DOOR_NOMONSTER) && (other->svflags & SVF_MONSTER)) { return; } if (level.time < self->touch_debounce_time) { return; } self->touch_debounce_time = level.time + 1.0; door_use(self->owner, other, other); } void Think_CalcMoveSpeed(edict_t *self) { edict_t *ent; float min; float time; float newspeed; float ratio; float dist; if (!self) { return; } if (self->flags & FL_TEAMSLAVE) { return; /* only the team master does this */ } /* find the smallest distance any member of the team will be moving */ min = fabs(self->moveinfo.distance); for (ent = self->teamchain; ent; ent = ent->teamchain) { dist = fabs(ent->moveinfo.distance); if (dist < min) { min = dist; } } time = min / self->moveinfo.speed; /* adjust speeds so they will all complete at the same time */ for (ent = self; ent; ent = ent->teamchain) { newspeed = fabs(ent->moveinfo.distance) / time; ratio = newspeed / ent->moveinfo.speed; if (ent->moveinfo.accel == ent->moveinfo.speed) { ent->moveinfo.accel = newspeed; } else { ent->moveinfo.accel *= ratio; } if (ent->moveinfo.decel == ent->moveinfo.speed) { ent->moveinfo.decel = newspeed; } else { ent->moveinfo.decel *= ratio; } ent->moveinfo.speed = newspeed; } } void Think_SpawnDoorTrigger(edict_t *ent) { edict_t *other; vec3_t mins, maxs; if (!ent) { return; } if (ent->flags & FL_TEAMSLAVE) { return; /* only the team leader spawns a trigger */ } VectorCopy(ent->absmin, mins); VectorCopy(ent->absmax, maxs); for (other = ent->teamchain; other; other = other->teamchain) { AddPointToBounds(other->absmin, mins, maxs); AddPointToBounds(other->absmax, mins, maxs); } /* expand */ mins[0] -= 60; mins[1] -= 60; maxs[0] += 60; maxs[1] += 60; other = G_Spawn(); VectorCopy(mins, other->mins); VectorCopy(maxs, other->maxs); other->owner = ent; other->solid = SOLID_TRIGGER; other->movetype = MOVETYPE_NONE; other->touch = Touch_DoorTrigger; gi.linkentity(other); if (ent->spawnflags & DOOR_START_OPEN) { door_use_areaportals(ent, true); } Think_CalcMoveSpeed(ent); } void door_blocked(edict_t *self, edict_t *other) { edict_t *ent; if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); /* if it's still there, nuke it */ if (other->inuse) { /* Hack for entitiy without their origin near the model */ VectorMA(other->absmin, 0.5, other->size, other->s.origin); BecomeExplosion1(other); } return; } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); if (self->spawnflags & DOOR_CRUSHER) { return; } /* 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->moveinfo.wait >= 0) { if (self->moveinfo.state == STATE_DOWN) { for (ent = self->teammaster; ent; ent = ent->teamchain) { door_go_up(ent, ent->activator); } } else { for (ent = self->teammaster; ent; ent = ent->teamchain) { door_go_down(ent); } } } } void door_killed(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage /* unused */, vec3_t point /* unused */) { edict_t *ent; if (!self || !attacker) { return; } for (ent = self->teammaster; ent; ent = ent->teamchain) { ent->health = ent->max_health; ent->takedamage = DAMAGE_NO; } door_use(self->teammaster, attacker, attacker); } void door_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (!other->client) { return; } if (level.time < self->touch_debounce_time) { return; } self->touch_debounce_time = level.time + 5.0; gi.centerprintf(other, "%s", self->message); gi.sound(other, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0); } void SP_func_door(edict_t *ent) { vec3_t abs_movedir; if (!ent) { return; } if (ent->sounds != 1) { ent->moveinfo.sound_start = gi.soundindex("doors/dr1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("doors/dr1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("doors/dr1_end.wav"); } G_SetMovedir(ent->s.angles, ent->movedir); ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; gi.setmodel(ent, ent->model); ent->blocked = door_blocked; ent->use = door_use; if (!ent->speed) { ent->speed = 100; } if (deathmatch->value) { ent->speed *= 2; } if (!ent->accel) { ent->accel = ent->speed; } if (!ent->decel) { ent->decel = ent->speed; } if (!ent->wait) { ent->wait = 3; } if (!st.lip) { st.lip = 8; } if (!ent->dmg) { ent->dmg = 2; } /* calculate second position */ VectorCopy(ent->s.origin, ent->pos1); abs_movedir[0] = fabs(ent->movedir[0]); abs_movedir[1] = fabs(ent->movedir[1]); abs_movedir[2] = fabs(ent->movedir[2]); ent->moveinfo.distance = abs_movedir[0] * ent->size[0] + abs_movedir[1] * ent->size[1] + abs_movedir[2] * ent->size[2] - st.lip; VectorMA(ent->pos1, ent->moveinfo.distance, ent->movedir, ent->pos2); /* if it starts open, switch the positions */ if (ent->spawnflags & DOOR_START_OPEN) { VectorCopy(ent->pos2, ent->s.origin); VectorCopy(ent->pos1, ent->pos2); VectorCopy(ent->s.origin, ent->pos1); } ent->moveinfo.state = STATE_BOTTOM; if (ent->health) { ent->takedamage = DAMAGE_YES; ent->die = door_killed; ent->max_health = ent->health; } else if (ent->targetname && ent->message) { gi.soundindex("misc/talk.wav"); ent->touch = door_touch; } ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy(ent->pos1, ent->moveinfo.start_origin); VectorCopy(ent->s.angles, ent->moveinfo.start_angles); VectorCopy(ent->pos2, ent->moveinfo.end_origin); VectorCopy(ent->s.angles, ent->moveinfo.end_angles); if (ent->spawnflags & 16) { ent->s.effects |= EF_ANIM_ALL; } if (ent->spawnflags & 64) { ent->s.effects |= EF_ANIM_ALLFAST; } /* to simplify logic elsewhere, make non-teamed doors into a team of one */ if (!ent->team) { ent->teammaster = ent; } gi.linkentity(ent); ent->nextthink = level.time + FRAMETIME; if (ent->health || ent->targetname) { ent->think = Think_CalcMoveSpeed; } else { ent->think = Think_SpawnDoorTrigger; } } void Door_Activate(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->use = NULL; if (self->health) { self->takedamage = DAMAGE_YES; self->die = door_killed; self->max_health = self->health; } if (self->health) { self->think = Think_CalcMoveSpeed; } else { self->think = Think_SpawnDoorTrigger; } self->nextthink = level.time + FRAMETIME; } /* * QUAKED func_door_rotating (0 .5 .8) ? START_OPEN REVERSE CRUSHER NOMONSTER ANIMATED TOGGLE X_AXIS Y_AXIS * * TOGGLE causes the door to wait in both the start and end states for a trigger event. * START_OPEN the door to moves to its destination when spawned, and operate in reverse. * It is used to temporarily or permanently close off an area when triggered * (not useful for touch or takedamage doors). * NOMONSTER monsters will not trigger this door * * You need to have an origin brush as part of this entity. The center of that brush will be * the point around which it is rotated. It will rotate around the Z axis by default. You can * check either the X_AXIS or Y_AXIS box to change that. * * "distance" is how many degrees the door will be rotated. * "speed" determines how fast the door moves; default value is 100. * * REVERSE will cause the door to rotate in the opposite direction. * * "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet * "angle" determines the opening direction * "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. * "health" if set, door must be shot open * "speed" movement speed (100 default) * "wait" wait before returning (3 default, -1 = never return) * "dmg" damage to inflict when blocked (2 default) * "sounds" * 1) silent * 2) light * 3) medium * 4) heavy */ void SP_func_door_rotating(edict_t *ent) { if (!ent) { return; } VectorClear(ent->s.angles); /* set the axis of rotation */ VectorClear(ent->movedir); if (ent->spawnflags & DOOR_X_AXIS) { ent->movedir[2] = 1.0; } else if (ent->spawnflags & DOOR_Y_AXIS) { ent->movedir[0] = 1.0; } else /* Z_AXIS */ { ent->movedir[1] = 1.0; } /* check for reverse rotation */ if (ent->spawnflags & DOOR_REVERSE) { VectorNegate(ent->movedir, ent->movedir); } if (!st.distance) { gi.dprintf("%s at %s with no distance set\n", ent->classname, vtos(ent->s.origin)); st.distance = 90; } VectorCopy(ent->s.angles, ent->pos1); VectorMA(ent->s.angles, st.distance, ent->movedir, ent->pos2); ent->moveinfo.distance = st.distance; ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; gi.setmodel(ent, ent->model); ent->blocked = door_blocked; ent->use = door_use; if (!ent->speed) { ent->speed = 100; } if (!ent->accel) { ent->accel = ent->speed; } if (!ent->decel) { ent->decel = ent->speed; } if (!ent->wait) { ent->wait = 3; } if (!ent->dmg) { ent->dmg = 2; } if (ent->sounds != 1) { ent->moveinfo.sound_start = gi.soundindex("doors/dr1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("doors/dr1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("doors/dr1_end.wav"); } /* if it starts open, switch the positions */ if (ent->spawnflags & DOOR_START_OPEN) { VectorCopy(ent->pos2, ent->s.angles); VectorCopy(ent->pos1, ent->pos2); VectorCopy(ent->s.angles, ent->pos1); VectorNegate(ent->movedir, ent->movedir); } if (ent->health) { ent->takedamage = DAMAGE_YES; ent->die = door_killed; ent->max_health = ent->health; } if (ent->targetname && ent->message) { gi.soundindex("misc/talk.wav"); ent->touch = door_touch; } ent->moveinfo.state = STATE_BOTTOM; ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy(ent->s.origin, ent->moveinfo.start_origin); VectorCopy(ent->pos1, ent->moveinfo.start_angles); VectorCopy(ent->s.origin, ent->moveinfo.end_origin); VectorCopy(ent->pos2, ent->moveinfo.end_angles); if (ent->spawnflags & 16) { ent->s.effects |= EF_ANIM_ALL; } /* to simplify logic elsewhere, make non-teamed doors into a team of one */ if (!ent->team) { ent->teammaster = ent; } gi.linkentity(ent); ent->nextthink = level.time + FRAMETIME; if (ent->health || ent->targetname) { ent->think = Think_CalcMoveSpeed; } else { ent->think = Think_SpawnDoorTrigger; } if (ent->spawnflags & DOOR_INACTIVE) { ent->takedamage = DAMAGE_NO; ent->die = NULL; ent->think = NULL; ent->nextthink = 0; ent->use = Door_Activate; } } void smart_water_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_LAVA); /* if it's still there, nuke it */ if (other->inuse) { BecomeExplosion1(other); } return; } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100, 1, 0, MOD_LAVA); } /* ==================================================================== */ /* * QUAKED func_water (0 .5 .8) ? START_OPEN * * func_water is a moveable water brush. It must be targeted to operate. * Use a non-water texture at your own risk. * * START_OPEN causes the water to move to its destination when spawned * and operate in reverse. * * "angle" determines the opening direction (up or down only) * "speed" movement speed (25 default) * "wait" wait before returning (-1 default, -1 = TOGGLE) * "lip" lip remaining at end of move (0 default) * "sounds" (yes, these need to be changed) * 0) no sound * 1) water * 2) lava */ void SP_func_water(edict_t *self) { vec3_t abs_movedir; if (!self) { return; } G_SetMovedir(self->s.angles, self->movedir); self->movetype = MOVETYPE_PUSH; self->solid = SOLID_BSP; gi.setmodel(self, self->model); switch (self->sounds) { default: break; case 1: /* water */ case 2: /* lava */ self->moveinfo.sound_start = gi.soundindex("world/mov_watr.wav"); self->moveinfo.sound_end = gi.soundindex("world/stp_watr.wav"); break; } /* calculate second position */ VectorCopy(self->s.origin, self->pos1); abs_movedir[0] = fabs(self->movedir[0]); abs_movedir[1] = fabs(self->movedir[1]); abs_movedir[2] = fabs(self->movedir[2]); self->moveinfo.distance = abs_movedir[0] * self->size[0] + abs_movedir[1] * self->size[1] + abs_movedir[2] * self->size[2] - st.lip; VectorMA(self->pos1, self->moveinfo.distance, self->movedir, self->pos2); /* if it starts open, switch the positions */ if (self->spawnflags & DOOR_START_OPEN) { VectorCopy(self->pos2, self->s.origin); VectorCopy(self->pos1, self->pos2); VectorCopy(self->s.origin, self->pos1); } VectorCopy(self->pos1, self->moveinfo.start_origin); VectorCopy(self->s.angles, self->moveinfo.start_angles); VectorCopy(self->pos2, self->moveinfo.end_origin); VectorCopy(self->s.angles, self->moveinfo.end_angles); self->moveinfo.state = STATE_BOTTOM; if (!self->speed) { self->speed = 25; } self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed = self->speed; if (self->spawnflags & 2) /* smart water */ { if (!self->accel) { self->accel = 20; } self->blocked = smart_water_blocked; } if (!self->wait) { self->wait = -1; } self->moveinfo.wait = self->wait; self->use = door_use; if (self->wait == -1) { self->spawnflags |= DOOR_TOGGLE; } self->classname = "func_door"; gi.linkentity(self); } /* * QUAKED func_train (0 .5 .8) ? START_ON TOGGLE BLOCK_STOPS * * Trains are moving platforms that players can ride. * The targets origin specifies the min point of the train * at each corner. The train spawns at the first target it * is pointing at. If the train is the target of a button * or trigger, it will not begin moving until activated. * * speed default 100 * dmg default 2 * noise looping sound to play when the train is in motion * */ void train_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); /* if it's still there, nuke it */ if (other->inuse) { /* Hack for entity without an origin near the model */ VectorMA(other->absmin, 0.5, other->size, other->s.origin); BecomeExplosion1(other); } return; } if (level.time < self->touch_debounce_time) { return; } if (!self->dmg) { return; } self->touch_debounce_time = level.time + 0.5; T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); } void train_wait(edict_t *self) { if (!self) { return; } if (self->target_ent->pathtarget) { char *savetarget; edict_t *ent; ent = self->target_ent; savetarget = ent->target; ent->target = ent->pathtarget; G_UseTargets(ent, self->activator); ent->target = savetarget; /* make sure we didn't get killed by a killtarget */ if (!self->inuse) { return; } } if (self->moveinfo.wait) { if (self->moveinfo.wait > 0) { self->nextthink = level.time + self->moveinfo.wait; self->think = train_next; } else if (self->spawnflags & TRAIN_TOGGLE) { self->target_ent = NULL; self->spawnflags &= ~TRAIN_START_ON; VectorClear(self->velocity); self->nextthink = 0; } if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_end) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_end, 1, ATTN_STATIC, 0); } self->s.sound = 0; } } else { train_next(self); } } void train_piece_wait(edict_t *self) { } void train_next(edict_t *self) { edict_t *ent; vec3_t dest; qboolean first; if (!self) { return; } first = true; again: if (!self->target) { return; } ent = G_PickTarget(self->target); if (!ent) { gi.dprintf("train_next: bad target %s\n", self->target); return; } self->target = ent->target; /* check for a teleport path_corner */ if (ent->spawnflags & 1) { if (!first) { gi.dprintf("connected teleport path_corners, see %s at %s\n", ent->classname, vtos(ent->s.origin)); return; } first = false; VectorSubtract(ent->s.origin, self->mins, self->s.origin); VectorCopy(self->s.origin, self->s.old_origin); self->s.event = EV_OTHER_TELEPORT; gi.linkentity(self); goto again; } if (ent->speed) { self->speed = ent->speed; self->moveinfo.speed = ent->speed; if (ent->accel) { self->moveinfo.accel = ent->accel; } else { self->moveinfo.accel = ent->speed; } if (ent->decel) { self->moveinfo.decel = ent->decel; } else { self->moveinfo.decel = ent->speed; } self->moveinfo.current_speed = 0; } self->moveinfo.wait = ent->wait; self->target_ent = ent; if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_start) { gi.sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); } self->s.sound = self->moveinfo.sound_middle; } VectorSubtract(ent->s.origin, self->mins, dest); self->moveinfo.state = STATE_TOP; VectorCopy(self->s.origin, self->moveinfo.start_origin); VectorCopy(dest, self->moveinfo.end_origin); Move_Calc(self, dest, train_wait); self->spawnflags |= TRAIN_START_ON; if (self->team) { edict_t *e; vec3_t dir, dst; VectorSubtract(dest, self->s.origin, dir); for (e = self->teamchain; e; e = e->teamchain) { VectorAdd(dir, e->s.origin, dst); VectorCopy(e->s.origin, e->moveinfo.start_origin); VectorCopy(dst, e->moveinfo.end_origin); e->moveinfo.state = STATE_TOP; e->speed = self->speed; e->moveinfo.speed = self->moveinfo.speed; e->moveinfo.accel = self->moveinfo.accel; e->moveinfo.decel = self->moveinfo.decel; e->movetype = MOVETYPE_PUSH; Move_Calc(e, dst, train_piece_wait); } } } void train_resume(edict_t *self) { edict_t *ent; vec3_t dest; if (!self) { return; } ent = self->target_ent; VectorSubtract(ent->s.origin, self->mins, dest); self->moveinfo.state = STATE_TOP; VectorCopy(self->s.origin, self->moveinfo.start_origin); VectorCopy(dest, self->moveinfo.end_origin); Move_Calc(self, dest, train_wait); self->spawnflags |= TRAIN_START_ON; } void func_train_find(edict_t *self) { edict_t *ent; if (!self) { return; } if (!self->target) { gi.dprintf("train_find: no target\n"); return; } ent = G_PickTarget(self->target); if (!ent) { gi.dprintf("train_find: target %s not found\n", self->target); return; } self->target = ent->target; VectorSubtract(ent->s.origin, self->mins, self->s.origin); gi.linkentity(self); /* if not triggered, start immediately */ if (!self->targetname) { self->spawnflags |= TRAIN_START_ON; } if (self->spawnflags & TRAIN_START_ON) { self->nextthink = level.time + FRAMETIME; self->think = train_next; self->activator = self; } } void train_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->activator = activator; if (self->spawnflags & TRAIN_START_ON) { if (!(self->spawnflags & TRAIN_TOGGLE)) { return; } self->spawnflags &= ~TRAIN_START_ON; VectorClear(self->velocity); self->nextthink = 0; } else { if (self->target_ent) { train_resume(self); } else { train_next(self); } } } void SP_func_train(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_PUSH; VectorClear(self->s.angles); self->blocked = train_blocked; if (self->spawnflags & TRAIN_BLOCK_STOPS) { self->dmg = 0; } else { if (!self->dmg) { self->dmg = 100; } } self->solid = SOLID_BSP; gi.setmodel(self, self->model); if (st.noise) { self->moveinfo.sound_middle = gi.soundindex(st.noise); } if (!self->speed) { self->speed = 100; } self->moveinfo.speed = self->speed; self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; self->use = train_use; gi.linkentity(self); if (self->target) { /* start trains on the second frame, to make sure their targets have had a chance to spawn */ self->nextthink = level.time + FRAMETIME; self->think = func_train_find; } else { gi.dprintf("func_train without a target at %s\n", vtos(self->absmin)); } } /* * QUAKED trigger_elevator (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) */ void trigger_elevator_use(edict_t *self, edict_t *other, edict_t *activator /* unused */) { edict_t *target; edict_t *train; if (!self || !other) { return; } train = self->movetarget; if (!train || !train->inuse || !train->classname || strcmp(train->classname, "func_train") != 0) { return; } if (train->nextthink) { return; } if (!other->pathtarget) { gi.dprintf("elevator used with no pathtarget\n"); return; } target = G_PickTarget(other->pathtarget); if (!target) { gi.dprintf("elevator used with bad pathtarget: %s\n", other->pathtarget); return; } train->target_ent = target; train_resume(train); } void trigger_elevator_init(edict_t *self) { if (!self) { return; } if (!self->target) { gi.dprintf("trigger_elevator has no target\n"); return; } self->movetarget = G_PickTarget(self->target); if (!self->movetarget) { gi.dprintf("trigger_elevator unable to find target %s\n", self->target); return; } if (strcmp(self->movetarget->classname, "func_train") != 0) { gi.dprintf("trigger_elevator target %s is not a train\n", self->target); return; } self->use = trigger_elevator_use; self->svflags = SVF_NOCLIENT; } void SP_trigger_elevator(edict_t *self) { if (!self) { return; } self->think = trigger_elevator_init; self->nextthink = level.time + FRAMETIME; } /* ==================================================================== */ /* * QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON * * "wait" base time between triggering all targets, default is 1 * "random" wait variance, default is 0 * * so, the basic time between firing is a random time * between (wait - random) and (wait + random) * * "delay" delay before first firing when turned on, default is 0 * "pausetime" additional delay used only the very first time * and only if spawned with START_ON * * These can used but not touched. */ void func_timer_think(edict_t *self) { if (!self) { return; } G_UseTargets(self, self->activator); self->nextthink = level.time + self->wait + crandom() * self->random; } void func_timer_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self) { return; } self->activator = activator; /* if on, turn it off */ if (self->nextthink) { self->nextthink = 0; return; } /* turn it on */ if (self->delay) { self->nextthink = level.time + self->delay; } else { func_timer_think(self); } } void SP_func_timer(edict_t *self) { if (!self) { return; } if (!self->wait) { self->wait = 1.0; } self->use = func_timer_use; self->think = func_timer_think; if (self->random >= self->wait) { self->random = self->wait - FRAMETIME; gi.dprintf("func_timer at %s has random >= wait\n", vtos(self->s.origin)); } if (self->spawnflags & 1) { self->nextthink = level.time + 1.0 + st.pausetime + self->delay + self->wait + crandom() * self->random; self->activator = self; } self->svflags = SVF_NOCLIENT; } /* ==================================================================== */ /* * QUAKED func_conveyor (0 .5 .8) ? START_ON TOGGLE * * Conveyors are stationary brushes that move what's on them. * The brush should be have a surface with at least one current * content enabled. * * speed default 100 */ void func_conveyor_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->spawnflags & 1) { self->speed = 0; self->spawnflags &= ~1; } else { self->speed = self->count; self->spawnflags |= 1; } if (!(self->spawnflags & 2)) { self->count = 0; } } void SP_func_conveyor(edict_t *self) { if (!self) { return; } if (!self->speed) { self->speed = 100; } if (!(self->spawnflags & 1)) { self->count = self->speed; self->speed = 0; } self->use = func_conveyor_use; gi.setmodel(self, self->model); self->solid = SOLID_BSP; gi.linkentity(self); } /* ==================================================================== */ /* * QUAKED func_door_secret (0 .5 .8) ? always_shoot 1st_left 1st_down * A secret door. Slide back and then to the side. * * open_once doors never closes * 1st_left 1st move is left of arrow * 1st_down 1st move is down from arrow * always_shoot door is shootebale even if targeted * * "angle" determines the direction * "dmg" damage to inflic when blocked (default 2) * "wait" how long to hold in the open position (default 5, -1 means hold) */ void door_secret_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /*unused */) { if (!self) { return; } /* make sure we're not already moving */ if (!VectorCompare(self->s.origin, vec3_origin)) { return; } Move_Calc(self, self->pos1, door_secret_move1); door_use_areaportals(self, true); } void door_secret_move1(edict_t *self) { if (!self) { return; } self->nextthink = level.time + 1.0; self->think = door_secret_move2; } void door_secret_move2(edict_t *self) { if (!self) { return; } Move_Calc(self, self->pos2, door_secret_move3); } void door_secret_move3(edict_t *self) { if (!self) { return; } if (self->wait == -1) { return; } self->nextthink = level.time + self->wait; self->think = door_secret_move4; } void door_secret_move4(edict_t *self) { if (!self) { return; } Move_Calc(self, self->pos1, door_secret_move5); } void door_secret_move5(edict_t *self) { if (!self) { return; } self->nextthink = level.time + 1.0; self->think = door_secret_move6; } void door_secret_move6(edict_t *self) { if (!self) { return; } Move_Calc(self, vec3_origin, door_secret_done); } void door_secret_done(edict_t *self) { if (!self) { return; } if (!(self->targetname) || (self->spawnflags & SECRET_ALWAYS_SHOOT)) { self->health = 0; self->takedamage = DAMAGE_YES; } door_use_areaportals(self, false); } void door_secret_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(other->svflags & SVF_MONSTER) && (!other->client)) { /* give it a chance to go away on it's own terms (like gibs) */ T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); /* if it's still there, nuke it */ if (other->inuse) { /* Hack for entities without their origin near the model */ VectorMA(other->absmin, 0.5, other->size, other->s.origin); BecomeExplosion1(other); } return; } if (level.time < self->touch_debounce_time) { return; } self->touch_debounce_time = level.time + 0.5; T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); } void door_secret_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage /* unused */, vec3_t point /* unused */) { if (!self || !attacker) { return; } self->takedamage = DAMAGE_NO; door_secret_use(self, attacker, attacker); } void SP_func_door_secret(edict_t *ent) { if (!ent) { return; } vec3_t forward, right, up; float side; float width; float length; ent->moveinfo.sound_start = gi.soundindex("doors/dr1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("doors/dr1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("doors/dr1_end.wav"); ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; gi.setmodel(ent, ent->model); ent->blocked = door_secret_blocked; ent->use = door_secret_use; if (!(ent->targetname) || (ent->spawnflags & SECRET_ALWAYS_SHOOT)) { ent->health = 0; ent->takedamage = DAMAGE_YES; ent->die = door_secret_die; } if (!ent->dmg) { ent->dmg = 2; } if (!ent->wait) { ent->wait = 5; } ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = 50; /* calculate positions */ AngleVectors(ent->s.angles, forward, right, up); VectorClear(ent->s.angles); side = 1.0 - (ent->spawnflags & SECRET_1ST_LEFT); if (ent->spawnflags & SECRET_1ST_DOWN) { width = fabs(DotProduct(up, ent->size)); } else { width = fabs(DotProduct(right, ent->size)); } length = fabs(DotProduct(forward, ent->size)); if (ent->spawnflags & SECRET_1ST_DOWN) { VectorMA(ent->s.origin, -1 * width, up, ent->pos1); } else { VectorMA(ent->s.origin, side * width, right, ent->pos1); } VectorMA(ent->pos1, length, forward, ent->pos2); if (ent->health) { ent->takedamage = DAMAGE_YES; ent->die = door_killed; ent->max_health = ent->health; } else if (ent->targetname && ent->message) { gi.soundindex("misc/talk.wav"); ent->touch = door_touch; } ent->classname = "func_door"; gi.linkentity(ent); } /* ==================================================================== */ /* * QUAKED func_killbox (1 0 0) ? * * Kills everything inside when fired, * irrespective of protection. */ void use_killbox(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } KillBox(self); /* Hack to make sure that really everything is killed */ self->count--; if (!self->count) { self->think = G_FreeEdict; self->nextthink = level.time + 1; } } void SP_func_killbox(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, ent->model); ent->use = use_killbox; ent->svflags = SVF_NOCLIENT; } rogue-ROGUE_2_13/src/g_items.c000066400000000000000000001761261477320066100162070ustar00rootroot00000000000000/* * ======================================================================= * * Item handling and item definitions. * * ======================================================================= */ #include "header/local.h" #define HEALTH_IGNORE_MAX 1 #define HEALTH_TIMED 2 qboolean Pickup_Weapon(edict_t *ent, edict_t *other); void Use_Weapon(edict_t *ent, gitem_t *inv); void Drop_Weapon(edict_t *ent, gitem_t *inv); void Weapon_Blaster(edict_t *ent); void Weapon_Shotgun(edict_t *ent); void Weapon_SuperShotgun(edict_t *ent); void Weapon_Machinegun(edict_t *ent); void Weapon_Chaingun(edict_t *ent); void Weapon_HyperBlaster(edict_t *ent); void Weapon_RocketLauncher(edict_t *ent); void Weapon_Grenade(edict_t *ent); void Weapon_GrenadeLauncher(edict_t *ent); void Weapon_Railgun(edict_t *ent); void Weapon_BFG(edict_t *ent); void Weapon_ChainFist(edict_t *ent); void Weapon_Disintegrator(edict_t *ent); void Weapon_ETF_Rifle(edict_t *ent); void Weapon_Heatbeam(edict_t *ent); void Weapon_Prox(edict_t *ent); void Weapon_Tesla(edict_t *ent); void Weapon_ProxLauncher(edict_t *ent); gitem_armor_t jacketarmor_info = {25, 50, .30, .00, ARMOR_JACKET}; gitem_armor_t combatarmor_info = {50, 100, .60, .30, ARMOR_COMBAT}; gitem_armor_t bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY}; int jacket_armor_index; int combat_armor_index; int body_armor_index; static int power_screen_index; static int power_shield_index; void Use_Quad(edict_t *ent, gitem_t *item); static int quad_drop_timeout_hack; /* ====================================================================== */ gitem_t * GetItemByIndex(int index) { if ((index == 0) || (index >= game.num_items)) { return NULL; } return &itemlist[index]; } gitem_t * FindItemByClassname(char *classname) { int i; gitem_t *it; if (!classname) { return NULL; } it = itemlist; for (i = 0; i < game.num_items; i++, it++) { if (!it->classname) { continue; } if (!Q_stricmp(it->classname, classname)) { return it; } } return NULL; } gitem_t * FindItem(char *pickup_name) { int i; gitem_t *it; if (!pickup_name) { return NULL; } it = itemlist; for (i = 0; i < game.num_items; i++, it++) { if (!it->pickup_name) { continue; } if (!Q_stricmp(it->pickup_name, pickup_name)) { return it; } } return NULL; } /* ====================================================================== */ void DoRespawn(edict_t *ent) { if (!ent) { return; } if (ent->team) { edict_t *master; int count; int choice; master = ent->teammaster; for (count = 0, ent = master; ent; ent = ent->chain, count++) { } choice = count ? randk() % count : 0; for (count = 0, ent = master; count < choice; ent = ent->chain, count++) { } } if (randomrespawn && randomrespawn->value) { edict_t *newEnt; newEnt = DoRandomRespawn(ent); /* if we've changed entities, then do some sleight * of hand. otherwise, the old entity will respawn */ if (newEnt) { G_FreeEdict(ent); ent = newEnt; } } ent->svflags &= ~SVF_NOCLIENT; ent->solid = SOLID_TRIGGER; gi.linkentity(ent); /* send an effect */ ent->s.event = EV_ITEM_RESPAWN; } void SetRespawn(edict_t *ent, float delay) { if (!ent) { return; } ent->flags |= FL_RESPAWN; ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; ent->nextthink = level.time + delay; ent->think = DoRespawn; gi.linkentity(ent); } /* ====================================================================== */ qboolean Pickup_Powerup(edict_t *ent, edict_t *other) { int quantity; if (!ent || !other) { return false; } quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; if (((skill->value == SKILL_MEDIUM) && (quantity >= 2)) || ((skill->value >= SKILL_HARD) && (quantity >= 1))) { return false; } if ((coop->value) && (ent->item->flags & IT_STAY_COOP) && (quantity > 0)) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; if (deathmatch->value) { if (!(ent->spawnflags & DROPPED_ITEM)) { SetRespawn(ent, ent->item->quantity); } } return true; } void Drop_General(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } Drop_Item(ent, item); ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); } /* ====================================================================== */ qboolean Pickup_Adrenaline(edict_t *ent, edict_t *other) { if (!ent || !other) { return false; } if (!deathmatch->value) { other->max_health += 1; } if (other->health < other->max_health) { other->health = other->max_health; } if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, ent->item->quantity); } return true; } qboolean Pickup_AncientHead(edict_t *ent, edict_t *other) { if (!ent || !other) { return false; } other->max_health += 2; if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, ent->item->quantity); } return true; } qboolean Pickup_Bandolier(edict_t *ent, edict_t *other) { if (!ent || !other) { return false; } gitem_t *item; int index; if (other->client->pers.max_bullets < 250) { other->client->pers.max_bullets = 250; } if (other->client->pers.max_shells < 150) { other->client->pers.max_shells = 150; } if (other->client->pers.max_cells < 250) { other->client->pers.max_cells = 250; } if (other->client->pers.max_slugs < 75) { other->client->pers.max_slugs = 75; } if (other->client->pers.max_flechettes < 250) { other->client->pers.max_flechettes = 250; } if (g_disruptor->value) { if (other->client->pers.max_rounds < 150) { other->client->pers.max_rounds = 150; } } item = FindItem("Bullets"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_bullets) { other->client->pers.inventory[index] = other->client->pers.max_bullets; } } item = FindItem("Shells"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_shells) { other->client->pers.inventory[index] = other->client->pers.max_shells; } } if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, ent->item->quantity); } return true; } qboolean Pickup_Pack(edict_t *ent, edict_t *other) { gitem_t *item; int index; if (!ent || !other) { return false; } if (other->client->pers.max_bullets < 300) { other->client->pers.max_bullets = 300; } if (other->client->pers.max_shells < 200) { other->client->pers.max_shells = 200; } if (other->client->pers.max_rockets < 100) { other->client->pers.max_rockets = 100; } if (other->client->pers.max_grenades < 100) { other->client->pers.max_grenades = 100; } if (other->client->pers.max_cells < 300) { other->client->pers.max_cells = 300; } if (other->client->pers.max_slugs < 100) { other->client->pers.max_slugs = 100; } if (other->client->pers.max_flechettes < 300) { other->client->pers.max_flechettes = 300; } if (g_disruptor->value) { if (other->client->pers.max_rounds < 200) { other->client->pers.max_rounds = 200; } } item = FindItem("Bullets"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_bullets) { other->client->pers.inventory[index] = other->client->pers.max_bullets; } } item = FindItem("Shells"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_shells) { other->client->pers.inventory[index] = other->client->pers.max_shells; } } item = FindItem("Cells"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_cells) { other->client->pers.inventory[index] = other->client->pers.max_cells; } } item = FindItem("Grenades"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_grenades) { other->client->pers.inventory[index] = other->client->pers.max_grenades; } } item = FindItem("Rockets"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_rockets) { other->client->pers.inventory[index] = other->client->pers.max_rockets; } } item = FindItem("Slugs"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_slugs) { other->client->pers.inventory[index] = other->client->pers.max_slugs; } } item = FindItem("Flechettes"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_flechettes) { other->client->pers.inventory[index] = other->client->pers.max_flechettes; } } item = FindItem("Rounds"); if (item) { index = ITEM_INDEX(item); other->client->pers.inventory[index] += item->quantity; if (other->client->pers.inventory[index] > other->client->pers.max_rounds) { other->client->pers.inventory[index] = other->client->pers.max_rounds; } } if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, ent->item->quantity); } return true; } qboolean Pickup_Nuke(edict_t *ent, edict_t *other) { int quantity; if (!ent || !other) { return false; } quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; if (quantity >= 1) { return false; } if ((coop->value) && (ent->item->flags & IT_STAY_COOP)) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; if (deathmatch->value) { if (!(ent->spawnflags & DROPPED_ITEM)) { SetRespawn(ent, ent->item->quantity); } } return true; } void Use_IR(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (ent->client->ir_framenum > level.framenum) { ent->client->ir_framenum += 600; } else { ent->client->ir_framenum = level.framenum + 600; } gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ir_start.wav"), 1, ATTN_NORM, 0); } void Use_Double(edict_t *ent, gitem_t *item) { ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (ent->client->double_framenum > level.framenum) { ent->client->double_framenum += 300; } else { ent->client->double_framenum = level.framenum + 300; } gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage1.wav"), 1, ATTN_NORM, 0); } void Use_Compass(edict_t *ent, gitem_t *item) { int ang; if (!ent || !item) { return; } ang = (int)(ent->client->v_angle[1]); if (ang < 0) { ang += 360; } gi.cprintf(ent, PRINT_HIGH, "Origin: %0.0f,%0.0f,%0.0f Dir: %d\n", ent->s.origin[0], ent->s.origin[1], ent->s.origin[2], ang); } void Use_Nuke(edict_t *ent, gitem_t *item) { vec3_t forward, right, start; float speed; if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); AngleVectors(ent->client->v_angle, forward, right, NULL); VectorCopy(ent->s.origin, start); speed = 100; fire_nuke(ent, start, forward, speed); } void Use_Doppleganger(edict_t *ent, gitem_t *item) { vec3_t forward, right; vec3_t createPt, spawnPt; vec3_t ang; if (!ent || !item) { return; } VectorClear(ang); ang[YAW] = ent->client->v_angle[YAW]; AngleVectors(ang, forward, right, NULL); VectorMA(ent->s.origin, 48, forward, createPt); if (!FindSpawnPoint(createPt, ent->mins, ent->maxs, spawnPt, 32)) { return; } if (!CheckGroundSpawnPoint(spawnPt, ent->mins, ent->maxs, 64, -1)) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); SpawnGrow_Spawn(spawnPt, 0); fire_doppleganger(ent, spawnPt, forward); } qboolean Pickup_Doppleganger(edict_t *ent, edict_t *other) { int quantity; if (!ent || !other) { return false; } if (!(deathmatch->value)) { return false; } quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; if (quantity >= 1) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; if (!(ent->spawnflags & DROPPED_ITEM)) { SetRespawn(ent, ent->item->quantity); } return true; } qboolean Pickup_Sphere(edict_t *ent, edict_t *other) { int quantity; if (!ent || !other) { return false; } if (other->client && other->client->owned_sphere) { return false; } quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; if (((skill->value == SKILL_MEDIUM) && (quantity >= 2)) || ((skill->value >= SKILL_HARD) && (quantity >= 1))) { return false; } if ((coop->value) && (ent->item->flags & IT_STAY_COOP) && (quantity > 0)) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; if (deathmatch->value) { if (!(ent->spawnflags & DROPPED_ITEM)) { SetRespawn(ent, ent->item->quantity); } } return true; } void Use_Defender(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } if (ent->client && ent->client->owned_sphere) { gi.cprintf(ent, PRINT_HIGH, "Only one sphere at a time!\n"); return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); Defender_Launch(ent); } void Use_Hunter(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } if (ent->client && ent->client->owned_sphere) { gi.cprintf(ent, PRINT_HIGH, "Only one sphere at a time!\n"); return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); Hunter_Launch(ent); } void Use_Vengeance(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } if (ent->client && ent->client->owned_sphere) { gi.cprintf(ent, PRINT_HIGH, "Only one sphere at a time!\n"); return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); Vengeance_Launch(ent); } /* ====================================================================== */ void Use_Quad(edict_t *ent, gitem_t *item) { int timeout; if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (quad_drop_timeout_hack) { timeout = quad_drop_timeout_hack; quad_drop_timeout_hack = 0; } else { timeout = 300; } if (ent->client->quad_framenum > level.framenum) { ent->client->quad_framenum += timeout; } else { ent->client->quad_framenum = level.framenum + timeout; } gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0); } /* ====================================================================== */ void Use_Breather(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (ent->client->breather_framenum > level.framenum) { ent->client->breather_framenum += 300; } else { ent->client->breather_framenum = level.framenum + 300; } } /* ====================================================================== */ void Use_Envirosuit(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (ent->client->enviro_framenum > level.framenum) { ent->client->enviro_framenum += 300; } else { ent->client->enviro_framenum = level.framenum + 300; } } /* ====================================================================== */ void Use_Invulnerability(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); if (ent->client->invincible_framenum > level.framenum) { ent->client->invincible_framenum += 300; } else { ent->client->invincible_framenum = level.framenum + 300; } gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect.wav"), 1, ATTN_NORM, 0); } /* ====================================================================== */ void Use_Silencer(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); ent->client->silencer_shots += 30; } /* ====================================================================== */ qboolean Pickup_Key(edict_t *ent, edict_t *other) { if (!ent || !other) { return false; } if (coop->value) { if (strcmp(ent->classname, "key_power_cube") == 0) { if (other->client->pers.power_cubes & ((ent->spawnflags & 0x0000ff00) >> 8)) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; other->client->pers.power_cubes |= ((ent->spawnflags & 0x0000ff00) >> 8); } else { if (other->client->pers.inventory[ITEM_INDEX(ent->item)]) { return false; } other->client->pers.inventory[ITEM_INDEX(ent->item)] = 1; } return true; } other->client->pers.inventory[ITEM_INDEX(ent->item)]++; return true; } /* ====================================================================== */ qboolean Add_Ammo(edict_t *ent, gitem_t *item, int count) { int index; int max; if (!ent || !item) { return false; } if (!ent->client) { return false; } if (item->tag == AMMO_BULLETS) { max = ent->client->pers.max_bullets; } else if (item->tag == AMMO_SHELLS) { max = ent->client->pers.max_shells; } else if (item->tag == AMMO_ROCKETS) { max = ent->client->pers.max_rockets; } else if (item->tag == AMMO_GRENADES) { max = ent->client->pers.max_grenades; } else if (item->tag == AMMO_CELLS) { max = ent->client->pers.max_cells; } else if (item->tag == AMMO_SLUGS) { max = ent->client->pers.max_slugs; } else if (item->tag == AMMO_FLECHETTES) { max = ent->client->pers.max_flechettes; } else if (item->tag == AMMO_PROX) { max = ent->client->pers.max_prox; } else if (item->tag == AMMO_TESLA) { max = ent->client->pers.max_tesla; } else if (item->tag == AMMO_DISRUPTOR) { max = ent->client->pers.max_rounds; } else { gi.dprintf("undefined ammo type\n"); return false; } index = ITEM_INDEX(item); if (ent->client->pers.inventory[index] == max) { return false; } ent->client->pers.inventory[index] += count; if (ent->client->pers.inventory[index] > max) { ent->client->pers.inventory[index] = max; } return true; } qboolean Pickup_Ammo(edict_t *ent, edict_t *other) { int oldcount; int count; qboolean weapon; if (!ent || !other) { return false; } weapon = (ent->item->flags & IT_WEAPON); if ((weapon) && ((int)dmflags->value & DF_INFINITE_AMMO)) { count = 1000; } else if (ent->count) { count = ent->count; } else { count = ent->item->quantity; } oldcount = other->client->pers.inventory[ITEM_INDEX(ent->item)]; if (!Add_Ammo(other, ent->item, count)) { return false; } if (weapon && !oldcount) { /* don't switch to tesla */ if ((other->client->pers.weapon != ent->item) && (!deathmatch->value || (other->client->pers.weapon == FindItem("blaster"))) && (strcmp(ent->classname, "ammo_tesla"))) { other->client->newweapon = ent->item; } } if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)) && (deathmatch->value)) { SetRespawn(ent, 30); } return true; } void Drop_Ammo(edict_t *ent, gitem_t *item) { edict_t *dropped; int index; if (!ent || !item) { return; } index = ITEM_INDEX(item); dropped = Drop_Item(ent, item); if (ent->client->pers.inventory[index] >= item->quantity) { dropped->count = item->quantity; } else { dropped->count = ent->client->pers.inventory[index]; } if (ent->client->pers.weapon && (ent->client->pers.weapon->tag == AMMO_GRENADES) && (item->tag == AMMO_GRENADES) && (ent->client->pers.inventory[index] - dropped->count <= 0)) { gi.cprintf(ent, PRINT_HIGH, "Can't drop current weapon\n"); G_FreeEdict(dropped); return; } ent->client->pers.inventory[index] -= dropped->count; ValidateSelectedItem(ent); } /* ====================================================================== */ void MegaHealth_think(edict_t *self) { if (!self) { return; } if (self->owner->health > self->owner->max_health) { self->nextthink = level.time + 1; self->owner->health -= 1; return; } if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(self, 20); } else { G_FreeEdict(self); } } qboolean Pickup_Health(edict_t *ent, edict_t *other) { if (!ent || !other) { return false; } if (!(ent->style & HEALTH_IGNORE_MAX)) { if (other->health >= other->max_health) { return false; } } other->health += ent->count; if (!(ent->style & HEALTH_IGNORE_MAX)) { if (other->health > other->max_health) { other->health = other->max_health; } } if (ent->style & HEALTH_TIMED) { ent->think = MegaHealth_think; ent->nextthink = level.time + 5; ent->owner = other; ent->flags |= FL_RESPAWN; ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; } else { if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, 30); } } return true; } /* ====================================================================== */ int ArmorIndex(edict_t *ent) { if (!ent) { return 0; } if (!ent->client) { return 0; } if (ent->client->pers.inventory[jacket_armor_index] > 0) { return jacket_armor_index; } if (ent->client->pers.inventory[combat_armor_index] > 0) { return combat_armor_index; } if (ent->client->pers.inventory[body_armor_index] > 0) { return body_armor_index; } return 0; } qboolean Pickup_Armor(edict_t *ent, edict_t *other) { int old_armor_index; gitem_armor_t *oldinfo; gitem_armor_t *newinfo; int newcount; float salvage; int salvagecount; if (!ent || !other) { return false; } /* get info on new armor */ newinfo = (gitem_armor_t *)ent->item->info; old_armor_index = ArmorIndex(other); /* handle armor shards specially */ if (ent->item->tag == ARMOR_SHARD) { if (!old_armor_index) { other->client->pers.inventory[jacket_armor_index] = 2; } else { other->client->pers.inventory[old_armor_index] += 2; } } /* if player has no armor, just use it */ else if (!old_armor_index) { other->client->pers.inventory[ITEM_INDEX(ent->item)] = newinfo->base_count; } /* use the better armor */ else { /* get info on old armor */ if (old_armor_index == jacket_armor_index) { oldinfo = &jacketarmor_info; } else if (old_armor_index == combat_armor_index) { oldinfo = &combatarmor_info; } else { oldinfo = &bodyarmor_info; } if (newinfo->normal_protection > oldinfo->normal_protection) { /* calc new armor values */ salvage = oldinfo->normal_protection / newinfo->normal_protection; salvagecount = salvage * other->client->pers.inventory[old_armor_index]; newcount = newinfo->base_count + salvagecount; if (newcount > newinfo->max_count) { newcount = newinfo->max_count; } /* zero count of old armor so it goes away */ other->client->pers.inventory[old_armor_index] = 0; /* change armor to new item with computed value */ other->client->pers.inventory[ITEM_INDEX(ent->item)] = newcount; } else { /* calc new armor values */ salvage = newinfo->normal_protection / oldinfo->normal_protection; salvagecount = salvage * newinfo->base_count; newcount = other->client->pers.inventory[old_armor_index] + salvagecount; if (newcount > oldinfo->max_count) { newcount = oldinfo->max_count; } /* if we're already maxed out then we don't need the new armor */ if (other->client->pers.inventory[old_armor_index] >= newcount) { return false; } /* update current armor value */ other->client->pers.inventory[old_armor_index] = newcount; } } if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) { SetRespawn(ent, 20); } return true; } /* ====================================================================== */ int PowerArmorType(edict_t *ent) { if (!ent) { return POWER_ARMOR_NONE; } if (!ent->client) { return POWER_ARMOR_NONE; } if (!(ent->flags & FL_POWER_ARMOR)) { return POWER_ARMOR_NONE; } if (ent->client->pers.inventory[power_shield_index] > 0) { return POWER_ARMOR_SHIELD; } if (ent->client->pers.inventory[power_screen_index] > 0) { return POWER_ARMOR_SCREEN; } return POWER_ARMOR_NONE; } void Use_PowerArmor(edict_t *ent, gitem_t *item) { int index; if (ent->flags & FL_POWER_ARMOR) { ent->flags &= ~FL_POWER_ARMOR; gi.sound(ent, CHAN_AUTO, gi.soundindex( "misc/power2.wav"), 1, ATTN_NORM, 0); } else { index = ITEM_INDEX(FindItem("cells")); if (!ent->client->pers.inventory[index]) { gi.cprintf(ent, PRINT_HIGH, "No cells for power armor.\n"); return; } ent->flags |= FL_POWER_ARMOR; gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0); } } qboolean Pickup_PowerArmor(edict_t *ent, edict_t *other) { int quantity; if (!ent || !other) { return false; } quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; other->client->pers.inventory[ITEM_INDEX(ent->item)]++; if (deathmatch->value) { if (!(ent->spawnflags & DROPPED_ITEM)) { SetRespawn(ent, ent->item->quantity); } /* auto-use for DM only if we didn't already have one */ if (!quantity) { ent->item->use(other, ent->item); } } return true; } void Drop_PowerArmor(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } if ((ent->flags & FL_POWER_ARMOR) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1)) { Use_PowerArmor(ent, item); } Drop_General(ent, item); } /* ====================================================================== */ void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { qboolean taken; if (!ent || !other) { return; } if (!other->client) { return; } if (other->health < 1) { return; /* dead people can't pickup */ } if (!ent->item->pickup) { return; /* not a grabbable item? */ } taken = ent->item->pickup(ent, other); if (taken) { /* flash the screen */ other->client->bonus_alpha = 0.25; /* show icon and name on status bar */ other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(ent->item->icon); other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(ent->item); other->client->pickup_msg_time = level.time + 3.0; /* change selected item */ if (ent->item->use) { other->client->pers.selected_item = other->client->ps.stats[STAT_SELECTED_ITEM] = ITEM_INDEX(ent->item); } if (ent->item->pickup == Pickup_Health) { if (ent->count == 2) { gi.sound(other, CHAN_ITEM, gi.soundindex("items/s_health.wav"), 1, ATTN_NORM, 0); } else if (ent->count == 10) { gi.sound(other, CHAN_ITEM, gi.soundindex("items/n_health.wav"), 1, ATTN_NORM, 0); } else if (ent->count == 25) { gi.sound(other, CHAN_ITEM, gi.soundindex("items/l_health.wav"), 1, ATTN_NORM, 0); } else /* (ent->count == 100) */ { gi.sound(other, CHAN_ITEM, gi.soundindex("items/m_health.wav"), 1, ATTN_NORM, 0); } } else if (ent->item->pickup_sound) { gi.sound(other, CHAN_ITEM, gi.soundindex(ent->item->pickup_sound), 1, ATTN_NORM, 0); } /* activate item instantly if appropriate */ /* moved down here so activation sounds override the pickup sound */ if (deathmatch->value) { if ((((int)dmflags->value & DF_INSTANT_ITEMS) && (ent->item->flags & IT_INSTANT_USE)) || ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM))) { if ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM)) { quad_drop_timeout_hack = (ent->nextthink - level.time) / FRAMETIME; } if (ent->item->use) { ent->item->use(other, ent->item); } else { gi.dprintf("Powerup has no use function!\n"); } } } } if (!(ent->spawnflags & ITEM_TARGETS_USED)) { G_UseTargets(ent, other); ent->spawnflags |= ITEM_TARGETS_USED; } if (!taken) { return; } if (!((coop->value) && (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) { if (ent->flags & FL_RESPAWN) { ent->flags &= ~FL_RESPAWN; } else { G_FreeEdict(ent); } } } /* ====================================================================== */ void drop_temp_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { if (!ent || !other) { return; } if (other == ent->owner) { return; } Touch_Item(ent, other, plane, surf); } void drop_make_touchable(edict_t *ent) { if (!ent) { return; } ent->touch = Touch_Item; if (deathmatch->value) { ent->nextthink = level.time + 29; ent->think = G_FreeEdict; } } edict_t * Drop_Item(edict_t *ent, gitem_t *item) { edict_t *dropped; vec3_t forward, right; vec3_t offset; if (!ent || !item) { return NULL; } dropped = G_Spawn(); dropped->classname = item->classname; dropped->item = item; dropped->spawnflags = DROPPED_ITEM; dropped->s.effects = item->world_model_flags; dropped->s.renderfx = RF_GLOW | RF_IR_VISIBLE; VectorSet(dropped->mins, -15, -15, -15); VectorSet(dropped->maxs, 15, 15, 15); gi.setmodel(dropped, dropped->item->world_model); dropped->solid = SOLID_TRIGGER; dropped->movetype = MOVETYPE_TOSS; dropped->touch = drop_temp_touch; dropped->owner = ent; if (ent->client) { trace_t trace; AngleVectors(ent->client->v_angle, forward, right, NULL); VectorSet(offset, 24, 0, -16); G_ProjectSource(ent->s.origin, offset, forward, right, dropped->s.origin); trace = gi.trace(ent->s.origin, dropped->mins, dropped->maxs, dropped->s.origin, ent, CONTENTS_SOLID); VectorCopy(trace.endpos, dropped->s.origin); } else { AngleVectors(ent->s.angles, forward, right, NULL); VectorCopy(ent->s.origin, dropped->s.origin); } VectorScale(forward, 100, dropped->velocity); dropped->velocity[2] = 300; dropped->think = drop_make_touchable; dropped->nextthink = level.time + 1; gi.linkentity(dropped); return dropped; } void Use_Item(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } ent->svflags &= ~SVF_NOCLIENT; ent->use = NULL; if (ent->spawnflags & ITEM_NO_TOUCH) { ent->solid = SOLID_BBOX; ent->touch = NULL; } else { ent->solid = SOLID_TRIGGER; ent->touch = Touch_Item; } gi.linkentity(ent); } /* ====================================================================== */ void droptofloor(edict_t *ent) { if (!ent) { return; } trace_t tr; vec3_t dest; float *v; v = tv(-15, -15, -15); VectorCopy(v, ent->mins); v = tv(15, 15, 15); VectorCopy(v, ent->maxs); if (ent->model) { gi.setmodel(ent, ent->model); } else if (ent->item->world_model) { gi.setmodel(ent, ent->item->world_model); } ent->solid = SOLID_TRIGGER; ent->movetype = MOVETYPE_TOSS; ent->touch = Touch_Item; v = tv(0, 0, -128); VectorAdd(ent->s.origin, v, dest); tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID); if (tr.startsolid) { gi.dprintf("droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin)); G_FreeEdict(ent); return; } VectorCopy(tr.endpos, ent->s.origin); if (ent->team) { ent->flags &= ~FL_TEAMSLAVE; ent->chain = ent->teamchain; ent->teamchain = NULL; ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; if (ent == ent->teammaster) { ent->nextthink = level.time + FRAMETIME; ent->think = DoRespawn; } } if (ent->spawnflags & ITEM_NO_TOUCH) { ent->solid = SOLID_BBOX; ent->touch = NULL; ent->s.effects &= ~EF_ROTATE; ent->s.renderfx &= ~RF_GLOW; } if (ent->spawnflags & ITEM_TRIGGER_SPAWN) { ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; ent->use = Use_Item; } gi.linkentity(ent); } /* * Precaches all data needed for a given item. * This will be called for each item spawned in a level, * and for each item in each client's inventory. */ void PrecacheItem(gitem_t *it) { char *s, *start; char data[MAX_QPATH]; int len; gitem_t *ammo; if (!it) { return; } if (it->pickup_sound) { gi.soundindex(it->pickup_sound); } if (it->world_model) { gi.modelindex(it->world_model); } if (it->view_model) { gi.modelindex(it->view_model); } if (it->icon) { gi.imageindex(it->icon); } /* parse everything for its ammo */ if (it->ammo && it->ammo[0]) { ammo = FindItem(it->ammo); if (ammo != it) { PrecacheItem(ammo); } } /* parse the space seperated precache string for other items */ s = it->precaches; if (!s || !s[0]) { return; } while (*s) { start = s; while (*s && *s != ' ') { s++; } len = s - start; if ((len >= MAX_QPATH) || (len < 5)) { gi.error("PrecacheItem: %s has bad precache string", it->classname); } memcpy(data, start, len); data[len] = 0; if (*s) { s++; } /* determine type based on extension */ if (!strcmp(data + len - 3, "md2")) { gi.modelindex(data); } else if (!strcmp(data + len - 3, "sp2")) { gi.modelindex(data); } else if (!strcmp(data + len - 3, "wav")) { gi.soundindex(data); } if (!strcmp(data + len - 3, "pcx")) { gi.imageindex(data); } } } /* * Create the item marked for spawn creation */ void Item_TriggeredSpawn(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { self->svflags &= ~SVF_NOCLIENT; self->use = NULL; if (strcmp(self->classname, "key_power_cube")) { self->spawnflags = 0; } droptofloor(self); } /* * Set up an item to spawn in later. */ void SetTriggeredSpawn(edict_t *ent) { if (!ent) { return; } /* don't do anything on key_power_cubes. */ if (!strcmp(ent->classname, "key_power_cube")) { return; } ent->think = NULL; ent->nextthink = 0; ent->use = Item_TriggeredSpawn; ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; } /* * ============ * Sets the clipping size and * plants the object on the floor. * * Items can't be immediately dropped * to floor, because they might be on * an entity that hasn't spawned yet. * ============ */ void SpawnItem(edict_t *ent, gitem_t *item) { if (!ent || !item) { return; } if (!g_disruptor->value) { if ((!strcmp(ent->classname, "ammo_disruptor")) || (!strcmp(ent->classname, "weapon_disintegrator"))) { G_FreeEdict(ent); return; } } if (ent->spawnflags > 1) { if (strcmp(ent->classname, "key_power_cube") != 0) { ent->spawnflags = 0; gi.dprintf("%s at %s has invalid spawnflags set\n", ent->classname, vtos(ent->s.origin)); } } /* some items will be prevented in deathmatch */ if (deathmatch->value) { if ((int)dmflags->value & DF_NO_ARMOR) { if ((item->pickup == Pickup_Armor) || (item->pickup == Pickup_PowerArmor)) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_NO_ITEMS) { if (item->pickup == Pickup_Powerup) { G_FreeEdict(ent); return; } if (item->pickup == Pickup_Sphere) { G_FreeEdict(ent); return; } if (item->pickup == Pickup_Doppleganger) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_NO_HEALTH) { if ((item->pickup == Pickup_Health) || (item->pickup == Pickup_Adrenaline) || (item->pickup == Pickup_AncientHead)) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_INFINITE_AMMO) { if ((item->flags == IT_AMMO) || (strcmp(ent->classname, "weapon_bfg") == 0)) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_NO_MINES) { if (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_NO_NUKES) { if (!strcmp(ent->classname, "ammo_nuke")) { G_FreeEdict(ent); return; } } if ((int)dmflags->value & DF_NO_SPHERES) { if (item->pickup == Pickup_Sphere) { G_FreeEdict(ent); return; } } } /* DM only items */ if (!deathmatch->value) { if ((item->pickup == Pickup_Doppleganger) || (item->pickup == Pickup_Nuke)) { G_FreeEdict(ent); return; } if ((item->use == Use_Vengeance) || (item->use == Use_Hunter)) { G_FreeEdict(ent); return; } } PrecacheItem(item); if (coop->value && !(ent->spawnflags & ITEM_NO_TOUCH) && (strcmp(ent->classname, "key_power_cube") == 0)) { ent->spawnflags |= (1 << (8 + level.power_cubes)); level.power_cubes++; } /* don't let them drop items that stay in a coop game */ if ((coop->value) && (item->flags & IT_STAY_COOP)) { item->drop = NULL; } ent->item = item; ent->nextthink = level.time + 2 * FRAMETIME; /* items start after other solids */ ent->think = droptofloor; ent->s.effects = item->world_model_flags; ent->s.renderfx = RF_GLOW; if (ent->model) { gi.modelindex(ent->model); } if (ent->spawnflags & 1) { SetTriggeredSpawn(ent); } } /* ====================================================================== */ gitem_t itemlist[] = { { NULL }, /* leave index 0 alone */ /* QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_armor_body", Pickup_Armor, NULL, NULL, NULL, "misc/ar1_pkup.wav", "models/items/armor/body/tris.md2", EF_ROTATE, NULL, "i_bodyarmor", "Body Armor", 3, 0, NULL, IT_ARMOR, 0, &bodyarmor_info, ARMOR_BODY, "" }, /* QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_armor_combat", Pickup_Armor, NULL, NULL, NULL, "misc/ar1_pkup.wav", "models/items/armor/combat/tris.md2", EF_ROTATE, NULL, "i_combatarmor", "Combat Armor", 3, 0, NULL, IT_ARMOR, 0, &combatarmor_info, ARMOR_COMBAT, "" }, /* QUAKED item_armor_jacket (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_armor_jacket", Pickup_Armor, NULL, NULL, NULL, "misc/ar1_pkup.wav", "models/items/armor/jacket/tris.md2", EF_ROTATE, NULL, "i_jacketarmor", "Jacket Armor", 3, 0, NULL, IT_ARMOR, 0, &jacketarmor_info, ARMOR_JACKET, "" }, /* QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_armor_shard", Pickup_Armor, NULL, NULL, NULL, "misc/ar2_pkup.wav", "models/items/armor/shard/tris.md2", EF_ROTATE, NULL, "i_jacketarmor", "Armor Shard", 3, 0, NULL, IT_ARMOR, 0, NULL, ARMOR_SHARD, "" }, /* QUAKED item_power_screen (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_power_screen", Pickup_PowerArmor, Use_PowerArmor, Drop_PowerArmor, NULL, "misc/ar3_pkup.wav", "models/items/armor/screen/tris.md2", EF_ROTATE, NULL, "i_powerscreen", "Power Screen", 0, 60, NULL, IT_ARMOR, 0, NULL, 0, "" }, /* QUAKED item_power_shield (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_power_shield", Pickup_PowerArmor, Use_PowerArmor, Drop_PowerArmor, NULL, "misc/ar3_pkup.wav", "models/items/armor/shield/tris.md2", EF_ROTATE, NULL, "i_powershield", "Power Shield", 0, 60, NULL, IT_ARMOR, 0, NULL, 0, "misc/power2.wav misc/power1.wav" }, /* weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) always owned, never in the world */ { "weapon_blaster", NULL, Use_Weapon, NULL, Weapon_Blaster, "misc/w_pkup.wav", NULL, 0, "models/weapons/v_blast/tris.md2", "w_blaster", "Blaster", 0, 0, NULL, IT_WEAPON | IT_STAY_COOP, WEAP_BLASTER, NULL, 0, "weapons/blastf1a.wav misc/lasfly.wav" }, /* QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_shotgun", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Shotgun, "misc/w_pkup.wav", "models/weapons/g_shotg/tris.md2", EF_ROTATE, "models/weapons/v_shotg/tris.md2", "w_shotgun", "Shotgun", 0, 1, "Shells", IT_WEAPON | IT_STAY_COOP, WEAP_SHOTGUN, NULL, 0, "weapons/shotgf1b.wav weapons/shotgr1b.wav" }, /* QUAKED weapon_supershotgun (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_supershotgun", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_SuperShotgun, "misc/w_pkup.wav", "models/weapons/g_shotg2/tris.md2", EF_ROTATE, "models/weapons/v_shotg2/tris.md2", "w_sshotgun", "Super Shotgun", 0, 2, "Shells", IT_WEAPON | IT_STAY_COOP, WEAP_SUPERSHOTGUN, NULL, 0, "weapons/sshotf1b.wav" }, /* QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_machinegun", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Machinegun, "misc/w_pkup.wav", "models/weapons/g_machn/tris.md2", EF_ROTATE, "models/weapons/v_machn/tris.md2", "w_machinegun", "Machinegun", 0, 1, "Bullets", IT_WEAPON | IT_STAY_COOP, WEAP_MACHINEGUN, NULL, 0, "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav" }, /* QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_chaingun", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Chaingun, "misc/w_pkup.wav", "models/weapons/g_chain/tris.md2", EF_ROTATE, "models/weapons/v_chain/tris.md2", "w_chaingun", "Chaingun", 0, 1, "Bullets", IT_WEAPON | IT_STAY_COOP, WEAP_CHAINGUN, NULL, 0, "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav` weapons/chngnd1a.wav" }, /* QUAKED weapon_etf_rifle (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_etf_rifle", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_ETF_Rifle, "misc/w_pkup.wav", "models/weapons/g_etf_rifle/tris.md2", EF_ROTATE, "models/weapons/v_etf_rifle/tris.md2", "w_etf_rifle", "ETF Rifle", 0, 1, "Flechettes", IT_WEAPON, WEAP_ETFRIFLE, NULL, 0, "weapons/nail1.wav models/proj/flechette/tris.md2", }, /* QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_grenades", Pickup_Ammo, Use_Weapon, Drop_Ammo, Weapon_Grenade, "misc/am_pkup.wav", "models/items/ammo/grenades/medium/tris.md2", 0, "models/weapons/v_handgr/tris.md2", "a_grenades", "Grenades", 3, 5, "grenades", IT_AMMO | IT_WEAPON, WEAP_GRENADES, NULL, AMMO_GRENADES, "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav " }, /* QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_grenadelauncher", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_GrenadeLauncher, "misc/w_pkup.wav", "models/weapons/g_launch/tris.md2", EF_ROTATE, "models/weapons/v_launch/tris.md2", "w_glauncher", "Grenade Launcher", 0, 1, "Grenades", IT_WEAPON | IT_STAY_COOP, WEAP_GRENADELAUNCHER, NULL, 0, "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav" }, /* QUAKED weapon_proxlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_proxlauncher", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_ProxLauncher, "misc/w_pkup.wav", "models/weapons/g_plaunch/tris.md2", EF_ROTATE, "models/weapons/v_plaunch/tris.md2", "w_proxlaunch", "Prox Launcher", 0, 1, "Prox", IT_WEAPON, WEAP_PROXLAUNCH, NULL, AMMO_PROX, "weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav weapons/proxwarn.wav weapons/proxopen.wav", }, /* QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_rocketlauncher", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_RocketLauncher, "misc/w_pkup.wav", "models/weapons/g_rocket/tris.md2", EF_ROTATE, "models/weapons/v_rocket/tris.md2", "w_rlauncher", "Rocket Launcher", 0, 1, "Rockets", IT_WEAPON | IT_STAY_COOP, WEAP_ROCKETLAUNCHER, NULL, 0, "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2" }, /* QUAKED weapon_hyperblaster (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_hyperblaster", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_HyperBlaster, "misc/w_pkup.wav", "models/weapons/g_hyperb/tris.md2", EF_ROTATE, "models/weapons/v_hyperb/tris.md2", "w_hyperblaster", "HyperBlaster", 0, 1, "Cells", IT_WEAPON | IT_STAY_COOP, WEAP_HYPERBLASTER, NULL, 0, "weapons/hyprbu1a.wav weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav" }, /* QUAKED weapon_plasmabeam (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_plasmabeam", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Heatbeam, "misc/w_pkup.wav", "models/weapons/g_beamer/tris.md2", EF_ROTATE, "models/weapons/v_beamer/tris.md2", "w_heatbeam", "Plasma Beam", 0, 2, "Cells", IT_WEAPON, WEAP_PLASMA, NULL, 0, "models/weapons/v_beamer2/tris.md2 weapons/bfg__l1a.wav", }, /* QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_railgun", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Railgun, "misc/w_pkup.wav", "models/weapons/g_rail/tris.md2", EF_ROTATE, "models/weapons/v_rail/tris.md2", "w_railgun", "Railgun", 0, 1, "Slugs", IT_WEAPON | IT_STAY_COOP, WEAP_RAILGUN, NULL, 0, "weapons/rg_hum.wav" }, /* QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_bfg", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_BFG, "misc/w_pkup.wav", "models/weapons/g_bfg/tris.md2", EF_ROTATE, "models/weapons/v_bfg/tris.md2", "w_bfg", "BFG10K", 0, 50, "Cells", IT_WEAPON | IT_STAY_COOP, WEAP_BFG, NULL, 0, "sprites/s_bfg1.sp2 sprites/s_bfg2.sp2 sprites/s_bfg3.sp2 weapons/bfg__f1y.wav weapons/bfg__l1a.wav weapons/bfg__x1b.wav weapons/bfg_hum.wav" }, /* QUAKED weapon_chainfist (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_chainfist", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_ChainFist, "misc/w_pkup.wav", "models/weapons/g_chainf/tris.md2", EF_ROTATE, "models/weapons/v_chainf/tris.md2", "w_chainfist", "Chainfist", 0, 0, NULL, IT_WEAPON | IT_MELEE, WEAP_CHAINFIST, NULL, 1, "weapons/sawidle.wav weapons/sawhit.wav", }, /* QUAKED weapon_disintegrator (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "weapon_disintegrator", Pickup_Weapon, Use_Weapon, Drop_Weapon, Weapon_Disintegrator, "misc/w_pkup.wav", "models/weapons/g_dist/tris.md2", EF_ROTATE, "models/weapons/v_dist/tris.md2", "w_disintegrator", "Disruptor", 0, 1, "Rounds", IT_WEAPON, WEAP_DISRUPTOR, NULL, 1, "models/items/spawngro/tris.md2 models/proj/disintegrator/tris.md2 weapons/disrupt.wav weapons/disint2.wav weapons/disrupthit.wav", }, /* QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_shells", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/items/ammo/shells/medium/tris.md2", 0, NULL, "a_shells", "Shells", 3, 10, NULL, IT_AMMO, 0, NULL, AMMO_SHELLS, "" }, /* QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_bullets", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/items/ammo/bullets/medium/tris.md2", 0, NULL, "a_bullets", "Bullets", 3, 50, NULL, IT_AMMO, 0, NULL, AMMO_BULLETS, "" }, /* QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_cells", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/items/ammo/cells/medium/tris.md2", 0, NULL, "a_cells", "Cells", 3, 50, NULL, IT_AMMO, 0, NULL, AMMO_CELLS, "" }, /* QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_rockets", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/items/ammo/rockets/medium/tris.md2", 0, NULL, "a_rockets", "Rockets", 3, 5, NULL, IT_AMMO, 0, NULL, AMMO_ROCKETS, "" }, /* QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_slugs", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/items/ammo/slugs/medium/tris.md2", 0, NULL, "a_slugs", "Slugs", 3, 10, NULL, IT_AMMO, 0, NULL, AMMO_SLUGS, "" }, /* QUAKED ammo_flechettes (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_flechettes", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/ammo/am_flechette/tris.md2", 0, NULL, "a_flechettes", "Flechettes", 3, 50, NULL, IT_AMMO, 0, NULL, AMMO_FLECHETTES }, /* QUAKED ammo_prox (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_prox", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/ammo/am_prox/tris.md2", 0, NULL, "a_prox", "Prox", 3, 5, NULL, IT_AMMO, 0, NULL, AMMO_PROX, "models/weapons/g_prox/tris.md2 weapons/proxwarn.wav" }, /* QUAKED ammo_tesla (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_tesla", Pickup_Ammo, Use_Weapon, Drop_Ammo, Weapon_Tesla, "misc/am_pkup.wav", "models/ammo/am_tesl/tris.md2", 0, "models/weapons/v_tesla/tris.md2", "a_tesla", "Tesla", 3, 5, "Tesla", IT_AMMO | IT_WEAPON, 0, NULL, AMMO_TESLA, "models/weapons/v_tesla2/tris.md2 weapons/teslaopen.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav models/weapons/g_tesla/tris.md2" }, /* QUAKED ammo_nuke (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_nuke", Pickup_Nuke, Use_Nuke, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/weapons/g_nuke/tris.md2", EF_ROTATE, NULL, "p_nuke", "A-M Bomb", 3, 300, "A-M Bomb", IT_POWERUP, 0, NULL, 0, "weapons/nukewarn2.wav world/rumble.wav" }, /* QUAKED ammo_disruptor (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "ammo_disruptor", Pickup_Ammo, NULL, Drop_Ammo, NULL, "misc/am_pkup.wav", "models/ammo/am_disr/tris.md2", 0, NULL, "a_disruptor", "Rounds", 3, 15, NULL, IT_AMMO, 0, NULL, AMMO_DISRUPTOR }, /* QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_quad", Pickup_Powerup, Use_Quad, Drop_General, NULL, "items/pkup.wav", "models/items/quaddama/tris.md2", EF_ROTATE, NULL, "p_quad", "Quad Damage", 2, 60, NULL, IT_POWERUP|IT_INSTANT_USE, 0, NULL, 0, "items/damage.wav items/damage2.wav items/damage3.wav" }, /* QUAKED item_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_invulnerability", Pickup_Powerup, Use_Invulnerability, Drop_General, NULL, "items/pkup.wav", "models/items/invulner/tris.md2", EF_ROTATE, NULL, "p_invulnerability", "Invulnerability", 2, 300, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "items/protect.wav items/protect2.wav items/protect4.wav" }, /* QUAKED item_silencer (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_silencer", Pickup_Powerup, Use_Silencer, Drop_General, NULL, "items/pkup.wav", "models/items/silencer/tris.md2", EF_ROTATE, NULL, "p_silencer", "Silencer", 2, 60, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "" }, /* QUAKED item_breather (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_breather", Pickup_Powerup, Use_Breather, Drop_General, NULL, "items/pkup.wav", "models/items/breather/tris.md2", EF_ROTATE, NULL, "p_rebreather", "Rebreather", 2, 60, NULL, IT_STAY_COOP | IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "items/airout.wav" }, /* QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_enviro", Pickup_Powerup, Use_Envirosuit, Drop_General, NULL, "items/pkup.wav", "models/items/enviro/tris.md2", EF_ROTATE, NULL, "p_envirosuit", "Environment Suit", 2, 60, NULL, IT_STAY_COOP | IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "items/airout.wav" }, /* QUAKED item_ancient_head (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN Special item that gives +2 to maximum health */ { "item_ancient_head", Pickup_AncientHead, NULL, NULL, NULL, "items/pkup.wav", "models/items/c_head/tris.md2", EF_ROTATE, NULL, "i_fixme", "Ancient Head", 2, 60, NULL, 0, 0, NULL, 0, "" }, /* QUAKED item_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN gives +1 to maximum health */ { "item_adrenaline", Pickup_Adrenaline, NULL, NULL, NULL, "items/pkup.wav", "models/items/adrenal/tris.md2", EF_ROTATE, NULL, "p_adrenaline", "Adrenaline", 2, 60, NULL, 0, 0, NULL, 0, "" }, /* QUAKED item_bandolier (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_bandolier", Pickup_Bandolier, NULL, NULL, NULL, "items/pkup.wav", "models/items/band/tris.md2", EF_ROTATE, NULL, "p_bandolier", "Bandolier", 2, 60, NULL, 0, 0, NULL, 0, "" }, /* QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_pack", Pickup_Pack, NULL, NULL, NULL, "items/pkup.wav", "models/items/pack/tris.md2", EF_ROTATE, NULL, "i_pack", "Ammo Pack", 2, 180, NULL, 0, 0, NULL, 0, "" }, /* QUAKED item_ir_goggles (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_ir_goggles", Pickup_Powerup, Use_IR, Drop_General, NULL, "items/pkup.wav", "models/items/goggles/tris.md2", EF_ROTATE, NULL, "p_ir", "IR Goggles", 2, 60, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "misc/ir_start.wav" }, /* QUAKED item_double (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_double", Pickup_Powerup, Use_Double, Drop_General, NULL, "items/pkup.wav", "models/items/ddamage/tris.md2", EF_ROTATE, NULL, "p_double", "Double Damage", 2, 60, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "misc/ddamage1.wav misc/ddamage2.wav misc/ddamage3.wav" }, /* QUAKED item_compass (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_compass", Pickup_Powerup, Use_Compass, NULL, NULL, "items/pkup.wav", "models/objects/fire/tris.md2", EF_ROTATE, NULL, "p_compass", "compass", 2, 60, NULL, IT_POWERUP, 0, NULL, 0, }, /* QUAKED item_sphere_vengeance (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_sphere_vengeance", Pickup_Sphere, Use_Vengeance, NULL, NULL, "items/pkup.wav", "models/items/vengnce/tris.md2", EF_ROTATE, NULL, "p_vengeance", "vengeance sphere", 2, 60, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "spheres/v_idle.wav" }, /* QUAKED item_sphere_hunter (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_sphere_hunter", Pickup_Sphere, Use_Hunter, NULL, NULL, "items/pkup.wav", "models/items/hunter/tris.md2", EF_ROTATE, NULL, "p_hunter", "hunter sphere", 2, 120, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "spheres/h_idle.wav spheres/h_active.wav spheres/h_lurk.wav" }, /* QUAKED item_sphere_defender (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_sphere_defender", Pickup_Sphere, Use_Defender, NULL, NULL, "items/pkup.wav", "models/items/defender/tris.md2", EF_ROTATE, NULL, "p_defender", "defender sphere", 2, 60, NULL, IT_POWERUP | IT_INSTANT_USE, 0, NULL, 0, "models/proj/laser2/tris.md2 models/items/shell/tris.md2 spheres/d_idle.wav" }, /* QUAKED item_doppleganger (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "item_doppleganger", Pickup_Doppleganger, Use_Doppleganger, Drop_General, NULL, "items/pkup.wav", "models/items/dopple/tris.md2", EF_ROTATE, NULL, "p_doppleganger", "Doppleganger", 0, 90, NULL, IT_POWERUP, 0, NULL, 0, "models/objects/dopplebase/tris.md2 models/items/spawngro2/tris.md2 models/items/hunter/tris.md2 models/items/vengnce/tris.md2", }, { NULL, Tag_PickupToken, NULL, NULL, NULL, "items/pkup.wav", "models/items/tagtoken/tris.md2", EF_ROTATE | EF_TAGTRAIL, NULL, "i_tagtoken", "Tag Token", 0, 0, NULL, IT_POWERUP | IT_NOT_GIVEABLE, 0, NULL, 1, NULL, }, /* QUAKED key_data_cd (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN key for computer centers */ { "key_data_cd", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/data_cd/tris.md2", EF_ROTATE, NULL, "k_datacd", "Data CD", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_power_cube (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN NO_TOUCH warehouse circuits */ { "key_power_cube", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/power/tris.md2", EF_ROTATE, NULL, "k_powercube", "Power Cube", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN key for the entrance of jail3 */ { "key_pyramid", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/pyramid/tris.md2", EF_ROTATE, NULL, "k_pyramid", "Pyramid Key", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_data_spinner (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN key for the city computer */ { "key_data_spinner", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/spinner/tris.md2", EF_ROTATE, NULL, "k_dataspin", "Data Spinner", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_pass (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN security pass for the security level */ { "key_pass", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/pass/tris.md2", EF_ROTATE, NULL, "k_security", "Security Pass", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_blue_key (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN normal door key - blue */ { "key_blue_key", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/key/tris.md2", EF_ROTATE, NULL, "k_bluekey", "Blue Key", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_red_key (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN normal door key - red */ { "key_red_key", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/red_key/tris.md2", EF_ROTATE, NULL, "k_redkey", "Red Key", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_commander_head (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN tank commander's head */ { "key_commander_head", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/monsters/commandr/head/tris.md2", EF_GIB, NULL, "k_comhead", "Commander's Head", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_airstrike_target (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN tank commander's head */ { "key_airstrike_target", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/target/tris.md2", EF_ROTATE, NULL, "i_airstrike", "Airstrike Marker", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, "" }, /* QUAKED key_nuke_container (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "key_nuke_container", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/weapons/g_nuke/tris.md2", EF_ROTATE, NULL, "i_contain", "Antimatter Pod", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, NULL, }, /* QUAKED key_nuke (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ { "key_nuke", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/weapons/g_nuke/tris.md2", EF_ROTATE, NULL, "i_nuke", "Antimatter Bomb", 2, 0, NULL, IT_STAY_COOP | IT_KEY, 0, NULL, 0, NULL, }, { NULL, Pickup_Health, NULL, NULL, NULL, "items/pkup.wav", NULL, 0, NULL, "i_health", "Health", 3, 0, NULL, 0, 0, NULL, 0, "items/s_health.wav items/n_health.wav items/l_health.wav items/m_health.wav" }, /* end of list marker */ {NULL} }; /* * QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ void SP_item_health(edict_t *self) { if (!self) { return; } if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); return; } self->model = "models/items/healing/medium/tris.md2"; self->count = 10; SpawnItem(self, FindItem("Health")); gi.soundindex("items/n_health.wav"); } /* * QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ void SP_item_health_small(edict_t *self) { if (!self) { return; } if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); return; } self->model = "models/items/healing/stimpack/tris.md2"; self->count = 2; SpawnItem(self, FindItem("Health")); self->style = HEALTH_IGNORE_MAX; gi.soundindex("items/s_health.wav"); } /* * QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ void SP_item_health_large(edict_t *self) { if (!self) { return; } if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); return; } self->model = "models/items/healing/large/tris.md2"; self->count = 25; SpawnItem(self, FindItem("Health")); gi.soundindex("items/l_health.wav"); } /* * QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN */ void SP_item_health_mega(edict_t *self) { if (!self) { return; } if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); return; } self->model = "models/items/mega_h/tris.md2"; self->count = 100; SpawnItem(self, FindItem("Health")); gi.soundindex("items/m_health.wav"); self->style = HEALTH_IGNORE_MAX | HEALTH_TIMED; } void InitItems(void) { game.num_items = sizeof(itemlist) / sizeof(itemlist[0]) - 1; } /* * Called by worldspawn */ void SetItemNames(void) { int i; gitem_t *it; for (i = 0; i < game.num_items; i++) { it = &itemlist[i]; gi.configstring(CS_ITEMS + i, it->pickup_name); } jacket_armor_index = ITEM_INDEX(FindItem("Jacket Armor")); combat_armor_index = ITEM_INDEX(FindItem("Combat Armor")); body_armor_index = ITEM_INDEX(FindItem("Body Armor")); power_screen_index = ITEM_INDEX(FindItem("Power Screen")); power_shield_index = ITEM_INDEX(FindItem("Power Shield")); } void SP_xatrix_item(edict_t *self) { gitem_t *item; int i; char *spawnClass = NULL; if (!self) { return; } if (!self->classname) { return; } if (!strcmp(self->classname, "ammo_magslug")) { spawnClass = "ammo_flechettes"; } else if (!strcmp(self->classname, "ammo_trap")) { spawnClass = "weapon_proxlauncher"; } else if (!strcmp(self->classname, "item_quadfire")) { float chance; chance = random(); if (chance < 0.2) { spawnClass = "item_sphere_hunter"; } else if (chance < 0.6) { spawnClass = "item_sphere_vengeance"; } else { spawnClass = "item_sphere_defender"; } } else if (!strcmp(self->classname, "weapon_boomer")) { spawnClass = "weapon_etf_rifle"; } else if (!strcmp(self->classname, "weapon_phalanx")) { spawnClass = "weapon_plasmabeam"; } /* check item spawn functions */ for (i = 0, item = itemlist; i < game.num_items; i++, item++) { if (!item->classname) { continue; } if (!strcmp(item->classname, spawnClass)) { /* found it */ SpawnItem(self, item); return; } } } rogue-ROGUE_2_13/src/g_main.c000066400000000000000000000211251477320066100157760ustar00rootroot00000000000000/* * ======================================================================= * * Jump in into the game.so and support functions. * * ======================================================================= */ #include "header/local.h" game_locals_t game; level_locals_t level; game_import_t gi; game_export_t globals; spawn_temp_t st; int sm_meat_index; int snd_fry; int meansOfDeath; edict_t *g_edicts; cvar_t *deathmatch; cvar_t *coop; cvar_t *coop_baseq2; /* treat spawnflags according to baseq2 rules */ cvar_t *coop_elevator_delay; cvar_t *coop_pickup_weapons; cvar_t *dmflags; cvar_t *skill; cvar_t *fraglimit; cvar_t *timelimit; cvar_t *password; cvar_t *spectator_password; cvar_t *needpass; cvar_t *maxclients; cvar_t *maxspectators; cvar_t *maxentities; cvar_t *g_select_empty; cvar_t *dedicated; cvar_t *g_footsteps; cvar_t *g_monsterfootsteps; cvar_t *g_fix_triggered; cvar_t *filterban; cvar_t *sv_maxvelocity; cvar_t *sv_gravity; cvar_t *sv_rollspeed; cvar_t *sv_rollangle; cvar_t *gun_x; cvar_t *gun_y; cvar_t *gun_z; cvar_t *run_pitch; cvar_t *run_roll; cvar_t *bob_up; cvar_t *bob_pitch; cvar_t *bob_roll; cvar_t *sv_cheats; cvar_t *flood_msgs; cvar_t *flood_persecond; cvar_t *flood_waitdelay; cvar_t *sv_maplist; cvar_t *sv_stopspeed; cvar_t *g_showlogic; cvar_t *gamerules; cvar_t *huntercam; cvar_t *strong_mines; cvar_t *randomrespawn; cvar_t *g_disruptor; cvar_t *aimfix; cvar_t *g_machinegun_norecoil; cvar_t *g_quick_weap; cvar_t *g_swap_speed; void SpawnEntities(char *mapname, char *entities, char *spawnpoint); void ClientThink(edict_t *ent, usercmd_t *cmd); qboolean ClientConnect(edict_t *ent, char *userinfo); void ClientUserinfoChanged(edict_t *ent, char *userinfo); void ClientDisconnect(edict_t *ent); void ClientBegin(edict_t *ent); void ClientCommand(edict_t *ent); void RunEntity(edict_t *ent); void WriteGame(char *filename, qboolean autosave); void ReadGame(char *filename); void WriteLevel(char *filename); void ReadLevel(char *filename); void InitGame(void); void G_RunFrame(void); /* =================================================================== */ void ShutdownGame(void) { gi.dprintf("==== ShutdownGame ====\n"); gi.FreeTags(TAG_LEVEL); gi.FreeTags(TAG_GAME); } /* * Returns a pointer to the structure with * all entry points and global variables */ game_export_t * GetGameAPI(game_import_t *import) { gi = *import; globals.apiversion = GAME_API_VERSION; globals.Init = InitGame; globals.Shutdown = ShutdownGame; globals.SpawnEntities = SpawnEntities; globals.WriteGame = WriteGame; globals.ReadGame = ReadGame; globals.WriteLevel = WriteLevel; globals.ReadLevel = ReadLevel; globals.ClientThink = ClientThink; globals.ClientConnect = ClientConnect; globals.ClientUserinfoChanged = ClientUserinfoChanged; globals.ClientDisconnect = ClientDisconnect; globals.ClientBegin = ClientBegin; globals.ClientCommand = ClientCommand; globals.RunFrame = G_RunFrame; globals.ServerCommand = ServerCommand; globals.edict_size = sizeof(edict_t); /* Seed the PRNG */ randk_seed(); return &globals; } /* * this is only here so the functions in * q_shared.c and q_shwin.c can link */ void Sys_Error(char *error, ...) { va_list argptr; char text[1024]; va_start(argptr, error); vsprintf(text, error, argptr); va_end(argptr); gi.error("%s", text); } void Com_Printf(char *msg, ...) { va_list argptr; char text[1024]; va_start(argptr, msg); vsprintf(text, msg, argptr); va_end(argptr); gi.dprintf("%s", text); } /* ====================================================================== */ void ClientEndServerFrames(void) { int i; edict_t *ent; /* calc the player views now that all pushing and damage has been added */ for (i = 0; i < maxclients->value; i++) { ent = g_edicts + 1 + i; if (!ent->inuse || !ent->client) { continue; } ClientEndServerFrame(ent); } } /* * Returns the created target changelevel */ edict_t * CreateTargetChangeLevel(char *map) { edict_t *ent; if (!map) { return NULL; } ent = G_Spawn(); ent->classname = "target_changelevel"; Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map); ent->map = level.nextmap; return ent; } /* * The timelimit or fraglimit has been exceeded */ void EndDMLevel(void) { edict_t *ent; char *s, *t, *f; static const char *seps = " ,\n\r"; /* stay on same level flag */ if ((int)dmflags->value & DF_SAME_LEVEL) { BeginIntermission(CreateTargetChangeLevel(level.mapname)); return; } /* see if it's in the map list */ if (*sv_maplist->string) { s = strdup(sv_maplist->string); f = NULL; t = strtok(s, seps); while (t != NULL) { if (Q_stricmp(t, level.mapname) == 0) { /* it's in the list, go to the next one */ t = strtok(NULL, seps); if (t == NULL) /* end of list, go to first one */ { if (f == NULL) /* there isn't a first one, same level */ { BeginIntermission(CreateTargetChangeLevel(level.mapname)); } else { BeginIntermission(CreateTargetChangeLevel(f)); } } else { BeginIntermission(CreateTargetChangeLevel(t)); } free(s); return; } if (!f) { f = t; } t = strtok(NULL, seps); } free(s); } if (level.nextmap[0]) /* go to a specific map */ { BeginIntermission(CreateTargetChangeLevel(level.nextmap)); } else /* search for a changelevel */ { ent = G_Find(NULL, FOFS(classname), "target_changelevel"); if (!ent) { /* the map designer didn't include a changelevel, so create a fake ent that goes back to the same level */ BeginIntermission(CreateTargetChangeLevel(level.mapname)); return; } BeginIntermission(ent); } } void CheckNeedPass(void) { int need; /* if password or spectator_password has changed, update needpass as needed */ if (password->modified || spectator_password->modified) { password->modified = spectator_password->modified = false; need = 0; if (*password->string && Q_stricmp(password->string, "none")) { need |= 1; } if (*spectator_password->string && Q_stricmp(spectator_password->string, "none")) { need |= 2; } gi.cvar_set("needpass", va("%d", need)); } } void CheckDMRules(void) { int i; gclient_t *cl; if (level.intermissiontime) { return; } if (!deathmatch->value) { return; } if (gamerules && gamerules->value && DMGame.CheckDMRules) { if (DMGame.CheckDMRules()) { return; } } if (timelimit->value) { if (level.time >= timelimit->value * 60) { gi.bprintf(PRINT_HIGH, "Timelimit hit.\n"); EndDMLevel(); return; } } if (fraglimit->value) { for (i = 0; i < maxclients->value; i++) { cl = game.clients + i; if (!g_edicts[i + 1].inuse) { continue; } if (cl->resp.score >= fraglimit->value) { gi.bprintf(PRINT_HIGH, "Fraglimit hit.\n"); EndDMLevel(); return; } } } } void ExitLevel(void) { int i; edict_t *ent; char command[256]; Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.changemap); gi.AddCommandString(command); level.changemap = NULL; level.exitintermission = 0; level.intermissiontime = 0; ClientEndServerFrames(); /* clear some things before going to next level */ for (i = 0; i < maxclients->value; i++) { ent = g_edicts + 1 + i; if (!ent->inuse) { continue; } if (ent->health > ent->max_health) { ent->health = ent->max_health; } } debristhisframe = 0; gibsthisframe = 0; } /* * Advances the world by 0.1 seconds */ void G_RunFrame(void) { int i; edict_t *ent; level.framenum++; level.time = level.framenum * FRAMETIME; debristhisframe = 0; gibsthisframe = 0; /* choose a client for monsters to target this frame */ AI_SetSightClient(); /* exit intermissions */ if (level.exitintermission) { ExitLevel(); return; } /* treat each object in turn even the world gets a chance to think */ ent = &g_edicts[0]; for (i = 0; i < globals.num_edicts; i++, ent++) { if (!ent->inuse) { continue; } level.current_entity = ent; VectorCopy(ent->s.origin, ent->s.old_origin); /* if the ground entity moved, make sure we are still on it */ if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount)) { ent->groundentity = NULL; if (!(ent->flags & (FL_SWIM | FL_FLY)) && (ent->svflags & SVF_MONSTER)) { M_CheckGround(ent); } } if ((i > 0) && (i <= maxclients->value)) { ClientBeginServerFrame(ent); continue; } G_RunEntity(ent); } /* see if it is time to end a deathmatch */ CheckDMRules(); /* see if needpass needs updated */ CheckNeedPass(); /* build the playerstate_t structures for all players */ ClientEndServerFrames(); } rogue-ROGUE_2_13/src/g_misc.c000066400000000000000000001432171477320066100160140ustar00rootroot00000000000000/* * ======================================================================= * * Miscellaneos entities, functs and functions. * * ======================================================================= */ #include "header/local.h" int debristhisframe; int gibsthisframe; extern void M_WorldEffects(edict_t *ent); /* ===================================================== */ void Use_Areaportal(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } ent->count ^= 1; /* toggle state */ gi.SetAreaPortalState(ent->style, ent->count); } /* * QUAKED func_areaportal (0 0 0) ? * * This is a non-visible object that divides the world into * areas that are seperated when this portal is not activated. * Usually enclosed in the middle of a door. */ void SP_func_areaportal(edict_t *ent) { if (!ent) { return; } ent->use = Use_Areaportal; ent->count = 0; /* always start closed; */ } /* ===================================================== */ void VelocityForDamage(int damage, vec3_t v) { v[0] = 100.0 * crandom(); v[1] = 100.0 * crandom(); v[2] = 200.0 + 100.0 * random(); if (damage < 50) { VectorScale(v, 0.7, v); } else { VectorScale(v, 1.2, v); } } void ClipGibVelocity(edict_t *ent) { if (!ent) { return; } if (ent->velocity[0] < -300) { ent->velocity[0] = -300; } else if (ent->velocity[0] > 300) { ent->velocity[0] = 300; } if (ent->velocity[1] < -300) { ent->velocity[1] = -300; } else if (ent->velocity[1] > 300) { ent->velocity[1] = 300; } if (ent->velocity[2] < 200) { ent->velocity[2] = 200; /* always some upwards */ } else if (ent->velocity[2] > 500) { ent->velocity[2] = 500; } } void gib_think(edict_t *self) { if (!self) { return; } self->s.frame++; self->nextthink = level.time + FRAMETIME; if (self->s.frame == 10) { self->think = G_FreeEdict; self->nextthink = level.time + 8 + random() * 10; } } void gib_touch(edict_t *self, edict_t *other /* unused */, cplane_t *plane, csurface_t *surf /* unused */) { vec3_t normal_angles, right; if (!self) { return; } if (!self->groundentity) { return; } self->touch = NULL; if (plane) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/fhit3.wav"), 1, ATTN_NORM, 0); vectoangles(plane->normal, normal_angles); AngleVectors(normal_angles, NULL, right, NULL); vectoangles(right, self->s.angles); if (self->s.modelindex == sm_meat_index) { self->s.frame++; self->think = gib_think; self->nextthink = level.time + FRAMETIME; } } } void gib_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } G_FreeEdict(self); } void ThrowGib(edict_t *self, char *gibname, int damage, int type) { edict_t *gib; vec3_t vd; vec3_t origin; vec3_t size; float vscale; if (!self || !gibname) { return; } if (gibsthisframe > MAX_GIBS) { return; } gib = G_SpawnOptional(); if (!gib) { return; } gibsthisframe++; VectorScale(self->size, 0.5, size); VectorAdd(self->absmin, size, origin); gib->s.origin[0] = origin[0] + crandom() * size[0]; gib->s.origin[1] = origin[1] + crandom() * size[1]; gib->s.origin[2] = origin[2] + crandom() * size[2]; gi.setmodel(gib, gibname); gib->solid = SOLID_BBOX; gib->svflags = SVF_DEADMONSTER; gib->s.effects |= EF_GIB; gib->flags |= FL_NO_KNOCKBACK; gib->takedamage = DAMAGE_YES; gib->die = gib_die; gib->health = 250; if (type == GIB_ORGANIC) { gib->movetype = MOVETYPE_TOSS; gib->touch = gib_touch; vscale = 0.5; } else { gib->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage(damage, vd); VectorMA(self->velocity, vscale, vd, gib->velocity); ClipGibVelocity(gib); gib->avelocity[0] = random() * 600; gib->avelocity[1] = random() * 600; gib->avelocity[2] = random() * 600; gib->think = G_FreeEdict; gib->nextthink = level.time + 10 + random() * 10; gib->s.renderfx |= RF_IR_VISIBLE; gi.linkentity(gib); } void ThrowHead(edict_t *self, char *gibname, int damage, int type) { vec3_t vd; float vscale; if (!self || !gibname) { return; } self->s.skinnum = 0; self->s.frame = 0; VectorClear(self->mins); VectorClear(self->maxs); self->s.modelindex2 = 0; gi.setmodel(self, gibname); self->solid = SOLID_BBOX; self->s.effects |= EF_GIB; self->s.effects &= ~EF_FLIES; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; self->svflags &= ~SVF_MONSTER; self->takedamage = DAMAGE_YES; self->targetname = NULL; self->die = gib_die; // The entity still has the monsters clipmaks. // Reset it to MASK_SHOT to be on the save side. self->clipmask = MASK_SHOT; if (type == GIB_ORGANIC) { self->movetype = MOVETYPE_TOSS; self->touch = gib_touch; vscale = 0.5; } else { self->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } VelocityForDamage(damage, vd); VectorMA(self->velocity, vscale, vd, self->velocity); ClipGibVelocity(self); self->avelocity[YAW] = crandom() * 600; self->think = G_FreeEdict; self->nextthink = level.time + 10 + random() * 10; gi.linkentity(self); } void ThrowClientHead(edict_t *self, int damage) { vec3_t vd; char *gibname; if (!self) { return; } if (rand() & 1) { gibname = "models/objects/gibs/head2/tris.md2"; self->s.skinnum = 1; /* second skin is player */ } else { gibname = "models/objects/gibs/skull/tris.md2"; self->s.skinnum = 0; } self->s.origin[2] += 32; self->s.frame = 0; gi.setmodel(self, gibname); VectorSet(self->mins, -16, -16, 0); VectorSet(self->maxs, 16, 16, 16); self->takedamage = DAMAGE_NO; self->solid = SOLID_BBOX; self->s.effects = EF_GIB; self->s.sound = 0; self->flags |= FL_NO_KNOCKBACK; // The entity still has the monsters clipmaks. // Reset it to MASK_SHOT to be on the save side. self->clipmask = MASK_SHOT; self->movetype = MOVETYPE_BOUNCE; VelocityForDamage(damage, vd); VectorAdd(self->velocity, vd, self->velocity); if (self->client) /* bodies in the queue don't have a client anymore */ { self->client->anim_priority = ANIM_DEATH; self->client->anim_end = self->s.frame; } else { self->think = NULL; self->nextthink = 0; } gi.linkentity(self); } void debris_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } G_FreeEdict(self); } void ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin) { edict_t *chunk; vec3_t v; if (!self || !modelname) { return; } if (debristhisframe > MAX_DEBRIS) { return; } chunk = G_SpawnOptional(); if (!chunk) { return; } debristhisframe++; VectorCopy(origin, chunk->s.origin); gi.setmodel(chunk, modelname); v[0] = 100 * crandom(); v[1] = 100 * crandom(); v[2] = 100 + 100 * crandom(); VectorMA(self->velocity, speed, v, chunk->velocity); chunk->movetype = MOVETYPE_BOUNCE; chunk->solid = SOLID_NOT; chunk->avelocity[0] = random() * 600; chunk->avelocity[1] = random() * 600; chunk->avelocity[2] = random() * 600; chunk->think = G_FreeEdict; chunk->nextthink = level.time + 5 + random() * 5; chunk->s.frame = 0; chunk->flags = 0; chunk->classname = "debris"; chunk->takedamage = DAMAGE_YES; chunk->die = debris_die; chunk->health = 250; gi.linkentity(chunk); } void BecomeExplosion1(edict_t *self) { if (!self) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); G_FreeEdict(self); } void BecomeExplosion2(edict_t *self) { if (!self) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION2); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); G_FreeEdict(self); } /* * QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORT * * Target: next path corner * Pathtarget: gets used when an entity that has * this path_corner targeted touches it */ void path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { vec3_t v; edict_t *next; if (!self || !other) { return; } if (other->movetarget != self) { return; } if (other->enemy) { return; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets(self, other); self->target = savetarget; } if (self->target) { next = G_PickTarget(self->target); } else { next = NULL; } if ((next) && (next->spawnflags & 1)) { VectorCopy(next->s.origin, v); v[2] += next->mins[2]; v[2] -= other->mins[2]; VectorCopy(v, other->s.origin); next = G_PickTarget(next->target); other->s.event = EV_OTHER_TELEPORT; } other->goalentity = other->movetarget = next; if (self->wait) { other->monsterinfo.pausetime = level.time + self->wait; other->monsterinfo.stand(other); return; } if (!other->movetarget) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand(other); } else { VectorSubtract(other->goalentity->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw(v); } } void SP_path_corner(edict_t *self) { if (!self) { return; } if (!self->targetname) { gi.dprintf("path_corner with no targetname at %s\n", vtos( self->s.origin)); G_FreeEdict(self); return; } self->solid = SOLID_TRIGGER; self->touch = path_corner_touch; VectorSet(self->mins, -8, -8, -8); VectorSet(self->maxs, 8, 8, 8); self->svflags |= SVF_NOCLIENT; gi.linkentity(self); } /* * QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold * * Makes this the target of a monster and it will head here * when first activated before going after the activator. If * hold is selected, it will stay here. */ void point_combat_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { edict_t *activator; if (!self || !other) { return; } if (other->movetarget != self) { return; } if (self->target) { other->target = self->target; other->goalentity = other->movetarget = G_PickTarget(other->target); if (!other->goalentity) { gi.dprintf("%s at %s target %s does not exist\n", self->classname, vtos(self->s.origin), self->target); other->movetarget = self; } self->target = NULL; } else if ((self->spawnflags & 1) && !(other->flags & (FL_SWIM | FL_FLY))) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.aiflags |= AI_STAND_GROUND; other->monsterinfo.stand(other); } if (other->movetarget == self) { other->target = NULL; other->movetarget = NULL; other->goalentity = other->enemy; other->monsterinfo.aiflags &= ~AI_COMBAT_POINT; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; if (other->enemy && other->enemy->client) { activator = other->enemy; } else if (other->oldenemy && other->oldenemy->client) { activator = other->oldenemy; } else if (other->activator && other->activator->client) { activator = other->activator; } else { activator = other; } G_UseTargets(self, activator); self->target = savetarget; } } void SP_point_combat(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->solid = SOLID_TRIGGER; self->touch = point_combat_touch; VectorSet(self->mins, -8, -8, -16); VectorSet(self->maxs, 8, 8, 16); self->svflags = SVF_NOCLIENT; gi.linkentity(self); } /* * QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8) * * Just for the debugging level. Don't use */ void TH_viewthing(edict_t *ent) { if (!ent) { return; } ent->s.frame = (ent->s.frame + 1) % 7; ent->nextthink = level.time + FRAMETIME; } void SP_viewthing(edict_t *ent) { if (!ent) { return; } gi.dprintf("viewthing spawned\n"); ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.renderfx = RF_FRAMELERP; VectorSet(ent->mins, -16, -16, -24); VectorSet(ent->maxs, 16, 16, 32); ent->s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); gi.linkentity(ent); ent->nextthink = level.time + 0.5; ent->think = TH_viewthing; return; } /* * QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) * * Used as a positional target for spotlights, etc. */ void SP_info_null(edict_t *self) { if (!self) { return; } G_FreeEdict(self); } /* * QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) * * Used as a positional target for lighting. */ void SP_info_notnull(edict_t *self) { if (!self) { return; } VectorCopy(self->s.origin, self->absmin); VectorCopy(self->s.origin, self->absmax); } #define START_OFF 1 /* * QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF * * Non-displayed light. * Default light value is 300. * Default style is 0. * If targeted, will toggle between on and off. * Default _cone value is 10 (used to set size of light for spotlights) */ void light_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->spawnflags & START_OFF) { gi.configstring(CS_LIGHTS + self->style, "m"); self->spawnflags &= ~START_OFF; } else { gi.configstring(CS_LIGHTS + self->style, "a"); self->spawnflags |= START_OFF; } } void SP_light(edict_t *self) { if (!self) { return; } /* no targeted lights in deathmatch, because they cause global messages */ if (!self->targetname || deathmatch->value) { G_FreeEdict(self); return; } if (self->style >= 32) { self->use = light_use; if (self->spawnflags & START_OFF) { gi.configstring(CS_LIGHTS + self->style, "a"); } else { gi.configstring(CS_LIGHTS + self->style, "m"); } } } /* * QUAKED func_wall (0 .5 .8) ? TRIGGER_SPAWN TOGGLE START_ON ANIMATED ANIMATED_FAST * * This is just a solid wall if not inhibited * TRIGGER_SPAWN the wall will not be present until triggered * it will then blink in to existance; it will * kill anything that was in it's way * * TOGGLE only valid for TRIGGER_SPAWN walls * this allows the wall to be turned on and off * * START_ON only valid for TRIGGER_SPAWN walls * the wall will initially be present */ void func_wall_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->solid == SOLID_NOT) { self->solid = SOLID_BSP; self->svflags &= ~SVF_NOCLIENT; KillBox(self); } else { self->solid = SOLID_NOT; self->svflags |= SVF_NOCLIENT; } gi.linkentity(self); if (!(self->spawnflags & 2)) { self->use = NULL; } } void SP_func_wall(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); if (self->spawnflags & 8) { self->s.effects |= EF_ANIM_ALL; } if (self->spawnflags & 16) { self->s.effects |= EF_ANIM_ALLFAST; } /* just a wall */ if ((self->spawnflags & 7) == 0) { self->solid = SOLID_BSP; gi.linkentity(self); return; } /* it must be TRIGGER_SPAWN */ if (!(self->spawnflags & 1)) { self->spawnflags |= 1; } /* yell if the spawnflags are odd */ if (self->spawnflags & 4) { if (!(self->spawnflags & 2)) { gi.dprintf("func_wall START_ON without TOGGLE\n"); self->spawnflags |= 2; } } self->use = func_wall_use; if (self->spawnflags & 4) { self->solid = SOLID_BSP; } else { self->solid = SOLID_NOT; self->svflags |= SVF_NOCLIENT; } gi.linkentity(self); } /* * QUAKED func_object (0 .5 .8) ? TRIGGER_SPAWN ANIMATED ANIMATED_FAST * * This is solid bmodel that will fall if it's support it removed. */ void func_object_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf /* unused */) { if (!self || !other) { return; } /* only squash thing we fall on top of */ if (plane && plane->normal[2] < 1.0) { return; } if (other->takedamage == DAMAGE_NO) { return; } T_Damage(other, self, self, vec3_origin, self->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); } void func_object_release(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_TOSS; self->touch = func_object_touch; } void func_object_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->solid = SOLID_BSP; self->svflags &= ~SVF_NOCLIENT; self->use = NULL; KillBox(self); func_object_release(self); } void SP_func_object(edict_t *self) { if (!self) { return; } gi.setmodel(self, self->model); self->mins[0] += 1; self->mins[1] += 1; self->mins[2] += 1; self->maxs[0] -= 1; self->maxs[1] -= 1; self->maxs[2] -= 1; if (!self->dmg) { self->dmg = 100; } if (self->spawnflags == 0) { self->solid = SOLID_BSP; self->movetype = MOVETYPE_PUSH; self->think = func_object_release; self->nextthink = level.time + 2 * FRAMETIME; } else { self->solid = SOLID_NOT; self->movetype = MOVETYPE_PUSH; self->use = func_object_use; self->svflags |= SVF_NOCLIENT; } if (self->spawnflags & 2) { self->s.effects |= EF_ANIM_ALL; } if (self->spawnflags & 4) { self->s.effects |= EF_ANIM_ALLFAST; } self->clipmask = MASK_MONSTERSOLID; gi.linkentity(self); } /* * QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST INACTIVE * * Any brush that you want to explode or break apart. If you want an * ex0plosion, set dmg and it will do a radius explosion of that amount * at the center of the bursh. * * If targeted it will not be shootable. * * INACTIVE - specifies that the entity is not explodable until triggered. If you use this you must * target the entity you want to trigger it. This is the only entity approved to activate it. * * health defaults to 100. * * mass defaults to 75. This determines how much debris is emitted when * it explodes. You get one large chunk per 100 of mass (up to 8) and * one small chunk per 25 of mass (up to 16). So 800 gives the most. */ void func_explosive_explode(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage /* unused */, vec3_t point /* unused */) { vec3_t origin; vec3_t chunkorigin; vec3_t size; int count; int mass; edict_t *master; if (!self || !inflictor || !attacker) { return; } /* bmodel origins are (0 0 0), we need to adjust that here */ VectorScale(self->size, 0.5, size); VectorAdd(self->absmin, size, origin); VectorCopy(origin, self->s.origin); self->takedamage = DAMAGE_NO; if (self->dmg) { T_RadiusDamage(self, attacker, self->dmg, NULL, self->dmg + 40, MOD_EXPLOSIVE); } VectorSubtract(self->s.origin, inflictor->s.origin, self->velocity); VectorNormalize(self->velocity); VectorScale(self->velocity, 150, self->velocity); /* start chunks towards the center */ VectorScale(size, 0.5, size); mass = self->mass; if (!mass) { mass = 75; } /* big chunks */ if (mass >= 100) { count = mass / 100; if (count > 8) { count = 8; } while (count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris(self, "models/objects/debris1/tris.md2", 1, chunkorigin); } } /* small chunks */ count = mass / 25; if (count > 16) { count = 16; } while (count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", 2, chunkorigin); } if (self->flags & FL_TEAMSLAVE) { master = self->teammaster; /* because mappers (other than jim (usually)) are stupid.... */ while (master) { if (master->teamchain == self) { master->teamchain = self->teamchain; break; } master = master->teamchain; } } G_UseTargets(self, attacker); if (self->dmg) { BecomeExplosion1(self); } else { G_FreeEdict(self); } } void func_explosive_use(edict_t *self, edict_t *other, edict_t *activator /* unused */) { if (!self || !other) { return; } func_explosive_explode(self, self, other, self->health, vec3_origin); } void func_explosive_activate(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->use = func_explosive_use; if (!self->health) { self->health = 100; } self->die = func_explosive_explode; self->takedamage = DAMAGE_YES; } void func_explosive_spawn(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->solid = SOLID_BSP; self->svflags &= ~SVF_NOCLIENT; self->use = NULL; KillBox(self); gi.linkentity(self); } void SP_func_explosive(edict_t *self) { if (!self) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(self); return; } self->movetype = MOVETYPE_PUSH; gi.modelindex("models/objects/debris1/tris.md2"); gi.modelindex("models/objects/debris2/tris.md2"); gi.setmodel(self, self->model); if (self->spawnflags & 1) { self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; self->use = func_explosive_spawn; } else if (self->spawnflags & 8) { self->solid = SOLID_BSP; if (self->targetname) { self->use = func_explosive_activate; } } else { self->solid = SOLID_BSP; if (self->targetname) { self->use = func_explosive_use; } } if (self->spawnflags & 2) { self->s.effects |= EF_ANIM_ALL; } if (self->spawnflags & 4) { self->s.effects |= EF_ANIM_ALLFAST; } if ((self->use != func_explosive_use) && (self->use != func_explosive_activate)) { if (!self->health) { self->health = 100; } self->die = func_explosive_explode; self->takedamage = DAMAGE_YES; } gi.linkentity(self); } /* * QUAKED misc_explobox (0 .5 .8) (-16 -16 0) (16 16 40) * * Large exploding box. You can override its mass (100), * health (80), and dmg (150). */ void barrel_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { float ratio; vec3_t v; if (!self || !other) { return; } if ((!other->groundentity) || (other->groundentity == self)) { return; } ratio = (float)other->mass / (float)self->mass; VectorSubtract(self->s.origin, other->s.origin, v); M_walkmove(self, vectoyaw(v), 20 * ratio * FRAMETIME); } void barrel_explode(edict_t *self) { vec3_t org; float spd; vec3_t save; if (!self) { return; } T_RadiusDamage(self, self->activator, self->dmg, NULL, self->dmg + 40, MOD_BARREL); VectorCopy(self->s.origin, save); VectorMA(self->absmin, 0.5, self->size, self->s.origin); /* a few big chunks */ spd = 1.5 * (float)self->dmg / 200.0; org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris1/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris1/tris.md2", spd, org); /* bottom corners */ spd = 1.75 * (float)self->dmg / 200.0; VectorCopy(self->absmin, org); ThrowDebris(self, "models/objects/debris3/tris.md2", spd, org); VectorCopy(self->absmin, org); org[0] += self->size[0]; ThrowDebris(self, "models/objects/debris3/tris.md2", spd, org); VectorCopy(self->absmin, org); org[1] += self->size[1]; ThrowDebris(self, "models/objects/debris3/tris.md2", spd, org); VectorCopy(self->absmin, org); org[0] += self->size[0]; org[1] += self->size[1]; ThrowDebris(self, "models/objects/debris3/tris.md2", spd, org); /* a bunch of little chunks */ spd = 2.0 * (float)self->dmg / 200.0; org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", spd, org); VectorCopy(save, self->s.origin); if (self->groundentity) { BecomeExplosion2(self); } else { BecomeExplosion1(self); } } void barrel_delay(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage /* unused */, vec3_t point /* unused */) { if (!self || !attacker) { return; } self->takedamage = DAMAGE_NO; self->nextthink = level.time + 2 * FRAMETIME; self->think = barrel_explode; self->activator = attacker; } void barrel_think(edict_t *self) { if (!self) { return; } /* the think needs to be first since later stuff may override. */ self->think = barrel_think; self->nextthink = level.time + FRAMETIME; M_CatagorizePosition(self); self->flags |= FL_IMMUNE_SLIME; self->air_finished = level.time + 100; M_WorldEffects(self); } void barrel_start(edict_t *self) { if (!self) { return; } M_droptofloor(self); self->think = barrel_think; self->nextthink = level.time + FRAMETIME; } void SP_misc_explobox(edict_t *self) { if (!self) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(self); return; } gi.modelindex("models/objects/debris1/tris.md2"); gi.modelindex("models/objects/debris2/tris.md2"); gi.modelindex("models/objects/debris3/tris.md2"); self->solid = SOLID_BBOX; self->movetype = MOVETYPE_STEP; self->model = "models/objects/barrels/tris.md2"; self->s.modelindex = gi.modelindex(self->model); VectorSet(self->mins, -16, -16, 0); VectorSet(self->maxs, 16, 16, 40); if (!self->mass) { self->mass = 400; } if (!self->health) { self->health = 10; } if (!self->dmg) { self->dmg = 150; } self->die = barrel_delay; self->takedamage = DAMAGE_YES; self->monsterinfo.aiflags = AI_NOSTEP; self->touch = barrel_touch; self->think = barrel_start; self->nextthink = level.time + 2 * FRAMETIME; gi.linkentity(self); } /* * QUAKED misc_blackhole (1 .5 0) (-8 -8 -8) (8 8 8) */ void misc_blackhole_use(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } G_FreeEdict(ent); } void misc_blackhole_think(edict_t *self) { if (!self) { return; } if (++self->s.frame < 19) { self->nextthink = level.time + FRAMETIME; } else { self->s.frame = 0; self->nextthink = level.time + FRAMETIME; } } void SP_misc_blackhole(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_NOT; VectorSet(ent->mins, -64, -64, 0); VectorSet(ent->maxs, 64, 64, 8); ent->s.modelindex = gi.modelindex("models/objects/black/tris.md2"); ent->s.renderfx = RF_TRANSLUCENT; ent->use = misc_blackhole_use; ent->think = misc_blackhole_think; ent->nextthink = level.time + 2 * FRAMETIME; gi.linkentity(ent); } /* * QUAKED misc_eastertank (1 .5 0) (-32 -32 -16) (32 32 32) */ void misc_eastertank_think(edict_t *self) { if (!self) { return; } if (++self->s.frame < 293) { self->nextthink = level.time + FRAMETIME; } else { self->s.frame = 254; self->nextthink = level.time + FRAMETIME; } } void SP_misc_eastertank(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, -16); VectorSet(ent->maxs, 32, 32, 32); ent->s.modelindex = gi.modelindex("models/monsters/tank/tris.md2"); ent->s.frame = 254; ent->think = misc_eastertank_think; ent->nextthink = level.time + 2 * FRAMETIME; gi.linkentity(ent); } /* * QUAKED misc_easterchick (1 .5 0) (-32 -32 0) (32 32 32) */ void misc_easterchick_think(edict_t *self) { if (!self) { return; } if (++self->s.frame < 247) { self->nextthink = level.time + FRAMETIME; } else { self->s.frame = 208; self->nextthink = level.time + FRAMETIME; } } void SP_misc_easterchick(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, 0); VectorSet(ent->maxs, 32, 32, 32); ent->s.modelindex = gi.modelindex("models/monsters/bitch/tris.md2"); ent->s.frame = 208; ent->think = misc_easterchick_think; ent->nextthink = level.time + 2 * FRAMETIME; gi.linkentity(ent); } /* * QUAKED misc_easterchick2 (1 .5 0) (-32 -32 0) (32 32 32) */ void misc_easterchick2_think(edict_t *self) { if (!self) { return; } if (++self->s.frame < 287) { self->nextthink = level.time + FRAMETIME; } else { self->s.frame = 248; self->nextthink = level.time + FRAMETIME; } } void SP_misc_easterchick2(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, 0); VectorSet(ent->maxs, 32, 32, 32); ent->s.modelindex = gi.modelindex("models/monsters/bitch/tris.md2"); ent->s.frame = 248; ent->think = misc_easterchick2_think; ent->nextthink = level.time + 2 * FRAMETIME; gi.linkentity(ent); } /* * QUAKED monster_commander_body (1 .5 0) (-32 -32 0) (32 32 48) * * Not really a monster, this is the Tank Commander's decapitated body. * There should be a item_commander_head that has this as it's target. */ void commander_body_think(edict_t *self) { if (!self) { return; } if (++self->s.frame < 24) { self->nextthink = level.time + FRAMETIME; } else { self->nextthink = 0; } if (self->s.frame == 22) { gi.sound(self, CHAN_BODY, gi.soundindex("tank/thud.wav"), 1, ATTN_NORM, 0); } } void commander_body_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->think = commander_body_think; self->nextthink = level.time + FRAMETIME; gi.sound(self, CHAN_BODY, gi.soundindex("tank/pain.wav"), 1, ATTN_NORM, 0); } void commander_body_drop(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_TOSS; self->s.origin[2] += 2; } void SP_monster_commander_body(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_NONE; self->solid = SOLID_BBOX; self->model = "models/monsters/commandr/tris.md2"; self->s.modelindex = gi.modelindex(self->model); VectorSet(self->mins, -32, -32, 0); VectorSet(self->maxs, 32, 32, 48); self->use = commander_body_use; self->takedamage = DAMAGE_YES; self->flags = FL_GODMODE; self->s.renderfx |= RF_FRAMELERP; gi.linkentity(self); gi.soundindex("tank/thud.wav"); gi.soundindex("tank/pain.wav"); self->think = commander_body_drop; self->nextthink = level.time + 5 * FRAMETIME; } /* * QUAKED misc_banner (1 .5 0) (-4 -4 -4) (4 4 4) * * The origin is the bottom of the banner. * The banner is 128 tall. */ void misc_banner_think(edict_t *ent) { if (!ent) { return; } ent->s.frame = (ent->s.frame + 1) % 16; ent->nextthink = level.time + FRAMETIME; } void SP_misc_banner(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); ent->s.frame = rand() % 16; gi.linkentity(ent); ent->think = misc_banner_think; ent->nextthink = level.time + FRAMETIME; } /* * QUAKED misc_deadsoldier (1 .5 0) (-16 -16 0) (16 16 16) ON_BACK ON_STOMACH BACK_DECAP FETAL_POS SIT_DECAP IMPALED * * This is the dead player model. Comes in 6 exciting different poses! */ void misc_deadsoldier_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } if (self->health > -30) { return; } gi.sound(self, CHAN_BODY, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); } void SP_misc_deadsoldier(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex("models/deadbods/dude/tris.md2"); /* Defaults to frame 0 */ if (ent->spawnflags & 2) { ent->s.frame = 1; } else if (ent->spawnflags & 4) { ent->s.frame = 2; } else if (ent->spawnflags & 8) { ent->s.frame = 3; } else if (ent->spawnflags & 16) { ent->s.frame = 4; } else if (ent->spawnflags & 32) { ent->s.frame = 5; } else { ent->s.frame = 0; } VectorSet(ent->mins, -16, -16, 0); VectorSet(ent->maxs, 16, 16, 16); ent->deadflag = DEAD_DEAD; ent->takedamage = DAMAGE_YES; ent->svflags |= SVF_MONSTER | SVF_DEADMONSTER; ent->die = misc_deadsoldier_die; ent->monsterinfo.aiflags |= AI_GOOD_GUY; gi.linkentity(ent); } extern void train_use(edict_t *self, edict_t *other, edict_t *activator); extern void func_train_find(edict_t *self); /* * QUAKED misc_viper (1 .5 0) (-16 -16 0) (16 16 32) * * This is the Viper for the flyby bombing. * It is trigger_spawned, so you must have something use it for it to show up. * There must be a path for it to follow once it is activated. * * "speed" How fast the Viper should fly */ void misc_viper_use(edict_t *self, edict_t *other, edict_t *activator) { if (!self || !other || !activator) { return; } self->svflags &= ~SVF_NOCLIENT; self->use = train_use; train_use(self, other, activator); } void SP_misc_viper(edict_t *ent) { if (!ent) { return; } if (!ent->target) { gi.dprintf("misc_viper without a target at %s\n", vtos(ent->absmin)); G_FreeEdict(ent); return; } if (!ent->speed) { ent->speed = 300; } ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex("models/ships/viper/tris.md2"); VectorSet(ent->mins, -16, -16, 0); VectorSet(ent->maxs, 16, 16, 32); ent->think = func_train_find; ent->nextthink = level.time + FRAMETIME; ent->use = misc_viper_use; ent->svflags |= SVF_NOCLIENT; ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed; gi.linkentity(ent); } /* * QUAKED misc_bigviper (1 .5 0) (-176 -120 -24) (176 120 72) * * This is a large stationary viper as seen in Paul's intro */ void SP_misc_bigviper(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -176, -120, -24); VectorSet(ent->maxs, 176, 120, 72); ent->s.modelindex = gi.modelindex("models/ships/bigviper/tris.md2"); gi.linkentity(ent); } /* * QUAKED misc_viper_bomb (1 0 0) (-8 -8 -8) (8 8 8) * * "dmg" how much boom should the bomb make? */ void misc_viper_bomb_touch(edict_t *self, edict_t *other /* unused */, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self) { return; } G_UseTargets(self, self->activator); self->s.origin[2] = self->absmin[2] + 1; T_RadiusDamage(self, self, self->dmg, NULL, self->dmg + 40, MOD_BOMB); BecomeExplosion2(self); } void misc_viper_bomb_prethink(edict_t *self) { vec3_t v; float diff; if (!self) { return; } self->groundentity = NULL; diff = self->timestamp - level.time; if (diff < -1.0) { diff = -1.0; } VectorScale(self->moveinfo.dir, 1.0 + diff, v); v[2] = diff; diff = self->s.angles[2]; vectoangles(v, self->s.angles); self->s.angles[2] = diff + 10; } void misc_viper_bomb_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { edict_t *viper; if (!self || !activator) { return; } self->solid = SOLID_BBOX; self->svflags &= ~SVF_NOCLIENT; self->s.effects |= EF_ROCKET; self->use = NULL; self->movetype = MOVETYPE_TOSS; self->prethink = misc_viper_bomb_prethink; self->touch = misc_viper_bomb_touch; self->activator = activator; viper = G_Find(NULL, FOFS(classname), "misc_viper"); VectorScale(viper->moveinfo.dir, viper->moveinfo.speed, self->velocity); self->timestamp = level.time; VectorCopy(viper->moveinfo.dir, self->moveinfo.dir); } void SP_misc_viper_bomb(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; VectorSet(self->mins, -8, -8, -8); VectorSet(self->maxs, 8, 8, 8); self->s.modelindex = gi.modelindex("models/objects/bomb/tris.md2"); if (!self->dmg) { self->dmg = 1000; } self->use = misc_viper_bomb_use; self->svflags |= SVF_NOCLIENT; gi.linkentity(self); } extern void train_use(edict_t *self, edict_t *other, edict_t *activator); extern void func_train_find(edict_t *self); /* * QUAKED misc_strogg_ship (1 .5 0) (-16 -16 0) (16 16 32) * * This is a Storgg ship for the flybys. * It is trigger_spawned, so you must have something use it for it to show up. * There must be a path for it to follow once it is activated. * * "speed" How fast it should fly */ void misc_strogg_ship_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->svflags &= ~SVF_NOCLIENT; self->use = train_use; train_use(self, other, activator); } void SP_misc_strogg_ship(edict_t *ent) { if (!ent) { return; } if (!ent->target) { gi.dprintf("%s without a target at %s\n", ent->classname, vtos(ent->absmin)); G_FreeEdict(ent); return; } if (!ent->speed) { ent->speed = 300; } ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex("models/ships/strogg1/tris.md2"); VectorSet(ent->mins, -16, -16, 0); VectorSet(ent->maxs, 16, 16, 32); ent->think = func_train_find; ent->nextthink = level.time + FRAMETIME; ent->use = misc_strogg_ship_use; ent->svflags |= SVF_NOCLIENT; ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed; gi.linkentity(ent); } /* * QUAKED misc_satellite_dish (1 .5 0) (-64 -64 0) (64 64 128) */ void misc_satellite_dish_think(edict_t *self) { if (!self) { return; } self->s.frame++; if (self->s.frame < 38) { self->nextthink = level.time + FRAMETIME; } } void misc_satellite_dish_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->s.frame = 0; self->think = misc_satellite_dish_think; self->nextthink = level.time + FRAMETIME; } void SP_misc_satellite_dish(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -64, -64, 0); VectorSet(ent->maxs, 64, 64, 128); ent->s.modelindex = gi.modelindex("models/objects/satellite/tris.md2"); ent->use = misc_satellite_dish_use; gi.linkentity(ent); } /* * QUAKED light_mine1 (0 1 0) (-2 -2 -12) (2 2 12) */ void SP_light_mine1(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex("models/objects/minelite/light1/tris.md2"); gi.linkentity(ent); } /* * QUAKED light_mine2 (0 1 0) (-2 -2 -12) (2 2 12) */ void SP_light_mine2(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex("models/objects/minelite/light2/tris.md2"); gi.linkentity(ent); } /* * QUAKED misc_gib_arm (1 0 0) (-8 -8 -8) (8 8 8) * * Intended for use with the target_spawner */ void SP_misc_gib_arm(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, "models/objects/gibs/arm/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; ent->takedamage = DAMAGE_YES; ent->die = gib_die; ent->movetype = MOVETYPE_TOSS; ent->svflags |= SVF_MONSTER; ent->deadflag = DEAD_DEAD; ent->avelocity[0] = random() * 200; ent->avelocity[1] = random() * 200; ent->avelocity[2] = random() * 200; ent->think = G_FreeEdict; ent->nextthink = level.time + 30; gi.linkentity(ent); } /* * QUAKED misc_gib_leg (1 0 0) (-8 -8 -8) (8 8 8) * Intended for use with the target_spawner */ void SP_misc_gib_leg(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, "models/objects/gibs/leg/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; ent->takedamage = DAMAGE_YES; ent->die = gib_die; ent->movetype = MOVETYPE_TOSS; ent->svflags |= SVF_MONSTER; ent->deadflag = DEAD_DEAD; ent->avelocity[0] = random() * 200; ent->avelocity[1] = random() * 200; ent->avelocity[2] = random() * 200; ent->think = G_FreeEdict; ent->nextthink = level.time + 30; gi.linkentity(ent); } /* * QUAKED misc_gib_head (1 0 0) (-8 -8 -8) (8 8 8) * Intended for use with the target_spawner */ void SP_misc_gib_head(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, "models/objects/gibs/head/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; ent->takedamage = DAMAGE_YES; ent->die = gib_die; ent->movetype = MOVETYPE_TOSS; ent->svflags |= SVF_MONSTER; ent->deadflag = DEAD_DEAD; ent->avelocity[0] = random() * 200; ent->avelocity[1] = random() * 200; ent->avelocity[2] = random() * 200; ent->think = G_FreeEdict; ent->nextthink = level.time + 30; gi.linkentity(ent); } /* ===================================================== */ /* * QUAKED target_character (0 0 1) ? * * used with target_string (must be on same "team") * "count" is position in the string (starts at 1) */ void SP_target_character(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); self->solid = SOLID_BSP; self->s.frame = 12; gi.linkentity(self); return; } /* * QUAKED target_string (0 0 1) (-8 -8 -8) (8 8 8) */ void target_string_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { edict_t *e; int n, l; char c; if (!self) { return; } l = strlen(self->message); for (e = self->teammaster; e; e = e->teamchain) { if (!e->count) { continue; } n = e->count - 1; if (n > l) { e->s.frame = 12; continue; } c = self->message[n]; if ((c >= '0') && (c <= '9')) { e->s.frame = c - '0'; } else if (c == '-') { e->s.frame = 10; } else if (c == ':') { e->s.frame = 11; } else { e->s.frame = 12; } } } void SP_target_string(edict_t *self) { if (!self) { return; } if (!self->message) { self->message = ""; } self->use = target_string_use; } #define CLOCK_MESSAGE_SIZE 16 /* * QUAKED func_clock (0 0 1) (-8 -8 -8) (8 8 8) TIMER_UP TIMER_DOWN START_OFF MULTI_USE * * target a target_string with this * * The default is to be a time of day clock * * TIMER_UP and TIMER_DOWN run for "count" seconds and the fire "pathtarget" * If START_OFF, this entity must be used before it starts * * "style" 0 "xx" * 1 "xx:xx" * 2 "xx:xx:xx" */ void func_clock_reset(edict_t *self) { if (!self) { return; } self->activator = NULL; if (self->spawnflags & 1) { self->health = 0; self->wait = self->count; } else if (self->spawnflags & 2) { self->health = self->count; self->wait = 0; } } void func_clock_format_countdown(edict_t *self) { if (!self) { return; } if (self->style == 0) { Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i", self->health); return; } if (self->style == 1) { Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i", self->health / 60, self->health % 60); if (self->message[3] == ' ') { self->message[3] = '0'; } return; } if (self->style == 2) { Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", self->health / 3600, (self->health - (self->health / 3600) * 3600) / 60, self->health % 60); if (self->message[3] == ' ') { self->message[3] = '0'; } if (self->message[6] == ' ') { self->message[6] = '0'; } return; } } void func_clock_think(edict_t *self) { if (!self) { return; } if (!self->enemy) { self->enemy = G_Find(NULL, FOFS(targetname), self->target); if (!self->enemy) { return; } } if (self->spawnflags & 1) { func_clock_format_countdown(self); self->health++; } else if (self->spawnflags & 2) { func_clock_format_countdown(self); self->health--; } else { struct tm *ltime; time_t gmtime; time(&gmtime); ltime = localtime(&gmtime); Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", ltime->tm_hour, ltime->tm_min, ltime->tm_sec); if (self->message[3] == ' ') { self->message[3] = '0'; } if (self->message[6] == ' ') { self->message[6] = '0'; } } self->enemy->message = self->message; self->enemy->use(self->enemy, self, self); if (((self->spawnflags & 1) && (self->health > self->wait)) || ((self->spawnflags & 2) && (self->health < self->wait))) { if (self->pathtarget) { char *savetarget; char *savemessage; savetarget = self->target; savemessage = self->message; self->target = self->pathtarget; self->message = NULL; G_UseTargets(self, self->activator); self->target = savetarget; self->message = savemessage; } if (!(self->spawnflags & 8)) { return; } func_clock_reset(self); if (self->spawnflags & 4) { return; } } self->nextthink = level.time + 1; } void func_clock_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } if (!(self->spawnflags & 8)) { self->use = NULL; } if (self->activator) { return; } self->activator = activator; self->think(self); } void SP_func_clock(edict_t *self) { if (!self) { return; } if (!self->target) { gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin)); G_FreeEdict(self); return; } if ((self->spawnflags & 2) && (!self->count)) { gi.dprintf("%s with no count at %s\n", self->classname, vtos(self->s.origin)); G_FreeEdict(self); return; } if ((self->spawnflags & 1) && (!self->count)) { self->count = 60 * 60; } func_clock_reset(self); self->message = gi.TagMalloc(CLOCK_MESSAGE_SIZE, TAG_LEVEL); self->think = func_clock_think; if (self->spawnflags & 4) { self->use = func_clock_use; } else { self->nextthink = level.time + 1; } } /* ================================================================================= */ void teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { edict_t *dest; int i; if (!self || !other) { return; } if (!other->client) { return; } dest = G_Find(NULL, FOFS(targetname), self->target); if (!dest) { gi.dprintf("Couldn't find destination\n"); return; } /* unlink to make sure it can't possibly interfere with KillBox */ gi.unlinkentity(other); VectorCopy(dest->s.origin, other->s.origin); VectorCopy(dest->s.origin, other->s.old_origin); other->s.origin[2] += 10; /* clear the velocity and hold them in place briefly */ VectorClear(other->velocity); other->client->ps.pmove.pm_time = 160 >> 3; /* hold time */ other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; /* draw the teleport splash at source and on the player */ self->owner->s.event = EV_PLAYER_TELEPORT; other->s.event = EV_PLAYER_TELEPORT; /* set angles */ for (i = 0; i < 3; i++) { other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT( dest->s.angles[i] - other->client->resp.cmd_angles[i]); } VectorClear(other->s.angles); VectorClear(other->client->ps.viewangles); VectorClear(other->client->v_angle); /* kill anything at the destination */ KillBox(other); gi.linkentity(other); } /* * QUAKED misc_teleporter (1 0 0) (-32 -32 -24) (32 32 -16) * * Stepping onto this disc will teleport players to the targeted misc_teleporter_dest object. */ void SP_misc_teleporter(edict_t *ent) { if (!ent) { return; } edict_t *trig; if (!ent->target) { gi.dprintf("teleporter without a target.\n"); G_FreeEdict(ent); return; } gi.setmodel(ent, "models/objects/dmspot/tris.md2"); ent->s.skinnum = 1; ent->s.effects = EF_TELEPORTER; ent->s.sound = gi.soundindex("world/amb10.wav"); ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, -24); VectorSet(ent->maxs, 32, 32, -16); gi.linkentity(ent); trig = G_Spawn(); trig->touch = teleporter_touch; trig->solid = SOLID_TRIGGER; trig->target = ent->target; trig->owner = ent; VectorCopy(ent->s.origin, trig->s.origin); VectorSet(trig->mins, -8, -8, 8); VectorSet(trig->maxs, 8, 8, 24); gi.linkentity(trig); } /* * QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16) * * Point teleporters at these. */ void SP_misc_teleporter_dest(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, "models/objects/dmspot/tris.md2"); ent->s.skinnum = 0; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, -24); VectorSet(ent->maxs, 32, 32, -16); gi.linkentity(ent); } void misc_nuke_core_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->svflags & SVF_NOCLIENT) { self->svflags &= ~SVF_NOCLIENT; } else { self->svflags |= SVF_NOCLIENT; } } /* * QUAKED misc_nuke_core (1 0 0) (-16 -16 -16) (16 16 16) * * toggles visible/not visible. starts visible. */ void SP_misc_nuke_core(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, "models/objects/core/tris.md2"); gi.linkentity(ent); ent->use = misc_nuke_core_use; } rogue-ROGUE_2_13/src/g_monster.c000066400000000000000000000542771477320066100165570ustar00rootroot00000000000000/* * ======================================================================= * * Monster utility functions. * * ======================================================================= */ #include "header/local.h" void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype) { if (!self) { return; } fire_bullet(self, start, dir, damage, kick, hspread, vspread, MOD_UNKNOWN); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int flashtype) { if (!self) { return; } fire_shotgun(self, start, aimdir, damage, kick, hspread, vspread, count, MOD_UNKNOWN); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect) { if (!self) { return; } fire_blaster(self, start, dir, damage, speed, effect, false); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect) { if (!self) { return; } fire_blaster2(self, start, dir, damage, speed, effect, false); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, edict_t *enemy, int flashtype) { if (!self || !enemy) { return; } fire_tracker(self, start, dir, damage, speed, enemy); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_heat(edict_t *self, vec3_t start, vec3_t dir, vec3_t offset, int damage, int kick, int flashtype) { if (!self) { return; } fire_heat(self, start, dir, offset, damage, kick, true); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype) { if (!self) { return; } fire_grenade(self, start, aimdir, damage, speed, 2.5, damage + 40); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype) { if (!self) { return; } fire_rocket(self, start, dir, damage, speed, damage + 20, damage); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype) { if (!self) { return; } if (!(gi.pointcontents(start) & MASK_SOLID)) { fire_rail(self, start, aimdir, damage, kick); } gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int kick, float damage_radius, int flashtype) { if (!self) { return; } fire_bfg(self, start, aimdir, damage, speed, damage_radius); gi.WriteByte(svc_muzzleflash2); gi.WriteShort(self - g_edicts); gi.WriteByte(flashtype); gi.multicast(start, MULTICAST_PVS); } void M_FliesOff(edict_t *self) { if (!self) { return; } self->s.effects &= ~EF_FLIES; self->s.sound = 0; } void M_FliesOn(edict_t *self) { if (!self) { return; } if (self->waterlevel) { return; } self->s.effects |= EF_FLIES; self->s.sound = gi.soundindex("infantry/inflies1.wav"); self->think = M_FliesOff; self->nextthink = level.time + 60; } void M_FlyCheck(edict_t *self) { if (!self) { return; } if (self->waterlevel) { return; } if (random() > 0.5) { return; } self->think = M_FliesOn; self->nextthink = level.time + 5 + 10 * random(); } void AttackFinished(edict_t *self, float time) { if (!self) { return; } self->monsterinfo.attack_finished = level.time + time; } void M_CheckGround(edict_t *ent) { if (!ent) { return; } vec3_t point; trace_t trace; if (ent->flags & (FL_SWIM | FL_FLY)) { return; } if ((ent->velocity[2] * ent->gravityVector[2]) < -100) { ent->groundentity = NULL; return; } /* if the hull point one-quarter unit down is solid the entity is on ground */ point[0] = ent->s.origin[0]; point[1] = ent->s.origin[1]; point[2] = ent->s.origin[2] + (0.25 * ent->gravityVector[2]); trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, point, ent, MASK_MONSTERSOLID); /* check steepness */ if (ent->gravityVector[2] < 0) /* normal gravity */ { if ((trace.plane.normal[2] < 0.7) && !trace.startsolid) { ent->groundentity = NULL; return; } } else /* inverted gravity */ { if ((trace.plane.normal[2] > -0.7) && !trace.startsolid) { ent->groundentity = NULL; return; } } if (!trace.startsolid && !trace.allsolid) { VectorCopy(trace.endpos, ent->s.origin); ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; ent->velocity[2] = 0; } } void M_CatagorizePosition(edict_t *ent) { vec3_t point; int cont; if (!ent) { return; } /* get waterlevel */ point[0] = (ent->absmax[0] + ent->absmin[0])/2; point[1] = (ent->absmax[1] + ent->absmin[1])/2; point[2] = ent->absmin[2] + 2; cont = gi.pointcontents(point); if (!(cont & MASK_WATER)) { ent->waterlevel = 0; ent->watertype = 0; return; } ent->watertype = cont; ent->waterlevel = 1; point[2] += 26; cont = gi.pointcontents(point); if (!(cont & MASK_WATER)) { return; } ent->waterlevel = 2; point[2] += 22; cont = gi.pointcontents(point); if (cont & MASK_WATER) { ent->waterlevel = 3; } } void M_WorldEffects(edict_t *ent) { int dmg; if (!ent) { return; } if (ent->health > 0) { if (!(ent->flags & FL_SWIM)) { if (ent->waterlevel < 3) { ent->air_finished = level.time + 12; } else if (ent->air_finished < level.time) { /* drown! */ if (ent->pain_debounce_time < level.time) { dmg = 2 + 2 * floor(level.time - ent->air_finished); if (dmg > 15) { dmg = 15; } T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); ent->pain_debounce_time = level.time + 1; } } } else { if (ent->waterlevel > 0) { ent->air_finished = level.time + 9; } else if (ent->air_finished < level.time) { /* suffocate! */ if (ent->pain_debounce_time < level.time) { dmg = 2 + 2 * floor(level.time - ent->air_finished); if (dmg > 15) { dmg = 15; } T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); ent->pain_debounce_time = level.time + 1; } } } } if (ent->waterlevel == 0) { if (ent->flags & FL_INWATER) { gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); ent->flags &= ~FL_INWATER; } return; } if ((ent->watertype & CONTENTS_LAVA) && !(ent->flags & FL_IMMUNE_LAVA)) { if (ent->damage_debounce_time < level.time) { ent->damage_debounce_time = level.time + 0.2; T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 10 * ent->waterlevel, 0, 0, MOD_LAVA); } } if ((ent->watertype & CONTENTS_SLIME) && !(ent->flags & FL_IMMUNE_SLIME)) { if (ent->damage_debounce_time < level.time) { ent->damage_debounce_time = level.time + 1; T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 4 * ent->waterlevel, 0, 0, MOD_SLIME); } } if (!(ent->flags & FL_INWATER)) { if (!(ent->svflags & SVF_DEADMONSTER)) { if (ent->watertype & CONTENTS_LAVA) { if (random() <= 0.5) { gi.sound(ent, CHAN_BODY, gi.soundindex("player/lava1.wav"), 1, ATTN_NORM, 0); } else { gi.sound(ent, CHAN_BODY, gi.soundindex("player/lava2.wav"), 1, ATTN_NORM, 0); } } else if (ent->watertype & CONTENTS_SLIME) { gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); } else if (ent->watertype & CONTENTS_WATER) { gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); } } ent->flags |= FL_INWATER; ent->damage_debounce_time = 0; } } void M_droptofloor(edict_t *ent) { vec3_t end; trace_t trace; if (!ent) { return; } if (ent->gravityVector[2] < 0) { ent->s.origin[2] += 1; VectorCopy(ent->s.origin, end); end[2] -= 256; } else { ent->s.origin[2] -= 1; VectorCopy(ent->s.origin, end); end[2] += 256; } trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); if ((trace.fraction == 1) || trace.allsolid) { return; } VectorCopy(trace.endpos, ent->s.origin); gi.linkentity(ent); M_CheckGround(ent); M_CatagorizePosition(ent); } void M_SetEffects(edict_t *ent) { int remaining; if (!ent) { return; } ent->s.effects &= ~(EF_COLOR_SHELL | EF_POWERSCREEN | EF_DOUBLE | EF_QUAD | EF_PENT); ent->s.renderfx &= ~(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE); if (ent->monsterinfo.aiflags & AI_RESURRECTING) { ent->s.effects |= EF_COLOR_SHELL; ent->s.renderfx |= RF_SHELL_RED; } if (ent->health <= 0) { return; } if (ent->powerarmor_time > level.time) { if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SCREEN) { ent->s.effects |= EF_POWERSCREEN; } else if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SHIELD) { ent->s.effects |= EF_COLOR_SHELL; ent->s.renderfx |= RF_SHELL_GREEN; } } if (ent->monsterinfo.quad_framenum > level.framenum) { remaining = ent->monsterinfo.quad_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_QUAD; } } else { ent->s.effects &= ~EF_QUAD; } if (ent->monsterinfo.double_framenum > level.framenum) { remaining = ent->monsterinfo.double_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_DOUBLE; } } else { ent->s.effects &= ~EF_DOUBLE; } if (ent->monsterinfo.invincible_framenum > level.framenum) { remaining = ent->monsterinfo.invincible_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_PENT; } } else { ent->s.effects &= ~EF_PENT; } } void M_MoveFrame(edict_t *self) { mmove_t *move; int index; if (!self) { return; } move = self->monsterinfo.currentmove; self->nextthink = level.time + FRAMETIME; if ((self->monsterinfo.nextframe) && (self->monsterinfo.nextframe >= move->firstframe) && (self->monsterinfo.nextframe <= move->lastframe)) { if (self->s.frame != self->monsterinfo.nextframe) { self->s.frame = self->monsterinfo.nextframe; self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; } self->monsterinfo.nextframe = 0; } else { /* prevent nextframe from leaking into a future move */ self->monsterinfo.nextframe = 0; if (self->s.frame == move->lastframe) { if (move->endfunc) { move->endfunc(self); /* regrab move, endfunc is very likely to change it */ move = self->monsterinfo.currentmove; /* check for death */ if (self->svflags & SVF_DEADMONSTER) { return; } } } if ((self->s.frame < move->firstframe) || (self->s.frame > move->lastframe)) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; self->s.frame = move->firstframe; } else { if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) { self->s.frame++; if (self->s.frame > move->lastframe) { self->s.frame = move->firstframe; } } } } index = self->s.frame - move->firstframe; if (move->frame[index].aifunc) { if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) { move->frame[index].aifunc(self, move->frame[index].dist * self->monsterinfo.scale); } else { move->frame[index].aifunc(self, 0); } } if (move->frame[index].thinkfunc) { move->frame[index].thinkfunc(self); } } void monster_think(edict_t *self) { if (!self) { return; } M_MoveFrame(self); if (self->linkcount != self->monsterinfo.linkcount) { self->monsterinfo.linkcount = self->linkcount; M_CheckGround(self); } M_CatagorizePosition(self); M_WorldEffects(self); M_SetEffects(self); } /* * Using a monster makes it angry at the current activator */ void monster_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } if (self->enemy) { return; } if (self->health <= 0) { return; } if (activator->flags & FL_NOTARGET) { return; } if (!(activator->client) && !(activator->monsterinfo.aiflags & AI_GOOD_GUY)) { return; } if (activator->flags & FL_DISGUISED) { return; } /* delay reaction so if the monster is teleported, its sound is still heard */ self->enemy = activator; FoundTarget(self); } void monster_start_go(edict_t *self); void monster_triggered_spawn(edict_t *self) { if (!self) { return; } self->s.origin[2] += 1; KillBox(self); self->solid = SOLID_BBOX; self->movetype = MOVETYPE_STEP; self->svflags &= ~SVF_NOCLIENT; self->air_finished = level.time + 12; gi.linkentity(self); monster_start_go(self); if (self->enemy && !(self->spawnflags & 1) && !(self->enemy->flags & FL_NOTARGET)) { if (!(self->enemy->flags & FL_DISGUISED)) { FoundTarget(self); } else { self->enemy = NULL; } } else { self->enemy = NULL; } } void monster_triggered_spawn_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } /* we have a one frame delay here so we don't telefrag the guy who activated us */ self->think = monster_triggered_spawn; self->nextthink = level.time + FRAMETIME; if (activator->client) { self->enemy = activator; } self->use = monster_use; } void monster_triggered_start(edict_t *self) { if (!self) { return; } self->solid = SOLID_NOT; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->nextthink = 0; self->use = monster_triggered_spawn_use; } /* * When a monster dies, it fires all of its * targets with the current enemy as activator. */ void monster_death_use(edict_t *self) { if (!self) { return; } self->flags &= ~(FL_FLY | FL_SWIM); self->monsterinfo.aiflags &= AI_GOOD_GUY; if (self->item) { Drop_Item(self, self->item); self->item = NULL; } if (self->deathtarget) { self->target = self->deathtarget; } if (!self->target) { return; } G_UseTargets(self, self->enemy); } /* ============================================================================ */ qboolean monster_start(edict_t *self) { if (!self) { return false; } if (deathmatch->value) { G_FreeEdict(self); return false; } if ((self->spawnflags & 4) && !(self->monsterinfo.aiflags & AI_GOOD_GUY)) { self->spawnflags &= ~4; self->spawnflags |= 1; } if ((self->spawnflags & 2) && !self->targetname) { if (g_fix_triggered->value) { self->spawnflags &= ~2; } gi.dprintf ("triggered %s at %s has no targetname\n", self->classname, vtos (self->s.origin)); } if ((!(self->monsterinfo.aiflags & AI_GOOD_GUY)) && (!(self->monsterinfo.aiflags & AI_DO_NOT_COUNT))) { level.total_monsters++; } self->nextthink = level.time + FRAMETIME; self->svflags |= SVF_MONSTER; self->s.renderfx |= RF_FRAMELERP; self->takedamage = DAMAGE_AIM; self->air_finished = level.time + 12; self->use = monster_use; if(!self->max_health) { self->max_health = self->health; } self->clipmask = MASK_MONSTERSOLID; self->s.skinnum = 0; self->deadflag = DEAD_NO; self->svflags &= ~SVF_DEADMONSTER; if (!self->monsterinfo.checkattack) { self->monsterinfo.checkattack = M_CheckAttack; } VectorCopy(self->s.origin, self->s.old_origin); if (st.item) { self->item = FindItemByClassname(st.item); if (!self->item) { gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item); } } /* randomize what frame they start on */ if (self->monsterinfo.currentmove) { self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1)); } self->monsterinfo.base_height = self->maxs[2]; self->monsterinfo.quad_framenum = 0; self->monsterinfo.double_framenum = 0; self->monsterinfo.invincible_framenum = 0; return true; } void monster_start_go(edict_t *self) { vec3_t v; if (!self) { return; } if (self->health <= 0) { return; } /* check for target to combat_point and change to combattarget */ if (self->target) { qboolean notcombat; qboolean fixup; edict_t *target; target = NULL; notcombat = false; fixup = false; while ((target = G_Find(target, FOFS(targetname), self->target)) != NULL) { if (strcmp(target->classname, "point_combat") == 0) { self->combattarget = self->target; fixup = true; } else { notcombat = true; } } if (notcombat && self->combattarget) { gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin)); } if (fixup) { self->target = NULL; } } /* validate combattarget */ if (self->combattarget) { edict_t *target; target = NULL; while ((target = G_Find(target, FOFS(targetname), self->combattarget)) != NULL) { if (strcmp(target->classname, "point_combat") != 0) { gi.dprintf( "%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n", self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2], self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1], (int)target->s.origin[2]); } } } if (self->target) { self->goalentity = self->movetarget = G_PickTarget(self->target); if (!self->movetarget) { gi.dprintf("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); self->target = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } else if (strcmp(self->movetarget->classname, "path_corner") == 0) { VectorSubtract(self->goalentity->s.origin, self->s.origin, v); self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); self->monsterinfo.walk(self); self->target = NULL; } else { self->goalentity = self->movetarget = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } } else { self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } self->think = monster_think; self->nextthink = level.time + FRAMETIME; } void walkmonster_start_go(edict_t *self) { if (!self) { return; } if (!(self->spawnflags & 2) && (level.time < 1)) { M_droptofloor(self); if (self->groundentity) { if (!M_walkmove(self, 0, 0)) { gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin)); } } } if (!self->yaw_speed) { self->yaw_speed = 20; } if (!self->viewheight) { self->viewheight = 25; } if (self->spawnflags & 2) { monster_triggered_start(self); } else { monster_start_go(self); } } void walkmonster_start(edict_t *self) { if (!self) { return; } self->think = walkmonster_start_go; monster_start(self); } void flymonster_start_go(edict_t *self) { if (!self) { return; } if (!M_walkmove(self, 0, 0)) { gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin)); } if (!self->yaw_speed) { self->yaw_speed = 10; } if (!self->viewheight) { self->viewheight = 25; } if (self->spawnflags & 2) { monster_triggered_start(self); } else { monster_start_go(self); } } void flymonster_start(edict_t *self) { if (!self) { return; } self->flags |= FL_FLY; self->think = flymonster_start_go; monster_start(self); } void swimmonster_start_go(edict_t *self) { if (!self) { return; } if (!self->yaw_speed) { self->yaw_speed = 10; } if (!self->viewheight) { self->viewheight = 10; } if (self->spawnflags & 2) { monster_triggered_start(self); } else { monster_start_go(self); } } void swimmonster_start(edict_t *self) { if (!self) { return; } self->flags |= FL_SWIM; self->think = swimmonster_start_go; monster_start(self); } void stationarymonster_start_go(edict_t *self); void stationarymonster_triggered_spawn(edict_t *self) { if (!self) { return; } KillBox(self); self->solid = SOLID_BBOX; self->movetype = MOVETYPE_NONE; self->svflags &= ~SVF_NOCLIENT; self->air_finished = level.time + 12; gi.linkentity(self); monster_start_go(self); if (self->enemy && !(self->spawnflags & 1) && !(self->enemy->flags & FL_NOTARGET)) { if (!(self->enemy->flags & FL_DISGUISED)) { FoundTarget(self); } else { self->enemy = NULL; } } else { self->enemy = NULL; } } void stationarymonster_triggered_spawn_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } /* we have a one frame delay here so we don't telefrag the guy who activated us */ self->think = stationarymonster_triggered_spawn; self->nextthink = level.time + FRAMETIME; if (activator->client) { self->enemy = activator; } self->use = monster_use; } void stationarymonster_triggered_start(edict_t *self) { if (!self) { return; } self->solid = SOLID_NOT; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->nextthink = 0; self->use = stationarymonster_triggered_spawn_use; } void stationarymonster_start_go(edict_t *self) { if (!self) { return; } if (!self->yaw_speed) { self->yaw_speed = 20; } if (self->spawnflags & 2) { stationarymonster_triggered_start(self); } else { monster_start_go(self); } } void stationarymonster_start(edict_t *self) { if (!self) { return; } self->think = stationarymonster_start_go; monster_start(self); } void monster_done_dodge(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_DODGING; } rogue-ROGUE_2_13/src/g_newai.c000066400000000000000000000763501477320066100161670ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific AI code * * ======================================================================= */ #include "header/local.h" #define STATE_TOP 0 #define STATE_BOTTOM 1 #define STATE_UP 2 #define STATE_DOWN 3 #define HINT_ENDPOINT 0x0001 #define MAX_HINT_CHAINS 100 #define TESLA_DAMAGE_RADIUS 128 edict_t *hint_path_start[MAX_HINT_CHAINS]; int hint_paths_present; int num_hint_paths; qboolean face_wall(edict_t *self); qboolean monsterlost_checkhint2(edict_t *self); void HuntTarget(edict_t *self); qboolean blocked_checkplat(edict_t *self, float dist) { int playerPosition; trace_t trace; vec3_t pt1, pt2; vec3_t forward; edict_t *plat; if (!self) { return false; } if (!self->enemy) { return false; } /* check player's relative altitude */ if (self->enemy->absmin[2] >= self->absmax[2]) { playerPosition = 1; } else if (self->enemy->absmax[2] <= self->absmin[2]) { playerPosition = -1; } else { playerPosition = 0; } /* if we're close to the same position, don't bother trying plats. */ if (playerPosition == 0) { return false; } plat = NULL; /* see if we're already standing on a plat. */ if (self->groundentity && (self->groundentity != world)) { if (!strncmp(self->groundentity->classname, "func_plat", 8)) { plat = self->groundentity; } } /* if we're not, check to see if we'll step onto one with this move */ if (!plat) { AngleVectors(self->s.angles, forward, NULL, NULL); VectorMA(self->s.origin, dist, forward, pt1); VectorCopy(pt1, pt2); pt2[2] -= 384; trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID); if ((trace.fraction < 1) && !trace.allsolid && !trace.startsolid) { if (!strncmp(trace.ent->classname, "func_plat", 8)) { plat = trace.ent; } } } /* if we've found a plat, trigger it. */ if (plat && plat->use) { if (playerPosition == 1) { if (((self->groundentity == plat) && (plat->moveinfo.state == STATE_BOTTOM)) || ((self->groundentity != plat) && (plat->moveinfo.state == STATE_TOP))) { plat->use(plat, self, self); return true; } } else if (playerPosition == -1) { if (((self->groundentity == plat) && (plat->moveinfo.state == STATE_TOP)) || ((self->groundentity != plat) && (plat->moveinfo.state == STATE_BOTTOM))) { plat->use(plat, self, self); return true; } } } return false; } qboolean blocked_checkjump(edict_t *self, float dist, float maxDown, float maxUp) { int playerPosition; trace_t trace; vec3_t pt1, pt2; vec3_t forward, up; if (!self) { return false; } if (!self->enemy) { return false; } AngleVectors(self->s.angles, forward, NULL, up); if (self->enemy->absmin[2] > (self->absmin[2] + 16)) { playerPosition = 1; } else if (self->enemy->absmin[2] < (self->absmin[2] - 16)) { playerPosition = -1; } else { playerPosition = 0; } if ((playerPosition == -1) && maxDown) { /* check to make sure we can even get to the spot we're going to "fall" from */ VectorMA(self->s.origin, 48, forward, pt1); trace = gi.trace(self->s.origin, self->mins, self->maxs, pt1, self, MASK_MONSTERSOLID); if (trace.fraction < 1) { return false; } VectorCopy(pt1, pt2); pt2[2] = self->absmin[2] - maxDown - 1; trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID | MASK_WATER); if ((trace.fraction < 1) && !trace.allsolid && !trace.startsolid) { if (((self->absmin[2] - trace.endpos[2]) >= 24) && (trace.contents & MASK_SOLID)) { if ((self->enemy->absmin[2] - trace.endpos[2]) > 32) { return false; } if (trace.plane.normal[2] < 0.9) { return false; } return true; } } } else if ((playerPosition == 1) && maxUp) { VectorMA(self->s.origin, 48, forward, pt1); VectorCopy(pt1, pt2); pt1[2] = self->absmax[2] + maxUp; trace = gi.trace(pt1, vec3_origin, vec3_origin, pt2, self, MASK_MONSTERSOLID | MASK_WATER); if ((trace.fraction < 1) && !trace.allsolid && !trace.startsolid) { if (((trace.endpos[2] - self->absmin[2]) <= maxUp) && trace.contents & MASK_SOLID) { face_wall(self); return true; } } } return false; } qboolean blocked_checknewenemy(edict_t *self) { return false; } edict_t * hintpath_findstart(edict_t *ent) { edict_t *e; edict_t *last; int field; if (!ent) { return NULL; } if (ent->target) /* starting point */ { last = world; field = FOFS(targetname); e = G_Find(NULL, field, ent->target); while (e) { last = e; if (!e->target) { break; } e = G_Find(NULL, field, e->target); } } else /* end point */ { last = world; field = FOFS(target); e = G_Find(NULL, field, ent->targetname); while (e) { last = e; if (!e->targetname) { break; } e = G_Find(NULL, field, e->targetname); } } if (!(last->spawnflags & HINT_ENDPOINT)) { return NULL; } if (last == world) { last = NULL; } return last; } edict_t * hintpath_other_end(edict_t *ent) { edict_t *e; edict_t *last; int field; if (!ent) { return NULL; } if (ent->target) /* starting point */ { last = world; field = FOFS(targetname); e = G_Find(NULL, field, ent->target); while (e) { last = e; if (!e->target) { break; } e = G_Find(NULL, field, e->target); } } else /* end point */ { last = world; field = FOFS(target); e = G_Find(NULL, field, ent->targetname); while (e) { last = e; if (!e->targetname) { break; } e = G_Find(NULL, field, e->targetname); } } if (!(last->spawnflags & HINT_ENDPOINT)) { return NULL; } if (last == world) { last = NULL; } return last; } void hintpath_go(edict_t *self, edict_t *point) { vec3_t dir; vec3_t angles; if (!self || !point) { return; } VectorSubtract(point->s.origin, self->s.origin, dir); vectoangles2(dir, angles); self->ideal_yaw = angles[YAW]; self->goalentity = self->movetarget = point; self->monsterinfo.pausetime = 0; self->monsterinfo.aiflags |= AI_HINT_PATH; self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); /* run for it */ self->monsterinfo.search_time = level.time; self->monsterinfo.run(self); } void hintpath_stop(edict_t *self) { if (!self) { return; } self->goalentity = NULL; self->movetarget = NULL; self->monsterinfo.last_hint_time = level.time; self->monsterinfo.goal_hint = NULL; self->monsterinfo.aiflags &= ~AI_HINT_PATH; if (has_valid_enemy(self)) { /* if we can see our target, go nuts */ if (visible(self, self->enemy)) { FoundTarget(self); return; } /* otherwise, keep chasing */ HuntTarget(self); return; } /* if our enemy is no longer valid, forget about our enemy and go into stand */ self->enemy = NULL; /* we need the pausetime otherwise the stand code will just revert to walking with no target and the monsters will wonder around aimlessly trying to hunt the world entity */ self->monsterinfo.pausetime = level.time + 100000000; self->monsterinfo.stand(self); } qboolean monsterlost_checkhint(edict_t *self) { edict_t *e, *monster_pathchain, *target_pathchain; edict_t *checkpoint = NULL; edict_t *closest; float closest_range = 1000000; edict_t *start, *destination; int count1 = 0, count2 = 0, count4 = 0, count5 = 0; float r; int i; qboolean hint_path_represented[MAX_HINT_CHAINS]; if (!self) { return false; } /* if there are no hint paths on this map, exit immediately. */ if (!hint_paths_present) { return false; } if (!self->enemy) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { return false; } if (!strcmp(self->classname, "monster_turret")) { return false; } monster_pathchain = NULL; /* find all the hint_paths. */ for (i = 0; i < num_hint_paths; i++) { e = hint_path_start[i]; while (e) { count1++; if (e->monster_hint_chain) { e->monster_hint_chain = NULL; } if (monster_pathchain) { checkpoint->monster_hint_chain = e; checkpoint = e; } else { monster_pathchain = e; checkpoint = e; } e = e->hint_chain; } } /* filter them by distance and visibility to the monster */ e = monster_pathchain; checkpoint = NULL; while (e) { r = realrange(self, e); if (r > 512) { count2++; if (checkpoint) { checkpoint->monster_hint_chain = e->monster_hint_chain; e->monster_hint_chain = NULL; e = checkpoint->monster_hint_chain; continue; } else { /* use checkpoint as temp pointer */ checkpoint = e; e = e->monster_hint_chain; checkpoint->monster_hint_chain = NULL; /* and clear it again */ checkpoint = NULL; /* since we have yet to find a valid one (or else checkpoint would be set) move the start of monster_pathchain */ monster_pathchain = e; continue; } } if (!visible(self, e)) { count4++; if (checkpoint) { checkpoint->monster_hint_chain = e->monster_hint_chain; e->monster_hint_chain = NULL; e = checkpoint->monster_hint_chain; continue; } else { /* use checkpoint as temp pointer */ checkpoint = e; e = e->monster_hint_chain; checkpoint->monster_hint_chain = NULL; /* and clear it again */ checkpoint = NULL; /* since we have yet to find a valid one (or else checkpoint would be set) move the start of monster_pathchain */ monster_pathchain = e; continue; } } /* if it passes all the tests, it's a keeper */ count5++; checkpoint = e; e = e->monster_hint_chain; } /* at this point, we have a list of all of the eligible hint nodes for the monster we now take them, figure out what hint chains they're on, and traverse down those chains, seeing whether any can see the player. first, we figure out which hint chains we have represented in monster_pathchain */ if (count5 == 0) { return false; } for (i = 0; i < num_hint_paths; i++) { hint_path_represented[i] = false; } e = monster_pathchain; checkpoint = NULL; while (e) { if ((e->hint_chain_id < 0) || (e->hint_chain_id > num_hint_paths)) { return false; } hint_path_represented[e->hint_chain_id] = true; e = e->monster_hint_chain; } count2 = 0; count4 = 0; count5 = 0; /* now, build the target_pathchain which contains all of the hint_path nodes we need to check for validity (within range, visibility) */ target_pathchain = NULL; checkpoint = NULL; for (i = 0; i < num_hint_paths; i++) { /* if this hint chain is represented in the monster_hint_chain, add all of it's nodes to the target_pathchain for validity checking */ if (hint_path_represented[i]) { e = hint_path_start[i]; while (e) { if (target_pathchain) { checkpoint->target_hint_chain = e; checkpoint = e; } else { target_pathchain = e; checkpoint = e; } e = e->hint_chain; } } } /* target_pathchain is a list of all of the hint_path nodes we need to check for validity relative to the target */ e = target_pathchain; checkpoint = NULL; while (e) { r = realrange(self->enemy, e); if (r > 512) { count2++; if (checkpoint) { checkpoint->target_hint_chain = e->target_hint_chain; e->target_hint_chain = NULL; e = checkpoint->target_hint_chain; continue; } else { /* use checkpoint as temp pointer */ checkpoint = e; e = e->target_hint_chain; checkpoint->target_hint_chain = NULL; /* and clear it again */ checkpoint = NULL; target_pathchain = e; continue; } } if (!visible(self->enemy, e)) { count4++; if (checkpoint) { checkpoint->target_hint_chain = e->target_hint_chain; e->target_hint_chain = NULL; e = checkpoint->target_hint_chain; continue; } else { /* use checkpoint as temp pointer */ checkpoint = e; e = e->target_hint_chain; checkpoint->target_hint_chain = NULL; /* and clear it again */ checkpoint = NULL; target_pathchain = e; continue; } } /* if it passes all the tests, it's a keeper */ count5++; checkpoint = e; e = e->target_hint_chain; } /* at this point we should have: - monster_pathchain - a list of "monster valid" hint_path nodes linked together by monster_hint_chain - target_pathcain - a list of "target valid" hint_path nodes linked together by target_hint_chain. these are filtered such that only nodes which are on the same chain as "monster valid" nodes Now, we figure out which "monster valid" node we want to use. To do this, we first off make sure we have some target nodes. If we don't, there are no valid hint_path nodes for us to take. If we have some, we filter all of our "monster valid" nodes by which ones have "target valid" nodes on them. Once this filter is finished, we select the closest "monster valid" node, and go to it. */ if (count5 == 0) { return false; } /* reuse the hint_chain_represented array, this time to see which chains are represented by the target */ for (i = 0; i < num_hint_paths; i++) { hint_path_represented[i] = false; } e = target_pathchain; checkpoint = NULL; while (e) { if ((e->hint_chain_id < 0) || (e->hint_chain_id > num_hint_paths)) { return false; } hint_path_represented[e->hint_chain_id] = true; e = e->target_hint_chain; } /* traverse the monster_pathchain - if the hint_node isn't represented in the "target valid" chain list, remove it. if it is on the list, check it for range from the monster. If the range is the closest, keep it */ closest = NULL; e = monster_pathchain; while (e) { if (!(hint_path_represented[e->hint_chain_id])) { checkpoint = e->monster_hint_chain; e->monster_hint_chain = NULL; e = checkpoint; continue; } r = realrange(self, e); if (r < closest_range) { closest = e; } e = e->monster_hint_chain; } if (!closest) { return false; } start = closest; /* now we know which one is the closest to the monster.. this is the one the monster will go to. we need to finally determine what the DESTINATION node is for the monster. walk down the hint_chain, and find the closest one to the player */ closest = NULL; closest_range = 10000000; e = target_pathchain; while (e) { if (start->hint_chain_id == e->hint_chain_id) { r = realrange(self, e); if (r < closest_range) { closest = e; } } e = e->target_hint_chain; } if (!closest) { return false; } destination = closest; self->monsterinfo.goal_hint = destination; hintpath_go(self, start); return true; } void hint_path_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { edict_t *e, *goal; edict_t *next = NULL; qboolean goalFound = false; if (!self || !other) { return; } /* make sure we're the target of it's obsession */ if (other->movetarget == self) { goal = other->monsterinfo.goal_hint; /* if the monster is where he wants to be */ if (goal == self) { hintpath_stop(other); return; } else { /* if we aren't, figure out which way we want to go */ e = hint_path_start[self->hint_chain_id]; while (e) { /* if we get up to ourselves on the hint chain, we're going down it */ if (e == self) { next = e->hint_chain; break; } if (e == goal) { goalFound = true; } /* if we get to where the next link on the chain is this hint_path and have found the goal on the way we're going upstream, so remember who the previous link is */ if ((e->hint_chain == self) && goalFound) { next = e; break; } e = e->hint_chain; } } /* if we couldn't find it, have the monster go back to normal hunting. */ if (!next) { hintpath_stop(other); return; } /* set the last_hint entry to this hint_path, and send him on his way */ hintpath_go(other, next); /* have the monster freeze if the hint path we just touched has a wait time on it, for e xample, when riding a plat. */ if (self->wait) { other->nextthink = level.time + self->wait; } } } /* * QUAKED hint_path (.5 .3 0) (-8 -8 -8) (8 8 8) END * * Target: next hint path * * END - set this flag on the endpoints of each hintpath. * "wait" - set this if you want the monster to freeze when they touch this hintpath */ void SP_hint_path(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } if (!self->targetname && !self->target) { gi.dprintf("unlinked hint_path at %s\n", vtos(self->s.origin)); G_FreeEdict(self); return; } self->solid = SOLID_TRIGGER; self->touch = hint_path_touch; VectorSet(self->mins, -8, -8, -8); VectorSet(self->maxs, 8, 8, 8); self->svflags |= SVF_NOCLIENT; gi.linkentity(self); } void InitHintPaths(void) { edict_t *e, *current; int field, i, count2; hint_paths_present = 0; /* check all the hint_paths. */ field = FOFS(classname); e = G_Find(NULL, field, "hint_path"); if (e) { hint_paths_present = 1; } else { return; } memset(hint_path_start, 0, MAX_HINT_CHAINS * sizeof(edict_t *)); num_hint_paths = 0; while (e) { if (e->spawnflags & HINT_ENDPOINT) { if (e->target) /* start point */ { if (e->targetname) /* this is a bad end, ignore it */ { gi.dprintf("Hint path at %s marked as endpoint with both target (%s) and targetname (%s)\n", vtos(e->s.origin), e->target, e->targetname); } else { if (num_hint_paths >= MAX_HINT_CHAINS) { break; } hint_path_start[num_hint_paths++] = e; } } } e = G_Find(e, field, "hint_path"); } field = FOFS(targetname); for (i = 0; i < num_hint_paths; i++) { count2 = 1; current = hint_path_start[i]; current->hint_chain_id = i; e = G_Find(NULL, field, current->target); if (G_Find(e, field, current->target)) { gi.dprintf("\nForked hint path at %s detected for chain %d, target %s\n", vtos(current->s.origin), num_hint_paths, current->target); hint_path_start[i]->hint_chain = NULL; continue; } while (e) { if (e->hint_chain) { gi.dprintf("\nCircular hint path at %s detected for chain %d, targetname %s\n", vtos(e->s.origin), num_hint_paths, e->targetname); hint_path_start[i]->hint_chain = NULL; break; } count2++; current->hint_chain = e; current = e; current->hint_chain_id = i; if (!current->target) { break; } e = G_Find(NULL, field, current->target); if (G_Find(e, field, current->target)) { gi.dprintf("\nForked hint path at %s detected for chain %d, target %s\n", vtos(current->s.origin), num_hint_paths, current->target); hint_path_start[i]->hint_chain = NULL; break; } } } } qboolean inback(edict_t *self, edict_t *other) { vec3_t vec; float dot; vec3_t forward; if (!self || !other) { return false; } AngleVectors(self->s.angles, forward, NULL, NULL); VectorSubtract(other->s.origin, self->s.origin, vec); VectorNormalize(vec); dot = DotProduct(vec, forward); if (dot < -0.3) { return true; } return false; } float realrange(edict_t *self, edict_t *other) { vec3_t dir; if (!self || !other) { return 0; } VectorSubtract(self->s.origin, other->s.origin, dir); return VectorLength(dir); } qboolean face_wall(edict_t *self) { vec3_t pt; vec3_t forward; vec3_t ang; trace_t tr; if (!self) { return false; } AngleVectors(self->s.angles, forward, NULL, NULL); VectorMA(self->s.origin, 64, forward, pt); tr = gi.trace(self->s.origin, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); if ((tr.fraction < 1) && !tr.allsolid && !tr.startsolid) { vectoangles2(tr.plane.normal, ang); self->ideal_yaw = ang[YAW] + 180; if (self->ideal_yaw > 360) { self->ideal_yaw -= 360; } M_ChangeYaw(self); return true; } return false; } void badarea_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { } edict_t * SpawnBadArea(vec3_t mins, vec3_t maxs, float lifespan, edict_t *owner) { edict_t *badarea; vec3_t origin; if (!owner) { return NULL; } VectorAdd(mins, maxs, origin); VectorScale(origin, 0.5, origin); VectorSubtract(maxs, origin, maxs); VectorSubtract(mins, origin, mins); badarea = G_Spawn(); VectorCopy(origin, badarea->s.origin); VectorCopy(maxs, badarea->maxs); VectorCopy(mins, badarea->mins); badarea->touch = badarea_touch; badarea->movetype = MOVETYPE_NONE; badarea->solid = SOLID_TRIGGER; badarea->classname = "bad_area"; gi.linkentity(badarea); if (lifespan) { badarea->think = G_FreeEdict; badarea->nextthink = level.time + lifespan; } badarea->owner = owner; return badarea; } edict_t * CheckForBadArea(edict_t *ent) { int i, num; edict_t *touch[MAX_EDICTS], *hit; vec3_t mins, maxs; if (!ent) { return NULL; } VectorAdd(ent->s.origin, ent->mins, mins); VectorAdd(ent->s.origin, ent->maxs, maxs); num = gi.BoxEdicts(mins, maxs, touch, MAX_EDICTS, AREA_TRIGGERS); /* be careful, it is possible to have an entity in this list removed before we get to it (killtriggered) */ for (i = 0; i < num; i++) { hit = touch[i]; if (!hit->inuse) { continue; } if (hit->touch == badarea_touch) { return hit; } } return NULL; } qboolean MarkTeslaArea(edict_t *self, edict_t *tesla) { vec3_t mins, maxs; edict_t *e; edict_t *tail; edict_t *area; if (!tesla || !self) { return false; } area = NULL; /* make sure this tesla doesn't have a bad area around it already... */ e = tesla->teamchain; tail = tesla; while (e) { tail = tail->teamchain; if (!strcmp(e->classname, "bad_area")) { return false; } e = e->teamchain; } /* see if we can grab the trigger directly */ if (tesla->teamchain && tesla->teamchain->inuse) { edict_t *trigger; trigger = tesla->teamchain; VectorCopy(trigger->absmin, mins); VectorCopy(trigger->absmax, maxs); if (tesla->air_finished) { area = SpawnBadArea(mins, maxs, tesla->air_finished, tesla); } else { area = SpawnBadArea(mins, maxs, tesla->nextthink, tesla); } } /* otherwise we just guess at how long it'll last. */ else { VectorSet(mins, -TESLA_DAMAGE_RADIUS, -TESLA_DAMAGE_RADIUS, tesla->mins[2]); VectorSet(maxs, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS); area = SpawnBadArea(mins, maxs, 30, tesla); } /* if we spawned a bad area, then link it to the tesla */ if (area) { tail->teamchain = area; } return true; } void PredictAim(edict_t *target, vec3_t start, float bolt_speed, qboolean eye_height, float offset, vec3_t aimdir, vec3_t aimpoint) { vec3_t dir, vec; float dist, time; if (!target || !target->inuse) { VectorCopy(vec3_origin, aimdir); return; } VectorSubtract(target->s.origin, start, dir); if (eye_height) { dir[2] += target->viewheight; } dist = VectorLength(dir); time = dist / bolt_speed; VectorMA(target->s.origin, time - offset, target->velocity, vec); if (eye_height) { vec[2] += target->viewheight; } if (aimdir) { VectorSubtract(vec, start, aimdir); VectorNormalize(aimdir); } if (aimpoint) { VectorCopy(vec, aimpoint); } } qboolean below(edict_t *self, edict_t *other) { vec3_t vec; float dot; vec3_t down; if (!self || !other) { return false; } VectorSubtract(other->s.origin, self->s.origin, vec); VectorNormalize(vec); VectorSet(down, 0, 0, -1); dot = DotProduct(vec, down); if (dot > 0.95) /* 18 degree arc below */ { return true; } return false; } void drawbbox(edict_t *self) { int lines[4][3] = { {1, 2, 4}, {1, 2, 7}, {1, 4, 5}, {2, 4, 7} }; if (!self) { return; } int starts[4] = {0, 3, 5, 6}; vec3_t pt[8]; int i, j, k; vec3_t coords[2]; vec3_t newbox; vec3_t f, r, u, dir; VectorCopy(self->absmin, coords[0]); VectorCopy(self->absmax, coords[1]); for (i = 0; i <= 1; i++) { for (j = 0; j <= 1; j++) { for (k = 0; k <= 1; k++) { pt[4 * i + 2 * j + k][0] = coords[i][0]; pt[4 * i + 2 * j + k][1] = coords[j][1]; pt[4 * i + 2 * j + k][2] = coords[k][2]; } } } for (i = 0; i <= 3; i++) { for (j = 0; j <= 2; j++) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DEBUGTRAIL); gi.WritePosition(pt[starts[i]]); gi.WritePosition(pt[lines[i][j]]); gi.multicast(pt[starts[i]], MULTICAST_ALL); } } vectoangles2(self->s.angles, dir); AngleVectors(dir, f, r, u); VectorMA(self->s.origin, 50, f, newbox); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DEBUGTRAIL); gi.WritePosition(self->s.origin); gi.WritePosition(newbox); gi.multicast(self->s.origin, MULTICAST_PVS); VectorClear(newbox); VectorMA(self->s.origin, 50, r, newbox); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DEBUGTRAIL); gi.WritePosition(self->s.origin); gi.WritePosition(newbox); gi.multicast(self->s.origin, MULTICAST_PVS); VectorClear(newbox); VectorMA(self->s.origin, 50, u, newbox); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_DEBUGTRAIL); gi.WritePosition(self->s.origin); gi.WritePosition(newbox); gi.multicast(self->s.origin, MULTICAST_PVS); VectorClear(newbox); } void M_MonsterDodge(edict_t *self, edict_t *attacker, float eta, trace_t *tr) { float r = random(); float height; qboolean ducker = false, dodger = false; if (!self || !attacker || !tr) { return; } /* this needs to be here since this can be called after the monster has "died" */ if (self->health < 1) { return; } if ((self->monsterinfo.duck) && (self->monsterinfo.unduck)) { ducker = true; } if ((self->monsterinfo.sidestep) && !(self->monsterinfo.aiflags & AI_STAND_GROUND)) { dodger = true; } if ((!ducker) && (!dodger)) { return; } if (!self->enemy) { self->enemy = attacker; FoundTarget(self); } if ((eta < 0.1) || (eta > 5)) { return; } /* skill level determination.. */ if (r > (0.25 * ((skill->value) + 1))) { return; } if (ducker) { height = self->absmax[2] - 32 - 1; /* the -1 is because the absmax is s.origin + maxs + 1 */ if ((!dodger) && ((tr->endpos[2] <= height) || (self->monsterinfo.aiflags & AI_DUCKED))) { return; } } else { height = self->absmax[2]; } if (dodger) { /* if we're already dodging, just finish the sequence, i.e. don't do anything else */ if (self->monsterinfo.aiflags & AI_DODGING) { return; } /* if we're ducking already, or the shot is at our knees */ if ((tr->endpos[2] <= height) || (self->monsterinfo.aiflags & AI_DUCKED)) { vec3_t right, diff; AngleVectors(self->s.angles, NULL, right, NULL); VectorSubtract(tr->endpos, self->s.origin, diff); if (DotProduct(right, diff) < 0) { self->monsterinfo.lefty = 0; } else { self->monsterinfo.lefty = 1; } /* if we are currently ducked, unduck */ if ((ducker) && (self->monsterinfo.aiflags & AI_DUCKED)) { self->monsterinfo.unduck(self); } self->monsterinfo.aiflags |= AI_DODGING; self->monsterinfo.attack_state = AS_SLIDING; /* call the monster specific code here */ self->monsterinfo.sidestep(self); return; } } if (ducker) { if (self->monsterinfo.next_duck_time > level.time) { return; } monster_done_dodge(self); /* set this prematurely; it doesn't hurt, and prevents extra iterations */ self->monsterinfo.aiflags |= AI_DUCKED; self->monsterinfo.duck(self, eta); } } void monster_duck_down(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_DUCKED; self->maxs[2] = self->monsterinfo.base_height - 32; self->takedamage = DAMAGE_YES; if (self->monsterinfo.duck_wait_time < level.time) { self->monsterinfo.duck_wait_time = level.time + 1; } gi.linkentity(self); } void monster_duck_hold(edict_t *self) { if (!self) { return; } if (level.time >= self->monsterinfo.duck_wait_time) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; } else { self->monsterinfo.aiflags |= AI_HOLD_FRAME; } } void monster_duck_up(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_DUCKED; self->maxs[2] = self->monsterinfo.base_height; self->takedamage = DAMAGE_AIM; self->monsterinfo.next_duck_time = level.time + DUCK_INTERVAL; gi.linkentity(self); } qboolean has_valid_enemy(edict_t *self) { if (!self) { return false; } if (!self->enemy) { return false; } if (!self->enemy->inuse) { return false; } if (self->enemy->health < 1) { return false; } return true; } void TargetTesla(edict_t *self, edict_t *tesla) { if ((!self) || (!tesla)) { return; } /* medic bails on healing things */ if (self->monsterinfo.aiflags & AI_MEDIC) { if (self->enemy) { cleanupHealTarget(self->enemy); } self->monsterinfo.aiflags &= ~AI_MEDIC; } /* store the player enemy in case we lose track of him. */ if (self->enemy && self->enemy->client) { self->monsterinfo.last_player_enemy = self->enemy; } if (self->enemy != tesla) { self->oldenemy = self->enemy; self->enemy = tesla; if (self->monsterinfo.attack) { if (self->health <= 0) { return; } self->monsterinfo.attack(self); } else { FoundTarget(self); } } } edict_t * PickCoopTarget(edict_t *self) { if (!self) { return NULL; } /* no more than 4 players in coop, so.. */ edict_t *targets[4]; int num_targets = 0, targetID; edict_t *ent; int player; /* if we're not in coop, this is a noop */ if (!coop || !coop->value) { return NULL; } memset(targets, 0, 4 * sizeof(edict_t *)); for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (visible(self, ent)) { targets[num_targets++] = ent; } } if (!num_targets) { return NULL; } /* get a number from 0 to (num_targets-1) */ targetID = (random() * (float)num_targets); /* just in case we got a 1.0 from random */ if (targetID == num_targets) { targetID--; } return targets[targetID]; } int CountPlayers(void) { edict_t *ent; int count = 0; int player; /* if we're not in coop, this is a noop */ if (!coop || !coop->value) { return 1; } for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } count++; } return count; } void monster_jump_start(edict_t *self) { if (!self) { return; } self->timestamp = level.time; } qboolean monster_jump_finished(edict_t *self) { if (!self) { return false; } if ((level.time - self->timestamp) > 3) { return true; } return false; } qboolean blind_rocket_ok (edict_t *self, vec3_t start, vec3_t right, vec3_t target, float ofs, vec3_t dir) { trace_t tr; vec3_t vec; if (!self) { return false; } tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT); /* since all traces have the same start point this only needs one check */ if (tr.startsolid) { return false; } if (!tr.allsolid && (tr.fraction >= 0.5f)) { return true; } VectorMA(target, -ofs, right, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); tr = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); if (!tr.allsolid && (tr.fraction >= 0.5f)) { return true; } VectorMA(target, ofs, right, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); tr = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); return !tr.allsolid && (tr.fraction >= 0.5f); } rogue-ROGUE_2_13/src/g_newdm.c000066400000000000000000000202611477320066100161640ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific deathmatch stuff. * * ======================================================================= */ #include "header/local.h" #include "monster/misc/player.h" #define IT_TYPE_MASK (IT_WEAPON | IT_AMMO | IT_POWERUP | IT_ARMOR | IT_KEY) dm_game_rt DMGame; extern qboolean Pickup_Health(edict_t *ent, edict_t *other); extern qboolean Pickup_Adrenaline(edict_t *ent, edict_t *other); extern qboolean Pickup_Armor(edict_t *ent, edict_t *other); extern qboolean Pickup_PowerArmor(edict_t *ent, edict_t *other); extern edict_t *Sphere_Spawn(edict_t *owner, int spawnflags); extern void ED_CallSpawn(edict_t *ent); void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir); void InitGameRules(void) { int gameNum; /* clear out the game rule structure before we start */ memset(&DMGame, 0, sizeof(dm_game_rt)); if (gamerules && gamerules->value) { gameNum = gamerules->value; switch (gameNum) { case RDM_TAG: DMGame.GameInit = Tag_GameInit; DMGame.PostInitSetup = Tag_PostInitSetup; DMGame.PlayerDeath = Tag_PlayerDeath; DMGame.Score = Tag_Score; DMGame.PlayerEffects = Tag_PlayerEffects; DMGame.DogTag = Tag_DogTag; DMGame.PlayerDisconnect = Tag_PlayerDisconnect; DMGame.ChangeDamage = Tag_ChangeDamage; break; /* reset gamerules if it's not a valid number */ default: gamerules->value = 0; break; } } /* if we're set up to play, initialize the game as needed. */ if (DMGame.GameInit) { DMGame.GameInit(); } } char * FindSubstituteItem(edict_t *ent) { int i; int itflags, myflags; float rnd; int count; int pick; gitem_t *it; /* there are only two classes of power armor, and we don't want to give out power screens. therefore, power shields should remain power shields. (powerscreens shouldn't be there at all...) */ if (ent->item->pickup == Pickup_PowerArmor) { return NULL; } /* health is special case */ if ((ent->item->pickup == Pickup_Health) || (ent->item->pickup == Pickup_Adrenaline)) { /* health pellets stay health pellets */ if (!strcmp(ent->classname, "item_health_small")) { return NULL; } rnd = random(); if (rnd < 0.6) { return "item_health"; } else if (rnd < 0.9) { return "item_health_large"; } else if (rnd < 0.99) { return "item_adrenaline"; } else { return "item_health_mega"; } } /* armor is also special case */ else if (ent->item->pickup == Pickup_Armor) { /* armor shards stay armor shards */ if (ent->item->tag == ARMOR_SHARD) { return NULL; } rnd = random(); if (rnd < 0.6) { return "item_armor_jacket"; } else if (rnd < 0.9) { return "item_armor_combat"; } else { return "item_armor_body"; } } /* we want to stay within the item class */ myflags = ent->item->flags & IT_TYPE_MASK; if ((myflags & IT_AMMO) && (myflags & IT_WEAPON)) { myflags = IT_AMMO; } count = 0; /* first pass, count the matching items */ it = itemlist; for (i = 0; i < game.num_items; i++, it++) { itflags = it->flags; if (!itflags || (itflags & IT_NOT_GIVEABLE)) { continue; } /* prox,grenades,etc should count as ammo. */ if ((itflags & IT_AMMO) && (itflags & IT_WEAPON)) { itflags = IT_AMMO; } /* don't respawn spheres if they're dmflag disabled. */ if ((int)dmflags->value & DF_NO_SPHERES) { if (!strcmp(ent->classname, "item_sphere_vengeance") || !strcmp(ent->classname, "item_sphere_hunter") || !strcmp(ent->classname, "item_spehre_defender")) { continue; } } if (((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke")) { continue; } if (((int)dmflags->value & DF_NO_MINES) && (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla"))) { continue; } if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK)) { count++; } } if (!count) { return NULL; } pick = ceil(random() * count); count = 0; /* second pass, pick one. */ it = itemlist; for (i = 0; i < game.num_items; i++, it++) { itflags = it->flags; if (!itflags || (itflags & IT_NOT_GIVEABLE)) { continue; } /* prox,grenades,etc should count as ammo. */ if ((itflags & IT_AMMO) && (itflags & IT_WEAPON)) { itflags = IT_AMMO; } if (((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke")) { continue; } if (((int)dmflags->value & DF_NO_MINES) && (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla"))) { continue; } if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK)) { count++; if (pick == count) { return it->classname; } } } return NULL; } edict_t * DoRandomRespawn(edict_t *ent) { edict_t *newEnt; char *classname; if (!ent) { return NULL; } classname = FindSubstituteItem(ent); if (classname == NULL) { return NULL; } gi.unlinkentity(ent); newEnt = G_Spawn(); newEnt->classname = classname; VectorCopy(ent->s.origin, newEnt->s.origin); VectorCopy(ent->s.old_origin, newEnt->s.old_origin); VectorCopy(ent->mins, newEnt->mins); VectorCopy(ent->maxs, newEnt->maxs); VectorSet(newEnt->gravityVector, 0, 0, -1); ED_CallSpawn(newEnt); newEnt->s.renderfx |= RF_IR_VISIBLE; return newEnt; } void PrecacheForRandomRespawn(void) { gitem_t *it; int i; int itflags; it = itemlist; for (i = 0; i < game.num_items; i++, it++) { itflags = it->flags; if (!itflags || (itflags & IT_NOT_GIVEABLE)) { continue; } PrecacheItem(it); } } void doppleganger_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage, vec3_t point) { edict_t *sphere; float dist; vec3_t dir; if (!self || !attacker) { return; } if ((self->enemy) && (self->enemy != self->teammaster)) { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); dist = VectorLength(dir); if (dist > 768) { sphere = Sphere_Spawn(self, SPHERE_HUNTER | SPHERE_DOPPLEGANGER); sphere->pain(sphere, attacker, 0, 0); } else { sphere = Sphere_Spawn(self, SPHERE_VENGEANCE | SPHERE_DOPPLEGANGER); sphere->pain(sphere, attacker, 0, 0); } } if (self->teamchain) { BecomeExplosion1(self->teamchain); } BecomeExplosion1(self); } void doppleganger_pain(edict_t *self, edict_t *other, float kick, int damage) { self->enemy = other; } void doppleganger_timeout(edict_t *self) { if (self->teamchain) { BecomeExplosion1(self->teamchain); } BecomeExplosion1(self); } void body_think(edict_t *self) { float r; if (fabsf(self->ideal_yaw - anglemod(self->s.angles[YAW])) < 2) { if (self->timestamp < level.time) { r = random(); if (r < 0.10) { self->ideal_yaw = random() * 350.0; self->timestamp = level.time + 1; } } } else { M_ChangeYaw(self); } self->s.frame++; if (self->s.frame > FRAME_stand40) { self->s.frame = FRAME_stand01; } self->nextthink = level.time + 0.1; } void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir) { edict_t *base; edict_t *body; vec3_t dir; vec3_t forward, right, up; int number; if (!ent) { return; } vectoangles2(aimdir, dir); AngleVectors(dir, forward, right, up); base = G_Spawn(); VectorCopy(start, base->s.origin); VectorCopy(dir, base->s.angles); VectorClear(base->velocity); VectorClear(base->avelocity); base->movetype = MOVETYPE_TOSS; base->solid = SOLID_BBOX; base->s.renderfx |= RF_IR_VISIBLE; base->s.angles[PITCH] = 0; VectorSet(base->mins, -16, -16, -24); VectorSet(base->maxs, 16, 16, 32); base->s.modelindex = 0; base->teammaster = ent; base->svflags |= SVF_DAMAGEABLE; base->takedamage = DAMAGE_AIM; base->health = 30; base->pain = doppleganger_pain; base->die = doppleganger_die; base->nextthink = level.time + 30; base->think = doppleganger_timeout; base->classname = "doppleganger"; gi.linkentity(base); body = G_Spawn(); number = body->s.number; body->s = ent->s; body->s.sound = 0; body->s.event = 0; body->s.number = number; body->yaw_speed = 30; body->ideal_yaw = 0; VectorCopy(start, body->s.origin); body->s.origin[2] += 8; body->think = body_think; body->nextthink = level.time + FRAMETIME; gi.linkentity(body); base->teamchain = body; body->teammaster = base; } rogue-ROGUE_2_13/src/g_newfnc.c000066400000000000000000000211471477320066100163360ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific level functions. * * ======================================================================= */ #include "header/local.h" void fd_secret_move1(edict_t *self); void fd_secret_move2(edict_t *self); void fd_secret_move3(edict_t *self); void fd_secret_move4(edict_t *self); void fd_secret_move5(edict_t *self); void fd_secret_move6(edict_t *self); void fd_secret_done(edict_t *self); void Move_Calc(edict_t *ent, vec3_t dest, void (*func)(edict_t *)); /* * ============================================================================= * * SECRET DOORS * * ============================================================================= */ #define SEC_OPEN_ONCE 1 /* stays open */ #define SEC_1ST_LEFT 2 /* 1st move is left of arrow */ #define SEC_1ST_DOWN 4 /* 1st move is down from arrow */ #define SEC_NO_SHOOT 8 /* only opened by trigger */ #define SEC_YES_SHOOT 16 /* shootable even if targeted */ #define SEC_MOVE_RIGHT 32 #define SEC_MOVE_FORWARD 64 void fd_secret_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { edict_t *ent; if (!self) { return; } if (self->flags & FL_TEAMSLAVE) { return; } /* trigger all paired doors */ for (ent = self; ent; ent = ent->teamchain) { Move_Calc(ent, ent->moveinfo.start_origin, fd_secret_move1); } } void fd_secret_killed(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { if (!self || !inflictor || !attacker) { return; } self->health = self->max_health; self->takedamage = DAMAGE_NO; if (self->flags & FL_TEAMSLAVE && self->teammaster && (self->teammaster->takedamage != DAMAGE_NO)) { fd_secret_killed(self->teammaster, inflictor, attacker, damage, point); } else { fd_secret_use(self, inflictor, attacker); } } void fd_secret_move1(edict_t *self) { if (!self) { return; } self->nextthink = level.time + 1.0; self->think = fd_secret_move2; } /* * Start moving sideways w/sound... */ void fd_secret_move2(edict_t *self) { if (!self) { return; } Move_Calc(self, self->moveinfo.end_origin, fd_secret_move3); } /* * Wait here until time to go back... */ void fd_secret_move3(edict_t *self) { if (!self) { return; } if (!(self->spawnflags & SEC_OPEN_ONCE)) { self->nextthink = level.time + self->wait; self->think = fd_secret_move4; } } /* * Move backward... */ void fd_secret_move4(edict_t *self) { if (!self) { return; } Move_Calc(self, self->moveinfo.start_origin, fd_secret_move5); } /* * Wait 1 second... */ void fd_secret_move5(edict_t *self) { if (!self) { return; } self->nextthink = level.time + 1.0; self->think = fd_secret_move6; } void fd_secret_move6(edict_t *self) { if (!self) { return; } Move_Calc(self, self->move_origin, fd_secret_done); } void fd_secret_done(edict_t *self) { if (!self) { return; } if (!self->targetname || self->spawnflags & SEC_YES_SHOOT) { self->health = 1; self->takedamage = DAMAGE_YES; self->die = fd_secret_killed; } } void secret_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (!(self->flags & FL_TEAMSLAVE)) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 0, 0, MOD_CRUSH); } } /* * Prints messages */ void secret_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (other->health <= 0) { return; } if (!(other->client)) { return; } if (self->monsterinfo.attack_finished > level.time) { return; } self->monsterinfo.attack_finished = level.time + 2; if (self->message) { gi.centerprintf(other, self->message); } } /* * QUAKED func_door_secret2 (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot slide_right slide_forward * * Basic secret door. Slides back, then to the left. Angle determines direction. * * FLAGS: * open_once = not implemented yet * 1st_left = 1st move is left/right of arrow * 1st_down = 1st move is forwards/backwards * no_shoot = not implemented yet * always_shoot = even if targeted, keep shootable * reverse_left = the sideways move will be to right of arrow * reverse_back = the to/fro move will be forward * * VALUES: * wait = # of seconds before coming back (5 default) * dmg = damage to inflict when blocked (2 default) */ void SP_func_door_secret2(edict_t *ent) { vec3_t forward, right, up; float lrSize = 0, fbSize = 0; if (!ent) { return; } ent->moveinfo.sound_start = gi.soundindex("doors/dr1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex("doors/dr1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex("doors/dr1_end.wav"); if (!ent->dmg) { ent->dmg = 2; } AngleVectors(ent->s.angles, forward, right, up); VectorCopy(ent->s.origin, ent->move_origin); VectorCopy(ent->s.angles, ent->move_angles); G_SetMovedir(ent->s.angles, ent->movedir); ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; gi.setmodel(ent, ent->model); if ((ent->move_angles[1] == 0) || (ent->move_angles[1] == 180)) { lrSize = ent->size[1]; fbSize = ent->size[0]; } else if ((ent->move_angles[1] == 90) || (ent->move_angles[1] == 270)) { lrSize = ent->size[0]; fbSize = ent->size[1]; } else { gi.dprintf("Secret door not at 0,90,180,270!\n"); } if (ent->spawnflags & SEC_MOVE_FORWARD) { VectorScale(forward, fbSize, forward); } else { VectorScale(forward, fbSize * -1, forward); } if (ent->spawnflags & SEC_MOVE_RIGHT) { VectorScale(right, lrSize, right); } else { VectorScale(right, lrSize * -1, right); } if (ent->spawnflags & SEC_1ST_DOWN) { VectorAdd(ent->s.origin, forward, ent->moveinfo.start_origin); VectorAdd(ent->moveinfo.start_origin, right, ent->moveinfo.end_origin); } else { VectorAdd(ent->s.origin, right, ent->moveinfo.start_origin); VectorAdd(ent->moveinfo.start_origin, forward, ent->moveinfo.end_origin); } ent->touch = secret_touch; ent->blocked = secret_blocked; ent->use = fd_secret_use; ent->moveinfo.speed = 50; ent->moveinfo.accel = 50; ent->moveinfo.decel = 50; if (!ent->targetname || ent->spawnflags & SEC_YES_SHOOT) { ent->health = 1; ent->max_health = ent->health; ent->takedamage = DAMAGE_YES; ent->die = fd_secret_killed; } if (!ent->wait) { ent->wait = 5; /* 5 seconds before closing */ } gi.linkentity(ent); } /* ================================================== */ #define FWALL_START_ON 1 void force_wall_think(edict_t *self) { if (!self) { return; } if (!self->wait) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_FORCEWALL); gi.WritePosition(self->pos1); gi.WritePosition(self->pos2); gi.WriteByte(self->style); gi.multicast(self->offset, MULTICAST_PVS); } self->think = force_wall_think; self->nextthink = level.time + 0.1; } void force_wall_use(edict_t *self, edict_t *other /* activator */, edict_t *activator /* activator */) { if (!self) { return; } if (!self->wait) { self->wait = 1; self->think = NULL; self->nextthink = 0; self->solid = SOLID_NOT; gi.linkentity(self); } else { self->wait = 0; self->think = force_wall_think; self->nextthink = level.time + 0.1; self->solid = SOLID_BSP; KillBox(self); /* Is this appropriate? */ gi.linkentity(self); } } /* * QUAKED func_force_wall (1 0 1) ? start_on * * A vertical particle force wall. Turns on and solid when triggered. * If someone is in the force wall when it turns on, they're telefragged. * * start_on - forcewall begins activated. triggering will turn it off. * style - color of particles to use. * 208: green, 240: red, 241: blue, 224: orange */ void SP_func_force_wall(edict_t *ent) { if (!ent) { return; } gi.setmodel(ent, ent->model); ent->offset[0] = (ent->absmax[0] + ent->absmin[0]) / 2; ent->offset[1] = (ent->absmax[1] + ent->absmin[1]) / 2; ent->offset[2] = (ent->absmax[2] + ent->absmin[2]) / 2; ent->pos1[2] = ent->absmax[2]; ent->pos2[2] = ent->absmax[2]; if (ent->size[0] > ent->size[1]) { ent->pos1[0] = ent->absmin[0]; ent->pos2[0] = ent->absmax[0]; ent->pos1[1] = ent->offset[1]; ent->pos2[1] = ent->offset[1]; } else { ent->pos1[0] = ent->offset[0]; ent->pos2[0] = ent->offset[0]; ent->pos1[1] = ent->absmin[1]; ent->pos2[1] = ent->absmax[1]; } if (!ent->style) { ent->style = 208; } ent->movetype = MOVETYPE_NONE; ent->wait = 1; if (ent->spawnflags & FWALL_START_ON) { ent->solid = SOLID_BSP; ent->think = force_wall_think; ent->nextthink = level.time + 0.1; } else { ent->solid = SOLID_NOT; } ent->use = force_wall_use; ent->svflags = SVF_NOCLIENT; gi.linkentity(ent); } rogue-ROGUE_2_13/src/g_newtarg.c000066400000000000000000000167661477320066100165400ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific targets. * * ======================================================================= */ #include "header/local.h" /* * QUAKED target_steam (1 0 0) (-8 -8 -8) (8 8 8) * Creates a steam effect (particles w/ velocity in a line). * * speed = velocity of particles (default 50) * count = number of particles (default 32) * sounds = color of particles (default 8 for steam) * the color range is from this color to this color + 6 * wait = seconds to run before stopping (overrides default * value derived from func_timer) * * best way to use this is to tie it to a func_timer that "pokes" * it every second (or however long you set the wait time, above) * * note that the width of the base is proportional to the speed * good colors to use: * 6-9 - varying whites (darker to brighter) * 224 - sparks * 176 - blue water * 80 - brown water * 208 - slime * 232 - blood */ void use_target_steam(edict_t *self, edict_t *other, edict_t *activator /* unused */) { static int nextid; vec3_t point; if (!self) { return; } if (nextid > 20000) { nextid = nextid % 20000; } nextid++; /* automagically set wait from func_timer unless they set it already, or default to 1000 if not called by a func_timer */ if (!self->wait) { if (other) { self->wait = other->wait * 1000; } else { self->wait = 1000; } } if (self->enemy) { VectorMA(self->enemy->absmin, 0.5, self->enemy->size, point); VectorSubtract(point, self->s.origin, self->movedir); VectorNormalize(self->movedir); } VectorMA(self->s.origin, self->plat2flags * 0.5, self->movedir, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_STEAM); if (self->wait > 100) { gi.WriteShort(nextid); gi.WriteByte(self->count); gi.WritePosition(self->s.origin); gi.WriteDir(self->movedir); gi.WriteByte(self->sounds & 0xff); gi.WriteShort((short int)(self->plat2flags)); gi.WriteLong((int)(self->wait)); } else { gi.WriteShort((short int)-1); gi.WriteByte(self->count); gi.WritePosition(self->s.origin); gi.WriteDir(self->movedir); gi.WriteByte(self->sounds & 0xff); gi.WriteShort((short int)(self->plat2flags)); } gi.multicast(self->s.origin, MULTICAST_PVS); } void target_steam_start(edict_t *self) { edict_t *ent; if (!self) { return; } self->use = use_target_steam; if (self->target) { ent = G_Find(NULL, FOFS(targetname), self->target); if (!ent) { gi.dprintf("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); } self->enemy = ent; } else { G_SetMovedir(self->s.angles, self->movedir); } if (!self->count) { self->count = 32; } if (!self->plat2flags) { self->plat2flags = 75; } if (!self->sounds) { self->sounds = 8; } if (self->wait) { self->wait *= 1000; /* we want it in milliseconds, not seconds */ } /* paranoia is good */ self->sounds &= 0xff; self->count &= 0xff; self->svflags = SVF_NOCLIENT; gi.linkentity(self); } void SP_target_steam(edict_t *self) { self->plat2flags = self->speed; if (self->target) { self->think = target_steam_start; self->nextthink = level.time + 1; } else { target_steam_start(self); } } void target_anger_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { edict_t *target; edict_t *t; if (!self) { return; } t = NULL; target = G_Find(t, FOFS(targetname), self->killtarget); if (target && self->target) { /* Make whatever a "good guy" so the monster will try to kill it! */ target->monsterinfo.aiflags |= AI_GOOD_GUY; target->svflags |= SVF_MONSTER; target->health = 300; t = NULL; while ((t = G_Find(t, FOFS(targetname), self->target))) { if (t == self) { gi.dprintf("WARNING: entity used itself.\n"); } else { if (t->use) { if (t->health < 0) { return; } t->enemy = target; t->monsterinfo.aiflags |= AI_TARGET_ANGER; FoundTarget(t); } } if (!self->inuse) { gi.dprintf("entity was removed while using targets\n"); return; } } } } /* * QUAKED target_anger (1 0 0) (-8 -8 -8) (8 8 8) * * This trigger will cause an entity to be angry at another entity when a player touches it. * Target the entity you want to anger, and killtarget the entity you want it to be angry at. * * target - entity to piss off * killtarget - entity to be pissed off at */ void SP_target_anger(edict_t *self) { if (!self) { return; } if (!self->target) { gi.dprintf("target_anger without target!\n"); G_FreeEdict(self); return; } if (!self->killtarget) { gi.dprintf("target_anger without killtarget!\n"); G_FreeEdict(self); return; } self->use = target_anger_use; self->svflags = SVF_NOCLIENT; } void target_killplayers_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { int i; edict_t *ent, *player; if (!self) { return; } /* kill the players */ for (i = 0; i < game.maxclients; i++) { player = &g_edicts[1 + i]; if (!player->inuse) { continue; } /* nail it */ T_Damage(player, self, self, vec3_origin, self->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); } /* kill any visible monsters */ for (ent = g_edicts; ent < &g_edicts[globals.num_edicts]; ent++) { if (!ent->inuse) { continue; } if (ent->health < 1) { continue; } if (!ent->takedamage) { continue; } for (i = 0; i < game.maxclients; i++) { player = &g_edicts[1 + i]; if (!player->inuse) { continue; } if (visible(player, ent)) { T_Damage(ent, self, self, vec3_origin, ent->s.origin, vec3_origin, ent->health, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); break; } } } } /* * QUAKED target_killplayers (1 0 0) (-8 -8 -8) (8 8 8) * * When triggered, this will kill all the players on the map. */ void SP_target_killplayers(edict_t *self) { if (!self) { return; } self->use = target_killplayers_use; self->svflags = SVF_NOCLIENT; } /* * QUAKED target_blacklight (1 0 1) (-16 -16 -24) (16 16 24) * * Pulsing black light with sphere in the center */ void blacklight_think(edict_t *self) { if (!self) { return; } self->s.angles[0] = rand() % 360; self->s.angles[1] = rand() % 360; self->s.angles[2] = rand() % 360; self->nextthink = level.time + 0.1; } void SP_target_blacklight(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } VectorClear(ent->mins); VectorClear(ent->maxs); ent->s.effects |= (EF_TRACKERTRAIL | EF_TRACKER); ent->think = blacklight_think; ent->s.modelindex = gi.modelindex("models/items/spawngro2/tris.md2"); ent->s.frame = 1; ent->nextthink = level.time + 0.1; gi.linkentity(ent); } /* * QUAKED target_orb (1 0 1) (-16 -16 -24) (16 16 24) * * Translucent pulsing orb with speckles */ void orb_think(edict_t *self) { if (!self) { return; } self->s.angles[0] = rand() % 360; self->s.angles[1] = rand() % 360; self->s.angles[2] = rand() % 360; self->nextthink = level.time + 0.1; } void SP_target_orb(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } VectorClear(ent->mins); VectorClear(ent->maxs); ent->think = orb_think; ent->nextthink = level.time + 0.1; ent->s.modelindex = gi.modelindex("models/items/spawngro2/tris.md2"); ent->s.frame = 2; ent->s.effects |= EF_SPHERETRANS; gi.linkentity(ent); } rogue-ROGUE_2_13/src/g_newtrig.c000066400000000000000000000110231477320066100165250ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific triggers. * * ======================================================================= */ #include "header/local.h" #define TELEPORT_PLAYER_ONLY 1 #define TELEPORT_SILENT 2 #define TELEPORT_CTF_ONLY 4 #define TELEPORT_START_ON 8 extern void TeleportEffect(vec3_t origin); /* * QUAKED info_teleport_destination (.5 .5 .5) (-16 -16 -24) (16 16 32) * * Destination marker for a teleporter. */ void SP_info_teleport_destination(edict_t *self) { } /* * QUAKED trigger_teleport (.5 .5 .5) ? player_only silent ctf_only start_on * * Any object touching this will be transported to the corresponding * info_teleport_destination entity. You must set the "target" field, * and create an object with a "targetname" field that matches. * * If the trigger_teleport has a targetname, it will only teleport * entities when it has been fired. * * player_only: only players are teleported * silent: * ctf_only: * start_on: when trigger has targetname, start active, deactivate when used. */ void trigger_teleport_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { edict_t *dest; int i; if (!self || !other) { return; } if (!(other->client)) { return; } if (self->delay) { return; } dest = G_Find(NULL, FOFS(targetname), self->target); if (!dest) { gi.dprintf("Teleport Destination not found!\n"); return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_TELEPORT_EFFECT); gi.WritePosition(other->s.origin); gi.multicast(other->s.origin, MULTICAST_PVS); /* unlink to make sure it can't possibly interfere with KillBox */ gi.unlinkentity(other); VectorCopy(dest->s.origin, other->s.origin); VectorCopy(dest->s.origin, other->s.old_origin); other->s.origin[2] += 10; /* clear the velocity and hold them in place briefly */ VectorClear(other->velocity); if (other->client) { other->client->ps.pmove.pm_time = 160 >> 3; /* hold time */ other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; /* draw the teleport splash at source and on the player */ other->s.event = EV_PLAYER_TELEPORT; /* set angles */ for (i = 0; i < 3; i++) { other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT( dest->s.angles[i] - other->client->resp.cmd_angles[i]); } VectorClear(other->client->ps.viewangles); VectorClear(other->client->v_angle); } VectorClear(other->s.angles); /* kill anything at the destination */ KillBox(other); gi.linkentity(other); } void trigger_teleport_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->delay) { self->delay = 0; } else { self->delay = 1; } } void SP_trigger_teleport(edict_t *self) { if (!self) { return; } if (!self->wait) { self->wait = 0.2; } self->delay = 0; if (self->targetname) { self->use = trigger_teleport_use; if (!(self->spawnflags & TELEPORT_START_ON)) { self->delay = 1; } } self->touch = trigger_teleport_touch; self->solid = SOLID_TRIGGER; self->movetype = MOVETYPE_NONE; if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } gi.setmodel(self, self->model); gi.linkentity(self); } /* * QUAKED trigger_disguise (.5 .5 .5) ? TOGGLE START_ON REMOVE * * Anything passing through this trigger when it is active will * be marked as disguised. * * TOGGLE - field is turned off and on when used. * START_ON - field is active when spawned. * REMOVE - field removes the disguise */ void trigger_disguise_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (other->client) { if (self->spawnflags & 4) { other->flags &= ~FL_DISGUISED; } else { other->flags |= FL_DISGUISED; } } } void trigger_disguise_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->solid == SOLID_NOT) { self->solid = SOLID_TRIGGER; } else { self->solid = SOLID_NOT; } gi.linkentity(self); } void SP_trigger_disguise(edict_t *self) { if (!self) { return; } if (self->spawnflags & 2) { self->solid = SOLID_TRIGGER; } else { self->solid = SOLID_NOT; } self->touch = trigger_disguise_touch; self->use = trigger_disguise_use; self->movetype = MOVETYPE_NONE; self->svflags = SVF_NOCLIENT; gi.setmodel(self, self->model); gi.linkentity(self); } rogue-ROGUE_2_13/src/g_newweap.c000066400000000000000000001153241477320066100165250ustar00rootroot00000000000000/* * ======================================================================= * * Rogue specific weapons. * * ======================================================================= */ #include "header/local.h" #define NUKE_DELAY 4 #define NUKE_TIME_TO_LIVE 6 #define NUKE_RADIUS 512 #define NUKE_DAMAGE 400 #define NUKE_QUAKE_TIME 3 #define NUKE_QUAKE_STRENGTH 100 #define PROX_TIME_TO_LIVE 45 #define PROX_TIME_DELAY 0.5 #define PROX_BOUND_SIZE 96 #define PROX_DAMAGE_RADIUS 192 #define PROX_HEALTH 20 #define PROX_DAMAGE 90 #define TESLA_TIME_TO_LIVE 30 #define TESLA_DAMAGE_RADIUS 128 #define TESLA_DAMAGE 3 #define TESLA_KNOCKBACK 8 #define TESLA_ACTIVATE_TIME 3 #define TESLA_EXPLOSION_DAMAGE_MULT 50 #define TESLA_EXPLOSION_RADIUS 200 #define TRACKER_DAMAGE_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY | DAMAGE_NO_KNOCKBACK) #define TRACKER_IMPACT_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY) #define TRACKER_DAMAGE_TIME 0.5 extern byte P_DamageModifier(edict_t *ent); extern void check_dodge(edict_t *self, vec3_t start, vec3_t dir, int speed); extern void hurt_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); extern void droptofloor(edict_t *ent); extern void Grenade_Explode(edict_t *ent); extern void drawbbox(edict_t *ent); void flechette_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t dir; vec3_t normal; if (!self || !other) { return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } get_normal_vector(plane, normal); if (other->takedamage) { T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg, self->dmg_radius, DAMAGE_NO_REG_ARMOR, MOD_ETF_RIFLE); } else { VectorScale(normal, 256, dir); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_FLECHETTE); gi.WritePosition(self->s.origin); gi.WriteDir(dir); gi.multicast(self->s.origin, MULTICAST_PVS); } G_FreeEdict(self); } void fire_flechette(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick) { edict_t *flechette; if (!self) { return; } VectorNormalize(dir); flechette = G_Spawn(); VectorCopy(start, flechette->s.origin); VectorCopy(start, flechette->s.old_origin); vectoangles2(dir, flechette->s.angles); VectorScale(dir, speed, flechette->velocity); flechette->movetype = MOVETYPE_FLYMISSILE; flechette->clipmask = MASK_SHOT; flechette->solid = SOLID_BBOX; flechette->s.renderfx = RF_FULLBRIGHT; VectorClear(flechette->mins); VectorClear(flechette->maxs); flechette->s.modelindex = gi.modelindex("models/proj/flechette/tris.md2"); flechette->owner = self; flechette->touch = flechette_touch; flechette->nextthink = level.time + (8000.0f / (float)speed); flechette->think = G_FreeEdict; flechette->dmg = damage; flechette->dmg_radius = kick; gi.linkentity(flechette); if (self->client) { check_dodge(self, flechette->s.origin, dir, speed); } } void Prox_Explode(edict_t *ent) { vec3_t origin; edict_t *owner; if (!ent) { return; } /* free the trigger field */ if (ent->teamchain && (ent->teamchain->owner == ent)) { G_FreeEdict(ent->teamchain); } owner = ent; if (ent->teammaster) { owner = ent->teammaster; PlayerNoise(owner, ent->s.origin, PNOISE_IMPACT); } /* play double/quad sound if appopriate */ if (ent->dmg >= (PROX_DAMAGE * 4)) { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (ent->dmg == (PROX_DAMAGE * 2)) { gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } ent->takedamage = DAMAGE_NO; T_RadiusDamage(ent, owner, ent->dmg, ent, PROX_DAMAGE_RADIUS, MOD_PROX); VectorMA(ent->s.origin, -0.02, ent->velocity, origin); gi.WriteByte(svc_temp_entity); if (ent->groundentity) { gi.WriteByte(TE_GRENADE_EXPLOSION); } else { gi.WriteByte(TE_ROCKET_EXPLOSION); } gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PVS); G_FreeEdict(ent); } void prox_die(edict_t *self, edict_t *inflictor, edict_t *attacker /* unused */, int damage, vec3_t point) { if (!self || !inflictor) { return; } if (strcmp(inflictor->classname, "prox")) { self->takedamage = DAMAGE_NO; Prox_Explode(self); } else { self->takedamage = DAMAGE_NO; self->think = Prox_Explode; self->nextthink = level.time + FRAMETIME; } } void Prox_Field_Touch(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { edict_t *prox; if (!ent || !other) { return; } if (!(other->svflags & SVF_MONSTER) && !other->client) { return; } /* trigger the prox mine if it's still there, and still mine. */ prox = ent->owner; if (other == prox) /* don't set self off */ { return; } if (prox->think == Prox_Explode) /* we're set to blow! */ { return; } if (prox->teamchain == ent) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); prox->think = Prox_Explode; prox->nextthink = level.time + PROX_TIME_DELAY; return; } ent->solid = SOLID_NOT; G_FreeEdict(ent); } void prox_seek(edict_t *ent) { if (!ent) { return; } if (level.time > ent->wait) { Prox_Explode(ent); } else { ent->s.frame++; if (ent->s.frame > 13) { ent->s.frame = 9; } ent->think = prox_seek; ent->nextthink = level.time + 0.1; } } void prox_open(edict_t *ent) { edict_t *search; if (!ent) { return; } search = NULL; if (ent->s.frame == 9) /* end of opening animation */ { /* set the owner to NULL so the owner can shoot it, etc. needs to be done here so the owner doesn't get stuck on it while it's opening if fired at point blank wall */ ent->s.sound = 0; ent->owner = NULL; if (ent->teamchain) { ent->teamchain->touch = Prox_Field_Touch; } while ((search = findradius(search, ent->s.origin, PROX_DAMAGE_RADIUS + 10)) != NULL) { if (!search->classname) /* tag token and other weird shit */ { continue; } /* if it's a monster or player with health > 0 or it's a player start point and we can see it blow up */ if (((((search->svflags & SVF_MONSTER) || (search->client)) && (search->health > 0)) || ((deathmatch->value) &&((!strcmp(search->classname, "info_player_deathmatch")) || (!strcmp(search->classname, "info_player_start")) || (!strcmp(search->classname, "info_player_coop")) || (!strcmp(search->classname, "misc_teleporter_dest"))))) && (visible(search, ent))) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); Prox_Explode(ent); return; } } if (strong_mines && (strong_mines->value)) { ent->wait = level.time + PROX_TIME_TO_LIVE; } else { switch (ent->dmg / PROX_DAMAGE) { case 1: ent->wait = level.time + PROX_TIME_TO_LIVE; break; case 2: ent->wait = level.time + 30; break; case 4: ent->wait = level.time + 15; break; case 8: ent->wait = level.time + 10; break; default: ent->wait = level.time + PROX_TIME_TO_LIVE; break; } } ent->think = prox_seek; ent->nextthink = level.time + 0.2; } else { if (ent->s.frame == 0) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxopen.wav"), 1, ATTN_NORM, 0); } ent->s.frame++; ent->think = prox_open; ent->nextthink = level.time + 0.05; } } void prox_land(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { edict_t *field; vec3_t dir; vec3_t normal; vec3_t forward, right, up; int movetype = MOVETYPE_NONE; int stick_ok = 0; vec3_t land_point; if (!ent || !other) { return; } /* must turn off owner so owner can shoot it and set it off moved to prox_open so owner can get away from it if fired at pointblank range into wall */ if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(ent); return; } get_normal_vector(plane, normal); VectorMA(ent->s.origin, -10.0, normal, land_point); if (gi.pointcontents(land_point) & (CONTENTS_SLIME | CONTENTS_LAVA)) { Prox_Explode(ent); return; } if ((other->svflags & (SVF_MONSTER|SVF_DAMAGEABLE)) || other->client) { if (other != ent->teammaster) { Prox_Explode(ent); } return; } #define STOP_EPSILON 0.1 else if (other != world) { /* Here we need to check to see if we can stop on this entity. */ vec3_t out; float backoff, change; int i; if ((other->movetype == MOVETYPE_PUSH) && (normal[2] > 0.7)) { stick_ok = 1; } else { stick_ok = 0; } backoff = DotProduct(ent->velocity, normal) * 1.5; for (i = 0; i < 3; i++) { change = normal[i] * backoff; out[i] = ent->velocity[i] - change; if ((out[i] > -STOP_EPSILON) && (out[i] < STOP_EPSILON)) { out[i] = 0; } } if (out[2] > 60) { return; } movetype = MOVETYPE_BOUNCE; /* if we're here, we're going to stop on an entity */ if (stick_ok) { /* it's a happy entity */ VectorCopy(vec3_origin, ent->velocity); VectorCopy(vec3_origin, ent->avelocity); } else /* no-stick. teflon time */ { if (normal[2] > 0.7) { Prox_Explode(ent); return; } return; } } else if (other->s.modelindex != 1) { return; } vectoangles2(normal, dir); AngleVectors(dir, forward, right, up); if (gi.pointcontents(ent->s.origin) & (CONTENTS_LAVA | CONTENTS_SLIME)) { Prox_Explode(ent); return; } field = G_Spawn(); VectorCopy(ent->s.origin, field->s.origin); VectorClear(field->velocity); VectorClear(field->avelocity); VectorSet(field->mins, -PROX_BOUND_SIZE, -PROX_BOUND_SIZE, -PROX_BOUND_SIZE); VectorSet(field->maxs, PROX_BOUND_SIZE, PROX_BOUND_SIZE, PROX_BOUND_SIZE); field->movetype = MOVETYPE_NONE; field->solid = SOLID_TRIGGER; field->owner = ent; field->classname = "prox_field"; field->teammaster = ent; gi.linkentity(field); VectorClear(ent->velocity); VectorClear(ent->avelocity); /* rotate to vertical */ dir[PITCH] = dir[PITCH] + 90; VectorCopy(dir, ent->s.angles); ent->takedamage = DAMAGE_AIM; ent->movetype = movetype; /* either bounce or none, depending on whether we stuck to something */ ent->die = prox_die; ent->teamchain = field; ent->health = PROX_HEALTH; ent->nextthink = level.time + 0.05; ent->think = prox_open; ent->touch = NULL; ent->solid = SOLID_BBOX; /* record who we're attached to */ gi.linkentity(ent); } void fire_prox(edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed) { edict_t *prox; vec3_t dir; vec3_t forward, right, up; if (!self) { return; } vectoangles2(aimdir, dir); AngleVectors(dir, forward, right, up); prox = G_Spawn(); VectorCopy(start, prox->s.origin); VectorScale(aimdir, speed, prox->velocity); VectorMA(prox->velocity, 200 + crandom() * 10.0, up, prox->velocity); VectorMA(prox->velocity, crandom() * 10.0, right, prox->velocity); VectorCopy(dir, prox->s.angles); prox->s.angles[PITCH] -= 90; prox->movetype = MOVETYPE_BOUNCE; prox->solid = SOLID_BBOX; prox->s.effects |= EF_GRENADE; prox->clipmask = MASK_SHOT | CONTENTS_LAVA | CONTENTS_SLIME; prox->s.renderfx |= RF_IR_VISIBLE; VectorSet(prox->mins, -6, -6, -6); VectorSet(prox->maxs, 6, 6, 6); prox->s.modelindex = gi.modelindex("models/weapons/g_prox/tris.md2"); prox->owner = self; prox->teammaster = self; prox->touch = prox_land; prox->think = Prox_Explode; prox->dmg = PROX_DAMAGE * damage_multiplier; prox->classname = "prox"; prox->svflags |= SVF_DAMAGEABLE; prox->flags |= FL_MECHANICAL; switch (damage_multiplier) { case 1: prox->nextthink = level.time + PROX_TIME_TO_LIVE; break; case 2: prox->nextthink = level.time + 30; break; case 4: prox->nextthink = level.time + 15; break; case 8: prox->nextthink = level.time + 10; break; default: prox->nextthink = level.time + PROX_TIME_TO_LIVE; break; } gi.linkentity(prox); } void fire_player_melee(edict_t *self, vec3_t start, vec3_t aim, int reach, int damage, int kick, int quiet, int mod) { vec3_t forward, right, up; vec3_t v; vec3_t point; trace_t tr; if (!self) { return; } vectoangles2(aim, v); AngleVectors(v, forward, right, up); VectorNormalize(forward); VectorMA(start, reach, forward, point); /* see if the hit connects */ tr = gi.trace(start, NULL, NULL, point, self, MASK_SHOT); if (tr.fraction == 1.0) { if (!quiet) { gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/swish.wav"), 1, ATTN_NORM, 0); } return; } if ((tr.ent->takedamage == DAMAGE_YES) || (tr.ent->takedamage == DAMAGE_AIM)) { /* pull the player forward if you do damage */ VectorMA(self->velocity, 75, forward, self->velocity); VectorMA(self->velocity, 75, up, self->velocity); /* do the damage */ if (mod == MOD_CHAINFIST) { T_Damage(tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, damage, kick / 2, DAMAGE_DESTROY_ARMOR | DAMAGE_NO_KNOCKBACK, mod); } else { T_Damage(tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, damage, kick / 2, DAMAGE_NO_KNOCKBACK, mod); } if (!quiet) { gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/meatht.wav"), 1, ATTN_NORM, 0); } } else { if (!quiet) { gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/tink1.wav"), 1, ATTN_NORM, 0); } VectorScale(tr.plane.normal, 256, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_GUNSHOT); gi.WritePosition(tr.endpos); gi.WriteDir(point); gi.multicast(tr.endpos, MULTICAST_PVS); } } void Nuke_Quake(edict_t *self) { int i; edict_t *e; if (!self) { return; } if (self->last_move_time < level.time) { gi.positioned_sound(self->s.origin, self, CHAN_AUTO, self->noise_index, 0.75, ATTN_NONE, 0); self->last_move_time = level.time + 0.5; } for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) { continue; } if (!e->client) { continue; } if (!e->groundentity) { continue; } e->groundentity = NULL; e->velocity[0] += crandom() * 150; e->velocity[1] += crandom() * 150; e->velocity[2] = self->speed * (100.0 / e->mass); } if (level.time < self->timestamp) { self->nextthink = level.time + FRAMETIME; } else { G_FreeEdict(self); } } void Nuke_Explode(edict_t *ent) { if (!ent) { return; } if (ent->teammaster->client) { PlayerNoise(ent->teammaster, ent->s.origin, PNOISE_IMPACT); } T_RadiusNukeDamage(ent, ent->teammaster, ent->dmg, ent, ent->dmg_radius, MOD_NUKE); if (ent->dmg >= (NUKE_DAMAGE * 4)) { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (ent->dmg == (NUKE_DAMAGE * 2)) { gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/grenlx1a.wav"), 1, ATTN_NONE, 0); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1_BIG); gi.WritePosition(ent->s.origin); gi.multicast(ent->s.origin, MULTICAST_PVS); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_NUKEBLAST); gi.WritePosition(ent->s.origin); gi.multicast(ent->s.origin, MULTICAST_ALL); /* become a quake */ ent->svflags |= SVF_NOCLIENT; ent->noise_index = gi.soundindex("world/rumble.wav"); ent->think = Nuke_Quake; ent->speed = NUKE_QUAKE_STRENGTH; ent->timestamp = level.time + NUKE_QUAKE_TIME; ent->nextthink = level.time + FRAMETIME; ent->last_move_time = 0; } void nuke_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, int damage, vec3_t point) { if (!self) { return; } self->takedamage = DAMAGE_NO; if ((attacker) && !(strcmp(attacker->classname, "nuke"))) { G_FreeEdict(self); return; } Nuke_Explode(self); } void Nuke_Think(edict_t *ent) { float attenuation, default_atten = 1.8; int damage_multiplier, muzzleflash; if (!ent) { return; } damage_multiplier = ent->dmg / NUKE_DAMAGE; switch (damage_multiplier) { case 1: attenuation = default_atten / 1.4; muzzleflash = MZ_NUKE1; break; case 2: attenuation = default_atten / 2.0; muzzleflash = MZ_NUKE2; break; case 4: attenuation = default_atten / 3.0; muzzleflash = MZ_NUKE4; break; case 8: attenuation = default_atten / 5.0; muzzleflash = MZ_NUKE8; break; default: attenuation = default_atten; muzzleflash = MZ_NUKE1; break; } if (ent->wait < level.time) { Nuke_Explode(ent); } else if (level.time >= (ent->wait - NUKE_TIME_TO_LIVE)) { ent->s.frame++; if (ent->s.frame > 11) { ent->s.frame = 6; } if (gi.pointcontents(ent->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA)) { Nuke_Explode(ent); return; } ent->think = Nuke_Think; ent->nextthink = level.time + 0.1; ent->health = 1; ent->owner = NULL; gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(muzzleflash); gi.multicast(ent->s.origin, MULTICAST_PVS); if (ent->timestamp <= level.time) { if ((ent->wait - level.time) <= (NUKE_TIME_TO_LIVE / 2.0)) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 0.3; } else { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 0.5; } } } else { if (ent->timestamp <= level.time) { gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 1.0; } ent->nextthink = level.time + FRAMETIME; } } void nuke_bounce(edict_t *ent, edict_t *other /* unused */, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!ent) { return; } if (random() > 0.5) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); } else { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); } } void fire_nuke(edict_t *self, vec3_t start, vec3_t aimdir, int speed) { edict_t *nuke; vec3_t dir; vec3_t forward, right, up; int damage_modifier; if (!self) { return; } damage_modifier = (int)P_DamageModifier(self); vectoangles2(aimdir, dir); AngleVectors(dir, forward, right, up); nuke = G_Spawn(); VectorCopy(start, nuke->s.origin); VectorScale(aimdir, speed, nuke->velocity); VectorMA(nuke->velocity, 200 + crandom() * 10.0, up, nuke->velocity); VectorMA(nuke->velocity, crandom() * 10.0, right, nuke->velocity); VectorClear(nuke->avelocity); VectorClear(nuke->s.angles); nuke->movetype = MOVETYPE_BOUNCE; nuke->clipmask = MASK_SHOT; nuke->solid = SOLID_BBOX; nuke->s.effects |= EF_GRENADE; nuke->s.renderfx |= RF_IR_VISIBLE; VectorSet(nuke->mins, -8, -8, 0); VectorSet(nuke->maxs, 8, 8, 16); nuke->s.modelindex = gi.modelindex("models/weapons/g_nuke/tris.md2"); nuke->owner = self; nuke->teammaster = self; nuke->nextthink = level.time + FRAMETIME; nuke->wait = level.time + NUKE_DELAY + NUKE_TIME_TO_LIVE; nuke->think = Nuke_Think; nuke->touch = nuke_bounce; nuke->health = 10000; nuke->takedamage = DAMAGE_YES; nuke->svflags |= SVF_DAMAGEABLE; nuke->dmg = NUKE_DAMAGE * damage_modifier; if (damage_modifier == 1) { nuke->dmg_radius = NUKE_RADIUS; } else { nuke->dmg_radius = NUKE_RADIUS + NUKE_RADIUS * (0.25 * (float)damage_modifier); } nuke->classname = "nuke"; nuke->die = nuke_die; gi.linkentity(nuke); } void tesla_remove(edict_t *self) { edict_t *cur, *next; if (!self) { return; } self->takedamage = DAMAGE_NO; if (self->teamchain) { cur = self->teamchain; while (cur) { next = cur->teamchain; G_FreeEdict(cur); cur = next; } } else if (self->air_finished) { gi.dprintf("tesla without a field!\n"); } self->owner = self->teammaster; /* Going away, set the owner correctly. */ self->enemy = NULL; /* play double/quad sound if doubled/quadded and an underwater explosion */ if (self->dmg_radius) { if (self->dmg >= (TESLA_DAMAGE * TESLA_EXPLOSION_DAMAGE_MULT * 4)) { gi.sound(self, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (self->dmg == (TESLA_DAMAGE * TESLA_EXPLOSION_DAMAGE_MULT * 2)) { gi.sound(self, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } } Grenade_Explode(self); } void tesla_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } tesla_remove(self); } void tesla_blow(edict_t *self) { if (!self) { return; } self->dmg = self->dmg * TESLA_EXPLOSION_DAMAGE_MULT; self->dmg_radius = TESLA_EXPLOSION_RADIUS; tesla_remove(self); } void tesla_zap(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { } void tesla_think_active(edict_t *self) { int i, num; edict_t *touch[MAX_EDICTS], *hit; vec3_t dir, start; trace_t tr; if (!self) { return; } if (level.time > self->air_finished) { tesla_remove(self); return; } VectorCopy(self->s.origin, start); start[2] += 16; num = gi.BoxEdicts(self->teamchain->absmin, self->teamchain->absmax, touch, MAX_EDICTS, AREA_SOLID); for (i = 0; i < num; i++) { /* if the tesla died while zapping things, stop zapping. */ if (!(self->inuse)) { break; } hit = touch[i]; if (!hit->inuse) { continue; } if (hit == self) { continue; } if (hit->health < 1) { continue; } /* don't hit clients in single-player or coop */ if (hit->client) { if (coop->value || !deathmatch->value) { continue; } } if (!(hit->svflags & (SVF_MONSTER | SVF_DAMAGEABLE)) && !hit->client) { continue; } tr = gi.trace(start, vec3_origin, vec3_origin, hit->s.origin, self, MASK_SHOT); if ((tr.fraction == 1) || (tr.ent == hit)) { VectorSubtract(hit->s.origin, start, dir); /* play double/quad sound if it's above the "normal" damage */ if (self->dmg >= (TESLA_DAMAGE * 4)) { gi.sound(self, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (self->dmg == (TESLA_DAMAGE * 2)) { gi.sound(self, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } /* don't do knockback to walking monsters */ if ((hit->svflags & SVF_MONSTER) && !(hit->flags & (FL_FLY | FL_SWIM))) { T_Damage(hit, self, self->teammaster, dir, tr.endpos, tr.plane.normal, self->dmg, 0, 0, MOD_TESLA); } else { T_Damage(hit, self, self->teammaster, dir, tr.endpos, tr.plane.normal, self->dmg, TESLA_KNOCKBACK, 0, MOD_TESLA); } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_LIGHTNING); gi.WriteShort(hit - g_edicts); /* destination entity */ gi.WriteShort(self - g_edicts); /* source entity */ gi.WritePosition(tr.endpos); gi.WritePosition(start); gi.multicast(start, MULTICAST_PVS); } } if (self->inuse) { self->think = tesla_think_active; self->nextthink = level.time + FRAMETIME; } } void tesla_activate(edict_t *self) { edict_t *trigger; edict_t *search; if (!self) { return; } if (gi.pointcontents(self->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_WATER)) { tesla_blow(self); return; } /* only check for spawn points in deathmatch */ if (deathmatch->value) { search = NULL; while ((search = findradius(search, self->s.origin, 1.5 * TESLA_DAMAGE_RADIUS)) != NULL) { if (search->classname) { if (((!strcmp(search->classname, "info_player_deathmatch")) || (!strcmp(search->classname, "info_player_start")) || (!strcmp(search->classname, "info_player_coop")) || (!strcmp(search->classname, "misc_teleporter_dest"))) && (visible(search, self))) { tesla_remove(self); return; } } } } trigger = G_Spawn(); VectorCopy(self->s.origin, trigger->s.origin); VectorSet(trigger->mins, -TESLA_DAMAGE_RADIUS, -TESLA_DAMAGE_RADIUS, self->mins[2]); VectorSet(trigger->maxs, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS); trigger->movetype = MOVETYPE_NONE; trigger->solid = SOLID_TRIGGER; trigger->owner = self; trigger->touch = tesla_zap; trigger->classname = "tesla trigger"; /* doesn't need to be marked as a teamslave since the move code for bounce looks for teamchains */ gi.linkentity(trigger); VectorClear(self->s.angles); /* clear the owner if in deathmatch */ if (deathmatch->value) { self->owner = NULL; } self->teamchain = trigger; self->think = tesla_think_active; self->nextthink = level.time + FRAMETIME; self->air_finished = level.time + TESLA_TIME_TO_LIVE; } void tesla_think(edict_t *ent) { if (!ent) { return; } if (gi.pointcontents(ent->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA)) { tesla_remove(ent); return; } VectorClear(ent->s.angles); if (!(ent->s.frame)) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/teslaopen.wav"), 1, ATTN_NORM, 0); } ent->s.frame++; if (ent->s.frame > 14) { ent->s.frame = 14; ent->think = tesla_activate; ent->nextthink = level.time + 0.1; } else { if (ent->s.frame > 9) { if (ent->s.frame == 10) { if (ent->owner && ent->owner->client) { PlayerNoise(ent->owner, ent->s.origin, PNOISE_WEAPON); /* PGM */ } ent->s.skinnum = 1; } else if (ent->s.frame == 12) { ent->s.skinnum = 2; } else if (ent->s.frame == 14) { ent->s.skinnum = 3; } } ent->think = tesla_think; ent->nextthink = level.time + 0.1; } } void tesla_lava(edict_t *ent, edict_t *other /* unused */, cplane_t *plane, csurface_t *surf /* unused */) { vec3_t land_point; vec3_t normal; if (!ent) { return; } get_normal_vector(plane, normal); VectorMA(ent->s.origin, -20.0, normal, land_point); if (gi.pointcontents(land_point) & (CONTENTS_SLIME | CONTENTS_LAVA)) { tesla_blow(ent); return; } if (random() > 0.5) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); } else { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); } } void fire_tesla(edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed) { edict_t *tesla; vec3_t dir; vec3_t forward, right, up; if (!self) { return; } vectoangles2(aimdir, dir); AngleVectors(dir, forward, right, up); tesla = G_Spawn(); VectorCopy(start, tesla->s.origin); VectorScale(aimdir, speed, tesla->velocity); VectorMA(tesla->velocity, 200 + crandom() * 10.0, up, tesla->velocity); VectorMA(tesla->velocity, crandom() * 10.0, right, tesla->velocity); VectorClear(tesla->s.angles); tesla->movetype = MOVETYPE_BOUNCE; tesla->solid = SOLID_BBOX; tesla->s.effects |= EF_GRENADE; tesla->s.renderfx |= RF_IR_VISIBLE; VectorSet(tesla->mins, -12, -12, 0); VectorSet(tesla->maxs, 12, 12, 20); tesla->s.modelindex = gi.modelindex("models/weapons/g_tesla/tris.md2"); tesla->owner = self; tesla->teammaster = self; tesla->wait = level.time + TESLA_TIME_TO_LIVE; tesla->think = tesla_think; tesla->nextthink = level.time + TESLA_ACTIVATE_TIME; /* blow up on contact with lava & slime code */ tesla->touch = tesla_lava; if (deathmatch->value) { tesla->health = 20; } else { tesla->health = 30; } tesla->takedamage = DAMAGE_YES; tesla->die = tesla_die; tesla->dmg = TESLA_DAMAGE * damage_multiplier; tesla->classname = "tesla"; tesla->svflags |= SVF_DAMAGEABLE; tesla->clipmask = MASK_SHOT | CONTENTS_SLIME | CONTENTS_LAVA; tesla->flags |= FL_MECHANICAL; gi.linkentity(tesla); } void fire_beams(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, int damage, int kick, int te_beam, int te_impact, int mod) { trace_t tr; vec3_t dir; vec3_t forward, right, up; vec3_t end; vec3_t water_start, endpoint; qboolean water = false, underwater = false; int content_mask = MASK_SHOT | MASK_WATER; vec3_t beam_endpt; if (!self) { return; } vectoangles2(aimdir, dir); AngleVectors(dir, forward, right, up); VectorMA(start, 8192, forward, end); if (gi.pointcontents(start) & MASK_WATER) { underwater = true; VectorCopy(start, water_start); content_mask &= ~MASK_WATER; } tr = gi.trace(start, NULL, NULL, end, self, content_mask); /* see if we hit water */ if (tr.contents & MASK_WATER) { water = true; VectorCopy(tr.endpos, water_start); if (!VectorCompare(start, tr.endpos)) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_HEATBEAM_SPARKS); gi.WritePosition(water_start); gi.WriteDir(tr.plane.normal); gi.multicast(tr.endpos, MULTICAST_PVS); } /* re-trace ignoring water this time */ tr = gi.trace(water_start, NULL, NULL, end, self, MASK_SHOT); } VectorCopy(tr.endpos, endpoint); /* halve the damage if target underwater */ if (water) { damage = damage / 2; } /* send gun puff / flash */ if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { if (tr.fraction < 1.0) { if (tr.ent->takedamage) { T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_ENERGY, mod); } else { if ((!water) && (strncmp(tr.surface->name, "sky", 3))) { /* This is the truncated steam entry - uses 1+1+2 extra bytes of data */ gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_HEATBEAM_STEAM); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.multicast(tr.endpos, MULTICAST_PVS); if (self->client) { PlayerNoise(self, tr.endpos, PNOISE_IMPACT); } } } } } /* if went through water, determine where the end and make a bubble trail */ if ((water) || (underwater)) { vec3_t pos; VectorSubtract(tr.endpos, water_start, dir); VectorNormalize(dir); VectorMA(tr.endpos, -2, dir, pos); if (gi.pointcontents(pos) & MASK_WATER) { VectorCopy(pos, tr.endpos); } else { tr = gi.trace(pos, NULL, NULL, water_start, tr.ent, MASK_WATER); } VectorAdd(water_start, tr.endpos, pos); VectorScale(pos, 0.5, pos); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BUBBLETRAIL2); gi.WritePosition(water_start); gi.WritePosition(tr.endpos); gi.multicast(pos, MULTICAST_PVS); } if ((!underwater) && (!water)) { VectorCopy(tr.endpos, beam_endpt); } else { VectorCopy(endpoint, beam_endpt); } gi.WriteByte(svc_temp_entity); gi.WriteByte(te_beam); gi.WriteShort(self - g_edicts); gi.WritePosition(start); gi.WritePosition(beam_endpt); gi.multicast(self->s.origin, MULTICAST_ALL); } void fire_heat(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, int damage, int kick, qboolean monster) { if (!self) { return; } if (monster) { fire_beams(self, start, aimdir, offset, damage, kick, TE_MONSTER_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); } else { fire_beams(self, start, aimdir, offset, damage, kick, TE_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); } } /* * Fires a single green blaster bolt. Used by monsters, generally. */ void blaster2_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int mod; int damagestat; vec3_t normal; if (!self || !other) { return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->owner && self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } get_normal_vector(plane, normal); if (other->takedamage) { mod = MOD_BLASTER2; if (self->owner) { /* the only time players will be firing blaster2 bolts will be from the defender sphere. */ if (self->owner->client) { mod = MOD_DEFENDER_SPHERE; } damagestat = self->owner->takedamage; self->owner->takedamage = DAMAGE_NO; if (self->dmg >= 5) { T_RadiusDamage(self, self->owner, self->dmg * 3, other, self->dmg_radius, 0); } T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg, 1, DAMAGE_ENERGY, mod); self->owner->takedamage = damagestat; } else { if (self->dmg >= 5) { T_RadiusDamage(self, self->owner, self->dmg * 3, other, self->dmg_radius, 0); } T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg, 1, DAMAGE_ENERGY, mod); } } else { /* yeowch this will get expensive */ if (self->dmg >= 5) { T_RadiusDamage(self, self->owner, self->dmg * 3, self->owner, self->dmg_radius, 0); } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BLASTER2); gi.WritePosition(self->s.origin); gi.WriteDir(normal); gi.multicast(self->s.origin, MULTICAST_PVS); } G_FreeEdict(self); } void fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper) { edict_t *bolt; trace_t tr; if (!self) { return; } VectorNormalize(dir); bolt = G_Spawn(); VectorCopy(start, bolt->s.origin); VectorCopy(start, bolt->s.old_origin); vectoangles2(dir, bolt->s.angles); VectorScale(dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->s.effects |= effect; VectorClear(bolt->mins); VectorClear(bolt->maxs); if (effect) { bolt->s.effects |= EF_TRACKER; } bolt->dmg_radius = 128; bolt->s.modelindex = gi.modelindex("models/proj/laser2/tris.md2"); bolt->touch = blaster2_touch; bolt->owner = self; bolt->nextthink = level.time + 2; bolt->think = G_FreeEdict; bolt->dmg = damage; bolt->classname = "bolt"; gi.linkentity(bolt); if (self->client) { check_dodge(self, bolt->s.origin, dir, speed); } tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); if (tr.fraction < 1.0) { VectorMA(bolt->s.origin, -10, dir, bolt->s.origin); bolt->touch(bolt, tr.ent, NULL, NULL); } } void tracker_pain_daemon_think(edict_t *self) { static vec3_t pain_normal = {0, 0, 1}; int hurt; if (!self) { return; } if (!self->inuse) { return; } if ((level.time - self->timestamp) > TRACKER_DAMAGE_TIME) { if (!self->enemy->client) { self->enemy->s.effects &= ~EF_TRACKERTRAIL; } G_FreeEdict(self); } else { if (self->enemy->health > 0) { T_Damage(self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, pain_normal, self->dmg, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); /* if we kill the player, we'll be removed. */ if (self->inuse) { /* if we killed a monster, gib them. */ if (self->enemy->health < 1) { if (self->enemy->gib_health) { hurt = -self->enemy->gib_health; } else { hurt = 500; } T_Damage(self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, pain_normal, hurt, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); } if (self->enemy->client) { self->enemy->client->tracker_pain_framenum = level.framenum + 1; } else { self->enemy->s.effects |= EF_TRACKERTRAIL; } self->nextthink = level.time + FRAMETIME; } } else { if (!self->enemy->client) { self->enemy->s.effects &= ~EF_TRACKERTRAIL; } G_FreeEdict(self); } } } void tracker_pain_daemon_spawn(edict_t *owner, edict_t *enemy, int damage) { edict_t *daemon; if (!owner || !enemy) { return; } daemon = G_Spawn(); daemon->classname = "pain daemon"; daemon->think = tracker_pain_daemon_think; daemon->nextthink = level.time + FRAMETIME; daemon->timestamp = level.time; daemon->owner = owner; daemon->enemy = enemy; daemon->dmg = damage; } void tracker_explode(edict_t *self) { if (!self) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_TRACKER_EXPLOSION); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); G_FreeEdict(self); } void tracker_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { float damagetime; vec3_t normal; if (!self || !other) { return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } if (other->takedamage) { get_normal_vector(plane, normal); if ((other->svflags & SVF_MONSTER) || other->client) { if (other->health > 0) /* knockback only for living creatures */ { T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, 0, (self->dmg * 3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); if (!(other->flags & (FL_FLY | FL_SWIM))) { other->velocity[2] += 140; } damagetime = ((float)self->dmg) * FRAMETIME; damagetime = damagetime / TRACKER_DAMAGE_TIME; tracker_pain_daemon_spawn(self->owner, other, (int)damagetime); } else /* lots of damage (almost autogib) for dead bodies */ { T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg * 4, (self->dmg * 3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); } } else /* full damage in one shot for inanimate objects */ { T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg, (self->dmg * 3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); } } tracker_explode(self); } void tracker_fly(edict_t *self) { vec3_t dest; vec3_t dir; vec3_t center; if (!self) { return; } if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->health < 1)) { tracker_explode(self); return; } /* try to hunt for center of enemy, if possible and not client */ if (self->enemy->client) { VectorCopy(self->enemy->s.origin, dest); dest[2] += self->enemy->viewheight; } else if (VectorCompare(self->enemy->absmin, vec3_origin) || VectorCompare(self->enemy->absmax, vec3_origin)) { VectorCopy(self->enemy->s.origin, dest); } else { VectorMA(vec3_origin, 0.5, self->enemy->absmin, center); VectorMA(center, 0.5, self->enemy->absmax, center); VectorCopy(center, dest); } VectorSubtract(dest, self->s.origin, dir); VectorNormalize(dir); vectoangles2(dir, self->s.angles); VectorScale(dir, self->speed, self->velocity); VectorCopy(dest, self->monsterinfo.saved_goal); self->nextthink = level.time + 0.1; } void fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, edict_t *enemy) { edict_t *bolt; trace_t tr; if (!self) { return; } VectorNormalize(dir); bolt = G_Spawn(); VectorCopy(start, bolt->s.origin); VectorCopy(start, bolt->s.old_origin); vectoangles2(dir, bolt->s.angles); VectorScale(dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->speed = speed; bolt->s.effects = EF_TRACKER; bolt->s.sound = gi.soundindex("weapons/disrupt.wav"); VectorClear(bolt->mins); VectorClear(bolt->maxs); bolt->s.modelindex = gi.modelindex("models/proj/disintegrator/tris.md2"); bolt->touch = tracker_touch; bolt->enemy = enemy; bolt->owner = self; bolt->dmg = damage; bolt->classname = "tracker"; gi.linkentity(bolt); if (enemy) { bolt->nextthink = level.time + 0.1; bolt->think = tracker_fly; } else { bolt->nextthink = level.time + 10; bolt->think = G_FreeEdict; } if (self->client) { check_dodge(self, bolt->s.origin, dir, speed); } tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); if (tr.fraction < 1.0) { VectorMA(bolt->s.origin, -10, dir, bolt->s.origin); bolt->touch(bolt, tr.ent, NULL, NULL); } } rogue-ROGUE_2_13/src/g_phys.c000066400000000000000000000645171477320066100160510ustar00rootroot00000000000000/* ======================================================================= * * Quake IIs legendary physic engine. * * ======================================================================= */ #include "header/local.h" #define MAX_CLIP_PLANES 5 #define STOP_EPSILON 0.1 #define sv_friction 6 #define sv_waterfriction 1 void SV_Physics_NewToss(edict_t *ent); typedef struct { edict_t *ent; vec3_t origin; vec3_t angles; } pushed_t; pushed_t pushed[MAX_EDICTS], *pushed_p; edict_t *obstacle; /* * pushmove objects do not obey gravity, and do not interact with each other or * trigger fields, but block normal movement and push normal objects when they move. * * onground is set for toss objects when they come to a complete rest. it is set for * steping or walking objects * * - doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH * - bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS * - corpses are SOLID_NOT and MOVETYPE_TOSS * - crates are SOLID_BBOX and MOVETYPE_TOSS * - walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP * - flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY * - solid_edge items only clip against bsp models. * */ edict_t * SV_TestEntityPosition(edict_t *ent) { trace_t trace; int mask; if (!ent) { return NULL; } /* dead bodies are supposed to not be solid so lets ensure they only collide with BSP during pushmoves */ if (ent->clipmask && !(ent->svflags & SVF_DEADMONSTER)) { mask = ent->clipmask; } else { mask = MASK_SOLID; } trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask); if (trace.startsolid) { return g_edicts; } return NULL; } void SV_CheckVelocity(edict_t *ent) { if (!ent) { return; } if (VectorLength(ent->velocity) > sv_maxvelocity->value) { VectorNormalize(ent->velocity); VectorScale(ent->velocity, sv_maxvelocity->value, ent->velocity); } } /* * Runs thinking code for * this frame if necessary */ qboolean SV_RunThink(edict_t *ent) { float thinktime; if (!ent) { return false; } thinktime = ent->nextthink; if (thinktime <= 0) { return true; } if (thinktime > level.time + 0.001) { return true; } ent->nextthink = 0; if (!ent->think) { gi.error("NULL ent->think"); } ent->think(ent); return false; } /* * Two entities have touched, so * run their touch functions */ void SV_Impact(edict_t *e1, trace_t *trace) { edict_t *e2; if (!e1 || !trace) { return; } e2 = trace->ent; if (e1->touch && (e1->solid != SOLID_NOT)) { e1->touch(e1, e2, &trace->plane, trace->surface); } if (e2->touch && (e2->solid != SOLID_NOT)) { e2->touch(e2, e1, NULL, NULL); } } /* * Slide off of the impacting object * returns the blocked flags (1 = floor, * 2 = step / wall) */ int ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) { float backoff; float change; int i, blocked; blocked = 0; if (normal[2] > 0) { blocked |= 1; /* floor */ } if (!normal[2]) { blocked |= 2; /* step */ } backoff = DotProduct(in, normal) * overbounce; for (i = 0; i < 3; i++) { change = normal[i] * backoff; out[i] = in[i] - change; if ((out[i] > -STOP_EPSILON) && (out[i] < STOP_EPSILON)) { out[i] = 0; } } return blocked; } /* * The basic solid body movement clip that slides * along multiple planes. Returns the clipflags if * the velocity was modified (hit something solid) * 1 = floor * 2 = wall / step * 4 = dead stop */ int SV_FlyMove(edict_t *ent, float time, int mask) { edict_t *hit; int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; if (!ent) { return 0; } numbumps = 4; blocked = 0; VectorCopy(ent->velocity, original_velocity); VectorCopy(ent->velocity, primal_velocity); numplanes = 0; time_left = time; ent->groundentity = NULL; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) { end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; } trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, end, ent, mask); if (trace.allsolid) { /* entity is trapped in another solid */ VectorCopy(vec3_origin, ent->velocity); return 3; } if (trace.fraction > 0) { /* actually covered some distance */ VectorCopy(trace.endpos, ent->s.origin); VectorCopy(ent->velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) { break; /* moved the entire distance */ } hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; /* floor */ if (hit->solid == SOLID_BSP) { ent->groundentity = hit; ent->groundentity_linkcount = hit->linkcount; } } if (!trace.plane.normal[2]) { blocked |= 2; /* step */ } /* run the impact function */ SV_Impact(ent, &trace); if (!ent->inuse) { break; /* removed by the impact function */ } time_left -= time_left * trace.fraction; /* cliped to another plane */ if (numplanes >= MAX_CLIP_PLANES) { /* this shouldn't really happen */ VectorCopy(vec3_origin, ent->velocity); return 3; } VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; /* modify original_velocity so it parallels all of the clip planes */ for (i = 0; i < numplanes; i++) { ClipVelocity(original_velocity, planes[i], new_velocity, 1); for (j = 0; j < numplanes; j++) { if ((j != i) && !VectorCompare(planes[i], planes[j])) { if (DotProduct(new_velocity, planes[j]) < 0) { break; /* not ok */ } } } if (j == numplanes) { break; } } if (i != numplanes) { /* go along this plane */ VectorCopy(new_velocity, ent->velocity); } else { /* go along the crease */ if (numplanes != 2) { VectorCopy(vec3_origin, ent->velocity); return 7; } CrossProduct(planes[0], planes[1], dir); d = DotProduct(dir, ent->velocity); VectorScale(dir, d, ent->velocity); } /* if original velocity is against the original velocity, stop dead to avoid tiny occilations in sloping corners */ if (DotProduct(ent->velocity, primal_velocity) <= 0) { VectorCopy(vec3_origin, ent->velocity); return blocked; } } return blocked; } void SV_AddGravity(edict_t *ent) { if (!ent) { return; } if (ent->gravityVector[2] > 0) { VectorMA(ent->velocity, ent->gravity * sv_gravity->value * FRAMETIME, ent->gravityVector, ent->velocity); } else { ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME; } } /* * Returns the actual bounding box of a bmodel. * This is a big improvement over what q2 normally * does with rotating bmodels - q2 sets absmin, * absmax to a cube that will completely contain * the bmodel at *any* rotation on *any* axis, whether * the bmodel can actually rotate to that angle or not. * This leads to a lot of false block tests in SV_Push * if another bmodel is in the vicinity. */ void RealBoundingBox(edict_t *ent, vec3_t mins, vec3_t maxs) { vec3_t forward, left, up, f1, l1, u1; vec3_t p[8]; int i, j, k, j2, k4; if (!ent) { return; } for (k = 0; k < 2; k++) { k4 = k * 4; if (k) { p[k4][2] = ent->maxs[2]; } else { p[k4][2] = ent->mins[2]; } p[k4 + 1][2] = p[k4][2]; p[k4 + 2][2] = p[k4][2]; p[k4 + 3][2] = p[k4][2]; for (j = 0; j < 2; j++) { j2 = j * 2; if (j) { p[j2 + k4][1] = ent->maxs[1]; } else { p[j2 + k4][1] = ent->mins[1]; } p[j2 + k4 + 1][1] = p[j2 + k4][1]; for (i = 0; i < 2; i++) { if (i) { p[i + j2 + k4][0] = ent->maxs[0]; } else { p[i + j2 + k4][0] = ent->mins[0]; } } } } AngleVectors(ent->s.angles, forward, left, up); for (i = 0; i < 8; i++) { VectorScale(forward, p[i][0], f1); VectorScale(left, -p[i][1], l1); VectorScale(up, p[i][2], u1); VectorAdd(ent->s.origin, f1, p[i]); VectorAdd(p[i], l1, p[i]); VectorAdd(p[i], u1, p[i]); } VectorCopy(p[0], mins); VectorCopy(p[0], maxs); for (i = 1; i < 8; i++) { if (mins[0] > p[i][0]) { mins[0] = p[i][0]; } if (mins[1] > p[i][1]) { mins[1] = p[i][1]; } if (mins[2] > p[i][2]) { mins[2] = p[i][2]; } if (maxs[0] < p[i][0]) { maxs[0] = p[i][0]; } if (maxs[1] < p[i][1]) { maxs[1] = p[i][1]; } if (maxs[2] < p[i][2]) { maxs[2] = p[i][2]; } } } /* * Does not change the entities velocity at all */ trace_t SV_PushEntity(edict_t *ent, vec3_t push) { trace_t trace; vec3_t start; vec3_t end; int mask; VectorCopy(ent->s.origin, start); VectorAdd(start, push, end); retry: if (ent->clipmask) { mask = ent->clipmask; } else { mask = MASK_SOLID; } trace = gi.trace(start, ent->mins, ent->maxs, end, ent, mask); /* startsolid treats different-content volumes as continuous, like the bbox of a monster/player and the floor of an elevator. So do another trace that only collides with BSP so that we make a best effort to keep these entities inside non-solid space */ if (trace.startsolid && (mask & ~MASK_SOLID)) { trace = gi.trace (start, ent->mins, ent->maxs, end, ent, MASK_SOLID); } VectorCopy(trace.endpos, ent->s.origin); gi.linkentity(ent); /* Push slightly away from non-horizontal surfaces, prevent origin stuck in the plane which causes the entity to be rendered in full black. */ if (trace.plane.type != 2) { /* Limit the fix to gibs, debris and dead monsters. Everything else may break existing maps. Items may slide to unreachable locations, monsters may get stuck, etc. */ if (((strncmp(ent->classname, "monster_", 8) == 0) && ent->health < 1) || (strcmp(ent->classname, "debris") == 0) || (ent->s.effects & EF_GIB)) { VectorAdd(ent->s.origin, trace.plane.normal, ent->s.origin); } } if (trace.fraction != 1.0) { SV_Impact(ent, &trace); /* if the pushed entity went away and the pusher is still there */ if (!trace.ent->inuse && ent->inuse) { /* move the pusher back and try again */ VectorCopy(start, ent->s.origin); gi.linkentity(ent); goto retry; } } ent->gravity = 1.0; if (ent->inuse) { G_TouchTriggers(ent); } return trace; } /* * Objects need to be moved back on a failed push, * otherwise riders would continue to slide. */ qboolean SV_Push(edict_t *pusher, vec3_t move, vec3_t amove) { int i, e; edict_t *check, *block; pushed_t *p; vec3_t org, org2, move2, forward, right, up; vec3_t realmins, realmaxs; if (!pusher) { return false; } /* clamp the move to 1/8 units, so the position will be accurate for client side prediction */ for (i = 0; i < 3; i++) { float temp; temp = move[i] * 8.0; if (temp > 0.0) { temp += 0.5; } else { temp -= 0.5; } move[i] = 0.125 * (int)temp; } /* we need this for pushing things later */ VectorSubtract(vec3_origin, amove, org); AngleVectors(org, forward, right, up); /* save the pusher's original position */ pushed_p->ent = pusher; VectorCopy(pusher->s.origin, pushed_p->origin); VectorCopy(pusher->s.angles, pushed_p->angles); pushed_p++; /* move the pusher to it's final position */ VectorAdd(pusher->s.origin, move, pusher->s.origin); VectorAdd(pusher->s.angles, amove, pusher->s.angles); gi.linkentity(pusher); /* Create a real bounding box for rotating brush models. */ RealBoundingBox(pusher, realmins, realmaxs); /* see if any solid entities are inside the final position */ check = g_edicts + 1; for (e = 1; e < globals.num_edicts; e++, check++) { if (!check->inuse) { continue; } if ((check->movetype == MOVETYPE_PUSH) || (check->movetype == MOVETYPE_STOP) || (check->movetype == MOVETYPE_NONE) || (check->movetype == MOVETYPE_NOCLIP)) { continue; } if (!check->area.prev) { continue; /* not linked in anywhere */ } /* if the entity is standing on the pusher, it will definitely be moved */ if (check->groundentity != pusher) { /* see if the ent needs to be tested */ if ((check->absmin[0] >= realmaxs[0]) || (check->absmin[1] >= realmaxs[1]) || (check->absmin[2] >= realmaxs[2]) || (check->absmax[0] <= realmins[0]) || (check->absmax[1] <= realmins[1]) || (check->absmax[2] <= realmins[2])) { continue; } /* see if the ent's bbox is inside the pusher's final position */ if (!SV_TestEntityPosition(check)) { continue; } } if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher)) { /* move this entity */ pushed_p->ent = check; VectorCopy(check->s.origin, pushed_p->origin); VectorCopy(check->s.angles, pushed_p->angles); pushed_p++; /* try moving the contacted entity */ VectorAdd(check->s.origin, move, check->s.origin); /* figure movement due to the pusher's amove */ VectorSubtract(check->s.origin, pusher->s.origin, org); org2[0] = DotProduct(org, forward); org2[1] = -DotProduct(org, right); org2[2] = DotProduct(org, up); VectorSubtract(org2, org, move2); VectorAdd(check->s.origin, move2, check->s.origin); /* may have pushed them off an edge */ if (check->groundentity != pusher) { check->groundentity = NULL; } block = SV_TestEntityPosition(check); if (!block) { /* pushed ok */ gi.linkentity(check); /* impact? */ continue; } /* if it is ok to leave in the old position, do it this is only relevent for riding entities, not pushed */ VectorSubtract(check->s.origin, move, check->s.origin); block = SV_TestEntityPosition(check); if (!block) { pushed_p--; continue; } } /* save off the obstacle so we can call the block function */ obstacle = check; /* move back any entities we already moved go backwards, so if the same entity was pushed twice, it goes back to the original position */ for (p = pushed_p - 1; p >= pushed; p--) { VectorCopy(p->origin, p->ent->s.origin); VectorCopy(p->angles, p->ent->s.angles); gi.linkentity(p->ent); } return false; } /* see if anything we moved has touched a trigger */ for (p = pushed_p - 1; p >= pushed; p--) { G_TouchTriggers(p->ent); } return true; } /* * Bmodel objects don't interact with each * other, but push all box objects */ void SV_Physics_Pusher(edict_t *ent) { vec3_t move, amove; edict_t *part, *mv; if (!ent) { return; } /* if not a team captain, so movement will be handled elsewhere */ if (ent->flags & FL_TEAMSLAVE) { return; } /* make sure all team slaves can move before commiting any moves or calling any think functionsif the move is blocked, all moved objects will be backed out */ pushed_p = pushed; for (part = ent; part; part = part->teamchain) { if (part->velocity[0] || part->velocity[1] || part->velocity[2] || part->avelocity[0] || part->avelocity[1] || part->avelocity[2]) { /* object is moving */ VectorScale(part->velocity, FRAMETIME, move); VectorScale(part->avelocity, FRAMETIME, amove); if (!SV_Push(part, move, amove)) { break; /* move was blocked */ } } } if (pushed_p > &pushed[MAX_EDICTS-1]) { gi.error("pushed_p > &pushed[MAX_EDICTS-1], memory corrupted"); } if (part) { /* the move failed, bump all nextthink times and back out moves */ for (mv = ent; mv; mv = mv->teamchain) { if (mv->nextthink > 0) { mv->nextthink += FRAMETIME; } } /* if the pusher has a "blocked" function, call it otherwise, just stay in place until the obstacle is gone */ if (part->blocked) { part->blocked(part, obstacle); } } else { /* the move succeeded, so call all think functions */ for (part = ent; part; part = part->teamchain) { /* prevent entities that are on trains that have gone away from thinking! */ if (part->inuse) { SV_RunThink(part); } } } } /* * Non moving objects can only think */ void SV_Physics_None(edict_t *ent) { if (!ent) { return; } /* regular thinking */ SV_RunThink(ent); } /* * A moving object that doesn't obey physics */ void SV_Physics_Noclip(edict_t *ent) { if (!ent) { return; } /* regular thinking */ if (!SV_RunThink(ent)) { return; } VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); VectorMA(ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin); gi.linkentity(ent); } /* * Toss, bounce, and fly movement. When onground, do nothing. */ void SV_Physics_Toss(edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; if (!ent) { return; } /* regular thinking */ SV_RunThink(ent); /* entities are very often freed during thinking */ if (!ent->inuse) { return; } /* if not a team captain, so movement will be handled elsewhere */ if (ent->flags & FL_TEAMSLAVE) { return; } if (ent->velocity[2] > 0) { ent->groundentity = NULL; } /* check for the groundentity going away */ if (ent->groundentity) { if (!ent->groundentity->inuse) { ent->groundentity = NULL; } } /* if onground, return without moving */ if (ent->groundentity && (ent->gravity > 0.0)) { return; } VectorCopy(ent->s.origin, old_origin); SV_CheckVelocity(ent); /* add gravity */ if ((ent->movetype != MOVETYPE_FLY) && (ent->movetype != MOVETYPE_FLYMISSILE)) { SV_AddGravity(ent); } /* move angles */ VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); /* move origin */ VectorScale(ent->velocity, FRAMETIME, move); trace = SV_PushEntity(ent, move); if (!ent->inuse) { return; } if (trace.fraction < 1) { if (ent->movetype == MOVETYPE_BOUNCE) { backoff = 1.5; } else { backoff = 1; } ClipVelocity(ent->velocity, trace.plane.normal, ent->velocity, backoff); /* stop if on ground */ if (trace.plane.normal[2] > 0.7) { if ((ent->velocity[2] < 60) || (ent->movetype != MOVETYPE_BOUNCE)) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy(vec3_origin, ent->velocity); VectorCopy(vec3_origin, ent->avelocity); } } } /* check for water transition */ wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents(ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) { ent->waterlevel = 1; } else { ent->waterlevel = 0; } if (!wasinwater && isinwater) { /* don't play splash sound for entities already in water on level start */ if (level.framenum > 3) { gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } } else if (wasinwater && !isinwater) { gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } /* move teamslaves */ for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy(ent->s.origin, slave->s.origin); gi.linkentity(slave); } } /* * Monsters freefall when they don't have a ground entity, otherwise * all movement is done with discrete steps. * * This is also used for objects that have become still on the ground, but * will fall if the floor is pulled out from under them. */ void SV_AddRotationalFriction(edict_t *ent) { int n; float adjustment; if (!ent) { return; } VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); adjustment = FRAMETIME * sv_stopspeed->value * sv_friction; for (n = 0; n < 3; n++) { if (ent->avelocity[n] > 0) { ent->avelocity[n] -= adjustment; if (ent->avelocity[n] < 0) { ent->avelocity[n] = 0; } } else { ent->avelocity[n] += adjustment; if (ent->avelocity[n] > 0) { ent->avelocity[n] = 0; } } } } void SV_Physics_Step(edict_t *ent) { qboolean wasonground; qboolean hitsound = false; float *vel; float speed, newspeed, control; float friction; edict_t *groundentity; int mask; if (!ent) { return; } /* airborn monsters should always check for ground */ if (!ent->groundentity) { M_CheckGround(ent); } groundentity = ent->groundentity; SV_CheckVelocity(ent); if (groundentity) { wasonground = true; } else { wasonground = false; } if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) { SV_AddRotationalFriction(ent); } /* add gravity except: flying monsters swimming monsters who are in the water */ if (!wasonground) { if (!(ent->flags & FL_FLY)) { if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { if (ent->velocity[2] < sv_gravity->value * -0.1) { hitsound = true; } if (ent->waterlevel == 0) { SV_AddGravity(ent); } } } } /* friction for flying monsters that have been given vertical velocity */ if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; friction = sv_friction / 3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; ent->velocity[2] *= newspeed; } /* friction for flying monsters that have been given vertical velocity */ if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; ent->velocity[2] *= newspeed; } if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { /* apply friction */ if ((wasonground) || (ent->flags & (FL_SWIM | FL_FLY))) { if (!((ent->health <= 0.0) && !M_CheckBottom(ent))) { vel = ent->velocity; speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]); if (speed) { friction = sv_friction; control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; newspeed = speed - FRAMETIME * control * friction; if (newspeed < 0) { newspeed = 0; } newspeed /= speed; vel[0] *= newspeed; vel[1] *= newspeed; } } } if (ent->svflags & SVF_MONSTER) { mask = MASK_MONSTERSOLID; } else { mask = MASK_SOLID; } SV_FlyMove(ent, FRAMETIME, mask); gi.linkentity(ent); ent->gravity = 1.0; G_TouchTriggers(ent); if (!ent->inuse) { return; } if (ent->groundentity) { if (!wasonground) { if (hitsound) { gi.sound(ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); } } } } if (!ent->inuse) /* g_touchtrigger free problem */ { return; } /* regular thinking */ SV_RunThink(ent); } void G_RunEntity(edict_t *ent) { trace_t trace; vec3_t previous_origin; qboolean saved_origin; if (!ent) { return; } if (ent->movetype == MOVETYPE_STEP) { VectorCopy(ent->s.origin, previous_origin); saved_origin = true; } else { saved_origin = false; } if (ent->prethink) { ent->prethink(ent); } switch ((int)ent->movetype) { case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher(ent); break; case MOVETYPE_NONE: SV_Physics_None(ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip(ent); break; case MOVETYPE_STEP: SV_Physics_Step(ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: SV_Physics_Toss(ent); break; case MOVETYPE_NEWTOSS: SV_Physics_NewToss(ent); break; default: gi.error("SV_Physics: bad movetype %i", (int)ent->movetype); } /* if we moved, check and fix origin if needed */ /* also check inuse since entities are very often freed while thinking */ if (saved_origin && ent->inuse && !VectorCompare(ent->s.origin, previous_origin)) { trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, previous_origin, ent, MASK_MONSTERSOLID); if (trace.allsolid || trace.startsolid) { VectorCopy(previous_origin, ent->s.origin); } } } /* * Toss, bounce, and fly movement. When on ground and * no velocity, do nothing. With velocity, slide. */ void SV_Physics_NewToss(edict_t *ent) { trace_t trace; vec3_t move; edict_t *slave; qboolean wasinwater; qboolean isinwater; float speed, newspeed; vec3_t old_origin; if (!ent) { return; } /* regular thinking */ SV_RunThink(ent); /* if not a team captain, so movement will be handled elsewhere */ if (ent->flags & FL_TEAMSLAVE) { return; } /* find out what we're sitting on. */ VectorCopy(ent->s.origin, move); move[2] -= 0.25; trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, move, ent, ent->clipmask); if (ent->groundentity && ent->groundentity->inuse) { ent->groundentity = trace.ent; } else { ent->groundentity = NULL; } /* if we're sitting on something flat and have no velocity of our own, return. */ if (ent->groundentity && (trace.plane.normal[2] == 1.0) && !ent->velocity[0] && !ent->velocity[1] && !ent->velocity[2]) { return; } /* store the old origin */ VectorCopy(ent->s.origin, old_origin); SV_CheckVelocity(ent); /* add gravity */ SV_AddGravity(ent); if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) { SV_AddRotationalFriction(ent); } /* add friction */ speed = VectorLength(ent->velocity); if (ent->waterlevel) /* friction for water movement */ { newspeed = speed - (sv_waterfriction * 6 * ent->waterlevel); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; VectorScale(ent->velocity, newspeed, ent->velocity); } else if (!ent->groundentity) /* friction for air movement */ { newspeed = speed - ((sv_friction)); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; VectorScale(ent->velocity, newspeed, ent->velocity); } else /* use ground friction */ { newspeed = speed - (sv_friction * 6); if (newspeed < 0) { newspeed = 0; } newspeed /= speed; VectorScale(ent->velocity, newspeed, ent->velocity); } SV_FlyMove(ent, FRAMETIME, ent->clipmask); gi.linkentity(ent); G_TouchTriggers(ent); /* check for water transition */ wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents(ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) { ent->waterlevel = 1; } else { ent->waterlevel = 0; } if (!wasinwater && isinwater) { gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } else if (wasinwater && !isinwater) { gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); } /* move teamslaves */ for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy(ent->s.origin, slave->s.origin); gi.linkentity(slave); } } rogue-ROGUE_2_13/src/g_spawn.c000066400000000000000000001170701477320066100162070ustar00rootroot00000000000000/* * ======================================================================= * * Item spawning. * * ======================================================================= */ #include "header/local.h" #define LEG_WAIT_TIME 1 #define MAX_LEGSFRAME 23 #define SPAWNGROW_LIFESPAN 0.3 #define STEPSIZE 18 typedef struct { char *name; void (*spawn)(edict_t *ent); } spawn_t; void SP_item_health(edict_t *self); void SP_item_health_small(edict_t *self); void SP_item_health_large(edict_t *self); void SP_item_health_mega(edict_t *self); void SP_info_player_start(edict_t *ent); void SP_info_player_deathmatch(edict_t *ent); void SP_info_player_coop(edict_t *ent); void SP_info_player_intermission(edict_t *ent); void SP_func_plat(edict_t *ent); void SP_func_rotating(edict_t *ent); void SP_func_button(edict_t *ent); void SP_func_door(edict_t *ent); void SP_func_door_secret(edict_t *ent); void SP_func_door_rotating(edict_t *ent); void SP_func_water(edict_t *ent); void SP_func_train(edict_t *ent); void SP_func_conveyor(edict_t *self); void SP_func_wall(edict_t *self); void SP_func_object(edict_t *self); void SP_func_explosive(edict_t *self); void SP_func_timer(edict_t *self); void SP_func_areaportal(edict_t *ent); void SP_func_clock(edict_t *ent); void SP_func_killbox(edict_t *ent); void SP_trigger_always(edict_t *ent); void SP_trigger_once(edict_t *ent); void SP_trigger_multiple(edict_t *ent); void SP_trigger_relay(edict_t *ent); void SP_trigger_push(edict_t *ent); void SP_trigger_hurt(edict_t *ent); void SP_trigger_key(edict_t *ent); void SP_trigger_counter(edict_t *ent); void SP_trigger_elevator(edict_t *ent); void SP_trigger_gravity(edict_t *ent); void SP_trigger_monsterjump(edict_t *ent); void SP_target_temp_entity(edict_t *ent); void SP_target_speaker(edict_t *ent); void SP_target_explosion(edict_t *ent); void SP_target_changelevel(edict_t *ent); void SP_target_secret(edict_t *ent); void SP_target_goal(edict_t *ent); void SP_target_splash(edict_t *ent); void SP_target_spawner(edict_t *ent); void SP_target_blaster(edict_t *ent); void SP_target_crosslevel_trigger(edict_t *ent); void SP_target_crosslevel_target(edict_t *ent); void SP_target_laser(edict_t *self); void SP_target_help(edict_t *ent); void SP_target_lightramp(edict_t *self); void SP_target_earthquake(edict_t *ent); void SP_target_character(edict_t *ent); void SP_target_string(edict_t *ent); void SP_worldspawn(edict_t *ent); void SP_viewthing(edict_t *ent); void SP_light(edict_t *self); void SP_light_mine1(edict_t *ent); void SP_light_mine2(edict_t *ent); void SP_info_null(edict_t *self); void SP_info_notnull(edict_t *self); void SP_path_corner(edict_t *self); void SP_point_combat(edict_t *self); void SP_misc_explobox(edict_t *self); void SP_misc_banner(edict_t *self); void SP_misc_satellite_dish(edict_t *self); void SP_misc_gib_arm(edict_t *self); void SP_misc_gib_leg(edict_t *self); void SP_misc_gib_head(edict_t *self); void SP_misc_insane(edict_t *self); void SP_misc_deadsoldier(edict_t *self); void SP_misc_viper(edict_t *self); void SP_misc_viper_bomb(edict_t *self); void SP_misc_bigviper(edict_t *self); void SP_misc_strogg_ship(edict_t *self); void SP_misc_teleporter(edict_t *self); void SP_misc_teleporter_dest(edict_t *self); void SP_misc_blackhole(edict_t *self); void SP_misc_eastertank(edict_t *self); void SP_misc_easterchick(edict_t *self); void SP_misc_easterchick2(edict_t *self); void SP_monster_berserk(edict_t *self); void SP_monster_gladiator(edict_t *self); void SP_monster_gunner(edict_t *self); void SP_monster_infantry(edict_t *self); void SP_monster_soldier_light(edict_t *self); void SP_monster_soldier(edict_t *self); void SP_monster_soldier_ss(edict_t *self); void SP_monster_tank(edict_t *self); void SP_monster_medic(edict_t *self); void SP_monster_flipper(edict_t *self); void SP_monster_chick(edict_t *self); void SP_monster_parasite(edict_t *self); void SP_monster_flyer(edict_t *self); void SP_monster_brain(edict_t *self); void SP_monster_floater(edict_t *self); void SP_monster_hover(edict_t *self); void SP_monster_mutant(edict_t *self); void SP_monster_supertank(edict_t *self); void SP_monster_boss2(edict_t *self); void SP_monster_jorg(edict_t *self); void SP_monster_makron(edict_t *self); void SP_monster_boss3_stand(edict_t *self); void SP_monster_commander_body(edict_t *self); void SP_turret_breach(edict_t *self); void SP_turret_base(edict_t *self); void SP_turret_driver(edict_t *self); void SP_func_plat2(edict_t *ent); void SP_func_door_secret2(edict_t *ent); void SP_func_force_wall(edict_t *ent); void SP_info_player_coop_lava(edict_t *self); void SP_info_teleport_destination(edict_t *self); void SP_trigger_teleport(edict_t *self); void SP_trigger_disguise(edict_t *self); void SP_monster_stalker(edict_t *self); void SP_monster_turret(edict_t *self); void SP_target_steam(edict_t *self); void SP_target_anger(edict_t *self); void SP_target_killplayers(edict_t *self); void SP_target_blacklight(edict_t *self); void SP_target_orb(edict_t *self); void SP_hint_path(edict_t *self); void SP_monster_carrier(edict_t *self); void SP_monster_widow(edict_t *self); void SP_monster_widow2(edict_t *self); void SP_dm_tag_token(edict_t *self); void SP_dm_dball_goal(edict_t *self); void SP_dm_dball_ball(edict_t *self); void SP_dm_dball_team1_start(edict_t *self); void SP_dm_dball_team2_start(edict_t *self); void SP_dm_dball_ball_start(edict_t *self); void SP_dm_dball_speed_change(edict_t *self); void SP_monster_kamikaze(edict_t *self); void SP_turret_invisible_brain(edict_t *self); void SP_xatrix_item(edict_t *self); void SP_misc_nuke_core(edict_t *self); void ThrowMoreStuff(edict_t *self, vec3_t point); void ThrowSmallStuff(edict_t *self, vec3_t point); void ThrowWidowGibLoc(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, qboolean fade); void ThrowWidowGibSized(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, int hitsound, qboolean fade); spawn_t spawns[] = { {"item_health", SP_item_health}, {"item_health_small", SP_item_health_small}, {"item_health_large", SP_item_health_large}, {"item_health_mega", SP_item_health_mega}, {"info_player_start", SP_info_player_start}, {"info_player_deathmatch", SP_info_player_deathmatch}, {"info_player_coop", SP_info_player_coop}, {"info_player_intermission", SP_info_player_intermission}, {"func_plat", SP_func_plat}, {"func_button", SP_func_button}, {"func_door", SP_func_door}, {"func_door_secret", SP_func_door_secret}, {"func_door_rotating", SP_func_door_rotating}, {"func_rotating", SP_func_rotating}, {"func_train", SP_func_train}, {"func_water", SP_func_water}, {"func_conveyor", SP_func_conveyor}, {"func_areaportal", SP_func_areaportal}, {"func_clock", SP_func_clock}, {"func_wall", SP_func_wall}, {"func_object", SP_func_object}, {"func_timer", SP_func_timer}, {"func_explosive", SP_func_explosive}, {"func_killbox", SP_func_killbox}, {"trigger_always", SP_trigger_always}, {"trigger_once", SP_trigger_once}, {"trigger_multiple", SP_trigger_multiple}, {"trigger_relay", SP_trigger_relay}, {"trigger_push", SP_trigger_push}, {"trigger_hurt", SP_trigger_hurt}, {"trigger_key", SP_trigger_key}, {"trigger_counter", SP_trigger_counter}, {"trigger_elevator", SP_trigger_elevator}, {"trigger_gravity", SP_trigger_gravity}, {"trigger_monsterjump", SP_trigger_monsterjump}, {"target_temp_entity", SP_target_temp_entity}, {"target_speaker", SP_target_speaker}, {"target_explosion", SP_target_explosion}, {"target_changelevel", SP_target_changelevel}, {"target_secret", SP_target_secret}, {"target_goal", SP_target_goal}, {"target_splash", SP_target_splash}, {"target_spawner", SP_target_spawner}, {"target_blaster", SP_target_blaster}, {"target_crosslevel_trigger", SP_target_crosslevel_trigger}, {"target_crosslevel_target", SP_target_crosslevel_target}, {"target_laser", SP_target_laser}, {"target_help", SP_target_help}, {"target_lightramp", SP_target_lightramp}, {"target_earthquake", SP_target_earthquake}, {"target_character", SP_target_character}, {"target_string", SP_target_string}, {"worldspawn", SP_worldspawn}, {"viewthing", SP_viewthing}, {"light", SP_light}, {"light_mine1", SP_light_mine1}, {"light_mine2", SP_light_mine2}, {"info_null", SP_info_null}, {"func_group", SP_info_null}, {"info_notnull", SP_info_notnull}, {"path_corner", SP_path_corner}, {"point_combat", SP_point_combat}, {"misc_explobox", SP_misc_explobox}, {"misc_banner", SP_misc_banner}, {"misc_satellite_dish", SP_misc_satellite_dish}, {"misc_gib_arm", SP_misc_gib_arm}, {"misc_gib_leg", SP_misc_gib_leg}, {"misc_gib_head", SP_misc_gib_head}, {"misc_insane", SP_misc_insane}, {"misc_deadsoldier", SP_misc_deadsoldier}, {"misc_viper", SP_misc_viper}, {"misc_viper_bomb", SP_misc_viper_bomb}, {"misc_bigviper", SP_misc_bigviper}, {"misc_strogg_ship", SP_misc_strogg_ship}, {"misc_teleporter", SP_misc_teleporter}, {"misc_teleporter_dest", SP_misc_teleporter_dest}, {"misc_blackhole", SP_misc_blackhole}, {"misc_eastertank", SP_misc_eastertank}, {"misc_easterchick", SP_misc_easterchick}, {"misc_easterchick2", SP_misc_easterchick2}, {"monster_berserk", SP_monster_berserk}, {"monster_gladiator", SP_monster_gladiator}, {"monster_gunner", SP_monster_gunner}, {"monster_infantry", SP_monster_infantry}, {"monster_soldier_light", SP_monster_soldier_light}, {"monster_soldier", SP_monster_soldier}, {"monster_soldier_ss", SP_monster_soldier_ss}, {"monster_tank", SP_monster_tank}, {"monster_tank_commander", SP_monster_tank}, {"monster_medic", SP_monster_medic}, {"monster_flipper", SP_monster_flipper}, {"monster_chick", SP_monster_chick}, {"monster_parasite", SP_monster_parasite}, {"monster_flyer", SP_monster_flyer}, {"monster_brain", SP_monster_brain}, {"monster_floater", SP_monster_floater}, {"monster_hover", SP_monster_hover}, {"monster_mutant", SP_monster_mutant}, {"monster_supertank", SP_monster_supertank}, {"monster_boss2", SP_monster_boss2}, {"monster_boss3_stand", SP_monster_boss3_stand}, {"monster_makron", SP_monster_makron}, {"monster_jorg", SP_monster_jorg}, {"monster_commander_body", SP_monster_commander_body}, {"turret_breach", SP_turret_breach}, {"turret_base", SP_turret_base}, {"turret_driver", SP_turret_driver}, {"func_plat2", SP_func_plat2}, {"func_door_secret2", SP_func_door_secret2}, {"func_force_wall", SP_func_force_wall}, {"trigger_teleport", SP_trigger_teleport}, {"trigger_disguise", SP_trigger_disguise}, {"info_teleport_destination", SP_info_teleport_destination}, {"info_player_coop_lava", SP_info_player_coop_lava}, {"monster_stalker", SP_monster_stalker}, {"monster_turret", SP_monster_turret}, {"target_steam", SP_target_steam}, {"target_anger", SP_target_anger}, {"target_killplayers", SP_target_killplayers}, {"target_blacklight", SP_target_blacklight}, {"target_orb", SP_target_orb}, {"monster_daedalus", SP_monster_hover}, {"hint_path", SP_hint_path}, {"monster_carrier", SP_monster_carrier}, {"monster_widow", SP_monster_widow}, {"monster_widow2", SP_monster_widow2}, {"monster_medic_commander", SP_monster_medic}, {"dm_tag_token", SP_dm_tag_token}, {"dm_dball_goal", SP_dm_dball_goal}, {"dm_dball_ball", SP_dm_dball_ball}, {"dm_dball_team1_start", SP_dm_dball_team1_start}, {"dm_dball_team2_start", SP_dm_dball_team2_start}, {"dm_dball_ball_start", SP_dm_dball_ball_start}, {"dm_dball_speed_change", SP_dm_dball_speed_change}, {"monster_kamikaze", SP_monster_kamikaze}, {"turret_invisible_brain", SP_turret_invisible_brain}, {"misc_nuke_core", SP_misc_nuke_core}, {"ammo_magslug", SP_xatrix_item}, {"ammo_trap", SP_xatrix_item}, {"item_quadfire", SP_xatrix_item}, {"weapon_boomer", SP_xatrix_item}, {"weapon_phalanx", SP_xatrix_item}, {NULL, NULL} }; /* * Finds the spawn function for the entity and calls it */ void ED_CallSpawn(edict_t *ent) { spawn_t *s; gitem_t *item; int i; if (!ent) { return; } if (!ent->classname) { gi.dprintf("ED_CallSpawn: NULL classname\n"); G_FreeEdict(ent); return; } ent->gravityVector[0] = 0.0; ent->gravityVector[1] = 0.0; ent->gravityVector[2] = -1.0; if (!strcmp(ent->classname, "weapon_nailgun")) { ent->classname = (FindItem("ETF Rifle"))->classname; } if (!strcmp(ent->classname, "ammo_nails")) { ent->classname = (FindItem("Flechettes"))->classname; } if (!strcmp(ent->classname, "weapon_heatbeam")) { ent->classname = (FindItem("Plasma Beam"))->classname; } /* check item spawn functions */ for (i = 0, item = itemlist; i < game.num_items; i++, item++) { if (!item->classname) { continue; } if (!strcmp(item->classname, ent->classname)) { /* found it */ SpawnItem(ent, item); return; } } /* check normal spawn functions */ for (s = spawns; s->name; s++) { if (!strcmp(s->name, ent->classname)) { /* found it */ s->spawn(ent); return; } } gi.dprintf("%s doesn't have a spawn function\n", ent->classname); } char * ED_NewString(const char *string) { char *newb, *new_p; int i, l; if (!string) { return NULL; } l = strlen(string) + 1; newb = gi.TagMalloc(l, TAG_LEVEL); new_p = newb; for (i = 0; i < l; i++) { if ((string[i] == '\\') && (i < l - 1)) { i++; if (string[i] == 'n') { *new_p++ = '\n'; } else { *new_p++ = '\\'; } } else { *new_p++ = string[i]; } } return newb; } /* * Takes a key/value pair and sets * the binary values in an edict */ void ED_ParseField(const char *key, const char *value, edict_t *ent) { field_t *f; byte *b; float v; vec3_t vec; if (!ent || !value || !key) { return; } for (f = fields; f->name; f++) { if (!(f->flags & FFL_NOSPAWN) && !Q_strcasecmp(f->name, (char *)key)) { /* found it */ if (f->flags & FFL_SPAWNTEMP) { b = (byte *)&st; } else { b = (byte *)ent; } switch (f->type) { case F_LSTRING: *(char **)(b + f->ofs) = ED_NewString(value); break; case F_VECTOR: sscanf(value, "%f %f %f", &vec[0], &vec[1], &vec[2]); ((float *)(b + f->ofs))[0] = vec[0]; ((float *)(b + f->ofs))[1] = vec[1]; ((float *)(b + f->ofs))[2] = vec[2]; break; case F_INT: *(int *)(b + f->ofs) = (int)strtol(value, (char **)NULL, 10); break; case F_FLOAT: *(float *)(b + f->ofs) = strtof(value, (char **)NULL);; break; case F_ANGLEHACK: v = strtof(value, (char **)NULL);; ((float *)(b + f->ofs))[0] = 0; ((float *)(b + f->ofs))[1] = v; ((float *)(b + f->ofs))[2] = 0; break; case F_IGNORE: break; default: break; } return; } } gi.dprintf("%s is not a field\n", key); } /* * Parses an edict out of the given string, returning the new position */ char * ED_ParseEdict(char *data, edict_t *ent) { qboolean init; char keyname[256]; const char *com_token; if (!ent) { return NULL; } init = false; memset(&st, 0, sizeof(st)); /* go through all the dictionary pairs */ while (1) { /* parse key */ com_token = COM_Parse(&data); if (com_token[0] == '}') { break; } if (!data) { gi.error("ED_ParseEntity: EOF without closing brace"); } strncpy(keyname, com_token, sizeof(keyname) - 1); /* parse value */ com_token = COM_Parse(&data); if (!data) { gi.error("ED_ParseEntity: EOF without closing brace"); } if (com_token[0] == '}') { gi.error("ED_ParseEntity: closing brace without data"); } init = true; /* keynames with a leading underscore are used for utility comments, and are immediately discarded by quake */ if (keyname[0] == '_') { continue; } ED_ParseField(keyname, com_token, ent); } if (!init) { memset(ent, 0, sizeof(*ent)); } return data; } /* * Chain together all entities with a matching team field. * * All but the first will have the FL_TEAMSLAVE flag set. * All but the last will have the teamchain field set to the next one */ void G_FixTeams(void) { edict_t *e, *e2, *chain; int i, j; int c, c2; c = 0; c2 = 0; for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) { continue; } if (!e->team) { continue; } if (!strcmp(e->classname, "func_train")) { if (e->flags & FL_TEAMSLAVE) { chain = e; e->teammaster = e; e->teamchain = NULL; e->flags &= ~FL_TEAMSLAVE; c++; c2++; for (j = 1, e2 = g_edicts + j; j < globals.num_edicts; j++, e2++) { if (e2 == e) { continue; } if (!e2->inuse) { continue; } if (!e2->team) { continue; } if (!strcmp(e->team, e2->team)) { c2++; chain->teamchain = e2; e2->teammaster = e; e2->teamchain = NULL; chain = e2; e2->flags |= FL_TEAMSLAVE; e2->movetype = MOVETYPE_PUSH; e2->speed = e->speed; } } } } } gi.dprintf("%i teams repaired\n", c); } void G_FindTeams(void) { edict_t *e, *e2, *chain; int i, j; int c, c2; c = 0; c2 = 0; for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) { continue; } if (!e->team) { continue; } if (e->flags & FL_TEAMSLAVE) { continue; } chain = e; e->teammaster = e; c++; c2++; for (j = i + 1, e2 = e + 1; j < globals.num_edicts; j++, e2++) { if (!e2->inuse) { continue; } if (!e2->team) { continue; } if (e2->flags & FL_TEAMSLAVE) { continue; } if (!strcmp(e->team, e2->team)) { c2++; chain->teamchain = e2; e2->teammaster = e; chain = e2; e2->flags |= FL_TEAMSLAVE; } } } G_FixTeams(); gi.dprintf("%i teams with %i entities.\n", c, c2); } /* * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; const char *com_token; int i; float skill_level; if (!mapname || !entities || !spawnpoint) { return; } skill_level = floor(skill->value); if (skill_level < 0) { skill_level = 0; } if (skill_level > 3) { skill_level = 3; } if (skill->value != skill_level) { gi.cvar_forceset("skill", va("%f", skill_level)); } SaveClientData(); gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); strncpy(level.mapname, mapname, sizeof(level.mapname) - 1); strncpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint) - 1); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) { g_edicts[i + 1].client = game.clients + i; } ent = NULL; inhibit = 0; /* parse ents */ while (1) { /* parse the opening brace */ com_token = COM_Parse(&entities); if (!entities) { break; } if (com_token[0] != '{') { gi.error("ED_LoadFromFile: found %s when expecting {", com_token); } if (!ent) { ent = g_edicts; } else { ent = G_Spawn(); } entities = ED_ParseEdict(entities, ent); /* yet another map hack */ if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) { ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; } /* ahh, the joys of map hacks .. */ if (!Q_stricmp(level.mapname, "rhangar2") && !Q_stricmp(ent->classname, "func_door_rotating") && ent->targetname && !Q_stricmp(ent->targetname, "t265")) { ent->spawnflags &= ~SPAWNFLAG_NOT_COOP; } if (!Q_stricmp(level.mapname, "rhangar2") && !Q_stricmp(ent->classname, "trigger_always") && ent->target && !Q_stricmp(ent->target, "t265")) { ent->spawnflags |= SPAWNFLAG_NOT_COOP; } if (!Q_stricmp(level.mapname, "rhangar2") && !Q_stricmp(ent->classname, "func_wall") && !Q_stricmp(ent->model, "*15")) { ent->spawnflags |= SPAWNFLAG_NOT_COOP; } /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict(ent); inhibit++; continue; } } else if (coop->value && !coop_baseq2->value) { if (ent->spawnflags & SPAWNFLAG_NOT_COOP) { G_FreeEdict(ent); inhibit++; continue; } /* stuff marked !easy & !med & !hard are coop only, all levels */ if (!((ent->spawnflags & SPAWNFLAG_NOT_EASY) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { if (((skill->value == SKILL_EASY) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == SKILL_MEDIUM) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == SKILL_HARD) || (skill->value == SKILL_HARDPLUS)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { G_FreeEdict(ent); inhibit++; continue; } } } else { if (((skill->value == SKILL_EASY) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == SKILL_MEDIUM) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == SKILL_HARD) || (skill->value == SKILL_HARDPLUS)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { G_FreeEdict(ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ent->gravityVector[0] = 0.0; ent->gravityVector[1] = 0.0; ent->gravityVector[2] = -1.0; ED_CallSpawn(ent); ent->s.renderfx |= RF_IR_VISIBLE; } /* in case the last entity in the entstring has spawntemp fields */ memset(&st, 0, sizeof(st)); gi.dprintf("%i entities inhibited.\n", inhibit); G_FindTeams(); PlayerTrail_Init(); if (deathmatch->value) { if (randomrespawn && randomrespawn->value) { PrecacheForRandomRespawn(); } } else { InitHintPaths(); } if (deathmatch->value && gamerules && gamerules->value) { if (DMGame.PostInitSetup) { DMGame.PostInitSetup(); } } } /* =================================================================== */ char *single_statusbar = "yb -24 " /* health */ "xv 0 " "hnum " "xv 50 " "pic 0 " /* ammo */ "if 2 " " xv 100 " " anum " " xv 150 " " pic 2 " "endif " /* armor */ "if 4 " " xv 200 " " rnum " " xv 250 " " pic 4 " "endif " /* selected item */ "if 6 " " xv 296 " " pic 6 " "endif " "yb -50 " /* picked up item */ "if 7 " " xv 0 " " pic 7 " " xv 26 " " yb -42 " " stat_string 8 " " yb -50 " "endif " /* timer */ "if 9 " " xv 262 " " num 2 10 " " xv 296 " " pic 9 " "endif " /* help / weapon icon */ "if 11 " " xv 148 " " pic 11 " "endif " ; char *dm_statusbar = "yb -24 " /* health */ "xv 0 " "hnum " "xv 50 " "pic 0 " /* ammo */ "if 2 " " xv 100 " " anum " " xv 150 " " pic 2 " "endif " /* armor */ "if 4 " " xv 200 " " rnum " " xv 250 " " pic 4 " "endif " /* selected item */ "if 6 " " xv 296 " " pic 6 " "endif " "yb -50 " /* picked up item */ "if 7 " " xv 0 " " pic 7 " " xv 26 " " yb -42 " " stat_string 8 " " yb -50 " "endif " /* timer */ "if 9 " " xv 246 " " num 2 10 " " xv 296 " " pic 9 " "endif " /* help / weapon icon */ "if 11 " " xv 148 " " pic 11 " "endif " /* frags */ "xr -50 " "yt 2 " "num 3 14 " /* spectator */ "if 17 " "xv 0 " "yb -58 " "string2 \"SPECTATOR MODE\" " "endif " /* chase camera */ "if 16 " "xv 0 " "yb -68 " "string \"Chasing\" " "xv 64 " "stat_string 16 " "endif " ; /* * QUAKED worldspawn (0 0 0) ? * * Only used for the world. * "sky" environment map name * "skyaxis" vector axis for rotating sky * "skyrotate" speed of rotation in degrees/second * "sounds" music cd track number * "gravity" 800 is default gravity * "message" text to print at user logon */ void SP_worldspawn(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; ent->inuse = true; /* since the world doesn't use G_Spawn() */ ent->s.modelindex = 1; /* world model is always index 1 */ /* reserve some spots for dead player bodies for coop / deathmatch */ InitBodyQue(); /* set configstrings for items */ SetItemNames(); if (st.nextmap) { strcpy(level.nextmap, st.nextmap); } /* make some data visible to the server */ if (ent->message && ent->message[0]) { gi.configstring(CS_NAME, ent->message); Q_strlcpy(level.level_name, ent->message, sizeof(level.level_name)); } else { Q_strlcpy(level.level_name, level.mapname, sizeof(level.level_name)); } if (st.sky && st.sky[0]) { gi.configstring(CS_SKY, st.sky); } else { gi.configstring(CS_SKY, "unit1_"); } gi.configstring(CS_SKYROTATE, va("%f", st.skyrotate)); gi.configstring(CS_SKYAXIS, va("%f %f %f", st.skyaxis[0], st.skyaxis[1], st.skyaxis[2])); gi.configstring(CS_CDTRACK, va("%i", ent->sounds)); gi.configstring(CS_MAXCLIENTS, va("%i", (int)(maxclients->value))); /* status bar program */ if (deathmatch->value) { gi.configstring(CS_STATUSBAR, dm_statusbar); } else { gi.configstring(CS_STATUSBAR, single_statusbar); } /* help icon for statusbar */ gi.imageindex("i_help"); level.pic_health = gi.imageindex("i_health"); gi.imageindex("help"); gi.imageindex("field_3"); if (!st.gravity) { gi.cvar_set("sv_gravity", "800"); } else { gi.cvar_set("sv_gravity", st.gravity); } snd_fry = gi.soundindex("player/fry.wav"); /* standing in lava / slime */ PrecacheItem(FindItem("Blaster")); gi.soundindex("player/lava1.wav"); gi.soundindex("player/lava2.wav"); gi.soundindex("misc/pc_up.wav"); gi.soundindex("misc/talk1.wav"); gi.soundindex("misc/udeath.wav"); /* gibs */ gi.soundindex("items/respawn1.wav"); /* sexed sounds */ gi.soundindex("*death1.wav"); gi.soundindex("*death2.wav"); gi.soundindex("*death3.wav"); gi.soundindex("*death4.wav"); gi.soundindex("*fall1.wav"); gi.soundindex("*fall2.wav"); gi.soundindex("*gurp1.wav"); /* drowning damage */ gi.soundindex("*gurp2.wav"); gi.soundindex("*jump1.wav"); /* player jump */ gi.soundindex("*pain25_1.wav"); gi.soundindex("*pain25_2.wav"); gi.soundindex("*pain50_1.wav"); gi.soundindex("*pain50_2.wav"); gi.soundindex("*pain75_1.wav"); gi.soundindex("*pain75_2.wav"); gi.soundindex("*pain100_1.wav"); gi.soundindex("*pain100_2.wav"); /* sexed models: THIS ORDER MUST MATCH THE DEFINES IN g_local.h you can add more, max 19 (pete change)these models are only loaded in coop or deathmatch. not singleplayer. */ if (coop->value || deathmatch->value) { gi.modelindex("#w_blaster.md2"); gi.modelindex("#w_shotgun.md2"); gi.modelindex("#w_sshotgun.md2"); gi.modelindex("#w_machinegun.md2"); gi.modelindex("#w_chaingun.md2"); gi.modelindex("#a_grenades.md2"); gi.modelindex("#w_glauncher.md2"); gi.modelindex("#w_rlauncher.md2"); gi.modelindex("#w_hyperblaster.md2"); gi.modelindex("#w_railgun.md2"); gi.modelindex("#w_bfg.md2"); gi.modelindex("#w_disrupt.md2"); gi.modelindex("#w_etfrifle.md2"); gi.modelindex("#w_plasma.md2"); gi.modelindex("#w_plauncher.md2"); gi.modelindex("#w_chainfist.md2"); } /* ------------------- */ gi.soundindex("player/gasp1.wav"); /* gasping for air */ gi.soundindex("player/gasp2.wav"); /* head breaking surface, not gasping */ gi.soundindex("player/watr_in.wav"); /* feet hitting water */ gi.soundindex("player/watr_out.wav"); /* feet leaving water */ gi.soundindex("player/watr_un.wav"); /* head going underwater */ gi.soundindex("player/u_breath1.wav"); gi.soundindex("player/u_breath2.wav"); gi.soundindex("items/pkup.wav"); /* bonus item pickup */ gi.soundindex("world/land.wav"); /* landing thud */ gi.soundindex("misc/h2ohit1.wav"); /* landing splash */ gi.soundindex("items/damage.wav"); gi.soundindex("misc/ddamage1.wav"); gi.soundindex("items/protect.wav"); gi.soundindex("items/protect4.wav"); gi.soundindex("weapons/noammo.wav"); gi.soundindex("infantry/inflies1.wav"); sm_meat_index = gi.modelindex("models/objects/gibs/sm_meat/tris.md2"); gi.modelindex("models/objects/gibs/arm/tris.md2"); gi.modelindex("models/objects/gibs/bone/tris.md2"); gi.modelindex("models/objects/gibs/bone2/tris.md2"); gi.modelindex("models/objects/gibs/chest/tris.md2"); gi.modelindex("models/objects/gibs/skull/tris.md2"); gi.modelindex("models/objects/gibs/head2/tris.md2"); /* Setup light animation tables. 'a' is total darkness, 'z' is doublebright. */ /* 0 normal */ gi.configstring(CS_LIGHTS + 0, "m"); /* 1 FLICKER (first variety) */ gi.configstring(CS_LIGHTS + 1, "mmnmmommommnonmmonqnmmo"); /* 2 SLOW STRONG PULSE */ gi.configstring(CS_LIGHTS + 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); /* 3 CANDLE (first variety) */ gi.configstring(CS_LIGHTS + 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); /* 4 FAST STROBE */ gi.configstring(CS_LIGHTS + 4, "mamamamamama"); /* 5 GENTLE PULSE 1 */ gi.configstring(CS_LIGHTS + 5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj"); /* 6 FLICKER (second variety) */ gi.configstring(CS_LIGHTS + 6, "nmonqnmomnmomomno"); /* 7 CANDLE (second variety) */ gi.configstring(CS_LIGHTS + 7, "mmmaaaabcdefgmmmmaaaammmaamm"); /* 8 CANDLE (third variety) */ gi.configstring(CS_LIGHTS + 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); /* 9 SLOW STROBE (fourth variety) */ gi.configstring(CS_LIGHTS + 9, "aaaaaaaazzzzzzzz"); /* 10 FLUORESCENT FLICKER */ gi.configstring(CS_LIGHTS + 10, "mmamammmmammamamaaamammma"); /* 11 SLOW PULSE NOT FADE TO BLACK */ gi.configstring(CS_LIGHTS + 11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); /* styles 32-62 are assigned by the light program for switchable lights */ /* 63 testing */ gi.configstring(CS_LIGHTS + 63, "a"); } /* * Monster spawning code: * Used by the carrier, the medic_commander, and the black widow * * The sequence to create a flying monster is: * FindSpawnPoint - tries to find suitable spot to spawn the monster in * CreateFlyMonster - this verifies the point as good and creates the monster * * To create a ground walking monster: * FindSpawnPoint - same thing * CreateGroundMonster - this checks the volume and makes sure the floor under the volume is suitable */ edict_t * CreateMonster(vec3_t origin, vec3_t angles, char *classname) { edict_t *newEnt; if (!classname) { return NULL; } newEnt = G_Spawn(); VectorCopy(origin, newEnt->s.origin); VectorCopy(angles, newEnt->s.angles); newEnt->classname = ED_NewString(classname); newEnt->monsterinfo.aiflags |= AI_DO_NOT_COUNT; VectorSet(newEnt->gravityVector, 0, 0, -1); ED_CallSpawn(newEnt); newEnt->s.renderfx |= RF_IR_VISIBLE; return newEnt; } edict_t * CreateFlyMonster(vec3_t origin, vec3_t angles, vec3_t mins, vec3_t maxs, char *classname) { if (!classname) { return NULL; } if (!mins || !maxs || VectorCompare(mins, vec3_origin) || VectorCompare(maxs, vec3_origin)) { DetermineBBox(classname, mins, maxs); } if (!CheckSpawnPoint(origin, mins, maxs)) { return NULL; } return CreateMonster(origin, angles, classname); } edict_t * CreateGroundMonster(vec3_t origin, vec3_t angles, vec3_t entMins, vec3_t entMaxs, char *classname, int height) { edict_t *newEnt; vec3_t mins, maxs; if (!classname) { return NULL; } /* if they don't provide us a bounding box, figure it out */ if (!entMins || !entMaxs || VectorCompare(entMins, vec3_origin) || VectorCompare(entMaxs, vec3_origin)) { DetermineBBox(classname, mins, maxs); } else { VectorCopy(entMins, mins); VectorCopy(entMaxs, maxs); } /* check the ground to make sure it's there, it's relatively flat, and it's not toxic */ if (!CheckGroundSpawnPoint(origin, mins, maxs, height, -1)) { return NULL; } newEnt = CreateMonster(origin, angles, classname); if (!newEnt) { return NULL; } return newEnt; } qboolean FindSpawnPoint(vec3_t startpoint, vec3_t mins, vec3_t maxs, vec3_t spawnpoint, float maxMoveUp) { trace_t tr; vec3_t top; tr = gi.trace(startpoint, mins, maxs, startpoint, NULL, MASK_MONSTERSOLID | CONTENTS_PLAYERCLIP); if ((tr.startsolid || tr.allsolid) || (tr.ent != world)) { VectorCopy(startpoint, top); top[2] += maxMoveUp; tr = gi.trace(top, mins, maxs, startpoint, NULL, MASK_MONSTERSOLID); if (tr.startsolid || tr.allsolid) { return false; } else { VectorCopy(tr.endpos, spawnpoint); return true; } } else { VectorCopy(startpoint, spawnpoint); return true; } } qboolean CheckSpawnPoint(vec3_t origin, vec3_t mins, vec3_t maxs) { trace_t tr; if (!mins || !maxs || VectorCompare(mins, vec3_origin) || VectorCompare(maxs, vec3_origin)) { return false; } tr = gi.trace(origin, mins, maxs, origin, NULL, MASK_MONSTERSOLID); if (tr.startsolid || tr.allsolid) { return false; } if (tr.ent != world) { return false; } return true; } qboolean CheckGroundSpawnPoint(vec3_t origin, vec3_t entMins, vec3_t entMaxs, float height, float gravity) { trace_t tr; vec3_t start, stop; vec3_t mins, maxs; int x, y; float mid, bottom; if (!CheckSpawnPoint(origin, entMins, entMaxs)) { return false; } VectorCopy(origin, stop); stop[2] = origin[2] + entMins[2] - height; tr = gi.trace(origin, entMins, entMaxs, stop, NULL, MASK_MONSTERSOLID | MASK_WATER); if ((tr.fraction < 1) && (tr.contents & MASK_MONSTERSOLID)) { /* first, do the midpoint trace */ VectorAdd(tr.endpos, entMins, mins); VectorAdd(tr.endpos, entMaxs, maxs); /* first, do the easy flat check */ if (gravity > 0) { start[2] = maxs[2] + 1; } else { start[2] = mins[2] - 1; } for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { start[0] = x ? maxs[0] : mins[0]; start[1] = y ? maxs[1] : mins[1]; if (gi.pointcontents(start) != CONTENTS_SOLID) { goto realcheck; } } } /* if it passed all four above checks, we're done */ return true; realcheck: /* check it for real */ start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5; start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5; start[2] = mins[2]; tr = gi.trace(start, vec3_origin, vec3_origin, stop, NULL, MASK_MONSTERSOLID); if (tr.fraction == 1.0) { return false; } if (gravity < 0) { start[2] = mins[2]; stop[2] = start[2] - STEPSIZE - STEPSIZE; mid = bottom = tr.endpos[2] + entMins[2]; } else { start[2] = maxs[2]; stop[2] = start[2] + STEPSIZE + STEPSIZE; mid = bottom = tr.endpos[2] - entMaxs[2]; } for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; tr = gi.trace(start, vec3_origin, vec3_origin, stop, NULL, MASK_MONSTERSOLID); if (gravity > 0) { if ((tr.fraction != 1.0) && (tr.endpos[2] < bottom)) { bottom = tr.endpos[2]; } if ((tr.fraction == 1.0) || (tr.endpos[2] - mid > STEPSIZE)) { return false; } } else { if ((tr.fraction != 1.0) && (tr.endpos[2] > bottom)) { bottom = tr.endpos[2]; } if ((tr.fraction == 1.0) || (mid - tr.endpos[2] > STEPSIZE)) { return false; } } } } return true; /* we can land on it, it's ok */ } /* otherwise, it's either water (bad) or not * there (too far) if we're here, it's bad below */ return false; } void DetermineBBox(char *classname, vec3_t mins, vec3_t maxs) { edict_t *newEnt; if (!classname) { return; } newEnt = G_Spawn(); VectorCopy(vec3_origin, newEnt->s.origin); VectorCopy(vec3_origin, newEnt->s.angles); newEnt->classname = ED_NewString(classname); newEnt->monsterinfo.aiflags |= AI_DO_NOT_COUNT; ED_CallSpawn(newEnt); VectorCopy(newEnt->mins, mins); VectorCopy(newEnt->maxs, maxs); G_FreeEdict(newEnt); } void spawngrow_think(edict_t *self) { int i; if (!self) { return; } for (i = 0; i < 2; i++) { self->s.angles[0] = rand() % 360; self->s.angles[1] = rand() % 360; self->s.angles[2] = rand() % 360; } if ((level.time < self->wait) && (self->s.frame < 2)) { self->s.frame++; } if (level.time >= self->wait) { if (self->s.effects & EF_SPHERETRANS) { G_FreeEdict(self); return; } else if (self->s.frame > 0) { self->s.frame--; } else { G_FreeEdict(self); return; } } self->nextthink += FRAMETIME; } void SpawnGrow_Spawn(vec3_t startpos, int size) { edict_t *ent; int i; float lifespan; ent = G_Spawn(); VectorCopy(startpos, ent->s.origin); for (i = 0; i < 2; i++) { ent->s.angles[0] = rand() % 360; ent->s.angles[1] = rand() % 360; ent->s.angles[2] = rand() % 360; } ent->solid = SOLID_NOT; ent->s.renderfx = RF_IR_VISIBLE; ent->movetype = MOVETYPE_NONE; ent->classname = "spawngro"; if (size <= 1) { lifespan = SPAWNGROW_LIFESPAN; ent->s.modelindex = gi.modelindex("models/items/spawngro2/tris.md2"); } else if (size == 2) { ent->s.modelindex = gi.modelindex("models/items/spawngro3/tris.md2"); lifespan = 2; } else { ent->s.modelindex = gi.modelindex("models/items/spawngro/tris.md2"); lifespan = SPAWNGROW_LIFESPAN; } ent->think = spawngrow_think; ent->wait = level.time + lifespan; ent->nextthink = level.time + FRAMETIME; if (size != 2) { ent->s.effects |= EF_SPHERETRANS; } gi.linkentity(ent); } void widowlegs_think(edict_t *self) { vec3_t offset; vec3_t point; vec3_t f, r, u; if (!self) { return; } if (self->s.frame == 17) { VectorSet(offset, 11.77, -7.24, 23.31); AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(point); gi.multicast(point, MULTICAST_ALL); ThrowSmallStuff(self, point); } if (self->s.frame < MAX_LEGSFRAME) { self->s.frame++; self->nextthink = level.time + FRAMETIME; return; } else if (self->wait == 0) { self->wait = level.time + LEG_WAIT_TIME; } if (level.time > self->wait) { AngleVectors(self->s.angles, f, r, u); VectorSet(offset, -65.6, -8.44, 28.59); G_ProjectSource2(self->s.origin, offset, f, r, u, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(point); gi.multicast(point, MULTICAST_ALL); ThrowSmallStuff(self, point); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib1/tris.md2", 80 + (int)(random() * 20.0), GIB_METALLIC, point, 0, true); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib2/tris.md2", 80 + (int)(random() * 20.0), GIB_METALLIC, point, 0, true); VectorSet(offset, -1.04, -51.18, 7.04); G_ProjectSource2(self->s.origin, offset, f, r, u, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(point); gi.multicast(point, MULTICAST_ALL); ThrowSmallStuff(self, point); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib1/tris.md2", 80 + (int)(random() * 20.0), GIB_METALLIC, point, 0, true); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib2/tris.md2", 80 + (int)(random() * 20.0), GIB_METALLIC, point, 0, true); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib3/tris.md2", 80 + (int)(random() * 20.0), GIB_METALLIC, point, 0, true); G_FreeEdict(self); return; } if ((level.time > (self->wait - 0.5)) && (self->count == 0)) { self->count = 1; AngleVectors(self->s.angles, f, r, u); VectorSet(offset, 31, -88.7, 10.96); G_ProjectSource2(self->s.origin, offset, f, r, u, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(point); gi.multicast(point, MULTICAST_ALL); VectorSet(offset, -12.67, -4.39, 15.68); G_ProjectSource2(self->s.origin, offset, f, r, u, point); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(point); gi.multicast(point, MULTICAST_ALL); self->nextthink = level.time + FRAMETIME; return; } self->nextthink = level.time + FRAMETIME; } void Widowlegs_Spawn(vec3_t startpos, vec3_t angles) { edict_t *ent; ent = G_Spawn(); VectorCopy(startpos, ent->s.origin); VectorCopy(angles, ent->s.angles); ent->solid = SOLID_NOT; ent->s.renderfx = RF_IR_VISIBLE; ent->movetype = MOVETYPE_NONE; ent->classname = "widowlegs"; ent->s.modelindex = gi.modelindex("models/monsters/legs/tris.md2"); ent->think = widowlegs_think; ent->nextthink = level.time + FRAMETIME; gi.linkentity(ent); } rogue-ROGUE_2_13/src/g_sphere.c000066400000000000000000000361061477320066100163450ustar00rootroot00000000000000/* * ======================================================================= * * Defender sphere. * * ======================================================================= */ #include "header/local.h" #define DEFENDER_LIFESPAN 30 #define HUNTER_LIFESPAN 30 #define VENGEANCE_LIFESPAN 30 #define MINIMUM_FLY_TIME 15 extern char *ED_NewString(char *string); void LookAtKiller(edict_t *self, edict_t *inflictor, edict_t *attacker); void defender_think(edict_t *self); void hunter_think(edict_t *self); void vengeance_think(edict_t *self); void vengeance_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); void hunter_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); void sphere_think_explode(edict_t *self) { if (!self) { return; } if (self->owner && self->owner->client && !(self->spawnflags & SPHERE_DOPPLEGANGER)) { self->owner->client->owned_sphere = NULL; } BecomeExplosion1(self); } void sphere_explode(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } sphere_think_explode(self); } void sphere_if_idle_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } if (!self->enemy) { sphere_think_explode(self); } } void sphere_fly(edict_t *self) { vec3_t dest; vec3_t dir; if (!self) { return; } if (level.time >= self->wait) { sphere_think_explode(self); return; } VectorCopy(self->owner->s.origin, dest); dest[2] = self->owner->absmax[2] + 4; if (level.time == (float)(int)level.time) { if (!visible(self, self->owner)) { VectorCopy(dest, self->s.origin); gi.linkentity(self); return; } } VectorSubtract(dest, self->s.origin, dir); VectorScale(dir, 5, self->velocity); } void sphere_chase(edict_t *self, int stupidChase) { vec3_t dest; vec3_t dir; float dist; if (!self) { return; } if ((level.time >= self->wait) || (self->enemy && (self->enemy->health < 1))) { sphere_think_explode(self); return; } VectorCopy(self->enemy->s.origin, dest); if (self->enemy->client) { dest[2] += self->enemy->viewheight; } if (visible(self, self->enemy) || stupidChase) { /* if moving, hunter sphere uses active sound */ if (!stupidChase) { self->s.sound = gi.soundindex("spheres/h_active.wav"); } VectorSubtract(dest, self->s.origin, dir); VectorNormalize(dir); vectoangles2(dir, self->s.angles); VectorScale(dir, 500, self->velocity); VectorCopy(dest, self->monsterinfo.saved_goal); } else if (VectorCompare(self->monsterinfo.saved_goal, vec3_origin)) { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); vectoangles2(dir, self->s.angles); /* if lurking, hunter sphere uses lurking sound */ self->s.sound = gi.soundindex("spheres/h_lurk.wav"); VectorClear(self->velocity); } else { VectorSubtract(self->monsterinfo.saved_goal, self->s.origin, dir); dist = VectorNormalize(dir); if (dist > 1) { vectoangles2(dir, self->s.angles); if (dist > 500) { VectorScale(dir, 500, self->velocity); } else if (dist < 20) { VectorScale(dir, (dist / FRAMETIME), self->velocity); } else { VectorScale(dir, dist, self->velocity); } /* if moving, hunter sphere uses active sound */ self->s.sound = gi.soundindex("spheres/h_active.wav"); } else { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); vectoangles2(dir, self->s.angles); /* if not moving, hunter sphere uses lurk sound */ self->s.sound = gi.soundindex("spheres/h_lurk.wav"); VectorClear(self->velocity); } } } void sphere_fire(edict_t *self, edict_t *enemy) { vec3_t dest; vec3_t dir; if (!self) { return; } if ((level.time >= self->wait) || !enemy) { sphere_think_explode(self); return; } VectorCopy(enemy->s.origin, dest); self->s.effects |= EF_ROCKET; VectorSubtract(dest, self->s.origin, dir); VectorNormalize(dir); vectoangles2(dir, self->s.angles); VectorScale(dir, 1000, self->velocity); self->touch = vengeance_touch; self->think = sphere_think_explode; self->nextthink = self->wait; } void sphere_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf, int mod) { vec3_t normal; if (!self || !other) { return; } if (self->spawnflags & SPHERE_DOPPLEGANGER) { if (other == self->teammaster) { return; } self->takedamage = DAMAGE_NO; self->owner = self->teammaster; self->teammaster = NULL; } else { if (other == self->owner) { return; } /* Don't blow up on bodies */ if (!strcmp(other->classname, "bodyque")) { return; } } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (other->takedamage) { get_normal_vector(plane, normal); T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, 10000, 1, DAMAGE_DESTROY_ARMOR, mod); } else { T_RadiusDamage(self, self->owner, 512, self->owner, 256, mod); } sphere_think_explode(self); } void vengeance_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { if (!self || !other) { return; } if (self->spawnflags & SPHERE_DOPPLEGANGER) { sphere_touch(self, other, plane, surf, MOD_DOPPLE_VENGEANCE); } else { sphere_touch(self, other, plane, surf, MOD_VENGEANCE_SPHERE); } } void hunter_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { edict_t *owner; if (!self || !other) { return; } /* don't blow up if you hit the world.... sheesh. */ if (other == world) { return; } if (self->owner) { /* if owner is flying with us, make sure they stop too. */ owner = self->owner; if (owner->flags & FL_SAM_RAIMI) { VectorClear(owner->velocity); owner->movetype = MOVETYPE_NONE; gi.linkentity(owner); } } if (self->spawnflags & SPHERE_DOPPLEGANGER) { sphere_touch(self, other, plane, surf, MOD_DOPPLE_HUNTER); } else { sphere_touch(self, other, plane, surf, MOD_HUNTER_SPHERE); } } void defender_shoot(edict_t *self, edict_t *enemy) { vec3_t dir; vec3_t start; if (!self || !enemy) { return; } if (!(enemy->inuse) || (enemy->health <= 0)) { return; } if (enemy == self->owner) { return; } VectorSubtract(enemy->s.origin, self->s.origin, dir); VectorNormalize(dir); if (self->monsterinfo.attack_finished > level.time) { return; } if (!visible(self, self->enemy)) { return; } VectorCopy(self->s.origin, start); start[2] += 2; fire_blaster2(self->owner, start, dir, 10, 1000, EF_BLASTER, 0); self->monsterinfo.attack_finished = level.time + 0.4; } void body_gib(edict_t *self) { int n; if (!self) { return; } gi.sound(self, CHAN_BODY, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", 50, GIB_ORGANIC); } ThrowGib(self, "models/objects/gibs/skull/tris.md2", 50, GIB_ORGANIC); } void hunter_pain(edict_t *self, edict_t *other, float kick, int damage) { edict_t *owner; float dist; vec3_t dir; if (!self || !other) { return; } if (self->enemy) { return; } owner = self->owner; if (!(self->spawnflags & SPHERE_DOPPLEGANGER)) { if (owner && (owner->health > 0)) { return; } if (other == owner) { return; } } else { /* if fired by a doppleganger, set it to 10 second timeout */ self->wait = level.time + MINIMUM_FLY_TIME; } if ((self->wait - level.time) < MINIMUM_FLY_TIME) { self->wait = level.time + MINIMUM_FLY_TIME; } self->s.effects |= EF_BLASTER | EF_TRACKER; self->touch = hunter_touch; self->enemy = other; if ((self->spawnflags & SPHERE_DOPPLEGANGER) || !(owner && owner->client)) { return; } if (!((int)dmflags->value & DF_FORCE_RESPAWN) && (huntercam && (huntercam->value))) { VectorSubtract(other->s.origin, self->s.origin, dir); dist = VectorLength(dir); if (dist >= 192) { /* detach owner from body and send him flying */ owner->movetype = MOVETYPE_FLYMISSILE; /* gib like we just died, even though we didn't, really. */ body_gib(owner); /* move the sphere to the owner's current viewpoint./ we know it's a valid spot (or will be momentarily) */ VectorCopy(owner->s.origin, self->s.origin); self->s.origin[2] += owner->viewheight; /* move the player's origin to the sphere's new origin */ VectorCopy(self->s.origin, owner->s.origin); VectorCopy(self->s.angles, owner->s.angles); VectorCopy(self->s.angles, owner->client->v_angle); VectorClear(owner->mins); VectorClear(owner->maxs); VectorSet(owner->mins, -5, -5, -5); VectorSet(owner->maxs, 5, 5, 5); owner->client->ps.fov = 140; owner->s.modelindex = 0; owner->s.modelindex2 = 0; owner->viewheight = 8; owner->solid = SOLID_NOT; owner->flags |= FL_SAM_RAIMI; gi.linkentity(owner); self->solid = SOLID_BBOX; gi.linkentity(self); } } } void defender_pain(edict_t *self, edict_t *other, float kick, int damage) { if (!self || !other) { return; } if (other == self->owner) { return; } self->enemy = other; } void vengeance_pain(edict_t *self, edict_t *other, float kick, int damage) { if (!self || !other) { return; } if (self->enemy) { return; } if (!(self->spawnflags & SPHERE_DOPPLEGANGER)) { if (self->owner->health >= 25) { return; } if (other == self->owner) { return; } } else { self->wait = level.time + MINIMUM_FLY_TIME; } if ((self->wait - level.time) < MINIMUM_FLY_TIME) { self->wait = level.time + MINIMUM_FLY_TIME; } self->s.effects |= EF_ROCKET; self->touch = vengeance_touch; self->enemy = other; } void defender_think(edict_t *self) { if (!self) { return; } if (!self->owner) { G_FreeEdict(self); return; } /* if we've exited the level, just remove ourselves. */ if (level.intermissiontime) { sphere_think_explode(self); return; } if (self->owner->health <= 0) { sphere_think_explode(self); return; } self->s.frame++; if (self->s.frame > 19) { self->s.frame = 0; } if (self->enemy) { if (self->enemy->health > 0) { defender_shoot(self, self->enemy); } else { self->enemy = NULL; } } sphere_fly(self); if (self->inuse) { self->nextthink = level.time + 0.1; } } void hunter_think(edict_t *self) { edict_t *owner; vec3_t dir, ang; if (!self) { return; } /* if we've exited the level, just remove ourselves. */ if (level.intermissiontime) { sphere_think_explode(self); return; } owner = self->owner; if (!owner && !(self->spawnflags & SPHERE_DOPPLEGANGER)) { G_FreeEdict(self); return; } if (owner) { self->ideal_yaw = owner->s.angles[YAW]; } else if (self->enemy) /* fired by doppleganger */ { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); vectoangles2(dir, ang); self->ideal_yaw = ang[YAW]; } M_ChangeYaw(self); if (self->enemy) { sphere_chase(self, 0); /* deal with sam raimi cam */ if (owner && (owner->flags & FL_SAM_RAIMI)) { if (self->inuse) { owner->movetype = MOVETYPE_FLYMISSILE; LookAtKiller(owner, self, self->enemy); /* owner is flying with us, move him too */ owner->movetype = MOVETYPE_FLYMISSILE; owner->viewheight = self->s.origin[2] - owner->s.origin[2]; VectorCopy(self->s.origin, owner->s.origin); VectorCopy(self->velocity, owner->velocity); VectorClear(owner->mins); VectorClear(owner->maxs); gi.linkentity(owner); } else /* sphere timed out */ { VectorClear(owner->velocity); owner->movetype = MOVETYPE_NONE; gi.linkentity(owner); } } } else { sphere_fly(self); } if (self->inuse) { self->nextthink = level.time + 0.1; } } void vengeance_think(edict_t *self) { if (!self) { return; } /* if we've exited the level, just remove ourselves. */ if (level.intermissiontime) { sphere_think_explode(self); return; } if (!(self->owner) && !(self->spawnflags & SPHERE_DOPPLEGANGER)) { G_FreeEdict(self); return; } if (self->enemy) { sphere_chase(self, 1); } else { sphere_fly(self); } if (self->inuse) { self->nextthink = level.time + 0.1; } } edict_t * Sphere_Spawn(edict_t *owner, int spawnflags) { edict_t *sphere; if (!owner) { return NULL; } sphere = G_Spawn(); VectorCopy(owner->s.origin, sphere->s.origin); sphere->s.origin[2] = owner->absmax[2]; sphere->s.angles[YAW] = owner->s.angles[YAW]; sphere->solid = SOLID_BBOX; sphere->clipmask = MASK_SHOT; sphere->s.renderfx = RF_FULLBRIGHT | RF_IR_VISIBLE; sphere->movetype = MOVETYPE_FLYMISSILE; if (spawnflags & SPHERE_DOPPLEGANGER) { sphere->teammaster = owner->teammaster; } else { sphere->owner = owner; } sphere->classname = "sphere"; sphere->yaw_speed = 40; sphere->monsterinfo.attack_finished = 0; sphere->spawnflags = spawnflags; /* need this for the HUD to recognize sphere */ /* PMM */ sphere->takedamage = DAMAGE_NO; switch (spawnflags & SPHERE_TYPE) { case SPHERE_DEFENDER: sphere->s.modelindex = gi.modelindex("models/items/defender/tris.md2"); sphere->s.modelindex2 = gi.modelindex("models/items/shell/tris.md2"); sphere->s.sound = gi.soundindex("spheres/d_idle.wav"); sphere->pain = defender_pain; sphere->wait = level.time + DEFENDER_LIFESPAN; sphere->die = sphere_explode; sphere->think = defender_think; break; case SPHERE_HUNTER: sphere->s.modelindex = gi.modelindex("models/items/hunter/tris.md2"); sphere->s.sound = gi.soundindex("spheres/h_idle.wav"); sphere->wait = level.time + HUNTER_LIFESPAN; sphere->pain = hunter_pain; sphere->die = sphere_if_idle_die; sphere->think = hunter_think; break; case SPHERE_VENGEANCE: sphere->s.modelindex = gi.modelindex("models/items/vengnce/tris.md2"); sphere->s.sound = gi.soundindex("spheres/v_idle.wav"); sphere->wait = level.time + VENGEANCE_LIFESPAN; sphere->pain = vengeance_pain; sphere->die = sphere_if_idle_die; sphere->think = vengeance_think; VectorSet(sphere->avelocity, 30, 30, 0); break; default: gi.dprintf("Tried to create an invalid sphere\n"); G_FreeEdict(sphere); return NULL; } sphere->nextthink = level.time + 0.1; gi.linkentity(sphere); return sphere; } void Own_Sphere(edict_t *self, edict_t *sphere) { if (!sphere || !self) { return; } /* ownership only for players */ if (self->client) { /* if they don't have one */ if (!(self->client->owned_sphere)) { self->client->owned_sphere = sphere; } /* they already have one, take care of the old one */ else { if (self->client->owned_sphere->inuse) { G_FreeEdict(self->client->owned_sphere); self->client->owned_sphere = sphere; } else { self->client->owned_sphere = sphere; } } } } void Defender_Launch(edict_t *self) { edict_t *sphere; if (!self) { return; } sphere = Sphere_Spawn(self, SPHERE_DEFENDER); Own_Sphere(self, sphere); } void Hunter_Launch(edict_t *self) { edict_t *sphere; if (!self) { return; } sphere = Sphere_Spawn(self, SPHERE_HUNTER); Own_Sphere(self, sphere); } void Vengeance_Launch(edict_t *self) { edict_t *sphere; if (!self) { return; } sphere = Sphere_Spawn(self, SPHERE_VENGEANCE); Own_Sphere(self, sphere); } rogue-ROGUE_2_13/src/g_svcmds.c000066400000000000000000000130241477320066100163500ustar00rootroot00000000000000/* ======================================================================= * * Game side of server CMDs. At this time only the ipfilter. * * ======================================================================= */ #include "header/local.h" #define MAX_IPFILTERS 1024 /* * ============================================================================== * * PACKET FILTERING * * * You can add or remove addresses from the filter list with: * * addip * removeip * * The ip address is specified in dot format, and any unspecified digits will match * any value, so you can specify an entire class C network with "addip 192.246.40". * * Removeip will only remove an address specified exactly the same way. You cannot * addip a subnet, then removeip a single host. * * listip * Prints the current list of filters. * * writeip * Dumps "addip " commands to listip.cfg so it can be execed at a later date. * The filter lists are not saved and restored by default, because I beleive it * would cause too much confusion. * * filterban <0 or 1> * * If 1 (the default), then ip addresses matching the current list will be prohibited * from entering the game. This is the default setting. * * If 0, then only addresses matching the list will be allowed. This lets you easily * set up a private game, or a game that only allows players from your local network. * * ============================================================================== */ typedef struct { unsigned mask; unsigned compare; } ipfilter_t; ipfilter_t ipfilters[MAX_IPFILTERS]; int numipfilters; void Svcmd_Test_f(void) { gi.cprintf(NULL, PRINT_HIGH, "Svcmd_Test_f()\n"); } qboolean StringToFilter(char *s, ipfilter_t *f) { char num[128]; int i, j; byte b[4]; byte m[4]; if (!s || !f) { return false; } for (i = 0; i < 4; i++) { b[i] = 0; m[i] = 0; } for (i = 0; i < 4; i++) { if ((*s < '0') || (*s > '9')) { gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s); return false; } j = 0; while (*s >= '0' && *s <= '9') { num[j++] = *s++; } num[j] = 0; b[i] = atoi(num); if (b[i] != 0) { m[i] = 255; } if (!*s) { break; } s++; } /* PVS NOTE: maybe use memcpy here? */ f->mask = *(unsigned *)m; f->compare = *(unsigned *)b; return true; } qboolean SV_FilterPacket(char *from) { int i; unsigned in; byte m[4]; char *p; if (!from) { return false; } i = 0; p = from; while (*p && i < 4) { m[i] = 0; while (*p >= '0' && *p <= '9') { m[i] = m[i] * 10 + (*p - '0'); p++; } if (!*p || (*p == ':')) { break; } i++, p++; } /* PVS NOTE: maybe use memcpy here? */ in = *(unsigned *)m; for (i = 0; i < numipfilters; i++) { if ((in & ipfilters[i].mask) == ipfilters[i].compare) { return (filterban->value != 0); } } return (filterban->value == 0); } void SVCmd_AddIP_f(void) { int i; if (gi.argc() < 3) { gi.cprintf(NULL, PRINT_HIGH, "Usage: addip \n"); return; } for (i = 0; i < numipfilters; i++) { if (ipfilters[i].compare == 0xffffffff) { break; /* free spot */ } } if (i == numipfilters) { if (numipfilters == MAX_IPFILTERS) { gi.cprintf(NULL, PRINT_HIGH, "IP filter list is full\n"); return; } numipfilters++; } if (!StringToFilter(gi.argv(2), &ipfilters[i])) { ipfilters[i].compare = 0xffffffff; } } void SVCmd_RemoveIP_f(void) { ipfilter_t f; int i, j; if (gi.argc() < 3) { gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip \n"); return; } if (!StringToFilter(gi.argv(2), &f)) { return; } for (i = 0; i < numipfilters; i++) { if ((ipfilters[i].mask == f.mask) && (ipfilters[i].compare == f.compare)) { for (j = i + 1; j < numipfilters; j++) { ipfilters[j - 1] = ipfilters[j]; } numipfilters--; gi.cprintf(NULL, PRINT_HIGH, "Removed.\n"); return; } } gi.cprintf(NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2)); } void SVCmd_ListIP_f(void) { int i; byte b[4]; gi.cprintf(NULL, PRINT_HIGH, "Filter list:\n"); for (i = 0; i < numipfilters; i++) { /* PVS NOTE: maybe use memcpy here? */ *(unsigned *)b = ipfilters[i].compare; gi.cprintf(NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]); } } void SVCmd_WriteIP_f(void) { FILE *f; char name[MAX_OSPATH]; byte b[4]; int i; cvar_t *game; game = gi.cvar("game", "", 0); if (!*game->string) { sprintf(name, "%s/listip.cfg", GAMEVERSION); } else { sprintf(name, "%s/listip.cfg", game->string); } gi.cprintf(NULL, PRINT_HIGH, "Writing %s.\n", name); f = fopen(name, "wb"); if (!f) { gi.cprintf(NULL, PRINT_HIGH, "Couldn't open %s\n", name); return; } fprintf(f, "set filterban %d\n", (int)filterban->value); for (i = 0; i < numipfilters; i++) { /* PVS NOTE: maybe use memcpy here? */ *(unsigned *)b = ipfilters[i].compare; fprintf(f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]); } fclose(f); } /* * ServerCommand will be called when an "sv" command is issued. * The game can issue gi.argc() / gi.argv() commands to get the * rest of the parameters */ void ServerCommand(void) { char *cmd; cmd = gi.argv(1); if (Q_stricmp(cmd, "test") == 0) { Svcmd_Test_f(); } else if (Q_stricmp(cmd, "addip") == 0) { SVCmd_AddIP_f(); } else if (Q_stricmp(cmd, "removeip") == 0) { SVCmd_RemoveIP_f(); } else if (Q_stricmp(cmd, "listip") == 0) { SVCmd_ListIP_f(); } else if (Q_stricmp(cmd, "writeip") == 0) { SVCmd_WriteIP_f(); } else { gi.cprintf(NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd); } } rogue-ROGUE_2_13/src/g_target.c000066400000000000000000000547771477320066100163630ustar00rootroot00000000000000/* ======================================================================= * * Targets. * * ======================================================================= */ #include "header/local.h" #define TARGET_HELP_PRIMARY 1 #define TARGET_HELP_THINK_DELAY 0.3f #define LASER_ON 0x0001 #define LASER_RED 0x0002 #define LASER_GREEN 0x0004 #define LASER_BLUE 0x0008 #define LASER_YELLOW 0x0010 #define LASER_ORANGE 0x0020 #define LASER_FAT 0x0040 #define LASER_STOPWINDOW 0x0080 void ED_CallSpawn(edict_t *ent); /* * QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8) * * Fire an origin based temp entity event to the clients. * "style" type byte */ void Use_Target_Tent(edict_t *ent, edict_t *other, edict_t *activator) { gi.WriteByte(svc_temp_entity); gi.WriteByte(ent->style); gi.WritePosition(ent->s.origin); gi.multicast(ent->s.origin, MULTICAST_PVS); } void SP_target_temp_entity(edict_t *ent) { ent->use = Use_Target_Tent; } /* * QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable * * "noise" wav file to play * "attenuation" * -1 = none, send to whole level * 1 = normal fighting sounds * 2 = idle sound level * 3 = ambient sound level * "volume" 0.0 to 1.0 * * Normal sounds play each time the target is used. The reliable flag can be set for * crucial voiceovers. * * Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off. * Multiple identical looping sounds will just increase volume without any speed cost. */ void Use_Target_Speaker(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { int chan; if (!ent) { return; } if (ent->spawnflags & 3) { /* looping sound toggles */ if (ent->s.sound) { ent->s.sound = 0; /* turn it off */ } else { ent->s.sound = ent->noise_index; /* start it */ } } else { /* normal sound */ if (ent->spawnflags & 4) { chan = CHAN_VOICE | CHAN_RELIABLE; } else { chan = CHAN_VOICE; } /* use a positioned_sound, because this entity won't normally be sent to any clients because it is invisible */ gi.positioned_sound(ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0); } } void SP_target_speaker(edict_t *ent) { char buffer[MAX_QPATH]; if (!ent) { return; } if (!st.noise) { gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin)); return; } if (!strstr(st.noise, ".wav")) { Com_sprintf(buffer, sizeof(buffer), "%s.wav", st.noise); } else { Q_strlcpy(buffer, st.noise, sizeof(buffer)); } ent->noise_index = gi.soundindex(buffer); if (!ent->volume) { ent->volume = 1.0; } if (!ent->attenuation) { ent->attenuation = 1.0; } else if (ent->attenuation == -1) /* use -1 so 0 defaults to 1 */ { ent->attenuation = 0; } /* check for prestarted looping sound */ if (ent->spawnflags & 1) { ent->s.sound = ent->noise_index; } ent->use = Use_Target_Speaker; /* must link the entity so we get areas and clusters so the server can determine who to send updates to */ gi.linkentity(ent); } /* ========================================================== */ static void Target_Help_Apply(const char *msg, int is_primary) { char *curr; size_t sz; if (!msg) { return; } if (is_primary) { curr = game.helpmessage1; sz = sizeof(game.helpmessage1); } else { curr = game.helpmessage2; sz = sizeof(game.helpmessage2); } if (strcmp(curr, msg) == 0) { return; } Q_strlcpy(curr, msg, sz - 1); game.helpchanged++; } void Target_Help_Think(edict_t *ent) { if (!ent) { return; } Target_Help_Apply(ent->message, ent->spawnflags & TARGET_HELP_PRIMARY); ent->think = NULL; } void Use_Target_Help(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } if (level.time > TARGET_HELP_THINK_DELAY) { Target_Help_Apply(ent->message, ent->spawnflags & TARGET_HELP_PRIMARY); } else { /* The game is still pre-loading so delay the help message a bit, otherwise its changes to game structure will leak past save loads */ ent->think = Target_Help_Think; ent->nextthink = TARGET_HELP_THINK_DELAY; } } /* * QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1 * * When fired, the "message" key becomes the current personal computer string, * and the message light will be set on all clients status bars. */ void SP_target_help(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } if (!ent->message) { gi.dprintf("%s with no message at %s\n", ent->classname, vtos(ent->s.origin)); G_FreeEdict(ent); return; } ent->use = Use_Target_Help; } /* ========================================================== */ /* * QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) * * Counts a secret found. * These are single use targets. */ void use_target_secret(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } gi.sound(ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_secrets++; G_UseTargets(ent, activator); G_FreeEdict(ent); } void SP_target_secret(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } ent->use = use_target_secret; if (!st.noise) { st.noise = "misc/secret.wav"; } ent->noise_index = gi.soundindex(st.noise); ent->svflags = SVF_NOCLIENT; level.total_secrets++; /* map bug hack */ if (!Q_stricmp(level.mapname, "mine3") && (ent->s.origin[0] == 280) && (ent->s.origin[1] == -2048) && (ent->s.origin[2] == -624)) { ent->message = "You have found a secret area."; } } /* ========================================================== */ /* * QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8) * Counts a goal completed. * These are single use targets. */ void use_target_goal(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } gi.sound(ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_goals++; if (level.found_goals == level.total_goals) { gi.configstring(CS_CDTRACK, "0"); } G_UseTargets(ent, activator); G_FreeEdict(ent); } void SP_target_goal(edict_t *ent) { if (!ent) { return; } if (deathmatch->value) { /* auto-remove for deathmatch */ G_FreeEdict(ent); return; } ent->use = use_target_goal; if (!st.noise) { st.noise = "misc/secret.wav"; } ent->noise_index = gi.soundindex(st.noise); ent->svflags = SVF_NOCLIENT; level.total_goals++; } /* ========================================================== */ /* * QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8) * Spawns an explosion temporary entity when used. * * "delay" wait this long before going off * "dmg" how much radius damage should be done, defaults to 0 */ void target_explosion_explode(edict_t *self) { float save; if (!self) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PHS); T_RadiusDamage(self, self->activator, self->dmg, NULL, self->dmg + 40, MOD_EXPLOSIVE); save = self->delay; self->delay = 0; G_UseTargets(self, self->activator); self->delay = save; } void use_target_explosion(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->activator = activator; if (!self->delay) { target_explosion_explode(self); return; } self->think = target_explosion_explode; self->nextthink = level.time + self->delay; } void SP_target_explosion(edict_t *ent) { if (!ent) { return; } ent->use = use_target_explosion; ent->svflags = SVF_NOCLIENT; } /* ========================================================== */ /* * QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) * * Changes level to "map" when fired */ void use_target_changelevel(edict_t *self, edict_t *other, edict_t *activator) { if (!self || !other) { return; } if (level.intermissiontime) { return; /* already activated */ } if (!deathmatch->value && !coop->value) { if (g_edicts[1].health <= 0) { return; } } /* if noexit, do a ton of damage to other */ if (deathmatch->value && !((int)dmflags->value & DF_ALLOW_EXIT) && (other != world)) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } /* if multiplayer, let everyone know who hit the exit */ if (deathmatch->value) { if (activator && activator->client) { gi.bprintf(PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } } /* if going to a new unit, clear cross triggers */ if (strstr(self->map, "*")) { game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); } BeginIntermission(self); } void SP_target_changelevel(edict_t *ent) { if (!ent) { return; } if (!ent->map) { gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); G_FreeEdict(ent); return; } /* ugly hack because *SOMEBODY* screwed up their map */ if ((Q_stricmp(level.mapname, "fact1") == 0) && (Q_stricmp(ent->map, "fact3") == 0)) { ent->map = "fact3$secret1"; } ent->use = use_target_changelevel; ent->svflags = SVF_NOCLIENT; } /* ========================================================== */ /* * QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8) * Creates a particle splash effect when used. * * Set "sounds" to one of the following: * 1) sparks * 2) blue water * 3) brown water * 4) slime * 5) lava * 6) blood * * "count" how many pixels in the splash * "dmg" if set, does a radius damage at this location when it splashes * useful for lava/sparks */ void use_target_splash(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_SPLASH); gi.WriteByte(self->count); gi.WritePosition(self->s.origin); gi.WriteDir(self->movedir); gi.WriteByte(self->sounds); gi.multicast(self->s.origin, MULTICAST_PVS); if (self->dmg) { T_RadiusDamage(self, activator, self->dmg, NULL, self->dmg + 40, MOD_SPLASH); } } void SP_target_splash(edict_t *self) { if (!self) { return; } self->use = use_target_splash; G_SetMovedir(self->s.angles, self->movedir); if (!self->count) { self->count = 32; } self->svflags = SVF_NOCLIENT; } /* ========================================================== */ /* * QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8) * Set target to the type of entity you want spawned. * Useful for spawning monsters and gibs in the factory levels. * * For monsters: * Set direction to the facing you want it to have. * * For gibs: * Set direction if you want it moving and * speed how fast it should be moving otherwise it * will just be dropped */ void use_target_spawner(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { edict_t *ent; if (!self) { return; } ent = G_Spawn(); ent->classname = self->target; VectorCopy(self->s.origin, ent->s.origin); VectorCopy(self->s.angles, ent->s.angles); ED_CallSpawn(ent); gi.unlinkentity(ent); KillBox(ent); gi.linkentity(ent); if (self->speed) { VectorCopy(self->movedir, ent->velocity); } ent->s.renderfx |= RF_IR_VISIBLE; /* PGM */ } void SP_target_spawner(edict_t *self) { if (!self) { return; } self->use = use_target_spawner; self->svflags = SVF_NOCLIENT; if (self->speed) { G_SetMovedir(self->s.angles, self->movedir); VectorScale(self->movedir, self->speed, self->movedir); } } /* ========================================================== */ /* * QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS * Fires a blaster bolt in the set direction when triggered. * * dmg default is 15 * speed default is 1000 */ void use_target_blaster(edict_t *self, edict_t *other, edict_t *activator) { if (!self) { return; } fire_blaster(self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER); gi.sound(self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); } void SP_target_blaster(edict_t *self) { if (!self) { return; } self->use = use_target_blaster; G_SetMovedir(self->s.angles, self->movedir); self->noise_index = gi.soundindex("weapons/laser2.wav"); if (!self->dmg) { self->dmg = 15; } if (!self->speed) { self->speed = 1000; } self->svflags = SVF_NOCLIENT; } /* ========================================================== */ /* * QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 * * Once this trigger is touched/used, any trigger_crosslevel_target * with the same trigger number is automatically used when a level * is started within the same unit. It is OK to check multiple triggers. * Message, delay, target, and killtarget also work. */ void trigger_crosslevel_trigger_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } game.serverflags |= self->spawnflags; G_FreeEdict(self); } void SP_target_crosslevel_trigger(edict_t *self) { if (!self) { return; } self->svflags = SVF_NOCLIENT; self->use = trigger_crosslevel_trigger_use; } /* * QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 * * Triggered by a trigger_crosslevel elsewhere within a unit. * If multiple triggers are checked, all must be true. * Delay, target and killtarget also work. * * "delay" delay before using targets if the trigger has been activated (default 1) */ void target_crosslevel_target_think(edict_t *self) { if (!self) { return; } if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) { G_UseTargets(self, self); G_FreeEdict(self); } } void SP_target_crosslevel_target(edict_t *self) { if (!self) { return; } if (!self->delay) { self->delay = 1; } self->svflags = SVF_NOCLIENT; self->think = target_crosslevel_target_think; self->nextthink = level.time + self->delay; } /* ========================================================== */ /* * QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT WINDOWSTOP * When triggered, fires a laser. You can either set a target * or a direction. * * WINDOWSTOP - stops at CONTENTS_WINDOW */ void target_laser_think(edict_t *self) { edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; if (!self) { return; } if (self->spawnflags & 0x80000000) { count = 8; } else { count = 4; } if (self->enemy) { VectorCopy(self->movedir, last_movedir); VectorMA(self->enemy->absmin, 0.5, self->enemy->size, point); VectorSubtract(point, self->s.origin, self->movedir); VectorNormalize(self->movedir); if (!VectorCompare(self->movedir, last_movedir)) { self->spawnflags |= 0x80000000; } } ignore = self; VectorCopy(self->s.origin, start); VectorMA(start, 2048, self->movedir, end); while (1) { if (self->spawnflags & LASER_STOPWINDOW) { tr = gi.trace(start, NULL, NULL, end, ignore, MASK_SHOT); } else { tr = gi.trace(start, NULL, NULL, end, ignore, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); } if (!tr.ent) { break; } /* hurt it if we can */ if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER)) { T_Damage(tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); } /* if we hit something that's not a monster or player or is immune to lasers, we're done */ if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client) && !(tr.ent->svflags & SVF_DAMAGEABLE)) { if (self->spawnflags & 0x80000000) { self->spawnflags &= ~0x80000000; gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_LASER_SPARKS); gi.WriteByte(count); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.WriteByte(self->s.skinnum); gi.multicast(tr.endpos, MULTICAST_PVS); } break; } ignore = tr.ent; VectorCopy(tr.endpos, start); } VectorCopy(tr.endpos, self->s.old_origin); self->nextthink = level.time + FRAMETIME; } void target_laser_on(edict_t *self) { if (!self) { return; } if (!self->activator) { self->activator = self; } self->spawnflags |= 0x80000001; self->svflags &= ~SVF_NOCLIENT; target_laser_think(self); } void target_laser_off(edict_t *self) { if (!self) { return; } self->spawnflags &= ~1; self->svflags |= SVF_NOCLIENT; self->nextthink = 0; } void target_laser_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->activator = activator; if (self->spawnflags & 1) { target_laser_off(self); } else { target_laser_on(self); } } void target_laser_start(edict_t *self) { edict_t *ent; if (!self) { return; } self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; self->s.renderfx |= RF_BEAM | RF_TRANSLUCENT; self->s.modelindex = 1; /* must be non-zero */ /* set the beam diameter */ if (self->spawnflags & 64) { self->s.frame = 16; } else { self->s.frame = 4; } /* set the color */ if (self->spawnflags & 2) { self->s.skinnum = 0xf2f2f0f0; } else if (self->spawnflags & 4) { self->s.skinnum = 0xd0d1d2d3; } else if (self->spawnflags & 8) { self->s.skinnum = 0xf3f3f1f1; } else if (self->spawnflags & 16) { self->s.skinnum = 0xdcdddedf; } else if (self->spawnflags & 32) { self->s.skinnum = 0xe0e1e2e3; } if (!self->enemy) { if (self->target) { ent = G_Find(NULL, FOFS(targetname), self->target); if (!ent) { gi.dprintf("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); } self->enemy = ent; } else { G_SetMovedir(self->s.angles, self->movedir); } } self->use = target_laser_use; self->think = target_laser_think; if (!self->dmg) { self->dmg = 1; } VectorSet(self->mins, -8, -8, -8); VectorSet(self->maxs, 8, 8, 8); gi.linkentity(self); if (self->spawnflags & 1) { target_laser_on(self); } else { target_laser_off(self); } } void SP_target_laser(edict_t *self) { if (!self) { return; } self->think = target_laser_start; self->nextthink = level.time + 1; } /* ========================================================== */ /* * QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE * * speed How many seconds the ramping will take * message two letters; starting lightlevel and ending lightlevel */ void target_lightramp_think(edict_t *self) { char style[2]; if (!self) { return; } style[0] = 'a' + self->movedir[0] + (level.time - self->timestamp) / FRAMETIME * self->movedir[2]; style[1] = 0; gi.configstring(CS_LIGHTS + self->enemy->style, style); if ((level.time - self->timestamp) < self->speed) { self->nextthink = level.time + FRAMETIME; } else if (self->spawnflags & 1) { char temp; temp = self->movedir[0]; self->movedir[0] = self->movedir[1]; self->movedir[1] = temp; self->movedir[2] *= -1; } } void target_lightramp_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (!self->enemy) { edict_t *e; /* check all the targets */ e = NULL; while (1) { e = G_Find(e, FOFS(targetname), self->target); if (!e) { break; } if (strcmp(e->classname, "light") != 0) { gi.dprintf("%s at %s ", self->classname, vtos(self->s.origin)); gi.dprintf("target %s (%s at %s) is not a light\n", self->target, e->classname, vtos(e->s.origin)); } else { self->enemy = e; } } if (!self->enemy) { gi.dprintf("%s target %s not found at %s\n", self->classname, self->target, vtos(self->s.origin)); G_FreeEdict(self); return; } } self->timestamp = level.time; target_lightramp_think(self); } void SP_target_lightramp(edict_t *self) { if (!self) { return; } if (!self->message || (strlen(self->message) != 2) || (self->message[0] < 'a') || (self->message[0] > 'z') || (self->message[1] < 'a') || (self->message[1] > 'z') || (self->message[0] == self->message[1])) { gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin)); G_FreeEdict(self); return; } if (deathmatch->value) { G_FreeEdict(self); return; } if (!self->target) { gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin)); G_FreeEdict(self); return; } self->svflags |= SVF_NOCLIENT; self->use = target_lightramp_use; self->think = target_lightramp_think; self->movedir[0] = self->message[0] - 'a'; self->movedir[1] = self->message[1] - 'a'; self->movedir[2] = (self->movedir[1] - self->movedir[0]) / (self->speed / FRAMETIME); } /* ========================================================== */ /* * QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) SILENT * * When triggered, this initiates a level-wide earthquake. * All players and monsters are affected. * "speed" severity of the quake (default:200) * "count" duration of the quake (default:5) */ void target_earthquake_think(edict_t *self) { int i; edict_t *e; if (!self) { return; } if (!(self->spawnflags & 1)) { if (self->last_move_time < level.time) { gi.positioned_sound(self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0, ATTN_NONE, 0); self->last_move_time = level.time + 0.5; } } for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) { continue; } if (!e->client) { continue; } if (!e->groundentity) { continue; } e->groundentity = NULL; e->velocity[0] += crandom() * 150; e->velocity[1] += crandom() * 150; e->velocity[2] = self->speed * (100.0 / e->mass); } if (level.time < self->timestamp) { self->nextthink = level.time + FRAMETIME; } } void target_earthquake_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } self->timestamp = level.time + self->count; self->nextthink = level.time + FRAMETIME; self->activator = activator; self->last_move_time = 0; } void SP_target_earthquake(edict_t *self) { if (!self) { return; } if (!self->targetname) { gi.dprintf("untargeted %s at %s\n", self->classname, vtos( self->s.origin)); } if (!self->count) { self->count = 5; } if (!self->speed) { self->speed = 200; } self->svflags |= SVF_NOCLIENT; self->think = target_earthquake_think; self->use = target_earthquake_use; if (!(self->spawnflags & 1)) { self->noise_index = gi.soundindex("world/quake.wav"); } } rogue-ROGUE_2_13/src/g_trigger.c000066400000000000000000000357751477320066100165350ustar00rootroot00000000000000/* ======================================================================= * * Trigger. * * ======================================================================= */ #include "header/local.h" #define TRIGGER_MONSTER 0x01 #define TRIGGER_NOT_PLAYER 0x02 #define TRIGGER_TRIGGERED 0x04 #define TRIGGER_TOGGLE 0x08 #define PUSH_ONCE 0x01 #define PUSH_START_OFF 0x02 #define PUSH_SILENT 0x04 static int windsound; void InitTrigger(edict_t *self) { if (!self) { return; } if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } self->solid = SOLID_TRIGGER; self->movetype = MOVETYPE_NONE; gi.setmodel(self, self->model); self->svflags = SVF_NOCLIENT; } /* * the wait time has passed, so set * back up for another activation */ void multi_wait(edict_t *ent) { if (!ent) { return; } ent->nextthink = 0; } void multi_trigger(edict_t *ent) { if (!ent) { return; } if (ent->nextthink) { return; /* already been triggered */ } G_UseTargets(ent, ent->activator); if (ent->wait > 0) { ent->think = multi_wait; ent->nextthink = level.time + ent->wait; } else { /* we can't just remove (self) here, because this is a touch function called while looping through area links... */ ent->touch = NULL; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEdict; } } void Use_Multi(edict_t *ent, edict_t *other /* unused */, edict_t *activator) { if (!ent || !activator) { return; } if (ent->spawnflags & TRIGGER_TOGGLE) { if (ent->solid == SOLID_TRIGGER) { ent->solid = SOLID_NOT; } else { ent->solid = SOLID_TRIGGER; } gi.linkentity(ent); } else { ent->activator = activator; multi_trigger(ent); } } void Touch_Multi(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (other->client) { if (self->spawnflags & 2) { return; } } else if (other->svflags & SVF_MONSTER) { if (!(self->spawnflags & 1)) { return; } } else { return; } if (!VectorCompare(self->movedir, vec3_origin)) { vec3_t forward; AngleVectors(other->s.angles, forward, NULL, NULL); if (_DotProduct(forward, self->movedir) < 0) { return; } } self->activator = other; multi_trigger(self); } /* * QUAKED trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED TOGGLE * Variable sized repeatable trigger. Must be targeted at one or more entities. * If "delay" is set, the trigger waits some time after activating before firing. * "wait" : Seconds between triggerings. (.2 default) * * TOGGLE - using this trigger will activate/deactivate it. trigger will begin inactive. * * sounds * 1) secret * 2) beep beep * 3) large switch * 4) * set "message" to text string */ void trigger_enable(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->solid = SOLID_TRIGGER; self->use = Use_Multi; gi.linkentity(self); } void SP_trigger_multiple(edict_t *ent) { if (!ent) { return; } if (ent->sounds == 1) { ent->noise_index = gi.soundindex("misc/secret.wav"); } else if (ent->sounds == 2) { ent->noise_index = gi.soundindex("misc/talk.wav"); } else if (ent->sounds == 3) { ent->noise_index = gi.soundindex("misc/trigger1.wav"); } if (!ent->wait) { ent->wait = 0.2; } ent->touch = Touch_Multi; ent->movetype = MOVETYPE_NONE; ent->svflags |= SVF_NOCLIENT; if (ent->spawnflags & (TRIGGER_TRIGGERED | TRIGGER_TOGGLE)) { ent->solid = SOLID_NOT; ent->use = trigger_enable; } else { ent->solid = SOLID_TRIGGER; ent->use = Use_Multi; } if (!VectorCompare(ent->s.angles, vec3_origin)) { G_SetMovedir(ent->s.angles, ent->movedir); } gi.setmodel(ent, ent->model); gi.linkentity(ent); } /* * QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED * * 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 TRIGGERED, this trigger must be triggered before it is live. * * sounds * 1) secret * 2) beep beep * 3) large switch * 4) * * "message" string to be displayed when triggered */ void SP_trigger_once(edict_t *ent) { if (!ent) { return; } /* make old maps work because I messed up on flag assignments here */ if (ent->spawnflags & 1) { vec3_t v; VectorMA(ent->mins, 0.5, ent->size, v); ent->spawnflags &= ~1; ent->spawnflags |= 4; gi.dprintf("fixed TRIGGERED flag on %s at %s\n", ent->classname, vtos(v)); } ent->wait = -1; SP_trigger_multiple(ent); } /* * QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) * * This fixed size trigger cannot be touched, it can only be fired by other events. */ void trigger_relay_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } G_UseTargets(self, activator); } void SP_trigger_relay(edict_t *self) { if (!self) { return; } self->use = trigger_relay_use; } /* * QUAKED trigger_key (.5 .5 .5) (-8 -8 -8) (8 8 8) * * A relay trigger that only fires it's targets if player has the proper key. * Use "item" to specify the required key, for example "key_data_cd" */ void trigger_key_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { int index; if (!self|| !activator) { return; } if (!self->item) { return; } if (!activator->client) { return; } index = ITEM_INDEX(self->item); if (!activator->client->pers.inventory[index]) { if (level.time < self->touch_debounce_time) { return; } self->touch_debounce_time = level.time + 5.0; gi.centerprintf(activator, "You need the %s", self->item->pickup_name); gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/keytry.wav"), 1, ATTN_NORM, 0); return; } gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/keyuse.wav"), 1, ATTN_NORM, 0); if (coop->value) { int player; edict_t *ent; if (strcmp(self->item->classname, "key_power_cube") == 0) { int cube; for (cube = 0; cube < 8; cube++) { if (activator->client->pers.power_cubes & (1 << cube)) { break; } } for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (ent->client->pers.power_cubes & (1 << cube)) { ent->client->pers.inventory[index]--; ent->client->pers.power_cubes &= ~(1 << cube); } } } else { for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } ent->client->pers.inventory[index] = 0; } } } else { activator->client->pers.inventory[index]--; } G_UseTargets(self, activator); self->use = NULL; } void SP_trigger_key(edict_t *self) { if (!self) { return; } if (!st.item) { gi.dprintf("no key item for trigger_key at %s\n", vtos(self->s.origin)); return; } self->item = FindItemByClassname(st.item); if (!self->item) { gi.dprintf("item %s not found for trigger_key at %s\n", st.item, vtos(self->s.origin)); return; } if (!self->target) { gi.dprintf("%s at %s has no target\n", self->classname, vtos(self->s.origin)); return; } gi.soundindex("misc/keytry.wav"); gi.soundindex("misc/keyuse.wav"); self->use = trigger_key_use; } /* * QUAKED trigger_counter (.5 .5 .5) ? nomessage * * Acts as an intermediary for an action that takes multiple inputs. * * If nomessage is not set, t will print "1 more.. " etc when triggered * and "sequence complete" when finished. * * After the counter has been triggered "count" times (default 2), * it will fire all of it's targets and remove itself. */ void trigger_counter_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } if (self->count == 0) { return; } self->count--; if (self->count) { if (!(self->spawnflags & 1)) { gi.centerprintf(activator, "%i more to go...", self->count); gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0); } return; } if (!(self->spawnflags & 1)) { gi.centerprintf(activator, "Sequence completed!"); gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0); } self->activator = activator; multi_trigger(self); } void SP_trigger_counter(edict_t *self) { if (!self) { return; } self->wait = -1; if (!self->count) { self->count = 2; } self->use = trigger_counter_use; } /* * QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8) * * This trigger will always fire. It is activated by the world. */ void SP_trigger_always(edict_t *ent) { if (!ent) { return; } /* we must have some delay to make sure our use targets are present */ if (ent->delay < 0.2) { ent->delay = 0.2; } G_UseTargets(ent, ent); } void trigger_push_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (strcmp(other->classname, "grenade") == 0) { VectorScale(self->movedir, self->speed * 10, other->velocity); } else if (other->health > 0) { VectorScale(self->movedir, self->speed * 10, other->velocity); if (other->client) { /* don't take falling damage immediately from this */ VectorCopy(other->velocity, other->client->oldvelocity); if (!(self->spawnflags & PUSH_SILENT) && (other->fly_sound_debounce_time < level.time)) { other->fly_sound_debounce_time = level.time + 1.5; gi.sound(other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0); } } } if (self->spawnflags & PUSH_ONCE) { G_FreeEdict(self); } } void trigger_push_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->solid == SOLID_NOT) { self->solid = SOLID_TRIGGER; } else { self->solid = SOLID_NOT; } gi.linkentity(self); } /* * QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE START_OFF SILENT * Pushes the player * "speed" defaults to 1000 * * If targeted, it will toggle on and off when used. * * START_OFF - toggled trigger_push begins in off setting * SILENT - doesn't make wind noise */ void SP_trigger_push(edict_t *self) { if (!self) { return; } InitTrigger(self); windsound = gi.soundindex("misc/windfly.wav"); self->touch = trigger_push_touch; if (!self->speed) { self->speed = 1000; } if (self->targetname) /* toggleable */ { self->use = trigger_push_use; if (self->spawnflags & PUSH_START_OFF) { self->solid = SOLID_NOT; } } else if (self->spawnflags & PUSH_START_OFF) { gi.dprintf("trigger_push is START_OFF but not targeted.\n"); self->svflags = 0; self->touch = NULL; self->solid = SOLID_BSP; self->movetype = MOVETYPE_PUSH; } gi.linkentity(self); } /* * QUAKED trigger_hurt (.5 .5 .5) ? START_OFF TOGGLE SILENT NO_PROTECTION SLOW * * Any entity that touches this will be hurt. * * It does dmg points of damage each server frame * * SILENT supresses playing the sound * SLOW changes the damage rate to once per second * NO_PROTECTION *nothing* stops the damage * * "dmg" default 5 (whole numbers only) * */ void hurt_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->solid == SOLID_NOT) { self->solid = SOLID_TRIGGER; } else { self->solid = SOLID_NOT; } gi.linkentity(self); if (!(self->spawnflags & 2)) { self->use = NULL; } } void hurt_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { int dflags; if (!self || !other) { return; } if (!other->takedamage) { return; } if (self->timestamp > level.time) { return; } if (self->spawnflags & 16) { self->timestamp = level.time + 1; } else { self->timestamp = level.time + FRAMETIME; } if (!(self->spawnflags & 4)) { if ((level.framenum % 10) == 0) { gi.sound(other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0); } } if (self->spawnflags & 8) { dflags = DAMAGE_NO_PROTECTION; } else { dflags = 0; } T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, self->dmg, dflags, MOD_TRIGGER_HURT); } void SP_trigger_hurt(edict_t *self) { if (!self) { return; } InitTrigger(self); self->noise_index = gi.soundindex("world/electro.wav"); self->touch = hurt_touch; if (!self->dmg) { self->dmg = 5; } if (self->spawnflags & 1) { self->solid = SOLID_NOT; } else { self->solid = SOLID_TRIGGER; } if (self->spawnflags & 2) { self->use = hurt_use; } gi.linkentity(self); } void trigger_gravity_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } if (self->solid == SOLID_NOT) { self->solid = SOLID_TRIGGER; } else { self->solid = SOLID_NOT; } gi.linkentity(self); } /* PGM */ void trigger_gravity_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } other->gravity = self->gravity; } /* * QUAKED trigger_gravity (.5 .5 .5) ? TOGGLE START_OFF * Changes the touching entites gravity to * the value of "gravity". 1.0 is standard * gravity for the level. * * TOGGLE - trigger_gravity can be turned on and off * START_OFF - trigger_gravity starts turned off (implies TOGGLE) */ void SP_trigger_gravity(edict_t *self) { if (!self) { return; } if (st.gravity == 0) { gi.dprintf("trigger_gravity without gravity set at %s\n", vtos(self->s.origin)); G_FreeEdict(self); return; } InitTrigger(self); self->gravity = strtof(st.gravity, (char **)NULL); if (self->spawnflags & 1) /* TOGGLE */ { self->use = trigger_gravity_use; } if (self->spawnflags & 2) /* START_OFF */ { self->use = trigger_gravity_use; self->solid = SOLID_NOT; } self->touch = trigger_gravity_touch; gi.linkentity(self); } /* * QUAKED trigger_monsterjump (.5 .5 .5) ? * * Walking monsters that touch this will jump in the direction of the trigger's angle * "speed" default to 200, the speed thrown forward * "height" default to 200, the speed thrown upwards */ void trigger_monsterjump_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (other->flags & (FL_FLY | FL_SWIM)) { return; } if (other->svflags & SVF_DEADMONSTER) { return; } if (!(other->svflags & SVF_MONSTER)) { return; } /* set XY even if not on ground, so the jump will clear lips */ other->velocity[0] = self->movedir[0] * self->speed; other->velocity[1] = self->movedir[1] * self->speed; if (!other->groundentity) { return; } other->groundentity = NULL; other->velocity[2] = self->movedir[2]; } void SP_trigger_monsterjump(edict_t *self) { if (!self) { return; } if (!self->speed) { self->speed = 200; } if (!st.height) { st.height = 200; } if (self->s.angles[YAW] == 0) { self->s.angles[YAW] = 360; } InitTrigger(self); self->touch = trigger_monsterjump_touch; self->movedir[2] = st.height; } rogue-ROGUE_2_13/src/g_turret.c000066400000000000000000000375631477320066100164140ustar00rootroot00000000000000/* ======================================================================= * * Turrets aka big cannons with a driver. * * ======================================================================= */ #include "header/local.h" qboolean FindTarget(edict_t *self); void infantry_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void infantry_stand(edict_t *self); void monster_use(edict_t *self, edict_t *other, edict_t *activator); void SpawnTargetingSystem(edict_t *turret); void AnglesNormalize(vec3_t vec) { while (vec[0] > 360) { vec[0] -= 360; } while (vec[0] < 0) { vec[0] += 360; } while (vec[1] > 360) { vec[1] -= 360; } while (vec[1] < 0) { vec[1] += 360; } } float SnapToEights(float x) { x *= 8.0; if (x > 0.0) { x += 0.5; } else { x -= 0.5; } return 0.125 * (int)x; } void turret_blocked(edict_t *self, edict_t *other) { if (!self || !other) { return; } edict_t *attacker; if (other->takedamage) { if (self->teammaster->owner) { attacker = self->teammaster->owner; } else { attacker = self->teammaster; } T_Damage(other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH); } } /* * QUAKED turret_breach (0 0 0) ? * This portion of the turret can change both pitch and yaw. * The model should be made with a flat pitch. * It (and the associated base) need to be oriented towards 0. * Use "angle" to set the starting angle. * * "speed" default 50 * "dmg" default 10 * "angle" point this forward * "target" point this at an info_notnull at the muzzle tip * "minpitch" min acceptable pitch angle : default -30 * "maxpitch" max acceptable pitch angle : default 30 * "minyaw" min acceptable yaw angle : default 0 * "maxyaw" max acceptable yaw angle : default 360 */ void turret_breach_fire(edict_t *self) { vec3_t f, r, u; vec3_t start; int damage; int speed; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); VectorMA(self->s.origin, self->move_origin[0], f, start); VectorMA(start, self->move_origin[1], r, start); VectorMA(start, self->move_origin[2], u, start); damage = 100 + random() * 50; speed = 550 + 50 * skill->value; fire_rocket(self->teammaster->owner, start, f, damage, speed, 150, damage); gi.positioned_sound(start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); } void turret_breach_think(edict_t *self) { edict_t *ent; vec3_t current_angles; vec3_t delta; if (!self) { return; } VectorCopy(self->s.angles, current_angles); AnglesNormalize(current_angles); AnglesNormalize(self->move_angles); if (self->move_angles[PITCH] > 180) { self->move_angles[PITCH] -= 360; } /* clamp angles to mins & maxs */ if (self->move_angles[PITCH] > self->pos1[PITCH]) { self->move_angles[PITCH] = self->pos1[PITCH]; } else if (self->move_angles[PITCH] < self->pos2[PITCH]) { self->move_angles[PITCH] = self->pos2[PITCH]; } if ((self->move_angles[YAW] < self->pos1[YAW]) || (self->move_angles[YAW] > self->pos2[YAW])) { float dmin, dmax; dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]); if (dmin < -180) { dmin += 360; } else if (dmin > 180) { dmin -= 360; } dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]); if (dmax < -180) { dmax += 360; } else if (dmax > 180) { dmax -= 360; } if (fabs(dmin) < fabs(dmax)) { self->move_angles[YAW] = self->pos1[YAW]; } else { self->move_angles[YAW] = self->pos2[YAW]; } } VectorSubtract(self->move_angles, current_angles, delta); if (delta[0] < -180) { delta[0] += 360; } else if (delta[0] > 180) { delta[0] -= 360; } if (delta[1] < -180) { delta[1] += 360; } else if (delta[1] > 180) { delta[1] -= 360; } delta[2] = 0; if (delta[0] > self->speed * FRAMETIME) { delta[0] = self->speed * FRAMETIME; } if (delta[0] < -1 * self->speed * FRAMETIME) { delta[0] = -1 * self->speed * FRAMETIME; } if (delta[1] > self->speed * FRAMETIME) { delta[1] = self->speed * FRAMETIME; } if (delta[1] < -1 * self->speed * FRAMETIME) { delta[1] = -1 * self->speed * FRAMETIME; } VectorScale(delta, 1.0 / FRAMETIME, self->avelocity); self->nextthink = level.time + FRAMETIME; for (ent = self->teammaster; ent; ent = ent->teamchain) { ent->avelocity[1] = self->avelocity[1]; } /* if we have adriver, adjust his velocities */ if (self->owner) { float angle; float target_z; float diff; vec3_t target; vec3_t dir; /* angular is easy, just copy ours */ self->owner->avelocity[0] = self->avelocity[0]; self->owner->avelocity[1] = self->avelocity[1]; /* x & y */ angle = self->s.angles[1] + self->owner->move_origin[1]; angle *= (M_PI * 2 / 360); target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]); target[1] = SnapToEights(self->s.origin[1] + sin(angle) * self->owner->move_origin[0]); target[2] = self->owner->s.origin[2]; VectorSubtract(target, self->owner->s.origin, dir); self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME; self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME; /* z */ angle = self->s.angles[PITCH] * (M_PI * 2 / 360); target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]); diff = target_z - self->owner->s.origin[2]; self->owner->velocity[2] = diff * 1.0 / FRAMETIME; if (self->spawnflags & 65536) { turret_breach_fire(self); self->spawnflags &= ~65536; } } } void turret_breach_finish_init(edict_t *self) { if (!self) { return; } /* get and save info for muzzle location */ if (!self->target) { gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin)); } else { self->target_ent = G_PickTarget(self->target); if (self->target_ent) { VectorSubtract(self->target_ent->s.origin, self->s.origin, self->move_origin); G_FreeEdict(self->target_ent); } else { gi.dprintf("could not find target entity for %s at %s\n", self->classname, vtos(self->s.origin)); } } self->teammaster->dmg = self->dmg; self->think = turret_breach_think; self->think(self); } void SP_turret_breach(edict_t *self) { if (!self) { return; } self->solid = SOLID_BSP; self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); if (!self->speed) { self->speed = 50; } if (!self->dmg) { self->dmg = 10; } if (!st.minpitch) { st.minpitch = -30; } if (!st.maxpitch) { st.maxpitch = 30; } if (!st.maxyaw) { st.maxyaw = 360; } self->pos1[PITCH] = -1 * st.minpitch; self->pos1[YAW] = st.minyaw; self->pos2[PITCH] = -1 * st.maxpitch; self->pos2[YAW] = st.maxyaw; self->ideal_yaw = self->s.angles[YAW]; self->move_angles[YAW] = self->ideal_yaw; self->blocked = turret_blocked; self->think = turret_breach_finish_init; self->nextthink = level.time + FRAMETIME; gi.linkentity(self); } /* * QUAKED turret_base (0 0 0) ? * This portion of the turret changes yaw only. * MUST be teamed with a turret_breach. */ void SP_turret_base(edict_t *self) { if (!self) { return; } self->solid = SOLID_BSP; self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); self->blocked = turret_blocked; gi.linkentity(self); } /* * QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32) * Must NOT be on the team with the rest of the turret parts. * Instead it must target the turret_breach. */ void turret_driver_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { edict_t *ent; if (!self || !inflictor || !attacker) { return; } /* level the gun */ self->target_ent->move_angles[0] = 0; /* remove the driver from the end of them team chain */ for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain) { } ent->teamchain = NULL; self->teammaster = NULL; self->flags &= ~FL_TEAMSLAVE; self->target_ent->owner = NULL; self->target_ent->teammaster->owner = NULL; infantry_die(self, inflictor, attacker, damage, point); } void turret_driver_think(edict_t *self) { vec3_t target; vec3_t dir; float reaction_time; if (!self) { return; } self->nextthink = level.time + FRAMETIME; if (self->enemy && (!self->enemy->inuse || (self->enemy->health <= 0))) { self->enemy = NULL; } if (!self->enemy) { if (!FindTarget(self)) { return; } self->monsterinfo.trail_time = level.time; self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; } else { if (visible(self, self->enemy)) { if (self->monsterinfo.aiflags & AI_LOST_SIGHT) { self->monsterinfo.trail_time = level.time; self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; } } else { self->monsterinfo.aiflags |= AI_LOST_SIGHT; return; } } /* let the turret know where we want it to aim */ VectorCopy(self->enemy->s.origin, target); target[2] += self->enemy->viewheight; VectorSubtract(target, self->target_ent->s.origin, dir); vectoangles(dir, self->target_ent->move_angles); /* decide if we should shoot */ if (level.time < self->monsterinfo.attack_finished) { return; } reaction_time = (3 - skill->value) * 1.0; if ((level.time - self->monsterinfo.trail_time) < reaction_time) { return; } self->monsterinfo.attack_finished = level.time + reaction_time + 1.0; self->target_ent->spawnflags |= 65536; } void turret_driver_link(edict_t *self) { vec3_t vec; edict_t *ent; if (!self) { return; } self->think = turret_driver_think; self->nextthink = level.time + FRAMETIME; self->target_ent = G_PickTarget(self->target); self->target_ent->owner = self; self->target_ent->teammaster->owner = self; VectorCopy(self->target_ent->s.angles, self->s.angles); vec[0] = self->target_ent->s.origin[0] - self->s.origin[0]; vec[1] = self->target_ent->s.origin[1] - self->s.origin[1]; vec[2] = 0; self->move_origin[0] = VectorLength(vec); VectorSubtract(self->s.origin, self->target_ent->s.origin, vec); vectoangles(vec, vec); AnglesNormalize(vec); self->move_origin[1] = vec[1]; self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2]; /* add the driver to the end of them team chain */ for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain) { } ent->teamchain = self; self->teammaster = self->target_ent->teammaster; self->flags |= FL_TEAMSLAVE; } void SP_turret_driver(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->movetype = MOVETYPE_PUSH; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->health = 100; self->gib_health = 0; self->mass = 200; self->viewheight = 24; self->die = turret_driver_die; self->monsterinfo.stand = infantry_stand; self->flags |= FL_NO_KNOCKBACK; level.total_monsters++; self->svflags |= SVF_MONSTER; self->s.renderfx |= RF_FRAMELERP; self->takedamage = DAMAGE_AIM; self->use = monster_use; self->clipmask = MASK_MONSTERSOLID; VectorCopy(self->s.origin, self->s.old_origin); self->monsterinfo.aiflags |= AI_STAND_GROUND | AI_DUCKED; if (st.item) { self->item = FindItemByClassname(st.item); if (!self->item) { gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item); } } self->think = turret_driver_link; self->nextthink = level.time + FRAMETIME; gi.linkentity(self); } /* * invisible turret drivers so we can have unmanned turrets. * originally designed to shoot at func_trains and such, so they * fire at the center of the bounding box, rather than the entity's * origin. */ void turret_brain_think(edict_t *self) { vec3_t dir; vec3_t endpos; float reaction_time; trace_t trace; if (!self) { return; } self->nextthink = level.time + FRAMETIME; if (self->enemy) { if (!self->enemy->inuse) { self->enemy = NULL; } else if (self->enemy->takedamage && (self->enemy->health <= 0)) { self->enemy = NULL; } } if (!self->enemy) { if (!FindTarget(self)) { return; } self->monsterinfo.trail_time = level.time; self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; VectorAdd(self->enemy->absmax, self->enemy->absmin, endpos); VectorScale(endpos, 0.5, endpos); } else { VectorAdd(self->enemy->absmax, self->enemy->absmin, endpos); VectorScale(endpos, 0.5, endpos); trace = gi.trace(self->target_ent->s.origin, vec3_origin, vec3_origin, endpos, self->target_ent, MASK_SHOT); if ((trace.fraction == 1) || (trace.ent == self->enemy)) { if (self->monsterinfo.aiflags & AI_LOST_SIGHT) { self->monsterinfo.trail_time = level.time; self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; } } else { self->monsterinfo.aiflags |= AI_LOST_SIGHT; return; } } /* let the turret know where we want it to aim */ VectorSubtract(endpos, self->target_ent->s.origin, dir); vectoangles(dir, self->target_ent->move_angles); /* decide if we should shoot */ if (level.time < self->monsterinfo.attack_finished) { return; } if (self->delay) { reaction_time = self->delay; } else { reaction_time = (3 - skill->value) * 1.0; } if ((level.time - self->monsterinfo.trail_time) < reaction_time) { return; } self->monsterinfo.attack_finished = level.time + reaction_time + 1.0; self->target_ent->spawnflags |= 65536; } void turret_brain_link(edict_t *self) { vec3_t vec; edict_t *ent; if (!self) { return; } if (self->killtarget) { self->enemy = G_PickTarget(self->killtarget); } self->think = turret_brain_think; self->nextthink = level.time + FRAMETIME; self->target_ent = G_PickTarget(self->target); self->target_ent->owner = self; self->target_ent->teammaster->owner = self; VectorCopy(self->target_ent->s.angles, self->s.angles); vec[0] = self->target_ent->s.origin[0] - self->s.origin[0]; vec[1] = self->target_ent->s.origin[1] - self->s.origin[1]; vec[2] = 0; self->move_origin[0] = VectorLength(vec); VectorSubtract(self->s.origin, self->target_ent->s.origin, vec); vectoangles(vec, vec); AnglesNormalize(vec); self->move_origin[1] = vec[1]; self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2]; /* add the driver to the end of them team chain */ for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain) { } ent->teamchain = self; self->teammaster = self->target_ent->teammaster; self->flags |= FL_TEAMSLAVE; } void turret_brain_deactivate(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!self) { return; } self->think = NULL; self->nextthink = 0; } void turret_brain_activate(edict_t *self, edict_t *other /* unused */, edict_t *activator) { if (!self || !activator) { return; } if (!self->enemy) { self->enemy = activator; } /* wait at least 3 seconds to fire. */ self->monsterinfo.attack_finished = level.time + 3; self->use = turret_brain_deactivate; self->think = turret_brain_link; self->nextthink = level.time + FRAMETIME; } /* * QUAKED turret_invisible_brain (1 .5 0) (-16 -16 -16) (16 16 16) * Invisible brain to drive the turret. * * Does not search for targets. If targeted, can only be turned on once * and then off once. After that they are completely disabled. * * "delay" the delay between firing (default ramps for skill level) * "Target" the turret breach * "Killtarget" the item you want it to attack. * Target the brain if you want it activated later, instead of immediately. It will wait 3 seconds * before firing to acquire the target. */ void SP_turret_invisible_brain(edict_t *self) { if (!self) { return; } if (!self->killtarget) { gi.dprintf("turret_invisible_brain with no killtarget!\n"); G_FreeEdict(self); return; } if (!self->target) { gi.dprintf("turret_invisible_brain with no target!\n"); G_FreeEdict(self); return; } if (self->targetname) { self->use = turret_brain_activate; } else { self->think = turret_brain_link; self->nextthink = level.time + FRAMETIME; } self->movetype = MOVETYPE_PUSH; gi.linkentity(self); } rogue-ROGUE_2_13/src/g_utils.c000066400000000000000000000326541477320066100162230ustar00rootroot00000000000000/* ======================================================================= * * Misc. utility functions for the game logic. * * ======================================================================= */ #include "header/local.h" #define MAXCHOICES 8 vec3_t VEC_UP = {0, -1, 0}; vec3_t MOVEDIR_UP = {0, 0, 1}; vec3_t VEC_DOWN = {0, -2, 0}; vec3_t MOVEDIR_DOWN = {0, 0, -1}; void G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) { result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1]; result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1]; result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2]; } void G_ProjectSource2(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t up, vec3_t result) { result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1] + up[0] * distance[2]; result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1] + up[1] * distance[2]; result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + up[2] * distance[2]; } /* * Searches all active entities for the next one that holds * the matching string at fieldofs (use the FOFS() macro) in * the structure. * * Searches beginning at the edict after from, or the beginning * if NULL. * * NULL will be returned if the end of the list is reached. */ edict_t * G_Find(edict_t *from, int fieldofs, char *match) { char *s; if (!match) { return NULL; } if (!from) { from = g_edicts; } else { from++; } for ( ; from < &g_edicts[globals.num_edicts]; from++) { if (!from->inuse) { continue; } s = *(char **)((byte *)from + fieldofs); if (!s) { continue; } if (!Q_stricmp(s, match)) { return from; } } return NULL; } /* * Returns entities that have origins within a spherical area */ edict_t * findradius(edict_t *from, vec3_t org, float rad) { vec3_t eorg; int j; if (!from) { from = g_edicts; } else { from++; } for ( ; from < &g_edicts[globals.num_edicts]; from++) { if (!from->inuse) { continue; } if (from->solid == SOLID_NOT) { continue; } for (j = 0; j < 3; j++) { eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j]) * 0.5); } if (VectorLength(eorg) > rad) { continue; } return from; } return NULL; } /* * Returns entities that have origins within a spherical area */ edict_t * findradius2(edict_t *from, vec3_t org, float rad) { /* rad must be positive */ vec3_t eorg; int j; if (!from) { from = g_edicts; } else { from++; } for ( ; from < &g_edicts[globals.num_edicts]; from++) { if (!from->inuse) { continue; } if (from->solid == SOLID_NOT) { continue; } if (!from->takedamage) { continue; } if (!(from->svflags & SVF_DAMAGEABLE)) { continue; } for (j = 0; j < 3; j++) { eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j]) * 0.5); } if (VectorLength(eorg) > rad) { continue; } return from; } return NULL; } /* * Searches all active entities for the next one that holds * the matching string at fieldofs (use the FOFS() macro) in * the structure. * * Searches beginning at the edict after from, or the beginning * if NULL. * * NULL will be returned if the end of the list is reached. */ edict_t * G_PickTarget(char *targetname) { edict_t *ent = NULL; int num_choices = 0; edict_t *choice[MAXCHOICES]; if (!targetname) { gi.dprintf("G_PickTarget called with NULL targetname\n"); return NULL; } while (1) { ent = G_Find(ent, FOFS(targetname), targetname); if (!ent) { break; } choice[num_choices++] = ent; if (num_choices == MAXCHOICES) { break; } } if (!num_choices) { gi.dprintf("G_PickTarget: target %s not found\n", targetname); return NULL; } return choice[rand() % num_choices]; } void Think_Delay(edict_t *ent) { if (!ent) { return; } G_UseTargets(ent, ent->activator); G_FreeEdict(ent); } /* * 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. * * Search for (string)targetname in all entities that * match (string)self.target and call their .use function * * ============================== */ void G_UseTargets(edict_t *ent, edict_t *activator) { edict_t *t; edict_t *master; if (!ent) { return; } /* check for a delay */ if (ent->delay) { /* create a temp object to fire at a later time */ t = G_Spawn(); t->classname = "DelayedUse"; t->nextthink = level.time + ent->delay; t->think = Think_Delay; t->activator = activator; t->message = ent->message; t->target = ent->target; t->killtarget = ent->killtarget; return; } /* print the message */ if (activator && (ent->message) && !(activator->svflags & SVF_MONSTER)) { gi.centerprintf(activator, "%s", ent->message); if (ent->noise_index) { gi.sound(activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0); } else { gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0); } } /* kill killtargets */ if (ent->killtarget) { t = NULL; while ((t = G_Find(t, FOFS(targetname), ent->killtarget))) { /* if this entity is part of a train, cleanly remove it */ if (t->flags & FL_TEAMSLAVE) { master = t->teammaster; while (master) { if (master->teamchain == t) { master->teamchain = t->teamchain; break; } master = master->teamchain; } } /* correct killcounter if a living monster gets killtargeted */ if ((t->monsterinfo.checkattack || strcmp (t->classname, "turret_driver") == 0) && !(t->monsterinfo.aiflags & (AI_GOOD_GUY|AI_DO_NOT_COUNT)) && t->deadflag != DEAD_DEAD) { level.killed_monsters++; } G_FreeEdict(t); if (!ent->inuse) { gi.dprintf("entity was removed while using killtargets\n"); return; } } } /* fire targets */ if (ent->target) { t = NULL; while ((t = G_Find(t, FOFS(targetname), ent->target))) { /* doors fire area portals in a specific way */ if (!Q_stricmp(t->classname, "func_areaportal") && (!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating"))) { continue; } if (t == ent) { gi.dprintf("WARNING: Entity used itself.\n"); } else { if (t->use) { t->use(t, ent, activator); } } if (!ent->inuse) { gi.dprintf("entity was removed while using targets\n"); return; } } } } /* * This is just a convenience function * for making temporary vectors for function calls */ float * tv(float x, float y, float z) { static int index; static vec3_t vecs[8]; float *v; /* use an array so that multiple tempvectors won't collide for a while */ v = vecs[index]; index = (index + 1) & 7; v[0] = x; v[1] = y; v[2] = z; return v; } /* * This is just a convenience function * for printing vectors */ char * vtos(vec3_t v) { static int index; static char str[8][32]; char *s; /* use an array so that multiple vtos won't collide */ s = str[index]; index = (index + 1) & 7; Com_sprintf(s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]); return s; } void get_normal_vector(const cplane_t *p, vec3_t normal) { if (p) { VectorCopy(p->normal, normal); } else { VectorCopy(vec3_origin, normal); } } void G_SetMovedir(vec3_t angles, vec3_t movedir) { if (VectorCompare(angles, VEC_UP)) { VectorCopy(MOVEDIR_UP, movedir); } else if (VectorCompare(angles, VEC_DOWN)) { VectorCopy(MOVEDIR_DOWN, movedir); } else { AngleVectors(angles, movedir, NULL, NULL); } VectorClear(angles); } float vectoyaw(vec3_t vec) { float yaw; if (vec[PITCH] == 0) { if (vec[YAW] == 0) { yaw = 0; } else if (vec[YAW] > 0) { yaw = 90; } else { yaw = 270; } } else { yaw = (int)(atan2(vec[YAW], vec[PITCH]) * 180 / M_PI); if (yaw < 0) { yaw += 360; } } return yaw; } float vectoyaw2(vec3_t vec) { float yaw; if (vec[PITCH] == 0) { if (vec[YAW] == 0) { yaw = 0; } else if (vec[YAW] > 0) { yaw = 90; } else { yaw = 270; } } else { yaw = (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI); if (yaw < 0) { yaw += 360; } } return yaw; } void vectoangles(vec3_t value1, vec3_t angles) { float forward; float yaw, pitch; if ((value1[1] == 0) && (value1[0] == 0)) { yaw = 0; if (value1[2] > 0) { pitch = 90; } else { pitch = 270; } } else { if (value1[0]) { yaw = (int)(atan2(value1[1], value1[0]) * 180 / M_PI); } else if (value1[1] > 0) { yaw = 90; } else { yaw = 270; } if (yaw < 0) { yaw += 360; } forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]); pitch = (int)(atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) { pitch += 360; } } angles[PITCH] = -pitch; angles[YAW] = yaw; angles[ROLL] = 0; } void vectoangles2(vec3_t value1, vec3_t angles) { float forward; float yaw, pitch; if ((value1[1] == 0) && (value1[0] == 0)) { yaw = 0; if (value1[2] > 0) { pitch = 90; } else { pitch = 270; } } else { if (value1[0]) { yaw = (atan2(value1[1], value1[0]) * 180 / M_PI); } else if (value1[1] > 0) { yaw = 90; } else { yaw = 270; } if (yaw < 0) { yaw += 360; } forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]); pitch = (atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) { pitch += 360; } } angles[PITCH] = -pitch; angles[YAW] = yaw; angles[ROLL] = 0; } char * G_CopyString(char *in) { char *out; if (!in) { return NULL; } out = gi.TagMalloc(strlen(in) + 1, TAG_LEVEL); strcpy(out, in); return out; } void G_InitEdict(edict_t *e) { if (!e) { return; } if (e->nextthink) { e->nextthink = 0; } e->inuse = true; e->classname = "noclass"; e->gravity = 1.0; e->s.number = e - g_edicts; e->gravityVector[0] = 0.0; e->gravityVector[1] = 0.0; e->gravityVector[2] = -1.0; } /* * Either finds a free edict, or allocates a * new one. Try to avoid reusing an entity * that was recently freed, because it can * cause the client to think the entity * morphed into something else instead of * being removed and recreated, which can * cause interpolated angles and bad trails. */ #define POLICY_DEFAULT 0 #define POLICY_DESPERATE 1 static edict_t * G_FindFreeEdict(int policy) { edict_t *e; for (e = g_edicts + game.maxclients + 1 ; e < &g_edicts[globals.num_edicts] ; e++) { /* the first couple seconds of server time can involve a lot of freeing and allocating, so relax the replacement policy */ if (!e->inuse && (policy == POLICY_DESPERATE || e->freetime < 2.0f || (level.time - e->freetime) > 0.5f)) { G_InitEdict (e); return e; } } return NULL; } edict_t * G_SpawnOptional(void) { edict_t *e = G_FindFreeEdict (POLICY_DEFAULT); if (e) { return e; } if (globals.num_edicts >= game.maxentities) { return G_FindFreeEdict (POLICY_DESPERATE); } e = &g_edicts[globals.num_edicts++]; G_InitEdict (e); return e; } edict_t * G_Spawn(void) { edict_t *e = G_SpawnOptional(); if (!e) gi.error ("ED_Alloc: no free edicts"); return e; } /* * Marks the edict as free */ void G_FreeEdict(edict_t *ed) { if (!ed) { return; } gi.unlinkentity(ed); /* unlink from world */ if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE)) { return; } memset(ed, 0, sizeof(*ed)); ed->classname = "freed"; ed->freetime = level.time; ed->inuse = false; } void G_TouchTriggers(edict_t *ent) { int i, num; edict_t *touch[MAX_EDICTS], *hit; if (!ent) { return; } /* dead things don't activate triggers! */ if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0)) { return; } num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_TRIGGERS); /* be careful, it is possible to have an entity in this list removed before we get to it (killtriggered) */ for (i = 0; i < num; i++) { hit = touch[i]; if (!hit->inuse) { continue; } if (!hit->touch) { continue; } hit->touch(hit, ent, NULL, NULL); } } /* * Call after linking a new trigger in during gameplay * to force all entities it covers to immediately touch it */ void G_TouchSolids(edict_t *ent) { int i, num; edict_t *touch[MAX_EDICTS], *hit; if (!ent) { return; } num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID); /* be careful, it is possible to have an entity in this list removed before we get to it (killtriggered) */ for (i = 0; i < num; i++) { hit = touch[i]; if (!hit->inuse) { continue; } if (ent->touch) { ent->touch(hit, ent, NULL, NULL); } if (!ent->inuse) { break; } } } /* * Kills all entities that would touch the proposed new positioning * of ent. Ent should be unlinked before calling this! */ qboolean KillBox(edict_t *ent) { trace_t tr; if (!ent) { return false; } while (1) { tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin, NULL, MASK_PLAYERSOLID); if (!tr.ent) { break; } /* nail it */ T_Damage(tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); /* if we didn't kill it, fail */ if (tr.ent->solid) { return false; } } return true; /* all clear */ } rogue-ROGUE_2_13/src/g_weapon.c000066400000000000000000000556001477320066100163500ustar00rootroot00000000000000/* ======================================================================= * * Weapon support functions. * * ======================================================================= */ #include "header/local.h" /* * This is a support routine used when a client is firing * a non-instant attack weapon. It checks to see if a * monster's dodge function should be called. */ void check_dodge(edict_t *self, vec3_t start, vec3_t dir, int speed) { vec3_t end; vec3_t v; trace_t tr; float eta; if (!self) { return; } /* easy mode only ducks one quarter the time */ if (skill->value == SKILL_EASY) { if (random() > 0.25) { return; } } VectorMA(start, 8192, dir, end); tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self)) { VectorSubtract(tr.endpos, start, v); eta = (VectorLength(v) - tr.ent->maxs[0]) / speed; tr.ent->monsterinfo.dodge(tr.ent, self, eta, &tr); } } /* * Used for all impact (hit/punch/slash) attacks */ qboolean fire_hit(edict_t *self, vec3_t aim, int damage, int kick) { trace_t tr; vec3_t forward, right, up; vec3_t v; vec3_t point; float range; vec3_t dir; if (!self) { return false; } /* see if enemy is in range */ VectorSubtract(self->enemy->s.origin, self->s.origin, dir); range = VectorLength(dir); if (range > aim[0]) { return false; } if ((aim[1] > self->mins[0]) && (aim[1] < self->maxs[0])) { /* the hit is straight on so back the range up to the edge of their bbox */ range -= self->enemy->maxs[0]; } else { /* this is a side hit so adjust the "right" value out to the edge of their bbox */ if (aim[1] < 0) { aim[1] = self->enemy->mins[0]; } else { aim[1] = self->enemy->maxs[0]; } } VectorMA(self->s.origin, range, dir, point); tr = gi.trace(self->s.origin, NULL, NULL, point, self, MASK_SHOT); if (tr.fraction < 1) { if (!tr.ent->takedamage) { return false; } /* if it will hit any client/monster then hit the one we wanted to hit */ if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) { tr.ent = self->enemy; } } AngleVectors(self->s.angles, forward, right, up); VectorMA(self->s.origin, range, forward, point); VectorMA(point, aim[1], right, point); VectorMA(point, aim[2], up, point); VectorSubtract(point, self->enemy->s.origin, dir); /* do the damage */ T_Damage(tr.ent, self, self, dir, point, vec3_origin, damage, kick / 2, DAMAGE_NO_KNOCKBACK, MOD_HIT); if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) { return false; } /* do our special form of knockback here */ VectorMA(self->enemy->absmin, 0.5, self->enemy->size, v); VectorSubtract(v, point, v); VectorNormalize(v); VectorMA(self->enemy->velocity, kick, v, self->enemy->velocity); if (self->enemy->velocity[2] > 0) { self->enemy->groundentity = NULL; } return true; } /* * This is an internal support routine used for bullet/pellet based weapons. */ void fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod) { trace_t tr; vec3_t dir; vec3_t forward, right, up; vec3_t end; float r; float u; vec3_t water_start; qboolean water = false; int content_mask = MASK_SHOT | MASK_WATER; if (!self) { return; } tr = gi.trace(self->s.origin, NULL, NULL, start, self, MASK_SHOT); if (!(tr.fraction < 1.0)) { vectoangles(aimdir, dir); AngleVectors(dir, forward, right, up); r = crandom() * hspread; u = crandom() * vspread; VectorMA(start, 8192, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); if (gi.pointcontents(start) & MASK_WATER) { water = true; VectorCopy(start, water_start); content_mask &= ~MASK_WATER; } tr = gi.trace(start, NULL, NULL, end, self, content_mask); /* see if we hit water */ if (tr.contents & MASK_WATER) { int color; water = true; VectorCopy(tr.endpos, water_start); if (!VectorCompare(start, tr.endpos)) { if (tr.contents & CONTENTS_WATER) { if (strcmp(tr.surface->name, "*brwater") == 0) { color = SPLASH_BROWN_WATER; } else { color = SPLASH_BLUE_WATER; } } else if (tr.contents & CONTENTS_SLIME) { color = SPLASH_SLIME; } else if (tr.contents & CONTENTS_LAVA) { color = SPLASH_LAVA; } else { color = SPLASH_UNKNOWN; } if (color != SPLASH_UNKNOWN) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_SPLASH); gi.WriteByte(8); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.WriteByte(color); gi.multicast(tr.endpos, MULTICAST_PVS); } /* change bullet's course when it enters water */ VectorSubtract(end, start, dir); vectoangles(dir, dir); AngleVectors(dir, forward, right, up); r = crandom() * hspread * 2; u = crandom() * vspread * 2; VectorMA(water_start, 8192, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); } /* re-trace ignoring water this time */ tr = gi.trace(water_start, NULL, NULL, end, self, MASK_SHOT); } } /* send gun puff / flash */ if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { if (tr.fraction < 1.0) { if (tr.ent->takedamage) { T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod); } else { if (strncmp(tr.surface->name, "sky", 3) != 0) { gi.WriteByte(svc_temp_entity); gi.WriteByte(te_impact); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.multicast(tr.endpos, MULTICAST_PVS); if (self->client) { PlayerNoise(self, tr.endpos, PNOISE_IMPACT); } } } } } /* if went through water, determine where the end and make a bubble trail */ if (water) { vec3_t pos; VectorSubtract(tr.endpos, water_start, dir); VectorNormalize(dir); VectorMA(tr.endpos, -2, dir, pos); if (gi.pointcontents(pos) & MASK_WATER) { VectorCopy(pos, tr.endpos); } else { tr = gi.trace(pos, NULL, NULL, water_start, tr.ent, MASK_WATER); } VectorAdd(water_start, tr.endpos, pos); VectorScale(pos, 0.5, pos); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BUBBLETRAIL); gi.WritePosition(water_start); gi.WritePosition(tr.endpos); gi.multicast(pos, MULTICAST_PVS); } } /* * Fires a single round. Used for machinegun and chaingun. * Would be fine for pistols, rifles, etc.... */ void fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod) { if (!self) { return; } fire_lead(self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod); } /* * Shoots shotgun pellets. Used by shotgun and super shotgun. */ void fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod) { int i; if (!self) { return; } for (i = 0; i < count; i++) { fire_lead(self, start, aimdir, damage, kick, TE_SHOTGUN, hspread, vspread, mod); } } /* * Fires a single blaster bolt. Used by the blaster and hyper blaster. */ void blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int mod; vec3_t normal; if (!self || !other) { return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->owner && self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } get_normal_vector(plane, normal); if (other->takedamage) { if (self->spawnflags & 1) { mod = MOD_HYPERBLASTER; } else { mod = MOD_BLASTER; } T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, self->dmg, 1, DAMAGE_ENERGY, mod); } else { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BLASTER); gi.WritePosition(self->s.origin); gi.WriteDir(normal); gi.multicast(self->s.origin, MULTICAST_PVS); } G_FreeEdict(self); } void fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper) { edict_t *bolt; trace_t tr; if (!self) { return; } VectorNormalize(dir); bolt = G_Spawn(); bolt->svflags = SVF_DEADMONSTER; VectorCopy(start, bolt->s.origin); VectorCopy(start, bolt->s.old_origin); vectoangles(dir, bolt->s.angles); VectorScale(dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->s.effects |= effect; VectorClear(bolt->mins); VectorClear(bolt->maxs); bolt->s.modelindex = gi.modelindex("models/objects/laser/tris.md2"); bolt->s.sound = gi.soundindex("misc/lasfly.wav"); bolt->owner = self; bolt->touch = blaster_touch; bolt->nextthink = level.time + 2; bolt->think = G_FreeEdict; bolt->dmg = damage; bolt->classname = "bolt"; if (hyper) { bolt->spawnflags = 1; } gi.linkentity(bolt); if (self->client) { check_dodge(self, bolt->s.origin, dir, speed); } tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); if (tr.fraction < 1.0) { VectorMA(bolt->s.origin, -10, dir, bolt->s.origin); bolt->touch(bolt, tr.ent, NULL, NULL); } } void Grenade_Explode(edict_t *ent) { vec3_t origin; int mod; if (!ent) { return; } if (ent->owner->client) { PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); } if (ent->enemy) { float points; vec3_t v; vec3_t dir; VectorAdd(ent->enemy->mins, ent->enemy->maxs, v); VectorMA(ent->enemy->s.origin, 0.5, v, v); VectorSubtract(ent->s.origin, v, v); points = ent->dmg - 0.5 * VectorLength(v); VectorSubtract(ent->enemy->s.origin, ent->s.origin, dir); if (ent->spawnflags & 1) { mod = MOD_HANDGRENADE; } else { mod = MOD_GRENADE; } T_Damage(ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } if (ent->spawnflags & 2) { mod = MOD_HELD_GRENADE; } else if (ent->spawnflags & 1) { mod = MOD_HG_SPLASH; } else { mod = MOD_G_SPLASH; } T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod); VectorMA(ent->s.origin, -0.02, ent->velocity, origin); gi.WriteByte(svc_temp_entity); if (ent->waterlevel) { if (ent->groundentity) { gi.WriteByte(TE_GRENADE_EXPLOSION_WATER); } else { gi.WriteByte(TE_ROCKET_EXPLOSION_WATER); } } else { if (ent->groundentity) { gi.WriteByte(TE_GRENADE_EXPLOSION); } else { gi.WriteByte(TE_ROCKET_EXPLOSION); } } gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PHS); G_FreeEdict(ent); } void Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf) { if (!ent || !other) { return; } if (other == ent->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(ent); return; } if (!other->takedamage) { if (ent->spawnflags & 1) { if (random() > 0.5) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); } else { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); } } else { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/grenlb1b.wav"), 1, ATTN_NORM, 0); } return; } ent->enemy = other; Grenade_Explode(ent); } void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius) { edict_t *grenade; vec3_t dir; vec3_t forward, right, up; if (!self) { return; } vectoangles(aimdir, dir); AngleVectors(dir, forward, right, up); grenade = G_Spawn(); VectorCopy(start, grenade->s.origin); VectorScale(aimdir, speed, grenade->velocity); VectorMA(grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); VectorMA(grenade->velocity, crandom() * 10.0, right, grenade->velocity); VectorSet(grenade->avelocity, 300, 300, 300); grenade->movetype = MOVETYPE_BOUNCE; grenade->clipmask = MASK_SHOT; grenade->solid = SOLID_BBOX; grenade->s.effects |= EF_GRENADE; VectorClear(grenade->mins); VectorClear(grenade->maxs); grenade->s.modelindex = gi.modelindex("models/objects/grenade/tris.md2"); grenade->owner = self; grenade->touch = Grenade_Touch; grenade->nextthink = level.time + timer; grenade->think = Grenade_Explode; grenade->dmg = damage; grenade->dmg_radius = damage_radius; grenade->classname = "grenade"; gi.linkentity(grenade); } void fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, qboolean held) { edict_t *grenade; vec3_t dir; vec3_t forward, right, up; if (!self) { return; } vectoangles(aimdir, dir); AngleVectors(dir, forward, right, up); grenade = G_Spawn(); VectorCopy(start, grenade->s.origin); VectorScale(aimdir, speed, grenade->velocity); VectorMA(grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); VectorMA(grenade->velocity, crandom() * 10.0, right, grenade->velocity); VectorSet(grenade->avelocity, 300, 300, 300); grenade->movetype = MOVETYPE_BOUNCE; grenade->clipmask = MASK_SHOT; grenade->solid = SOLID_BBOX; grenade->s.effects |= EF_GRENADE; VectorClear(grenade->mins); VectorClear(grenade->maxs); grenade->s.modelindex = gi.modelindex("models/objects/grenade2/tris.md2"); grenade->owner = self; grenade->touch = Grenade_Touch; grenade->nextthink = level.time + timer; grenade->think = Grenade_Explode; grenade->dmg = damage; grenade->dmg_radius = damage_radius; grenade->classname = "hgrenade"; if (held) { grenade->spawnflags = 3; } else { grenade->spawnflags = 1; } grenade->s.sound = gi.soundindex("weapons/hgrenc1b.wav"); if (timer <= 0.0) { Grenade_Explode(grenade); } else { gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0); gi.linkentity(grenade); } } void rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; vec3_t normal; int n; if (!ent || !other) { return; } if (other == ent->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(ent); return; } if (ent->owner->client) { PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); } /* calculate position for the explosion entity */ VectorMA(ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { get_normal_vector(plane, normal); T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin, normal, ent->dmg, 0, 0, MOD_ROCKET); } else { /* don't throw any debris in net games */ if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP | SURF_TRANS33 | SURF_TRANS66 | SURF_FLOWING))) { n = rand() % 5; while (n--) { ThrowDebris(ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_R_SPLASH); gi.WriteByte(svc_temp_entity); if (ent->waterlevel) { gi.WriteByte(TE_ROCKET_EXPLOSION_WATER); } else { gi.WriteByte(TE_ROCKET_EXPLOSION); } gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PHS); G_FreeEdict(ent); } void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage) { edict_t *rocket; if (!self) { return; } rocket = G_Spawn(); VectorCopy(start, rocket->s.origin); VectorCopy(dir, rocket->movedir); vectoangles(dir, rocket->s.angles); VectorScale(dir, speed, rocket->velocity); rocket->movetype = MOVETYPE_FLYMISSILE; rocket->clipmask = MASK_SHOT; rocket->solid = SOLID_BBOX; rocket->s.effects |= EF_ROCKET; VectorClear(rocket->mins); VectorClear(rocket->maxs); rocket->s.modelindex = gi.modelindex("models/objects/rocket/tris.md2"); rocket->owner = self; rocket->touch = rocket_touch; rocket->nextthink = level.time + (8000.0f / (float)speed); rocket->think = G_FreeEdict; rocket->dmg = damage; rocket->radius_dmg = radius_damage; rocket->dmg_radius = damage_radius; rocket->s.sound = gi.soundindex("weapons/rockfly.wav"); rocket->classname = "rocket"; if (self->client) { check_dodge(self, rocket->s.origin, dir, speed); } gi.linkentity(rocket); } void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick) { vec3_t from; vec3_t end; trace_t tr; edict_t *ignore; int mask; qboolean water; if (!self) { return; } VectorMA(start, 8192, aimdir, end); VectorCopy(start, from); ignore = self; water = false; mask = MASK_SHOT | CONTENTS_SLIME | CONTENTS_LAVA; while (ignore) { tr = gi.trace(from, NULL, NULL, end, ignore, mask); if (tr.contents & (CONTENTS_SLIME | CONTENTS_LAVA)) { mask &= ~(CONTENTS_SLIME | CONTENTS_LAVA); water = true; } else { if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client) || (tr.ent->svflags & SVF_DAMAGEABLE) || (tr.ent->solid == SOLID_BBOX)) { ignore = tr.ent; } else { ignore = NULL; } if ((tr.ent != self) && (tr.ent->takedamage)) { T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_RAILGUN); } } VectorCopy(tr.endpos, from); } /* send gun puff / flash */ gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_RAILTRAIL); gi.WritePosition(start); gi.WritePosition(tr.endpos); gi.multicast(self->s.origin, MULTICAST_PHS); if (water) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_RAILTRAIL); gi.WritePosition(start); gi.WritePosition(tr.endpos); gi.multicast(tr.endpos, MULTICAST_PHS); } if (self->client) { PlayerNoise(self, tr.endpos, PNOISE_IMPACT); } } void bfg_explode(edict_t *self) { edict_t *ent; float points; vec3_t v; float dist; if (!self) { return; } if (self->s.frame == 0) { /* the BFG effect */ ent = NULL; while ((ent = findradius(ent, self->s.origin, self->dmg_radius)) != NULL) { if (!ent->takedamage) { continue; } if (ent == self->owner) { continue; } if (!CanDamage(ent, self)) { continue; } if (!CanDamage(ent, self->owner)) { continue; } VectorAdd(ent->mins, ent->maxs, v); VectorMA(ent->s.origin, 0.5, v, v); VectorSubtract(self->s.origin, v, v); dist = VectorLength(v); points = self->radius_dmg * (1.0 - sqrt(dist / self->dmg_radius)); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BFG_EXPLOSION); gi.WritePosition(ent->s.origin); gi.multicast(ent->s.origin, MULTICAST_PHS); T_Damage(ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT); } } self->nextthink = level.time + FRAMETIME; self->s.frame++; if (self->s.frame == 5) { self->think = G_FreeEdict; } } void bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t normal; if (!self || !other) { return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } /* core explosion - prevents firing it into the wall/floor */ if (other->takedamage) { get_normal_vector(plane, normal); T_Damage(other, self, self->owner, self->velocity, self->s.origin, normal, 200, 0, 0, MOD_BFG_BLAST); } T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST); gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0); self->solid = SOLID_NOT; self->touch = NULL; /* move it back a bit from walls so the effects aren't cut off */ if (!other->takedamage) { VectorNormalize(self->velocity); VectorMA(self->s.origin, -40.0f, self->velocity, self->s.origin); } VectorClear(self->velocity); self->s.modelindex = gi.modelindex("sprites/s_bfg3.sp2"); self->s.frame = 0; self->s.sound = 0; self->s.effects &= ~EF_ANIM_ALLFAST; self->think = bfg_explode; self->nextthink = level.time + FRAMETIME; self->enemy = other; gi.linkentity(self); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BFG_BIGEXPLOSION); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); } void bfg_think(edict_t *self) { edict_t *ent; edict_t *ignore; vec3_t point; vec3_t dir; vec3_t start; vec3_t end; int dmg; trace_t tr; if (!self) { return; } if (deathmatch->value) { dmg = 5; } else { dmg = 10; } ent = NULL; while ((ent = findradius(ent, self->s.origin, 256)) != NULL) { if (ent == self) { continue; } if (ent == self->owner) { continue; } if (!ent->takedamage) { continue; } if (!(ent->svflags & SVF_MONSTER) && !(ent->svflags & SVF_DAMAGEABLE) && (!ent->client) && (strcmp(ent->classname, "misc_explobox") != 0)) { continue; } VectorMA(ent->absmin, 0.5, ent->size, point); VectorSubtract(point, self->s.origin, dir); VectorNormalize(dir); ignore = self; VectorCopy(self->s.origin, start); VectorMA(start, 2048, dir, end); while (1) { tr = gi.trace(start, NULL, NULL, end, ignore, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); if (!tr.ent) { break; } /* hurt it if we can */ if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER) && (tr.ent != self->owner)) { T_Damage(tr.ent, self, self->owner, dir, tr.endpos, vec3_origin, dmg, 1, DAMAGE_ENERGY, MOD_BFG_LASER); } /* if we hit something that's not a monster or player we're done */ if (!(tr.ent->svflags & SVF_MONSTER) && !(tr.ent->svflags & SVF_DAMAGEABLE) && (!tr.ent->client)) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_LASER_SPARKS); gi.WriteByte(4); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.WriteByte(self->s.skinnum); gi.multicast(tr.endpos, MULTICAST_PVS); break; } ignore = tr.ent; VectorCopy(tr.endpos, start); } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BFG_LASER); gi.WritePosition(self->s.origin); gi.WritePosition(tr.endpos); gi.multicast(self->s.origin, MULTICAST_PHS); } self->nextthink = level.time + FRAMETIME; } void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius) { edict_t *bfg; if (!self) { return; } bfg = G_Spawn(); VectorCopy(start, bfg->s.origin); VectorCopy(dir, bfg->movedir); vectoangles(dir, bfg->s.angles); VectorScale(dir, speed, bfg->velocity); bfg->movetype = MOVETYPE_FLYMISSILE; bfg->clipmask = MASK_SHOT; bfg->solid = SOLID_BBOX; bfg->s.effects |= EF_BFG | EF_ANIM_ALLFAST; VectorClear(bfg->mins); VectorClear(bfg->maxs); bfg->s.modelindex = gi.modelindex("sprites/s_bfg1.sp2"); bfg->owner = self; bfg->touch = bfg_touch; bfg->nextthink = level.time + (8000.0f / (float)speed); bfg->think = G_FreeEdict; bfg->radius_dmg = damage; bfg->dmg_radius = damage_radius; bfg->classname = "bfg blast"; bfg->s.sound = gi.soundindex("weapons/bfg__l1a.wav"); bfg->think = bfg_think; bfg->nextthink = level.time + FRAMETIME; bfg->teammaster = bfg; bfg->teamchain = NULL; if (self->client) { check_dodge(self, bfg->s.origin, dir, speed); } gi.linkentity(bfg); } rogue-ROGUE_2_13/src/header/000077500000000000000000000000001477320066100156275ustar00rootroot00000000000000rogue-ROGUE_2_13/src/header/game.h000066400000000000000000000163611477320066100167200ustar00rootroot00000000000000/* ======================================================================= * * Here are the client, server and game are tied together. * * ======================================================================= */ /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * THIS FILE IS _VERY_ FRAGILE AND THERE'S NOTHING IN IT THAT CAN OR * MUST BE CHANGED. IT'S MOST LIKELY A VERY GOOD IDEA TO CLOSE THE * EDITOR NOW AND NEVER LOOK BACK. OTHERWISE YOU MAY SCREW UP EVERYTHING! * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #ifndef ROGUE_GAME_H #define ROGUE_GAME_H #define GAME_API_VERSION 3 #define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */ #define SVF_DEADMONSTER 0x00000002 /* treat as CONTENTS_DEADMONSTER for collision */ #define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */ #define SVF_DAMAGEABLE 0x00000008 typedef enum { SOLID_NOT, /* no interaction with other objects */ SOLID_TRIGGER, /* only touch when inside, after moving */ SOLID_BBOX, /* touch on edge */ SOLID_BSP /* bsp clip, touch on edge */ } solid_t; /* =============================================================== */ /* link_t is only used for entity area links now */ typedef struct link_s { struct link_s *prev, *next; } link_t; #define MAX_ENT_CLUSTERS 16 typedef struct edict_s edict_t; typedef struct gclient_s gclient_t; #ifndef GAME_INCLUDE struct gclient_s { player_state_t ps; /* communicated by server to clients */ int ping; /* the game dll can add anything it wants after this point in the structure */ }; struct edict_s { entity_state_t s; struct gclient_s *client; qboolean inuse; int linkcount; link_t area; /* linked to a division node or leaf */ int num_clusters; /* if -1, use headnode instead */ int clusternums[MAX_ENT_CLUSTERS]; int headnode; /* unused if num_clusters != -1 */ int areanum, areanum2; /* ================================ */ int svflags; /* SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc */ vec3_t mins, maxs; vec3_t absmin, absmax, size; solid_t solid; int clipmask; edict_t *owner; /* the game dll can add anything it wants after this point in the structure */ }; #endif /* GAME_INCLUDE */ /* =============================================================== */ /* functions provided by the main engine */ typedef struct { /* special messages */ void (*bprintf)(int printlevel, char *fmt, ...); void (*dprintf)(char *fmt, ...); void (*cprintf)(edict_t *ent, int printlevel, char *fmt, ...); void (*centerprintf)(edict_t *ent, char *fmt, ...); void (*sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs); void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel, int soundinedex, float volume, float attenuation, float timeofs); /* config strings hold all the index strings, the lightstyles, and misc data like the sky definition and cdtrack. All of the current configstrings are sent to clients when they connect, and changes are sent to all connected clients. */ void (*configstring)(int num, char *string); void (*error)(char *fmt, ...); /* the *index functions create configstrings and some internal server state */ int (*modelindex)(char *name); int (*soundindex)(char *name); int (*imageindex)(char *name); void (*setmodel)(edict_t *ent, char *name); /* collision detection */ trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask); int (*pointcontents)(vec3_t point); qboolean (*inPVS)(vec3_t p1, vec3_t p2); qboolean (*inPHS)(vec3_t p1, vec3_t p2); void (*SetAreaPortalState)(int portalnum, qboolean open); qboolean (*AreasConnected)(int area1, int area2); /* an entity will never be sent to a client or used for collision if it is not passed to linkentity. If the size, position, or solidity changes, it must be relinked. */ void (*linkentity)(edict_t *ent); void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */ int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype); void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */ /* network messaging */ void (*multicast)(vec3_t origin, multicast_t to); void (*unicast)(edict_t *ent, qboolean reliable); void (*WriteChar)(int c); void (*WriteByte)(int c); void (*WriteShort)(int c); void (*WriteLong)(int c); void (*WriteFloat)(float f); void (*WriteString)(char *s); void (*WritePosition)(vec3_t pos); /* some fractional bits */ void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */ void (*WriteAngle)(float f); /* managed memory allocation */ void *(*TagMalloc)(int size, int tag); void (*TagFree)(void *block); void (*FreeTags)(int tag); /* console variable interaction */ cvar_t *(*cvar)(char *var_name, char *value, int flags); cvar_t *(*cvar_set)(char *var_name, char *value); cvar_t *(*cvar_forceset)(char *var_name, char *value); /* ClientCommand and ServerCommand parameter access */ int (*argc)(void); char *(*argv)(int n); char *(*args)(void); /* concatenation of all argv >= 1 */ /* add commands to the server console as if they were typed in for map changing, etc */ void (*AddCommandString)(char *text); void (*DebugGraph)(float value, int color); } game_import_t; /* functions exported by the game subsystem */ typedef struct { int apiversion; /* the init function will only be called when a game starts, not each time a level is loaded. Persistant data for clients and the server can be allocated in init */ void (*Init)(void); void (*Shutdown)(void); /* each new level entered will cause a call to SpawnEntities */ void (*SpawnEntities)(char *mapname, char *entstring, char *spawnpoint); /* Read/Write Game is for storing persistant cross level information about the world state and the clients. WriteGame is called every time a level is exited. ReadGame is called on a loadgame. */ void (*WriteGame)(char *filename, qboolean autosave); void (*ReadGame)(char *filename); /* ReadLevel is called after the default map information has been loaded with SpawnEntities */ void (*WriteLevel)(char *filename); void (*ReadLevel)(char *filename); qboolean (*ClientConnect)(edict_t *ent, char *userinfo); void (*ClientBegin)(edict_t *ent); void (*ClientUserinfoChanged)(edict_t *ent, char *userinfo); void (*ClientDisconnect)(edict_t *ent); void (*ClientCommand)(edict_t *ent); void (*ClientThink)(edict_t *ent, usercmd_t *cmd); void (*RunFrame)(void); /* ServerCommand will be called when an "sv " command is issued on the server console. The game can issue gi.argc() gi.argv() commands to get the rest of the parameters */ void (*ServerCommand)(void); /* global variables shared between game and server */ /* The edict array is allocated in the game dll so it can vary in size from one game to another. The size will be fixed when ge->Init() is called */ struct edict_s *edicts; int edict_size; int num_edicts; /* current number, <= max_edicts */ int max_edicts; } game_export_t; #endif /* ROGUE_GAME_H */ rogue-ROGUE_2_13/src/header/local.h000066400000000000000000001175721477320066100171070ustar00rootroot00000000000000/* ======================================================================= * * Main header file for the game module. * * ======================================================================= */ #ifndef ROGUE_LOCAL_H #define ROGUE_LOCAL_H #include "shared.h" /* define GAME_INCLUDE so that game.h does not define the short, server-visible gclient_t and edict_t structures, because we define the full size ones in this file */ #define GAME_INCLUDE #include "game.h" /* the "gameversion" client command will print this plus compile date */ #define GAMEVERSION "rogue" /* protocol bytes that can be directly added to messages */ #define svc_muzzleflash 1 #define svc_muzzleflash2 2 #define svc_temp_entity 3 #define svc_layout 4 #define svc_inventory 5 #define svc_stufftext 11 /* ================================================================== */ #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #define _isnan(a) (isnan(a)) /* ================================================================== */ /* view pitching times */ #define DAMAGE_TIME 0.5 #define FALL_TIME 0.3 /* these are set with checkboxes on each entity in the map editor */ #define SPAWNFLAG_NOT_EASY 0x00000100 #define SPAWNFLAG_NOT_MEDIUM 0x00000200 #define SPAWNFLAG_NOT_HARD 0x00000400 #define SPAWNFLAG_NOT_DEATHMATCH 0x00000800 #define SPAWNFLAG_NOT_COOP 0x00001000 /* edict->flags */ #define FL_FLY 0x00000001 #define FL_SWIM 0x00000002 /* implied immunity to drowining */ #define FL_IMMUNE_LASER 0x00000004 #define FL_INWATER 0x00000008 #define FL_GODMODE 0x00000010 #define FL_NOTARGET 0x00000020 #define FL_IMMUNE_SLIME 0x00000040 #define FL_IMMUNE_LAVA 0x00000080 #define FL_PARTIALGROUND 0x00000100 /* not all corners are valid */ #define FL_WATERJUMP 0x00000200 /* player jumping out of water */ #define FL_TEAMSLAVE 0x00000400 /* not the first on the team */ #define FL_NO_KNOCKBACK 0x00000800 #define FL_POWER_ARMOR 0x00001000 /* power armor (if any) is active */ #define FL_COOP_TAKEN 0x00002000 /* Another client has already taken it */ #define FL_RESPAWN 0x80000000 /* used for item respawning */ #define FL_MECHANICAL 0x00002000 /* entity is mechanical, use sparks not blood */ #define FL_SAM_RAIMI 0x00004000 /* entity is in sam raimi cam mode */ #define FL_DISGUISED 0x00008000 /* entity is in disguise, monsters will not recognize. */ #define FL_NOGIB 0x00010000 /* player has been vaporized by a nuke, drop no gibs */ #define FRAMETIME 0.1 /* memory tags to allow dynamic memory to be cleaned up */ #define TAG_GAME 765 /* clear when unloading the dll */ #define TAG_LEVEL 766 /* clear when loading a new level */ #define MELEE_DISTANCE 80 #define BODY_QUEUE_SIZE 8 typedef enum { DAMAGE_NO, DAMAGE_YES, /* will take damage if hit */ DAMAGE_AIM /* auto targeting recognizes this */ } damage_t; typedef enum { WEAPON_READY, WEAPON_ACTIVATING, WEAPON_DROPPING, WEAPON_FIRING } weaponstate_t; typedef enum { AMMO_BULLETS, AMMO_SHELLS, AMMO_ROCKETS, AMMO_GRENADES, AMMO_CELLS, AMMO_SLUGS, AMMO_FLECHETTES, AMMO_TESLA, AMMO_PROX, AMMO_DISRUPTOR } ammo_t; /* Maximum debris / gibs per frame */ #define MAX_GIBS 20 #define MAX_DEBRIS 20 /* deadflag */ #define DEAD_NO 0 #define DEAD_DYING 1 #define DEAD_DEAD 2 #define DEAD_RESPAWNABLE 3 /* range */ #define RANGE_MELEE 0 #define RANGE_NEAR 1 #define RANGE_MID 2 #define RANGE_FAR 3 /* gib types */ #define GIB_ORGANIC 0 #define GIB_METALLIC 1 /* monster ai flags */ #define AI_STAND_GROUND 0x00000001 #define AI_TEMP_STAND_GROUND 0x00000002 #define AI_SOUND_TARGET 0x00000004 #define AI_LOST_SIGHT 0x00000008 #define AI_PURSUIT_LAST_SEEN 0x00000010 #define AI_PURSUE_NEXT 0x00000020 #define AI_PURSUE_TEMP 0x00000040 #define AI_HOLD_FRAME 0x00000080 #define AI_GOOD_GUY 0x00000100 #define AI_BRUTAL 0x00000200 #define AI_NOSTEP 0x00000400 #define AI_DUCKED 0x00000800 #define AI_COMBAT_POINT 0x00001000 #define AI_MEDIC 0x00002000 #define AI_RESURRECTING 0x00004000 /* ROGUE */ #define AI_WALK_WALLS 0x00008000 #define AI_MANUAL_STEERING 0x00010000 #define AI_TARGET_ANGER 0x00020000 #define AI_DODGING 0x00040000 #define AI_CHARGING 0x00080000 #define AI_HINT_PATH 0x00100000 #define AI_IGNORE_SHOTS 0x00200000 #define AI_DO_NOT_COUNT 0x00400000 /* set for healed monsters */ #define AI_SPAWNED_CARRIER 0x00800000 /* both do_not_count and spawned are set for spawned monsters */ #define AI_SPAWNED_MEDIC_C 0x01000000 /* both do_not_count and spawned are set for spawned monsters */ #define AI_SPAWNED_WIDOW 0x02000000 /* both do_not_count and spawned are set for spawned monsters */ #define AI_SPAWNED_MASK 0x03800000 /* mask to catch all three flavors of spawned */ #define AI_BLOCKED 0x04000000 /* used by blocked_checkattack: set to say I'm attacking while blocked */ /* (prevents run-attacks) */ /* monster attack state */ #define AS_STRAIGHT 1 #define AS_SLIDING 2 #define AS_MELEE 3 #define AS_MISSILE 4 #define AS_BLIND 5 /* armor types */ #define ARMOR_NONE 0 #define ARMOR_JACKET 1 #define ARMOR_COMBAT 2 #define ARMOR_BODY 3 #define ARMOR_SHARD 4 /* power armor types */ #define POWER_ARMOR_NONE 0 #define POWER_ARMOR_SCREEN 1 #define POWER_ARMOR_SHIELD 2 /* handedness values */ #define RIGHT_HANDED 0 #define LEFT_HANDED 1 #define CENTER_HANDED 2 /* game.serverflags values */ #define SFL_CROSS_TRIGGER_1 0x00000001 #define SFL_CROSS_TRIGGER_2 0x00000002 #define SFL_CROSS_TRIGGER_3 0x00000004 #define SFL_CROSS_TRIGGER_4 0x00000008 #define SFL_CROSS_TRIGGER_5 0x00000010 #define SFL_CROSS_TRIGGER_6 0x00000020 #define SFL_CROSS_TRIGGER_7 0x00000040 #define SFL_CROSS_TRIGGER_8 0x00000080 #define SFL_CROSS_TRIGGER_MASK 0x000000ff /* noise types for PlayerNoise */ #define PNOISE_SELF 0 #define PNOISE_WEAPON 1 #define PNOISE_IMPACT 2 /* edict->movetype values */ typedef enum { MOVETYPE_NONE, /* never moves */ MOVETYPE_NOCLIP, /* origin and angles change with no interaction */ MOVETYPE_PUSH, /* no clip to world, push on box contact */ MOVETYPE_STOP, /* no clip to world, stops on box contact */ MOVETYPE_WALK, /* gravity */ MOVETYPE_STEP, /* gravity, special edge handling */ MOVETYPE_FLY, MOVETYPE_TOSS, /* gravity */ MOVETYPE_FLYMISSILE, /* extra size to monsters */ MOVETYPE_BOUNCE, MOVETYPE_NEWTOSS /* for deathball */ } movetype_t; typedef struct { int base_count; int max_count; float normal_protection; float energy_protection; int armor; } gitem_armor_t; #define IT_WEAPON 0x00000001 /* use makes active weapon */ #define IT_AMMO 0x00000002 #define IT_ARMOR 0x00000004 #define IT_STAY_COOP 0x00000008 #define IT_KEY 0x00000010 #define IT_POWERUP 0x00000020 #define IT_MELEE 0x00000040 #define IT_NOT_GIVEABLE 0x00000080 /* item can not be given */ #define IT_INSTANT_USE 0x000000100 /* item is insta-used on pickup if dmflag is set */ /* gitem_t->weapmodel for weapons indicates model index */ #define WEAP_BLASTER 1 #define WEAP_SHOTGUN 2 #define WEAP_SUPERSHOTGUN 3 #define WEAP_MACHINEGUN 4 #define WEAP_CHAINGUN 5 #define WEAP_GRENADES 6 #define WEAP_GRENADELAUNCHER 7 #define WEAP_ROCKETLAUNCHER 8 #define WEAP_HYPERBLASTER 9 #define WEAP_RAILGUN 10 #define WEAP_BFG 11 #define WEAP_DISRUPTOR 12 #define WEAP_ETFRIFLE 13 #define WEAP_PLASMA 14 #define WEAP_PROXLAUNCH 15 #define WEAP_CHAINFIST 16 typedef struct gitem_s { char *classname; /* spawning name */ qboolean (*pickup)(struct edict_s *ent, struct edict_s *other); void (*use)(struct edict_s *ent, struct gitem_s *item); void (*drop)(struct edict_s *ent, struct gitem_s *item); void (*weaponthink)(struct edict_s *ent); char *pickup_sound; char *world_model; int world_model_flags; char *view_model; /* client side info */ char *icon; char *pickup_name; /* for printing on pickup */ int count_width; /* number of digits to display by icon */ int quantity; /* for ammo how much, for weapons how much is used per shot */ char *ammo; /* for weapons */ int flags; /* IT_* flags */ int weapmodel; /* weapon model index (for weapons) */ void *info; int tag; char *precaches; /* string of all models, sounds, and images this item will use */ } gitem_t; /* this structure is left intact through an entire game it should be initialized at dll load time, and read/written to the server.ssv file for savegames */ typedef struct { char helpmessage1[512]; char helpmessage2[512]; int helpchanged; /* flash F1 icon if non 0, play sound */ /* and increment only if 1, 2, or 3 */ gclient_t *clients; /* [maxclients] */ /* can't store spawnpoint in level, because it would get overwritten by the savegame restore */ char spawnpoint[512]; /* needed for coop respawns */ /* store latched cvars here that we want to get at often */ int maxclients; int maxentities; /* cross level triggers */ int serverflags; /* items */ int num_items; qboolean autosaved; } game_locals_t; /* this structure is cleared as each map is entered it is read/written to the level.sav file for savegames */ typedef struct { int framenum; float time; char level_name[MAX_QPATH]; /* the descriptive name (Outer Base, etc) */ char mapname[MAX_QPATH]; /* the server name (base1, etc) */ char nextmap[MAX_QPATH]; /* go here when fraglimit is hit */ /* intermission state */ float intermissiontime; /* time the intermission was started */ char *changemap; int exitintermission; vec3_t intermission_origin; vec3_t intermission_angle; edict_t *sight_client; /* changed once each frame for coop games */ edict_t *sight_entity; int sight_entity_framenum; edict_t *sound_entity; int sound_entity_framenum; edict_t *sound2_entity; int sound2_entity_framenum; int pic_health; int total_secrets; int found_secrets; int total_goals; int found_goals; int total_monsters; int killed_monsters; edict_t *current_entity; /* entity running from G_RunFrame */ int body_que; /* dead bodies */ int power_cubes; /* ugly necessity for coop */ edict_t *disguise_violator; int disguise_violation_framenum; } level_locals_t; /* spawn_temp_t is only used to hold entity field values that can be set from the editor, but aren't actualy present/ in edict_t during gameplay */ typedef struct { /* world vars */ char *sky; float skyrotate; vec3_t skyaxis; char *nextmap; int lip; int distance; int height; char *noise; float pausetime; char *item; char *gravity; float minyaw; float maxyaw; float minpitch; float maxpitch; } spawn_temp_t; typedef struct { /* fixed data */ vec3_t start_origin; vec3_t start_angles; vec3_t end_origin; vec3_t end_angles; int sound_start; int sound_middle; int sound_end; float accel; float speed; float decel; float distance; float wait; /* state data */ int state; vec3_t dir; float current_speed; float move_speed; float next_speed; float remaining_distance; float decel_distance; void (*endfunc)(edict_t *); } moveinfo_t; typedef struct { void (*aifunc)(edict_t *self, float dist); float dist; void (*thinkfunc)(edict_t *self); } mframe_t; typedef struct { int firstframe; int lastframe; mframe_t *frame; void (*endfunc)(edict_t *self); } mmove_t; typedef struct { mmove_t *currentmove; unsigned int aiflags; /* unsigned, since we're close to the max */ int nextframe; float scale; void (*stand)(edict_t *self); void (*idle)(edict_t *self); void (*search)(edict_t *self); void (*walk)(edict_t *self); void (*run)(edict_t *self); void (*dodge)(edict_t *self, edict_t *other, float eta, trace_t *tr); void (*attack)(edict_t *self); void (*melee)(edict_t *self); void (*sight)(edict_t *self, edict_t *other); qboolean (*checkattack)(edict_t *self); float pausetime; float attack_finished; vec3_t saved_goal; float search_time; float trail_time; vec3_t last_sighting; int attack_state; int lefty; float idle_time; int linkcount; int power_armor_type; int power_armor_power; qboolean (*blocked)(edict_t *self, float dist); float last_hint_time; /* last time the monster checked for hintpaths. */ edict_t *goal_hint; /* which hint_path we're trying to get to */ int medicTries; edict_t *badMedic1, *badMedic2; /* these medics have declared this monster "unhealable" */ edict_t *healer; /* this is who is healing this monster */ void (*duck)(edict_t *self, float eta); void (*unduck)(edict_t *self); void (*sidestep)(edict_t *self); float base_height; float next_duck_time; float duck_wait_time; edict_t *last_player_enemy; qboolean blindfire; /* will the monster blindfire? */ float blind_fire_delay; vec3_t blind_fire_target; /* used by the spawners to not spawn too much and keep track of #s of monsters spawned */ int monster_slots; int monster_used; edict_t *commander; /* powerup timers, used by widow, our friend */ float quad_framenum; float invincible_framenum; float double_framenum; } monsterinfo_t; /* this determines how long to wait after a duck to duck again. this needs to be longer than the time after the monster_duck_up in all of the animation sequences */ #define DUCK_INTERVAL 0.5 extern game_locals_t game; extern level_locals_t level; extern game_import_t gi; extern game_export_t globals; extern spawn_temp_t st; extern int sm_meat_index; extern int snd_fry; extern int jacket_armor_index; extern int combat_armor_index; extern int body_armor_index; extern int debristhisframe; extern int gibsthisframe; /* means of death */ #define MOD_UNKNOWN 0 #define MOD_BLASTER 1 #define MOD_SHOTGUN 2 #define MOD_SSHOTGUN 3 #define MOD_MACHINEGUN 4 #define MOD_CHAINGUN 5 #define MOD_GRENADE 6 #define MOD_G_SPLASH 7 #define MOD_ROCKET 8 #define MOD_R_SPLASH 9 #define MOD_HYPERBLASTER 10 #define MOD_RAILGUN 11 #define MOD_BFG_LASER 12 #define MOD_BFG_BLAST 13 #define MOD_BFG_EFFECT 14 #define MOD_HANDGRENADE 15 #define MOD_HG_SPLASH 16 #define MOD_WATER 17 #define MOD_SLIME 18 #define MOD_LAVA 19 #define MOD_CRUSH 20 #define MOD_TELEFRAG 21 #define MOD_FALLING 22 #define MOD_SUICIDE 23 #define MOD_HELD_GRENADE 24 #define MOD_EXPLOSIVE 25 #define MOD_BARREL 26 #define MOD_BOMB 27 #define MOD_EXIT 28 #define MOD_SPLASH 29 #define MOD_TARGET_LASER 30 #define MOD_TRIGGER_HURT 31 #define MOD_HIT 32 #define MOD_TARGET_BLASTER 33 #define MOD_FRIENDLY_FIRE 0x8000000 #define MOD_CHAINFIST 40 #define MOD_DISINTEGRATOR 41 #define MOD_ETF_RIFLE 42 #define MOD_BLASTER2 43 #define MOD_HEATBEAM 44 #define MOD_TESLA 45 #define MOD_PROX 46 #define MOD_NUKE 47 #define MOD_VENGEANCE_SPHERE 48 #define MOD_HUNTER_SPHERE 49 #define MOD_DEFENDER_SPHERE 50 #define MOD_TRACKER 51 #define MOD_DBALL_CRUSH 52 #define MOD_DOPPLE_EXPLODE 53 #define MOD_DOPPLE_VENGEANCE 54 #define MOD_DOPPLE_HUNTER 55 /* Easier handling of AI skill levels */ #define SKILL_EASY 0 #define SKILL_MEDIUM 1 #define SKILL_HARD 2 #define SKILL_HARDPLUS 3 extern int meansOfDeath; extern edict_t *g_edicts; #define FOFS(x) (size_t)&(((edict_t *)NULL)->x) #define STOFS(x) (size_t)&(((spawn_temp_t *)NULL)->x) #define LLOFS(x) (size_t)&(((level_locals_t *)NULL)->x) #define CLOFS(x) (size_t)&(((gclient_t *)NULL)->x) #define random() ((randk() & 0x7fff) / ((float)0x7fff)) #define crandom() (2.0 * (random() - 0.5)) extern cvar_t *maxentities; extern cvar_t *deathmatch; extern cvar_t *coop; extern cvar_t *coop_baseq2; /* treat spawnflags according to baseq2 rules */ extern cvar_t *coop_elevator_delay; extern cvar_t *coop_pickup_weapons; extern cvar_t *dmflags; extern cvar_t *skill; extern cvar_t *fraglimit; extern cvar_t *timelimit; extern cvar_t *password; extern cvar_t *spectator_password; extern cvar_t *g_select_empty; extern cvar_t *dedicated; extern cvar_t *g_footsteps; extern cvar_t *g_monsterfootsteps; extern cvar_t *g_fix_triggered; extern cvar_t *filterban; extern cvar_t *sv_gravity; extern cvar_t *sv_maxvelocity; extern cvar_t *gun_x, *gun_y, *gun_z; extern cvar_t *sv_rollspeed; extern cvar_t *sv_rollangle; extern cvar_t *run_pitch; extern cvar_t *run_roll; extern cvar_t *bob_up; extern cvar_t *bob_pitch; extern cvar_t *bob_roll; extern cvar_t *sv_cheats; extern cvar_t *maxclients; extern cvar_t *maxspectators; extern cvar_t *flood_msgs; extern cvar_t *flood_persecond; extern cvar_t *flood_waitdelay; extern cvar_t *sv_maplist; extern cvar_t *sv_stopspeed; extern cvar_t *g_showlogic; extern cvar_t *gamerules; extern cvar_t *huntercam; extern cvar_t *strong_mines; extern cvar_t *randomrespawn; extern cvar_t *g_disruptor; extern cvar_t *aimfix; extern cvar_t *g_machinegun_norecoil; extern cvar_t *g_quick_weap; extern cvar_t *g_swap_speed; /* this is for the count of monsters */ #define ENT_SLOTS_LEFT \ (ent->monsterinfo.monster_slots - \ ent->monsterinfo.monster_used) #define SELF_SLOTS_LEFT \ (self->monsterinfo.monster_slots - \ self->monsterinfo.monster_used) #define world (&g_edicts[0]) /* item spawnflags */ #define ITEM_TRIGGER_SPAWN 0x00000001 #define ITEM_NO_TOUCH 0x00000002 /* 6 bits reserved for editor flags */ /* 8 bits used as power cube id bits for coop games */ #define DROPPED_ITEM 0x00010000 #define DROPPED_PLAYER_ITEM 0x00020000 #define ITEM_TARGETS_USED 0x00040000 /* fields are needed for spawning from the entity string and saving / loading games */ #define FFL_SPAWNTEMP 1 #define FFL_NOSPAWN 2 typedef enum { F_INT, F_FLOAT, F_LSTRING, /* string on disk, pointer in memory, TAG_LEVEL */ F_GSTRING, /* string on disk, pointer in memory, TAG_GAME */ F_VECTOR, F_ANGLEHACK, F_EDICT, /* index on disk, pointer in memory */ F_ITEM, /* index on disk, pointer in memory */ F_CLIENT, /* index on disk, pointer in memory */ F_FUNCTION, F_MMOVE, F_IGNORE } fieldtype_t; typedef struct { char *name; int ofs; fieldtype_t type; int flags; short save_ver; } field_t; extern field_t fields[]; extern gitem_t itemlist[]; /* g_cmds.c */ void Cmd_Help_f(edict_t *ent); /* g_items.c */ void PrecacheItem(gitem_t *it); void InitItems(void); void SetItemNames(void); gitem_t *FindItem(char *pickup_name); gitem_t *FindItemByClassname(char *classname); #define ITEM_INDEX(x) ((x) - itemlist) edict_t *Drop_Item(edict_t *ent, gitem_t *item); void SetRespawn(edict_t *ent, float delay); void ChangeWeapon(edict_t *ent); void SpawnItem(edict_t *ent, gitem_t *item); void Think_Weapon(edict_t *ent); int ArmorIndex(edict_t *ent); int PowerArmorType(edict_t *ent); gitem_t *GetItemByIndex(int index); qboolean Add_Ammo(edict_t *ent, gitem_t *item, int count); void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); /* g_utils.c */ qboolean KillBox(edict_t *ent); void G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result); edict_t *G_Find(edict_t *from, int fieldofs, char *match); edict_t *findradius(edict_t *from, vec3_t org, float rad); edict_t *G_PickTarget(char *targetname); void G_UseTargets(edict_t *ent, edict_t *activator); void G_SetMovedir(vec3_t angles, vec3_t movedir); void G_InitEdict(edict_t *e); edict_t *G_SpawnOptional(void); edict_t *G_Spawn(void); void G_FreeEdict(edict_t *e); void G_TouchTriggers(edict_t *ent); void G_TouchSolids(edict_t *ent); char *G_CopyString(char *in); float *tv(float x, float y, float z); char *vtos(vec3_t v); void get_normal_vector(const cplane_t *p, vec3_t normal); float vectoyaw(vec3_t vec); void vectoangles(vec3_t vec, vec3_t angles); void G_ProjectSource2(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t up, vec3_t result); float vectoyaw2(vec3_t vec); void vectoangles2(vec3_t vec, vec3_t angles); edict_t *findradius2(edict_t *from, vec3_t org, float rad); /* g_combat.c */ qboolean OnSameTeam(edict_t *ent1, edict_t *ent2); qboolean CanDamage(edict_t *targ, edict_t *inflictor); void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod); void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod); void T_RadiusNukeDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod); void T_RadiusClassDamage(edict_t *inflictor, edict_t *attacker, float damage, char *ignoreClass, float radius, int mod); void cleanupHealTarget(edict_t *ent); /* damage flags */ #define DAMAGE_RADIUS 0x00000001 /* damage was indirect */ #define DAMAGE_NO_ARMOR 0x00000002 /* armour does not protect from this damage */ #define DAMAGE_ENERGY 0x00000004 /* damage is from an energy based weapon */ #define DAMAGE_NO_KNOCKBACK 0x00000008 /* do not affect velocity, just view angles */ #define DAMAGE_BULLET 0x00000010 /* damage is from a bullet (used for ricochets) */ #define DAMAGE_NO_PROTECTION 0x00000020 /* armor, shields, invulnerability, and godmode have no effect */ #define DAMAGE_DESTROY_ARMOR 0x00000040 /* damage is done to armor and health. */ #define DAMAGE_NO_REG_ARMOR 0x00000080 /* damage skips regular armor */ #define DAMAGE_NO_POWER_ARMOR 0x00000100 /* damage skips power armor */ #define DEFAULT_BULLET_HSPREAD 300 #define DEFAULT_BULLET_VSPREAD 500 #define DEFAULT_SHOTGUN_HSPREAD 1000 #define DEFAULT_SHOTGUN_VSPREAD 500 #define DEFAULT_SHOTGUN_COUNT 12 #define DEFAULT_SSHOTGUN_COUNT 20 /* g_monster.c */ void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype); void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int flashtype); void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect); void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype); void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype); void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype); void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int kick, float damage_radius, int flashtype); void M_droptofloor(edict_t *ent); void monster_think(edict_t *self); void walkmonster_start(edict_t *self); void swimmonster_start(edict_t *self); void flymonster_start(edict_t *self); void AttackFinished(edict_t *self, float time); void monster_death_use(edict_t *self); void M_CatagorizePosition(edict_t *ent); qboolean M_CheckAttack(edict_t *self); void M_FlyCheck(edict_t *self); void M_CheckGround(edict_t *ent); void monster_fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect); void monster_fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, edict_t *enemy, int flashtype); void monster_fire_heat(edict_t *self, vec3_t start, vec3_t dir, vec3_t offset, int damage, int kick, int flashtype); void stationarymonster_start(edict_t *self); void monster_done_dodge(edict_t *self); /* g_misc.c */ void ThrowHead(edict_t *self, char *gibname, int damage, int type); void ThrowClientHead(edict_t *self, int damage); void ThrowGib(edict_t *self, char *gibname, int damage, int type); void BecomeExplosion1(edict_t *self); /* g_ai.c */ void AI_SetSightClient(void); void ai_stand(edict_t *self, float dist); void ai_move(edict_t *self, float dist); void ai_walk(edict_t *self, float dist); void ai_turn(edict_t *self, float dist); void ai_run(edict_t *self, float dist); void ai_charge(edict_t *self, float dist); int range(edict_t *self, edict_t *other); void FoundTarget(edict_t *self); qboolean infront(edict_t *self, edict_t *other); qboolean visible(edict_t *self, edict_t *other); qboolean FacingIdeal(edict_t *self); /* g_weapon.c */ void ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin); qboolean fire_hit(edict_t *self, vec3_t aim, int damage, int kick); void fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod); void fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod); void fire_blaster(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect, qboolean hyper); void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius); void fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, qboolean held); void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage); void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick); void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius); /* g_ptrail.c */ void PlayerTrail_Init(void); void PlayerTrail_Add(vec3_t spot); void PlayerTrail_New(vec3_t spot); edict_t *PlayerTrail_PickFirst(edict_t *self); edict_t *PlayerTrail_PickNext(edict_t *self); edict_t *PlayerTrail_LastSpot(void); /* g_client.c */ void respawn(edict_t *ent); void BeginIntermission(edict_t *targ); void PutClientInServer(edict_t *ent); void InitClientPersistant(gclient_t *client); void InitClientResp(gclient_t *client); void InitBodyQue(void); void ClientBeginServerFrame(edict_t *ent); /* g_player.c */ void player_pain(edict_t *self, edict_t *other, float kick, int damage); void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); /* g_svcmds.c */ void ServerCommand(void); qboolean SV_FilterPacket(char *from); /* p_view.c */ void ClientEndServerFrame(edict_t *ent); /* p_hud.c */ void MoveClientToIntermission(edict_t *client); void G_SetStats(edict_t *ent); void G_SetSpectatorStats(edict_t *ent); void G_CheckChaseStats(edict_t *ent); void ValidateSelectedItem(edict_t *ent); void DeathmatchScoreboardMessage(edict_t *client, edict_t *killer); void HelpComputerMessage(edict_t *client); void InventoryMessage(edict_t *client); /* g_pweapon.c */ void PlayerNoise(edict_t *who, vec3_t where, int type); /* m_move.c */ qboolean M_CheckBottom(edict_t *ent); qboolean M_walkmove(edict_t *ent, float yaw, float dist); void M_MoveToGoal(edict_t *ent, float dist); void M_ChangeYaw(edict_t *ent); /* g_phys.c */ void G_RunEntity(edict_t *ent); /* g_main.c */ void SaveClientData(void); void FetchClientEntData(edict_t *ent); /* g_chase.c */ void UpdateChaseCam(edict_t *ent); void ChaseNext(edict_t *ent); void ChasePrev(edict_t *ent); void GetChaseTarget(edict_t *ent); void fire_flechette(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick); void fire_prox(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed); void fire_nuke(edict_t *self, vec3_t start, vec3_t aimdir, int speed); void fire_flame(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed); void fire_burst(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed); void fire_maintain(edict_t *, edict_t *, vec3_t start, vec3_t aimdir, int damage, int speed); void fire_incendiary_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius); void fire_player_melee(edict_t *self, vec3_t start, vec3_t aim, int reach, int damage, int kick, int quiet, int mod); void fire_tesla(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed); void fire_blaster2(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect, qboolean hyper); void fire_heat(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, int damage, int kick, qboolean monster); void fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, edict_t *enemy); /* g_newai.c */ qboolean blocked_checkplat(edict_t *self, float dist); qboolean blocked_checkjump(edict_t *self, float dist, float maxDown, float maxUp); qboolean blocked_checknewenemy(edict_t *self); qboolean monsterlost_checkhint(edict_t *self); qboolean inback(edict_t *self, edict_t *other); float realrange(edict_t *self, edict_t *other); edict_t *SpawnBadArea(vec3_t mins, vec3_t maxs, float lifespan, edict_t *owner); edict_t *CheckForBadArea(edict_t *ent); qboolean MarkTeslaArea(edict_t *self, edict_t *tesla); void InitHintPaths(void); void PredictAim(edict_t *target, vec3_t start, float bolt_speed, qboolean eye_height, float offset, vec3_t aimdir, vec3_t aimpoint); qboolean below(edict_t *self, edict_t *other); void drawbbox(edict_t *self); void M_MonsterDodge(edict_t *self, edict_t *attacker, float eta, trace_t *tr); void monster_duck_down(edict_t *self); void monster_duck_hold(edict_t *self); void monster_duck_up(edict_t *self); qboolean has_valid_enemy(edict_t *self); void TargetTesla(edict_t *self, edict_t *tesla); void hintpath_stop(edict_t *self); edict_t *PickCoopTarget(edict_t *self); int CountPlayers(void); void monster_jump_start(edict_t *self); qboolean monster_jump_finished(edict_t *self); qboolean blind_rocket_ok (edict_t *self, vec3_t start, vec3_t right, vec3_t target, float ofs, vec3_t dir); /* g_sphere.c */ void Defender_Launch(edict_t *self); void Vengeance_Launch(edict_t *self); void Hunter_Launch(edict_t *self); /* g_newdm.c */ void InitGameRules(void); edict_t *DoRandomRespawn(edict_t *ent); void PrecacheForRandomRespawn(void); qboolean Tag_PickupToken(edict_t *ent, edict_t *other); void Tag_DropToken(edict_t *ent, gitem_t *item); void Tag_PlayerDeath(edict_t *targ, edict_t *inflictor, edict_t *attacker); void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir); /* g_spawn.c */ edict_t *CreateMonster(vec3_t origin, vec3_t angles, char *classname); edict_t *CreateFlyMonster(vec3_t origin, vec3_t angles, vec3_t mins, vec3_t maxs, char *classname); edict_t *CreateGroundMonster(vec3_t origin, vec3_t angles, vec3_t mins, vec3_t maxs, char *classname, int height); qboolean FindSpawnPoint(vec3_t startpoint, vec3_t mins, vec3_t maxs, vec3_t spawnpoint, float maxMoveUp); qboolean CheckSpawnPoint(vec3_t origin, vec3_t mins, vec3_t maxs); qboolean CheckGroundSpawnPoint(vec3_t origin, vec3_t entMins, vec3_t entMaxs, float height, float gravity); void DetermineBBox(char *classname, vec3_t mins, vec3_t maxs); void SpawnGrow_Spawn(vec3_t startpos, int size); void Widowlegs_Spawn(vec3_t startpos, vec3_t angles); /* p_client.c */ void RemoveAttackingPainDaemons(edict_t *self); /* ============================================================================ */ /* client_t->anim_priority */ #define ANIM_BASIC 0 /* stand / run */ #define ANIM_WAVE 1 #define ANIM_JUMP 2 #define ANIM_PAIN 3 #define ANIM_ATTACK 4 #define ANIM_DEATH 5 #define ANIM_REVERSE 6 /* client data that stays across multiple level loads */ typedef struct { char userinfo[MAX_INFO_STRING]; char netname[16]; int hand; qboolean connected; /* a loadgame will leave valid entities that just don't have a connection yet */ /* values saved and restored from edicts when changing levels */ int health; int max_health; int savedFlags; int selected_item; int inventory[MAX_ITEMS]; /* ammo capacities */ int max_bullets; int max_shells; int max_rockets; int max_grenades; int max_cells; int max_slugs; gitem_t *weapon; gitem_t *lastweapon; int power_cubes; /* used for tracking the cubes in coop games */ int score; /* for calculating total unit score in coop games */ int game_helpchanged; int helpchanged; qboolean spectator; /* client is a spectator */ int max_tesla; int max_prox; int max_mines; int max_flechettes; int max_rounds; } client_persistant_t; /* client data that stays across deathmatch respawns */ typedef struct { client_persistant_t coop_respawn; /* what to set client->pers to on a respawn */ int enterframe; /* level.framenum the client entered the game */ int score; /* frags, etc */ vec3_t cmd_angles; /* angles sent over in the last command */ qboolean spectator; /* client is a spectator */ } client_respawn_t; /* this structure is cleared on each PutClientInServer(), except for 'client->pers' */ struct gclient_s { /* known to server */ player_state_t ps; /* communicated by server to clients */ int ping; /* private to game */ client_persistant_t pers; client_respawn_t resp; pmove_state_t old_pmove; /* for detecting out-of-pmove changes */ qboolean showscores; /* set layout stat */ qboolean showinventory; /* set layout stat */ qboolean showhelp; qboolean showhelpicon; int ammo_index; int buttons; int oldbuttons; int latched_buttons; qboolean weapon_thunk; gitem_t *newweapon; /* sum up damage over an entire frame, so shotgun blasts give a single big kick */ int damage_armor; /* damage absorbed by armor */ int damage_parmor; /* damage absorbed by power armor */ int damage_blood; /* damage taken out of health */ int damage_knockback; /* impact damage */ vec3_t damage_from; /* origin for vector calculation */ float killer_yaw; /* when dead, look at killer */ weaponstate_t weaponstate; vec3_t kick_angles; /* weapon kicks */ vec3_t kick_origin; float v_dmg_roll, v_dmg_pitch, v_dmg_time; /* damage kicks */ float fall_time, fall_value; /* for view drop on fall */ float damage_alpha; float bonus_alpha; vec3_t damage_blend; vec3_t v_angle; /* aiming direction */ float bobtime; /* so off-ground doesn't change it */ vec3_t oldviewangles; vec3_t oldvelocity; float next_drown_time; int old_waterlevel; int breather_sound; int machinegun_shots; /* for weapon raising */ /* animation vars */ int anim_end; int anim_priority; qboolean anim_duck; qboolean anim_run; /* powerup timers */ float quad_framenum; float invincible_framenum; float breather_framenum; float enviro_framenum; qboolean grenade_blew_up; float grenade_time; int silencer_shots; int weapon_sound; float pickup_msg_time; float flood_locktill; /* locked from talking */ float flood_when[10]; /* when messages were said */ int flood_whenhead; /* head pointer for when said */ float respawn_time; /* can respawn when time > this */ edict_t *chase_target; /* player we are chasing */ qboolean update_chase; /* need to update chase info? */ float double_framenum; float ir_framenum; float nuke_framenum; float tracker_pain_framenum; edict_t *owned_sphere; /* this points to the player's sphere */ }; struct edict_s { entity_state_t s; struct gclient_s *client; /* NULL if not a player the server expects the first part of gclient_s to be a player_state_t but the rest of it is opaque */ qboolean inuse; int linkcount; link_t area; /* linked to a division node or leaf */ int num_clusters; /* if -1, use headnode instead */ int clusternums[MAX_ENT_CLUSTERS]; int headnode; /* unused if num_clusters != -1 */ int areanum, areanum2; /* ================================ */ int svflags; vec3_t mins, maxs; vec3_t absmin, absmax, size; solid_t solid; int clipmask; edict_t *owner; /* DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER */ /* EXPECTS THE FIELDS IN THAT ORDER! */ /* ================================ */ int movetype; int flags; char *model; float freetime; /* sv.time when the object was freed */ /* only used locally in game, not by server */ char *message; char *classname; int spawnflags; float timestamp; float angle; /* set in qe3, -1 = up, -2 = down */ char *target; char *targetname; char *killtarget; char *team; char *pathtarget; char *deathtarget; char *combattarget; edict_t *target_ent; float speed, accel, decel; vec3_t movedir; vec3_t pos1, pos2; vec3_t velocity; vec3_t avelocity; int mass; float air_finished; float gravity; /* per entity gravity multiplier (1.0 is normal) */ /* use for lowgrav artifact, flares */ edict_t *goalentity; edict_t *movetarget; float yaw_speed; float ideal_yaw; float nextthink; void (*prethink) (edict_t *ent); void (*think)(edict_t *self); void (*blocked)(edict_t *self, edict_t *other); /* move to moveinfo? */ void (*touch)(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); void (*use)(edict_t *self, edict_t *other, edict_t *activator); void (*pain)(edict_t *self, edict_t *other, float kick, int damage); void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); float touch_debounce_time; float pain_debounce_time; float damage_debounce_time; float fly_sound_debounce_time; /* now also used by insane marines to store pain sound timeout */ float last_move_time; int health; int max_health; int gib_health; int deadflag; float show_hostile; float powerarmor_time; char *map; /* target_changelevel */ int viewheight; /* height above origin where eyesight is determined */ int takedamage; int dmg; int radius_dmg; float dmg_radius; int sounds; /* now also used for player death sound aggregation */ int count; edict_t *chain; edict_t *enemy; edict_t *oldenemy; edict_t *activator; edict_t *groundentity; int groundentity_linkcount; edict_t *teamchain; edict_t *teammaster; edict_t *mynoise; /* can go in client only */ edict_t *mynoise2; int noise_index; int noise_index2; float volume; float attenuation; /* timing variables */ float wait; float delay; /* before firing targets */ float random; float last_sound_time; int watertype; int waterlevel; vec3_t move_origin; vec3_t move_angles; int light_level; int style; /* also used as areaportal number */ gitem_t *item; /* for bonus items */ /* common data blocks */ moveinfo_t moveinfo; monsterinfo_t monsterinfo; int plat2flags; vec3_t offset; vec3_t gravityVector; edict_t *bad_area; edict_t *hint_chain; edict_t *monster_hint_chain; edict_t *target_hint_chain; int hint_chain_id; float lastMoveTime; }; #define SPHERE_DEFENDER 0x0001 #define SPHERE_HUNTER 0x0002 #define SPHERE_VENGEANCE 0x0004 #define SPHERE_DOPPLEGANGER 0x0100 #define SPHERE_TYPE 0x00FF #define SPHERE_FLAGS 0xFF00 /* deathmatch games */ #define RDM_TAG 2 #define RDM_DEATHBALL 3 typedef struct dm_game_rs { void (*GameInit)(void); void (*PostInitSetup)(void); void (*ClientBegin)(edict_t *ent); void (*SelectSpawnPoint)(edict_t *ent, vec3_t origin, vec3_t angles); void (*PlayerDeath)(edict_t *targ, edict_t *inflictor, edict_t *attacker); void (*Score)(edict_t *attacker, edict_t *victim, int scoreChange); void (*PlayerEffects)(edict_t *ent); void (*DogTag)(edict_t *ent, edict_t *killer, char **pic); void (*PlayerDisconnect)(edict_t *ent); int (*ChangeDamage)(edict_t *targ, edict_t *attacker, int damage, int mod); int (*ChangeKnockback)(edict_t *targ, edict_t *attacker, int knockback, int mod); int (*CheckDMRules)(void); } dm_game_rt; extern dm_game_rt DMGame; void Tag_GameInit(void); void Tag_PostInitSetup(void); void Tag_PlayerDeath(edict_t *targ, edict_t *inflictor, edict_t *attacker); void Tag_Score(edict_t *attacker, edict_t *victim, int scoreChange); void Tag_PlayerEffects(edict_t *ent); void Tag_DogTag(edict_t *ent, edict_t *killer, char **pic); void Tag_PlayerDisconnect(edict_t *ent); int Tag_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod); void DBall_GameInit(void); void DBall_ClientBegin(edict_t *ent); void DBall_SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles); int DBall_ChangeKnockback(edict_t *targ, edict_t *attacker, int knockback, int mod); int DBall_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod); void DBall_PostInitSetup(void); int DBall_CheckDMRules(void); #endif /* ROGUE_LOCAL_H */ rogue-ROGUE_2_13/src/header/shared.h000066400000000000000000001016041477320066100172500ustar00rootroot00000000000000/* * ======================================================================= * * This is the main header file shared between client, renderer, server * and the game. * * ======================================================================= */ #ifndef ROGUE_SHARED_H #define ROGUE_SHARED_H #include #include #include #include #include #include #include #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L // C23 or newer typedef bool qboolean; #else #ifdef true #undef true #endif #ifdef false #undef false #endif typedef enum {false, true} qboolean; #endif typedef unsigned char byte; #ifndef NULL #define NULL ((void *)0) #endif /* angle indexes */ #define PITCH 0 /* up / down */ #define YAW 1 /* left / right */ #define ROLL 2 /* fall over */ #define MAX_STRING_CHARS 1024 /* max length of a string passed to Cmd_TokenizeString */ #define MAX_STRING_TOKENS 80 /* max tokens resulting from Cmd_TokenizeString */ #define MAX_TOKEN_CHARS 128 /* max length of an individual token */ #define MAX_QPATH 64 /* max length of a quake game pathname */ #ifdef _WIN32 #define MAX_OSPATH 256 /* max length of a filesystem pathname (same as MAX_PATH) */ #else #define MAX_OSPATH 128 /* max length of a filesystem pathname */ #endif /* */ /* per-level limits */ /* */ #define MAX_CLIENTS 256 /* absolute limit */ #define MAX_EDICTS 1024 /* must change protocol to increase more */ #define MAX_LIGHTSTYLES 256 #define MAX_MODELS 256 /* these are sent over the net as bytes */ #define MAX_SOUNDS 256 /* so they cannot be blindly increased */ #define MAX_IMAGES 256 #define MAX_ITEMS 256 #define MAX_GENERAL (MAX_CLIENTS * 2) /* general config strings */ /* game print flags */ #define PRINT_LOW 0 /* pickup messages */ #define PRINT_MEDIUM 1 /* death messages */ #define PRINT_HIGH 2 /* critical messages */ #define PRINT_CHAT 3 /* chat messages */ #define ERR_FATAL 0 /* exit the entire game with a popup window */ #define ERR_DROP 1 /* print to console and disconnect from game */ #define ERR_DISCONNECT 2 /* don't kill server */ #define PRINT_ALL 0 #define PRINT_DEVELOPER 1 /* only print when "developer 1" */ #define PRINT_ALERT 2 /* destination class for gi.multicast() */ typedef enum { MULTICAST_ALL, MULTICAST_PHS, MULTICAST_PVS, MULTICAST_ALL_R, MULTICAST_PHS_R, MULTICAST_PVS_R } multicast_t; /* * ============================================================== * * MATHLIB * * ============================================================== */ typedef float vec_t; typedef vec_t vec3_t[3]; typedef vec_t vec5_t[5]; typedef int fixed4_t; typedef int fixed8_t; typedef int fixed16_t; #ifndef M_PI #define M_PI 3.14159265358979323846 /* matches value in gcc v2 math.h */ #endif struct cplane_s; extern vec3_t vec3_origin; #define nanmask (255 << 23) #define IS_NAN(x) (((*(int *)&x) & nanmask) == nanmask) #define Q_ftol(f) (long)(f) #define DotProduct(x, y) (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]) #define VectorSubtract(a, b, c) (c[0] = a[0] - b[0], c[1] = a[1] - b[1], c[2] = \ a[2] - b[2]) #define VectorAdd(a, b, c) (c[0] = a[0] + b[0], c[1] = a[1] + b[1], c[2] = \ a[2] + b[2]) #define VectorCopy(a, b) (b[0] = a[0], b[1] = a[1], b[2] = a[2]) #define VectorClear(a) (a[0] = a[1] = a[2] = 0) #define VectorNegate(a, b) (b[0] = -a[0], b[1] = -a[1], b[2] = -a[2]) #define VectorSet(v, x, y, z) (v[0] = (x), v[1] = (y), v[2] = (z)) void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); /* just in case you do't want to use the macros */ vec_t _DotProduct(vec3_t v1, vec3_t v2); void _VectorSubtract(vec3_t veca, vec3_t vecb, vec3_t out); void _VectorAdd(vec3_t veca, vec3_t vecb, vec3_t out); void _VectorCopy(vec3_t in, vec3_t out); void ClearBounds(vec3_t mins, vec3_t maxs); void AddPointToBounds(vec3_t v, vec3_t mins, vec3_t maxs); int VectorCompare(vec3_t v1, vec3_t v2); vec_t VectorLength(vec3_t v); void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross); vec_t VectorNormalize(vec3_t v); /* returns vector length */ vec_t VectorNormalize2(vec3_t v, vec3_t out); void VectorInverse(vec3_t v); void VectorScale(vec3_t in, vec_t scale, vec3_t out); int Q_log2(int val); void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]); void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void AngleVectors2(vec3_t value1, vec3_t angles); int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *plane); float anglemod(float a); float LerpAngle(float a1, float a2, float frac); #define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ (((p)->type < 3) ? \ ( \ ((p)->dist <= (emins)[(p)->type]) ? \ 1 \ : \ ( \ ((p)->dist >= (emaxs)[(p)->type]) ? \ 2 \ : \ 3 \ ) \ ) \ : \ BoxOnPlaneSide((emins), (emaxs), (p))) void ProjectPointOnPlane(vec3_t dst, const vec3_t p, const vec3_t normal); void PerpendicularVector(vec3_t dst, const vec3_t src); void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); /* ============================================= */ char *COM_SkipPath(char *pathname); void COM_StripExtension(char *in, char *out); void COM_FileBase(char *in, char *out); void COM_FilePath(const char *in, char *out); void COM_DefaultExtension(char *path, const char *extension); char *COM_Parse(char **data_p); /* data is an in/out parm, returns a parsed out token */ void Com_sprintf(char *dest, int size, char *fmt, ...); void Com_PageInMemory(byte *buffer, int size); char *strlwr ( char *s ); int Q_strlcpy(char *dst, const char *src, int size); int Q_strlcat(char *dst, const char *src, int size); /* ============================================= */ /* portable case insensitive compare */ int Q_stricmp(const char *s1, const char *s2); int Q_strcasecmp(char *s1, char *s2); int Q_strncasecmp(char *s1, char *s2, int n); /* ============================================= */ short BigShort(short l); short LittleShort(short l); int BigLong(int l); int LittleLong(int l); float BigFloat(float l); float LittleFloat(float l); void Swap_Init(void); char *va(const char *format, ...); /* ============================================= */ /* key / value info strings */ #define MAX_INFO_KEY 64 #define MAX_INFO_VALUE 64 #define MAX_INFO_STRING 512 char *Info_ValueForKey(char *s, char *key); void Info_RemoveKey(char *s, char *key); void Info_SetValueForKey(char *s, char *key, char *value); qboolean Info_Validate(char *s); /* ============================================= */ /* Random number generator */ int randk(void); float frandk(void); float crandk(void); void randk_seed(void); /* * ============================================================== * * SYSTEM SPECIFIC * * ============================================================== */ extern int curtime; /* time returned by last Sys_Milliseconds */ int Sys_Milliseconds(void); void Sys_Mkdir(char *path); char *strlwr(char *s); /* large block stack allocation routines */ void *Hunk_Begin(int maxsize); void *Hunk_Alloc(int size); void Hunk_Free(void *buf); int Hunk_End(void); /* directory searching */ #define SFF_ARCH 0x01 #define SFF_HIDDEN 0x02 #define SFF_RDONLY 0x04 #define SFF_SUBDIR 0x08 #define SFF_SYSTEM 0x10 /* pass in an attribute mask of things you wish to REJECT */ char *Sys_FindFirst(char *path, unsigned musthave, unsigned canthave); char *Sys_FindNext(unsigned musthave, unsigned canthave); void Sys_FindClose(void); /* this is only here so the functions in q_shared.c and q_shwin.c can link */ void Sys_Error(char *error, ...); void Com_Printf(char *msg, ...); /* * ========================================================== * * CVARS (console variables) * * ========================================================== */ #ifndef CVAR #define CVAR #define CVAR_ARCHIVE 1 /* set to cause it to be saved to vars.rc */ #define CVAR_USERINFO 2 /* added to userinfo when changed */ #define CVAR_SERVERINFO 4 /* added to serverinfo when changed */ #define CVAR_NOSET 8 /* don't allow change from console at all, */ /* but can be set from the command line */ #define CVAR_LATCH 16 /* save changes until server restart */ /* nothing outside the Cvar_*() functions should modify these fields! */ typedef struct cvar_s { char *name; char *string; char *latched_string; /* for CVAR_LATCH vars */ int flags; qboolean modified; /* set each time the cvar is changed */ float value; struct cvar_s *next; } cvar_t; #endif /* CVAR */ /* * ============================================================== * * COLLISION DETECTION * * ============================================================== */ /* lower bits are stronger, and will eat weaker brushes completely */ #define CONTENTS_SOLID 1 /* an eye is never valid in a solid */ #define CONTENTS_WINDOW 2 /* translucent, but not watery */ #define CONTENTS_AUX 4 #define CONTENTS_LAVA 8 #define CONTENTS_SLIME 16 #define CONTENTS_WATER 32 #define CONTENTS_MIST 64 #define LAST_VISIBLE_CONTENTS 64 /* remaining contents are non-visible, and don't eat brushes */ #define CONTENTS_AREAPORTAL 0x8000 #define CONTENTS_PLAYERCLIP 0x10000 #define CONTENTS_MONSTERCLIP 0x20000 /* currents can be added to any other contents, and may be mixed */ #define CONTENTS_CURRENT_0 0x40000 #define CONTENTS_CURRENT_90 0x80000 #define CONTENTS_CURRENT_180 0x100000 #define CONTENTS_CURRENT_270 0x200000 #define CONTENTS_CURRENT_UP 0x400000 #define CONTENTS_CURRENT_DOWN 0x800000 #define CONTENTS_ORIGIN 0x1000000 /* removed before bsping an entity */ #define CONTENTS_MONSTER 0x2000000 /* should never be on a brush, only in game */ #define CONTENTS_DEADMONSTER 0x4000000 #define CONTENTS_DETAIL 0x8000000 /* brushes to be added after vis leafs */ #define CONTENTS_TRANSLUCENT 0x10000000 /* auto set if any surface has trans */ #define CONTENTS_LADDER 0x20000000 #define SURF_LIGHT 0x1 /* value will hold the light strength */ #define SURF_SLICK 0x2 /* effects game physics */ #define SURF_SKY 0x4 /* don't draw, but add to skybox */ #define SURF_WARP 0x8 /* turbulent water warp */ #define SURF_TRANS33 0x10 #define SURF_TRANS66 0x20 #define SURF_FLOWING 0x40 /* scroll towards angle */ #define SURF_NODRAW 0x80 /* don't bother referencing the texture */ /* content masks */ #define MASK_ALL (-1) #define MASK_SOLID (CONTENTS_SOLID | CONTENTS_WINDOW) #define MASK_PLAYERSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | \ CONTENTS_WINDOW | CONTENTS_MONSTER) #define MASK_DEADSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW) #define MASK_MONSTERSOLID (CONTENTS_SOLID | CONTENTS_MONSTERCLIP | \ CONTENTS_WINDOW | CONTENTS_MONSTER) #define MASK_WATER (CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME) #define MASK_OPAQUE (CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA) #define MASK_SHOT (CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_WINDOW | \ CONTENTS_DEADMONSTER) #define MASK_CURRENT (CONTENTS_CURRENT_0 | CONTENTS_CURRENT_90 | \ CONTENTS_CURRENT_180 | CONTENTS_CURRENT_270 | \ CONTENTS_CURRENT_UP | \ CONTENTS_CURRENT_DOWN) /* gi.BoxEdicts() can return a list of either solid or trigger entities */ #define AREA_SOLID 1 #define AREA_TRIGGERS 2 /* plane_t structure */ typedef struct cplane_s { vec3_t normal; float dist; byte type; /* for fast side tests */ byte signbits; /* signx + (signy<<1) + (signz<<1) */ byte pad[2]; } cplane_t; /* structure offset for asm code */ #define CPLANE_NORMAL_X 0 #define CPLANE_NORMAL_Y 4 #define CPLANE_NORMAL_Z 8 #define CPLANE_DIST 12 #define CPLANE_TYPE 16 #define CPLANE_SIGNBITS 17 #define CPLANE_PAD0 18 #define CPLANE_PAD1 19 typedef struct cmodel_s { vec3_t mins, maxs; vec3_t origin; /* for sounds or lights */ int headnode; } cmodel_t; typedef struct csurface_s { char name[16]; int flags; int value; } csurface_t; typedef struct mapsurface_s /* used internally due to name len probs */ { csurface_t c; char rname[32]; } mapsurface_t; /* a trace is returned when a box is swept through the world */ typedef struct { qboolean allsolid; /* if true, plane is not valid */ qboolean startsolid; /* if true, the initial point was in a solid area */ float fraction; /* time completed, 1.0 = didn't hit anything */ vec3_t endpos; /* final position */ cplane_t plane; /* surface normal at impact */ csurface_t *surface; /* surface hit */ int contents; /* contents on other side of surface hit */ struct edict_s *ent; /* not set by CM_*() functions */ } trace_t; /* pmove_state_t is the information necessary for client side movement */ /* prediction */ typedef enum { /* can accelerate and turn */ PM_NORMAL, PM_SPECTATOR, /* no acceleration or turning */ PM_DEAD, PM_GIB, /* different bounding box */ PM_FREEZE } pmtype_t; /* pmove->pm_flags */ #define PMF_DUCKED 1 #define PMF_JUMP_HELD 2 #define PMF_ON_GROUND 4 #define PMF_TIME_WATERJUMP 8 /* pm_time is waterjump */ #define PMF_TIME_LAND 16 /* pm_time is time before rejump */ #define PMF_TIME_TELEPORT 32 /* pm_time is non-moving time */ #define PMF_NO_PREDICTION 64 /* temporarily disables prediction (used for grappling hook) */ /* this structure needs to be communicated bit-accurate/ from the server to the client to guarantee that prediction stays in sync, so no floats are used. if any part of the game code modifies this struct, it will result in a prediction error of some degree. */ typedef struct { pmtype_t pm_type; short origin[3]; /* 12.3 */ short velocity[3]; /* 12.3 */ byte pm_flags; /* ducked, jump_held, etc */ byte pm_time; /* each unit = 8 ms */ short gravity; short delta_angles[3]; /* add to command angles to get view direction changed by spawns, rotating objects, and teleporters */ } pmove_state_t; /* button bits */ #define BUTTON_ATTACK 1 #define BUTTON_USE 2 #define BUTTON_ANY 128 /* any key whatsoever */ /* usercmd_t is sent to the server each client frame */ typedef struct usercmd_s { byte msec; byte buttons; short angles[3]; short forwardmove, sidemove, upmove; byte impulse; /* remove? */ byte lightlevel; /* light level the player is standing on */ } usercmd_t; #define MAXTOUCH 32 typedef struct { /* state (in / out) */ pmove_state_t s; /* command (in) */ usercmd_t cmd; qboolean snapinitial; /* if s has been changed outside pmove */ /* results (out) */ int numtouch; struct edict_s *touchents[MAXTOUCH]; vec3_t viewangles; /* clamped */ float viewheight; vec3_t mins, maxs; /* bounding box size */ struct edict_s *groundentity; int watertype; int waterlevel; /* callbacks to test the world */ trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end); int (*pointcontents)(vec3_t point); } pmove_t; /* entity_state_t->effects Effects are things handled on the client side (lights, particles, frame animations) that happen constantly on the given entity. An entity that has effects will be sent to the client even if it has a zero index model. */ #define EF_ROTATE 0x00000001 /* rotate (bonus items) */ #define EF_GIB 0x00000002 /* leave a trail */ #define EF_BLASTER 0x00000008 /* redlight + trail */ #define EF_ROCKET 0x00000010 /* redlight + trail */ #define EF_GRENADE 0x00000020 #define EF_HYPERBLASTER 0x00000040 #define EF_BFG 0x00000080 #define EF_COLOR_SHELL 0x00000100 #define EF_POWERSCREEN 0x00000200 #define EF_ANIM01 0x00000400 /* automatically cycle between frames 0 and 1 at 2 hz */ #define EF_ANIM23 0x00000800 /* automatically cycle between frames 2 and 3 at 2 hz */ #define EF_ANIM_ALL 0x00001000 /* automatically cycle through all frames at 2hz */ #define EF_ANIM_ALLFAST 0x00002000 /* automatically cycle through all frames at 10hz */ #define EF_FLIES 0x00004000 #define EF_QUAD 0x00008000 #define EF_PENT 0x00010000 #define EF_TELEPORTER 0x00020000 /* particle fountain */ #define EF_FLAG1 0x00040000 #define EF_FLAG2 0x00080000 #define EF_IONRIPPER 0x00100000 #define EF_GREENGIB 0x00200000 #define EF_BLUEHYPERBLASTER 0x00400000 #define EF_SPINNINGLIGHTS 0x00800000 #define EF_PLASMA 0x01000000 #define EF_TRAP 0x02000000 #define EF_TRACKER 0x04000000 #define EF_DOUBLE 0x08000000 #define EF_SPHERETRANS 0x10000000 #define EF_TAGTRAIL 0x20000000 #define EF_HALF_DAMAGE 0x40000000 #define EF_TRACKERTRAIL 0x80000000 /* entity_state_t->renderfx flags */ #define RF_MINLIGHT 1 /* allways have some light (viewmodel) */ #define RF_VIEWERMODEL 2 /* don't draw through eyes, only mirrors */ #define RF_WEAPONMODEL 4 /* only draw through eyes */ #define RF_FULLBRIGHT 8 /* allways draw full intensity */ #define RF_DEPTHHACK 16 /* for view weapon Z crunching */ #define RF_TRANSLUCENT 32 #define RF_FRAMELERP 64 #define RF_BEAM 128 #define RF_CUSTOMSKIN 256 /* skin is an index in image_precache */ #define RF_GLOW 512 /* pulse lighting for bonus items */ #define RF_SHELL_RED 1024 #define RF_SHELL_GREEN 2048 #define RF_SHELL_BLUE 4096 #define RF_NOSHADOW 8192 /* don't draw a shadow */ #define RF_IR_VISIBLE 0x00008000 /* 32768 */ #define RF_SHELL_DOUBLE 0x00010000 /* 65536 */ #define RF_SHELL_HALF_DAM 0x00020000 #define RF_USE_DISGUISE 0x00040000 /* player_state_t->refdef flags */ #define RDF_UNDERWATER 1 /* warp the screen as apropriate */ #define RDF_NOWORLDMODEL 2 /* used for player configuration screen */ #define RDF_IRGOGGLES 4 #define RDF_UVGOGGLES 8 /* muzzle flashes / player effects */ #define MZ_BLASTER 0 #define MZ_MACHINEGUN 1 #define MZ_SHOTGUN 2 #define MZ_CHAINGUN1 3 #define MZ_CHAINGUN2 4 #define MZ_CHAINGUN3 5 #define MZ_RAILGUN 6 #define MZ_ROCKET 7 #define MZ_GRENADE 8 #define MZ_LOGIN 9 #define MZ_LOGOUT 10 #define MZ_RESPAWN 11 #define MZ_BFG 12 #define MZ_SSHOTGUN 13 #define MZ_HYPERBLASTER 14 #define MZ_ITEMRESPAWN 15 #define MZ_IONRIPPER 16 #define MZ_BLUEHYPERBLASTER 17 #define MZ_PHALANX 18 #define MZ_SILENCED 128 /* bit flag ORed with one of the above numbers */ #define MZ_ETF_RIFLE 30 #define MZ_UNUSED 31 #define MZ_SHOTGUN2 32 #define MZ_HEATBEAM 33 #define MZ_BLASTER2 34 #define MZ_TRACKER 35 #define MZ_NUKE1 36 #define MZ_NUKE2 37 #define MZ_NUKE4 38 #define MZ_NUKE8 39 /* monster muzzle flashes */ #define MZ2_TANK_BLASTER_1 1 #define MZ2_TANK_BLASTER_2 2 #define MZ2_TANK_BLASTER_3 3 #define MZ2_TANK_MACHINEGUN_1 4 #define MZ2_TANK_MACHINEGUN_2 5 #define MZ2_TANK_MACHINEGUN_3 6 #define MZ2_TANK_MACHINEGUN_4 7 #define MZ2_TANK_MACHINEGUN_5 8 #define MZ2_TANK_MACHINEGUN_6 9 #define MZ2_TANK_MACHINEGUN_7 10 #define MZ2_TANK_MACHINEGUN_8 11 #define MZ2_TANK_MACHINEGUN_9 12 #define MZ2_TANK_MACHINEGUN_10 13 #define MZ2_TANK_MACHINEGUN_11 14 #define MZ2_TANK_MACHINEGUN_12 15 #define MZ2_TANK_MACHINEGUN_13 16 #define MZ2_TANK_MACHINEGUN_14 17 #define MZ2_TANK_MACHINEGUN_15 18 #define MZ2_TANK_MACHINEGUN_16 19 #define MZ2_TANK_MACHINEGUN_17 20 #define MZ2_TANK_MACHINEGUN_18 21 #define MZ2_TANK_MACHINEGUN_19 22 #define MZ2_TANK_ROCKET_1 23 #define MZ2_TANK_ROCKET_2 24 #define MZ2_TANK_ROCKET_3 25 #define MZ2_INFANTRY_MACHINEGUN_1 26 #define MZ2_INFANTRY_MACHINEGUN_2 27 #define MZ2_INFANTRY_MACHINEGUN_3 28 #define MZ2_INFANTRY_MACHINEGUN_4 29 #define MZ2_INFANTRY_MACHINEGUN_5 30 #define MZ2_INFANTRY_MACHINEGUN_6 31 #define MZ2_INFANTRY_MACHINEGUN_7 32 #define MZ2_INFANTRY_MACHINEGUN_8 33 #define MZ2_INFANTRY_MACHINEGUN_9 34 #define MZ2_INFANTRY_MACHINEGUN_10 35 #define MZ2_INFANTRY_MACHINEGUN_11 36 #define MZ2_INFANTRY_MACHINEGUN_12 37 #define MZ2_INFANTRY_MACHINEGUN_13 38 #define MZ2_SOLDIER_BLASTER_1 39 #define MZ2_SOLDIER_BLASTER_2 40 #define MZ2_SOLDIER_SHOTGUN_1 41 #define MZ2_SOLDIER_SHOTGUN_2 42 #define MZ2_SOLDIER_MACHINEGUN_1 43 #define MZ2_SOLDIER_MACHINEGUN_2 44 #define MZ2_GUNNER_MACHINEGUN_1 45 #define MZ2_GUNNER_MACHINEGUN_2 46 #define MZ2_GUNNER_MACHINEGUN_3 47 #define MZ2_GUNNER_MACHINEGUN_4 48 #define MZ2_GUNNER_MACHINEGUN_5 49 #define MZ2_GUNNER_MACHINEGUN_6 50 #define MZ2_GUNNER_MACHINEGUN_7 51 #define MZ2_GUNNER_MACHINEGUN_8 52 #define MZ2_GUNNER_GRENADE_1 53 #define MZ2_GUNNER_GRENADE_2 54 #define MZ2_GUNNER_GRENADE_3 55 #define MZ2_GUNNER_GRENADE_4 56 #define MZ2_CHICK_ROCKET_1 57 #define MZ2_FLYER_BLASTER_1 58 #define MZ2_FLYER_BLASTER_2 59 #define MZ2_MEDIC_BLASTER_1 60 #define MZ2_GLADIATOR_RAILGUN_1 61 #define MZ2_HOVER_BLASTER_1 62 #define MZ2_ACTOR_MACHINEGUN_1 63 #define MZ2_SUPERTANK_MACHINEGUN_1 64 #define MZ2_SUPERTANK_MACHINEGUN_2 65 #define MZ2_SUPERTANK_MACHINEGUN_3 66 #define MZ2_SUPERTANK_MACHINEGUN_4 67 #define MZ2_SUPERTANK_MACHINEGUN_5 68 #define MZ2_SUPERTANK_MACHINEGUN_6 69 #define MZ2_SUPERTANK_ROCKET_1 70 #define MZ2_SUPERTANK_ROCKET_2 71 #define MZ2_SUPERTANK_ROCKET_3 72 #define MZ2_BOSS2_MACHINEGUN_L1 73 #define MZ2_BOSS2_MACHINEGUN_L2 74 #define MZ2_BOSS2_MACHINEGUN_L3 75 #define MZ2_BOSS2_MACHINEGUN_L4 76 #define MZ2_BOSS2_MACHINEGUN_L5 77 #define MZ2_BOSS2_ROCKET_1 78 #define MZ2_BOSS2_ROCKET_2 79 #define MZ2_BOSS2_ROCKET_3 80 #define MZ2_BOSS2_ROCKET_4 81 #define MZ2_FLOAT_BLASTER_1 82 #define MZ2_SOLDIER_BLASTER_3 83 #define MZ2_SOLDIER_SHOTGUN_3 84 #define MZ2_SOLDIER_MACHINEGUN_3 85 #define MZ2_SOLDIER_BLASTER_4 86 #define MZ2_SOLDIER_SHOTGUN_4 87 #define MZ2_SOLDIER_MACHINEGUN_4 88 #define MZ2_SOLDIER_BLASTER_5 89 #define MZ2_SOLDIER_SHOTGUN_5 90 #define MZ2_SOLDIER_MACHINEGUN_5 91 #define MZ2_SOLDIER_BLASTER_6 92 #define MZ2_SOLDIER_SHOTGUN_6 93 #define MZ2_SOLDIER_MACHINEGUN_6 94 #define MZ2_SOLDIER_BLASTER_7 95 #define MZ2_SOLDIER_SHOTGUN_7 96 #define MZ2_SOLDIER_MACHINEGUN_7 97 #define MZ2_SOLDIER_BLASTER_8 98 #define MZ2_SOLDIER_SHOTGUN_8 99 #define MZ2_SOLDIER_MACHINEGUN_8 100 #define MZ2_MAKRON_BFG 101 #define MZ2_MAKRON_BLASTER_1 102 #define MZ2_MAKRON_BLASTER_2 103 #define MZ2_MAKRON_BLASTER_3 104 #define MZ2_MAKRON_BLASTER_4 105 #define MZ2_MAKRON_BLASTER_5 106 #define MZ2_MAKRON_BLASTER_6 107 #define MZ2_MAKRON_BLASTER_7 108 #define MZ2_MAKRON_BLASTER_8 109 #define MZ2_MAKRON_BLASTER_9 110 #define MZ2_MAKRON_BLASTER_10 111 #define MZ2_MAKRON_BLASTER_11 112 #define MZ2_MAKRON_BLASTER_12 113 #define MZ2_MAKRON_BLASTER_13 114 #define MZ2_MAKRON_BLASTER_14 115 #define MZ2_MAKRON_BLASTER_15 116 #define MZ2_MAKRON_BLASTER_16 117 #define MZ2_MAKRON_BLASTER_17 118 #define MZ2_MAKRON_RAILGUN_1 119 #define MZ2_JORG_MACHINEGUN_L1 120 #define MZ2_JORG_MACHINEGUN_L2 121 #define MZ2_JORG_MACHINEGUN_L3 122 #define MZ2_JORG_MACHINEGUN_L4 123 #define MZ2_JORG_MACHINEGUN_L5 124 #define MZ2_JORG_MACHINEGUN_L6 125 #define MZ2_JORG_MACHINEGUN_R1 126 #define MZ2_JORG_MACHINEGUN_R2 127 #define MZ2_JORG_MACHINEGUN_R3 128 #define MZ2_JORG_MACHINEGUN_R4 129 #define MZ2_JORG_MACHINEGUN_R5 130 #define MZ2_JORG_MACHINEGUN_R6 131 #define MZ2_JORG_BFG_1 132 #define MZ2_BOSS2_MACHINEGUN_R1 133 #define MZ2_BOSS2_MACHINEGUN_R2 134 #define MZ2_BOSS2_MACHINEGUN_R3 135 #define MZ2_BOSS2_MACHINEGUN_R4 136 #define MZ2_BOSS2_MACHINEGUN_R5 137 #define MZ2_CARRIER_MACHINEGUN_L1 138 #define MZ2_CARRIER_MACHINEGUN_R1 139 #define MZ2_CARRIER_GRENADE 140 #define MZ2_TURRET_MACHINEGUN 141 #define MZ2_TURRET_ROCKET 142 #define MZ2_TURRET_BLASTER 143 #define MZ2_STALKER_BLASTER 144 #define MZ2_DAEDALUS_BLASTER 145 #define MZ2_MEDIC_BLASTER_2 146 #define MZ2_CARRIER_RAILGUN 147 #define MZ2_WIDOW_DISRUPTOR 148 #define MZ2_WIDOW_BLASTER 149 #define MZ2_WIDOW_RAIL 150 #define MZ2_WIDOW_PLASMABEAM 151 #define MZ2_CARRIER_MACHINEGUN_L2 152 #define MZ2_CARRIER_MACHINEGUN_R2 153 #define MZ2_WIDOW_RAIL_LEFT 154 #define MZ2_WIDOW_RAIL_RIGHT 155 #define MZ2_WIDOW_BLASTER_SWEEP1 156 #define MZ2_WIDOW_BLASTER_SWEEP2 157 #define MZ2_WIDOW_BLASTER_SWEEP3 158 #define MZ2_WIDOW_BLASTER_SWEEP4 159 #define MZ2_WIDOW_BLASTER_SWEEP5 160 #define MZ2_WIDOW_BLASTER_SWEEP6 161 #define MZ2_WIDOW_BLASTER_SWEEP7 162 #define MZ2_WIDOW_BLASTER_SWEEP8 163 #define MZ2_WIDOW_BLASTER_SWEEP9 164 #define MZ2_WIDOW_BLASTER_100 165 #define MZ2_WIDOW_BLASTER_90 166 #define MZ2_WIDOW_BLASTER_80 167 #define MZ2_WIDOW_BLASTER_70 168 #define MZ2_WIDOW_BLASTER_60 169 #define MZ2_WIDOW_BLASTER_50 170 #define MZ2_WIDOW_BLASTER_40 171 #define MZ2_WIDOW_BLASTER_30 172 #define MZ2_WIDOW_BLASTER_20 173 #define MZ2_WIDOW_BLASTER_10 174 #define MZ2_WIDOW_BLASTER_0 175 #define MZ2_WIDOW_BLASTER_10L 176 #define MZ2_WIDOW_BLASTER_20L 177 #define MZ2_WIDOW_BLASTER_30L 178 #define MZ2_WIDOW_BLASTER_40L 179 #define MZ2_WIDOW_BLASTER_50L 180 #define MZ2_WIDOW_BLASTER_60L 181 #define MZ2_WIDOW_BLASTER_70L 182 #define MZ2_WIDOW_RUN_1 183 #define MZ2_WIDOW_RUN_2 184 #define MZ2_WIDOW_RUN_3 185 #define MZ2_WIDOW_RUN_4 186 #define MZ2_WIDOW_RUN_5 187 #define MZ2_WIDOW_RUN_6 188 #define MZ2_WIDOW_RUN_7 189 #define MZ2_WIDOW_RUN_8 190 #define MZ2_CARRIER_ROCKET_1 191 #define MZ2_CARRIER_ROCKET_2 192 #define MZ2_CARRIER_ROCKET_3 193 #define MZ2_CARRIER_ROCKET_4 194 #define MZ2_WIDOW2_BEAMER_1 195 #define MZ2_WIDOW2_BEAMER_2 196 #define MZ2_WIDOW2_BEAMER_3 197 #define MZ2_WIDOW2_BEAMER_4 198 #define MZ2_WIDOW2_BEAMER_5 199 #define MZ2_WIDOW2_BEAM_SWEEP_1 200 #define MZ2_WIDOW2_BEAM_SWEEP_2 201 #define MZ2_WIDOW2_BEAM_SWEEP_3 202 #define MZ2_WIDOW2_BEAM_SWEEP_4 203 #define MZ2_WIDOW2_BEAM_SWEEP_5 204 #define MZ2_WIDOW2_BEAM_SWEEP_6 205 #define MZ2_WIDOW2_BEAM_SWEEP_7 206 #define MZ2_WIDOW2_BEAM_SWEEP_8 207 #define MZ2_WIDOW2_BEAM_SWEEP_9 208 #define MZ2_WIDOW2_BEAM_SWEEP_10 209 #define MZ2_WIDOW2_BEAM_SWEEP_11 210 extern vec3_t monster_flash_offset[]; /* Temp entity events are for things that happen at a location seperate from any existing entity. Temporary entity messages are explicitly constructed and broadcast. */ typedef enum { TE_GUNSHOT, TE_BLOOD, TE_BLASTER, TE_RAILTRAIL, TE_SHOTGUN, TE_EXPLOSION1, TE_EXPLOSION2, TE_ROCKET_EXPLOSION, TE_GRENADE_EXPLOSION, TE_SPARKS, TE_SPLASH, TE_BUBBLETRAIL, TE_SCREEN_SPARKS, TE_SHIELD_SPARKS, TE_BULLET_SPARKS, TE_LASER_SPARKS, TE_PARASITE_ATTACK, TE_ROCKET_EXPLOSION_WATER, TE_GRENADE_EXPLOSION_WATER, TE_MEDIC_CABLE_ATTACK, TE_BFG_EXPLOSION, TE_BFG_BIGEXPLOSION, TE_BOSSTPORT, /* used as '22' in a map, so DON'T RENUMBER!!! */ TE_BFG_LASER, TE_GRAPPLE_CABLE, TE_WELDING_SPARKS, TE_GREENBLOOD, TE_BLUEHYPERBLASTER, TE_PLASMA_EXPLOSION, TE_TUNNEL_SPARKS, TE_BLASTER2, TE_RAILTRAIL2, TE_FLAME, TE_LIGHTNING, TE_DEBUGTRAIL, TE_PLAIN_EXPLOSION, TE_FLASHLIGHT, TE_FORCEWALL, TE_HEATBEAM, TE_MONSTER_HEATBEAM, TE_STEAM, TE_BUBBLETRAIL2, TE_MOREBLOOD, TE_HEATBEAM_SPARKS, TE_HEATBEAM_STEAM, TE_CHAINFIST_SMOKE, TE_ELECTRIC_SPARKS, TE_TRACKER_EXPLOSION, TE_TELEPORT_EFFECT, TE_DBALL_GOAL, TE_WIDOWBEAMOUT, TE_NUKEBLAST, TE_WIDOWSPLASH, TE_EXPLOSION1_BIG, TE_EXPLOSION1_NP, TE_FLECHETTE } temp_event_t; #define SPLASH_UNKNOWN 0 #define SPLASH_SPARKS 1 #define SPLASH_BLUE_WATER 2 #define SPLASH_BROWN_WATER 3 #define SPLASH_SLIME 4 #define SPLASH_LAVA 5 #define SPLASH_BLOOD 6 /* 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 /* modifier flags */ #define CHAN_NO_PHS_ADD 8 /* send to all clients, not just ones in PHS (ATTN 0 will also do this) */ #define CHAN_RELIABLE 16 /* send by reliable message, not datagram */ /* sound attenuation values */ #define ATTN_NONE 0 /* full volume the entire level */ #define ATTN_NORM 1 #define ATTN_IDLE 2 #define ATTN_STATIC 3 /* diminish very rapidly with distance */ /* player_state->stats[] indexes */ #define STAT_HEALTH_ICON 0 #define STAT_HEALTH 1 #define STAT_AMMO_ICON 2 #define STAT_AMMO 3 #define STAT_ARMOR_ICON 4 #define STAT_ARMOR 5 #define STAT_SELECTED_ICON 6 #define STAT_PICKUP_ICON 7 #define STAT_PICKUP_STRING 8 #define STAT_TIMER_ICON 9 #define STAT_TIMER 10 #define STAT_HELPICON 11 #define STAT_SELECTED_ITEM 12 #define STAT_LAYOUTS 13 #define STAT_FRAGS 14 #define STAT_FLASHES 15 /* cleared each frame, 1 = health, 2 = armor */ #define STAT_CHASE 16 #define STAT_SPECTATOR 17 #define MAX_STATS 32 /* dmflags->value flags */ #define DF_NO_HEALTH 0x00000001 /* 1 */ #define DF_NO_ITEMS 0x00000002 /* 2 */ #define DF_WEAPONS_STAY 0x00000004 /* 4 */ #define DF_NO_FALLING 0x00000008 /* 8 */ #define DF_INSTANT_ITEMS 0x00000010 /* 16 */ #define DF_SAME_LEVEL 0x00000020 /* 32 */ #define DF_SKINTEAMS 0x00000040 /* 64 */ #define DF_MODELTEAMS 0x00000080 /* 128 */ #define DF_NO_FRIENDLY_FIRE 0x00000100 /* 256 */ #define DF_SPAWN_FARTHEST 0x00000200 /* 512 */ #define DF_FORCE_RESPAWN 0x00000400 /* 1024 */ #define DF_NO_ARMOR 0x00000800 /* 2048 */ #define DF_ALLOW_EXIT 0x00001000 /* 4096 */ #define DF_INFINITE_AMMO 0x00002000 /* 8192 */ #define DF_QUAD_DROP 0x00004000 /* 16384 */ #define DF_FIXED_FOV 0x00008000 /* 32768 */ #define DF_QUADFIRE_DROP 0x00010000 /* 65536 */ #define DF_NO_MINES 0x00020000 #define DF_NO_STACK_DOUBLE 0x00040000 #define DF_NO_NUKES 0x00080000 #define DF_NO_SPHERES 0x00100000 #define ROGUE_VERSION_STRING "08/21/1998 Beta 2 for Ensemble" /* * ========================================================== * * ELEMENTS COMMUNICATED ACROSS THE NET * * ========================================================== */ #define ANGLE2SHORT(x) ((int)((x) * 65536 / 360) & 65535) #define SHORT2ANGLE(x) ((x) * (360.0 / 65536)) /* config strings are a general means of communication from the server to all connected clients. Each config string can be at most MAX_QPATH characters. */ #define CS_NAME 0 #define CS_CDTRACK 1 #define CS_SKY 2 #define CS_SKYAXIS 3 /* %f %f %f format */ #define CS_SKYROTATE 4 #define CS_STATUSBAR 5 /* display program string */ #define CS_AIRACCEL 29 /* air acceleration control */ #define CS_MAXCLIENTS 30 #define CS_MAPCHECKSUM 31 /* for catching cheater maps */ #define CS_MODELS 32 #define CS_SOUNDS (CS_MODELS + MAX_MODELS) #define CS_IMAGES (CS_SOUNDS + MAX_SOUNDS) #define CS_LIGHTS (CS_IMAGES + MAX_IMAGES) #define CS_ITEMS (CS_LIGHTS + MAX_LIGHTSTYLES) #define CS_PLAYERSKINS (CS_ITEMS + MAX_ITEMS) #define CS_GENERAL (CS_PLAYERSKINS + MAX_CLIENTS) #define MAX_CONFIGSTRINGS (CS_GENERAL + MAX_GENERAL) /* ============================================== */ /* entity_state_t->event values entity events are for effects that take place reletive to an existing entities origin. Very network efficient. All muzzle flashes really should be converted to events... */ typedef enum { EV_NONE, EV_ITEM_RESPAWN, EV_FOOTSTEP, EV_FALLSHORT, EV_FALL, EV_FALLFAR, EV_PLAYER_TELEPORT, EV_OTHER_TELEPORT } entity_event_t; /* entity_state_t is the information conveyed from the server in an update message about entities that the client will need to render in some way */ typedef struct entity_state_s { int number; /* edict index */ vec3_t origin; vec3_t angles; vec3_t old_origin; /* for lerping */ int modelindex; int modelindex2, modelindex3, modelindex4; /* weapons, CTF flags, etc */ int frame; int skinnum; unsigned int effects; int renderfx; int solid; /* for client side prediction, 8*(bits 0-4) is x/y radius */ /* 8*(bits 5-9) is z down distance, 8(bits10-15) is z up */ /* gi.linkentity sets this properly */ int sound; /* for looping sounds, to guarantee shutoff */ int event; /* impulse events -- muzzle flashes, footsteps, etc */ /* events only go out for a single frame, they */ /* are automatically cleared each frame */ } entity_state_t; /* ============================================== */ /* player_state_t is the information needed in addition to pmove_state_t to rendered a view. There will only be 10 player_state_t sent each second, but the number of pmove_state_t changes will be reletive to client frame rates */ typedef struct { pmove_state_t pmove; /* for prediction */ vec3_t viewangles; /* for fixed views */ vec3_t viewoffset; /* add to pmovestate->origin */ vec3_t kick_angles; /* add to view direction to get render angles */ /* set by weapon kicks, pain effects, etc */ vec3_t gunangles; vec3_t gunoffset; int gunindex; int gunframe; float blend[4]; /* rgba full screen effect */ float fov; /* horizontal field of view */ int rdflags; /* refdef flags */ short stats[MAX_STATS]; /* fast status bar updates */ } player_state_t; #define VIDREF_GL 1 #define VIDREF_SOFT 2 #define VIDREF_OTHER 3 extern int vidref_val; size_t verify_fread(void *, size_t, size_t, FILE *); size_t verify_fwrite(void *, size_t, size_t, FILE *); #endif /* ROGUE_SHARED_H */ rogue-ROGUE_2_13/src/monster/000077500000000000000000000000001477320066100160665ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/berserker/000077500000000000000000000000001477320066100200525ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/berserker/berserker.c000066400000000000000000000333361477320066100222120ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * The berserker. * * ======================================================================= */ #include "../../header/local.h" #include "berserker.h" static int sound_pain; static int sound_die; static int sound_idle; static int sound_punch; static int sound_sight; static int sound_search; static int sound_step; static int sound_step2; void berserk_fidget(edict_t *self); void berserk_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("berserk/step1.wav"); sound_step2 = gi.soundindex("berserk/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void berserk_sight(edict_t *self, edict_t *other) { if (!self || !other) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void berserk_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); } static mframe_t berserk_frames_stand[] = { {ai_stand, 0, berserk_fidget}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t berserk_move_stand = { FRAME_stand1, FRAME_stand5, berserk_frames_stand, NULL }; void berserk_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &berserk_move_stand; } static mframe_t berserk_frames_stand_fidget[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t berserk_move_stand_fidget = { FRAME_standb1, FRAME_standb20, berserk_frames_stand_fidget, berserk_stand }; void berserk_fidget(edict_t *self) { if (!self) { return; } if (self->enemy) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { return; } if (random() > 0.15) { return; } self->monsterinfo.currentmove = &berserk_move_stand_fidget; gi.sound(self, CHAN_WEAPON, sound_idle, 1, ATTN_IDLE, 0); } static mframe_t berserk_frames_walk[] = { {ai_walk, 9.1, NULL}, {ai_walk, 6.3, NULL}, {ai_walk, 4.9, NULL}, {ai_walk, 6.7, berserk_footstep}, {ai_walk, 6.0, NULL}, {ai_walk, 8.2, NULL}, {ai_walk, 7.2, NULL}, {ai_walk, 6.1, NULL}, {ai_walk, 4.9, berserk_footstep}, {ai_walk, 4.7, NULL}, {ai_walk, 4.7, NULL}, {ai_walk, 4.8, NULL} }; mmove_t berserk_move_walk = { FRAME_walkc1, FRAME_walkc11, berserk_frames_walk, NULL }; void berserk_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &berserk_move_walk; } static mframe_t berserk_frames_run1[] = { {ai_run, 21, NULL}, {ai_run, 11, berserk_footstep}, {ai_run, 21, NULL}, {ai_run, 25, monster_done_dodge}, {ai_run, 18, berserk_footstep}, {ai_run, 19, NULL} }; mmove_t berserk_move_run1 = { FRAME_run1, FRAME_run6, berserk_frames_run1, NULL }; void berserk_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &berserk_move_stand; } else { self->monsterinfo.currentmove = &berserk_move_run1; } } void berserk_attack_spike(edict_t *self) { if (!self) { return; } static vec3_t aim = {MELEE_DISTANCE, 0, -24}; fire_hit(self, aim, (15 + (rand() % 6)), 400); } void berserk_swing(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_punch, 1, ATTN_NORM, 0); } static mframe_t berserk_frames_attack_spike[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, berserk_swing}, {ai_charge, 0, berserk_attack_spike}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t berserk_move_attack_spike = { FRAME_att_c1, FRAME_att_c8, berserk_frames_attack_spike, berserk_run }; void berserk_attack_club(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], -4); fire_hit(self, aim, (5 + (rand() % 6)), 400); } static mframe_t berserk_frames_attack_club[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, berserk_footstep}, {ai_charge, 0, NULL}, {ai_charge, 0, berserk_swing}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, berserk_attack_club}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t berserk_move_attack_club = { FRAME_att_c9, FRAME_att_c20, berserk_frames_attack_club, berserk_run }; void berserk_strike(edict_t *self) { } static mframe_t berserk_frames_attack_strike[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, berserk_footstep}, {ai_move, 0, berserk_swing}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, berserk_strike}, {ai_move, 0, berserk_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 9.7, NULL}, {ai_move, 13.6, berserk_footstep} }; mmove_t berserk_move_attack_strike = { FRAME_att_c21, FRAME_att_c34, berserk_frames_attack_strike, berserk_run }; void berserk_melee(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if ((rand() % 2) == 0) { self->monsterinfo.currentmove = &berserk_move_attack_spike; } else { self->monsterinfo.currentmove = &berserk_move_attack_club; } } static mframe_t berserk_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_pain1 = { FRAME_painc1, FRAME_painc4, berserk_frames_pain1, berserk_run }; static mframe_t berserk_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_pain2 = { FRAME_painb1, FRAME_painb20, berserk_frames_pain2, berserk_run }; void berserk_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; gi.sound(self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } monster_done_dodge(self); if ((damage < 20) || (random() < 0.5)) { self->monsterinfo.currentmove = &berserk_move_pain1; } else { self->monsterinfo.currentmove = &berserk_move_pain2; } } void berserk_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t berserk_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_death1 = { FRAME_death1, FRAME_death13, berserk_frames_death1, berserk_dead }; static mframe_t berserk_frames_death2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_death2 = { FRAME_deathc1, FRAME_deathc8, berserk_frames_death2, berserk_dead }; void berserk_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; if (damage >= 50) { self->monsterinfo.currentmove = &berserk_move_death1; } else { self->monsterinfo.currentmove = &berserk_move_death2; } } void berserk_jump_now(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void berserk_jump2_now(edict_t *self) { vec3_t forward,up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 150, forward, self->velocity); VectorMA(self->velocity, 400, up, self->velocity); } void berserk_jump_wait_land(edict_t *self) { if (!self) { return; } if (self->groundentity == NULL) { self->monsterinfo.nextframe = self->s.frame; if (monster_jump_finished(self)) { self->monsterinfo.nextframe = self->s.frame + 1; } } else { self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t berserk_frames_jump[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, berserk_jump_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, berserk_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_jump = { FRAME_jump1, FRAME_jump9, berserk_frames_jump, berserk_run }; static mframe_t berserk_frames_jump2[] = { {ai_move, -8, NULL}, {ai_move, -4, NULL}, {ai_move, -4, NULL}, {ai_move, 0, berserk_jump2_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, berserk_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t berserk_move_jump2 = { FRAME_jump1, FRAME_jump9, berserk_frames_jump2, berserk_run }; void berserk_jump(edict_t *self) { if (!self || !self->enemy) { return; } monster_done_dodge(self); if (self->enemy->absmin[2] > self->absmin[2]) { self->monsterinfo.currentmove = &berserk_move_jump2; } else { self->monsterinfo.currentmove = &berserk_move_jump; } } qboolean berserk_blocked(edict_t *self, float dist) { if (blocked_checkjump(self, dist, 256, 40)) { berserk_jump(self); return true; } if (blocked_checkplat(self, dist)) { return true; } return false; } void berserk_sidestep(edict_t *self) { if (!self) { return; } if ((self->monsterinfo.currentmove == &berserk_move_jump) || (self->monsterinfo.currentmove == &berserk_move_jump2)) { return; } if (self->monsterinfo.currentmove != &berserk_move_run1) { self->monsterinfo.currentmove = &berserk_move_run1; } } /* * QUAKED monster_berserk (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_berserk(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; /* pre-caches */ sound_pain = gi.soundindex("berserk/berpain2.wav"); sound_die = gi.soundindex("berserk/berdeth2.wav"); sound_idle = gi.soundindex("berserk/beridle1.wav"); sound_punch = gi.soundindex("berserk/attack.wav"); sound_search = gi.soundindex("berserk/bersrch1.wav"); sound_sight = gi.soundindex("berserk/sight.wav"); self->s.modelindex = gi.modelindex("models/monsters/berserk/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->health = 240; self->gib_health = -60; self->mass = 250; self->pain = berserk_pain; self->die = berserk_die; self->monsterinfo.stand = berserk_stand; self->monsterinfo.walk = berserk_walk; self->monsterinfo.run = berserk_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.sidestep = berserk_sidestep; self->monsterinfo.attack = NULL; self->monsterinfo.melee = berserk_melee; self->monsterinfo.sight = berserk_sight; self->monsterinfo.search = berserk_search; self->monsterinfo.blocked = berserk_blocked; self->monsterinfo.currentmove = &berserk_move_stand; self->monsterinfo.scale = MODEL_SCALE; gi.linkentity(self); walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/berserker/berserker.h000066400000000000000000000212741477320066100222150ustar00rootroot00000000000000/* ======================================================================= * * Berserker animations. * * ======================================================================= */ #define FRAME_stand1 0 #define FRAME_stand2 1 #define FRAME_stand3 2 #define FRAME_stand4 3 #define FRAME_stand5 4 #define FRAME_standb1 5 #define FRAME_standb2 6 #define FRAME_standb3 7 #define FRAME_standb4 8 #define FRAME_standb5 9 #define FRAME_standb6 10 #define FRAME_standb7 11 #define FRAME_standb8 12 #define FRAME_standb9 13 #define FRAME_standb10 14 #define FRAME_standb11 15 #define FRAME_standb12 16 #define FRAME_standb13 17 #define FRAME_standb14 18 #define FRAME_standb15 19 #define FRAME_standb16 20 #define FRAME_standb17 21 #define FRAME_standb18 22 #define FRAME_standb19 23 #define FRAME_standb20 24 #define FRAME_walkc1 25 #define FRAME_walkc2 26 #define FRAME_walkc3 27 #define FRAME_walkc4 28 #define FRAME_walkc5 29 #define FRAME_walkc6 30 #define FRAME_walkc7 31 #define FRAME_walkc8 32 #define FRAME_walkc9 33 #define FRAME_walkc10 34 #define FRAME_walkc11 35 #define FRAME_run1 36 #define FRAME_run2 37 #define FRAME_run3 38 #define FRAME_run4 39 #define FRAME_run5 40 #define FRAME_run6 41 #define FRAME_att_a1 42 #define FRAME_att_a2 43 #define FRAME_att_a3 44 #define FRAME_att_a4 45 #define FRAME_att_a5 46 #define FRAME_att_a6 47 #define FRAME_att_a7 48 #define FRAME_att_a8 49 #define FRAME_att_a9 50 #define FRAME_att_a10 51 #define FRAME_att_a11 52 #define FRAME_att_a12 53 #define FRAME_att_a13 54 #define FRAME_att_b1 55 #define FRAME_att_b2 56 #define FRAME_att_b3 57 #define FRAME_att_b4 58 #define FRAME_att_b5 59 #define FRAME_att_b6 60 #define FRAME_att_b7 61 #define FRAME_att_b8 62 #define FRAME_att_b9 63 #define FRAME_att_b10 64 #define FRAME_att_b11 65 #define FRAME_att_b12 66 #define FRAME_att_b13 67 #define FRAME_att_b14 68 #define FRAME_att_b15 69 #define FRAME_att_b16 70 #define FRAME_att_b17 71 #define FRAME_att_b18 72 #define FRAME_att_b19 73 #define FRAME_att_b20 74 #define FRAME_att_b21 75 #define FRAME_att_c1 76 #define FRAME_att_c2 77 #define FRAME_att_c3 78 #define FRAME_att_c4 79 #define FRAME_att_c5 80 #define FRAME_att_c6 81 #define FRAME_att_c7 82 #define FRAME_att_c8 83 #define FRAME_att_c9 84 #define FRAME_att_c10 85 #define FRAME_att_c11 86 #define FRAME_att_c12 87 #define FRAME_att_c13 88 #define FRAME_att_c14 89 #define FRAME_att_c15 90 #define FRAME_att_c16 91 #define FRAME_att_c17 92 #define FRAME_att_c18 93 #define FRAME_att_c19 94 #define FRAME_att_c20 95 #define FRAME_att_c21 96 #define FRAME_att_c22 97 #define FRAME_att_c23 98 #define FRAME_att_c24 99 #define FRAME_att_c25 100 #define FRAME_att_c26 101 #define FRAME_att_c27 102 #define FRAME_att_c28 103 #define FRAME_att_c29 104 #define FRAME_att_c30 105 #define FRAME_att_c31 106 #define FRAME_att_c32 107 #define FRAME_att_c33 108 #define FRAME_att_c34 109 #define FRAME_r_att1 110 #define FRAME_r_att2 111 #define FRAME_r_att3 112 #define FRAME_r_att4 113 #define FRAME_r_att5 114 #define FRAME_r_att6 115 #define FRAME_r_att7 116 #define FRAME_r_att8 117 #define FRAME_r_att9 118 #define FRAME_r_att10 119 #define FRAME_r_att11 120 #define FRAME_r_att12 121 #define FRAME_r_att13 122 #define FRAME_r_att14 123 #define FRAME_r_att15 124 #define FRAME_r_att16 125 #define FRAME_r_att17 126 #define FRAME_r_att18 127 #define FRAME_r_attb1 128 #define FRAME_r_attb2 129 #define FRAME_r_attb3 130 #define FRAME_r_attb4 131 #define FRAME_r_attb5 132 #define FRAME_r_attb6 133 #define FRAME_r_attb7 134 #define FRAME_r_attb8 135 #define FRAME_r_attb9 136 #define FRAME_r_attb10 137 #define FRAME_r_attb11 138 #define FRAME_r_attb12 139 #define FRAME_r_attb13 140 #define FRAME_r_attb14 141 #define FRAME_r_attb15 142 #define FRAME_r_attb16 143 #define FRAME_r_attb17 144 #define FRAME_r_attb18 145 #define FRAME_slam1 146 #define FRAME_slam2 147 #define FRAME_slam3 148 #define FRAME_slam4 149 #define FRAME_slam5 150 #define FRAME_slam6 151 #define FRAME_slam7 152 #define FRAME_slam8 153 #define FRAME_slam9 154 #define FRAME_slam10 155 #define FRAME_slam11 156 #define FRAME_slam12 157 #define FRAME_slam13 158 #define FRAME_slam14 159 #define FRAME_slam15 160 #define FRAME_slam16 161 #define FRAME_slam17 162 #define FRAME_slam18 163 #define FRAME_slam19 164 #define FRAME_slam20 165 #define FRAME_slam21 166 #define FRAME_slam22 167 #define FRAME_slam23 168 #define FRAME_duck1 169 #define FRAME_duck2 170 #define FRAME_duck3 171 #define FRAME_duck4 172 #define FRAME_duck5 173 #define FRAME_duck6 174 #define FRAME_duck7 175 #define FRAME_duck8 176 #define FRAME_duck9 177 #define FRAME_duck10 178 #define FRAME_fall1 179 #define FRAME_fall2 180 #define FRAME_fall3 181 #define FRAME_fall4 182 #define FRAME_fall5 183 #define FRAME_fall6 184 #define FRAME_fall7 185 #define FRAME_fall8 186 #define FRAME_fall9 187 #define FRAME_fall10 188 #define FRAME_fall11 189 #define FRAME_fall12 190 #define FRAME_fall13 191 #define FRAME_fall14 192 #define FRAME_fall15 193 #define FRAME_fall16 194 #define FRAME_fall17 195 #define FRAME_fall18 196 #define FRAME_fall19 197 #define FRAME_fall20 198 #define FRAME_painc1 199 #define FRAME_painc2 200 #define FRAME_painc3 201 #define FRAME_painc4 202 #define FRAME_painb1 203 #define FRAME_painb2 204 #define FRAME_painb3 205 #define FRAME_painb4 206 #define FRAME_painb5 207 #define FRAME_painb6 208 #define FRAME_painb7 209 #define FRAME_painb8 210 #define FRAME_painb9 211 #define FRAME_painb10 212 #define FRAME_painb11 213 #define FRAME_painb12 214 #define FRAME_painb13 215 #define FRAME_painb14 216 #define FRAME_painb15 217 #define FRAME_painb16 218 #define FRAME_painb17 219 #define FRAME_painb18 220 #define FRAME_painb19 221 #define FRAME_painb20 222 #define FRAME_death1 223 #define FRAME_death2 224 #define FRAME_death3 225 #define FRAME_death4 226 #define FRAME_death5 227 #define FRAME_death6 228 #define FRAME_death7 229 #define FRAME_death8 230 #define FRAME_death9 231 #define FRAME_death10 232 #define FRAME_death11 233 #define FRAME_death12 234 #define FRAME_death13 235 #define FRAME_deathc1 236 #define FRAME_deathc2 237 #define FRAME_deathc3 238 #define FRAME_deathc4 239 #define FRAME_deathc5 240 #define FRAME_deathc6 241 #define FRAME_deathc7 242 #define FRAME_deathc8 243 #define FRAME_jump1 244 #define FRAME_jump2 245 #define FRAME_jump3 246 #define FRAME_jump4 247 #define FRAME_jump5 248 #define FRAME_jump6 249 #define FRAME_jump7 250 #define FRAME_jump8 251 #define FRAME_jump9 252 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/boss2/000077500000000000000000000000001477320066100171165ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/boss2/boss2.c000066400000000000000000000433371477320066100203240ustar00rootroot00000000000000/* ======================================================================= * * Boss 2 aka Hornet. * * ======================================================================= */ #include "../../header/local.h" #include "boss2.h" #define BOSS2_ROCKET_SPEED 750 qboolean infront(edict_t *self, edict_t *other); void BossExplode(edict_t *self); void boss2_run(edict_t *self); void boss2_stand(edict_t *self); void boss2_dead(edict_t *self); void boss2_attack(edict_t *self); void boss2_attack_mg(edict_t *self); void boss2_reattack_mg(edict_t *self); void boss2_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_death; static int sound_search1; void boss2_search(edict_t *self) { if (!self) { return; } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0); } } void Boss2PredictiveRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; float time, dist; if (!self || !self->enemy || !self->enemy->inuse) { return; } AngleVectors(self->s.angles, forward, right, NULL); //1 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); VectorSubtract(self->enemy->s.origin, start, dir); dist = VectorLength(dir); time = dist / BOSS2_ROCKET_SPEED; VectorMA(self->enemy->s.origin, time-0.3, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_1); //2 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); VectorSubtract(self->enemy->s.origin, start, dir); dist = VectorLength(dir); time = dist / BOSS2_ROCKET_SPEED; VectorMA(self->enemy->s.origin, time-0.15, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_2); //3 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); VectorSubtract(self->enemy->s.origin, start, dir); dist = VectorLength(dir); time = dist / BOSS2_ROCKET_SPEED; VectorMA(self->enemy->s.origin, time, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_3); //4 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); VectorSubtract(self->enemy->s.origin, start, dir); dist = VectorLength(dir); time = dist / BOSS2_ROCKET_SPEED; VectorMA(self->enemy->s.origin, time+0.15, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_4); } void Boss2Rocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; if (!self || !self->enemy || !self->enemy->inuse) { return; } if (self->enemy->client && random() < 0.9) { Boss2PredictiveRocket(self); return; } AngleVectors (self->s.angles, forward, right, NULL); //1 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] -= 15; VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, 0.4, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1); //2 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); VectorCopy(self->enemy->s.origin, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, 0.025, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2); //3 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); VectorCopy(self->enemy->s.origin, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, -0.025, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3); //4 G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] -= 15; VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, -0.4, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4); } void boss2_firebullet_right(edict_t *self) { vec3_t forward, right, target; vec3_t start; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start); VectorMA(self->enemy->s.origin, 0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1); } void boss2_firebullet_left(edict_t *self) { vec3_t forward, right, target; vec3_t start; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start); VectorMA(self->enemy->s.origin, 0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1); } void Boss2MachineGun(edict_t *self) { if (!self) { return; } boss2_firebullet_left(self); boss2_firebullet_right(self); } static mframe_t boss2_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t boss2_move_stand = { FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL }; static mframe_t boss2_frames_fidget[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t boss2_move_fidget = { FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL }; static mframe_t boss2_frames_walk[] = { {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL}, {ai_walk, 10, NULL} }; mmove_t boss2_move_walk = { FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL }; static mframe_t boss2_frames_run[] = { {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL} }; mmove_t boss2_move_run = { FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL }; static mframe_t boss2_frames_attack_pre_mg[] = { {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, boss2_attack_mg} }; mmove_t boss2_move_attack_pre_mg = { FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL }; /* Loop this */ static mframe_t boss2_frames_attack_mg[] = { {ai_charge, 2, Boss2MachineGun}, {ai_charge, 2, Boss2MachineGun}, {ai_charge, 2, Boss2MachineGun}, {ai_charge, 2, Boss2MachineGun}, {ai_charge, 2, Boss2MachineGun}, {ai_charge, 2, boss2_reattack_mg} }; mmove_t boss2_move_attack_mg = { FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL }; static mframe_t boss2_frames_attack_post_mg[] = { {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL} }; mmove_t boss2_move_attack_post_mg = { FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run }; static mframe_t boss2_frames_attack_rocket[] = { {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_move, -5, Boss2Rocket}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL} }; mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run }; static mframe_t boss2_frames_pain_heavy[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t boss2_move_pain_heavy = { FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run }; static mframe_t boss2_frames_pain_light[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t boss2_move_pain_light = { FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run }; static mframe_t boss2_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, BossExplode} }; mmove_t boss2_move_death = { FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead }; void boss2_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &boss2_move_stand; } void boss2_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &boss2_move_stand; } else { self->monsterinfo.currentmove = &boss2_move_run; } } void boss2_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &boss2_move_walk; } void boss2_attack(edict_t *self) { vec3_t vec; float range; if (!self) { return; } VectorSubtract(self->enemy->s.origin, self->s.origin, vec); range = VectorLength(vec); if (range <= 125) { self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; } else { if (random() <= 0.6) { self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; } else { self->monsterinfo.currentmove = &boss2_move_attack_rocket; } } } void boss2_attack_mg(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &boss2_move_attack_mg; } void boss2_reattack_mg(edict_t *self) { if (!self) { return; } if (infront(self, self->enemy)) { if (random() <= 0.7) { self->monsterinfo.currentmove = &boss2_move_attack_mg; } else { self->monsterinfo.currentmove = &boss2_move_attack_post_mg; } } else { self->monsterinfo.currentmove = &boss2_move_attack_post_mg; } } void boss2_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (damage < 10) { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &boss2_move_pain_light; } else if (damage < 30) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &boss2_move_pain_light; } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &boss2_move_pain_heavy; } } void boss2_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -56, -56, 0); VectorSet(self->maxs, 56, 56, 80); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void boss2_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; self->monsterinfo.currentmove = &boss2_move_death; } qboolean Boss2_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance; trace_t tr; int enemy_range; float enemy_yaw; if (!self) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* we want them to go ahead and shoot at info_notnulls if they can */ if (self->enemy->solid != SOLID_NOT || tr.fraction < 1.0) { return false; } } } enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw(temp); self->ideal_yaw = enemy_yaw; /* melee attack */ if (enemy_range == RANGE_MELEE) { if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } /* missile attack */ if (!self->monsterinfo.attack) { return false; } if (level.time < self->monsterinfo.attack_finished) { return false; } if (enemy_range == RANGE_FAR) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.8; } else if (enemy_range == RANGE_MID) { chance = 0.8; } else { return false; } if ((random() < chance) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; self->monsterinfo.attack_finished = level.time + 2 * random(); return true; } if (self->flags & FL_FLY) { if (random() < 0.3) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } return false; } /* * QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight */ void SP_monster_boss2(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("bosshovr/bhvpain1.wav"); sound_pain2 = gi.soundindex("bosshovr/bhvpain2.wav"); sound_pain3 = gi.soundindex("bosshovr/bhvpain3.wav"); sound_death = gi.soundindex("bosshovr/bhvdeth1.wav"); sound_search1 = gi.soundindex("bosshovr/bhvunqv1.wav"); self->s.sound = gi.soundindex("bosshovr/bhvengn1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/boss2/tris.md2"); VectorSet(self->mins, -56, -56, 0); VectorSet(self->maxs, 56, 56, 80); self->health = 2000; self->gib_health = -200; self->mass = 1000; self->flags |= FL_IMMUNE_LASER; self->pain = boss2_pain; self->die = boss2_die; self->monsterinfo.stand = boss2_stand; self->monsterinfo.walk = boss2_walk; self->monsterinfo.run = boss2_run; self->monsterinfo.attack = boss2_attack; self->monsterinfo.search = boss2_search; self->monsterinfo.checkattack = Boss2_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &boss2_move_stand; self->monsterinfo.scale = MODEL_SCALE; flymonster_start(self); } rogue-ROGUE_2_13/src/monster/boss2/boss2.h000066400000000000000000000144541477320066100203270ustar00rootroot00000000000000/* ======================================================================= * * Animations for boss2. * * ======================================================================= */ #define FRAME_stand30 0 #define FRAME_stand31 1 #define FRAME_stand32 2 #define FRAME_stand33 3 #define FRAME_stand34 4 #define FRAME_stand35 5 #define FRAME_stand36 6 #define FRAME_stand37 7 #define FRAME_stand38 8 #define FRAME_stand39 9 #define FRAME_stand40 10 #define FRAME_stand41 11 #define FRAME_stand42 12 #define FRAME_stand43 13 #define FRAME_stand44 14 #define FRAME_stand45 15 #define FRAME_stand46 16 #define FRAME_stand47 17 #define FRAME_stand48 18 #define FRAME_stand49 19 #define FRAME_stand50 20 #define FRAME_stand1 21 #define FRAME_stand2 22 #define FRAME_stand3 23 #define FRAME_stand4 24 #define FRAME_stand5 25 #define FRAME_stand6 26 #define FRAME_stand7 27 #define FRAME_stand8 28 #define FRAME_stand9 29 #define FRAME_stand10 30 #define FRAME_stand11 31 #define FRAME_stand12 32 #define FRAME_stand13 33 #define FRAME_stand14 34 #define FRAME_stand15 35 #define FRAME_stand16 36 #define FRAME_stand17 37 #define FRAME_stand18 38 #define FRAME_stand19 39 #define FRAME_stand20 40 #define FRAME_stand21 41 #define FRAME_stand22 42 #define FRAME_stand23 43 #define FRAME_stand24 44 #define FRAME_stand25 45 #define FRAME_stand26 46 #define FRAME_stand27 47 #define FRAME_stand28 48 #define FRAME_stand29 49 #define FRAME_walk1 50 #define FRAME_walk2 51 #define FRAME_walk3 52 #define FRAME_walk4 53 #define FRAME_walk5 54 #define FRAME_walk6 55 #define FRAME_walk7 56 #define FRAME_walk8 57 #define FRAME_walk9 58 #define FRAME_walk10 59 #define FRAME_walk11 60 #define FRAME_walk12 61 #define FRAME_walk13 62 #define FRAME_walk14 63 #define FRAME_walk15 64 #define FRAME_walk16 65 #define FRAME_walk17 66 #define FRAME_walk18 67 #define FRAME_walk19 68 #define FRAME_walk20 69 #define FRAME_attack1 70 #define FRAME_attack2 71 #define FRAME_attack3 72 #define FRAME_attack4 73 #define FRAME_attack5 74 #define FRAME_attack6 75 #define FRAME_attack7 76 #define FRAME_attack8 77 #define FRAME_attack9 78 #define FRAME_attack10 79 #define FRAME_attack11 80 #define FRAME_attack12 81 #define FRAME_attack13 82 #define FRAME_attack14 83 #define FRAME_attack15 84 #define FRAME_attack16 85 #define FRAME_attack17 86 #define FRAME_attack18 87 #define FRAME_attack19 88 #define FRAME_attack20 89 #define FRAME_attack21 90 #define FRAME_attack22 91 #define FRAME_attack23 92 #define FRAME_attack24 93 #define FRAME_attack25 94 #define FRAME_attack26 95 #define FRAME_attack27 96 #define FRAME_attack28 97 #define FRAME_attack29 98 #define FRAME_attack30 99 #define FRAME_attack31 100 #define FRAME_attack32 101 #define FRAME_attack33 102 #define FRAME_attack34 103 #define FRAME_attack35 104 #define FRAME_attack36 105 #define FRAME_attack37 106 #define FRAME_attack38 107 #define FRAME_attack39 108 #define FRAME_attack40 109 #define FRAME_pain2 110 #define FRAME_pain3 111 #define FRAME_pain4 112 #define FRAME_pain5 113 #define FRAME_pain6 114 #define FRAME_pain7 115 #define FRAME_pain8 116 #define FRAME_pain9 117 #define FRAME_pain10 118 #define FRAME_pain11 119 #define FRAME_pain12 120 #define FRAME_pain13 121 #define FRAME_pain14 122 #define FRAME_pain15 123 #define FRAME_pain16 124 #define FRAME_pain17 125 #define FRAME_pain18 126 #define FRAME_pain19 127 #define FRAME_pain20 128 #define FRAME_pain21 129 #define FRAME_pain22 130 #define FRAME_pain23 131 #define FRAME_death2 132 #define FRAME_death3 133 #define FRAME_death4 134 #define FRAME_death5 135 #define FRAME_death6 136 #define FRAME_death7 137 #define FRAME_death8 138 #define FRAME_death9 139 #define FRAME_death10 140 #define FRAME_death11 141 #define FRAME_death12 142 #define FRAME_death13 143 #define FRAME_death14 144 #define FRAME_death15 145 #define FRAME_death16 146 #define FRAME_death17 147 #define FRAME_death18 148 #define FRAME_death19 149 #define FRAME_death20 150 #define FRAME_death21 151 #define FRAME_death22 152 #define FRAME_death23 153 #define FRAME_death24 154 #define FRAME_death25 155 #define FRAME_death26 156 #define FRAME_death27 157 #define FRAME_death28 158 #define FRAME_death29 159 #define FRAME_death30 160 #define FRAME_death31 161 #define FRAME_death32 162 #define FRAME_death33 163 #define FRAME_death34 164 #define FRAME_death35 165 #define FRAME_death36 166 #define FRAME_death37 167 #define FRAME_death38 168 #define FRAME_death39 169 #define FRAME_death40 170 #define FRAME_death41 171 #define FRAME_death42 172 #define FRAME_death43 173 #define FRAME_death44 174 #define FRAME_death45 175 #define FRAME_death46 176 #define FRAME_death47 177 #define FRAME_death48 178 #define FRAME_death49 179 #define FRAME_death50 180 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/boss3/000077500000000000000000000000001477320066100171175ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/boss3/boss3.c000066400000000000000000000023701477320066100203160ustar00rootroot00000000000000#include "../../header/local.h" #include "boss32.h" void Use_Boss3(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { if (!ent) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BOSSTPORT); gi.WritePosition(ent->s.origin); gi.multicast(ent->s.origin, MULTICAST_PVS); G_FreeEdict(ent); } void Think_Boss3Stand(edict_t *ent) { if (!ent) { return; } if (ent->s.frame == FRAME_stand260) { ent->s.frame = FRAME_stand201; } else { ent->s.frame++; } ent->nextthink = level.time + FRAMETIME; } /* * QUAKED monster_boss3_stand (1 .5 0) (-32 -32 0) (32 32 90) * * Just stands and cycles in one place until targeted, then teleports away. */ void SP_monster_boss3_stand(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->model = "models/monsters/boss3/rider/tris.md2"; self->s.modelindex = gi.modelindex(self->model); self->s.frame = FRAME_stand201; gi.soundindex("misc/bigtele.wav"); VectorSet(self->mins, -32, -32, 0); VectorSet(self->maxs, 32, 32, 90); self->use = Use_Boss3; self->think = Think_Boss3Stand; self->nextthink = level.time + FRAMETIME; gi.linkentity(self); } rogue-ROGUE_2_13/src/monster/boss3/boss31.c000066400000000000000000000420501477320066100203760ustar00rootroot00000000000000/* ======================================================================= * * Final boss, stage 1 (jorg). * * ======================================================================= */ #include "../../header/local.h" #include "boss31.h" extern void SP_monster_makron(edict_t *self); qboolean visible(edict_t *self, edict_t *other); void BossExplode(edict_t *self); void MakronToss(edict_t *self); void jorg_dead(edict_t *self); void jorgBFG(edict_t *self); void jorgMachineGun(edict_t *self); void jorg_firebullet(edict_t *self); void jorg_reattack1(edict_t *self); void jorg_attack1(edict_t *self); void jorg_idle(edict_t *self); void jorg_step_left(edict_t *self); void jorg_step_right(edict_t *self); void jorg_death_hit(edict_t *self); static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_idle; static int sound_death; static int sound_search1; static int sound_search2; static int sound_search3; static int sound_attack1; static int sound_attack2; static int sound_firegun; static int sound_step_left; static int sound_step_right; static int sound_death_hit; void jorg_search(edict_t *self) { if (!self) { return; } float r; r = random(); if (r <= 0.3) { gi.sound(self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); } else if (r <= 0.6) { gi.sound(self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0); } } /* stand */ static mframe_t jorg_frames_stand[] = { {ai_stand, 0, jorg_idle}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 10 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 20 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 30 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 19, NULL}, {ai_stand, 11, jorg_step_left}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 6, NULL}, {ai_stand, 9, jorg_step_right}, {ai_stand, 0, NULL}, /* 40 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, -2, NULL}, {ai_stand, -17, jorg_step_left}, {ai_stand, 0, NULL}, {ai_stand, -12, NULL}, /* 50 */ {ai_stand, -14, jorg_step_right} }; mmove_t jorg_move_stand = { FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL }; void jorg_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_NORM, 0); } void jorg_death_hit(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM, 0); } void jorg_step_left(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_step_left, 1, ATTN_NORM, 0); } void jorg_step_right(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_step_right, 1, ATTN_NORM, 0); } void jorg_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &jorg_move_stand; } static mframe_t jorg_frames_run[] = { {ai_run, 17, jorg_step_left}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, 12, NULL}, {ai_run, 8, NULL}, {ai_run, 10, NULL}, {ai_run, 33, jorg_step_right}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, 9, NULL}, {ai_run, 9, NULL}, {ai_run, 9, NULL} }; mmove_t jorg_move_run = { FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL }; /* walk */ static mframe_t jorg_frames_start_walk[] = { {ai_walk, 5, NULL}, {ai_walk, 6, NULL}, {ai_walk, 7, NULL}, {ai_walk, 9, NULL}, {ai_walk, 15, NULL} }; mmove_t jorg_move_start_walk = { FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL }; static mframe_t jorg_frames_walk[] = { {ai_walk, 17, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 12, NULL}, {ai_walk, 8, NULL}, {ai_walk, 10, NULL}, {ai_walk, 33, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 9, NULL}, {ai_walk, 9, NULL}, {ai_walk, 9, NULL} }; mmove_t jorg_move_walk = { FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL }; static mframe_t jorg_frames_end_walk[] = { {ai_walk, 11, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 8, NULL}, {ai_walk, -8, NULL} }; mmove_t jorg_move_end_walk = { FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL }; void jorg_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &jorg_move_walk; } void jorg_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &jorg_move_stand; } else { self->monsterinfo.currentmove = &jorg_move_run; } } static mframe_t jorg_frames_pain3[] = { {ai_move, -28, NULL}, {ai_move, -6, NULL}, {ai_move, -3, jorg_step_left}, {ai_move, -9, NULL}, {ai_move, 0, jorg_step_right}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -7, NULL}, {ai_move, 1, NULL}, {ai_move, -11, NULL}, {ai_move, -4, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 10, NULL}, {ai_move, 11, NULL}, {ai_move, 0, NULL}, {ai_move, 10, NULL}, {ai_move, 3, NULL}, {ai_move, 10, NULL}, {ai_move, 7, jorg_step_left}, {ai_move, 17, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, jorg_step_right} }; mmove_t jorg_move_pain3 = { FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run }; static mframe_t jorg_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t jorg_move_pain2 = { FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run }; static mframe_t jorg_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t jorg_move_pain1 = { FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run }; static mframe_t jorg_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 10 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 20 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 30 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 40 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, MakronToss}, {ai_move, 0, BossExplode} /* 50 */ }; mmove_t jorg_move_death = { FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead }; static mframe_t jorg_frames_attack2[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, jorgBFG}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t jorg_move_attack2 = { FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run }; static mframe_t jorg_frames_start_attack1[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t jorg_move_start_attack1 = { FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1 }; static mframe_t jorg_frames_attack1[] = { {ai_charge, 0, jorg_firebullet}, {ai_charge, 0, jorg_firebullet}, {ai_charge, 0, jorg_firebullet}, {ai_charge, 0, jorg_firebullet}, {ai_charge, 0, jorg_firebullet}, {ai_charge, 0, jorg_firebullet} }; mmove_t jorg_move_attack1 = { FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1 }; static mframe_t jorg_frames_end_attack1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t jorg_move_end_attack1 = { FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run }; void jorg_reattack1(edict_t *self) { if (!self) { return; } if (visible(self, self->enemy)) { if (random() < 0.9) { self->monsterinfo.currentmove = &jorg_move_attack1; } else { self->s.sound = 0; self->monsterinfo.currentmove = &jorg_move_end_attack1; } } else { self->s.sound = 0; self->monsterinfo.currentmove = &jorg_move_end_attack1; } } void jorg_attack1(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &jorg_move_attack1; } void jorg_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } self->s.sound = 0; if (level.time < self->pain_debounce_time) { return; } /* Lessen the chance of him going into his pain frames if he takes little damage */ if (damage <= 40) { if (random() <= 0.6) { return; } } /* If he's entering his attack1 or using attack1, lessen the chance of him going into pain */ if ((self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108)) { if (random() <= 0.005) { return; } } if ((self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114)) { if (random() <= 0.00005) { return; } } if ((self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208)) { if (random() <= 0.005) { return; } } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (damage <= 50) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &jorg_move_pain1; } else if (damage <= 100) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &jorg_move_pain2; } else { if (random() <= 0.3) { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &jorg_move_pain3; } } } void jorgBFG(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, dir); VectorNormalize(dir); gi.sound(self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0); monster_fire_bfg(self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1); } void jorg_firebullet_right(edict_t *self) { vec3_t forward, right, target; vec3_t start; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start); VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1); } void jorg_firebullet_left(edict_t *self) { vec3_t forward, right, target; vec3_t start; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start); VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1); } void jorg_firebullet(edict_t *self) { if (!self) { return; } jorg_firebullet_left(self); jorg_firebullet_right(self); } void jorg_attack(edict_t *self) { if (!self) { return; } if (random() <= 0.75) { gi.sound(self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM, 0); self->s.sound = gi.soundindex("boss3/w_loop.wav"); self->monsterinfo.currentmove = &jorg_move_start_attack1; } else { gi.sound(self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &jorg_move_attack2; } } void jorg_dead(edict_t *self) { } void jorg_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->s.sound = 0; self->count = 0; self->monsterinfo.currentmove = &jorg_move_death; } qboolean Jorg_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance; trace_t tr; int enemy_range; float enemy_yaw; if (!self) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { return false; } } enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw(temp); self->ideal_yaw = enemy_yaw; /* melee attack */ if (enemy_range == RANGE_MELEE) { if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } /* missile attack */ if (!self->monsterinfo.attack) { return false; } if (level.time < self->monsterinfo.attack_finished) { return false; } if (enemy_range == RANGE_FAR) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.4; } else if (enemy_range == RANGE_MID) { chance = 0.2; } else { return false; } if (random() < chance) { self->monsterinfo.attack_state = AS_MISSILE; self->monsterinfo.attack_finished = level.time + 2 * random(); return true; } if (self->flags & FL_FLY) { if (random() < 0.3) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } return false; } void MakronPrecache(void); /* * QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight */ void SP_monster_jorg(edict_t *self) { if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("boss3/bs3pain1.wav"); sound_pain2 = gi.soundindex("boss3/bs3pain2.wav"); sound_pain3 = gi.soundindex("boss3/bs3pain3.wav"); sound_death = gi.soundindex("boss3/bs3deth1.wav"); sound_attack1 = gi.soundindex("boss3/bs3atck1.wav"); sound_attack2 = gi.soundindex("boss3/bs3atck2.wav"); sound_search1 = gi.soundindex("boss3/bs3srch1.wav"); sound_search2 = gi.soundindex("boss3/bs3srch2.wav"); sound_search3 = gi.soundindex("boss3/bs3srch3.wav"); sound_idle = gi.soundindex("boss3/bs3idle1.wav"); sound_step_left = gi.soundindex("boss3/step1.wav"); sound_step_right = gi.soundindex("boss3/step2.wav"); sound_firegun = gi.soundindex("boss3/xfire.wav"); sound_death_hit = gi.soundindex("boss3/d_hit.wav"); MakronPrecache(); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/boss3/jorg/tris.md2"); self->s.modelindex2 = gi.modelindex("models/monsters/boss3/rider/tris.md2"); VectorSet(self->mins, -80, -80, 0); VectorSet(self->maxs, 80, 80, 140); self->health = 3000; self->gib_health = -2000; self->mass = 1000; self->pain = jorg_pain; self->die = jorg_die; self->monsterinfo.stand = jorg_stand; self->monsterinfo.walk = jorg_walk; self->monsterinfo.run = jorg_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = jorg_attack; self->monsterinfo.search = jorg_search; self->monsterinfo.melee = NULL; self->monsterinfo.sight = NULL; self->monsterinfo.checkattack = Jorg_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &jorg_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/boss3/boss31.h000066400000000000000000000150561477320066100204110ustar00rootroot00000000000000/* ======================================================================= * * Animations for final boss stage 1. * * ======================================================================= */ #define FRAME_attak101 0 #define FRAME_attak102 1 #define FRAME_attak103 2 #define FRAME_attak104 3 #define FRAME_attak105 4 #define FRAME_attak106 5 #define FRAME_attak107 6 #define FRAME_attak108 7 #define FRAME_attak109 8 #define FRAME_attak110 9 #define FRAME_attak111 10 #define FRAME_attak112 11 #define FRAME_attak113 12 #define FRAME_attak114 13 #define FRAME_attak115 14 #define FRAME_attak116 15 #define FRAME_attak117 16 #define FRAME_attak118 17 #define FRAME_attak201 18 #define FRAME_attak202 19 #define FRAME_attak203 20 #define FRAME_attak204 21 #define FRAME_attak205 22 #define FRAME_attak206 23 #define FRAME_attak207 24 #define FRAME_attak208 25 #define FRAME_attak209 26 #define FRAME_attak210 27 #define FRAME_attak211 28 #define FRAME_attak212 29 #define FRAME_attak213 30 #define FRAME_death01 31 #define FRAME_death02 32 #define FRAME_death03 33 #define FRAME_death04 34 #define FRAME_death05 35 #define FRAME_death06 36 #define FRAME_death07 37 #define FRAME_death08 38 #define FRAME_death09 39 #define FRAME_death10 40 #define FRAME_death11 41 #define FRAME_death12 42 #define FRAME_death13 43 #define FRAME_death14 44 #define FRAME_death15 45 #define FRAME_death16 46 #define FRAME_death17 47 #define FRAME_death18 48 #define FRAME_death19 49 #define FRAME_death20 50 #define FRAME_death21 51 #define FRAME_death22 52 #define FRAME_death23 53 #define FRAME_death24 54 #define FRAME_death25 55 #define FRAME_death26 56 #define FRAME_death27 57 #define FRAME_death28 58 #define FRAME_death29 59 #define FRAME_death30 60 #define FRAME_death31 61 #define FRAME_death32 62 #define FRAME_death33 63 #define FRAME_death34 64 #define FRAME_death35 65 #define FRAME_death36 66 #define FRAME_death37 67 #define FRAME_death38 68 #define FRAME_death39 69 #define FRAME_death40 70 #define FRAME_death41 71 #define FRAME_death42 72 #define FRAME_death43 73 #define FRAME_death44 74 #define FRAME_death45 75 #define FRAME_death46 76 #define FRAME_death47 77 #define FRAME_death48 78 #define FRAME_death49 79 #define FRAME_death50 80 #define FRAME_pain101 81 #define FRAME_pain102 82 #define FRAME_pain103 83 #define FRAME_pain201 84 #define FRAME_pain202 85 #define FRAME_pain203 86 #define FRAME_pain301 87 #define FRAME_pain302 88 #define FRAME_pain303 89 #define FRAME_pain304 90 #define FRAME_pain305 91 #define FRAME_pain306 92 #define FRAME_pain307 93 #define FRAME_pain308 94 #define FRAME_pain309 95 #define FRAME_pain310 96 #define FRAME_pain311 97 #define FRAME_pain312 98 #define FRAME_pain313 99 #define FRAME_pain314 100 #define FRAME_pain315 101 #define FRAME_pain316 102 #define FRAME_pain317 103 #define FRAME_pain318 104 #define FRAME_pain319 105 #define FRAME_pain320 106 #define FRAME_pain321 107 #define FRAME_pain322 108 #define FRAME_pain323 109 #define FRAME_pain324 110 #define FRAME_pain325 111 #define FRAME_stand01 112 #define FRAME_stand02 113 #define FRAME_stand03 114 #define FRAME_stand04 115 #define FRAME_stand05 116 #define FRAME_stand06 117 #define FRAME_stand07 118 #define FRAME_stand08 119 #define FRAME_stand09 120 #define FRAME_stand10 121 #define FRAME_stand11 122 #define FRAME_stand12 123 #define FRAME_stand13 124 #define FRAME_stand14 125 #define FRAME_stand15 126 #define FRAME_stand16 127 #define FRAME_stand17 128 #define FRAME_stand18 129 #define FRAME_stand19 130 #define FRAME_stand20 131 #define FRAME_stand21 132 #define FRAME_stand22 133 #define FRAME_stand23 134 #define FRAME_stand24 135 #define FRAME_stand25 136 #define FRAME_stand26 137 #define FRAME_stand27 138 #define FRAME_stand28 139 #define FRAME_stand29 140 #define FRAME_stand30 141 #define FRAME_stand31 142 #define FRAME_stand32 143 #define FRAME_stand33 144 #define FRAME_stand34 145 #define FRAME_stand35 146 #define FRAME_stand36 147 #define FRAME_stand37 148 #define FRAME_stand38 149 #define FRAME_stand39 150 #define FRAME_stand40 151 #define FRAME_stand41 152 #define FRAME_stand42 153 #define FRAME_stand43 154 #define FRAME_stand44 155 #define FRAME_stand45 156 #define FRAME_stand46 157 #define FRAME_stand47 158 #define FRAME_stand48 159 #define FRAME_stand49 160 #define FRAME_stand50 161 #define FRAME_stand51 162 #define FRAME_walk01 163 #define FRAME_walk02 164 #define FRAME_walk03 165 #define FRAME_walk04 166 #define FRAME_walk05 167 #define FRAME_walk06 168 #define FRAME_walk07 169 #define FRAME_walk08 170 #define FRAME_walk09 171 #define FRAME_walk10 172 #define FRAME_walk11 173 #define FRAME_walk12 174 #define FRAME_walk13 175 #define FRAME_walk14 176 #define FRAME_walk15 177 #define FRAME_walk16 178 #define FRAME_walk17 179 #define FRAME_walk18 180 #define FRAME_walk19 181 #define FRAME_walk20 182 #define FRAME_walk21 183 #define FRAME_walk22 184 #define FRAME_walk23 185 #define FRAME_walk24 186 #define FRAME_walk25 187 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/boss3/boss32.c000066400000000000000000000600001477320066100203720ustar00rootroot00000000000000/* ======================================================================= * * Final boss, stage 2 (makron). * * ======================================================================= */ #include "../../header/local.h" #include "boss32.h" qboolean visible(edict_t *self, edict_t *other); void MakronRailgun(edict_t *self); void MakronSaveloc(edict_t *self); void MakronHyperblaster(edict_t *self); void makron_step_left(edict_t *self); void makron_step_right(edict_t *self); void makronBFG(edict_t *self); void makron_dead(edict_t *self); static int sound_pain4; static int sound_pain5; static int sound_pain6; static int sound_death; static int sound_step_left; static int sound_step_right; static int sound_attack_bfg; static int sound_brainsplorch; static int sound_prerailgun; static int sound_popup; static int sound_taunt1; static int sound_taunt2; static int sound_taunt3; static int sound_hit; void makron_taunt(edict_t *self) { float r; if (!self) { return; } r = random(); if (r <= 0.3) { gi.sound(self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0); } else if (r <= 0.6) { gi.sound(self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0); } else { gi.sound(self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0); } } /* stand */ static mframe_t makron_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 10 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 20 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 30 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 40 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 50 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} /* 60 */ }; mmove_t makron_move_stand = { FRAME_stand201, FRAME_stand260, makron_frames_stand, NULL }; void makron_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &makron_move_stand; } static mframe_t makron_frames_run[] = { {ai_run, 3, makron_step_left}, {ai_run, 12, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, makron_step_right}, {ai_run, 6, NULL}, {ai_run, 12, NULL}, {ai_run, 9, NULL}, {ai_run, 6, NULL}, {ai_run, 12, NULL} }; mmove_t makron_move_run = { FRAME_walk204, FRAME_walk213, makron_frames_run, NULL }; void makron_hit(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_AUTO, sound_hit, 1, ATTN_NONE, 0); } void makron_popup(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_popup, 1, ATTN_NONE, 0); } void makron_step_left(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_step_left, 1, ATTN_NORM, 0); } void makron_step_right(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_step_right, 1, ATTN_NORM, 0); } void makron_brainsplorch(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM, 0); } void makron_prerailgun(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM, 0); } mmove_t makron_move_walk = { FRAME_walk204, FRAME_walk213, makron_frames_run, NULL }; void makron_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &makron_move_walk; } void makron_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &makron_move_stand; } else { self->monsterinfo.currentmove = &makron_move_run; } } static mframe_t makron_frames_pain6[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 10 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, makron_popup}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 20 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, makron_taunt}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_pain6 = { FRAME_pain601, FRAME_pain627, makron_frames_pain6, makron_run }; static mframe_t makron_frames_pain5[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_pain5 = { FRAME_pain501, FRAME_pain504, makron_frames_pain5, makron_run }; static mframe_t makron_frames_pain4[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_pain4 = { FRAME_pain401, FRAME_pain404, makron_frames_pain4, makron_run }; static mframe_t makron_frames_death2[] = { {ai_move, -15, NULL}, {ai_move, 3, NULL}, {ai_move, -12, NULL}, {ai_move, 0, makron_step_left}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 10 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 11, NULL}, {ai_move, 12, NULL}, {ai_move, 11, makron_step_right}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 20 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 30 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 5, NULL}, {ai_move, 7, NULL}, {ai_move, 6, makron_step_left}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, 2, NULL}, /* 40 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 50 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -6, NULL}, {ai_move, -4, NULL}, {ai_move, -6, makron_step_right}, {ai_move, -4, NULL}, {ai_move, -4, makron_step_left}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 60 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, -5, NULL}, {ai_move, -3, makron_step_right}, {ai_move, -8, NULL}, {ai_move, -3, makron_step_left}, {ai_move, -7, NULL}, {ai_move, -4, NULL}, {ai_move, -4, makron_step_right}, /* 70 */ {ai_move, -6, NULL}, {ai_move, -7, NULL}, {ai_move, 0, makron_step_left}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 80 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, /* 90 */ {ai_move, 27, makron_hit}, {ai_move, 26, NULL}, {ai_move, 0, makron_brainsplorch}, {ai_move, 0, NULL}, {ai_move, 0, NULL} /* 95 */ }; mmove_t makron_move_death2 = { FRAME_death201, FRAME_death295, makron_frames_death2, makron_dead }; static mframe_t makron_frames_death3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_death3 = { FRAME_death301, FRAME_death320, makron_frames_death3, NULL }; static mframe_t makron_frames_sight[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_sight = { FRAME_active01, FRAME_active13, makron_frames_sight, makron_run }; void makronBFG(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, dir); VectorNormalize(dir); gi.sound(self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0); monster_fire_bfg(self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG); } static mframe_t makron_frames_attack3[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, makronBFG}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_attack3 = { FRAME_attak301, FRAME_attak308, makron_frames_attack3, makron_run }; static mframe_t makron_frames_attack4[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, MakronHyperblaster}, /* fire */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_attack4 = { FRAME_attak401, FRAME_attak426, makron_frames_attack4, makron_run }; static mframe_t makron_frames_attack5[] = { {ai_charge, 0, makron_prerailgun}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, MakronSaveloc}, {ai_move, 0, MakronRailgun}, /* Fire railgun */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t makron_move_attack5 = { FRAME_attak501, FRAME_attak516, makron_frames_attack5, makron_run }; void MakronSaveloc(edict_t *self) { if (!self) { return; } VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; } void MakronRailgun(edict_t *self) { vec3_t start; vec3_t dir; vec3_t forward, right; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start); /* calc direction to where we targted */ VectorSubtract(self->pos1, start, dir); VectorNormalize(dir); monster_fire_railgun(self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1); } void MakronHyperblaster(edict_t *self) { vec3_t dir; vec3_t vec; vec3_t start; vec3_t forward, right; int flash_number; if (!self) { return; } flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405); AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); if (self->enemy) { VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, vec); vectoangles(vec, vec); dir[0] = vec[0]; } else { dir[0] = 0; } if (self->s.frame <= FRAME_attak413) { dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413); } else { dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421); } dir[2] = 0; AngleVectors(dir, forward, NULL, NULL); monster_fire_blaster(self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER); } void makron_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } /* Lessen the chance of him going into his pain frames */ if (damage <= 25) { if (random() < 0.2) { return; } } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (damage <= 40) { gi.sound(self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &makron_move_pain4; } else if (damage <= 110) { gi.sound(self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &makron_move_pain5; } else { if (damage <= 150) { if (random() <= 0.45) { gi.sound(self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &makron_move_pain6; } } else { if (random() <= 0.35) { gi.sound(self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &makron_move_pain6; } } } } void makron_sight(edict_t *self, edict_t *other /* unused */) { } void makron_attack(edict_t *self) { float r; if (!self) { return; } r = random(); if (r <= 0.3) { self->monsterinfo.currentmove = &makron_move_attack3; } else if (r <= 0.6) { self->monsterinfo.currentmove = &makron_move_attack4; } else { self->monsterinfo.currentmove = &makron_move_attack5; } } void makron_torso_think(edict_t *self) { if (!self) { return; } /* detach from the makron if the legs are gone completely */ if (self->owner && (!self->owner->inuse || (self->owner->health <= self->owner->gib_health))) { self->owner = NULL; } /* if the makron is revived the torso was put back on him */ if (self->owner && self->owner->deadflag != DEAD_DEAD) { G_FreeEdict(self); return; } if (self->owner && (self->owner->monsterinfo.aiflags & AI_RESURRECTING)) { self->s.effects |= EF_COLOR_SHELL; self->s.renderfx |= RF_SHELL_RED; } else { self->s.effects &= ~EF_COLOR_SHELL; self->s.renderfx &= ~RF_SHELL_RED; } if (++self->s.frame >= FRAME_death320) { self->s.frame = FRAME_death301; } self->nextthink = level.time + FRAMETIME; } static void makron_torso_origin(edict_t *self, edict_t *torso) { vec3_t v; trace_t tr; AngleVectors(self->s.angles, v, NULL, NULL); VectorMA(self->s.origin, -84.0f, v, v); tr = gi.trace(self->s.origin, torso->mins, torso->maxs, v, self, MASK_SOLID); VectorCopy (tr.endpos, torso->s.origin); } void makron_torso_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { int n; if (self->health > self->gib_health) { return; } gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); } G_FreeEdict(self); } void makron_torso(edict_t *self) { edict_t *torso; if (!self) { return; } torso = G_SpawnOptional(); if (!torso) { return; } VectorCopy(self->s.angles, torso->s.angles); VectorSet(torso->mins, -24, -24, 0); VectorSet(torso->maxs, 24, 24, 16); makron_torso_origin(self, torso); torso->gib_health = -800; torso->takedamage = DAMAGE_YES; torso->die = makron_torso_die; torso->deadflag = DEAD_DEAD; torso->owner = self; torso->movetype = MOVETYPE_TOSS; torso->solid = SOLID_BBOX; torso->svflags = SVF_MONSTER|SVF_DEADMONSTER; torso->clipmask = MASK_MONSTERSOLID; torso->s.frame = FRAME_death301; torso->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2"); torso->think = makron_torso_think; torso->nextthink = level.time + 2 * FRAMETIME; torso->s.sound = gi.soundindex("makron/spine.wav"); gi.linkentity(torso); } /* death */ void makron_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -48, -48, 0); VectorSet(self->maxs, 48, 48, 24); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void makron_die(edict_t *self, edict_t *inflictor /* update */, edict_t *attacker /* update */, int damage, vec3_t point /* update */) { int n; if (!self) { return; } self->s.sound = 0; /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 1 /*4*/; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); } ThrowHead(self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; makron_torso(self); /* lower bbox since the torso is gone */ self->maxs[2] = 64; gi.linkentity (self); self->monsterinfo.currentmove = &makron_move_death2; } qboolean Makron_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance; trace_t tr; int enemy_range; float enemy_yaw; if (!self) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { return false; } } enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw(temp); self->ideal_yaw = enemy_yaw; /* melee attack */ if (enemy_range == RANGE_MELEE) { if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } /* missile attack */ if (!self->monsterinfo.attack) { return false; } if (level.time < self->monsterinfo.attack_finished) { return false; } if (enemy_range == RANGE_FAR) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.4; } else if (enemy_range == RANGE_MID) { chance = 0.2; } else { return false; } if (random() < chance) { self->monsterinfo.attack_state = AS_MISSILE; self->monsterinfo.attack_finished = level.time + 2 * random(); return true; } if (self->flags & FL_FLY) { if (random() < 0.3) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } return false; } void MakronPrecache(void) { sound_pain4 = gi.soundindex("makron/pain3.wav"); sound_pain5 = gi.soundindex("makron/pain2.wav"); sound_pain6 = gi.soundindex("makron/pain1.wav"); sound_death = gi.soundindex("makron/death.wav"); sound_step_left = gi.soundindex("makron/step1.wav"); sound_step_right = gi.soundindex("makron/step2.wav"); sound_attack_bfg = gi.soundindex("makron/bfg_fire.wav"); sound_brainsplorch = gi.soundindex("makron/brain1.wav"); sound_prerailgun = gi.soundindex("makron/rail_up.wav"); sound_popup = gi.soundindex("makron/popup.wav"); sound_taunt1 = gi.soundindex("makron/voice4.wav"); sound_taunt2 = gi.soundindex("makron/voice3.wav"); sound_taunt3 = gi.soundindex("makron/voice.wav"); sound_hit = gi.soundindex("makron/bhit.wav"); gi.modelindex("models/monsters/boss3/rider/tris.md2"); } /* * QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight */ void SP_monster_makron(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } MakronPrecache(); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2"); VectorSet(self->mins, -30, -30, 0); VectorSet(self->maxs, 30, 30, 90); self->health = 3000; self->gib_health = -2000; self->mass = 500; self->pain = makron_pain; self->die = makron_die; self->monsterinfo.stand = makron_stand; self->monsterinfo.walk = makron_walk; self->monsterinfo.run = makron_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = makron_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = makron_sight; self->monsterinfo.checkattack = Makron_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &makron_move_sight; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } void MakronSpawn(edict_t *self) { vec3_t vec; edict_t *enemy; edict_t *oldenemy; if (!self) { return; } /* spawning can mess with enemy state so clear it temporarily */ enemy = self->enemy; self->enemy = NULL; oldenemy = self->oldenemy; self->oldenemy = NULL; SP_monster_makron(self); if (self->think) { self->think(self); } /* and re-link enemy state now that he's spawned */ if (enemy && enemy->inuse && enemy->deadflag != DEAD_DEAD) { self->enemy = enemy; } if (oldenemy && oldenemy->inuse && oldenemy->deadflag != DEAD_DEAD) { self->oldenemy = oldenemy; } if (!self->enemy) { self->enemy = self->oldenemy; self->oldenemy = NULL; } enemy = self->enemy; if (enemy) { FoundTarget(self); VectorCopy(self->pos1, self->monsterinfo.last_sighting); } if (enemy && visible(self, enemy)) { VectorSubtract(enemy->s.origin, self->s.origin, vec); self->s.angles[YAW] = vectoyaw(vec); VectorNormalize(vec); } else AngleVectors(self->s.angles, vec, NULL, NULL); VectorScale(vec, 400, self->velocity); /* the jump frames are fixed length so best to normalize the up speed */ self->velocity[2] = 200.0f * (sv_gravity->value / 800.0f); self->groundentity = NULL; self->s.origin[2] += 1; gi.linkentity(self); self->pain_debounce_time = level.time + 1; self->monsterinfo.currentmove = &makron_move_sight; } /* * Jorg is just about dead, so set up to launch Makron out */ void MakronToss(edict_t *self) { edict_t *ent; if (!self) { return; } ent = G_Spawn(); ent->classname = "monster_makron"; ent->nextthink = level.time + 0.8; ent->think = MakronSpawn; ent->target = self->target; VectorCopy(self->s.origin, ent->s.origin); VectorCopy(self->s.angles, ent->s.angles); VectorCopy(self->monsterinfo.last_sighting, ent->pos1); ent->enemy = self->enemy; ent->oldenemy = self->oldenemy; } rogue-ROGUE_2_13/src/monster/boss3/boss32.h000066400000000000000000000416261477320066100204140ustar00rootroot00000000000000/* ======================================================================= * * Final boss, stage 2 (makron). * * ======================================================================= */ #define FRAME_attak101 0 #define FRAME_attak102 1 #define FRAME_attak103 2 #define FRAME_attak104 3 #define FRAME_attak105 4 #define FRAME_attak106 5 #define FRAME_attak107 6 #define FRAME_attak108 7 #define FRAME_attak109 8 #define FRAME_attak110 9 #define FRAME_attak111 10 #define FRAME_attak112 11 #define FRAME_attak113 12 #define FRAME_attak114 13 #define FRAME_attak115 14 #define FRAME_attak116 15 #define FRAME_attak117 16 #define FRAME_attak118 17 #define FRAME_attak201 18 #define FRAME_attak202 19 #define FRAME_attak203 20 #define FRAME_attak204 21 #define FRAME_attak205 22 #define FRAME_attak206 23 #define FRAME_attak207 24 #define FRAME_attak208 25 #define FRAME_attak209 26 #define FRAME_attak210 27 #define FRAME_attak211 28 #define FRAME_attak212 29 #define FRAME_attak213 30 #define FRAME_death01 31 #define FRAME_death02 32 #define FRAME_death03 33 #define FRAME_death04 34 #define FRAME_death05 35 #define FRAME_death06 36 #define FRAME_death07 37 #define FRAME_death08 38 #define FRAME_death09 39 #define FRAME_death10 40 #define FRAME_death11 41 #define FRAME_death12 42 #define FRAME_death13 43 #define FRAME_death14 44 #define FRAME_death15 45 #define FRAME_death16 46 #define FRAME_death17 47 #define FRAME_death18 48 #define FRAME_death19 49 #define FRAME_death20 50 #define FRAME_death21 51 #define FRAME_death22 52 #define FRAME_death23 53 #define FRAME_death24 54 #define FRAME_death25 55 #define FRAME_death26 56 #define FRAME_death27 57 #define FRAME_death28 58 #define FRAME_death29 59 #define FRAME_death30 60 #define FRAME_death31 61 #define FRAME_death32 62 #define FRAME_death33 63 #define FRAME_death34 64 #define FRAME_death35 65 #define FRAME_death36 66 #define FRAME_death37 67 #define FRAME_death38 68 #define FRAME_death39 69 #define FRAME_death40 70 #define FRAME_death41 71 #define FRAME_death42 72 #define FRAME_death43 73 #define FRAME_death44 74 #define FRAME_death45 75 #define FRAME_death46 76 #define FRAME_death47 77 #define FRAME_death48 78 #define FRAME_death49 79 #define FRAME_death50 80 #define FRAME_pain101 81 #define FRAME_pain102 82 #define FRAME_pain103 83 #define FRAME_pain201 84 #define FRAME_pain202 85 #define FRAME_pain203 86 #define FRAME_pain301 87 #define FRAME_pain302 88 #define FRAME_pain303 89 #define FRAME_pain304 90 #define FRAME_pain305 91 #define FRAME_pain306 92 #define FRAME_pain307 93 #define FRAME_pain308 94 #define FRAME_pain309 95 #define FRAME_pain310 96 #define FRAME_pain311 97 #define FRAME_pain312 98 #define FRAME_pain313 99 #define FRAME_pain314 100 #define FRAME_pain315 101 #define FRAME_pain316 102 #define FRAME_pain317 103 #define FRAME_pain318 104 #define FRAME_pain319 105 #define FRAME_pain320 106 #define FRAME_pain321 107 #define FRAME_pain322 108 #define FRAME_pain323 109 #define FRAME_pain324 110 #define FRAME_pain325 111 #define FRAME_stand01 112 #define FRAME_stand02 113 #define FRAME_stand03 114 #define FRAME_stand04 115 #define FRAME_stand05 116 #define FRAME_stand06 117 #define FRAME_stand07 118 #define FRAME_stand08 119 #define FRAME_stand09 120 #define FRAME_stand10 121 #define FRAME_stand11 122 #define FRAME_stand12 123 #define FRAME_stand13 124 #define FRAME_stand14 125 #define FRAME_stand15 126 #define FRAME_stand16 127 #define FRAME_stand17 128 #define FRAME_stand18 129 #define FRAME_stand19 130 #define FRAME_stand20 131 #define FRAME_stand21 132 #define FRAME_stand22 133 #define FRAME_stand23 134 #define FRAME_stand24 135 #define FRAME_stand25 136 #define FRAME_stand26 137 #define FRAME_stand27 138 #define FRAME_stand28 139 #define FRAME_stand29 140 #define FRAME_stand30 141 #define FRAME_stand31 142 #define FRAME_stand32 143 #define FRAME_stand33 144 #define FRAME_stand34 145 #define FRAME_stand35 146 #define FRAME_stand36 147 #define FRAME_stand37 148 #define FRAME_stand38 149 #define FRAME_stand39 150 #define FRAME_stand40 151 #define FRAME_stand41 152 #define FRAME_stand42 153 #define FRAME_stand43 154 #define FRAME_stand44 155 #define FRAME_stand45 156 #define FRAME_stand46 157 #define FRAME_stand47 158 #define FRAME_stand48 159 #define FRAME_stand49 160 #define FRAME_stand50 161 #define FRAME_stand51 162 #define FRAME_walk01 163 #define FRAME_walk02 164 #define FRAME_walk03 165 #define FRAME_walk04 166 #define FRAME_walk05 167 #define FRAME_walk06 168 #define FRAME_walk07 169 #define FRAME_walk08 170 #define FRAME_walk09 171 #define FRAME_walk10 172 #define FRAME_walk11 173 #define FRAME_walk12 174 #define FRAME_walk13 175 #define FRAME_walk14 176 #define FRAME_walk15 177 #define FRAME_walk16 178 #define FRAME_walk17 179 #define FRAME_walk18 180 #define FRAME_walk19 181 #define FRAME_walk20 182 #define FRAME_walk21 183 #define FRAME_walk22 184 #define FRAME_walk23 185 #define FRAME_walk24 186 #define FRAME_walk25 187 #define FRAME_active01 188 #define FRAME_active02 189 #define FRAME_active03 190 #define FRAME_active04 191 #define FRAME_active05 192 #define FRAME_active06 193 #define FRAME_active07 194 #define FRAME_active08 195 #define FRAME_active09 196 #define FRAME_active10 197 #define FRAME_active11 198 #define FRAME_active12 199 #define FRAME_active13 200 #define FRAME_attak301 201 #define FRAME_attak302 202 #define FRAME_attak303 203 #define FRAME_attak304 204 #define FRAME_attak305 205 #define FRAME_attak306 206 #define FRAME_attak307 207 #define FRAME_attak308 208 #define FRAME_attak401 209 #define FRAME_attak402 210 #define FRAME_attak403 211 #define FRAME_attak404 212 #define FRAME_attak405 213 #define FRAME_attak406 214 #define FRAME_attak407 215 #define FRAME_attak408 216 #define FRAME_attak409 217 #define FRAME_attak410 218 #define FRAME_attak411 219 #define FRAME_attak412 220 #define FRAME_attak413 221 #define FRAME_attak414 222 #define FRAME_attak415 223 #define FRAME_attak416 224 #define FRAME_attak417 225 #define FRAME_attak418 226 #define FRAME_attak419 227 #define FRAME_attak420 228 #define FRAME_attak421 229 #define FRAME_attak422 230 #define FRAME_attak423 231 #define FRAME_attak424 232 #define FRAME_attak425 233 #define FRAME_attak426 234 #define FRAME_attak501 235 #define FRAME_attak502 236 #define FRAME_attak503 237 #define FRAME_attak504 238 #define FRAME_attak505 239 #define FRAME_attak506 240 #define FRAME_attak507 241 #define FRAME_attak508 242 #define FRAME_attak509 243 #define FRAME_attak510 244 #define FRAME_attak511 245 #define FRAME_attak512 246 #define FRAME_attak513 247 #define FRAME_attak514 248 #define FRAME_attak515 249 #define FRAME_attak516 250 #define FRAME_death201 251 #define FRAME_death202 252 #define FRAME_death203 253 #define FRAME_death204 254 #define FRAME_death205 255 #define FRAME_death206 256 #define FRAME_death207 257 #define FRAME_death208 258 #define FRAME_death209 259 #define FRAME_death210 260 #define FRAME_death211 261 #define FRAME_death212 262 #define FRAME_death213 263 #define FRAME_death214 264 #define FRAME_death215 265 #define FRAME_death216 266 #define FRAME_death217 267 #define FRAME_death218 268 #define FRAME_death219 269 #define FRAME_death220 270 #define FRAME_death221 271 #define FRAME_death222 272 #define FRAME_death223 273 #define FRAME_death224 274 #define FRAME_death225 275 #define FRAME_death226 276 #define FRAME_death227 277 #define FRAME_death228 278 #define FRAME_death229 279 #define FRAME_death230 280 #define FRAME_death231 281 #define FRAME_death232 282 #define FRAME_death233 283 #define FRAME_death234 284 #define FRAME_death235 285 #define FRAME_death236 286 #define FRAME_death237 287 #define FRAME_death238 288 #define FRAME_death239 289 #define FRAME_death240 290 #define FRAME_death241 291 #define FRAME_death242 292 #define FRAME_death243 293 #define FRAME_death244 294 #define FRAME_death245 295 #define FRAME_death246 296 #define FRAME_death247 297 #define FRAME_death248 298 #define FRAME_death249 299 #define FRAME_death250 300 #define FRAME_death251 301 #define FRAME_death252 302 #define FRAME_death253 303 #define FRAME_death254 304 #define FRAME_death255 305 #define FRAME_death256 306 #define FRAME_death257 307 #define FRAME_death258 308 #define FRAME_death259 309 #define FRAME_death260 310 #define FRAME_death261 311 #define FRAME_death262 312 #define FRAME_death263 313 #define FRAME_death264 314 #define FRAME_death265 315 #define FRAME_death266 316 #define FRAME_death267 317 #define FRAME_death268 318 #define FRAME_death269 319 #define FRAME_death270 320 #define FRAME_death271 321 #define FRAME_death272 322 #define FRAME_death273 323 #define FRAME_death274 324 #define FRAME_death275 325 #define FRAME_death276 326 #define FRAME_death277 327 #define FRAME_death278 328 #define FRAME_death279 329 #define FRAME_death280 330 #define FRAME_death281 331 #define FRAME_death282 332 #define FRAME_death283 333 #define FRAME_death284 334 #define FRAME_death285 335 #define FRAME_death286 336 #define FRAME_death287 337 #define FRAME_death288 338 #define FRAME_death289 339 #define FRAME_death290 340 #define FRAME_death291 341 #define FRAME_death292 342 #define FRAME_death293 343 #define FRAME_death294 344 #define FRAME_death295 345 #define FRAME_death301 346 #define FRAME_death302 347 #define FRAME_death303 348 #define FRAME_death304 349 #define FRAME_death305 350 #define FRAME_death306 351 #define FRAME_death307 352 #define FRAME_death308 353 #define FRAME_death309 354 #define FRAME_death310 355 #define FRAME_death311 356 #define FRAME_death312 357 #define FRAME_death313 358 #define FRAME_death314 359 #define FRAME_death315 360 #define FRAME_death316 361 #define FRAME_death317 362 #define FRAME_death318 363 #define FRAME_death319 364 #define FRAME_death320 365 #define FRAME_jump01 366 #define FRAME_jump02 367 #define FRAME_jump03 368 #define FRAME_jump04 369 #define FRAME_jump05 370 #define FRAME_jump06 371 #define FRAME_jump07 372 #define FRAME_jump08 373 #define FRAME_jump09 374 #define FRAME_jump10 375 #define FRAME_jump11 376 #define FRAME_jump12 377 #define FRAME_jump13 378 #define FRAME_pain401 379 #define FRAME_pain402 380 #define FRAME_pain403 381 #define FRAME_pain404 382 #define FRAME_pain501 383 #define FRAME_pain502 384 #define FRAME_pain503 385 #define FRAME_pain504 386 #define FRAME_pain601 387 #define FRAME_pain602 388 #define FRAME_pain603 389 #define FRAME_pain604 390 #define FRAME_pain605 391 #define FRAME_pain606 392 #define FRAME_pain607 393 #define FRAME_pain608 394 #define FRAME_pain609 395 #define FRAME_pain610 396 #define FRAME_pain611 397 #define FRAME_pain612 398 #define FRAME_pain613 399 #define FRAME_pain614 400 #define FRAME_pain615 401 #define FRAME_pain616 402 #define FRAME_pain617 403 #define FRAME_pain618 404 #define FRAME_pain619 405 #define FRAME_pain620 406 #define FRAME_pain621 407 #define FRAME_pain622 408 #define FRAME_pain623 409 #define FRAME_pain624 410 #define FRAME_pain625 411 #define FRAME_pain626 412 #define FRAME_pain627 413 #define FRAME_stand201 414 #define FRAME_stand202 415 #define FRAME_stand203 416 #define FRAME_stand204 417 #define FRAME_stand205 418 #define FRAME_stand206 419 #define FRAME_stand207 420 #define FRAME_stand208 421 #define FRAME_stand209 422 #define FRAME_stand210 423 #define FRAME_stand211 424 #define FRAME_stand212 425 #define FRAME_stand213 426 #define FRAME_stand214 427 #define FRAME_stand215 428 #define FRAME_stand216 429 #define FRAME_stand217 430 #define FRAME_stand218 431 #define FRAME_stand219 432 #define FRAME_stand220 433 #define FRAME_stand221 434 #define FRAME_stand222 435 #define FRAME_stand223 436 #define FRAME_stand224 437 #define FRAME_stand225 438 #define FRAME_stand226 439 #define FRAME_stand227 440 #define FRAME_stand228 441 #define FRAME_stand229 442 #define FRAME_stand230 443 #define FRAME_stand231 444 #define FRAME_stand232 445 #define FRAME_stand233 446 #define FRAME_stand234 447 #define FRAME_stand235 448 #define FRAME_stand236 449 #define FRAME_stand237 450 #define FRAME_stand238 451 #define FRAME_stand239 452 #define FRAME_stand240 453 #define FRAME_stand241 454 #define FRAME_stand242 455 #define FRAME_stand243 456 #define FRAME_stand244 457 #define FRAME_stand245 458 #define FRAME_stand246 459 #define FRAME_stand247 460 #define FRAME_stand248 461 #define FRAME_stand249 462 #define FRAME_stand250 463 #define FRAME_stand251 464 #define FRAME_stand252 465 #define FRAME_stand253 466 #define FRAME_stand254 467 #define FRAME_stand255 468 #define FRAME_stand256 469 #define FRAME_stand257 470 #define FRAME_stand258 471 #define FRAME_stand259 472 #define FRAME_stand260 473 #define FRAME_walk201 474 #define FRAME_walk202 475 #define FRAME_walk203 476 #define FRAME_walk204 477 #define FRAME_walk205 478 #define FRAME_walk206 479 #define FRAME_walk207 480 #define FRAME_walk208 481 #define FRAME_walk209 482 #define FRAME_walk210 483 #define FRAME_walk211 484 #define FRAME_walk212 485 #define FRAME_walk213 486 #define FRAME_walk214 487 #define FRAME_walk215 488 #define FRAME_walk216 489 #define FRAME_walk217 490 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/brain/000077500000000000000000000000001477320066100171615ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/brain/brain.c000066400000000000000000000370311477320066100204240ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Brain. * * ======================================================================= */ #include "../../header/local.h" #include "brain.h" static int sound_chest_open; static int sound_tentacles_extend; static int sound_tentacles_retract; static int sound_death; static int sound_idle1; static int sound_idle2; static int sound_idle3; static int sound_pain1; static int sound_pain2; static int sound_sight; static int sound_search; static int sound_melee1; static int sound_melee2; static int sound_melee3; static int sound_step; static int sound_step2; void brain_run(edict_t *self); void brain_dead(edict_t *self); void brain_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("brain/step1.wav"); sound_step2 = gi.soundindex("brain/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void brain_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void brain_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); } /* STAND */ static mframe_t brain_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t brain_move_stand = { FRAME_stand01, FRAME_stand30, brain_frames_stand, NULL }; void brain_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &brain_move_stand; } /* IDLE */ static mframe_t brain_frames_idle[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t brain_move_idle = { FRAME_stand31, FRAME_stand60, brain_frames_idle, brain_stand }; void brain_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_AUTO, sound_idle3, 1, ATTN_IDLE, 0); self->monsterinfo.currentmove = &brain_move_idle; } /* WALK */ static mframe_t brain_frames_walk1[] = { {ai_walk, 7, NULL}, {ai_walk, 2, NULL}, {ai_walk, 3, NULL}, {ai_walk, 3, brain_footstep}, {ai_walk, 1, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 9, NULL}, {ai_walk, -4, NULL}, {ai_walk, -1, brain_footstep}, {ai_walk, 2, NULL} }; mmove_t brain_move_walk1 = { FRAME_walk101, FRAME_walk111, brain_frames_walk1, NULL }; void brain_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &brain_move_walk1; } static mframe_t brain_frames_defense[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t brain_move_defense = { FRAME_defens01, FRAME_defens08, brain_frames_defense, NULL }; static mframe_t brain_frames_pain3[] = { {ai_move, -2, NULL}, {ai_move, 2, NULL}, {ai_move, 1, NULL}, {ai_move, 3, NULL}, {ai_move, 0, NULL}, {ai_move, -4, NULL} }; mmove_t brain_move_pain3 = { FRAME_pain301, FRAME_pain306, brain_frames_pain3, brain_run }; static mframe_t brain_frames_pain2[] = { {ai_move, -2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 3, NULL}, {ai_move, 1, NULL}, {ai_move, -2, NULL} }; mmove_t brain_move_pain2 = { FRAME_pain201, FRAME_pain208, brain_frames_pain2, brain_run }; static mframe_t brain_frames_pain1[] = { {ai_move, -6, NULL}, {ai_move, -2, NULL}, {ai_move, -6, brain_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 1, NULL}, {ai_move, 7, NULL}, {ai_move, 0, NULL}, {ai_move, 3, brain_footstep}, {ai_move, -1, NULL} }; mmove_t brain_move_pain1 = { FRAME_pain101, FRAME_pain121, brain_frames_pain1, brain_run }; static mframe_t brain_frames_duck[] = { {ai_move, 0, NULL}, {ai_move, -2, monster_duck_down}, {ai_move, 17, monster_duck_hold}, {ai_move, -3, brain_footstep}, {ai_move, -1, monster_duck_up}, {ai_move, -5, NULL}, {ai_move, -6, NULL}, {ai_move, -6, brain_footstep} }; mmove_t brain_move_duck = { FRAME_duck01, FRAME_duck08, brain_frames_duck, brain_run }; static mframe_t brain_frames_death2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 9, NULL}, {ai_move, 0, NULL} }; mmove_t brain_move_death2 = { FRAME_death201, FRAME_death205, brain_frames_death2, brain_dead }; static mframe_t brain_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, 9, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t brain_move_death1 = { FRAME_death101, FRAME_death118, brain_frames_death1, brain_dead }; /* MELEE */ void brain_swing_right(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_melee1, 1, ATTN_NORM, 0); } void brain_hit_right(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->maxs[0], 8); if (fire_hit(self, aim, (15 + (rand() % 5)), 40)) { gi.sound(self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); } } void brain_swing_left(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_melee2, 1, ATTN_NORM, 0); } void brain_hit_left(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], 8); if (fire_hit(self, aim, (15 + (rand() % 5)), 40)) { gi.sound(self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); } } static mframe_t brain_frames_attack1[] = { {ai_charge, 8, NULL}, {ai_charge, 3, NULL}, {ai_charge, 5, NULL}, {ai_charge, 0, brain_footstep}, {ai_charge, -3, brain_swing_right}, {ai_charge, 0, NULL}, {ai_charge, -5, NULL}, {ai_charge, -7, brain_hit_right}, {ai_charge, 0, NULL}, {ai_charge, 6, brain_swing_left}, {ai_charge, 1, NULL}, {ai_charge, 2, brain_hit_left}, {ai_charge, -3, NULL}, {ai_charge, 6, NULL}, {ai_charge, -1, NULL}, {ai_charge, -3, NULL}, {ai_charge, 2, NULL}, {ai_charge, -11, brain_footstep} }; mmove_t brain_move_attack1 = { FRAME_attak101, FRAME_attak118, brain_frames_attack1, brain_run }; void brain_chest_open(edict_t *self) { if (!self) { return; } self->spawnflags &= ~65536; self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; gi.sound(self, CHAN_BODY, sound_chest_open, 1, ATTN_NORM, 0); } void brain_tentacle_attack(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, 0, 8); if (fire_hit(self, aim, (10 + (rand() % 5)), -600) && (skill->value > 0)) { self->spawnflags |= 65536; } gi.sound(self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0); } void brain_chest_closed(edict_t *self) { if (!self) { return; } self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; if (self->spawnflags & 65536) { self->spawnflags &= ~65536; self->monsterinfo.currentmove = &brain_move_attack1; } } static mframe_t brain_frames_attack2[] = { {ai_charge, 5, NULL}, {ai_charge, -4, NULL}, {ai_charge, -4, NULL}, {ai_charge, -3, NULL}, {ai_charge, 0, brain_chest_open}, {ai_charge, 0, NULL}, {ai_charge, 13, brain_tentacle_attack}, {ai_charge, 0, NULL}, {ai_charge, 2, NULL}, {ai_charge, 0, NULL}, {ai_charge, -9, brain_chest_closed}, {ai_charge, 0, NULL}, {ai_charge, 4, NULL}, {ai_charge, 3, NULL}, {ai_charge, 2, NULL}, {ai_charge, -3, NULL}, {ai_charge, -6, NULL} }; mmove_t brain_move_attack2 = { FRAME_attak201, FRAME_attak217, brain_frames_attack2, brain_run }; void brain_melee(edict_t *self) { if (!self) { return; } if (random() <= 0.5) { self->monsterinfo.currentmove = &brain_move_attack1; } else { self->monsterinfo.currentmove = &brain_move_attack2; } } /* RUN */ static mframe_t brain_frames_run[] = { {ai_run, 9, NULL}, {ai_run, 2, NULL}, {ai_run, 3, NULL}, {ai_run, 3, brain_footstep}, {ai_run, 1, NULL}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, 10, NULL}, {ai_run, -4, NULL}, {ai_run, -1, brain_footstep}, {ai_run, 2, NULL} }; mmove_t brain_move_run = { FRAME_walk101, FRAME_walk111, brain_frames_run, NULL }; void brain_run(edict_t *self) { if (!self) { return; } self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &brain_move_stand; } else { self->monsterinfo.currentmove = &brain_move_run; } } void brain_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage /* unused */) { float r; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } r = random(); if (r < 0.33) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &brain_move_pain1; } else if (r < 0.66) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &brain_move_pain2; } else { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &brain_move_pain3; } /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } void brain_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void brain_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } self->s.effects = 0; self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; if (random() <= 0.5) { self->monsterinfo.currentmove = &brain_move_death1; } else { self->monsterinfo.currentmove = &brain_move_death2; } } void brain_duck(edict_t *self, float eta) { if (!self) { return; } /* has to be done immediately otherwise he can get stuck */ monster_duck_down(self); if (skill->value == SKILL_EASY) { /* PMM - stupid dodge */ self->monsterinfo.duck_wait_time = level.time + eta + 1; } else { self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } self->monsterinfo.currentmove = &brain_move_duck; self->monsterinfo.nextframe = FRAME_duck01; return; } /* * QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_brain(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_chest_open = gi.soundindex("brain/brnatck1.wav"); sound_tentacles_extend = gi.soundindex("brain/brnatck2.wav"); sound_tentacles_retract = gi.soundindex("brain/brnatck3.wav"); sound_death = gi.soundindex("brain/brndeth1.wav"); sound_idle1 = gi.soundindex("brain/brnidle1.wav"); sound_idle2 = gi.soundindex("brain/brnidle2.wav"); sound_idle3 = gi.soundindex("brain/brnlens1.wav"); sound_pain1 = gi.soundindex("brain/brnpain1.wav"); sound_pain2 = gi.soundindex("brain/brnpain2.wav"); sound_sight = gi.soundindex("brain/brnsght1.wav"); sound_search = gi.soundindex("brain/brnsrch1.wav"); sound_melee1 = gi.soundindex("brain/melee1.wav"); sound_melee2 = gi.soundindex("brain/melee2.wav"); sound_melee3 = gi.soundindex("brain/melee3.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/brain/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->health = 300; self->gib_health = -150; self->mass = 400; self->pain = brain_pain; self->die = brain_die; self->monsterinfo.stand = brain_stand; self->monsterinfo.walk = brain_walk; self->monsterinfo.run = brain_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.duck = brain_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.melee = brain_melee; self->monsterinfo.sight = brain_sight; self->monsterinfo.search = brain_search; self->monsterinfo.idle = brain_idle; self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; self->monsterinfo.power_armor_power = 100; gi.linkentity(self); self->monsterinfo.currentmove = &brain_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/brain/brain.h000066400000000000000000000173061477320066100204340ustar00rootroot00000000000000/* ======================================================================= * * Brain animations. * * ======================================================================= * */ #define FRAME_walk101 0 #define FRAME_walk102 1 #define FRAME_walk103 2 #define FRAME_walk104 3 #define FRAME_walk105 4 #define FRAME_walk106 5 #define FRAME_walk107 6 #define FRAME_walk108 7 #define FRAME_walk109 8 #define FRAME_walk110 9 #define FRAME_walk111 10 #define FRAME_walk112 11 #define FRAME_walk113 12 #define FRAME_walk201 13 #define FRAME_walk202 14 #define FRAME_walk203 15 #define FRAME_walk204 16 #define FRAME_walk205 17 #define FRAME_walk206 18 #define FRAME_walk207 19 #define FRAME_walk208 20 #define FRAME_walk209 21 #define FRAME_walk210 22 #define FRAME_walk211 23 #define FRAME_walk212 24 #define FRAME_walk213 25 #define FRAME_walk214 26 #define FRAME_walk215 27 #define FRAME_walk216 28 #define FRAME_walk217 29 #define FRAME_walk218 30 #define FRAME_walk219 31 #define FRAME_walk220 32 #define FRAME_walk221 33 #define FRAME_walk222 34 #define FRAME_walk223 35 #define FRAME_walk224 36 #define FRAME_walk225 37 #define FRAME_walk226 38 #define FRAME_walk227 39 #define FRAME_walk228 40 #define FRAME_walk229 41 #define FRAME_walk230 42 #define FRAME_walk231 43 #define FRAME_walk232 44 #define FRAME_walk233 45 #define FRAME_walk234 46 #define FRAME_walk235 47 #define FRAME_walk236 48 #define FRAME_walk237 49 #define FRAME_walk238 50 #define FRAME_walk239 51 #define FRAME_walk240 52 #define FRAME_attak101 53 #define FRAME_attak102 54 #define FRAME_attak103 55 #define FRAME_attak104 56 #define FRAME_attak105 57 #define FRAME_attak106 58 #define FRAME_attak107 59 #define FRAME_attak108 60 #define FRAME_attak109 61 #define FRAME_attak110 62 #define FRAME_attak111 63 #define FRAME_attak112 64 #define FRAME_attak113 65 #define FRAME_attak114 66 #define FRAME_attak115 67 #define FRAME_attak116 68 #define FRAME_attak117 69 #define FRAME_attak118 70 #define FRAME_attak201 71 #define FRAME_attak202 72 #define FRAME_attak203 73 #define FRAME_attak204 74 #define FRAME_attak205 75 #define FRAME_attak206 76 #define FRAME_attak207 77 #define FRAME_attak208 78 #define FRAME_attak209 79 #define FRAME_attak210 80 #define FRAME_attak211 81 #define FRAME_attak212 82 #define FRAME_attak213 83 #define FRAME_attak214 84 #define FRAME_attak215 85 #define FRAME_attak216 86 #define FRAME_attak217 87 #define FRAME_pain101 88 #define FRAME_pain102 89 #define FRAME_pain103 90 #define FRAME_pain104 91 #define FRAME_pain105 92 #define FRAME_pain106 93 #define FRAME_pain107 94 #define FRAME_pain108 95 #define FRAME_pain109 96 #define FRAME_pain110 97 #define FRAME_pain111 98 #define FRAME_pain112 99 #define FRAME_pain113 100 #define FRAME_pain114 101 #define FRAME_pain115 102 #define FRAME_pain116 103 #define FRAME_pain117 104 #define FRAME_pain118 105 #define FRAME_pain119 106 #define FRAME_pain120 107 #define FRAME_pain121 108 #define FRAME_pain201 109 #define FRAME_pain202 110 #define FRAME_pain203 111 #define FRAME_pain204 112 #define FRAME_pain205 113 #define FRAME_pain206 114 #define FRAME_pain207 115 #define FRAME_pain208 116 #define FRAME_pain301 117 #define FRAME_pain302 118 #define FRAME_pain303 119 #define FRAME_pain304 120 #define FRAME_pain305 121 #define FRAME_pain306 122 #define FRAME_death101 123 #define FRAME_death102 124 #define FRAME_death103 125 #define FRAME_death104 126 #define FRAME_death105 127 #define FRAME_death106 128 #define FRAME_death107 129 #define FRAME_death108 130 #define FRAME_death109 131 #define FRAME_death110 132 #define FRAME_death111 133 #define FRAME_death112 134 #define FRAME_death113 135 #define FRAME_death114 136 #define FRAME_death115 137 #define FRAME_death116 138 #define FRAME_death117 139 #define FRAME_death118 140 #define FRAME_death201 141 #define FRAME_death202 142 #define FRAME_death203 143 #define FRAME_death204 144 #define FRAME_death205 145 #define FRAME_duck01 146 #define FRAME_duck02 147 #define FRAME_duck03 148 #define FRAME_duck04 149 #define FRAME_duck05 150 #define FRAME_duck06 151 #define FRAME_duck07 152 #define FRAME_duck08 153 #define FRAME_defens01 154 #define FRAME_defens02 155 #define FRAME_defens03 156 #define FRAME_defens04 157 #define FRAME_defens05 158 #define FRAME_defens06 159 #define FRAME_defens07 160 #define FRAME_defens08 161 #define FRAME_stand01 162 #define FRAME_stand02 163 #define FRAME_stand03 164 #define FRAME_stand04 165 #define FRAME_stand05 166 #define FRAME_stand06 167 #define FRAME_stand07 168 #define FRAME_stand08 169 #define FRAME_stand09 170 #define FRAME_stand10 171 #define FRAME_stand11 172 #define FRAME_stand12 173 #define FRAME_stand13 174 #define FRAME_stand14 175 #define FRAME_stand15 176 #define FRAME_stand16 177 #define FRAME_stand17 178 #define FRAME_stand18 179 #define FRAME_stand19 180 #define FRAME_stand20 181 #define FRAME_stand21 182 #define FRAME_stand22 183 #define FRAME_stand23 184 #define FRAME_stand24 185 #define FRAME_stand25 186 #define FRAME_stand26 187 #define FRAME_stand27 188 #define FRAME_stand28 189 #define FRAME_stand29 190 #define FRAME_stand30 191 #define FRAME_stand31 192 #define FRAME_stand32 193 #define FRAME_stand33 194 #define FRAME_stand34 195 #define FRAME_stand35 196 #define FRAME_stand36 197 #define FRAME_stand37 198 #define FRAME_stand38 199 #define FRAME_stand39 200 #define FRAME_stand40 201 #define FRAME_stand41 202 #define FRAME_stand42 203 #define FRAME_stand43 204 #define FRAME_stand44 205 #define FRAME_stand45 206 #define FRAME_stand46 207 #define FRAME_stand47 208 #define FRAME_stand48 209 #define FRAME_stand49 210 #define FRAME_stand50 211 #define FRAME_stand51 212 #define FRAME_stand52 213 #define FRAME_stand53 214 #define FRAME_stand54 215 #define FRAME_stand55 216 #define FRAME_stand56 217 #define FRAME_stand57 218 #define FRAME_stand58 219 #define FRAME_stand59 220 #define FRAME_stand60 221 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/carrier/000077500000000000000000000000001477320066100175155ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/carrier/carrier.c000066400000000000000000001015101477320066100213060ustar00rootroot00000000000000/* * ============================================================================== * * Carrier. * * ============================================================================== */ #include "../../header/local.h" #include "carrier.h" #define CARRIER_ROCKET_TIME 2 /* number of seconds between rocket shots */ #define CARRIER_ROCKET_SPEED 750 #define NUM_FLYERS_SPAWNED 6 /* max # of flyers he can spawn */ #define RAIL_FIRE_TIME 3 void BossExplode(edict_t *self); void Grenade_Explode(edict_t *ent); void carrier_run(edict_t *self); void carrier_stand(edict_t *self); void carrier_dead(edict_t *self); void carrier_attack(edict_t *self); void carrier_attack_mg(edict_t *self); void carrier_reattack_mg(edict_t *self); void carrier_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void carrier_attack_gren(edict_t *self); void carrier_reattack_gren(edict_t *self); void carrier_start_spawn(edict_t *self); void carrier_spawn_check(edict_t *self); void carrier_prep_spawn(edict_t *self); void CarrierMachineGunHold(edict_t *self); void CarrierRocket(edict_t *self); qboolean infront(edict_t *self, edict_t *other); qboolean inback(edict_t *self, edict_t *other); qboolean below(edict_t *self, edict_t *other); void drawbbox(edict_t *self); void ED_CallSpawn(edict_t *ent); static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_death; static int sound_sight; static int sound_rail; static int sound_spawn; float orig_yaw_speed; vec3_t flyer_mins = {-16, -16, -24}; vec3_t flyer_maxs = {16, 16, 16}; extern mmove_t flyer_move_attack2, flyer_move_attack3, flyer_move_kamikaze; void carrier_sight(edict_t *self, edict_t *other /* other */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void CarrierCoopCheck(edict_t *self) { if (!self) { return; } /* no more than 4 players in coop, so.. */ edict_t *targets[4]; int num_targets = 0, target, player; edict_t *ent; trace_t tr; /* if we're not in coop, this is a noop */ if (!coop || !coop->value) { return; } /* if we are, and we have recently fired, bail */ if (self->wait > level.time) { return; } memset(targets, 0, 4 * sizeof(edict_t *)); /* cycle through players */ for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (inback(self, ent) || below(self, ent)) { tr = gi.trace(self->s.origin, NULL, NULL, ent->s.origin, self, MASK_SOLID); if (tr.fraction == 1.0) { targets[num_targets++] = ent; } } } if (!num_targets) { return; } /* get a number from 0 to (num_targets-1) */ target = random() * num_targets; /* just in case we got a 1.0 from random */ if (target == num_targets) { target--; } /* make sure to prevent rapid fire rockets */ self->wait = level.time + CARRIER_ROCKET_TIME; /* save off the real enemy */ ent = self->enemy; /* set the new guy as temporary enemy */ self->enemy = targets[target]; CarrierRocket(self); /* put the real enemy back */ self->enemy = ent; /* we're done */ return; } void CarrierGrenade(edict_t *self) { vec3_t start; vec3_t forward, right, up; vec3_t aim; int flash_number; float direction; /* from lower left to upper right, or lower right to upper left */ float spreadR, spreadU; int mytime; if (!self) { return; } CarrierCoopCheck(self); if (!self->enemy) { return; } if (random() < 0.5) { direction = -1.0; } else { direction = 1.0; } mytime = (int)((level.time - self->timestamp) / 0.4); if (mytime == 0) { spreadR = 0.15 * direction; spreadU = 0.1 - 0.1 * direction; } else if (mytime == 1) { spreadR = 0; spreadU = 0.1; } else if (mytime == 2) { spreadR = -0.15 * direction; spreadU = 0.1 - -0.1 * direction; } else if (mytime == 3) { spreadR = 0; spreadU = 0.1; } else { /* error, shoot straight */ spreadR = 0; spreadU = 0; } AngleVectors(self->s.angles, forward, right, up); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_GRENADE], forward, right, start); VectorSubtract(self->enemy->s.origin, start, aim); VectorNormalize(aim); VectorMA(aim, spreadR, right, aim); VectorMA(aim, spreadU, up, aim); if (aim[2] > 0.15) { aim[2] = 0.15; } else if (aim[2] < -0.5) { aim[2] = -0.5; } flash_number = MZ2_GUNNER_GRENADE_1; monster_fire_grenade(self, start, aim, 50, 600, flash_number); } void CarrierPredictiveRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); /* 1 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_1], forward, right, start); PredictAim(self->enemy, start, CARRIER_ROCKET_SPEED, false, -0.3, dir, NULL); monster_fire_rocket(self, start, dir, 50, CARRIER_ROCKET_SPEED, MZ2_CARRIER_ROCKET_1); /* 2 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_2], forward, right, start); PredictAim(self->enemy, start, CARRIER_ROCKET_SPEED, false, -0.15, dir, NULL); monster_fire_rocket(self, start, dir, 50, CARRIER_ROCKET_SPEED, MZ2_CARRIER_ROCKET_2); /* 3 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_3], forward, right, start); PredictAim(self->enemy, start, CARRIER_ROCKET_SPEED, false, 0, dir, NULL); monster_fire_rocket(self, start, dir, 50, CARRIER_ROCKET_SPEED, MZ2_CARRIER_ROCKET_3); /* 4 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_4], forward, right, start); PredictAim(self->enemy, start, CARRIER_ROCKET_SPEED, false, 0.15, dir, NULL); monster_fire_rocket(self, start, dir, 50, CARRIER_ROCKET_SPEED, MZ2_CARRIER_ROCKET_4); } void CarrierRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; if (!self) { return; } if (self->enemy) { if (self->enemy->client && (random() < 0.5)) { CarrierPredictiveRocket(self); return; } } else { return; } AngleVectors(self->s.angles, forward, right, NULL); /* 1 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_1], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] -= 15; VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, 0.4, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_CARRIER_ROCKET_1); /* 2 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_2], forward, right, start); VectorCopy(self->enemy->s.origin, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, 0.025, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_CARRIER_ROCKET_2); /* 3 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_3], forward, right, start); VectorCopy(self->enemy->s.origin, vec); VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, -0.025, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_CARRIER_ROCKET_3); /* 4 */ G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_ROCKET_4], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] -= 15; VectorSubtract(vec, start, dir); VectorNormalize(dir); VectorMA(dir, -0.4, right, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, MZ2_CARRIER_ROCKET_4); } void carrier_firebullet_right(edict_t *self) { vec3_t forward, right, target; vec3_t start; int flashnum; if (!self) { return; } /* if we're in manual steering mode, it means we're leaning down .. use the lower shot */ if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { flashnum = MZ2_CARRIER_MACHINEGUN_R2; } else { flashnum = MZ2_CARRIER_MACHINEGUN_R1; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorMA(self->enemy->s.origin, 0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD * 3, DEFAULT_BULLET_VSPREAD, flashnum); } void carrier_firebullet_left(edict_t *self) { vec3_t forward, right, target; vec3_t start; int flashnum; if (!self) { return; } /* if we're in manual steering mode, it means we're leaning down .. use the lower shot */ if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { flashnum = MZ2_CARRIER_MACHINEGUN_L2; } else { flashnum = MZ2_CARRIER_MACHINEGUN_L1; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD * 3, DEFAULT_BULLET_VSPREAD, flashnum); } void CarrierMachineGun(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); if (self->enemy) { carrier_firebullet_left(self); } if (self->enemy) { carrier_firebullet_right(self); } } void CarrierSpawn(edict_t *self) { vec3_t f, r, offset, startpoint, spawnpoint; edict_t *ent; int mytime; if (!self) { return; } VectorSet(offset, 105, 0, -58); AngleVectors(self->s.angles, f, r, NULL); G_ProjectSource(self->s.origin, offset, f, r, startpoint); /* the +0.1 is because level.time is sometimes a little low */ mytime = (int)((level.time + 0.1 - self->timestamp) / 0.5); if (FindSpawnPoint(startpoint, flyer_mins, flyer_maxs, spawnpoint, 32)) { /* the second flier should be a kamikaze flyer */ if (mytime != 2) { ent = CreateMonster(spawnpoint, self->s.angles, "monster_flyer"); } else { ent = CreateMonster(spawnpoint, self->s.angles, "monster_kamikaze"); } if (!ent) { return; } gi.sound(self, CHAN_BODY, sound_spawn, 1, ATTN_NONE, 0); self->monsterinfo.monster_slots--; ent->nextthink = level.time; ent->think(ent); ent->monsterinfo.aiflags |= AI_SPAWNED_CARRIER | AI_DO_NOT_COUNT | AI_IGNORE_SHOTS; ent->monsterinfo.commander = self; if ((self->enemy->inuse) && (self->enemy->health > 0)) { ent->enemy = self->enemy; FoundTarget(ent); if (mytime == 1) { ent->monsterinfo.lefty = 0; ent->monsterinfo.attack_state = AS_SLIDING; ent->monsterinfo.currentmove = &flyer_move_attack3; } else if (mytime == 2) { ent->monsterinfo.lefty = 0; ent->monsterinfo.attack_state = AS_STRAIGHT; ent->monsterinfo.currentmove = &flyer_move_kamikaze; ent->mass = 100; ent->monsterinfo.aiflags |= AI_CHARGING; } else if (mytime == 3) { ent->monsterinfo.lefty = 1; ent->monsterinfo.attack_state = AS_SLIDING; ent->monsterinfo.currentmove = &flyer_move_attack3; } } } } void carrier_prep_spawn(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->timestamp = level.time; self->yaw_speed = 10; CarrierMachineGun(self); } void carrier_spawn_check(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); CarrierMachineGun(self); CarrierSpawn(self); if (level.time > (self->timestamp + 1.1)) /* 0.5 seconds per flyer. this gets three */ { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->yaw_speed = orig_yaw_speed; return; } else { self->monsterinfo.nextframe = FRAME_spawn08; } } void carrier_ready_spawn(edict_t *self) { float current_yaw; vec3_t offset, f, r, startpoint, spawnpoint; if (!self) { return; } CarrierCoopCheck(self); CarrierMachineGun(self); current_yaw = anglemod(self->s.angles[YAW]); if (fabs(current_yaw - self->ideal_yaw) > 0.1) { self->monsterinfo.aiflags |= AI_HOLD_FRAME; self->timestamp += FRAMETIME; return; } self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; VectorSet(offset, 105, 0, -58); AngleVectors(self->s.angles, f, r, NULL); G_ProjectSource(self->s.origin, offset, f, r, startpoint); if (FindSpawnPoint(startpoint, flyer_mins, flyer_maxs, spawnpoint, 32)) { SpawnGrow_Spawn(spawnpoint, 0); } } void carrier_start_spawn(edict_t *self) { int mytime; float enemy_yaw; vec3_t temp; if (!self) { return; } CarrierCoopCheck(self); if (!orig_yaw_speed) { orig_yaw_speed = self->yaw_speed; } if (!self->enemy) { return; } mytime = (int)((level.time - self->timestamp) / 0.5); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw2(temp); /* note that the offsets are based on a forward of 105 from the end angle */ if (mytime == 0) { self->ideal_yaw = anglemod(enemy_yaw - 30); } else if (mytime == 1) { self->ideal_yaw = anglemod(enemy_yaw); } else if (mytime == 2) { self->ideal_yaw = anglemod(enemy_yaw + 30); } CarrierMachineGun(self); } static mframe_t carrier_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t carrier_move_stand = { FRAME_search01, FRAME_search13, carrier_frames_stand, NULL }; static mframe_t carrier_frames_walk[] = { {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL} }; mmove_t carrier_move_walk = { FRAME_search01, FRAME_search13, carrier_frames_walk, NULL }; static mframe_t carrier_frames_run[] = { {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck}, {ai_run, 6, CarrierCoopCheck} }; mmove_t carrier_move_run = { FRAME_search01, FRAME_search13, carrier_frames_run, NULL }; static mframe_t carrier_frames_attack_pre_mg[] = { {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, carrier_attack_mg} }; mmove_t carrier_move_attack_pre_mg = { FRAME_firea01, FRAME_firea08, carrier_frames_attack_pre_mg, NULL }; /* Loop this */ static mframe_t carrier_frames_attack_mg[] = { {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, carrier_reattack_mg} }; mmove_t carrier_move_attack_mg = { FRAME_firea09, FRAME_firea11, carrier_frames_attack_mg, NULL }; static mframe_t carrier_frames_attack_post_mg[] = { {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck} }; mmove_t carrier_move_attack_post_mg = { FRAME_firea12, FRAME_firea15, carrier_frames_attack_post_mg, carrier_run }; static mframe_t carrier_frames_attack_pre_gren[] = { {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, carrier_attack_gren} }; mmove_t carrier_move_attack_pre_gren = { FRAME_fireb01, FRAME_fireb06, carrier_frames_attack_pre_gren, NULL }; static mframe_t carrier_frames_attack_gren[] = { {ai_charge, -15, CarrierGrenade}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, carrier_reattack_gren} }; mmove_t carrier_move_attack_gren = { FRAME_fireb07, FRAME_fireb10, carrier_frames_attack_gren, NULL }; static mframe_t carrier_frames_attack_post_gren[] = { {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck}, {ai_charge, 4, CarrierCoopCheck} }; mmove_t carrier_move_attack_post_gren = { FRAME_fireb11, FRAME_fireb16, carrier_frames_attack_post_gren, carrier_run }; static mframe_t carrier_frames_attack_rocket[] = { {ai_charge, 15, CarrierRocket} }; mmove_t carrier_move_attack_rocket = { FRAME_fireb01, FRAME_fireb01, carrier_frames_attack_rocket, carrier_run }; void CarrierRail(edict_t *self) { vec3_t start; vec3_t dir; vec3_t forward, right; if (!self) { return; } CarrierCoopCheck(self); AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CARRIER_RAILGUN], forward, right, start); /* calc direction to where we targeted */ VectorSubtract(self->pos1, start, dir); VectorNormalize(dir); monster_fire_railgun(self, start, dir, 50, 100, MZ2_CARRIER_RAILGUN); self->monsterinfo.attack_finished = level.time + RAIL_FIRE_TIME; } void CarrierSaveLoc(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; } static mframe_t carrier_frames_attack_rail[] = { {ai_charge, 2, CarrierCoopCheck}, {ai_charge, 2, CarrierSaveLoc}, {ai_charge, 2, CarrierCoopCheck}, {ai_charge, -20, CarrierRail}, {ai_charge, 2, CarrierCoopCheck}, {ai_charge, 2, CarrierCoopCheck}, {ai_charge, 2, CarrierCoopCheck}, {ai_charge, 2, CarrierCoopCheck}, {ai_charge, 2, CarrierCoopCheck} }; mmove_t carrier_move_attack_rail = { FRAME_search01, FRAME_search09, carrier_frames_attack_rail, carrier_run }; static mframe_t carrier_frames_spawn[] = { {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, carrier_prep_spawn}, /* 7 - end of wind down */ {ai_charge, -2, carrier_start_spawn}, /* 8 - start of spawn */ {ai_charge, -2, carrier_ready_spawn}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -10, carrier_spawn_check}, /* 12 - actual spawn */ {ai_charge, -2, CarrierMachineGun}, /* 13 - begin of wind down */ {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, CarrierMachineGun}, {ai_charge, -2, carrier_reattack_mg} /* 18 - end of wind down */ }; mmove_t carrier_move_spawn = { FRAME_spawn01, FRAME_spawn18, carrier_frames_spawn, NULL }; static mframe_t carrier_frames_pain_heavy[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t carrier_move_pain_heavy = { FRAME_death01, FRAME_death10, carrier_frames_pain_heavy, carrier_run }; static mframe_t carrier_frames_pain_light[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t carrier_move_pain_light = { FRAME_spawn01, FRAME_spawn04, carrier_frames_pain_light, carrier_run }; static mframe_t carrier_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, BossExplode} }; mmove_t carrier_move_death = { FRAME_death01, FRAME_death16, carrier_frames_death, carrier_dead }; void carrier_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &carrier_move_stand; } void carrier_run(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &carrier_move_stand; } else { self->monsterinfo.currentmove = &carrier_move_run; } } void carrier_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &carrier_move_walk; } void CarrierMachineGunHold(edict_t *self) { if (!self) { return; } CarrierMachineGun(self); } void carrier_attack(edict_t *self) { vec3_t vec; float range, luck; qboolean enemy_inback, enemy_infront, enemy_below; if (!self) { return; } self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; if ((!self->enemy) || (!self->enemy->inuse)) { return; } enemy_inback = inback(self, self->enemy); enemy_infront = infront(self, self->enemy); enemy_below = below(self, self->enemy); if (self->bad_area) { if ((enemy_inback) || (enemy_below)) { self->monsterinfo.currentmove = &carrier_move_attack_rocket; } else if ((random() < 0.1) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } return; } if (self->monsterinfo.attack_state == AS_BLIND) { self->monsterinfo.currentmove = &carrier_move_spawn; return; } if (!enemy_inback && !enemy_infront && !enemy_below) /* to side and not under */ { if ((random() < 0.1) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } return; } if (enemy_infront) { VectorSubtract(self->enemy->s.origin, self->s.origin, vec); range = VectorLength(vec); if (range <= 125) { if ((random() < 0.8) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } } else if (range < 600) { luck = random(); if (self->monsterinfo.monster_slots > 2) { if (luck <= 0.20) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else if (luck <= 0.40) { self->monsterinfo.currentmove = &carrier_move_attack_pre_gren; } else if ((luck <= 0.7) && !(level.time < self->monsterinfo.attack_finished)) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } else { self->monsterinfo.currentmove = &carrier_move_spawn; } } else { if (luck <= 0.30) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else if (luck <= 0.65) { self->monsterinfo.currentmove = &carrier_move_attack_pre_gren; } else if (level.time >= self->monsterinfo.attack_finished) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } else { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } } } else /* won't use grenades at this range */ { luck = random(); if (self->monsterinfo.monster_slots > 2) { if (luck < 0.3) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else if ((luck < 0.65) && !(level.time < self->monsterinfo.attack_finished)) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; self->monsterinfo.currentmove = &carrier_move_attack_rail; } else { self->monsterinfo.currentmove = &carrier_move_spawn; } } else { if ((luck < 0.45) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &carrier_move_attack_pre_mg; } else { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &carrier_move_attack_rail; } } } } else if ((enemy_below) || (enemy_inback)) { self->monsterinfo.currentmove = &carrier_move_attack_rocket; } } void carrier_attack_mg(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); self->monsterinfo.currentmove = &carrier_move_attack_mg; } void carrier_reattack_mg(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); if (infront(self, self->enemy)) { if (random() <= 0.5) { if ((random() < 0.7) || (self->monsterinfo.monster_slots <= 2)) { self->monsterinfo.currentmove = &carrier_move_attack_mg; } else { self->monsterinfo.currentmove = &carrier_move_spawn; } } else { self->monsterinfo.currentmove = &carrier_move_attack_post_mg; } } else { self->monsterinfo.currentmove = &carrier_move_attack_post_mg; } } void carrier_attack_gren(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); self->timestamp = level.time; self->monsterinfo.currentmove = &carrier_move_attack_gren; } void carrier_reattack_gren(edict_t *self) { if (!self) { return; } CarrierCoopCheck(self); if (infront(self, self->enemy)) { if (self->timestamp + 1.3 > level.time) /* four grenades */ { self->monsterinfo.currentmove = &carrier_move_attack_gren; return; } } self->monsterinfo.currentmove = &carrier_move_attack_post_gren; } void carrier_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { qboolean changed = false; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 5; if (damage < 10) { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); } else if (damage < 30) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); if (random() < 0.5) { changed = true; self->monsterinfo.currentmove = &carrier_move_pain_light; } } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); self->monsterinfo.currentmove = &carrier_move_pain_heavy; changed = true; } if (changed) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->yaw_speed = orig_yaw_speed; } } void carrier_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -56, -56, 0); VectorSet(self->maxs, 56, 56, 80); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void carrier_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; self->monsterinfo.currentmove = &carrier_move_death; } qboolean Carrier_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance = 0; trace_t tr; qboolean enemy_infront, enemy_inback, enemy_below; int enemy_range; float enemy_yaw; if (!self) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* go ahead and spawn stuff if we're mad a a client */ if (self->enemy->client && (self->monsterinfo.monster_slots > 2)) { self->monsterinfo.attack_state = AS_BLIND; return true; } /* we want them to go ahead and shoot at info_notnulls if they can. */ if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0)) { return false; } } } enemy_infront = infront(self, self->enemy); enemy_inback = inback(self, self->enemy); enemy_below = below(self, self->enemy); enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw2(temp); self->ideal_yaw = enemy_yaw; /* shoot out the back if appropriate */ if ((enemy_inback) || (!enemy_infront && enemy_below)) { /* this is using wait because the attack is supposed to be independent */ if (level.time >= self->wait) { self->wait = level.time + CARRIER_ROCKET_TIME; self->monsterinfo.attack(self); if (random() < 0.6) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } return true; } } /* melee attack */ if (enemy_range == RANGE_MELEE) { self->monsterinfo.attack_state = AS_MISSILE; return true; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.8; } else if (enemy_range == RANGE_MID) { chance = 0.8; } else if (enemy_range == RANGE_FAR) { chance = 0.5; } /* go ahead and shoot every time if it's a info_notnull */ if ((random() < chance) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; return true; } if (self->flags & FL_FLY) { if (random() < 0.6) { self->monsterinfo.attack_state = AS_SLIDING; } else { self->monsterinfo.attack_state = AS_STRAIGHT; } } return false; } void CarrierPrecache() { gi.soundindex("flyer/flysght1.wav"); gi.soundindex("flyer/flysrch1.wav"); gi.soundindex("flyer/flypain1.wav"); gi.soundindex("flyer/flypain2.wav"); gi.soundindex("flyer/flyatck2.wav"); gi.soundindex("flyer/flyatck1.wav"); gi.soundindex("flyer/flydeth1.wav"); gi.soundindex("flyer/flyatck3.wav"); gi.soundindex("flyer/flyidle1.wav"); gi.soundindex("weapons/rockfly.wav"); gi.soundindex("infantry/infatck1.wav"); gi.soundindex("gunner/gunatck3.wav"); gi.soundindex("weapons/grenlb1b.wav"); gi.soundindex("tank/rocket.wav"); gi.modelindex("models/monsters/flyer/tris.md2"); gi.modelindex("models/objects/rocket/tris.md2"); gi.modelindex("models/objects/debris2/tris.md2"); gi.modelindex("models/objects/grenade/tris.md2"); gi.modelindex("models/items/spawngro/tris.md2"); gi.modelindex("models/items/spawngro2/tris.md2"); gi.modelindex("models/objects/gibs/sm_metal/tris.md2"); gi.modelindex("models/objects/gibs/gear/tris.md2"); } /* * QUAKED monster_carrier (1 .5 0) (-56 -56 -44) (56 56 44) Ambush Trigger_Spawn Sight */ void SP_monster_carrier(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("carrier/pain_md.wav"); sound_pain2 = gi.soundindex("carrier/pain_lg.wav"); sound_pain3 = gi.soundindex("carrier/pain_sm.wav"); sound_death = gi.soundindex("carrier/death.wav"); sound_rail = gi.soundindex("gladiator/railgun.wav"); sound_sight = gi.soundindex("carrier/sight.wav"); sound_spawn = gi.soundindex("medic_commander/monsterspawn1.wav"); self->s.sound = gi.soundindex("bosshovr/bhvengn1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/carrier/tris.md2"); VectorSet(self->mins, -56, -56, -44); VectorSet(self->maxs, 56, 56, 44); /* 2000 - 4000 health */ self->health = max(2000, 2000 + 1000 * ((skill->value) - 1)); /* add health in coop (500 * skill) */ if (coop->value) { self->health += 500 * (skill->value); } self->gib_health = -200; self->mass = 1000; self->yaw_speed = 15; orig_yaw_speed = self->yaw_speed; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = carrier_pain; self->die = carrier_die; self->monsterinfo.melee = NULL; self->monsterinfo.stand = carrier_stand; self->monsterinfo.walk = carrier_walk; self->monsterinfo.run = carrier_run; self->monsterinfo.attack = carrier_attack; self->monsterinfo.sight = carrier_sight; self->monsterinfo.checkattack = Carrier_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &carrier_move_stand; self->monsterinfo.scale = MODEL_SCALE; CarrierPrecache(); flymonster_start(self); self->monsterinfo.attack_finished = 0; switch ((int)skill->value) { case 0: self->monsterinfo.monster_slots = 3; break; case 1: case 2: self->monsterinfo.monster_slots = 6; break; case 3: self->monsterinfo.monster_slots = 9; break; default: self->monsterinfo.monster_slots = 6; break; } } rogue-ROGUE_2_13/src/monster/carrier/carrier.h000066400000000000000000000054561477320066100213270ustar00rootroot00000000000000/* ======================================================================= * * Carrier animations. * * ======================================================================= * */ #define FRAME_search01 0 #define FRAME_search02 1 #define FRAME_search03 2 #define FRAME_search04 3 #define FRAME_search05 4 #define FRAME_search06 5 #define FRAME_search07 6 #define FRAME_search08 7 #define FRAME_search09 8 #define FRAME_search10 9 #define FRAME_search11 10 #define FRAME_search12 11 #define FRAME_search13 12 #define FRAME_firea01 13 #define FRAME_firea02 14 #define FRAME_firea03 15 #define FRAME_firea04 16 #define FRAME_firea05 17 #define FRAME_firea06 18 #define FRAME_firea07 19 #define FRAME_firea08 20 #define FRAME_firea09 21 #define FRAME_firea10 22 #define FRAME_firea11 23 #define FRAME_firea12 24 #define FRAME_firea13 25 #define FRAME_firea14 26 #define FRAME_firea15 27 #define FRAME_fireb01 28 #define FRAME_fireb02 29 #define FRAME_fireb03 30 #define FRAME_fireb04 31 #define FRAME_fireb05 32 #define FRAME_fireb06 33 #define FRAME_fireb07 34 #define FRAME_fireb08 35 #define FRAME_fireb09 36 #define FRAME_fireb10 37 #define FRAME_fireb11 38 #define FRAME_fireb12 39 #define FRAME_fireb13 40 #define FRAME_fireb14 41 #define FRAME_fireb15 42 #define FRAME_fireb16 43 #define FRAME_spawn01 44 #define FRAME_spawn02 45 #define FRAME_spawn03 46 #define FRAME_spawn04 47 #define FRAME_spawn05 48 #define FRAME_spawn06 49 #define FRAME_spawn07 50 #define FRAME_spawn08 51 #define FRAME_spawn09 52 #define FRAME_spawn10 53 #define FRAME_spawn11 54 #define FRAME_spawn12 55 #define FRAME_spawn13 56 #define FRAME_spawn14 57 #define FRAME_spawn15 58 #define FRAME_spawn16 59 #define FRAME_spawn17 60 #define FRAME_spawn18 61 #define FRAME_death01 62 #define FRAME_death02 63 #define FRAME_death03 64 #define FRAME_death04 65 #define FRAME_death05 66 #define FRAME_death06 67 #define FRAME_death07 68 #define FRAME_death08 69 #define FRAME_death09 70 #define FRAME_death10 71 #define FRAME_death11 72 #define FRAME_death12 73 #define FRAME_death13 74 #define FRAME_death14 75 #define FRAME_death15 76 #define FRAME_death16 77 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/chick/000077500000000000000000000000001477320066100171475ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/chick/chick.c000066400000000000000000000524611477320066100204040ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Iron Maiden. * * ======================================================================= */ #include "../../header/local.h" #include "chick.h" #define LEAD_TARGET 1 qboolean visible(edict_t *self, edict_t *other); void chick_stand(edict_t *self); void chick_run(edict_t *self); void chick_reslash(edict_t *self); void chick_rerocket(edict_t *self); void chick_attack1(edict_t *self); static int sound_missile_prelaunch; static int sound_missile_launch; static int sound_melee_swing; static int sound_melee_hit; static int sound_missile_reload; static int sound_death1; static int sound_death2; static int sound_fall_down; static int sound_idle1; static int sound_idle2; static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_sight; static int sound_search; static int sound_step; static int sound_step2; void chick_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("bitch/step1.wav"); sound_step2 = gi.soundindex("bitch/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void ChickMoan(edict_t *self) { if (!self) { return; } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); } else { gi.sound(self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0); } } static mframe_t chick_frames_fidget[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, ChickMoan}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t chick_move_fidget = { FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand }; void chick_fidget(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { return; } if (random() <= 0.3) { self->monsterinfo.currentmove = &chick_move_fidget; } } static mframe_t chick_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, chick_fidget}, }; mmove_t chick_move_stand = { FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL }; void chick_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &chick_move_stand; } static mframe_t chick_frames_start_run[] = { {ai_run, 1, NULL}, {ai_run, 0, NULL}, {ai_run, 0, NULL}, {ai_run, -1, NULL}, {ai_run, -1, NULL}, {ai_run, 0, NULL}, {ai_run, 1, NULL}, {ai_run, 3, NULL}, {ai_run, 6, NULL}, {ai_run, 3, NULL} }; mmove_t chick_move_start_run = { FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run }; static mframe_t chick_frames_run[] = { {ai_run, 6, NULL}, {ai_run, 8, chick_footstep}, {ai_run, 13, NULL}, {ai_run, 5, NULL}, {ai_run, 7, NULL}, {ai_run, 4, NULL}, {ai_run, 11, chick_footstep}, {ai_run, 5, NULL}, {ai_run, 9, NULL}, {ai_run, 7, NULL} }; mmove_t chick_move_run = { FRAME_walk11, FRAME_walk20, chick_frames_run, NULL }; static mframe_t chick_frames_walk[] = { {ai_walk, 6, NULL}, {ai_walk, 8, chick_footstep}, {ai_walk, 13, NULL}, {ai_walk, 5, NULL}, {ai_walk, 7, NULL}, {ai_walk, 4, NULL}, {ai_walk, 11, chick_footstep}, {ai_walk, 5, NULL}, {ai_walk, 9, NULL}, {ai_walk, 7, NULL} }; mmove_t chick_move_walk = { FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL }; void chick_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &chick_move_walk; } void chick_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &chick_move_stand; return; } if ((self->monsterinfo.currentmove == &chick_move_walk) || (self->monsterinfo.currentmove == &chick_move_start_run)) { self->monsterinfo.currentmove = &chick_move_run; } else { self->monsterinfo.currentmove = &chick_move_start_run; } } static mframe_t chick_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t chick_move_pain1 = { FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run }; static mframe_t chick_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t chick_move_pain2 = { FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run }; static mframe_t chick_frames_pain3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -6, NULL}, {ai_move, 3, NULL}, {ai_move, 11, NULL}, {ai_move, 3, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 4, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, -3, NULL}, {ai_move, -4, NULL}, {ai_move, 5, NULL}, {ai_move, 7, NULL}, {ai_move, -2, NULL}, {ai_move, 3, NULL}, {ai_move, -5, NULL}, {ai_move, -2, NULL}, {ai_move, -8, NULL}, {ai_move, 2, NULL} }; mmove_t chick_move_pain3 = { FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run }; void chick_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { float r; if (!self) { return; } monster_done_dodge(self); if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; r = random(); if (r < 0.33) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else if (r < 0.66) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } /* clear this from blindfire */ self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; if (damage <= 10) { self->monsterinfo.currentmove = &chick_move_pain1; } else if (damage <= 25) { self->monsterinfo.currentmove = &chick_move_pain2; } else { self->monsterinfo.currentmove = &chick_move_pain3; } /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } void chick_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, 0); VectorSet(self->maxs, 16, 16, 16); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t chick_frames_death2[] = { {ai_move, -6, NULL}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -5, chick_footstep}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -2, NULL}, {ai_move, 1, NULL}, {ai_move, 10, NULL}, {ai_move, 2, NULL}, {ai_move, 3, chick_footstep}, {ai_move, 1, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 3, NULL}, {ai_move, 3, NULL}, {ai_move, 1, chick_footstep}, {ai_move, -3, NULL}, {ai_move, -5, NULL}, {ai_move, 4, NULL}, {ai_move, 15, NULL}, {ai_move, 14, NULL}, {ai_move, 1, NULL} }; mmove_t chick_move_death2 = { FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead }; static mframe_t chick_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -7, NULL}, {ai_move, 4, NULL}, {ai_move, 11, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t chick_move_death1 = { FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead }; void chick_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /*unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; n = rand() % 2; if (n == 0) { self->monsterinfo.currentmove = &chick_move_death1; gi.sound(self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &chick_move_death2; gi.sound(self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); } } static mframe_t chick_frames_duck[] = { {ai_move, 0, monster_duck_down}, {ai_move, 1, NULL}, {ai_move, 4, monster_duck_hold}, {ai_move, -4, NULL}, {ai_move, -5, monster_duck_up}, {ai_move, 3, NULL}, {ai_move, 1, NULL} }; mmove_t chick_move_duck = { FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run }; void ChickSlash(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], 10); gi.sound(self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0); fire_hit(self, aim, (10 + (rand() % 6)), 100); } void ChickRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; trace_t trace; /* check target */ int rocketSpeed; float dist; vec3_t target; qboolean blindfire = false; if (!self) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { blindfire = true; } else { blindfire = false; } if (!self->enemy || !self->enemy->inuse) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start); rocketSpeed = 500 + (100 * skill->value); /* rock & roll.... :) */ if (blindfire) { VectorCopy(self->monsterinfo.blind_fire_target, target); } else { VectorCopy(self->enemy->s.origin, target); } /* blindfire shooting */ if (blindfire) { VectorCopy(target, vec); VectorSubtract(vec, start, dir); } /* don't shoot at feet if they're above where i'm shooting from. */ else if ((random() < 0.33) || (start[2] < self->enemy->absmin[2])) { VectorCopy(target, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, dir); } else { VectorCopy(target, vec); vec[2] = self->enemy->absmin[2]; VectorSubtract(vec, start, dir); } /* lead target (not when blindfiring) */ if ((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15))))) { float time; dist = VectorLength(dir); time = dist / rocketSpeed; VectorMA(vec, time, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); } VectorNormalize(dir); if (blindfire) { /* blindfire has different fail criteria for the trace */ if (!blind_rocket_ok(self, start, right, target, 10.0f, dir)) { return; } } else { trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); if (((trace.ent != self->enemy) && (trace.ent != world)) || ((trace.fraction <= 0.5f) && !trace.ent->client)) { return; } } monster_fire_rocket(self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1); } void Chick_PreAttack1(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0); } void ChickReload(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0); } static mframe_t chick_frames_start_attack1[] = { {ai_charge, 0, Chick_PreAttack1}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 4, NULL}, {ai_charge, 0, NULL}, {ai_charge, -3, NULL}, {ai_charge, 3, NULL}, {ai_charge, 5, NULL}, {ai_charge, 7, chick_footstep}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, chick_attack1} }; mmove_t chick_move_start_attack1 = { FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL }; static mframe_t chick_frames_attack1[] = { {ai_charge, 19, ChickRocket}, {ai_charge, -6, NULL}, {ai_charge, -5, chick_footstep}, {ai_charge, -2, NULL}, {ai_charge, -7, chick_footstep}, {ai_charge, 0, NULL}, {ai_charge, 1, NULL}, {ai_charge, 10, ChickReload}, {ai_charge, 4, NULL}, {ai_charge, 5, chick_footstep}, {ai_charge, 6, NULL}, {ai_charge, 6, NULL}, {ai_charge, 4, chick_footstep}, {ai_charge, 3, chick_rerocket} }; mmove_t chick_move_attack1 = { FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL }; static mframe_t chick_frames_end_attack1[] = { {ai_charge, -3, NULL}, {ai_charge, 0, NULL}, {ai_charge, -6, NULL}, {ai_charge, -4, NULL}, {ai_charge, -2, chick_footstep} }; mmove_t chick_move_end_attack1 = { FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run }; void chick_rerocket(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.currentmove = &chick_move_end_attack1; return; } if (self->enemy->health > 0) { if (range(self, self->enemy) > RANGE_MELEE) { if (visible(self, self->enemy)) { if (random() <= (0.6 + (0.05 * ((float)skill->value)))) { self->monsterinfo.currentmove = &chick_move_attack1; return; } } } } self->monsterinfo.currentmove = &chick_move_end_attack1; } void chick_attack1(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &chick_move_attack1; } static mframe_t chick_frames_slash[] = { {ai_charge, 1, NULL}, {ai_charge, 7, ChickSlash}, {ai_charge, -7, NULL}, {ai_charge, 1, NULL}, {ai_charge, -1, NULL}, {ai_charge, 1, NULL}, {ai_charge, 0, NULL}, {ai_charge, 1, NULL}, {ai_charge, -2, chick_reslash} }; mmove_t chick_move_slash = { FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL }; static mframe_t chick_frames_end_slash[] = { {ai_charge, -6, NULL}, {ai_charge, -1, NULL}, {ai_charge, -6, NULL}, {ai_charge, 0, chick_footstep} }; mmove_t chick_move_end_slash = { FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run }; void chick_reslash(edict_t *self) { if (!self) { return; } if (self->enemy->health > 0) { if (range(self, self->enemy) == RANGE_MELEE) { if (random() <= 0.9) { self->monsterinfo.currentmove = &chick_move_slash; return; } else { self->monsterinfo.currentmove = &chick_move_end_slash; return; } } } self->monsterinfo.currentmove = &chick_move_end_slash; } void chick_slash(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &chick_move_slash; } static mframe_t chick_frames_start_slash[] = { {ai_charge, 1, NULL}, {ai_charge, 8, NULL}, {ai_charge, 3, chick_footstep} }; mmove_t chick_move_start_slash = { FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash }; void chick_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &chick_move_start_slash; } void chick_attack(edict_t *self) { float r, chance; if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.attack_state == AS_BLIND) { /* setup shot probabilities */ if (self->monsterinfo.blind_fire_delay < 1.0) { chance = 1.0; } else if (self->monsterinfo.blind_fire_delay < 7.5) { chance = 0.4; } else { chance = 0.1; } r = random(); /* minimum of 2 seconds, plus 0-3, after the shots are done */ self->monsterinfo.blind_fire_delay += 4.0 + 1.5 + random(); /* don't shoot at the origin */ if (VectorCompare(self->monsterinfo.blind_fire_target, vec3_origin)) { return; } /* don't shoot if the dice say not to */ if (r > chance) { return; } /* turn on manual steering to signal both manual steering and blindfire */ self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->monsterinfo.currentmove = &chick_move_start_attack1; self->monsterinfo.attack_finished = level.time + 2 * random(); return; } self->monsterinfo.currentmove = &chick_move_start_attack1; } void chick_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } qboolean chick_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } void chick_duck(edict_t *self, float eta) { if (!self) { return; } if ((self->monsterinfo.currentmove == &chick_move_start_attack1) || (self->monsterinfo.currentmove == &chick_move_attack1)) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value) { self->monsterinfo.aiflags &= ~AI_DUCKED; return; } } if (skill->value == SKILL_EASY) { /* stupid dodge */ self->monsterinfo.duck_wait_time = level.time + eta + 1; } else { self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } /* has to be done immediately otherwise she can get stuck */ monster_duck_down(self); self->monsterinfo.nextframe = FRAME_duck01; self->monsterinfo.currentmove = &chick_move_duck; return; } void chick_sidestep(edict_t *self) { if (!self) { return; } if ((self->monsterinfo.currentmove == &chick_move_start_attack1) || (self->monsterinfo.currentmove == &chick_move_attack1)) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DODGING; return; } } if (self->monsterinfo.currentmove != &chick_move_run) { self->monsterinfo.currentmove = &chick_move_run; } } /* * QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_chick(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_missile_prelaunch = gi.soundindex("chick/chkatck1.wav"); sound_missile_launch = gi.soundindex("chick/chkatck2.wav"); sound_melee_swing = gi.soundindex("chick/chkatck3.wav"); sound_melee_hit = gi.soundindex("chick/chkatck4.wav"); sound_missile_reload = gi.soundindex("chick/chkatck5.wav"); sound_death1 = gi.soundindex("chick/chkdeth1.wav"); sound_death2 = gi.soundindex("chick/chkdeth2.wav"); sound_fall_down = gi.soundindex("chick/chkfall1.wav"); sound_idle1 = gi.soundindex("chick/chkidle1.wav"); sound_idle2 = gi.soundindex("chick/chkidle2.wav"); sound_pain1 = gi.soundindex("chick/chkpain1.wav"); sound_pain2 = gi.soundindex("chick/chkpain2.wav"); sound_pain3 = gi.soundindex("chick/chkpain3.wav"); sound_sight = gi.soundindex("chick/chksght1.wav"); sound_search = gi.soundindex("chick/chksrch1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/bitch2/tris.md2"); VectorSet(self->mins, -16, -16, 0); VectorSet(self->maxs, 16, 16, 56); self->health = 175; self->gib_health = -70; self->mass = 200; self->pain = chick_pain; self->die = chick_die; self->monsterinfo.stand = chick_stand; self->monsterinfo.walk = chick_walk; self->monsterinfo.run = chick_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.duck = chick_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.sidestep = chick_sidestep; self->monsterinfo.attack = chick_attack; self->monsterinfo.melee = chick_melee; self->monsterinfo.sight = chick_sight; self->monsterinfo.blocked = chick_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &chick_move_stand; self->monsterinfo.scale = MODEL_SCALE; self->monsterinfo.blindfire = true; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/chick/chick.h000066400000000000000000000237171477320066100204130ustar00rootroot00000000000000/* ======================================================================= * * Iron Maiden animations. * * ======================================================================= */ #define FRAME_attak101 0 #define FRAME_attak102 1 #define FRAME_attak103 2 #define FRAME_attak104 3 #define FRAME_attak105 4 #define FRAME_attak106 5 #define FRAME_attak107 6 #define FRAME_attak108 7 #define FRAME_attak109 8 #define FRAME_attak110 9 #define FRAME_attak111 10 #define FRAME_attak112 11 #define FRAME_attak113 12 #define FRAME_attak114 13 #define FRAME_attak115 14 #define FRAME_attak116 15 #define FRAME_attak117 16 #define FRAME_attak118 17 #define FRAME_attak119 18 #define FRAME_attak120 19 #define FRAME_attak121 20 #define FRAME_attak122 21 #define FRAME_attak123 22 #define FRAME_attak124 23 #define FRAME_attak125 24 #define FRAME_attak126 25 #define FRAME_attak127 26 #define FRAME_attak128 27 #define FRAME_attak129 28 #define FRAME_attak130 29 #define FRAME_attak131 30 #define FRAME_attak132 31 #define FRAME_attak201 32 #define FRAME_attak202 33 #define FRAME_attak203 34 #define FRAME_attak204 35 #define FRAME_attak205 36 #define FRAME_attak206 37 #define FRAME_attak207 38 #define FRAME_attak208 39 #define FRAME_attak209 40 #define FRAME_attak210 41 #define FRAME_attak211 42 #define FRAME_attak212 43 #define FRAME_attak213 44 #define FRAME_attak214 45 #define FRAME_attak215 46 #define FRAME_attak216 47 #define FRAME_death101 48 #define FRAME_death102 49 #define FRAME_death103 50 #define FRAME_death104 51 #define FRAME_death105 52 #define FRAME_death106 53 #define FRAME_death107 54 #define FRAME_death108 55 #define FRAME_death109 56 #define FRAME_death110 57 #define FRAME_death111 58 #define FRAME_death112 59 #define FRAME_death201 60 #define FRAME_death202 61 #define FRAME_death203 62 #define FRAME_death204 63 #define FRAME_death205 64 #define FRAME_death206 65 #define FRAME_death207 66 #define FRAME_death208 67 #define FRAME_death209 68 #define FRAME_death210 69 #define FRAME_death211 70 #define FRAME_death212 71 #define FRAME_death213 72 #define FRAME_death214 73 #define FRAME_death215 74 #define FRAME_death216 75 #define FRAME_death217 76 #define FRAME_death218 77 #define FRAME_death219 78 #define FRAME_death220 79 #define FRAME_death221 80 #define FRAME_death222 81 #define FRAME_death223 82 #define FRAME_duck01 83 #define FRAME_duck02 84 #define FRAME_duck03 85 #define FRAME_duck04 86 #define FRAME_duck05 87 #define FRAME_duck06 88 #define FRAME_duck07 89 #define FRAME_pain101 90 #define FRAME_pain102 91 #define FRAME_pain103 92 #define FRAME_pain104 93 #define FRAME_pain105 94 #define FRAME_pain201 95 #define FRAME_pain202 96 #define FRAME_pain203 97 #define FRAME_pain204 98 #define FRAME_pain205 99 #define FRAME_pain301 100 #define FRAME_pain302 101 #define FRAME_pain303 102 #define FRAME_pain304 103 #define FRAME_pain305 104 #define FRAME_pain306 105 #define FRAME_pain307 106 #define FRAME_pain308 107 #define FRAME_pain309 108 #define FRAME_pain310 109 #define FRAME_pain311 110 #define FRAME_pain312 111 #define FRAME_pain313 112 #define FRAME_pain314 113 #define FRAME_pain315 114 #define FRAME_pain316 115 #define FRAME_pain317 116 #define FRAME_pain318 117 #define FRAME_pain319 118 #define FRAME_pain320 119 #define FRAME_pain321 120 #define FRAME_stand101 121 #define FRAME_stand102 122 #define FRAME_stand103 123 #define FRAME_stand104 124 #define FRAME_stand105 125 #define FRAME_stand106 126 #define FRAME_stand107 127 #define FRAME_stand108 128 #define FRAME_stand109 129 #define FRAME_stand110 130 #define FRAME_stand111 131 #define FRAME_stand112 132 #define FRAME_stand113 133 #define FRAME_stand114 134 #define FRAME_stand115 135 #define FRAME_stand116 136 #define FRAME_stand117 137 #define FRAME_stand118 138 #define FRAME_stand119 139 #define FRAME_stand120 140 #define FRAME_stand121 141 #define FRAME_stand122 142 #define FRAME_stand123 143 #define FRAME_stand124 144 #define FRAME_stand125 145 #define FRAME_stand126 146 #define FRAME_stand127 147 #define FRAME_stand128 148 #define FRAME_stand129 149 #define FRAME_stand130 150 #define FRAME_stand201 151 #define FRAME_stand202 152 #define FRAME_stand203 153 #define FRAME_stand204 154 #define FRAME_stand205 155 #define FRAME_stand206 156 #define FRAME_stand207 157 #define FRAME_stand208 158 #define FRAME_stand209 159 #define FRAME_stand210 160 #define FRAME_stand211 161 #define FRAME_stand212 162 #define FRAME_stand213 163 #define FRAME_stand214 164 #define FRAME_stand215 165 #define FRAME_stand216 166 #define FRAME_stand217 167 #define FRAME_stand218 168 #define FRAME_stand219 169 #define FRAME_stand220 170 #define FRAME_stand221 171 #define FRAME_stand222 172 #define FRAME_stand223 173 #define FRAME_stand224 174 #define FRAME_stand225 175 #define FRAME_stand226 176 #define FRAME_stand227 177 #define FRAME_stand228 178 #define FRAME_stand229 179 #define FRAME_stand230 180 #define FRAME_walk01 181 #define FRAME_walk02 182 #define FRAME_walk03 183 #define FRAME_walk04 184 #define FRAME_walk05 185 #define FRAME_walk06 186 #define FRAME_walk07 187 #define FRAME_walk08 188 #define FRAME_walk09 189 #define FRAME_walk10 190 #define FRAME_walk11 191 #define FRAME_walk12 192 #define FRAME_walk13 193 #define FRAME_walk14 194 #define FRAME_walk15 195 #define FRAME_walk16 196 #define FRAME_walk17 197 #define FRAME_walk18 198 #define FRAME_walk19 199 #define FRAME_walk20 200 #define FRAME_walk21 201 #define FRAME_walk22 202 #define FRAME_walk23 203 #define FRAME_walk24 204 #define FRAME_walk25 205 #define FRAME_walk26 206 #define FRAME_walk27 207 #define FRAME_recln201 208 #define FRAME_recln202 209 #define FRAME_recln203 210 #define FRAME_recln204 211 #define FRAME_recln205 212 #define FRAME_recln206 213 #define FRAME_recln207 214 #define FRAME_recln208 215 #define FRAME_recln209 216 #define FRAME_recln210 217 #define FRAME_recln211 218 #define FRAME_recln212 219 #define FRAME_recln213 220 #define FRAME_recln214 221 #define FRAME_recln215 222 #define FRAME_recln216 223 #define FRAME_recln217 224 #define FRAME_recln218 225 #define FRAME_recln219 226 #define FRAME_recln220 227 #define FRAME_recln221 228 #define FRAME_recln222 229 #define FRAME_recln223 230 #define FRAME_recln224 231 #define FRAME_recln225 232 #define FRAME_recln226 233 #define FRAME_recln227 234 #define FRAME_recln228 235 #define FRAME_recln229 236 #define FRAME_recln230 237 #define FRAME_recln231 238 #define FRAME_recln232 239 #define FRAME_recln233 240 #define FRAME_recln234 241 #define FRAME_recln235 242 #define FRAME_recln236 243 #define FRAME_recln237 244 #define FRAME_recln238 245 #define FRAME_recln239 246 #define FRAME_recln240 247 #define FRAME_recln101 248 #define FRAME_recln102 249 #define FRAME_recln103 250 #define FRAME_recln104 251 #define FRAME_recln105 252 #define FRAME_recln106 253 #define FRAME_recln107 254 #define FRAME_recln108 255 #define FRAME_recln109 256 #define FRAME_recln110 257 #define FRAME_recln111 258 #define FRAME_recln112 259 #define FRAME_recln113 260 #define FRAME_recln114 261 #define FRAME_recln115 262 #define FRAME_recln116 263 #define FRAME_recln117 264 #define FRAME_recln118 265 #define FRAME_recln119 266 #define FRAME_recln120 267 #define FRAME_recln121 268 #define FRAME_recln122 269 #define FRAME_recln123 270 #define FRAME_recln124 271 #define FRAME_recln125 272 #define FRAME_recln126 273 #define FRAME_recln127 274 #define FRAME_recln128 275 #define FRAME_recln129 276 #define FRAME_recln130 277 #define FRAME_recln131 278 #define FRAME_recln132 279 #define FRAME_recln133 280 #define FRAME_recln134 281 #define FRAME_recln135 282 #define FRAME_recln136 283 #define FRAME_recln137 284 #define FRAME_recln138 285 #define FRAME_recln139 286 #define FRAME_recln140 287 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/flipper/000077500000000000000000000000001477320066100175275ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/flipper/flipper.c000066400000000000000000000236371477320066100213470ustar00rootroot00000000000000/* ======================================================================= * * Baracuda Shark. * * ======================================================================= */ #include "../../header/local.h" #include "flipper.h" #define FLIPPER_RUN_SPEED 24 static int sound_chomp; static int sound_attack; static int sound_pain1; static int sound_pain2; static int sound_death; static int sound_idle; static int sound_search; static int sound_sight; void flipper_stand(edict_t *self); static mframe_t flipper_frames_stand[] = { {ai_stand, 0, NULL} }; mmove_t flipper_move_stand = { FRAME_flphor01, FRAME_flphor01, flipper_frames_stand, NULL }; void flipper_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_stand; } static mframe_t flipper_frames_run[] = { {ai_run, FLIPPER_RUN_SPEED, NULL}, /* 6 */ {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, /* 10 */ {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, /* 20 */ {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL}, {ai_run, FLIPPER_RUN_SPEED, NULL} /* 29 */ }; mmove_t flipper_move_run_loop = { FRAME_flpver06, FRAME_flpver29, flipper_frames_run, NULL }; void flipper_run_loop(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_run_loop; } static mframe_t flipper_frames_run_start[] = { {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL} }; mmove_t flipper_move_run_start = { FRAME_flpver01, FRAME_flpver06, flipper_frames_run_start, flipper_run_loop }; void flipper_run(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_run_start; } /* Standard Swimming */ static mframe_t flipper_frames_walk[] = { {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL} }; mmove_t flipper_move_walk = { FRAME_flphor01, FRAME_flphor24, flipper_frames_walk, NULL }; void flipper_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_walk; } static mframe_t flipper_frames_start_run[] = { {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, NULL}, {ai_run, 8, flipper_run} }; mmove_t flipper_move_start_run = { FRAME_flphor01, FRAME_flphor05, flipper_frames_start_run, NULL }; void flipper_start_run(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_start_run; } static mframe_t flipper_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flipper_move_pain2 = { FRAME_flppn101, FRAME_flppn105, flipper_frames_pain2, flipper_run }; static mframe_t flipper_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flipper_move_pain1 = { FRAME_flppn201, FRAME_flppn205, flipper_frames_pain1, flipper_run }; void flipper_bite(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, 0, 0); fire_hit(self, aim, 5, 0); } void flipper_preattack(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0); } static mframe_t flipper_frames_attack[] = { {ai_charge, 0, flipper_preattack}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, flipper_bite}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, flipper_bite}, {ai_charge, 0, NULL} }; mmove_t flipper_move_attack = { FRAME_flpbit01, FRAME_flpbit20, flipper_frames_attack, flipper_run }; void flipper_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flipper_move_attack; } void flipper_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { int n; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } n = (rand() + 1) % 2; if (n == 0) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &flipper_move_pain1; } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &flipper_move_pain2; } } void flipper_dead(edict_t *self) { vec3_t p; trace_t tr; if (!self) { return; } /* original dead bbox was wrong - and make sure the bbox adjustment stays in solidity */ p[0] = self->s.origin[0]; p[1] = self->s.origin[1]; p[2] = self->s.origin[2] - 8; tr = gi.trace(self->s.origin, self->mins, self->maxs, p, self, self->clipmask); self->mins[2] = tr.endpos[2] - self->s.origin[2]; self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t flipper_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flipper_move_death = { FRAME_flpdth01, FRAME_flpdth56, flipper_frames_death, flipper_dead }; void flipper_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void flipper_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &flipper_move_death; } /* * QUAKED monster_flipper (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_flipper(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("flipper/flppain1.wav"); sound_pain2 = gi.soundindex("flipper/flppain2.wav"); sound_death = gi.soundindex("flipper/flpdeth1.wav"); sound_chomp = gi.soundindex("flipper/flpatck1.wav"); sound_attack = gi.soundindex("flipper/flpatck2.wav"); sound_idle = gi.soundindex("flipper/flpidle1.wav"); sound_search = gi.soundindex("flipper/flpsrch1.wav"); sound_sight = gi.soundindex("flipper/flpsght1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/flipper/tris.md2"); VectorSet(self->mins, -16, -16, 0); VectorSet(self->maxs, 16, 16, 32); self->health = 50; self->gib_health = -30; self->mass = 100; self->pain = flipper_pain; self->die = flipper_die; self->monsterinfo.stand = flipper_stand; self->monsterinfo.walk = flipper_walk; self->monsterinfo.run = flipper_start_run; self->monsterinfo.melee = flipper_melee; self->monsterinfo.sight = flipper_sight; gi.linkentity(self); self->monsterinfo.currentmove = &flipper_move_stand; self->monsterinfo.scale = MODEL_SCALE; swimmonster_start(self); } rogue-ROGUE_2_13/src/monster/flipper/flipper.h000066400000000000000000000131231477320066100213410ustar00rootroot00000000000000/* ======================================================================= * * Baracuda Shark animations. * * ======================================================================= */ #define FRAME_flpbit01 0 #define FRAME_flpbit02 1 #define FRAME_flpbit03 2 #define FRAME_flpbit04 3 #define FRAME_flpbit05 4 #define FRAME_flpbit06 5 #define FRAME_flpbit07 6 #define FRAME_flpbit08 7 #define FRAME_flpbit09 8 #define FRAME_flpbit10 9 #define FRAME_flpbit11 10 #define FRAME_flpbit12 11 #define FRAME_flpbit13 12 #define FRAME_flpbit14 13 #define FRAME_flpbit15 14 #define FRAME_flpbit16 15 #define FRAME_flpbit17 16 #define FRAME_flpbit18 17 #define FRAME_flpbit19 18 #define FRAME_flpbit20 19 #define FRAME_flptal01 20 #define FRAME_flptal02 21 #define FRAME_flptal03 22 #define FRAME_flptal04 23 #define FRAME_flptal05 24 #define FRAME_flptal06 25 #define FRAME_flptal07 26 #define FRAME_flptal08 27 #define FRAME_flptal09 28 #define FRAME_flptal10 29 #define FRAME_flptal11 30 #define FRAME_flptal12 31 #define FRAME_flptal13 32 #define FRAME_flptal14 33 #define FRAME_flptal15 34 #define FRAME_flptal16 35 #define FRAME_flptal17 36 #define FRAME_flptal18 37 #define FRAME_flptal19 38 #define FRAME_flptal20 39 #define FRAME_flptal21 40 #define FRAME_flphor01 41 #define FRAME_flphor02 42 #define FRAME_flphor03 43 #define FRAME_flphor04 44 #define FRAME_flphor05 45 #define FRAME_flphor06 46 #define FRAME_flphor07 47 #define FRAME_flphor08 48 #define FRAME_flphor09 49 #define FRAME_flphor10 50 #define FRAME_flphor11 51 #define FRAME_flphor12 52 #define FRAME_flphor13 53 #define FRAME_flphor14 54 #define FRAME_flphor15 55 #define FRAME_flphor16 56 #define FRAME_flphor17 57 #define FRAME_flphor18 58 #define FRAME_flphor19 59 #define FRAME_flphor20 60 #define FRAME_flphor21 61 #define FRAME_flphor22 62 #define FRAME_flphor23 63 #define FRAME_flphor24 64 #define FRAME_flpver01 65 #define FRAME_flpver02 66 #define FRAME_flpver03 67 #define FRAME_flpver04 68 #define FRAME_flpver05 69 #define FRAME_flpver06 70 #define FRAME_flpver07 71 #define FRAME_flpver08 72 #define FRAME_flpver09 73 #define FRAME_flpver10 74 #define FRAME_flpver11 75 #define FRAME_flpver12 76 #define FRAME_flpver13 77 #define FRAME_flpver14 78 #define FRAME_flpver15 79 #define FRAME_flpver16 80 #define FRAME_flpver17 81 #define FRAME_flpver18 82 #define FRAME_flpver19 83 #define FRAME_flpver20 84 #define FRAME_flpver21 85 #define FRAME_flpver22 86 #define FRAME_flpver23 87 #define FRAME_flpver24 88 #define FRAME_flpver25 89 #define FRAME_flpver26 90 #define FRAME_flpver27 91 #define FRAME_flpver28 92 #define FRAME_flpver29 93 #define FRAME_flppn101 94 #define FRAME_flppn102 95 #define FRAME_flppn103 96 #define FRAME_flppn104 97 #define FRAME_flppn105 98 #define FRAME_flppn201 99 #define FRAME_flppn202 100 #define FRAME_flppn203 101 #define FRAME_flppn204 102 #define FRAME_flppn205 103 #define FRAME_flpdth01 104 #define FRAME_flpdth02 105 #define FRAME_flpdth03 106 #define FRAME_flpdth04 107 #define FRAME_flpdth05 108 #define FRAME_flpdth06 109 #define FRAME_flpdth07 110 #define FRAME_flpdth08 111 #define FRAME_flpdth09 112 #define FRAME_flpdth10 113 #define FRAME_flpdth11 114 #define FRAME_flpdth12 115 #define FRAME_flpdth13 116 #define FRAME_flpdth14 117 #define FRAME_flpdth15 118 #define FRAME_flpdth16 119 #define FRAME_flpdth17 120 #define FRAME_flpdth18 121 #define FRAME_flpdth19 122 #define FRAME_flpdth20 123 #define FRAME_flpdth21 124 #define FRAME_flpdth22 125 #define FRAME_flpdth23 126 #define FRAME_flpdth24 127 #define FRAME_flpdth25 128 #define FRAME_flpdth26 129 #define FRAME_flpdth27 130 #define FRAME_flpdth28 131 #define FRAME_flpdth29 132 #define FRAME_flpdth30 133 #define FRAME_flpdth31 134 #define FRAME_flpdth32 135 #define FRAME_flpdth33 136 #define FRAME_flpdth34 137 #define FRAME_flpdth35 138 #define FRAME_flpdth36 139 #define FRAME_flpdth37 140 #define FRAME_flpdth38 141 #define FRAME_flpdth39 142 #define FRAME_flpdth40 143 #define FRAME_flpdth41 144 #define FRAME_flpdth42 145 #define FRAME_flpdth43 146 #define FRAME_flpdth44 147 #define FRAME_flpdth45 148 #define FRAME_flpdth46 149 #define FRAME_flpdth47 150 #define FRAME_flpdth48 151 #define FRAME_flpdth49 152 #define FRAME_flpdth50 153 #define FRAME_flpdth51 154 #define FRAME_flpdth52 155 #define FRAME_flpdth53 156 #define FRAME_flpdth54 157 #define FRAME_flpdth55 158 #define FRAME_flpdth56 159 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/float/000077500000000000000000000000001477320066100171735ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/float/float.c000066400000000000000000000423731477320066100204550ustar00rootroot00000000000000/* ======================================================================= * * Mechanic. * * ======================================================================= */ #include "../../header/local.h" #include "float.h" static int sound_attack2; static int sound_attack3; static int sound_death1; static int sound_idle; static int sound_pain1; static int sound_pain2; static int sound_sight; void floater_dead(edict_t *self); void floater_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void floater_run(edict_t *self); void floater_wham(edict_t *self); void floater_zap(edict_t *self); void floater_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void floater_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } void floater_fire_blaster(edict_t *self) { vec3_t start; vec3_t forward, right; vec3_t end; vec3_t dir; int effect; if (!self || !self->enemy || !self->enemy->inuse) { return; } if ((self->s.frame == FRAME_attak104) || (self->s.frame == FRAME_attak107)) { effect = EF_HYPERBLASTER; } else { effect = 0; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_FLOAT_BLASTER_1], forward, right, start); VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, dir); monster_fire_blaster(self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1, effect); } static mframe_t floater_frames_stand1[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t floater_move_stand1 = { FRAME_stand101, FRAME_stand152, floater_frames_stand1, NULL }; static mframe_t floater_frames_stand2[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t floater_move_stand2 = { FRAME_stand201, FRAME_stand252, floater_frames_stand2, NULL }; void floater_stand(edict_t *self) { if (!self) { return; } if (random() <= 0.5) { self->monsterinfo.currentmove = &floater_move_stand1; } else { self->monsterinfo.currentmove = &floater_move_stand2; } } static mframe_t floater_frames_activate[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t floater_move_activate = { FRAME_actvat01, FRAME_actvat31, floater_frames_activate, NULL }; static mframe_t floater_frames_attack1[] = { {ai_charge, 0, NULL}, /* Blaster attack */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, floater_fire_blaster}, /* BOOM (0, -25.8, 32.5) -- LOOP Starts */ {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, floater_fire_blaster}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} /* -- LOOP Ends */ }; mmove_t floater_move_attack1 = { FRAME_attak101, FRAME_attak114, floater_frames_attack1, floater_run }; /* circle strafe frames */ static mframe_t floater_frames_attack1a[] = { {ai_charge, 10, NULL}, // Blaster attack {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, floater_fire_blaster}, // BOOM (0, -25.8, 32.5) -- LOOP Starts {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, floater_fire_blaster}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL} // -- LOOP Ends }; mmove_t floater_move_attack1a = { FRAME_attak101, FRAME_attak114, floater_frames_attack1a, floater_run }; static mframe_t floater_frames_attack2[] = { {ai_charge, 0, NULL}, /* Claws */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, floater_wham}, /* WHAM (0, -45, 29}.6) -- LOOP Starts */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* -- LOOP Ends */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t floater_move_attack2 = { FRAME_attak201, FRAME_attak225, floater_frames_attack2, floater_run }; static mframe_t floater_frames_attack3[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, floater_zap}, /* -- LOOP Starts */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* -- LOOP Ends */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t floater_move_attack3 = { FRAME_attak301, FRAME_attak334, floater_frames_attack3, floater_run }; static mframe_t floater_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t floater_move_death = { FRAME_death01, FRAME_death13, floater_frames_death, floater_dead }; static mframe_t floater_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t floater_move_pain1 = { FRAME_pain101, FRAME_pain107, floater_frames_pain1, floater_run }; static mframe_t floater_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t floater_move_pain2 = { FRAME_pain201, FRAME_pain208, floater_frames_pain2, floater_run }; static mframe_t floater_frames_pain3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t floater_move_pain3 = { FRAME_pain301, FRAME_pain312, floater_frames_pain3, floater_run }; static mframe_t floater_frames_walk[] = { {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL} }; mmove_t floater_move_walk = { FRAME_stand101, FRAME_stand152, floater_frames_walk, NULL }; static mframe_t floater_frames_run[] = { {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL}, {ai_run, 13, NULL} }; mmove_t floater_move_run = { FRAME_stand101, FRAME_stand152, floater_frames_run, NULL }; void floater_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &floater_move_stand1; } else { self->monsterinfo.currentmove = &floater_move_run; } } void floater_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &floater_move_walk; } void floater_wham(edict_t *self) { static vec3_t aim = {MELEE_DISTANCE, 0, 0}; if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_attack3, 1, ATTN_NORM, 0); fire_hit(self, aim, 5 + rand() % 6, -50); } void floater_zap(edict_t *self) { vec3_t forward, right; vec3_t origin; vec3_t dir; vec3_t offset; if (!self) { return; } VectorSubtract(self->enemy->s.origin, self->s.origin, dir); AngleVectors(self->s.angles, forward, right, NULL); VectorSet(offset, 18.5, -0.9, 10); G_ProjectSource(self->s.origin, offset, forward, right, origin); gi.sound(self, CHAN_WEAPON, sound_attack2, 1, ATTN_NORM, 0); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_SPLASH); gi.WriteByte(32); gi.WritePosition(origin); gi.WriteDir(dir); gi.WriteByte(1); /* sparks */ gi.multicast(origin, MULTICAST_PVS); if (range(self, self->enemy) == RANGE_MELEE && infront(self, self->enemy) && visible(self, self->enemy)) { T_Damage(self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, 5 + rand() % 6, -10, DAMAGE_ENERGY, MOD_UNKNOWN); } } void floater_attack(edict_t *self) { float chance; if (!self) { return; } // 0% chance of circle in easy // 50% chance in normal // 75% chance in hard // 86.67% chance in nightmare if (skill->value == SKILL_EASY) { chance = 0; } else { chance = 1.0 - (0.5/(float)(skill->value)); } if (random() > chance) { self->monsterinfo.attack_state = AS_STRAIGHT; self->monsterinfo.currentmove = &floater_move_attack1; } else // circle strafe { if (random () <= 0.5) // switch directions { self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; } self->monsterinfo.attack_state = AS_SLIDING; self->monsterinfo.currentmove = &floater_move_attack1a; } } void floater_melee(edict_t *self) { if (!self) { return; } if (random() < 0.5) { self->monsterinfo.currentmove = &floater_move_attack3; } else { self->monsterinfo.currentmove = &floater_move_attack2; } } void floater_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { int n; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } n = (rand() + 1) % 3; if (n == 0) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &floater_move_pain1; } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &floater_move_pain2; } } void floater_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void floater_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); BecomeExplosion1(self); } qboolean floater_blocked(edict_t *self, float dist) { return false; } /* * QUAKED monster_floater (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_floater(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_attack2 = gi.soundindex("floater/fltatck2.wav"); sound_attack3 = gi.soundindex("floater/fltatck3.wav"); sound_death1 = gi.soundindex("floater/fltdeth1.wav"); sound_idle = gi.soundindex("floater/fltidle1.wav"); sound_pain1 = gi.soundindex("floater/fltpain1.wav"); sound_pain2 = gi.soundindex("floater/fltpain2.wav"); sound_sight = gi.soundindex("floater/fltsght1.wav"); gi.soundindex("floater/fltatck1.wav"); self->s.sound = gi.soundindex("floater/fltsrch1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/float/tris.md2"); VectorSet(self->mins, -24, -24, -24); VectorSet(self->maxs, 24, 24, 32); self->health = 200; self->gib_health = -80; self->mass = 300; self->pain = floater_pain; self->die = floater_die; self->monsterinfo.stand = floater_stand; self->monsterinfo.walk = floater_walk; self->monsterinfo.run = floater_run; self->monsterinfo.attack = floater_attack; self->monsterinfo.melee = floater_melee; self->monsterinfo.sight = floater_sight; self->monsterinfo.idle = floater_idle; self->monsterinfo.blocked = floater_blocked; gi.linkentity(self); if (random() <= 0.5) { self->monsterinfo.currentmove = &floater_move_stand1; } else { self->monsterinfo.currentmove = &floater_move_stand2; } self->monsterinfo.scale = MODEL_SCALE; flymonster_start(self); } rogue-ROGUE_2_13/src/monster/float/float.h000066400000000000000000000211241477320066100204510ustar00rootroot00000000000000/* ======================================================================= * * Mechanic animations. * * ======================================================================= */ #define FRAME_actvat01 0 #define FRAME_actvat02 1 #define FRAME_actvat03 2 #define FRAME_actvat04 3 #define FRAME_actvat05 4 #define FRAME_actvat06 5 #define FRAME_actvat07 6 #define FRAME_actvat08 7 #define FRAME_actvat09 8 #define FRAME_actvat10 9 #define FRAME_actvat11 10 #define FRAME_actvat12 11 #define FRAME_actvat13 12 #define FRAME_actvat14 13 #define FRAME_actvat15 14 #define FRAME_actvat16 15 #define FRAME_actvat17 16 #define FRAME_actvat18 17 #define FRAME_actvat19 18 #define FRAME_actvat20 19 #define FRAME_actvat21 20 #define FRAME_actvat22 21 #define FRAME_actvat23 22 #define FRAME_actvat24 23 #define FRAME_actvat25 24 #define FRAME_actvat26 25 #define FRAME_actvat27 26 #define FRAME_actvat28 27 #define FRAME_actvat29 28 #define FRAME_actvat30 29 #define FRAME_actvat31 30 #define FRAME_attak101 31 #define FRAME_attak102 32 #define FRAME_attak103 33 #define FRAME_attak104 34 #define FRAME_attak105 35 #define FRAME_attak106 36 #define FRAME_attak107 37 #define FRAME_attak108 38 #define FRAME_attak109 39 #define FRAME_attak110 40 #define FRAME_attak111 41 #define FRAME_attak112 42 #define FRAME_attak113 43 #define FRAME_attak114 44 #define FRAME_attak201 45 #define FRAME_attak202 46 #define FRAME_attak203 47 #define FRAME_attak204 48 #define FRAME_attak205 49 #define FRAME_attak206 50 #define FRAME_attak207 51 #define FRAME_attak208 52 #define FRAME_attak209 53 #define FRAME_attak210 54 #define FRAME_attak211 55 #define FRAME_attak212 56 #define FRAME_attak213 57 #define FRAME_attak214 58 #define FRAME_attak215 59 #define FRAME_attak216 60 #define FRAME_attak217 61 #define FRAME_attak218 62 #define FRAME_attak219 63 #define FRAME_attak220 64 #define FRAME_attak221 65 #define FRAME_attak222 66 #define FRAME_attak223 67 #define FRAME_attak224 68 #define FRAME_attak225 69 #define FRAME_attak301 70 #define FRAME_attak302 71 #define FRAME_attak303 72 #define FRAME_attak304 73 #define FRAME_attak305 74 #define FRAME_attak306 75 #define FRAME_attak307 76 #define FRAME_attak308 77 #define FRAME_attak309 78 #define FRAME_attak310 79 #define FRAME_attak311 80 #define FRAME_attak312 81 #define FRAME_attak313 82 #define FRAME_attak314 83 #define FRAME_attak315 84 #define FRAME_attak316 85 #define FRAME_attak317 86 #define FRAME_attak318 87 #define FRAME_attak319 88 #define FRAME_attak320 89 #define FRAME_attak321 90 #define FRAME_attak322 91 #define FRAME_attak323 92 #define FRAME_attak324 93 #define FRAME_attak325 94 #define FRAME_attak326 95 #define FRAME_attak327 96 #define FRAME_attak328 97 #define FRAME_attak329 98 #define FRAME_attak330 99 #define FRAME_attak331 100 #define FRAME_attak332 101 #define FRAME_attak333 102 #define FRAME_attak334 103 #define FRAME_death01 104 #define FRAME_death02 105 #define FRAME_death03 106 #define FRAME_death04 107 #define FRAME_death05 108 #define FRAME_death06 109 #define FRAME_death07 110 #define FRAME_death08 111 #define FRAME_death09 112 #define FRAME_death10 113 #define FRAME_death11 114 #define FRAME_death12 115 #define FRAME_death13 116 #define FRAME_pain101 117 #define FRAME_pain102 118 #define FRAME_pain103 119 #define FRAME_pain104 120 #define FRAME_pain105 121 #define FRAME_pain106 122 #define FRAME_pain107 123 #define FRAME_pain201 124 #define FRAME_pain202 125 #define FRAME_pain203 126 #define FRAME_pain204 127 #define FRAME_pain205 128 #define FRAME_pain206 129 #define FRAME_pain207 130 #define FRAME_pain208 131 #define FRAME_pain301 132 #define FRAME_pain302 133 #define FRAME_pain303 134 #define FRAME_pain304 135 #define FRAME_pain305 136 #define FRAME_pain306 137 #define FRAME_pain307 138 #define FRAME_pain308 139 #define FRAME_pain309 140 #define FRAME_pain310 141 #define FRAME_pain311 142 #define FRAME_pain312 143 #define FRAME_stand101 144 #define FRAME_stand102 145 #define FRAME_stand103 146 #define FRAME_stand104 147 #define FRAME_stand105 148 #define FRAME_stand106 149 #define FRAME_stand107 150 #define FRAME_stand108 151 #define FRAME_stand109 152 #define FRAME_stand110 153 #define FRAME_stand111 154 #define FRAME_stand112 155 #define FRAME_stand113 156 #define FRAME_stand114 157 #define FRAME_stand115 158 #define FRAME_stand116 159 #define FRAME_stand117 160 #define FRAME_stand118 161 #define FRAME_stand119 162 #define FRAME_stand120 163 #define FRAME_stand121 164 #define FRAME_stand122 165 #define FRAME_stand123 166 #define FRAME_stand124 167 #define FRAME_stand125 168 #define FRAME_stand126 169 #define FRAME_stand127 170 #define FRAME_stand128 171 #define FRAME_stand129 172 #define FRAME_stand130 173 #define FRAME_stand131 174 #define FRAME_stand132 175 #define FRAME_stand133 176 #define FRAME_stand134 177 #define FRAME_stand135 178 #define FRAME_stand136 179 #define FRAME_stand137 180 #define FRAME_stand138 181 #define FRAME_stand139 182 #define FRAME_stand140 183 #define FRAME_stand141 184 #define FRAME_stand142 185 #define FRAME_stand143 186 #define FRAME_stand144 187 #define FRAME_stand145 188 #define FRAME_stand146 189 #define FRAME_stand147 190 #define FRAME_stand148 191 #define FRAME_stand149 192 #define FRAME_stand150 193 #define FRAME_stand151 194 #define FRAME_stand152 195 #define FRAME_stand201 196 #define FRAME_stand202 197 #define FRAME_stand203 198 #define FRAME_stand204 199 #define FRAME_stand205 200 #define FRAME_stand206 201 #define FRAME_stand207 202 #define FRAME_stand208 203 #define FRAME_stand209 204 #define FRAME_stand210 205 #define FRAME_stand211 206 #define FRAME_stand212 207 #define FRAME_stand213 208 #define FRAME_stand214 209 #define FRAME_stand215 210 #define FRAME_stand216 211 #define FRAME_stand217 212 #define FRAME_stand218 213 #define FRAME_stand219 214 #define FRAME_stand220 215 #define FRAME_stand221 216 #define FRAME_stand222 217 #define FRAME_stand223 218 #define FRAME_stand224 219 #define FRAME_stand225 220 #define FRAME_stand226 221 #define FRAME_stand227 222 #define FRAME_stand228 223 #define FRAME_stand229 224 #define FRAME_stand230 225 #define FRAME_stand231 226 #define FRAME_stand232 227 #define FRAME_stand233 228 #define FRAME_stand234 229 #define FRAME_stand235 230 #define FRAME_stand236 231 #define FRAME_stand237 232 #define FRAME_stand238 233 #define FRAME_stand239 234 #define FRAME_stand240 235 #define FRAME_stand241 236 #define FRAME_stand242 237 #define FRAME_stand243 238 #define FRAME_stand244 239 #define FRAME_stand245 240 #define FRAME_stand246 241 #define FRAME_stand247 242 #define FRAME_stand248 243 #define FRAME_stand249 244 #define FRAME_stand250 245 #define FRAME_stand251 246 #define FRAME_stand252 247 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/flyer/000077500000000000000000000000001477320066100172075ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/flyer/flyer.c000066400000000000000000000510731477320066100205020ustar00rootroot00000000000000/* ======================================================================= * * Flyer. * * ======================================================================= */ #include "../../header/local.h" #include "flyer.h" qboolean visible(edict_t *self, edict_t *other); static int nextmove; /* Used for start/stop frames */ static int sound_sight; static int sound_idle; static int sound_pain1; static int sound_pain2; static int sound_slash; static int sound_sproing; static int sound_die; void flyer_check_melee(edict_t *self); void flyer_loop_melee(edict_t *self); void flyer_melee(edict_t *self); void flyer_setstart(edict_t *self); void flyer_stand(edict_t *self); void flyer_nextmove(edict_t *self); void flyer_kamikaze(edict_t *self); void flyer_kamikaze_check(edict_t *self); void flyer_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void flyer_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void flyer_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } void flyer_pop_blades(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sproing, 1, ATTN_NORM, 0); } static mframe_t flyer_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t flyer_move_stand = { FRAME_stand01, FRAME_stand45, flyer_frames_stand, NULL }; static mframe_t flyer_frames_walk[] = { {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL} }; mmove_t flyer_move_walk = { FRAME_stand01, FRAME_stand45, flyer_frames_walk, NULL }; static mframe_t flyer_frames_run[] = { {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL} }; mmove_t flyer_move_run = { FRAME_stand01, FRAME_stand45, flyer_frames_run, NULL }; static mframe_t flyer_frames_kamizake[] = { {ai_charge, 40, flyer_kamikaze_check}, {ai_charge, 40, flyer_kamikaze_check}, {ai_charge, 40, flyer_kamikaze_check}, {ai_charge, 40, flyer_kamikaze_check}, {ai_charge, 40, flyer_kamikaze_check} }; mmove_t flyer_move_kamikaze = { FRAME_rollr02, FRAME_rollr06, flyer_frames_kamizake, flyer_kamikaze }; void flyer_run(edict_t *self) { if (!self) { return; } if (self->mass > 50) { self->monsterinfo.currentmove = &flyer_move_kamikaze; } else if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &flyer_move_stand; } else { self->monsterinfo.currentmove = &flyer_move_run; } } void flyer_walk(edict_t *self) { if (!self) { return; } if (self->mass > 50) { flyer_run(self); } else { self->monsterinfo.currentmove = &flyer_move_walk; } } void flyer_stand(edict_t *self) { if (!self) { return; } if (self->mass > 50) { flyer_run(self); } else { self->monsterinfo.currentmove = &flyer_move_stand; } } void flyer_kamikaze_explode(edict_t *self) { vec3_t dir; if (!self) { return; } if (self->monsterinfo.commander && self->monsterinfo.commander->inuse && !strcmp(self->monsterinfo.commander->classname, "monster_carrier")) { self->monsterinfo.commander->monsterinfo.monster_slots++; } if (self->enemy) { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); T_Damage(self->enemy, self, self, dir, self->s.origin, vec3_origin, (int)50, (int)50, DAMAGE_RADIUS, MOD_UNKNOWN); } flyer_die(self, NULL, NULL, 0, dir); } void flyer_kamikaze(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flyer_move_kamikaze; } void flyer_kamikaze_check(edict_t *self) { float dist; if (!self) { return; } /* this needed because we could have gone away before we get here (blocked code) */ if (!self->inuse) { return; } if ((!self->enemy) || (!self->enemy->inuse)) { flyer_kamikaze_explode(self); return; } self->goalentity = self->enemy; dist = realrange(self, self->enemy); if (dist < 90) { flyer_kamikaze_explode(self); } } static mframe_t flyer_frames_start[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, flyer_nextmove} }; mmove_t flyer_move_start = { FRAME_start01, FRAME_start06, flyer_frames_start, NULL }; static mframe_t flyer_frames_stop[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, flyer_nextmove} }; mmove_t flyer_move_stop = { FRAME_stop01, FRAME_stop07, flyer_frames_stop, NULL }; void flyer_stop(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flyer_move_stop; } void flyer_start(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flyer_move_start; } static mframe_t flyer_frames_rollright[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_rollright = { FRAME_rollr01, FRAME_rollr09, flyer_frames_rollright, NULL }; static mframe_t flyer_frames_rollleft[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_rollleft = { FRAME_rollf01, FRAME_rollf09, flyer_frames_rollleft, NULL }; static mframe_t flyer_frames_pain3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_pain3 = { FRAME_pain301, FRAME_pain304, flyer_frames_pain3, flyer_run }; static mframe_t flyer_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_pain2 = { FRAME_pain201, FRAME_pain204, flyer_frames_pain2, flyer_run }; static mframe_t flyer_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_pain1 = { FRAME_pain101, FRAME_pain109, flyer_frames_pain1, flyer_run }; static mframe_t flyer_frames_defense[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* Hold this frame */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_defense = { FRAME_defens01, FRAME_defens06, flyer_frames_defense, NULL }; static mframe_t flyer_frames_bankright[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_bankright = { FRAME_bankr01, FRAME_bankr07, flyer_frames_bankright, NULL }; static mframe_t flyer_frames_bankleft[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t flyer_move_bankleft = { FRAME_bankl01, FRAME_bankl07, flyer_frames_bankleft, NULL }; void flyer_fire(edict_t *self, int flash_number) { vec3_t start; vec3_t forward, right; vec3_t end; vec3_t dir; int effect; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } if ((self->s.frame == FRAME_attak204) || (self->s.frame == FRAME_attak207) || (self->s.frame == FRAME_attak210)) { effect = EF_HYPERBLASTER; } else { effect = 0; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, dir); monster_fire_blaster(self, start, dir, 1, 1000, flash_number, effect); } void flyer_fireleft(edict_t *self) { if (!self) { return; } flyer_fire(self, MZ2_FLYER_BLASTER_1); } void flyer_fireright(edict_t *self) { if (!self) { return; } flyer_fire(self, MZ2_FLYER_BLASTER_2); } static mframe_t flyer_frames_attack2[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, -10, flyer_fireleft}, /* left gun */ {ai_charge, -10, flyer_fireright}, /* right gun */ {ai_charge, -10, flyer_fireleft}, /* left gun */ {ai_charge, -10, flyer_fireright}, /* right gun */ {ai_charge, -10, flyer_fireleft}, /* left gun */ {ai_charge, -10, flyer_fireright}, /* right gun */ {ai_charge, -10, flyer_fireleft}, /* left gun */ {ai_charge, -10, flyer_fireright}, /* right gun */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t flyer_move_attack2 = { FRAME_attak201, FRAME_attak217, flyer_frames_attack2, flyer_run }; /* circle strafe frames */ static mframe_t flyer_frames_attack3[] = { {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, flyer_fireleft}, /* left gun */ {ai_charge, 10, flyer_fireright}, /* right gun */ {ai_charge, 10, flyer_fireleft}, /* left gun */ {ai_charge, 10, flyer_fireright}, /* right gun */ {ai_charge, 10, flyer_fireleft}, /* left gun */ {ai_charge, 10, flyer_fireright}, /* right gun */ {ai_charge, 10, flyer_fireleft}, /* left gun */ {ai_charge, 10, flyer_fireright}, /* right gun */ {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, NULL} }; mmove_t flyer_move_attack3 = { FRAME_attak201, FRAME_attak217, flyer_frames_attack3, flyer_run }; void flyer_slash_left(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], 0); fire_hit(self, aim, 5, 0); gi.sound(self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); } void flyer_slash_right(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->maxs[0], 0); fire_hit(self, aim, 5, 0); gi.sound(self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); } static mframe_t flyer_frames_start_melee[] = { {ai_charge, 0, flyer_pop_blades}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t flyer_move_start_melee = { FRAME_attak101, FRAME_attak106, flyer_frames_start_melee, flyer_loop_melee }; static mframe_t flyer_frames_end_melee[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t flyer_move_end_melee = { FRAME_attak119, FRAME_attak121, flyer_frames_end_melee, flyer_run }; static mframe_t flyer_frames_loop_melee[] = { {ai_charge, 0, NULL}, /* Loop Start */ {ai_charge, 0, NULL}, {ai_charge, 0, flyer_slash_left}, /* Left Wing Strike */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, flyer_slash_right}, /* Right Wing Strike */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} /* Loop Ends */ }; mmove_t flyer_move_loop_melee = { FRAME_attak107, FRAME_attak118, flyer_frames_loop_melee, flyer_check_melee }; void flyer_loop_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &flyer_move_loop_melee; } void flyer_attack(edict_t *self) { float chance; if (!self) { return; } if (self->mass > 50) { flyer_run(self); return; } if (skill->value == SKILL_EASY) { chance = 0; } else { chance = 1.0 - (0.5 / (float)(skill->value)); } if (random() > chance) { self->monsterinfo.attack_state = AS_STRAIGHT; self->monsterinfo.currentmove = &flyer_move_attack2; } else /* circle strafe */ { if (random() <= 0.5) /* switch directions */ { self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; } self->monsterinfo.attack_state = AS_SLIDING; self->monsterinfo.currentmove = &flyer_move_attack3; } } void flyer_setstart(edict_t *self) { if (!self) { return; } nextmove = ACTION_run; self->monsterinfo.currentmove = &flyer_move_start; } void flyer_nextmove(edict_t *self) { if (!self) { return; } if (nextmove == ACTION_attack1) { self->monsterinfo.currentmove = &flyer_move_start_melee; } else if (nextmove == ACTION_attack2) { self->monsterinfo.currentmove = &flyer_move_attack2; } else if (nextmove == ACTION_run) { self->monsterinfo.currentmove = &flyer_move_run; } } void flyer_melee(edict_t *self) { if (!self) { return; } if (self->mass > 50) { flyer_run(self); } else { self->monsterinfo.currentmove = &flyer_move_start_melee; } } void flyer_check_melee(edict_t *self) { if (!self) { return; } if (range(self, self->enemy) == RANGE_MELEE) { if (random() <= 0.8) { self->monsterinfo.currentmove = &flyer_move_loop_melee; } else { self->monsterinfo.currentmove = &flyer_move_end_melee; } } else { self->monsterinfo.currentmove = &flyer_move_end_melee; } } void flyer_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { int n; /* kamikaze's don't feel pain */ if (self->mass != 50) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } n = rand() % 3; if (n == 0) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &flyer_move_pain1; } else if (n == 1) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &flyer_move_pain2; } else { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &flyer_move_pain3; } } void flyer_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); BecomeExplosion1(self); } /* kamikaze code .. blow up if blocked */ int flyer_blocked(edict_t *self, float dist) { vec3_t origin; if (!self) { return 0; } /* kamikaze = 100, normal = 50 */ if (self->mass == 100) { flyer_kamikaze_check(self); /* if the above didn't blow us up (i.e. I got blocked by the player) */ if (self->inuse) { if (self->monsterinfo.commander && self->monsterinfo.commander->inuse && !strcmp(self->monsterinfo.commander->classname, "monster_carrier")) { self->monsterinfo.commander->monsterinfo.monster_slots++; } VectorMA(self->s.origin, -0.02, self->velocity, origin); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_ROCKET_EXPLOSION); gi.WritePosition(origin); gi.multicast(self->s.origin, MULTICAST_PHS); G_FreeEdict(self); } return true; } /* we're a normal flyer */ return false; } /* * QUAKED monster_flyer (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_flyer(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } /* fix a map bug in jail5.bsp */ if (!Q_stricmp(level.mapname, "jail5") && (self->s.origin[2] == -104)) { self->targetname = self->target; self->target = NULL; } sound_sight = gi.soundindex("flyer/flysght1.wav"); sound_idle = gi.soundindex("flyer/flysrch1.wav"); sound_pain1 = gi.soundindex("flyer/flypain1.wav"); sound_pain2 = gi.soundindex("flyer/flypain2.wav"); sound_slash = gi.soundindex("flyer/flyatck2.wav"); sound_sproing = gi.soundindex("flyer/flyatck1.wav"); sound_die = gi.soundindex("flyer/flydeth1.wav"); gi.soundindex("flyer/flyatck3.wav"); self->s.modelindex = gi.modelindex("models/monsters/flyer/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 16); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.sound = gi.soundindex("flyer/flyidle1.wav"); self->health = 50; self->mass = 50; self->pain = flyer_pain; self->die = flyer_die; self->monsterinfo.stand = flyer_stand; self->monsterinfo.walk = flyer_walk; self->monsterinfo.run = flyer_run; self->monsterinfo.attack = flyer_attack; self->monsterinfo.melee = flyer_melee; self->monsterinfo.sight = flyer_sight; self->monsterinfo.idle = flyer_idle; self->monsterinfo.blocked = (void *)flyer_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &flyer_move_stand; self->monsterinfo.scale = MODEL_SCALE; flymonster_start(self); } /* suicide fliers */ void SP_monster_kamikaze(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_sight = gi.soundindex("flyer/flysght1.wav"); sound_idle = gi.soundindex("flyer/flysrch1.wav"); sound_pain1 = gi.soundindex("flyer/flypain1.wav"); sound_pain2 = gi.soundindex("flyer/flypain2.wav"); sound_slash = gi.soundindex("flyer/flyatck2.wav"); sound_sproing = gi.soundindex("flyer/flyatck1.wav"); sound_die = gi.soundindex("flyer/flydeth1.wav"); gi.soundindex("flyer/flyatck3.wav"); self->s.modelindex = gi.modelindex("models/monsters/flyer/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 16); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.sound = gi.soundindex("flyer/flyidle1.wav"); self->s.effects |= EF_ROCKET; self->health = 50; self->mass = 100; self->pain = flyer_pain; self->die = flyer_die; self->monsterinfo.stand = flyer_stand; self->monsterinfo.walk = flyer_walk; self->monsterinfo.run = flyer_run; self->monsterinfo.attack = flyer_attack; self->monsterinfo.melee = flyer_melee; self->monsterinfo.sight = flyer_sight; self->monsterinfo.idle = flyer_idle; self->monsterinfo.blocked = (void *)flyer_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &flyer_move_stand; self->monsterinfo.scale = MODEL_SCALE; flymonster_start(self); } rogue-ROGUE_2_13/src/monster/flyer/flyer.h000066400000000000000000000126201477320066100205020ustar00rootroot00000000000000/* ======================================================================= * * Flyer animations. * * ======================================================================= */ #define ACTION_nothing 0 #define ACTION_attack1 1 #define ACTION_attack2 2 #define ACTION_run 3 #define ACTION_walk 4 #define FRAME_start01 0 #define FRAME_start02 1 #define FRAME_start03 2 #define FRAME_start04 3 #define FRAME_start05 4 #define FRAME_start06 5 #define FRAME_stop01 6 #define FRAME_stop02 7 #define FRAME_stop03 8 #define FRAME_stop04 9 #define FRAME_stop05 10 #define FRAME_stop06 11 #define FRAME_stop07 12 #define FRAME_stand01 13 #define FRAME_stand02 14 #define FRAME_stand03 15 #define FRAME_stand04 16 #define FRAME_stand05 17 #define FRAME_stand06 18 #define FRAME_stand07 19 #define FRAME_stand08 20 #define FRAME_stand09 21 #define FRAME_stand10 22 #define FRAME_stand11 23 #define FRAME_stand12 24 #define FRAME_stand13 25 #define FRAME_stand14 26 #define FRAME_stand15 27 #define FRAME_stand16 28 #define FRAME_stand17 29 #define FRAME_stand18 30 #define FRAME_stand19 31 #define FRAME_stand20 32 #define FRAME_stand21 33 #define FRAME_stand22 34 #define FRAME_stand23 35 #define FRAME_stand24 36 #define FRAME_stand25 37 #define FRAME_stand26 38 #define FRAME_stand27 39 #define FRAME_stand28 40 #define FRAME_stand29 41 #define FRAME_stand30 42 #define FRAME_stand31 43 #define FRAME_stand32 44 #define FRAME_stand33 45 #define FRAME_stand34 46 #define FRAME_stand35 47 #define FRAME_stand36 48 #define FRAME_stand37 49 #define FRAME_stand38 50 #define FRAME_stand39 51 #define FRAME_stand40 52 #define FRAME_stand41 53 #define FRAME_stand42 54 #define FRAME_stand43 55 #define FRAME_stand44 56 #define FRAME_stand45 57 #define FRAME_attak101 58 #define FRAME_attak102 59 #define FRAME_attak103 60 #define FRAME_attak104 61 #define FRAME_attak105 62 #define FRAME_attak106 63 #define FRAME_attak107 64 #define FRAME_attak108 65 #define FRAME_attak109 66 #define FRAME_attak110 67 #define FRAME_attak111 68 #define FRAME_attak112 69 #define FRAME_attak113 70 #define FRAME_attak114 71 #define FRAME_attak115 72 #define FRAME_attak116 73 #define FRAME_attak117 74 #define FRAME_attak118 75 #define FRAME_attak119 76 #define FRAME_attak120 77 #define FRAME_attak121 78 #define FRAME_attak201 79 #define FRAME_attak202 80 #define FRAME_attak203 81 #define FRAME_attak204 82 #define FRAME_attak205 83 #define FRAME_attak206 84 #define FRAME_attak207 85 #define FRAME_attak208 86 #define FRAME_attak209 87 #define FRAME_attak210 88 #define FRAME_attak211 89 #define FRAME_attak212 90 #define FRAME_attak213 91 #define FRAME_attak214 92 #define FRAME_attak215 93 #define FRAME_attak216 94 #define FRAME_attak217 95 #define FRAME_bankl01 96 #define FRAME_bankl02 97 #define FRAME_bankl03 98 #define FRAME_bankl04 99 #define FRAME_bankl05 100 #define FRAME_bankl06 101 #define FRAME_bankl07 102 #define FRAME_bankr01 103 #define FRAME_bankr02 104 #define FRAME_bankr03 105 #define FRAME_bankr04 106 #define FRAME_bankr05 107 #define FRAME_bankr06 108 #define FRAME_bankr07 109 #define FRAME_rollf01 110 #define FRAME_rollf02 111 #define FRAME_rollf03 112 #define FRAME_rollf04 113 #define FRAME_rollf05 114 #define FRAME_rollf06 115 #define FRAME_rollf07 116 #define FRAME_rollf08 117 #define FRAME_rollf09 118 #define FRAME_rollr01 119 #define FRAME_rollr02 120 #define FRAME_rollr03 121 #define FRAME_rollr04 122 #define FRAME_rollr05 123 #define FRAME_rollr06 124 #define FRAME_rollr07 125 #define FRAME_rollr08 126 #define FRAME_rollr09 127 #define FRAME_defens01 128 #define FRAME_defens02 129 #define FRAME_defens03 130 #define FRAME_defens04 131 #define FRAME_defens05 132 #define FRAME_defens06 133 #define FRAME_pain101 134 #define FRAME_pain102 135 #define FRAME_pain103 136 #define FRAME_pain104 137 #define FRAME_pain105 138 #define FRAME_pain106 139 #define FRAME_pain107 140 #define FRAME_pain108 141 #define FRAME_pain109 142 #define FRAME_pain201 143 #define FRAME_pain202 144 #define FRAME_pain203 145 #define FRAME_pain204 146 #define FRAME_pain301 147 #define FRAME_pain302 148 #define FRAME_pain303 149 #define FRAME_pain304 150 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/gladiator/000077500000000000000000000000001477320066100200345ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/gladiator/gladiator.c000066400000000000000000000271321477320066100221530ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Gladiator. * * ======================================================================= */ #include "../../header/local.h" #include "gladiator.h" static int sound_pain1; static int sound_pain2; static int sound_die; static int sound_gun; static int sound_cleaver_swing; static int sound_cleaver_hit; static int sound_cleaver_miss; static int sound_idle; static int sound_search; static int sound_sight; static int sound_step; static int sound_step2; void gladiator_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("gladiator/step1.wav"); sound_step2 = gi.soundindex("gladiator/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void gladiator_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } void gladiator_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void gladiator_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); } void gladiator_cleaver_swing(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0); } static mframe_t gladiator_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t gladiator_move_stand = { FRAME_stand1, FRAME_stand7, gladiator_frames_stand, NULL }; void gladiator_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gladiator_move_stand; } static mframe_t gladiator_frames_walk[] = { {ai_walk, 15, NULL}, {ai_walk, 7, NULL}, {ai_walk, 6, NULL}, {ai_walk, 5, NULL}, {ai_walk, 2, gladiator_footstep}, {ai_walk, 0, NULL}, {ai_walk, 2, NULL}, {ai_walk, 8, NULL}, {ai_walk, 12, NULL}, {ai_walk, 8, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 2, gladiator_footstep}, {ai_walk, 2, NULL}, {ai_walk, 1, NULL}, {ai_walk, 8, NULL} }; mmove_t gladiator_move_walk = { FRAME_walk1, FRAME_walk16, gladiator_frames_walk, NULL }; void gladiator_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gladiator_move_walk; } static mframe_t gladiator_frames_run[] = { {ai_run, 23, NULL}, {ai_run, 14, NULL}, {ai_run, 14, gladiator_footstep}, {ai_run, 21, NULL}, {ai_run, 12, NULL}, {ai_run, 13, gladiator_footstep} }; mmove_t gladiator_move_run = { FRAME_run1, FRAME_run6, gladiator_frames_run, NULL }; void gladiator_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &gladiator_move_stand; } else { self->monsterinfo.currentmove = &gladiator_move_run; } } void GaldiatorMelee(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], -4); if (fire_hit(self, aim, (20 + (rand() % 5)), 300)) { gi.sound(self, CHAN_AUTO, sound_cleaver_hit, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_AUTO, sound_cleaver_miss, 1, ATTN_NORM, 0); } } static mframe_t gladiator_frames_attack_melee[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, gladiator_cleaver_swing}, {ai_charge, 0, NULL}, {ai_charge, 0, GaldiatorMelee}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, gladiator_cleaver_swing}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GaldiatorMelee}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t gladiator_move_attack_melee = { FRAME_melee1, FRAME_melee17, gladiator_frames_attack_melee, gladiator_run }; void gladiator_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gladiator_move_attack_melee; } void GladiatorGun(edict_t *self) { vec3_t start; vec3_t dir; vec3_t forward, right; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_GLADIATOR_RAILGUN_1], forward, right, start); /* calc direction to where we targted */ VectorSubtract(self->pos1, start, dir); VectorNormalize(dir); monster_fire_railgun(self, start, dir, 50, 100, MZ2_GLADIATOR_RAILGUN_1); } static mframe_t gladiator_frames_attack_gun[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GladiatorGun}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t gladiator_move_attack_gun = { FRAME_attack1, FRAME_attack9, gladiator_frames_attack_gun, gladiator_run }; void gladiator_attack(edict_t *self) { float range; vec3_t v; if (!self) { return; } /* a small safe zone but not for stand-ground ones since players can abuse it by standing still inside this range */ if (!(self->monsterinfo.aiflags & AI_STAND_GROUND)) { VectorSubtract(self->s.origin, self->enemy->s.origin, v); range = VectorLength(v); if (range <= (MELEE_DISTANCE + 32)) { return; } } /* charge up the railgun */ gi.sound(self, CHAN_WEAPON, sound_gun, 1, ATTN_NORM, 0); VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; self->monsterinfo.currentmove = &gladiator_move_attack_gun; } static mframe_t gladiator_frames_pain[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gladiator_move_pain = { FRAME_pain1, FRAME_pain6, gladiator_frames_pain, gladiator_run }; static mframe_t gladiator_frames_pain_air[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gladiator_move_pain_air = { FRAME_painup1, FRAME_painup7, gladiator_frames_pain_air, gladiator_run }; void gladiator_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { if ((self->velocity[2] > 100) && (self->monsterinfo.currentmove == &gladiator_move_pain)) { self->monsterinfo.currentmove = &gladiator_move_pain_air; } return; } self->pain_debounce_time = level.time + 3; if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (self->velocity[2] > 100) { self->monsterinfo.currentmove = &gladiator_move_pain_air; } else { self->monsterinfo.currentmove = &gladiator_move_pain; } } void gladiator_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t gladiator_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gladiator_move_death = { FRAME_death1, FRAME_death22, gladiator_frames_death, gladiator_dead }; void gladiator_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /*unused */, vec3_t point) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &gladiator_move_death; } qboolean gladiator_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } /* * QUAKED monster_gladiator (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight */ void SP_monster_gladiator(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_pain1 = gi.soundindex("gladiator/pain.wav"); sound_pain2 = gi.soundindex("gladiator/gldpain2.wav"); sound_die = gi.soundindex("gladiator/glddeth2.wav"); sound_gun = gi.soundindex("gladiator/railgun.wav"); sound_cleaver_swing = gi.soundindex("gladiator/melee1.wav"); sound_cleaver_hit = gi.soundindex("gladiator/melee2.wav"); sound_cleaver_miss = gi.soundindex("gladiator/melee3.wav"); sound_idle = gi.soundindex("gladiator/gldidle1.wav"); sound_search = gi.soundindex("gladiator/gldsrch1.wav"); sound_sight = gi.soundindex("gladiator/sight.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/gladiatr/tris.md2"); VectorSet(self->mins, -32, -32, -24); VectorSet(self->maxs, 32, 32, 64); self->health = 400; self->gib_health = -175; self->mass = 400; self->pain = gladiator_pain; self->die = gladiator_die; self->monsterinfo.stand = gladiator_stand; self->monsterinfo.walk = gladiator_walk; self->monsterinfo.run = gladiator_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = gladiator_attack; self->monsterinfo.melee = gladiator_melee; self->monsterinfo.sight = gladiator_sight; self->monsterinfo.idle = gladiator_idle; self->monsterinfo.search = gladiator_search; self->monsterinfo.blocked = gladiator_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &gladiator_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/gladiator/gladiator.h000066400000000000000000000063051477320066100221570ustar00rootroot00000000000000/* ======================================================================= * * Gladiator animations. * * ======================================================================= */ #define FRAME_stand1 0 #define FRAME_stand2 1 #define FRAME_stand3 2 #define FRAME_stand4 3 #define FRAME_stand5 4 #define FRAME_stand6 5 #define FRAME_stand7 6 #define FRAME_walk1 7 #define FRAME_walk2 8 #define FRAME_walk3 9 #define FRAME_walk4 10 #define FRAME_walk5 11 #define FRAME_walk6 12 #define FRAME_walk7 13 #define FRAME_walk8 14 #define FRAME_walk9 15 #define FRAME_walk10 16 #define FRAME_walk11 17 #define FRAME_walk12 18 #define FRAME_walk13 19 #define FRAME_walk14 20 #define FRAME_walk15 21 #define FRAME_walk16 22 #define FRAME_run1 23 #define FRAME_run2 24 #define FRAME_run3 25 #define FRAME_run4 26 #define FRAME_run5 27 #define FRAME_run6 28 #define FRAME_melee1 29 #define FRAME_melee2 30 #define FRAME_melee3 31 #define FRAME_melee4 32 #define FRAME_melee5 33 #define FRAME_melee6 34 #define FRAME_melee7 35 #define FRAME_melee8 36 #define FRAME_melee9 37 #define FRAME_melee10 38 #define FRAME_melee11 39 #define FRAME_melee12 40 #define FRAME_melee13 41 #define FRAME_melee14 42 #define FRAME_melee15 43 #define FRAME_melee16 44 #define FRAME_melee17 45 #define FRAME_attack1 46 #define FRAME_attack2 47 #define FRAME_attack3 48 #define FRAME_attack4 49 #define FRAME_attack5 50 #define FRAME_attack6 51 #define FRAME_attack7 52 #define FRAME_attack8 53 #define FRAME_attack9 54 #define FRAME_pain1 55 #define FRAME_pain2 56 #define FRAME_pain3 57 #define FRAME_pain4 58 #define FRAME_pain5 59 #define FRAME_pain6 60 #define FRAME_death1 61 #define FRAME_death2 62 #define FRAME_death3 63 #define FRAME_death4 64 #define FRAME_death5 65 #define FRAME_death6 66 #define FRAME_death7 67 #define FRAME_death8 68 #define FRAME_death9 69 #define FRAME_death10 70 #define FRAME_death11 71 #define FRAME_death12 72 #define FRAME_death13 73 #define FRAME_death14 74 #define FRAME_death15 75 #define FRAME_death16 76 #define FRAME_death17 77 #define FRAME_death18 78 #define FRAME_death19 79 #define FRAME_death20 80 #define FRAME_death21 81 #define FRAME_death22 82 #define FRAME_painup1 83 #define FRAME_painup2 84 #define FRAME_painup3 85 #define FRAME_painup4 86 #define FRAME_painup5 87 #define FRAME_painup6 88 #define FRAME_painup7 89 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/gunner/000077500000000000000000000000001477320066100173645ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/gunner/gunner.c000066400000000000000000000605571477320066100210430ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Gunner. * * ======================================================================= */ #include "../../header/local.h" #include "gunner.h" static int sound_pain; static int sound_pain2; static int sound_death; static int sound_idle; static int sound_open; static int sound_search; static int sound_sight; static int sound_step; static int sound_step2; qboolean visible(edict_t *self, edict_t *other); void GunnerGrenade(edict_t *self); void GunnerFire(edict_t *self); void gunner_fire_chain(edict_t *self); void gunner_refire_chain(edict_t *self); void gunner_stand(edict_t *self); void gunner_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("gunner/step1.wav"); sound_step2 = gi.soundindex("gunner/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void gunner_idlesound(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } void gunner_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void gunner_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); } static mframe_t gunner_frames_fidget[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, gunner_idlesound}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t gunner_move_fidget = { FRAME_stand31, FRAME_stand70, gunner_frames_fidget, gunner_stand }; void gunner_fidget(edict_t *self) { if (!self) { return; } if (self->enemy) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { return; } if (random() <= 0.05) { self->monsterinfo.currentmove = &gunner_move_fidget; } } static mframe_t gunner_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, gunner_fidget}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, gunner_fidget}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, gunner_fidget} }; mmove_t gunner_move_stand = { FRAME_stand01, FRAME_stand30, gunner_frames_stand, NULL }; void gunner_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gunner_move_stand; } static mframe_t gunner_frames_walk[] = { {ai_walk, 0, gunner_footstep}, {ai_walk, 3, NULL}, {ai_walk, 4, NULL}, {ai_walk, 5, NULL}, {ai_walk, 7, NULL}, {ai_walk, 2, gunner_footstep}, {ai_walk, 6, NULL}, {ai_walk, 4, NULL}, {ai_walk, 2, NULL}, {ai_walk, 7, NULL}, {ai_walk, 5, NULL}, {ai_walk, 7, NULL}, {ai_walk, 4, gunner_footstep} }; mmove_t gunner_move_walk = { FRAME_walk07, FRAME_walk19, gunner_frames_walk, NULL }; void gunner_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gunner_move_walk; } static mframe_t gunner_frames_run[] = { {ai_run, 26, NULL}, {ai_run, 9, gunner_footstep}, {ai_run, 9, NULL}, {ai_run, 9, monster_done_dodge}, {ai_run, 15, NULL}, {ai_run, 10, gunner_footstep}, {ai_run, 13, NULL}, {ai_run, 6, NULL} }; mmove_t gunner_move_run = { FRAME_run01, FRAME_run08, gunner_frames_run, NULL }; void gunner_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &gunner_move_stand; } else { self->monsterinfo.currentmove = &gunner_move_run; } } static mframe_t gunner_frames_runandshoot[] = { {ai_run, 32, NULL}, {ai_run, 15, gunner_footstep}, {ai_run, 10, NULL}, {ai_run, 18, NULL}, {ai_run, 8, gunner_footstep}, {ai_run, 20, NULL} }; mmove_t gunner_move_runandshoot = { FRAME_runs01, FRAME_runs06, gunner_frames_runandshoot, NULL }; void gunner_runandshoot(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gunner_move_runandshoot; } static mframe_t gunner_frames_pain3[] = { {ai_move, -3, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 1, NULL} }; mmove_t gunner_move_pain3 = { FRAME_pain301, FRAME_pain305, gunner_frames_pain3, gunner_run }; static mframe_t gunner_frames_pain2[] = { {ai_move, -2, NULL}, {ai_move, 11, NULL}, {ai_move, 6, gunner_footstep}, {ai_move, 2, NULL}, {ai_move, -1, NULL}, {ai_move, -7, NULL}, {ai_move, -2, NULL}, {ai_move, -7, gunner_footstep} }; mmove_t gunner_move_pain2 = { FRAME_pain201, FRAME_pain208, gunner_frames_pain2, gunner_run }; static mframe_t gunner_frames_pain1[] = { {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, -5, gunner_footstep}, {ai_move, 3, NULL}, {ai_move, -1, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, 2, NULL}, {ai_move, 1, gunner_footstep}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, -2, NULL}, {ai_move, 0, gunner_footstep}, {ai_move, 0, NULL} }; mmove_t gunner_move_pain1 = { FRAME_pain101, FRAME_pain118, gunner_frames_pain1, gunner_run }; void gunner_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } monster_done_dodge(self); if (!self->groundentity) { return; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (rand() & 1) { gi.sound(self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (damage <= 10) { self->monsterinfo.currentmove = &gunner_move_pain3; } else if (damage <= 25) { self->monsterinfo.currentmove = &gunner_move_pain2; } else { self->monsterinfo.currentmove = &gunner_move_pain1; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } void gunner_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t gunner_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -7, NULL}, {ai_move, -3, NULL}, {ai_move, -5, NULL}, {ai_move, 8, NULL}, {ai_move, 6, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gunner_move_death = { FRAME_death01, FRAME_death11, gunner_frames_death, gunner_dead }; void gunner_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &gunner_move_death; } void gunner_duck_down(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_DUCKED; self->maxs[2] = self->monsterinfo.base_height - 32; self->takedamage = DAMAGE_YES; if (self->monsterinfo.duck_wait_time < level.time) { self->monsterinfo.duck_wait_time = level.time + 1; } gi.linkentity(self); } static void gunner_duck_down_think(edict_t *self) { gunner_duck_down(self); /* rogue code calls duck_down twice, so move this here */ if (skill->value >= SKILL_HARD) { if (random() > 0.5) { GunnerGrenade(self); } } } static mframe_t gunner_frames_duck[] = { {ai_move, 1, gunner_duck_down_think}, {ai_move, 1, NULL}, {ai_move, 1, monster_duck_hold}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, 0, monster_duck_up}, {ai_move, -1, NULL} }; mmove_t gunner_move_duck = { FRAME_duck01, FRAME_duck08, gunner_frames_duck, gunner_run }; /* gunner dodge moved below so I know about attack sequences */ void gunner_opengun(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_open, 1, ATTN_IDLE, 0); } void GunnerFire(edict_t *self) { vec3_t start; vec3_t forward, right; vec3_t target; vec3_t aim; int flash_number; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216); AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); /* project enemy back a bit and target there */ VectorCopy(self->enemy->s.origin, target); VectorMA(target, -0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, aim); VectorNormalize(aim); monster_fire_bullet(self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); } qboolean gunner_grenade_check(edict_t *self) { vec3_t start; vec3_t forward, right; trace_t tr; vec3_t target, dir; if (!self) { return false; } if (!self->enemy) { return false; } /* if the player is above my head, use machinegun. */ /* check for flag telling us that we're blindfiring */ if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { if (self->s.origin[2] + self->viewheight < self->monsterinfo.blind_fire_target[2]) { return false; } } else if (self->absmax[2] <= self->enemy->absmin[2]) { return false; } /* check to see that we can trace to the player before we start tossing grenades around. */ AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_GUNNER_GRENADE_1], forward, right, start); /* check for blindfire flag */ if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { VectorCopy(self->monsterinfo.blind_fire_target, target); } else { VectorCopy(self->enemy->s.origin, target); } /* see if we're too close */ VectorSubtract(self->s.origin, target, dir); if (VectorLength(dir) < 100) { return false; } tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT); if ((tr.ent == self->enemy) || (tr.fraction == 1)) { return true; } return false; } void GunnerGrenade(edict_t *self) { vec3_t start; vec3_t forward, right, up; vec3_t aim; int flash_number; float spread; float pitch = 0; vec3_t target; qboolean blindfire = false; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { blindfire = true; } if (self->s.frame == FRAME_attak105) { spread = .02; flash_number = MZ2_GUNNER_GRENADE_1; } else if (self->s.frame == FRAME_attak108) { spread = .05; flash_number = MZ2_GUNNER_GRENADE_2; } else if (self->s.frame == FRAME_attak111) { spread = .08; flash_number = MZ2_GUNNER_GRENADE_3; } else { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; spread = .11; flash_number = MZ2_GUNNER_GRENADE_4; } /* if we're shooting blind and we still can't see our enemy */ if ((blindfire) && (!visible(self, self->enemy))) { /* and we have a valid blind_fire_target */ if (VectorCompare(self->monsterinfo.blind_fire_target, vec3_origin)) { return; } VectorCopy(self->monsterinfo.blind_fire_target, target); } else { VectorCopy(self->s.origin, target); } AngleVectors(self->s.angles, forward, right, up); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); if (self->enemy) { float dist; VectorSubtract(target, self->s.origin, aim); dist = VectorLength(aim); /* aim up if they're on the same level as me and far away. */ if ((dist > 512) && (aim[2] < 64) && (aim[2] > -64)) { aim[2] += (dist - 512); } VectorNormalize(aim); pitch = aim[2]; if (pitch > 0.4) { pitch = 0.4; } else if (pitch < -0.5) { pitch = -0.5; } } VectorMA(forward, spread, right, aim); VectorMA(aim, pitch, up, aim); monster_fire_grenade(self, start, aim, 50, 600, flash_number); } static mframe_t gunner_frames_attack_chain[] = { {ai_charge, 0, gunner_opengun}, {ai_charge, 0, gunner_footstep}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t gunner_move_attack_chain = { FRAME_attak209, FRAME_attak215, gunner_frames_attack_chain, gunner_fire_chain }; static mframe_t gunner_frames_fire_chain[] = { {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire}, {ai_charge, 0, GunnerFire} }; mmove_t gunner_move_fire_chain = { FRAME_attak216, FRAME_attak223, gunner_frames_fire_chain, gunner_refire_chain }; static mframe_t gunner_frames_endfire_chain[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, gunner_footstep} }; mmove_t gunner_move_endfire_chain = { FRAME_attak224, FRAME_attak230, gunner_frames_endfire_chain, gunner_run }; void gunner_blind_check(edict_t *self) { vec3_t aim; if (!self) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { VectorSubtract(self->monsterinfo.blind_fire_target, self->s.origin, aim); self->ideal_yaw = vectoyaw(aim); } } static mframe_t gunner_frames_attack_grenade[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GunnerGrenade}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GunnerGrenade}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GunnerGrenade}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, GunnerGrenade}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t gunner_move_attack_grenade = { FRAME_attak101, FRAME_attak121, gunner_frames_attack_grenade, gunner_run }; void gunner_attack(edict_t *self) { float chance, r; if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.attack_state == AS_BLIND) { /* setup shot probabilities */ if (self->monsterinfo.blind_fire_delay < 1.0) { chance = 1.0; } else if (self->monsterinfo.blind_fire_delay < 7.5) { chance = 0.4; } else { chance = 0.1; } r = random(); /* minimum of 2 seconds, plus 0-3, after the shots are done */ self->monsterinfo.blind_fire_delay += 2.1 + 2.0 + random() * 3.0; /* don't shoot at the origin */ if (VectorCompare(self->monsterinfo.blind_fire_target, vec3_origin)) { return; } /* don't shoot if the dice say not to */ if (r > chance) { return; } /* turn on manual steering to signal both manual steering and blindfire */ self->monsterinfo.aiflags |= AI_MANUAL_STEERING; if (gunner_grenade_check(self)) { /* if the check passes, go for the attack */ self->monsterinfo.currentmove = &gunner_move_attack_grenade; self->monsterinfo.attack_finished = level.time + 2 * random(); } /* turn off blindfire flag */ self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; return; } /* gunner needs to use his chaingun if he's being attacked by a tesla. */ if ((range(self, self->enemy) == RANGE_MELEE) || self->bad_area) { self->monsterinfo.currentmove = &gunner_move_attack_chain; } else { if ((random() <= 0.5) && gunner_grenade_check(self)) { self->monsterinfo.currentmove = &gunner_move_attack_grenade; } else { self->monsterinfo.currentmove = &gunner_move_attack_chain; } } } void gunner_fire_chain(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &gunner_move_fire_chain; } void gunner_refire_chain(edict_t *self) { if (!self) { return; } if (self->enemy->health > 0) { if (visible(self, self->enemy)) { if (random() <= 0.5) { self->monsterinfo.currentmove = &gunner_move_fire_chain; return; } } } self->monsterinfo.currentmove = &gunner_move_endfire_chain; } void gunner_jump_now(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void gunner_jump2_now(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 150, forward, self->velocity); VectorMA(self->velocity, 400, up, self->velocity); } void gunner_jump_wait_land(edict_t *self) { if (!self) { return; } if (self->groundentity == NULL) { self->monsterinfo.nextframe = self->s.frame; if (monster_jump_finished(self)) { self->monsterinfo.nextframe = self->s.frame + 1; } } else { self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t gunner_frames_jump[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, gunner_jump_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, gunner_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gunner_move_jump = { FRAME_jump01, FRAME_jump10, gunner_frames_jump, gunner_run }; static mframe_t gunner_frames_jump2[] = { {ai_move, -8, NULL}, {ai_move, -4, NULL}, {ai_move, -4, NULL}, {ai_move, 0, gunner_jump2_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, gunner_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t gunner_move_jump2 = { FRAME_jump01, FRAME_jump10, gunner_frames_jump2, gunner_run }; void gunner_jump(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } monster_done_dodge(self); if (self->enemy->absmin[2] > self->absmin[2]) { self->monsterinfo.currentmove = &gunner_move_jump2; } else { self->monsterinfo.currentmove = &gunner_move_jump; } } qboolean gunner_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } if (blocked_checkjump(self, dist, 192, 40)) { gunner_jump(self); return true; } return false; } /* new duck code */ void gunner_duck(edict_t *self, float eta) { if (!self) { return; } if ((self->monsterinfo.currentmove == &gunner_move_jump2) || (self->monsterinfo.currentmove == &gunner_move_jump)) { return; } if ((self->monsterinfo.currentmove == &gunner_move_attack_chain) || (self->monsterinfo.currentmove == &gunner_move_fire_chain) || (self->monsterinfo.currentmove == &gunner_move_attack_grenade) ) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DUCKED; return; } } if (skill->value == SKILL_EASY) { /* stupid dodge */ self->monsterinfo.duck_wait_time = level.time + eta + 1; } else { self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } /* has to be done immediately otherwise he can get stuck */ gunner_duck_down(self); self->monsterinfo.nextframe = FRAME_duck01; self->monsterinfo.currentmove = &gunner_move_duck; return; } void gunner_sidestep(edict_t *self) { if (!self) { return; } if ((self->monsterinfo.currentmove == &gunner_move_jump2) || (self->monsterinfo.currentmove == &gunner_move_jump)) { return; } if ((self->monsterinfo.currentmove == &gunner_move_attack_chain) || (self->monsterinfo.currentmove == &gunner_move_fire_chain) || (self->monsterinfo.currentmove == &gunner_move_attack_grenade) ) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DODGING; return; } } if (self->monsterinfo.currentmove != &gunner_move_run) { self->monsterinfo.currentmove = &gunner_move_run; } } /* * QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_gunner(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_death = gi.soundindex("gunner/death1.wav"); sound_pain = gi.soundindex("gunner/gunpain2.wav"); sound_pain2 = gi.soundindex("gunner/gunpain1.wav"); sound_idle = gi.soundindex("gunner/gunidle1.wav"); sound_open = gi.soundindex("gunner/gunatck1.wav"); sound_search = gi.soundindex("gunner/gunsrch1.wav"); sound_sight = gi.soundindex("gunner/sight1.wav"); gi.soundindex("gunner/gunatck2.wav"); gi.soundindex("gunner/gunatck3.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/gunner/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->health = 175; self->gib_health = -70; self->mass = 200; self->pain = gunner_pain; self->die = gunner_die; self->monsterinfo.stand = gunner_stand; self->monsterinfo.walk = gunner_walk; self->monsterinfo.run = gunner_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.duck = gunner_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.sidestep = gunner_sidestep; self->monsterinfo.attack = gunner_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = gunner_sight; self->monsterinfo.search = gunner_search; self->monsterinfo.blocked = gunner_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &gunner_move_stand; self->monsterinfo.scale = MODEL_SCALE; self->monsterinfo.blindfire = true; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/gunner/gunner.h000066400000000000000000000170131477320066100210350ustar00rootroot00000000000000/* ======================================================================= * * Gunner animations. * * ======================================================================= */ #define FRAME_stand01 0 #define FRAME_stand02 1 #define FRAME_stand03 2 #define FRAME_stand04 3 #define FRAME_stand05 4 #define FRAME_stand06 5 #define FRAME_stand07 6 #define FRAME_stand08 7 #define FRAME_stand09 8 #define FRAME_stand10 9 #define FRAME_stand11 10 #define FRAME_stand12 11 #define FRAME_stand13 12 #define FRAME_stand14 13 #define FRAME_stand15 14 #define FRAME_stand16 15 #define FRAME_stand17 16 #define FRAME_stand18 17 #define FRAME_stand19 18 #define FRAME_stand20 19 #define FRAME_stand21 20 #define FRAME_stand22 21 #define FRAME_stand23 22 #define FRAME_stand24 23 #define FRAME_stand25 24 #define FRAME_stand26 25 #define FRAME_stand27 26 #define FRAME_stand28 27 #define FRAME_stand29 28 #define FRAME_stand30 29 #define FRAME_stand31 30 #define FRAME_stand32 31 #define FRAME_stand33 32 #define FRAME_stand34 33 #define FRAME_stand35 34 #define FRAME_stand36 35 #define FRAME_stand37 36 #define FRAME_stand38 37 #define FRAME_stand39 38 #define FRAME_stand40 39 #define FRAME_stand41 40 #define FRAME_stand42 41 #define FRAME_stand43 42 #define FRAME_stand44 43 #define FRAME_stand45 44 #define FRAME_stand46 45 #define FRAME_stand47 46 #define FRAME_stand48 47 #define FRAME_stand49 48 #define FRAME_stand50 49 #define FRAME_stand51 50 #define FRAME_stand52 51 #define FRAME_stand53 52 #define FRAME_stand54 53 #define FRAME_stand55 54 #define FRAME_stand56 55 #define FRAME_stand57 56 #define FRAME_stand58 57 #define FRAME_stand59 58 #define FRAME_stand60 59 #define FRAME_stand61 60 #define FRAME_stand62 61 #define FRAME_stand63 62 #define FRAME_stand64 63 #define FRAME_stand65 64 #define FRAME_stand66 65 #define FRAME_stand67 66 #define FRAME_stand68 67 #define FRAME_stand69 68 #define FRAME_stand70 69 #define FRAME_walk01 70 #define FRAME_walk02 71 #define FRAME_walk03 72 #define FRAME_walk04 73 #define FRAME_walk05 74 #define FRAME_walk06 75 #define FRAME_walk07 76 #define FRAME_walk08 77 #define FRAME_walk09 78 #define FRAME_walk10 79 #define FRAME_walk11 80 #define FRAME_walk12 81 #define FRAME_walk13 82 #define FRAME_walk14 83 #define FRAME_walk15 84 #define FRAME_walk16 85 #define FRAME_walk17 86 #define FRAME_walk18 87 #define FRAME_walk19 88 #define FRAME_walk20 89 #define FRAME_walk21 90 #define FRAME_walk22 91 #define FRAME_walk23 92 #define FRAME_walk24 93 #define FRAME_run01 94 #define FRAME_run02 95 #define FRAME_run03 96 #define FRAME_run04 97 #define FRAME_run05 98 #define FRAME_run06 99 #define FRAME_run07 100 #define FRAME_run08 101 #define FRAME_runs01 102 #define FRAME_runs02 103 #define FRAME_runs03 104 #define FRAME_runs04 105 #define FRAME_runs05 106 #define FRAME_runs06 107 #define FRAME_attak101 108 #define FRAME_attak102 109 #define FRAME_attak103 110 #define FRAME_attak104 111 #define FRAME_attak105 112 #define FRAME_attak106 113 #define FRAME_attak107 114 #define FRAME_attak108 115 #define FRAME_attak109 116 #define FRAME_attak110 117 #define FRAME_attak111 118 #define FRAME_attak112 119 #define FRAME_attak113 120 #define FRAME_attak114 121 #define FRAME_attak115 122 #define FRAME_attak116 123 #define FRAME_attak117 124 #define FRAME_attak118 125 #define FRAME_attak119 126 #define FRAME_attak120 127 #define FRAME_attak121 128 #define FRAME_attak201 129 #define FRAME_attak202 130 #define FRAME_attak203 131 #define FRAME_attak204 132 #define FRAME_attak205 133 #define FRAME_attak206 134 #define FRAME_attak207 135 #define FRAME_attak208 136 #define FRAME_attak209 137 #define FRAME_attak210 138 #define FRAME_attak211 139 #define FRAME_attak212 140 #define FRAME_attak213 141 #define FRAME_attak214 142 #define FRAME_attak215 143 #define FRAME_attak216 144 #define FRAME_attak217 145 #define FRAME_attak218 146 #define FRAME_attak219 147 #define FRAME_attak220 148 #define FRAME_attak221 149 #define FRAME_attak222 150 #define FRAME_attak223 151 #define FRAME_attak224 152 #define FRAME_attak225 153 #define FRAME_attak226 154 #define FRAME_attak227 155 #define FRAME_attak228 156 #define FRAME_attak229 157 #define FRAME_attak230 158 #define FRAME_pain101 159 #define FRAME_pain102 160 #define FRAME_pain103 161 #define FRAME_pain104 162 #define FRAME_pain105 163 #define FRAME_pain106 164 #define FRAME_pain107 165 #define FRAME_pain108 166 #define FRAME_pain109 167 #define FRAME_pain110 168 #define FRAME_pain111 169 #define FRAME_pain112 170 #define FRAME_pain113 171 #define FRAME_pain114 172 #define FRAME_pain115 173 #define FRAME_pain116 174 #define FRAME_pain117 175 #define FRAME_pain118 176 #define FRAME_pain201 177 #define FRAME_pain202 178 #define FRAME_pain203 179 #define FRAME_pain204 180 #define FRAME_pain205 181 #define FRAME_pain206 182 #define FRAME_pain207 183 #define FRAME_pain208 184 #define FRAME_pain301 185 #define FRAME_pain302 186 #define FRAME_pain303 187 #define FRAME_pain304 188 #define FRAME_pain305 189 #define FRAME_death01 190 #define FRAME_death02 191 #define FRAME_death03 192 #define FRAME_death04 193 #define FRAME_death05 194 #define FRAME_death06 195 #define FRAME_death07 196 #define FRAME_death08 197 #define FRAME_death09 198 #define FRAME_death10 199 #define FRAME_death11 200 #define FRAME_duck01 201 #define FRAME_duck02 202 #define FRAME_duck03 203 #define FRAME_duck04 204 #define FRAME_duck05 205 #define FRAME_duck06 206 #define FRAME_duck07 207 #define FRAME_duck08 208 #define FRAME_jump01 209 #define FRAME_jump02 210 #define FRAME_jump03 211 #define FRAME_jump04 212 #define FRAME_jump05 213 #define FRAME_jump06 214 #define FRAME_jump07 215 #define FRAME_jump08 216 #define FRAME_jump09 217 #define FRAME_jump10 218 #define MODEL_SCALE 1.150000 rogue-ROGUE_2_13/src/monster/hover/000077500000000000000000000000001477320066100172115ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/hover/hover.c000066400000000000000000000376341477320066100205150ustar00rootroot00000000000000/* ======================================================================= * * Icarus and Daedalus. * * ======================================================================= */ #include "../../header/local.h" #include "hover.h" qboolean visible(edict_t *self, edict_t *other); void hover_run(edict_t *self); void hover_stand(edict_t *self); void hover_dead(edict_t *self); void hover_attack(edict_t *self); void hover_reattack(edict_t *self); void hover_fire_blaster(edict_t *self); void hover_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); static int sound_pain1; static int sound_pain2; static int sound_death1; static int sound_death2; static int sound_sight; static int sound_search1; static int sound_search2; /* daedalus sounds */ static int daed_sound_pain1; static int daed_sound_pain2; static int daed_sound_death1; static int daed_sound_death2; static int daed_sound_sight; static int daed_sound_search1; static int daed_sound_search2; void hover_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } if (self->mass < 225) { gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_sight, 1, ATTN_NORM, 0); } } void hover_search(edict_t *self) { if (!self) { return; } if (self->mass < 225) { if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); } } else { if (random() < 0.5) { gi.sound(self, CHAN_VOICE, daed_sound_search1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_search2, 1, ATTN_NORM, 0); } } } static mframe_t hover_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t hover_move_stand = { FRAME_stand01, FRAME_stand30, hover_frames_stand, NULL }; static mframe_t hover_frames_pain3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t hover_move_pain3 = { FRAME_pain301, FRAME_pain309, hover_frames_pain3, hover_run }; static mframe_t hover_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t hover_move_pain2 = { FRAME_pain201, FRAME_pain212, hover_frames_pain2, hover_run }; static mframe_t hover_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, -8, NULL}, {ai_move, -4, NULL}, {ai_move, -6, NULL}, {ai_move, -4, NULL}, {ai_move, -3, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 3, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, 7, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 5, NULL}, {ai_move, 3, NULL}, {ai_move, 4, NULL} }; mmove_t hover_move_pain1 = { FRAME_pain101, FRAME_pain128, hover_frames_pain1, hover_run }; static mframe_t hover_frames_walk[] = { {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL} }; mmove_t hover_move_walk = { FRAME_forwrd01, FRAME_forwrd35, hover_frames_walk, NULL }; static mframe_t hover_frames_run[] = { {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL}, {ai_run, 10, NULL} }; mmove_t hover_move_run = { FRAME_forwrd01, FRAME_forwrd35, hover_frames_run, NULL }; static mframe_t hover_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -10, NULL}, {ai_move, 3, NULL}, {ai_move, 5, NULL}, {ai_move, 4, NULL}, {ai_move, 7, NULL} }; mmove_t hover_move_death1 = { FRAME_death101, FRAME_death111, hover_frames_death1, hover_dead }; static mframe_t hover_frames_start_attack[] = { {ai_charge, 1, NULL}, {ai_charge, 1, NULL}, {ai_charge, 1, NULL} }; mmove_t hover_move_start_attack = { FRAME_attak101, FRAME_attak103, hover_frames_start_attack, hover_attack }; static mframe_t hover_frames_attack1[] = { {ai_charge, -10, hover_fire_blaster}, {ai_charge, -10, hover_fire_blaster}, {ai_charge, 0, hover_reattack}, }; mmove_t hover_move_attack1 = { FRAME_attak104, FRAME_attak106, hover_frames_attack1, NULL }; static mframe_t hover_frames_end_attack[] = { {ai_charge, 1, NULL}, {ai_charge, 1, NULL} }; mmove_t hover_move_end_attack = { FRAME_attak107, FRAME_attak108, hover_frames_end_attack, hover_run }; static mframe_t hover_frames_start_attack2[] = { {ai_charge, 15, NULL}, {ai_charge, 15, NULL}, {ai_charge, 15, NULL} }; mmove_t hover_move_start_attack2 = { FRAME_attak101, FRAME_attak103, hover_frames_start_attack2, hover_attack }; static mframe_t hover_frames_attack2[] = { {ai_charge, 10, hover_fire_blaster}, {ai_charge, 10, hover_fire_blaster}, {ai_charge, 10, hover_reattack}, }; mmove_t hover_move_attack2 = { FRAME_attak104, FRAME_attak106, hover_frames_attack2, NULL }; static mframe_t hover_frames_end_attack2[] = { {ai_charge, 15, NULL}, {ai_charge, 15, NULL} }; mmove_t hover_move_end_attack2 = { FRAME_attak107, FRAME_attak108, hover_frames_end_attack2, hover_run }; void hover_reattack(edict_t *self) { if (!self) { return; } if (self->enemy->health > 0) { if (visible(self, self->enemy)) { if (random() <= 0.6) { if (self->monsterinfo.attack_state == AS_STRAIGHT) { self->monsterinfo.currentmove = &hover_move_attack1; return; } else if (self->monsterinfo.attack_state == AS_SLIDING) { self->monsterinfo.currentmove = &hover_move_attack2; return; } else { gi.dprintf("hover_reattack: unexpected state %d\n", self->monsterinfo.attack_state); } } } } self->monsterinfo.currentmove = &hover_move_end_attack; } void hover_fire_blaster(edict_t *self) { vec3_t start; vec3_t forward, right; vec3_t end; vec3_t dir; int effect; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } if (self->s.frame == FRAME_attak104) { effect = EF_HYPERBLASTER; } else { effect = 0; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start); VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, dir); if (self->mass < 200) { monster_fire_blaster(self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect); } else { monster_fire_blaster2(self, start, dir, 1, 1000, MZ2_DAEDALUS_BLASTER, EF_BLASTER); } } void hover_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &hover_move_stand; } void hover_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &hover_move_stand; } else { self->monsterinfo.currentmove = &hover_move_run; } } void hover_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &hover_move_walk; } void hover_start_attack(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &hover_move_start_attack; } void hover_attack(edict_t *self) { float chance; if (!self) { return; } if (skill->value == SKILL_EASY) { chance = 0; } else { chance = 1.0 - (0.5 / (float)(skill->value)); } if (self->mass > 150) /* the daedalus strafes more */ { chance += 0.1; } if (random() > chance) { self->monsterinfo.currentmove = &hover_move_attack1; self->monsterinfo.attack_state = AS_STRAIGHT; } else /* circle strafe */ { if (random() <= 0.5) /* switch directions */ { self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; } self->monsterinfo.currentmove = &hover_move_attack2; self->monsterinfo.attack_state = AS_SLIDING; } } void hover_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; /* support for skins 2 & 3. */ } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (damage <= 25) { if (random() < 0.5) { /* daedalus sounds */ if (self->mass < 225) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_pain1, 1, ATTN_NORM, 0); } self->monsterinfo.currentmove = &hover_move_pain3; } else { /* daedalus sounds */ if (self->mass < 225) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_pain2, 1, ATTN_NORM, 0); } self->monsterinfo.currentmove = &hover_move_pain2; } } else { if (random() < (0.45 - (0.1 * skill->value))) { /* daedalus sounds */ if (self->mass < 225) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_pain1, 1, ATTN_NORM, 0); } self->monsterinfo.currentmove = &hover_move_pain1; } else { /* daedalus sounds */ if (self->mass < 225) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_pain2, 1, ATTN_NORM, 0); } self->monsterinfo.currentmove = &hover_move_pain2; } } } void hover_deadthink(edict_t *self) { if (!self) { return; } if (!self->groundentity && (level.time < self->timestamp)) { self->nextthink = level.time + FRAMETIME; return; } BecomeExplosion1(self); } void hover_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->think = hover_deadthink; self->nextthink = level.time + FRAMETIME; self->timestamp = level.time + 15; gi.linkentity(self); } void hover_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } self->s.effects = 0; self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ if (self->mass < 225) { if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); } } else { if (random() < 0.5) { gi.sound(self, CHAN_VOICE, daed_sound_death1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, daed_sound_death2, 1, ATTN_NORM, 0); } } self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &hover_move_death1; } qboolean hover_blocked(edict_t *self, float dist) { return false; } /* * QUAKED monster_hover (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight * * QUAKED monster_daedalus (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight * This is the improved icarus monster. */ void SP_monster_hover(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2"); VectorSet(self->mins, -24, -24, -24); VectorSet(self->maxs, 24, 24, 32); self->health = 240; self->gib_health = -100; self->mass = 150; self->pain = hover_pain; self->die = hover_die; self->monsterinfo.stand = hover_stand; self->monsterinfo.walk = hover_walk; self->monsterinfo.run = hover_run; self->monsterinfo.attack = hover_start_attack; self->monsterinfo.sight = hover_sight; self->monsterinfo.search = hover_search; self->monsterinfo.blocked = hover_blocked; if (strcmp(self->classname, "monster_daedalus") == 0) { self->health = 450; self->mass = 225; self->yaw_speed = 25; self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; self->monsterinfo.power_armor_power = 100; self->s.sound = gi.soundindex("daedalus/daedidle1.wav"); daed_sound_pain1 = gi.soundindex("daedalus/daedpain1.wav"); daed_sound_pain2 = gi.soundindex("daedalus/daedpain2.wav"); daed_sound_death1 = gi.soundindex("daedalus/daeddeth1.wav"); daed_sound_death2 = gi.soundindex("daedalus/daeddeth2.wav"); daed_sound_sight = gi.soundindex("daedalus/daedsght1.wav"); daed_sound_search1 = gi.soundindex("daedalus/daedsrch1.wav"); daed_sound_search2 = gi.soundindex("daedalus/daedsrch2.wav"); gi.soundindex("tank/tnkatck3.wav"); } else { sound_pain1 = gi.soundindex("hover/hovpain1.wav"); sound_pain2 = gi.soundindex("hover/hovpain2.wav"); sound_death1 = gi.soundindex("hover/hovdeth1.wav"); sound_death2 = gi.soundindex("hover/hovdeth2.wav"); sound_sight = gi.soundindex("hover/hovsght1.wav"); sound_search1 = gi.soundindex("hover/hovsrch1.wav"); sound_search2 = gi.soundindex("hover/hovsrch2.wav"); gi.soundindex("hover/hovatck1.wav"); self->s.sound = gi.soundindex("hover/hovidle1.wav"); } gi.linkentity(self); self->monsterinfo.currentmove = &hover_move_stand; self->monsterinfo.scale = MODEL_SCALE; flymonster_start(self); if (strcmp(self->classname, "monster_daedalus") == 0) { self->s.skinnum = 2; } } rogue-ROGUE_2_13/src/monster/hover/hover.h000066400000000000000000000161761477320066100205200ustar00rootroot00000000000000/* ======================================================================= * * Icarus and Daedalus animations. * * ======================================================================= */ #define FRAME_stand01 0 #define FRAME_stand02 1 #define FRAME_stand03 2 #define FRAME_stand04 3 #define FRAME_stand05 4 #define FRAME_stand06 5 #define FRAME_stand07 6 #define FRAME_stand08 7 #define FRAME_stand09 8 #define FRAME_stand10 9 #define FRAME_stand11 10 #define FRAME_stand12 11 #define FRAME_stand13 12 #define FRAME_stand14 13 #define FRAME_stand15 14 #define FRAME_stand16 15 #define FRAME_stand17 16 #define FRAME_stand18 17 #define FRAME_stand19 18 #define FRAME_stand20 19 #define FRAME_stand21 20 #define FRAME_stand22 21 #define FRAME_stand23 22 #define FRAME_stand24 23 #define FRAME_stand25 24 #define FRAME_stand26 25 #define FRAME_stand27 26 #define FRAME_stand28 27 #define FRAME_stand29 28 #define FRAME_stand30 29 #define FRAME_forwrd01 30 #define FRAME_forwrd02 31 #define FRAME_forwrd03 32 #define FRAME_forwrd04 33 #define FRAME_forwrd05 34 #define FRAME_forwrd06 35 #define FRAME_forwrd07 36 #define FRAME_forwrd08 37 #define FRAME_forwrd09 38 #define FRAME_forwrd10 39 #define FRAME_forwrd11 40 #define FRAME_forwrd12 41 #define FRAME_forwrd13 42 #define FRAME_forwrd14 43 #define FRAME_forwrd15 44 #define FRAME_forwrd16 45 #define FRAME_forwrd17 46 #define FRAME_forwrd18 47 #define FRAME_forwrd19 48 #define FRAME_forwrd20 49 #define FRAME_forwrd21 50 #define FRAME_forwrd22 51 #define FRAME_forwrd23 52 #define FRAME_forwrd24 53 #define FRAME_forwrd25 54 #define FRAME_forwrd26 55 #define FRAME_forwrd27 56 #define FRAME_forwrd28 57 #define FRAME_forwrd29 58 #define FRAME_forwrd30 59 #define FRAME_forwrd31 60 #define FRAME_forwrd32 61 #define FRAME_forwrd33 62 #define FRAME_forwrd34 63 #define FRAME_forwrd35 64 #define FRAME_stop101 65 #define FRAME_stop102 66 #define FRAME_stop103 67 #define FRAME_stop104 68 #define FRAME_stop105 69 #define FRAME_stop106 70 #define FRAME_stop107 71 #define FRAME_stop108 72 #define FRAME_stop109 73 #define FRAME_stop201 74 #define FRAME_stop202 75 #define FRAME_stop203 76 #define FRAME_stop204 77 #define FRAME_stop205 78 #define FRAME_stop206 79 #define FRAME_stop207 80 #define FRAME_stop208 81 #define FRAME_takeof01 82 #define FRAME_takeof02 83 #define FRAME_takeof03 84 #define FRAME_takeof04 85 #define FRAME_takeof05 86 #define FRAME_takeof06 87 #define FRAME_takeof07 88 #define FRAME_takeof08 89 #define FRAME_takeof09 90 #define FRAME_takeof10 91 #define FRAME_takeof11 92 #define FRAME_takeof12 93 #define FRAME_takeof13 94 #define FRAME_takeof14 95 #define FRAME_takeof15 96 #define FRAME_takeof16 97 #define FRAME_takeof17 98 #define FRAME_takeof18 99 #define FRAME_takeof19 100 #define FRAME_takeof20 101 #define FRAME_takeof21 102 #define FRAME_takeof22 103 #define FRAME_takeof23 104 #define FRAME_takeof24 105 #define FRAME_takeof25 106 #define FRAME_takeof26 107 #define FRAME_takeof27 108 #define FRAME_takeof28 109 #define FRAME_takeof29 110 #define FRAME_takeof30 111 #define FRAME_land01 112 #define FRAME_pain101 113 #define FRAME_pain102 114 #define FRAME_pain103 115 #define FRAME_pain104 116 #define FRAME_pain105 117 #define FRAME_pain106 118 #define FRAME_pain107 119 #define FRAME_pain108 120 #define FRAME_pain109 121 #define FRAME_pain110 122 #define FRAME_pain111 123 #define FRAME_pain112 124 #define FRAME_pain113 125 #define FRAME_pain114 126 #define FRAME_pain115 127 #define FRAME_pain116 128 #define FRAME_pain117 129 #define FRAME_pain118 130 #define FRAME_pain119 131 #define FRAME_pain120 132 #define FRAME_pain121 133 #define FRAME_pain122 134 #define FRAME_pain123 135 #define FRAME_pain124 136 #define FRAME_pain125 137 #define FRAME_pain126 138 #define FRAME_pain127 139 #define FRAME_pain128 140 #define FRAME_pain201 141 #define FRAME_pain202 142 #define FRAME_pain203 143 #define FRAME_pain204 144 #define FRAME_pain205 145 #define FRAME_pain206 146 #define FRAME_pain207 147 #define FRAME_pain208 148 #define FRAME_pain209 149 #define FRAME_pain210 150 #define FRAME_pain211 151 #define FRAME_pain212 152 #define FRAME_pain301 153 #define FRAME_pain302 154 #define FRAME_pain303 155 #define FRAME_pain304 156 #define FRAME_pain305 157 #define FRAME_pain306 158 #define FRAME_pain307 159 #define FRAME_pain308 160 #define FRAME_pain309 161 #define FRAME_death101 162 #define FRAME_death102 163 #define FRAME_death103 164 #define FRAME_death104 165 #define FRAME_death105 166 #define FRAME_death106 167 #define FRAME_death107 168 #define FRAME_death108 169 #define FRAME_death109 170 #define FRAME_death110 171 #define FRAME_death111 172 #define FRAME_backwd01 173 #define FRAME_backwd02 174 #define FRAME_backwd03 175 #define FRAME_backwd04 176 #define FRAME_backwd05 177 #define FRAME_backwd06 178 #define FRAME_backwd07 179 #define FRAME_backwd08 180 #define FRAME_backwd09 181 #define FRAME_backwd10 182 #define FRAME_backwd11 183 #define FRAME_backwd12 184 #define FRAME_backwd13 185 #define FRAME_backwd14 186 #define FRAME_backwd15 187 #define FRAME_backwd16 188 #define FRAME_backwd17 189 #define FRAME_backwd18 190 #define FRAME_backwd19 191 #define FRAME_backwd20 192 #define FRAME_backwd21 193 #define FRAME_backwd22 194 #define FRAME_backwd23 195 #define FRAME_backwd24 196 #define FRAME_attak101 197 #define FRAME_attak102 198 #define FRAME_attak103 199 #define FRAME_attak104 200 #define FRAME_attak105 201 #define FRAME_attak106 202 #define FRAME_attak107 203 #define FRAME_attak108 204 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/infantry/000077500000000000000000000000001477320066100177205ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/infantry/infantry.c000066400000000000000000000502211477320066100217160ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Infantry. * * ======================================================================= */ #include "../../header/local.h" #include "infantry.h" void InfantryMachineGun(edict_t *self); static int sound_pain1; static int sound_pain2; static int sound_die1; static int sound_die2; static int sound_gunshot; static int sound_weapon_cock; static int sound_punch_swing; static int sound_punch_hit; static int sound_sight; static int sound_search; static int sound_idle; static int sound_step; static int sound_step2; void infantry_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("infantry/step1.wav"); sound_step2 = gi.soundindex("infantry/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } static mframe_t infantry_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t infantry_move_stand = { FRAME_stand50, FRAME_stand71, infantry_frames_stand, NULL }; void infantry_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &infantry_move_stand; } static mframe_t infantry_frames_fidget[] = { {ai_stand, 1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 1, NULL}, {ai_stand, 3, NULL}, {ai_stand, 6, NULL}, {ai_stand, 3, infantry_footstep}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 1, NULL}, {ai_stand, 0, NULL}, {ai_stand, -1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 1, NULL}, {ai_stand, 0, NULL}, {ai_stand, -2, NULL}, {ai_stand, 1, NULL}, {ai_stand, 1, NULL}, {ai_stand, 1, NULL}, {ai_stand, -1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, -1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, -1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 1, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, -1, NULL}, {ai_stand, -1, NULL}, {ai_stand, 0, NULL}, {ai_stand, -3, NULL}, {ai_stand, -2, NULL}, {ai_stand, -3, NULL}, {ai_stand, -3, infantry_footstep}, {ai_stand, -2, NULL} }; mmove_t infantry_move_fidget = { FRAME_stand01, FRAME_stand49, infantry_frames_fidget, infantry_stand }; void infantry_fidget(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &infantry_move_fidget; gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } static mframe_t infantry_frames_walk[] = { {ai_walk, 5, infantry_footstep}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 5, NULL}, {ai_walk, 4, NULL}, {ai_walk, 5, NULL}, {ai_walk, 6, infantry_footstep}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 5, NULL} }; mmove_t infantry_move_walk = { FRAME_walk03, FRAME_walk14, infantry_frames_walk, NULL }; void infantry_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &infantry_move_walk; } static mframe_t infantry_frames_run[] = { {ai_run, 10, NULL}, {ai_run, 20, infantry_footstep}, {ai_run, 5, NULL}, {ai_run, 7, monster_done_dodge}, {ai_run, 30, NULL}, {ai_run, 35, infantry_footstep}, {ai_run, 2, NULL}, {ai_run, 6, NULL} }; mmove_t infantry_move_run = { FRAME_run01, FRAME_run08, infantry_frames_run, NULL }; void infantry_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &infantry_move_stand; } else { self->monsterinfo.currentmove = &infantry_move_run; } } static mframe_t infantry_frames_pain1[] = { {ai_move, -3, NULL}, {ai_move, -2, NULL}, {ai_move, -1, NULL}, {ai_move, -2, NULL}, {ai_move, -1, infantry_footstep}, {ai_move, 1, NULL}, {ai_move, -1, NULL}, {ai_move, 1, NULL}, {ai_move, 6, NULL}, {ai_move, 2, infantry_footstep} }; mmove_t infantry_move_pain1 = { FRAME_pain101, FRAME_pain110, infantry_frames_pain1, infantry_run }; static mframe_t infantry_frames_pain2[] = { {ai_move, -3, NULL}, {ai_move, -3, NULL}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -2, infantry_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 5, NULL}, {ai_move, 2, infantry_footstep} }; mmove_t infantry_move_pain2 = { FRAME_pain201, FRAME_pain210, infantry_frames_pain2, infantry_run }; void infantry_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { int n; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (!self->groundentity) { return; } monster_done_dodge(self); if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } n = rand() % 2; if (n == 0) { self->monsterinfo.currentmove = &infantry_move_pain1; gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &infantry_move_pain2; gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } vec3_t aimangles[] = { {0.0, 5.0, 0.0}, {10.0, 15.0, 0.0}, {20.0, 25.0, 0.0}, {25.0, 35.0, 0.0}, {30.0, 40.0, 0.0}, {30.0, 45.0, 0.0}, {25.0, 50.0, 0.0}, {20.0, 40.0, 0.0}, {15.0, 35.0, 0.0}, {40.0, 35.0, 0.0}, {70.0, 35.0, 0.0}, {90.0, 35.0, 0.0} }; void InfantryMachineGun(edict_t *self) { vec3_t start, target; vec3_t forward, right; vec3_t vec; int flash_number; if (!self) { return; } /* new attack start frame */ if (self->s.frame == FRAME_attak104) { flash_number = MZ2_INFANTRY_MACHINEGUN_1; AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); if (self->enemy && self->enemy->inuse) { VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target); target[2] += self->enemy->viewheight; VectorSubtract(target, start, forward); VectorNormalize(forward); } else { AngleVectors(self->s.angles, forward, right, NULL); } } else { flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211); AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); VectorSubtract(self->s.angles, aimangles[flash_number - MZ2_INFANTRY_MACHINEGUN_2], vec); AngleVectors(vec, forward, NULL, NULL); } monster_fire_bullet(self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); } void infantry_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0); } void infantry_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; gi.linkentity(self); M_FlyCheck(self); } static mframe_t infantry_frames_death1[] = { {ai_move, -4, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -4, infantry_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -1, infantry_footstep}, {ai_move, 3, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, -2, NULL}, {ai_move, 2, NULL}, {ai_move, 2, NULL}, {ai_move, 9, NULL}, {ai_move, 9, NULL}, {ai_move, 5, NULL}, {ai_move, -3, NULL}, {ai_move, -3, NULL} }; mmove_t infantry_move_death1 = { FRAME_death101, FRAME_death120, infantry_frames_death1, infantry_dead }; /* Off with his head */ static mframe_t infantry_frames_death2[] = { {ai_move, 0, NULL}, {ai_move, 1, NULL}, {ai_move, 5, NULL}, {ai_move, -1, NULL}, {ai_move, 0, NULL}, {ai_move, 1, infantry_footstep}, {ai_move, 1, infantry_footstep}, {ai_move, 4, NULL}, {ai_move, 3, NULL}, {ai_move, 0, NULL}, {ai_move, -2, InfantryMachineGun}, {ai_move, -2, InfantryMachineGun}, {ai_move, -3, InfantryMachineGun}, {ai_move, -1, InfantryMachineGun}, {ai_move, -2, InfantryMachineGun}, {ai_move, 0, InfantryMachineGun}, {ai_move, 2, InfantryMachineGun}, {ai_move, 2, InfantryMachineGun}, {ai_move, 3, InfantryMachineGun}, {ai_move, -10, InfantryMachineGun}, {ai_move, -7, InfantryMachineGun}, {ai_move, -8, InfantryMachineGun}, {ai_move, -6, NULL}, {ai_move, 4, NULL}, {ai_move, 0, NULL} }; mmove_t infantry_move_death2 = { FRAME_death201, FRAME_death225, infantry_frames_death2, infantry_dead }; static mframe_t infantry_frames_death3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -6, NULL}, {ai_move, -11, NULL}, {ai_move, -3, NULL}, {ai_move, -11, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t infantry_move_death3 = { FRAME_death301, FRAME_death309, infantry_frames_death3, infantry_dead }; void infantry_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->s.skinnum = 1; /* switch to bloody skin */ n = rand() % 3; if (n == 0) { self->monsterinfo.currentmove = &infantry_move_death1; gi.sound(self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); } else if (n == 1) { self->monsterinfo.currentmove = &infantry_move_death2; gi.sound(self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &infantry_move_death3; gi.sound(self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); } } static mframe_t infantry_frames_duck[] = { {ai_move, -2, monster_duck_down}, {ai_move, -5, monster_duck_hold}, {ai_move, 3, NULL}, {ai_move, 4, monster_duck_up}, {ai_move, 0, infantry_footstep} }; mmove_t infantry_move_duck = { FRAME_duck01, FRAME_duck05, infantry_frames_duck, infantry_run }; void infantry_cock_gun(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_weapon_cock, 1, ATTN_NORM, 0); } void infantry_fire(edict_t *self) { if (!self) { return; } InfantryMachineGun(self); if (level.time >= self->monsterinfo.pausetime) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; } else { self->monsterinfo.aiflags |= AI_HOLD_FRAME; } } void infantry_fire_prep(edict_t *self) { int n; if (!self) { return; } n = (rand() & 15) + 3 + 1; self->monsterinfo.pausetime = level.time + n * FRAMETIME; } static mframe_t infantry_frames_attack1[] = { {ai_charge, -3, NULL}, /* 101 */ {ai_charge, -2, NULL}, /* 102 */ {ai_charge, -1, infantry_fire_prep}, /* 103 */ {ai_charge, 5, infantry_fire}, /* 104 */ {ai_charge, 1, NULL}, /* 105 */ {ai_charge, -3, NULL}, /* 106 */ {ai_charge, -2, NULL}, /* 107 */ {ai_charge, 2, infantry_cock_gun}, /* 108 */ {ai_charge, 1, NULL}, /* 109 */ {ai_charge, 1, NULL}, /* 110 */ {ai_charge, -1, NULL}, /* 111 */ {ai_charge, 0, NULL}, /* 112 */ {ai_charge, -1, NULL}, /* 113 */ {ai_charge, -1, NULL}, /* 114 */ {ai_charge, 4, NULL} /* 115 */ }; mmove_t infantry_move_attack1 = { FRAME_attak101, FRAME_attak115, infantry_frames_attack1, infantry_run }; void infantry_swing(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_punch_swing, 1, ATTN_NORM, 0); } void infantry_smack(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, 0, 0); if (fire_hit(self, aim, (5 + (rand() % 5)), 50)) { gi.sound(self, CHAN_WEAPON, sound_punch_hit, 1, ATTN_NORM, 0); } } static mframe_t infantry_frames_attack2[] = { {ai_charge, 3, NULL}, {ai_charge, 6, NULL}, {ai_charge, 0, infantry_swing}, {ai_charge, 8, infantry_footstep}, {ai_charge, 5, NULL}, {ai_charge, 8, infantry_smack}, {ai_charge, 6, NULL}, {ai_charge, 3, NULL}, }; mmove_t infantry_move_attack2 = { FRAME_attak201, FRAME_attak208, infantry_frames_attack2, infantry_run }; void infantry_attack(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (range(self, self->enemy) == RANGE_MELEE) { self->monsterinfo.currentmove = &infantry_move_attack2; } else { self->monsterinfo.currentmove = &infantry_move_attack1; } } void infantry_jump_now(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void infantry_jump2_now(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 150, forward, self->velocity); VectorMA(self->velocity, 400, up, self->velocity); } void infantry_jump_wait_land(edict_t *self) { if (!self) { return; } if (self->groundentity == NULL) { self->monsterinfo.nextframe = self->s.frame; if (monster_jump_finished(self)) { self->monsterinfo.nextframe = self->s.frame + 1; } } else { self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t infantry_frames_jump[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, infantry_jump_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, infantry_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t infantry_move_jump = { FRAME_jump01, FRAME_jump10, infantry_frames_jump, infantry_run }; static mframe_t infantry_frames_jump2[] = { {ai_move, -8, NULL}, {ai_move, -4, NULL}, {ai_move, -4, NULL}, {ai_move, 0, infantry_jump2_now}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, infantry_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t infantry_move_jump2 = { FRAME_jump01, FRAME_jump10, infantry_frames_jump2, infantry_run }; void infantry_jump(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } monster_done_dodge(self); if (self->enemy->absmin[2] > self->absmin[2]) { self->monsterinfo.currentmove = &infantry_move_jump2; } else { self->monsterinfo.currentmove = &infantry_move_jump; } } qboolean infantry_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkjump(self, dist, 192, 40)) { infantry_jump(self); return true; } if (blocked_checkplat(self, dist)) { return true; } return false; } void infantry_duck(edict_t *self, float eta) { if (!self) { return; } /* if we're jumping, don't dodge */ if ((self->monsterinfo.currentmove == &infantry_move_jump) || (self->monsterinfo.currentmove == &infantry_move_jump2)) { return; } if ((self->monsterinfo.currentmove == &infantry_move_attack1) || (self->monsterinfo.currentmove == &infantry_move_attack2)) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DUCKED; return; } } if (skill->value == SKILL_EASY) { /* stupid dodge */ self->monsterinfo.duck_wait_time = level.time + eta + 1; } else { self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } /* has to be done immediately otherwise he can get stuck */ monster_duck_down(self); self->monsterinfo.nextframe = FRAME_duck01; self->monsterinfo.currentmove = &infantry_move_duck; return; } void infantry_sidestep(edict_t *self) { if (!self) { return; } /* if we're jumping, don't dodge */ if ((self->monsterinfo.currentmove == &infantry_move_jump) || (self->monsterinfo.currentmove == &infantry_move_jump2)) { return; } if ((self->monsterinfo.currentmove == &infantry_move_attack1) || (self->monsterinfo.currentmove == &infantry_move_attack2)) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DODGING; return; } } if (self->monsterinfo.currentmove != &infantry_move_run) { self->monsterinfo.currentmove = &infantry_move_run; } } /* * QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_infantry(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_pain1 = gi.soundindex("infantry/infpain1.wav"); sound_pain2 = gi.soundindex("infantry/infpain2.wav"); sound_die1 = gi.soundindex("infantry/infdeth1.wav"); sound_die2 = gi.soundindex("infantry/infdeth2.wav"); sound_gunshot = gi.soundindex("infantry/infatck1.wav"); sound_weapon_cock = gi.soundindex("infantry/infatck3.wav"); sound_punch_swing = gi.soundindex("infantry/infatck2.wav"); sound_punch_hit = gi.soundindex("infantry/melee2.wav"); sound_sight = gi.soundindex("infantry/infsght1.wav"); sound_search = gi.soundindex("infantry/infsrch1.wav"); sound_idle = gi.soundindex("infantry/infidle1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->health = 100; self->gib_health = -40; self->mass = 200; self->pain = infantry_pain; self->die = infantry_die; self->monsterinfo.stand = infantry_stand; self->monsterinfo.walk = infantry_walk; self->monsterinfo.run = infantry_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.duck = infantry_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.sidestep = infantry_sidestep; self->monsterinfo.attack = infantry_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = infantry_sight; self->monsterinfo.idle = infantry_fidget; self->monsterinfo.blocked = infantry_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &infantry_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/infantry/infantry.h000066400000000000000000000167071477320066100217360ustar00rootroot00000000000000/* ======================================================================= * * Infantry animations. * * ======================================================================= */ #define FRAME_gun02 0 #define FRAME_stand01 1 #define FRAME_stand02 2 #define FRAME_stand03 3 #define FRAME_stand04 4 #define FRAME_stand05 5 #define FRAME_stand06 6 #define FRAME_stand07 7 #define FRAME_stand08 8 #define FRAME_stand09 9 #define FRAME_stand10 10 #define FRAME_stand11 11 #define FRAME_stand12 12 #define FRAME_stand13 13 #define FRAME_stand14 14 #define FRAME_stand15 15 #define FRAME_stand16 16 #define FRAME_stand17 17 #define FRAME_stand18 18 #define FRAME_stand19 19 #define FRAME_stand20 20 #define FRAME_stand21 21 #define FRAME_stand22 22 #define FRAME_stand23 23 #define FRAME_stand24 24 #define FRAME_stand25 25 #define FRAME_stand26 26 #define FRAME_stand27 27 #define FRAME_stand28 28 #define FRAME_stand29 29 #define FRAME_stand30 30 #define FRAME_stand31 31 #define FRAME_stand32 32 #define FRAME_stand33 33 #define FRAME_stand34 34 #define FRAME_stand35 35 #define FRAME_stand36 36 #define FRAME_stand37 37 #define FRAME_stand38 38 #define FRAME_stand39 39 #define FRAME_stand40 40 #define FRAME_stand41 41 #define FRAME_stand42 42 #define FRAME_stand43 43 #define FRAME_stand44 44 #define FRAME_stand45 45 #define FRAME_stand46 46 #define FRAME_stand47 47 #define FRAME_stand48 48 #define FRAME_stand49 49 #define FRAME_stand50 50 #define FRAME_stand51 51 #define FRAME_stand52 52 #define FRAME_stand53 53 #define FRAME_stand54 54 #define FRAME_stand55 55 #define FRAME_stand56 56 #define FRAME_stand57 57 #define FRAME_stand58 58 #define FRAME_stand59 59 #define FRAME_stand60 60 #define FRAME_stand61 61 #define FRAME_stand62 62 #define FRAME_stand63 63 #define FRAME_stand64 64 #define FRAME_stand65 65 #define FRAME_stand66 66 #define FRAME_stand67 67 #define FRAME_stand68 68 #define FRAME_stand69 69 #define FRAME_stand70 70 #define FRAME_stand71 71 #define FRAME_walk01 72 #define FRAME_walk02 73 #define FRAME_walk03 74 #define FRAME_walk04 75 #define FRAME_walk05 76 #define FRAME_walk06 77 #define FRAME_walk07 78 #define FRAME_walk08 79 #define FRAME_walk09 80 #define FRAME_walk10 81 #define FRAME_walk11 82 #define FRAME_walk12 83 #define FRAME_walk13 84 #define FRAME_walk14 85 #define FRAME_walk15 86 #define FRAME_walk16 87 #define FRAME_walk17 88 #define FRAME_walk18 89 #define FRAME_walk19 90 #define FRAME_walk20 91 #define FRAME_run01 92 #define FRAME_run02 93 #define FRAME_run03 94 #define FRAME_run04 95 #define FRAME_run05 96 #define FRAME_run06 97 #define FRAME_run07 98 #define FRAME_run08 99 #define FRAME_pain101 100 #define FRAME_pain102 101 #define FRAME_pain103 102 #define FRAME_pain104 103 #define FRAME_pain105 104 #define FRAME_pain106 105 #define FRAME_pain107 106 #define FRAME_pain108 107 #define FRAME_pain109 108 #define FRAME_pain110 109 #define FRAME_pain201 110 #define FRAME_pain202 111 #define FRAME_pain203 112 #define FRAME_pain204 113 #define FRAME_pain205 114 #define FRAME_pain206 115 #define FRAME_pain207 116 #define FRAME_pain208 117 #define FRAME_pain209 118 #define FRAME_pain210 119 #define FRAME_duck01 120 #define FRAME_duck02 121 #define FRAME_duck03 122 #define FRAME_duck04 123 #define FRAME_duck05 124 #define FRAME_death101 125 #define FRAME_death102 126 #define FRAME_death103 127 #define FRAME_death104 128 #define FRAME_death105 129 #define FRAME_death106 130 #define FRAME_death107 131 #define FRAME_death108 132 #define FRAME_death109 133 #define FRAME_death110 134 #define FRAME_death111 135 #define FRAME_death112 136 #define FRAME_death113 137 #define FRAME_death114 138 #define FRAME_death115 139 #define FRAME_death116 140 #define FRAME_death117 141 #define FRAME_death118 142 #define FRAME_death119 143 #define FRAME_death120 144 #define FRAME_death201 145 #define FRAME_death202 146 #define FRAME_death203 147 #define FRAME_death204 148 #define FRAME_death205 149 #define FRAME_death206 150 #define FRAME_death207 151 #define FRAME_death208 152 #define FRAME_death209 153 #define FRAME_death210 154 #define FRAME_death211 155 #define FRAME_death212 156 #define FRAME_death213 157 #define FRAME_death214 158 #define FRAME_death215 159 #define FRAME_death216 160 #define FRAME_death217 161 #define FRAME_death218 162 #define FRAME_death219 163 #define FRAME_death220 164 #define FRAME_death221 165 #define FRAME_death222 166 #define FRAME_death223 167 #define FRAME_death224 168 #define FRAME_death225 169 #define FRAME_death301 170 #define FRAME_death302 171 #define FRAME_death303 172 #define FRAME_death304 173 #define FRAME_death305 174 #define FRAME_death306 175 #define FRAME_death307 176 #define FRAME_death308 177 #define FRAME_death309 178 #define FRAME_block01 179 #define FRAME_block02 180 #define FRAME_block03 181 #define FRAME_block04 182 #define FRAME_block05 183 #define FRAME_attak101 184 #define FRAME_attak102 185 #define FRAME_attak103 186 #define FRAME_attak104 187 #define FRAME_attak105 188 #define FRAME_attak106 189 #define FRAME_attak107 190 #define FRAME_attak108 191 #define FRAME_attak109 192 #define FRAME_attak110 193 #define FRAME_attak111 194 #define FRAME_attak112 195 #define FRAME_attak113 196 #define FRAME_attak114 197 #define FRAME_attak115 198 #define FRAME_attak201 199 #define FRAME_attak202 200 #define FRAME_attak203 201 #define FRAME_attak204 202 #define FRAME_attak205 203 #define FRAME_attak206 204 #define FRAME_attak207 205 #define FRAME_attak208 206 #define FRAME_jump01 207 #define FRAME_jump02 208 #define FRAME_jump03 209 #define FRAME_jump04 210 #define FRAME_jump05 211 #define FRAME_jump06 212 #define FRAME_jump07 213 #define FRAME_jump08 214 #define FRAME_jump09 215 #define FRAME_jump10 216 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/insane/000077500000000000000000000000001477320066100173435ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/insane/insane.c000066400000000000000000000473301477320066100207730ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * The insane earth soldiers. * * ======================================================================= */ #include "../../header/local.h" #include "insane.h" #define SPAWNFLAG_CRUSIFIED 8 static int sound_fist; static int sound_shake; static int sound_moan; static int sound_scream[8]; static int sound_step; static int sound_step2; static int sound_step3; static int sound_step4; void insane_stand(edict_t *self); void insane_dead(edict_t *self); void insane_cross(edict_t *self); void insane_walk(edict_t *self); void insane_run(edict_t *self); void insane_checkdown(edict_t *self); void insane_checkup(edict_t *self); void insane_onground(edict_t *self); void insane_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0 || sound_step3 == 0 || sound_step4 == 0) { sound_step = gi.soundindex("player/step1.wav"); sound_step2 = gi.soundindex("player/step2.wav"); sound_step3 = gi.soundindex("player/step3.wav"); sound_step4 = gi.soundindex("player/step4.wav"); } int i; i = randk() % 4; if (i == 0) { gi.sound(self, CHAN_BODY, sound_step, 0.7, ATTN_NORM, 0); } else if (i == 1) { gi.sound(self, CHAN_BODY, sound_step2, 0.7, ATTN_NORM, 0); } else if (i == 2) { gi.sound(self, CHAN_BODY, sound_step3, 0.7, ATTN_NORM, 0); } else if (i == 3) { gi.sound(self, CHAN_BODY, sound_step4, 0.7, ATTN_NORM, 0); } } void insane_fist(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_fist, 1, ATTN_IDLE, 0); } void insane_shake(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_shake, 1, ATTN_IDLE, 0); } void insane_moan(edict_t *self) { if (!self) { return; } /* suppress screaming so pain sounds can play */ if (self->fly_sound_debounce_time > level.time) { return; } gi.sound(self, CHAN_VOICE, sound_moan, 1, ATTN_IDLE, 0); } void insane_scream(edict_t *self) { if (!self) { return; } /* suppress screaming so pain sounds can play */ if (self->fly_sound_debounce_time > level.time) { return; } gi.sound(self, CHAN_VOICE, sound_scream[rand() % 8], 1, ATTN_IDLE, 0); } static mframe_t insane_frames_stand_normal[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, insane_checkdown} }; mmove_t insane_move_stand_normal = { FRAME_stand60, FRAME_stand65, insane_frames_stand_normal, insane_stand }; static mframe_t insane_frames_stand_insane[] = { {ai_stand, 0, insane_shake}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, insane_checkdown} }; mmove_t insane_move_stand_insane = { FRAME_stand65, FRAME_stand94, insane_frames_stand_insane, insane_stand }; static mframe_t insane_frames_uptodown[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_moan}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2.7, NULL}, {ai_move, 4.1, NULL}, {ai_move, 6, NULL}, {ai_move, 7.6, NULL}, {ai_move, 3.6, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_fist}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_fist}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_uptodown = { FRAME_stand1, FRAME_stand40, insane_frames_uptodown, insane_onground }; static mframe_t insane_frames_downtoup[] = { {ai_move, -0.7, NULL}, /* 41 */ {ai_move, -1.2, NULL}, /* 42 */ {ai_move, -1.5, NULL}, /* 43 */ {ai_move, -4.5, NULL}, /* 44 */ {ai_move, -3.5, NULL}, /* 45 */ {ai_move, -0.2, NULL}, /* 46 */ {ai_move, 0, NULL}, /* 47 */ {ai_move, -1.3, NULL}, /* 48 */ {ai_move, -3, NULL}, /* 49 */ {ai_move, -2, NULL}, /* 50 */ {ai_move, 0, NULL}, /* 51 */ {ai_move, 0, NULL}, /* 52 */ {ai_move, 0, NULL}, /* 53 */ {ai_move, -3.3, NULL}, /* 54 */ {ai_move, -1.6, NULL}, /* 55 */ {ai_move, -0.3, NULL}, /* 56 */ {ai_move, 0, NULL}, /* 57 */ {ai_move, 0, NULL}, /* 58 */ {ai_move, 0, NULL} /* 59 */ }; mmove_t insane_move_downtoup = { FRAME_stand41, FRAME_stand59, insane_frames_downtoup, insane_stand }; static mframe_t insane_frames_jumpdown[] = { {ai_move, 0.2, NULL}, {ai_move, 11.5, NULL}, {ai_move, 5.1, NULL}, {ai_move, 7.1, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_jumpdown = { FRAME_stand96, FRAME_stand100, insane_frames_jumpdown, insane_onground }; static mframe_t insane_frames_down[] = { {ai_move, 0, NULL}, /* 100 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 110 */ {ai_move, -1.7, NULL}, {ai_move, -1.6, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_fist}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 120 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 130 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_moan}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 140 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 150 */ {ai_move, 0.5, NULL}, {ai_move, 0, NULL}, {ai_move, -0.2, insane_scream}, {ai_move, 0, NULL}, {ai_move, 0.2, NULL}, {ai_move, 0.4, NULL}, {ai_move, 0.6, NULL}, {ai_move, 0.8, NULL}, {ai_move, 0.7, NULL}, {ai_move, 0, insane_checkup} /* 160 */ }; mmove_t insane_move_down = { FRAME_stand100, FRAME_stand160, insane_frames_down, insane_onground }; static mframe_t insane_frames_walk_normal[] = { {ai_walk, 0, insane_scream}, {ai_walk, 2.5, NULL}, {ai_walk, 3.5, NULL}, {ai_walk, 1.7, NULL}, {ai_walk, 2.3, NULL}, {ai_walk, 2.4, NULL}, {ai_walk, 2.2, insane_footstep}, {ai_walk, 4.2, NULL}, {ai_walk, 5.6, NULL}, {ai_walk, 3.3, NULL}, {ai_walk, 2.4, NULL}, {ai_walk, 0.9, NULL}, {ai_walk, 0, insane_footstep} }; mmove_t insane_move_walk_normal = { FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_walk }; mmove_t insane_move_run_normal = { FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_run }; static mframe_t insane_frames_walk_insane[] = { {ai_walk, 0, insane_scream}, /* walk 1 */ {ai_walk, 3.4, NULL}, /* walk 2 */ {ai_walk, 3.6, NULL}, /* 3 */ {ai_walk, 2.9, NULL}, /* 4 */ {ai_walk, 2.2, NULL}, /* 5 */ {ai_walk, 2.6, NULL}, /* 6 */ {ai_walk, 0, insane_footstep}, /* 7 */ {ai_walk, 0.7, NULL}, /* 8 */ {ai_walk, 4.8, NULL}, /* 9 */ {ai_walk, 5.3, NULL}, /* 10 */ {ai_walk, 1.1, NULL}, /* 11 */ {ai_walk, 2, insane_footstep}, /* 12 */ {ai_walk, 0.5, NULL}, /* 13 */ {ai_walk, 0, NULL}, /* 14 */ {ai_walk, 0, NULL}, /* 15 */ {ai_walk, 4.9, NULL}, /* 16 */ {ai_walk, 6.7, NULL}, /* 17 */ {ai_walk, 3.8, NULL}, /* 18 */ {ai_walk, 2, insane_footstep}, /* 19 */ {ai_walk, 0.2, NULL}, /* 20 */ {ai_walk, 0, NULL}, /* 21 */ {ai_walk, 3.4, NULL}, /* 22 */ {ai_walk, 6.4, NULL}, /* 23 */ {ai_walk, 5, NULL}, /* 24 */ {ai_walk, 1.8, insane_footstep}, /* 25 */ {ai_walk, 0, NULL} /* 26 */ }; mmove_t insane_move_walk_insane = { FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_walk }; mmove_t insane_move_run_insane = { FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_run }; static mframe_t insane_frames_stand_pain[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, insane_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_stand_pain = { FRAME_st_pain2, FRAME_st_pain12, insane_frames_stand_pain, insane_run }; static mframe_t insane_frames_stand_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_stand_death = { FRAME_st_death2, FRAME_st_death18, insane_frames_stand_death, insane_dead }; static mframe_t insane_frames_crawl[] = { {ai_walk, 0, insane_scream}, {ai_walk, 1.5, NULL}, {ai_walk, 2.1, NULL}, {ai_walk, 3.6, NULL}, {ai_walk, 2, NULL}, {ai_walk, 0.9, NULL}, {ai_walk, 3, NULL}, {ai_walk, 3.4, NULL}, {ai_walk, 2.4, NULL} }; mmove_t insane_move_crawl = { FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL }; mmove_t insane_move_runcrawl = { FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL }; static mframe_t insane_frames_crawl_pain[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_crawl_pain = { FRAME_cr_pain2, FRAME_cr_pain10, insane_frames_crawl_pain, insane_run }; static mframe_t insane_frames_crawl_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_crawl_death = { FRAME_cr_death10, FRAME_cr_death16, insane_frames_crawl_death, insane_dead }; static mframe_t insane_frames_cross[] = { {ai_move, 0, insane_moan}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_cross = { FRAME_cross1, FRAME_cross15, insane_frames_cross, insane_cross }; static mframe_t insane_frames_struggle_cross[] = { {ai_move, 0, insane_scream}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t insane_move_struggle_cross = { FRAME_cross16, FRAME_cross30, insane_frames_struggle_cross, insane_cross }; void insane_cross(edict_t *self) { if (!self) { return; } if (random() < 0.8) { self->monsterinfo.currentmove = &insane_move_cross; } else { self->monsterinfo.currentmove = &insane_move_struggle_cross; } } void insane_walk(edict_t *self) { if (!self) { return; } if (self->spawnflags & 16) /* Hold Ground? */ { if (self->s.frame == FRAME_cr_pain10) { self->monsterinfo.currentmove = &insane_move_down; return; } } if (self->spawnflags & 4) { self->monsterinfo.currentmove = &insane_move_crawl; } else if (random() <= 0.5) { self->monsterinfo.currentmove = &insane_move_walk_normal; } else { self->monsterinfo.currentmove = &insane_move_walk_insane; } } void insane_run(edict_t *self) { if (!self) { return; } if (self->spawnflags & 16) /* Hold Ground? */ { if (self->s.frame == FRAME_cr_pain10) { self->monsterinfo.currentmove = &insane_move_down; return; } } if (self->spawnflags & 4) /* Crawling? */ { self->monsterinfo.currentmove = &insane_move_runcrawl; } else if (random() <= 0.5) /* Else, mix it up */ { self->monsterinfo.currentmove = &insane_move_run_normal; } else { self->monsterinfo.currentmove = &insane_move_run_insane; } } void insane_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage) { int l, r; if (!self) { return; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; r = 1 + (rand() & 1); if (self->health < 25) { l = 25; } else if (self->health < 50) { l = 50; } else if (self->health < 75) { l = 75; } else { l = 100; } gi.sound(self, CHAN_VOICE, gi.soundindex(va("player/male/pain%i_%i.wav", l, r)), 1, ATTN_IDLE, 0); /* suppress screaming and moaning for 1 second so pain sound plays */ self->fly_sound_debounce_time = level.time + 1; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } /* Don't go into pain frames if crucified. */ if (self->spawnflags & SPAWNFLAG_CRUSIFIED) { self->monsterinfo.currentmove = &insane_move_struggle_cross; return; } if (((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160))) { self->monsterinfo.currentmove = &insane_move_crawl_pain; } else { self->monsterinfo.currentmove = &insane_move_stand_pain; } } void insane_onground(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &insane_move_down; } void insane_checkdown(edict_t *self) { if (!self) { return; } if (self->spawnflags & 32) /* Always stand */ { return; } if (random() < 0.3) { if (random() < 0.5) { self->monsterinfo.currentmove = &insane_move_uptodown; } else { self->monsterinfo.currentmove = &insane_move_jumpdown; } } } void insane_checkup(edict_t *self) { if (!self) { return; } /* If Hold_Ground and Crawl are set */ if ((self->spawnflags & 4) && (self->spawnflags & 16)) { return; } if (random() < 0.5) { self->monsterinfo.currentmove = &insane_move_downtoup; } } void insane_stand(edict_t *self) { if (!self) { return; } if (self->spawnflags & SPAWNFLAG_CRUSIFIED) /* If crucified */ { self->monsterinfo.currentmove = &insane_move_cross; self->monsterinfo.aiflags |= AI_STAND_GROUND; } /* If Hold_Ground and Crawl are set */ else if ((self->spawnflags & 4) && (self->spawnflags & 16)) { self->monsterinfo.currentmove = &insane_move_down; } else if (random() < 0.5) { self->monsterinfo.currentmove = &insane_move_stand_normal; } else { self->monsterinfo.currentmove = &insane_move_stand_insane; } } void insane_dead(edict_t *self) { if (!self) { return; } if (self->spawnflags & SPAWNFLAG_CRUSIFIED) { self->flags |= FL_FLY; } else { VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; } self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void insane_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_IDLE, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } gi.sound(self, CHAN_VOICE, gi.soundindex(va("player/male/death%i.wav", (rand() % 4) + 1)), 1, ATTN_IDLE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; if (self->spawnflags & SPAWNFLAG_CRUSIFIED) { insane_dead(self); } else { if (((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160))) { self->monsterinfo.currentmove = &insane_move_crawl_death; } else { self->monsterinfo.currentmove = &insane_move_stand_death; } } } /* * QUAKED misc_insane (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn CRAWL CRUCIFIED STAND_GROUND ALWAYS_STAND */ void SP_misc_insane(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_step3 = 0; sound_step4 = 0; sound_fist = gi.soundindex("insane/insane11.wav"); sound_shake = gi.soundindex("insane/insane5.wav"); sound_moan = gi.soundindex("insane/insane7.wav"); sound_scream[0] = gi.soundindex("insane/insane1.wav"); sound_scream[1] = gi.soundindex("insane/insane2.wav"); sound_scream[2] = gi.soundindex("insane/insane3.wav"); sound_scream[3] = gi.soundindex("insane/insane4.wav"); sound_scream[4] = gi.soundindex("insane/insane6.wav"); sound_scream[5] = gi.soundindex("insane/insane8.wav"); sound_scream[6] = gi.soundindex("insane/insane9.wav"); sound_scream[7] = gi.soundindex("insane/insane10.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/insane/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->health = 100; self->gib_health = -50; self->mass = 300; self->pain = insane_pain; self->die = insane_die; self->monsterinfo.stand = insane_stand; self->monsterinfo.walk = insane_walk; self->monsterinfo.run = insane_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = NULL; self->monsterinfo.melee = NULL; self->monsterinfo.sight = NULL; self->monsterinfo.aiflags |= AI_GOOD_GUY; gi.linkentity(self); if (self->spawnflags & 16) /* Stand Ground */ { self->monsterinfo.aiflags |= AI_STAND_GROUND; } self->monsterinfo.currentmove = &insane_move_stand_normal; self->monsterinfo.scale = MODEL_SCALE; if (self->spawnflags & SPAWNFLAG_CRUSIFIED) /* Crucified ? */ { VectorSet(self->mins, -16, 0, 0); VectorSet(self->maxs, 16, 8, 32); self->flags |= FL_NO_KNOCKBACK; flymonster_start(self); } else { walkmonster_start(self); self->s.skinnum = rand() % 3; } } rogue-ROGUE_2_13/src/monster/insane/insane.h000066400000000000000000000233671477320066100210040ustar00rootroot00000000000000/* ======================================================================= * * Insane animations * * ======================================================================= */ #define FRAME_stand1 0 #define FRAME_stand2 1 #define FRAME_stand3 2 #define FRAME_stand4 3 #define FRAME_stand5 4 #define FRAME_stand6 5 #define FRAME_stand7 6 #define FRAME_stand8 7 #define FRAME_stand9 8 #define FRAME_stand10 9 #define FRAME_stand11 10 #define FRAME_stand12 11 #define FRAME_stand13 12 #define FRAME_stand14 13 #define FRAME_stand15 14 #define FRAME_stand16 15 #define FRAME_stand17 16 #define FRAME_stand18 17 #define FRAME_stand19 18 #define FRAME_stand20 19 #define FRAME_stand21 20 #define FRAME_stand22 21 #define FRAME_stand23 22 #define FRAME_stand24 23 #define FRAME_stand25 24 #define FRAME_stand26 25 #define FRAME_stand27 26 #define FRAME_stand28 27 #define FRAME_stand29 28 #define FRAME_stand30 29 #define FRAME_stand31 30 #define FRAME_stand32 31 #define FRAME_stand33 32 #define FRAME_stand34 33 #define FRAME_stand35 34 #define FRAME_stand36 35 #define FRAME_stand37 36 #define FRAME_stand38 37 #define FRAME_stand39 38 #define FRAME_stand40 39 #define FRAME_stand41 40 #define FRAME_stand42 41 #define FRAME_stand43 42 #define FRAME_stand44 43 #define FRAME_stand45 44 #define FRAME_stand46 45 #define FRAME_stand47 46 #define FRAME_stand48 47 #define FRAME_stand49 48 #define FRAME_stand50 49 #define FRAME_stand51 50 #define FRAME_stand52 51 #define FRAME_stand53 52 #define FRAME_stand54 53 #define FRAME_stand55 54 #define FRAME_stand56 55 #define FRAME_stand57 56 #define FRAME_stand58 57 #define FRAME_stand59 58 #define FRAME_stand60 59 #define FRAME_stand61 60 #define FRAME_stand62 61 #define FRAME_stand63 62 #define FRAME_stand64 63 #define FRAME_stand65 64 #define FRAME_stand66 65 #define FRAME_stand67 66 #define FRAME_stand68 67 #define FRAME_stand69 68 #define FRAME_stand70 69 #define FRAME_stand71 70 #define FRAME_stand72 71 #define FRAME_stand73 72 #define FRAME_stand74 73 #define FRAME_stand75 74 #define FRAME_stand76 75 #define FRAME_stand77 76 #define FRAME_stand78 77 #define FRAME_stand79 78 #define FRAME_stand80 79 #define FRAME_stand81 80 #define FRAME_stand82 81 #define FRAME_stand83 82 #define FRAME_stand84 83 #define FRAME_stand85 84 #define FRAME_stand86 85 #define FRAME_stand87 86 #define FRAME_stand88 87 #define FRAME_stand89 88 #define FRAME_stand90 89 #define FRAME_stand91 90 #define FRAME_stand92 91 #define FRAME_stand93 92 #define FRAME_stand94 93 #define FRAME_stand95 94 #define FRAME_stand96 95 #define FRAME_stand97 96 #define FRAME_stand98 97 #define FRAME_stand99 98 #define FRAME_stand100 99 #define FRAME_stand101 100 #define FRAME_stand102 101 #define FRAME_stand103 102 #define FRAME_stand104 103 #define FRAME_stand105 104 #define FRAME_stand106 105 #define FRAME_stand107 106 #define FRAME_stand108 107 #define FRAME_stand109 108 #define FRAME_stand110 109 #define FRAME_stand111 110 #define FRAME_stand112 111 #define FRAME_stand113 112 #define FRAME_stand114 113 #define FRAME_stand115 114 #define FRAME_stand116 115 #define FRAME_stand117 116 #define FRAME_stand118 117 #define FRAME_stand119 118 #define FRAME_stand120 119 #define FRAME_stand121 120 #define FRAME_stand122 121 #define FRAME_stand123 122 #define FRAME_stand124 123 #define FRAME_stand125 124 #define FRAME_stand126 125 #define FRAME_stand127 126 #define FRAME_stand128 127 #define FRAME_stand129 128 #define FRAME_stand130 129 #define FRAME_stand131 130 #define FRAME_stand132 131 #define FRAME_stand133 132 #define FRAME_stand134 133 #define FRAME_stand135 134 #define FRAME_stand136 135 #define FRAME_stand137 136 #define FRAME_stand138 137 #define FRAME_stand139 138 #define FRAME_stand140 139 #define FRAME_stand141 140 #define FRAME_stand142 141 #define FRAME_stand143 142 #define FRAME_stand144 143 #define FRAME_stand145 144 #define FRAME_stand146 145 #define FRAME_stand147 146 #define FRAME_stand148 147 #define FRAME_stand149 148 #define FRAME_stand150 149 #define FRAME_stand151 150 #define FRAME_stand152 151 #define FRAME_stand153 152 #define FRAME_stand154 153 #define FRAME_stand155 154 #define FRAME_stand156 155 #define FRAME_stand157 156 #define FRAME_stand158 157 #define FRAME_stand159 158 #define FRAME_stand160 159 #define FRAME_walk27 160 #define FRAME_walk28 161 #define FRAME_walk29 162 #define FRAME_walk30 163 #define FRAME_walk31 164 #define FRAME_walk32 165 #define FRAME_walk33 166 #define FRAME_walk34 167 #define FRAME_walk35 168 #define FRAME_walk36 169 #define FRAME_walk37 170 #define FRAME_walk38 171 #define FRAME_walk39 172 #define FRAME_walk1 173 #define FRAME_walk2 174 #define FRAME_walk3 175 #define FRAME_walk4 176 #define FRAME_walk5 177 #define FRAME_walk6 178 #define FRAME_walk7 179 #define FRAME_walk8 180 #define FRAME_walk9 181 #define FRAME_walk10 182 #define FRAME_walk11 183 #define FRAME_walk12 184 #define FRAME_walk13 185 #define FRAME_walk14 186 #define FRAME_walk15 187 #define FRAME_walk16 188 #define FRAME_walk17 189 #define FRAME_walk18 190 #define FRAME_walk19 191 #define FRAME_walk20 192 #define FRAME_walk21 193 #define FRAME_walk22 194 #define FRAME_walk23 195 #define FRAME_walk24 196 #define FRAME_walk25 197 #define FRAME_walk26 198 #define FRAME_st_pain2 199 #define FRAME_st_pain3 200 #define FRAME_st_pain4 201 #define FRAME_st_pain5 202 #define FRAME_st_pain6 203 #define FRAME_st_pain7 204 #define FRAME_st_pain8 205 #define FRAME_st_pain9 206 #define FRAME_st_pain10 207 #define FRAME_st_pain11 208 #define FRAME_st_pain12 209 #define FRAME_st_death2 210 #define FRAME_st_death3 211 #define FRAME_st_death4 212 #define FRAME_st_death5 213 #define FRAME_st_death6 214 #define FRAME_st_death7 215 #define FRAME_st_death8 216 #define FRAME_st_death9 217 #define FRAME_st_death10 218 #define FRAME_st_death11 219 #define FRAME_st_death12 220 #define FRAME_st_death13 221 #define FRAME_st_death14 222 #define FRAME_st_death15 223 #define FRAME_st_death16 224 #define FRAME_st_death17 225 #define FRAME_st_death18 226 #define FRAME_crawl1 227 #define FRAME_crawl2 228 #define FRAME_crawl3 229 #define FRAME_crawl4 230 #define FRAME_crawl5 231 #define FRAME_crawl6 232 #define FRAME_crawl7 233 #define FRAME_crawl8 234 #define FRAME_crawl9 235 #define FRAME_cr_pain2 236 #define FRAME_cr_pain3 237 #define FRAME_cr_pain4 238 #define FRAME_cr_pain5 239 #define FRAME_cr_pain6 240 #define FRAME_cr_pain7 241 #define FRAME_cr_pain8 242 #define FRAME_cr_pain9 243 #define FRAME_cr_pain10 244 #define FRAME_cr_death10 245 #define FRAME_cr_death11 246 #define FRAME_cr_death12 247 #define FRAME_cr_death13 248 #define FRAME_cr_death14 249 #define FRAME_cr_death15 250 #define FRAME_cr_death16 251 #define FRAME_cross1 252 #define FRAME_cross2 253 #define FRAME_cross3 254 #define FRAME_cross4 255 #define FRAME_cross5 256 #define FRAME_cross6 257 #define FRAME_cross7 258 #define FRAME_cross8 259 #define FRAME_cross9 260 #define FRAME_cross10 261 #define FRAME_cross11 262 #define FRAME_cross12 263 #define FRAME_cross13 264 #define FRAME_cross14 265 #define FRAME_cross15 266 #define FRAME_cross16 267 #define FRAME_cross17 268 #define FRAME_cross18 269 #define FRAME_cross19 270 #define FRAME_cross20 271 #define FRAME_cross21 272 #define FRAME_cross22 273 #define FRAME_cross23 274 #define FRAME_cross24 275 #define FRAME_cross25 276 #define FRAME_cross26 277 #define FRAME_cross27 278 #define FRAME_cross28 279 #define FRAME_cross29 280 #define FRAME_cross30 281 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/medic/000077500000000000000000000000001477320066100171475ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/medic/medic.c000066400000000000000000001222221477320066100203750ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Medic and Medic commander. * * ======================================================================= */ #include "../../header/local.h" #include "medic.h" #define MEDIC_MIN_DISTANCE 32 #define MEDIC_MAX_HEAL_DISTANCE 400 #define MEDIC_TRY_TIME 10.0 qboolean visible(edict_t *self, edict_t *other); void M_SetEffects(edict_t *ent); qboolean FindTarget(edict_t *self); void HuntTarget(edict_t *self); void FoundTarget(edict_t *self); char *ED_NewString(char *string); void spawngrow_think(edict_t *self); void SpawnGrow_Spawn(vec3_t startpos, int size); void ED_CallSpawn(edict_t *ent); void M_FliesOff(edict_t *self); void M_FliesOn(edict_t *self); static int sound_idle1; static int sound_pain1; static int sound_pain2; static int sound_die; static int sound_sight; static int sound_search; static int sound_hook_launch; static int sound_hook_hit; static int sound_hook_heal; static int sound_hook_retract; static int sound_step; static int sound_step2; /* commander sounds */ static int commander_sound_idle1; static int commander_sound_pain1; static int commander_sound_pain2; static int commander_sound_die; static int commander_sound_sight; static int commander_sound_search; static int commander_sound_hook_launch; static int commander_sound_hook_hit; static int commander_sound_hook_heal; static int commander_sound_hook_retract; static int commander_sound_spawn; char *reinforcements[] = { "monster_soldier_light", /* 0 */ "monster_soldier", /* 1 */ "monster_soldier_ss", /* 2 */ "monster_infantry", /* 3 */ "monster_gunner", /* 4 */ "monster_medic", /* 5 */ "monster_gladiator" /* 6 */ }; vec3_t reinforcement_mins[] = { {-16, -16, -24}, {-16, -16, -24}, {-16, -16, -24}, {-16, -16, -24}, {-16, -16, -24}, {-16, -16, -24}, {-32, -32, -24} }; vec3_t reinforcement_maxs[] = { {16, 16, 32}, {16, 16, 32}, {16, 16, 32}, {16, 16, 32}, {16, 16, 32}, {16, 16, 32}, {32, 32, 64} }; vec3_t reinforcement_position[] = { {80, 0, 0}, {40, 60, 0}, {40, -60, 0}, {0, 80, 0}, {0, -80, 0} }; void medic_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0) { sound_step = gi.soundindex("medic/step1.wav"); sound_step2 = gi.soundindex("medic/step2.wav"); } if (randk() % 2 == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } } void cleanupHeal(edict_t *self, qboolean change_frame) { if (!self) { return; } /* clean up target, if we have one and it's legit */ if (self->enemy && self->enemy->inuse) { self->enemy->monsterinfo.healer = NULL; self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; self->enemy->takedamage = DAMAGE_YES; M_SetEffects(self->enemy); } if (change_frame) { self->monsterinfo.nextframe = FRAME_attack52; } } void abortHeal(edict_t *self, qboolean change_frame, qboolean gib, qboolean mark) { int hurt; static vec3_t pain_normal = {0, 0, 1}; if (!self) { return; } /* clean up target */ cleanupHeal(self, change_frame); /* gib em! */ if ((mark) && (self->enemy) && (self->enemy->inuse)) { if ((self->enemy->monsterinfo.badMedic1) && (self->enemy->monsterinfo.badMedic1->inuse) && (!strncmp(self->enemy->monsterinfo.badMedic1->classname, "monster_medic", 13))) { self->enemy->monsterinfo.badMedic2 = self; } else { self->enemy->monsterinfo.badMedic1 = self; } } if ((gib) && (self->enemy) && (self->enemy->inuse)) { if (self->enemy->gib_health) { hurt = -self->enemy->gib_health; } else { hurt = 500; } T_Damage(self->enemy, self, self, vec3_origin, self->enemy->s.origin, pain_normal, hurt, 0, 0, MOD_UNKNOWN); } /* clean up self */ self->monsterinfo.aiflags &= ~AI_MEDIC; if ((self->oldenemy) && (self->oldenemy->inuse)) { self->enemy = self->oldenemy; } else { self->enemy = NULL; } self->monsterinfo.medicTries = 0; } qboolean canReach(edict_t *self, edict_t *other) { vec3_t spot1; vec3_t spot2; trace_t trace; if (!self || !other) { return false; } VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(other->s.origin, spot2); spot2[2] += other->viewheight; trace = gi.trace(spot1, vec3_origin, vec3_origin, spot2, self, MASK_SHOT | MASK_WATER); if ((trace.fraction == 1.0) || (trace.ent == other)) { return true; } return false; } edict_t * medic_FindDeadMonster(edict_t *self) { float radius; edict_t *ent = NULL; edict_t *best = NULL; if (!self) { return NULL; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { radius = MEDIC_MAX_HEAL_DISTANCE; } else { radius = 1024; } while ((ent = findradius(ent, self->s.origin, radius)) != NULL) { if (ent == self) { continue; } if (!(ent->svflags & SVF_MONSTER)) { continue; } if (ent->monsterinfo.aiflags & AI_GOOD_GUY) { continue; } /* check to make sure we haven't bailed on this guy already */ if ((ent->monsterinfo.badMedic1 == self) || (ent->monsterinfo.badMedic2 == self)) { continue; } if (ent->monsterinfo.healer) { if ((ent->monsterinfo.healer->inuse) && (ent->monsterinfo.healer->health > 0) && (ent->monsterinfo.healer->svflags & SVF_MONSTER) && (ent->monsterinfo.healer->monsterinfo.aiflags & AI_MEDIC)) { continue; } } if (ent->health > 0) { continue; } if ((ent->nextthink) && !((ent->think == M_FliesOn) || (ent->think == M_FliesOff))) { continue; } if (!visible(self, ent)) { continue; } if (!strncmp(ent->classname, "player", 6)) /* stop it from trying to heal player_noise entities */ { continue; } /* make sure we don't spawn people right on top of us */ if (realrange(self, ent) <= MEDIC_MIN_DISTANCE) { continue; } if (!best) { best = ent; continue; } if (ent->max_health <= best->max_health) { continue; } best = ent; } if (best) { self->timestamp = level.time + MEDIC_TRY_TIME; } return best; } void medic_idle(edict_t *self) { edict_t *ent; if (!self) { return; } /* commander sounds */ if (self->mass == 400) { gi.sound(self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); } else { gi.sound(self, CHAN_VOICE, commander_sound_idle1, 1, ATTN_IDLE, 0); } if (!self->oldenemy) { ent = medic_FindDeadMonster(self); if (ent) { self->oldenemy = self->enemy; self->enemy = ent; self->enemy->monsterinfo.healer = self; self->monsterinfo.aiflags |= AI_MEDIC; FoundTarget(self); } } } void medic_search(edict_t *self) { edict_t *ent; if (!self) { return; } /* commander sounds */ if (self->mass == 400) { gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_IDLE, 0); } else { gi.sound(self, CHAN_VOICE, commander_sound_search, 1, ATTN_IDLE, 0); } if (!self->oldenemy) { ent = medic_FindDeadMonster(self); if (ent) { self->oldenemy = self->enemy; self->enemy = ent; self->enemy->monsterinfo.healer = self; self->monsterinfo.aiflags |= AI_MEDIC; FoundTarget(self); } } } void medic_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } /* commander sounds */ if (self->mass == 400) { gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, commander_sound_sight, 1, ATTN_NORM, 0); } } static mframe_t medic_frames_stand[] = { {ai_stand, 0, medic_idle}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, }; mmove_t medic_move_stand = { FRAME_wait1, FRAME_wait90, medic_frames_stand, NULL }; void medic_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &medic_move_stand; } static mframe_t medic_frames_walk[] = { {ai_walk, 6.2, NULL}, {ai_walk, 18.1, medic_footstep}, {ai_walk, 1, NULL}, {ai_walk, 9, NULL}, {ai_walk, 10, NULL}, {ai_walk, 9, NULL}, {ai_walk, 11, NULL}, {ai_walk, 11.6, medic_footstep}, {ai_walk, 2, NULL}, {ai_walk, 9.9, NULL}, {ai_walk, 14, NULL}, {ai_walk, 9.3, NULL} }; mmove_t medic_move_walk = { FRAME_walk1, FRAME_walk12, medic_frames_walk, NULL }; void medic_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &medic_move_walk; } static mframe_t medic_frames_run[] = { {ai_run, 18, medic_footstep}, {ai_run, 22.5, NULL}, {ai_run, 25.4, monster_done_dodge}, {ai_run, 23.4, NULL}, {ai_run, 24, medic_footstep}, {ai_run, 35.6, NULL} }; mmove_t medic_move_run = { FRAME_run1, FRAME_run6, medic_frames_run, NULL }; void medic_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (!(self->monsterinfo.aiflags & AI_MEDIC)) { edict_t *ent; ent = medic_FindDeadMonster(self); if (ent) { self->oldenemy = self->enemy; self->enemy = ent; self->enemy->monsterinfo.healer = self; self->monsterinfo.aiflags |= AI_MEDIC; FoundTarget(self); return; } } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &medic_move_stand; } else { self->monsterinfo.currentmove = &medic_move_run; } } static mframe_t medic_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t medic_move_pain1 = { FRAME_paina1, FRAME_paina8, medic_frames_pain1, medic_run }; static mframe_t medic_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, medic_footstep}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, medic_footstep} }; mmove_t medic_move_pain2 = { FRAME_painb1, FRAME_painb15, medic_frames_pain2, medic_run }; void medic_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage /* unused */) { if (!self) { return; } monster_done_dodge(self); if ((self->health < (self->max_health / 2))) { if (self->mass > 400) { self->s.skinnum = 3; } else { self->s.skinnum = 1; } } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } /* if we're healing someone, we ignore pain */ if (self->monsterinfo.aiflags & AI_MEDIC) { return; } if (self->mass > 400) { if (damage < 35) { gi.sound(self, CHAN_VOICE, commander_sound_pain1, 1, ATTN_NORM, 0); return; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; gi.sound(self, CHAN_VOICE, commander_sound_pain2, 1, ATTN_NORM, 0); if (random() < (min(((float)damage * 0.005), 0.5))) /* no more than 50% chance of big pain */ { self->monsterinfo.currentmove = &medic_move_pain2; } else { self->monsterinfo.currentmove = &medic_move_pain1; } } else if (random() < 0.5) { self->monsterinfo.currentmove = &medic_move_pain1; gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &medic_move_pain2; gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } void medic_fire_blaster(edict_t *self) { vec3_t start; vec3_t forward, right; vec3_t end; vec3_t dir; int effect; int damage = 2; if (!self) { return; } /* paranoia checking */ if (!(self->enemy && self->enemy->inuse)) { return; } if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12)) { effect = EF_BLASTER; } else if ((self->s.frame == FRAME_attack19) || (self->s.frame == FRAME_attack22) || (self->s.frame == FRAME_attack25) || (self->s.frame == FRAME_attack28)) { effect = EF_HYPERBLASTER; } else { effect = 0; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start); VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, dir); if (!strcmp(self->enemy->classname, "tesla")) { damage = 3; } /* medic commander shoots blaster2 */ if (self->mass > 400) { monster_fire_blaster2(self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_2, effect); } else { monster_fire_blaster(self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_1, effect); } } void medic_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t medic_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t medic_move_death = { FRAME_death1, FRAME_death30, medic_frames_death, medic_dead }; void medic_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ if (self->mass == 400) { gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, commander_sound_die, 1, ATTN_NORM, 0); } self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &medic_move_death; } static mframe_t medic_frames_duck[] = { {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, monster_duck_down}, {ai_move, -1, monster_duck_hold}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, monster_duck_up}, {ai_move, -1, NULL}, {ai_move, -1, NULL} }; mmove_t medic_move_duck = { FRAME_duck1, FRAME_duck16, medic_frames_duck, medic_run }; static mframe_t medic_frames_attackHyperBlaster[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, medic_fire_blaster} }; mmove_t medic_move_attackHyperBlaster = { FRAME_attack15, FRAME_attack30, medic_frames_attackHyperBlaster, medic_run }; void medic_continue(edict_t *self) { if (!self) { return; } if (visible(self, self->enemy)) { if (random() <= 0.95) { self->monsterinfo.currentmove = &medic_move_attackHyperBlaster; } } } static mframe_t medic_frames_attackBlaster[] = { {ai_charge, 0, NULL}, {ai_charge, 5, NULL}, {ai_charge, 5, NULL}, {ai_charge, 3, NULL}, {ai_charge, 2, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, medic_fire_blaster}, {ai_charge, 0, NULL}, {ai_charge, 0, medic_continue} }; mmove_t medic_move_attackBlaster = { FRAME_attack1, FRAME_attack14, medic_frames_attackBlaster, medic_run }; void medic_hook_launch(edict_t *self) { if (!self) { return; } /* commander sounds */ if (self->mass == 400) { gi.sound(self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, commander_sound_hook_launch, 1, ATTN_NORM, 0); } } static vec3_t medic_cable_offsets[] = { {45.0, -9.2, 15.5}, {48.4, -9.7, 15.2}, {47.8, -9.8, 15.8}, {47.3, -9.3, 14.3}, {45.4, -10.1, 13.1}, {41.9, -12.7, 12.0}, {37.8, -15.8, 11.2}, {34.3, -18.4, 10.7}, {32.7, -19.7, 10.4}, {32.7, -19.7, 10.4} }; void medic_cable_attack(edict_t *self) { vec3_t offset, start, end, f, r; trace_t tr; vec3_t dir; float distance; if (!self) { return; } if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->s.effects & EF_GIB)) { abortHeal(self, true, false, false); return; } /* see if our enemy has changed to a client, or our target has more than 0 health, abort it .. we got switched to someone else due to damage */ if ((self->enemy->client) || (self->enemy->health > 0)) { abortHeal(self, true, false, false); return; } AngleVectors(self->s.angles, f, r, NULL); VectorCopy(medic_cable_offsets[self->s.frame - FRAME_attack42], offset); G_ProjectSource(self->s.origin, offset, f, r, start); VectorSubtract(start, self->enemy->s.origin, dir); distance = VectorLength(dir); if (distance < MEDIC_MIN_DISTANCE) { abortHeal(self, true, true, false); return; } tr = gi.trace(start, NULL, NULL, self->enemy->s.origin, self, MASK_SOLID); if ((tr.fraction != 1.0) && (tr.ent != self->enemy)) { if (tr.ent == world) { /* give up on second try */ if (self->monsterinfo.medicTries > 1) { abortHeal(self, true, false, true); return; } self->monsterinfo.medicTries++; cleanupHeal(self, 1); return; } abortHeal(self, true, false, false); return; } if (self->s.frame == FRAME_attack43) { /* commander sounds */ if (self->mass == 400) { gi.sound(self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0); } else { gi.sound(self->enemy, CHAN_AUTO, commander_sound_hook_hit, 1, ATTN_NORM, 0); } self->enemy->monsterinfo.aiflags |= AI_RESURRECTING; self->enemy->takedamage = DAMAGE_NO; M_SetEffects(self->enemy); } else if (self->s.frame == FRAME_attack50) { vec3_t maxs; self->enemy->spawnflags = 0; self->enemy->monsterinfo.aiflags = 0; self->enemy->target = NULL; self->enemy->targetname = NULL; self->enemy->combattarget = NULL; self->enemy->deathtarget = NULL; self->enemy->monsterinfo.healer = self; VectorCopy(self->enemy->maxs, maxs); maxs[2] += 48; tr = gi.trace(self->enemy->s.origin, self->enemy->mins, maxs, self->enemy->s.origin, self->enemy, MASK_MONSTERSOLID); if (tr.startsolid || tr.allsolid) { abortHeal(self, true, true, false); return; } else if (tr.ent != world) { abortHeal(self, true, true, false); return; } else { self->enemy->monsterinfo.aiflags |= AI_DO_NOT_COUNT; ED_CallSpawn(self->enemy); if (self->enemy->think) { self->enemy->nextthink = level.time; self->enemy->think(self->enemy); } self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; self->enemy->monsterinfo.aiflags |= AI_IGNORE_SHOTS | AI_DO_NOT_COUNT; /* turn off flies */ self->enemy->s.effects &= ~EF_FLIES; self->enemy->monsterinfo.healer = NULL; if ((self->oldenemy) && (self->oldenemy->inuse) && (self->oldenemy->health > 0)) { self->enemy->enemy = self->oldenemy; FoundTarget(self->enemy); } else { self->enemy->enemy = NULL; if (!FindTarget(self->enemy)) { /* no valid enemy, so stop acting */ self->enemy->monsterinfo.pausetime = level.time + 100000000; self->enemy->monsterinfo.stand(self->enemy); } self->enemy = NULL; self->oldenemy = NULL; if (!FindTarget(self)) { /* no valid enemy, so stop acting */ self->monsterinfo.pausetime = level.time + 100000000; self->monsterinfo.stand(self); return; } } } } else { if (self->s.frame == FRAME_attack44) { /* medic commander sounds */ if (self->mass == 400) { gi.sound(self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, commander_sound_hook_heal, 1, ATTN_NORM, 0); } } } /* adjust start for beam origin being in middle of a segment */ VectorMA(start, 8, f, start); /* adjust end z for end spot since the monster is currently dead */ VectorCopy(self->enemy->s.origin, end); end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2; gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_MEDIC_CABLE_ATTACK); gi.WriteShort(self - g_edicts); gi.WritePosition(start); gi.WritePosition(end); gi.multicast(self->s.origin, MULTICAST_PVS); } void medic_hook_retract(edict_t *self) { if (!self) { return; } if (self->mass == 400) { gi.sound(self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, commander_sound_hook_retract, 1, ATTN_NORM, 0); } self->monsterinfo.aiflags &= ~AI_MEDIC; if ((self->oldenemy) && (self->oldenemy->inuse)) { self->enemy = self->oldenemy; } else { self->enemy = NULL; self->oldenemy = NULL; if (!FindTarget(self)) { /* no valid enemy, so stop acting */ self->monsterinfo.pausetime = level.time + 100000000; self->monsterinfo.stand(self); return; } } } static mframe_t medic_frames_attackCable[] = { {ai_charge, 2, NULL}, /* 33 */ {ai_charge, 3, NULL}, {ai_charge, 5, NULL}, {ai_charge, -4.4, NULL}, /* 36 */ {ai_charge, -4.7, NULL}, /* 37 */ {ai_charge, -5, NULL}, {ai_charge, -6, NULL}, {ai_charge, -4, medic_footstep}, /* 40 */ {ai_charge, 0, NULL}, {ai_move, 0, medic_hook_launch}, /* 42 */ {ai_move, 0, medic_cable_attack}, /* 43 */ {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, {ai_move, 0, medic_cable_attack}, /* 51 */ {ai_move, 0, medic_hook_retract}, /* 52 */ {ai_move, -1.5, NULL}, {ai_move, -1.2, medic_footstep}, {ai_move, -3, NULL}, {ai_move, -2, NULL}, {ai_move, 0.3, NULL}, {ai_move, 0.7, NULL}, {ai_move, 1.2, NULL}, {ai_move, 1.3, NULL} /* 60 */ }; mmove_t medic_move_attackCable = { FRAME_attack33, FRAME_attack60, medic_frames_attackCable, medic_run }; void medic_start_spawn(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, commander_sound_spawn, 1, ATTN_NORM, 0); self->monsterinfo.nextframe = FRAME_attack48; } void medic_determine_spawn(edict_t *self) { vec3_t f, r, offset, startpoint, spawnpoint; float lucky; int summonStr; int count; int inc; int num_summoned; /* should be 1, 3, or 5 */ int num_success = 0; lucky = random(); summonStr = skill->value; if (!self) { return; } if (lucky < 0.05) { summonStr -= 3; } else if (lucky < 0.15) { summonStr -= 2; } else if (lucky < 0.3) { summonStr -= 1; } else if (lucky > 0.95) { summonStr += 3; } else if (lucky > 0.85) { summonStr += 2; } else if (lucky > 0.7) { summonStr += 1; } if (summonStr < 0) { summonStr = 0; } self->plat2flags = summonStr; AngleVectors(self->s.angles, f, r, NULL); /* this yields either 1, 3, or 5 */ if (summonStr) { num_summoned = (summonStr - 1) + (summonStr % 2); } else { num_summoned = 1; } for (count = 0; count < num_summoned; count++) { inc = count + (count % 2); /* 0, 2, 2, 4, 4 */ VectorCopy(reinforcement_position[count], offset); G_ProjectSource(self->s.origin, offset, f, r, startpoint); startpoint[2] += 10; if (FindSpawnPoint(startpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], spawnpoint, 32)) { if (CheckGroundSpawnPoint(spawnpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], 256, -1)) { num_success++; /* we found a spot, we're done here */ count = num_summoned; } } } if (num_success == 0) { for (count = 0; count < num_summoned; count++) { inc = count + (count % 2); /* 0, 2, 2, 4, 4 */ VectorCopy(reinforcement_position[count], offset); /* check behind */ offset[0] *= -1.0; offset[1] *= -1.0; G_ProjectSource(self->s.origin, offset, f, r, startpoint); /* a little off the ground */ startpoint[2] += 10; if (FindSpawnPoint(startpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], spawnpoint, 32)) { if (CheckGroundSpawnPoint(spawnpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], 256, -1)) { num_success++; /* we found a spot, we're done here */ count = num_summoned; } } } if (num_success) { self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->ideal_yaw = anglemod(self->s.angles[YAW]) + 180; if (self->ideal_yaw > 360.0) { self->ideal_yaw -= 360.0; } } } if (num_success == 0) { self->monsterinfo.nextframe = FRAME_attack53; } } void medic_spawngrows(edict_t *self) { vec3_t f, r, offset, startpoint, spawnpoint; int summonStr; int count; int inc; int num_summoned; /* should be 1, 3, or 5 */ int num_success = 0; float current_yaw; if (!self) { return; } /* if we've been directed to turn around */ if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { current_yaw = anglemod(self->s.angles[YAW]); if (fabs(current_yaw - self->ideal_yaw) > 0.1) { self->monsterinfo.aiflags |= AI_HOLD_FRAME; return; } /* done turning around */ self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; } summonStr = self->plat2flags; AngleVectors(self->s.angles, f, r, NULL); if (summonStr) { num_summoned = (summonStr - 1) + (summonStr % 2); } else { num_summoned = 1; } for (count = 0; count < num_summoned; count++) { inc = count + (count % 2); /* 0, 2, 2, 4, 4 */ VectorCopy(reinforcement_position[count], offset); G_ProjectSource(self->s.origin, offset, f, r, startpoint); /* a little off the ground */ startpoint[2] += 10; if (FindSpawnPoint(startpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], spawnpoint, 32)) { if (CheckGroundSpawnPoint(spawnpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], 256, -1)) { num_success++; if ((summonStr - inc) > 3) { SpawnGrow_Spawn(spawnpoint, 1); /* big monster */ } else { SpawnGrow_Spawn(spawnpoint, 0); /* normal size */ } } } } if (num_success == 0) { self->monsterinfo.nextframe = FRAME_attack53; } } void medic_finish_spawn(edict_t *self) { edict_t *ent; vec3_t f, r, offset, startpoint, spawnpoint; int summonStr; int count; int inc; int num_summoned; /* should be 1, 3, or 5 */ edict_t *designated_enemy; if (!self) { return; } if (self->plat2flags < 0) { self->plat2flags *= -1; } summonStr = self->plat2flags; AngleVectors(self->s.angles, f, r, NULL); if (summonStr) { num_summoned = (summonStr - 1) + (summonStr % 2); } else { num_summoned = 1; } for (count = 0; count < num_summoned; count++) { inc = count + (count % 2); /* 0, 2, 2, 4, 4 */ VectorCopy(reinforcement_position[count], offset); G_ProjectSource(self->s.origin, offset, f, r, startpoint); /* a little off the ground */ startpoint[2] += 10; ent = NULL; if (FindSpawnPoint(startpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], spawnpoint, 32)) { if (CheckSpawnPoint(spawnpoint, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc])) { ent = CreateGroundMonster(spawnpoint, self->s.angles, reinforcement_mins[summonStr - inc], reinforcement_maxs[summonStr - inc], reinforcements[summonStr - inc], 256); } } if (!ent) { continue; } if (ent->think) { ent->nextthink = level.time; ent->think(ent); } ent->monsterinfo.aiflags |= AI_IGNORE_SHOTS | AI_DO_NOT_COUNT | AI_SPAWNED_MEDIC_C; ent->monsterinfo.commander = self; self->monsterinfo.monster_slots--; if (self->monsterinfo.aiflags & AI_MEDIC) { designated_enemy = self->oldenemy; } else { designated_enemy = self->enemy; } if (coop && coop->value) { designated_enemy = PickCoopTarget(ent); if (designated_enemy) { /* try to avoid using my enemy */ if (designated_enemy == self->enemy) { designated_enemy = PickCoopTarget(ent); if (!designated_enemy) { designated_enemy = self->enemy; } } } else { designated_enemy = self->enemy; } } if ((designated_enemy) && (designated_enemy->inuse) && (designated_enemy->health > 0)) { ent->enemy = designated_enemy; FoundTarget(ent); } else { ent->enemy = NULL; ent->monsterinfo.stand(ent); } } } static mframe_t medic_frames_callReinforcements[] = { {ai_charge, 2, NULL}, /* 33 */ {ai_charge, 3, NULL}, {ai_charge, 5, NULL}, {ai_charge, 4.4, NULL}, /* 36 */ {ai_charge, 4.7, NULL}, {ai_charge, 5, NULL}, {ai_charge, 6, NULL}, {ai_charge, 4, NULL}, /* 40 */ {ai_charge, 0, NULL}, {ai_move, 0, medic_start_spawn}, /* 42 */ {ai_move, 0, NULL}, /* 43 -- 43 through 47 are skipped */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, medic_determine_spawn}, /* 48 */ {ai_charge, 0, medic_spawngrows}, /* 49 */ {ai_move, 0, NULL}, /* 50 */ {ai_move, 0, NULL}, /* 51 */ {ai_move, -15, medic_finish_spawn}, /* 52 */ {ai_move, -1.5, NULL}, {ai_move, -1.2, NULL}, {ai_move, -3, NULL}, {ai_move, -2, NULL}, {ai_move, 0.3, NULL}, {ai_move, 0.7, NULL}, {ai_move, 1.2, NULL}, {ai_move, 1.3, NULL} /* 60 */ }; mmove_t medic_move_callReinforcements = { FRAME_attack33, FRAME_attack60, medic_frames_callReinforcements, medic_run }; void medic_attack(edict_t *self) { int enemy_range; float r; if (!self) { return; } monster_done_dodge(self); enemy_range = range(self, self->enemy); /* signal from checkattack to spawn */ if (self->monsterinfo.aiflags & AI_BLOCKED) { self->monsterinfo.currentmove = &medic_move_callReinforcements; self->monsterinfo.aiflags &= ~AI_BLOCKED; } r = random(); if (self->monsterinfo.aiflags & AI_MEDIC) { if ((self->mass > 400) && (r > 0.8) && (self->monsterinfo.monster_slots > 2)) { self->monsterinfo.currentmove = &medic_move_callReinforcements; } else { self->monsterinfo.currentmove = &medic_move_attackCable; } } else { if (self->monsterinfo.attack_state == AS_BLIND) { self->monsterinfo.currentmove = &medic_move_callReinforcements; return; } if ((self->mass > 400) && (r > 0.2) && (enemy_range != RANGE_MELEE) && (self->monsterinfo.monster_slots > 2)) { self->monsterinfo.currentmove = &medic_move_callReinforcements; } else { self->monsterinfo.currentmove = &medic_move_attackBlaster; } } } qboolean medic_checkattack(edict_t *self) { if (!self) { return false; } if (self->monsterinfo.aiflags & AI_MEDIC) { /* if our target went away */ if ((!self->enemy) || (!self->enemy->inuse)) { abortHeal(self, true, false, false); return false; } /* if we ran out of time, give up */ if (self->timestamp < level.time) { abortHeal(self, true, false, true); self->timestamp = 0; return false; } if (realrange(self, self->enemy) < MEDIC_MAX_HEAL_DISTANCE + 10) { medic_attack(self); return true; } else { self->monsterinfo.attack_state = AS_STRAIGHT; return false; } } if (self->enemy && self->enemy->client && !visible(self, self->enemy) && (self->monsterinfo.monster_slots > 2)) { self->monsterinfo.attack_state = AS_BLIND; return true; } if ((random() < 0.8) && (self->monsterinfo.monster_slots > 5) && (realrange(self, self->enemy) > 150)) { self->monsterinfo.aiflags |= AI_BLOCKED; self->monsterinfo.attack_state = AS_MISSILE; return true; } if (skill->value > SKILL_EASY) { if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.attack_state = AS_MISSILE; return true; } } return M_CheckAttack(self); } void MedicCommanderCache(void) { edict_t *newEnt; int i; /* better way to do this? this is quick and dirty */ for (i = 0; i < 7; i++) { newEnt = G_Spawn(); VectorCopy(vec3_origin, newEnt->s.origin); VectorCopy(vec3_origin, newEnt->s.angles); newEnt->classname = ED_NewString(reinforcements[i]); newEnt->monsterinfo.aiflags |= AI_DO_NOT_COUNT; ED_CallSpawn(newEnt); G_FreeEdict(newEnt); } gi.modelindex("models/items/spawngro/tris.md2"); gi.modelindex("models/items/spawngro2/tris.md2"); } void medic_duck(edict_t *self, float eta) { if (!self) { return; } /* don't dodge if you're healing */ if (self->monsterinfo.aiflags & AI_MEDIC) { return; } if ((self->monsterinfo.currentmove == &medic_move_attackHyperBlaster) || (self->monsterinfo.currentmove == &medic_move_attackCable) || (self->monsterinfo.currentmove == &medic_move_attackBlaster) || (self->monsterinfo.currentmove == &medic_move_callReinforcements)) { /* he ignores skill */ self->monsterinfo.aiflags &= ~AI_DUCKED; return; } if (skill->value == SKILL_EASY) { /* stupid dodge */ self->monsterinfo.duck_wait_time = level.time + eta + 1; } else { self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } /* has to be done immediately otherwise he can get stuck */ monster_duck_down(self); self->monsterinfo.nextframe = FRAME_duck1; self->monsterinfo.currentmove = &medic_move_duck; return; } void medic_sidestep(edict_t *self) { if (!self) { return; } if ((self->monsterinfo.currentmove == &medic_move_attackHyperBlaster) || (self->monsterinfo.currentmove == &medic_move_attackCable) || (self->monsterinfo.currentmove == &medic_move_attackBlaster) || (self->monsterinfo.currentmove == &medic_move_callReinforcements)) { /* if we're shooting, and not on easy, don't dodge */ if (skill->value > SKILL_EASY) { self->monsterinfo.aiflags &= ~AI_DODGING; return; } } if (self->monsterinfo.currentmove != &medic_move_run) { self->monsterinfo.currentmove = &medic_move_run; } } qboolean medic_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } /* * QUAKED monster_medic_commander (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight * * QUAKED monster_medic (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_medic(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/medic/tris.md2"); VectorSet(self->mins, -24, -24, -24); VectorSet(self->maxs, 24, 24, 32); if (strcmp(self->classname, "monster_medic_commander") == 0) { self->health = 600; self->gib_health = -130; self->mass = 600; self->yaw_speed = 40; MedicCommanderCache(); } else { self->health = 300; self->gib_health = -130; self->mass = 400; } self->pain = medic_pain; self->die = medic_die; self->monsterinfo.stand = medic_stand; self->monsterinfo.walk = medic_walk; self->monsterinfo.run = medic_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.duck = medic_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.sidestep = medic_sidestep; self->monsterinfo.attack = medic_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = medic_sight; self->monsterinfo.idle = medic_idle; self->monsterinfo.search = medic_search; self->monsterinfo.checkattack = medic_checkattack; self->monsterinfo.blocked = medic_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &medic_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; if (self->mass > 400) { self->s.skinnum = 2; if (skill->value == SKILL_EASY) { self->monsterinfo.monster_slots = 3; } else if (skill->value == SKILL_MEDIUM) { self->monsterinfo.monster_slots = 4; } else if (skill->value == SKILL_HARD) { self->monsterinfo.monster_slots = 6; } else if (skill->value == SKILL_HARDPLUS) { self->monsterinfo.monster_slots = 6; } /* commander sounds */ commander_sound_idle1 = gi.soundindex("medic_commander/medidle.wav"); commander_sound_pain1 = gi.soundindex("medic_commander/medpain1.wav"); commander_sound_pain2 = gi.soundindex("medic_commander/medpain2.wav"); commander_sound_die = gi.soundindex("medic_commander/meddeth.wav"); commander_sound_sight = gi.soundindex("medic_commander/medsght.wav"); commander_sound_search = gi.soundindex("medic_commander/medsrch.wav"); commander_sound_hook_launch = gi.soundindex("medic_commander/medatck2c.wav"); commander_sound_hook_hit = gi.soundindex("medic_commander/medatck3a.wav"); commander_sound_hook_heal = gi.soundindex("medic_commander/medatck4a.wav"); commander_sound_hook_retract = gi.soundindex("medic_commander/medatck5a.wav"); commander_sound_spawn = gi.soundindex("medic_commander/monsterspawn1.wav"); gi.soundindex("tank/tnkatck3.wav"); } else { sound_idle1 = gi.soundindex("medic/idle.wav"); sound_pain1 = gi.soundindex("medic/medpain1.wav"); sound_pain2 = gi.soundindex("medic/medpain2.wav"); sound_die = gi.soundindex("medic/meddeth1.wav"); sound_sight = gi.soundindex("medic/medsght1.wav"); sound_search = gi.soundindex("medic/medsrch1.wav"); sound_hook_launch = gi.soundindex("medic/medatck2.wav"); sound_hook_hit = gi.soundindex("medic/medatck3.wav"); sound_hook_heal = gi.soundindex("medic/medatck4.wav"); sound_hook_retract = gi.soundindex("medic/medatck5.wav"); gi.soundindex("medic/medatck1.wav"); self->s.skinnum = 0; } } rogue-ROGUE_2_13/src/monster/medic/medic.h000066400000000000000000000203441477320066100204040ustar00rootroot00000000000000/* ======================================================================= * * Medic and Medic Commander animations. * * ======================================================================= */ #define FRAME_walk1 0 #define FRAME_walk2 1 #define FRAME_walk3 2 #define FRAME_walk4 3 #define FRAME_walk5 4 #define FRAME_walk6 5 #define FRAME_walk7 6 #define FRAME_walk8 7 #define FRAME_walk9 8 #define FRAME_walk10 9 #define FRAME_walk11 10 #define FRAME_walk12 11 #define FRAME_wait1 12 #define FRAME_wait2 13 #define FRAME_wait3 14 #define FRAME_wait4 15 #define FRAME_wait5 16 #define FRAME_wait6 17 #define FRAME_wait7 18 #define FRAME_wait8 19 #define FRAME_wait9 20 #define FRAME_wait10 21 #define FRAME_wait11 22 #define FRAME_wait12 23 #define FRAME_wait13 24 #define FRAME_wait14 25 #define FRAME_wait15 26 #define FRAME_wait16 27 #define FRAME_wait17 28 #define FRAME_wait18 29 #define FRAME_wait19 30 #define FRAME_wait20 31 #define FRAME_wait21 32 #define FRAME_wait22 33 #define FRAME_wait23 34 #define FRAME_wait24 35 #define FRAME_wait25 36 #define FRAME_wait26 37 #define FRAME_wait27 38 #define FRAME_wait28 39 #define FRAME_wait29 40 #define FRAME_wait30 41 #define FRAME_wait31 42 #define FRAME_wait32 43 #define FRAME_wait33 44 #define FRAME_wait34 45 #define FRAME_wait35 46 #define FRAME_wait36 47 #define FRAME_wait37 48 #define FRAME_wait38 49 #define FRAME_wait39 50 #define FRAME_wait40 51 #define FRAME_wait41 52 #define FRAME_wait42 53 #define FRAME_wait43 54 #define FRAME_wait44 55 #define FRAME_wait45 56 #define FRAME_wait46 57 #define FRAME_wait47 58 #define FRAME_wait48 59 #define FRAME_wait49 60 #define FRAME_wait50 61 #define FRAME_wait51 62 #define FRAME_wait52 63 #define FRAME_wait53 64 #define FRAME_wait54 65 #define FRAME_wait55 66 #define FRAME_wait56 67 #define FRAME_wait57 68 #define FRAME_wait58 69 #define FRAME_wait59 70 #define FRAME_wait60 71 #define FRAME_wait61 72 #define FRAME_wait62 73 #define FRAME_wait63 74 #define FRAME_wait64 75 #define FRAME_wait65 76 #define FRAME_wait66 77 #define FRAME_wait67 78 #define FRAME_wait68 79 #define FRAME_wait69 80 #define FRAME_wait70 81 #define FRAME_wait71 82 #define FRAME_wait72 83 #define FRAME_wait73 84 #define FRAME_wait74 85 #define FRAME_wait75 86 #define FRAME_wait76 87 #define FRAME_wait77 88 #define FRAME_wait78 89 #define FRAME_wait79 90 #define FRAME_wait80 91 #define FRAME_wait81 92 #define FRAME_wait82 93 #define FRAME_wait83 94 #define FRAME_wait84 95 #define FRAME_wait85 96 #define FRAME_wait86 97 #define FRAME_wait87 98 #define FRAME_wait88 99 #define FRAME_wait89 100 #define FRAME_wait90 101 #define FRAME_run1 102 #define FRAME_run2 103 #define FRAME_run3 104 #define FRAME_run4 105 #define FRAME_run5 106 #define FRAME_run6 107 #define FRAME_paina1 108 #define FRAME_paina2 109 #define FRAME_paina3 110 #define FRAME_paina4 111 #define FRAME_paina5 112 #define FRAME_paina6 113 #define FRAME_paina7 114 #define FRAME_paina8 115 #define FRAME_painb1 116 #define FRAME_painb2 117 #define FRAME_painb3 118 #define FRAME_painb4 119 #define FRAME_painb5 120 #define FRAME_painb6 121 #define FRAME_painb7 122 #define FRAME_painb8 123 #define FRAME_painb9 124 #define FRAME_painb10 125 #define FRAME_painb11 126 #define FRAME_painb12 127 #define FRAME_painb13 128 #define FRAME_painb14 129 #define FRAME_painb15 130 #define FRAME_duck1 131 #define FRAME_duck2 132 #define FRAME_duck3 133 #define FRAME_duck4 134 #define FRAME_duck5 135 #define FRAME_duck6 136 #define FRAME_duck7 137 #define FRAME_duck8 138 #define FRAME_duck9 139 #define FRAME_duck10 140 #define FRAME_duck11 141 #define FRAME_duck12 142 #define FRAME_duck13 143 #define FRAME_duck14 144 #define FRAME_duck15 145 #define FRAME_duck16 146 #define FRAME_death1 147 #define FRAME_death2 148 #define FRAME_death3 149 #define FRAME_death4 150 #define FRAME_death5 151 #define FRAME_death6 152 #define FRAME_death7 153 #define FRAME_death8 154 #define FRAME_death9 155 #define FRAME_death10 156 #define FRAME_death11 157 #define FRAME_death12 158 #define FRAME_death13 159 #define FRAME_death14 160 #define FRAME_death15 161 #define FRAME_death16 162 #define FRAME_death17 163 #define FRAME_death18 164 #define FRAME_death19 165 #define FRAME_death20 166 #define FRAME_death21 167 #define FRAME_death22 168 #define FRAME_death23 169 #define FRAME_death24 170 #define FRAME_death25 171 #define FRAME_death26 172 #define FRAME_death27 173 #define FRAME_death28 174 #define FRAME_death29 175 #define FRAME_death30 176 #define FRAME_attack1 177 #define FRAME_attack2 178 #define FRAME_attack3 179 #define FRAME_attack4 180 #define FRAME_attack5 181 #define FRAME_attack6 182 #define FRAME_attack7 183 #define FRAME_attack8 184 #define FRAME_attack9 185 #define FRAME_attack10 186 #define FRAME_attack11 187 #define FRAME_attack12 188 #define FRAME_attack13 189 #define FRAME_attack14 190 #define FRAME_attack15 191 #define FRAME_attack16 192 #define FRAME_attack17 193 #define FRAME_attack18 194 #define FRAME_attack19 195 #define FRAME_attack20 196 #define FRAME_attack21 197 #define FRAME_attack22 198 #define FRAME_attack23 199 #define FRAME_attack24 200 #define FRAME_attack25 201 #define FRAME_attack26 202 #define FRAME_attack27 203 #define FRAME_attack28 204 #define FRAME_attack29 205 #define FRAME_attack30 206 #define FRAME_attack31 207 #define FRAME_attack32 208 #define FRAME_attack33 209 #define FRAME_attack34 210 #define FRAME_attack35 211 #define FRAME_attack36 212 #define FRAME_attack37 213 #define FRAME_attack38 214 #define FRAME_attack39 215 #define FRAME_attack40 216 #define FRAME_attack41 217 #define FRAME_attack42 218 #define FRAME_attack43 219 #define FRAME_attack44 220 #define FRAME_attack45 221 #define FRAME_attack46 222 #define FRAME_attack47 223 #define FRAME_attack48 224 #define FRAME_attack49 225 #define FRAME_attack50 226 #define FRAME_attack51 227 #define FRAME_attack52 228 #define FRAME_attack53 229 #define FRAME_attack54 230 #define FRAME_attack55 231 #define FRAME_attack56 232 #define FRAME_attack57 233 #define FRAME_attack58 234 #define FRAME_attack59 235 #define FRAME_attack60 236 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/misc/000077500000000000000000000000001477320066100170215ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/misc/move.c000066400000000000000000000344521477320066100201430ustar00rootroot00000000000000/* ======================================================================= * * Monster movement support functions. * * ======================================================================= */ #include "../../header/local.h" #define DI_NODIR -1 #define STEPSIZE 18 /* this is used for communications out of * sv_movestep to say what entity is blocking us */ edict_t *new_bad; /* * Returns false if any part of the bottom of the * entity is off an edge that is not a staircase. */ qboolean M_CheckBottom(edict_t *ent) { vec3_t mins, maxs, start, stop; trace_t trace; int x, y; float mid, bottom; if (!ent) { return false; } VectorAdd(ent->s.origin, ent->mins, mins); VectorAdd(ent->s.origin, ent->maxs, maxs); /* if all of the points under the corners are solid world, don't bother with the tougher checksthe corners must be within 16 of the midpoint */ start[2] = mins[2] - 1; if (ent->gravityVector[2] > 0) { start[2] = maxs[2] + 1; } for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { start[0] = x ? maxs[0] : mins[0]; start[1] = y ? maxs[1] : mins[1]; if (gi.pointcontents(start) != CONTENTS_SOLID) { goto realcheck; } } } return true; /* we got out easy */ realcheck: start[2] = mins[2]; /* the midpoint must be within 16 of the bottom */ start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5; start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5; if (ent->gravityVector[2] < 0) { start[2] = mins[2]; stop[2] = start[2] - STEPSIZE - STEPSIZE; } else { start[2] = maxs[2]; stop[2] = start[2] + STEPSIZE + STEPSIZE; } trace = gi.trace(start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); if (trace.fraction == 1.0) { return false; } mid = bottom = trace.endpos[2]; /* the corners must be within 16 of the midpoint */ for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; trace = gi.trace(start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); if (ent->gravityVector[2] > 0) { if ((trace.fraction != 1.0) && (trace.endpos[2] < bottom)) { bottom = trace.endpos[2]; } if ((trace.fraction == 1.0) || (trace.endpos[2] - mid > STEPSIZE)) { return false; } } else { if ((trace.fraction != 1.0) && (trace.endpos[2] > bottom)) { bottom = trace.endpos[2]; } if ((trace.fraction == 1.0) || (mid - trace.endpos[2] > STEPSIZE)) { return false; } } } } return true; } qboolean IsBadAhead(edict_t *self, edict_t *bad, vec3_t move) { vec3_t dir; vec3_t forward; float dp_bad, dp_move; vec3_t move_copy; if (!self || !bad) { return false; } VectorCopy(move, move_copy); VectorSubtract(bad->s.origin, self->s.origin, dir); VectorNormalize(dir); AngleVectors(self->s.angles, forward, NULL, NULL); dp_bad = DotProduct(forward, dir); VectorNormalize(move_copy); AngleVectors(self->s.angles, forward, NULL, NULL); dp_move = DotProduct(forward, move_copy); if ((dp_bad < 0) && (dp_move < 0)) { return true; } if ((dp_bad > 0) && (dp_move > 0)) { return true; } return false; } /* * The move will be adjusted for slopes and stairs, but if the move isn't * possible, no move is done, false is returned, and * pr_global_struct->trace_normal is set to the normal of the blocking wall */ qboolean SV_movestep(edict_t *ent, vec3_t move, qboolean relink) { float dz; vec3_t oldorg, neworg, end; trace_t trace; int i; float stepsize; vec3_t test; int contents; edict_t *current_bad = NULL; float minheight; if (!ent) { return false; } if (ent->health > 0) { current_bad = CheckForBadArea(ent); if (current_bad) { ent->bad_area = current_bad; if (ent->enemy && !strcmp(ent->enemy->classname, "tesla")) { /* if the tesla is in front of us, back up... */ if (IsBadAhead(ent, current_bad, move)) { VectorScale(move, -1, move); } } } else if (ent->bad_area) { /* if we're no longer in a bad area, get back to business. */ ent->bad_area = NULL; if (ent->oldenemy) { ent->enemy = ent->oldenemy; ent->goalentity = ent->oldenemy; FoundTarget(ent); return true; } } } /* try the move */ VectorCopy(ent->s.origin, oldorg); VectorAdd(ent->s.origin, move, neworg); /* flying monsters don't step up */ if (ent->flags & (FL_SWIM | FL_FLY)) { /* try one move with vertical motion, then one without */ for (i = 0; i < 2; i++) { VectorAdd(ent->s.origin, move, neworg); if ((i == 0) && ent->enemy) { if (!ent->goalentity) { ent->goalentity = ent->enemy; } dz = ent->s.origin[2] - ent->goalentity->s.origin[2]; if (ent->goalentity->client) { /* we want the carrier to stay a certain distance off the ground, to help prevent him from shooting his fliers, who spawn in below him */ if (!strcmp(ent->classname, "monster_carrier")) { minheight = 104; } else { minheight = 40; } if (dz > minheight) { neworg[2] -= 8; } if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2))) { if (dz < (minheight - 10)) { neworg[2] += 8; } } } else { if (dz > 8) { neworg[2] -= 8; } else if (dz > 0) { neworg[2] -= dz; } else if (dz < -8) { neworg[2] += 8; } else { neworg[2] += dz; } } } trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID); /* fly monsters don't enter water voluntarily */ if (ent->flags & FL_FLY) { if (!ent->waterlevel) { test[0] = trace.endpos[0]; test[1] = trace.endpos[1]; test[2] = trace.endpos[2] + ent->mins[2] + 1; contents = gi.pointcontents(test); if (contents & MASK_WATER) { return false; } } } /* swim monsters don't exit water voluntarily */ if (ent->flags & FL_SWIM) { if (ent->waterlevel < 2) { test[0] = trace.endpos[0]; test[1] = trace.endpos[1]; test[2] = trace.endpos[2] + ent->mins[2] + 1; contents = gi.pointcontents(test); if (!(contents & MASK_WATER)) { return false; } } } if ((trace.fraction == 1) && (!trace.allsolid) && (!trace.startsolid)) { VectorCopy(trace.endpos, ent->s.origin); if (!current_bad && CheckForBadArea(ent)) { VectorCopy(oldorg, ent->s.origin); } else { if (relink) { gi.linkentity(ent); G_TouchTriggers(ent); } return true; } } if (!ent->enemy) { break; } } return false; } /* push down from a step height above the wished position */ if (!(ent->monsterinfo.aiflags & AI_NOSTEP)) { stepsize = STEPSIZE; } else { stepsize = 1; } /* trace from 1 stepsize gravityUp to 2 stepsize gravityDown. */ VectorMA(neworg, -1 * stepsize, ent->gravityVector, neworg); VectorMA(neworg, 2 * stepsize, ent->gravityVector, end); trace = gi.trace(neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); if (trace.allsolid) { return false; } if (trace.startsolid) { neworg[2] -= stepsize; trace = gi.trace(neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); if (trace.allsolid || trace.startsolid) { return false; } } /* don't go in to water */ if (ent->waterlevel == 0) { test[0] = trace.endpos[0]; test[1] = trace.endpos[1]; if (ent->gravityVector[2] > 0) { test[2] = trace.endpos[2] + ent->maxs[2] - 1; } else { test[2] = trace.endpos[2] + ent->mins[2] + 1; } contents = gi.pointcontents(test); if (contents & MASK_WATER) { return false; } } if (trace.fraction == 1) { /* if monster had the ground pulled out, go ahead and fall */ if (ent->flags & FL_PARTIALGROUND) { VectorAdd(ent->s.origin, move, ent->s.origin); if (relink) { gi.linkentity(ent); G_TouchTriggers(ent); } ent->groundentity = NULL; return true; } return false;/* walked off an edge */ } /* check point traces down for dangling corners */ VectorCopy(trace.endpos, ent->s.origin); if (ent->health > 0) { /* use AI_BLOCKED to tell the calling layer that we're now mad at a tesla */ new_bad = CheckForBadArea(ent); if (!current_bad && new_bad) { if (new_bad->owner && !strcmp(new_bad->owner->classname, "tesla")) { if (!ent->enemy || !ent->enemy->inuse || !ent->enemy->client || !visible(ent, ent->enemy)) { TargetTesla(ent, new_bad->owner); ent->monsterinfo.aiflags |= AI_BLOCKED; } } VectorCopy(oldorg, ent->s.origin); return false; } } if (!M_CheckBottom(ent)) { if (ent->flags & FL_PARTIALGROUND) { /* entity had floor mostly pulled out from nderneath it and is trying to correct */ if (relink) { gi.linkentity(ent); G_TouchTriggers(ent); } return true; } VectorCopy(oldorg, ent->s.origin); return false; } if (ent->flags & FL_PARTIALGROUND) { ent->flags &= ~FL_PARTIALGROUND; } ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; if (relink) { gi.linkentity(ent); G_TouchTriggers(ent); } return true; } /* ============================================================================ */ void M_ChangeYaw(edict_t *ent) { float ideal; float current; float move; float speed; if (!ent) { return; } current = anglemod(ent->s.angles[YAW]); ideal = ent->ideal_yaw; if (current == ideal) { return; } move = ideal - current; speed = ent->yaw_speed; if (ideal > current) { if (move >= 180) { move = move - 360; } } else { if (move <= -180) { move = move + 360; } } if (move > 0) { if (move > speed) { move = speed; } } else { if (move < -speed) { move = -speed; } } ent->s.angles[YAW] = anglemod(current + move); } /* * Turns to the movement direction, and * walks the current distance if facing it. */ qboolean SV_StepDirection(edict_t *ent, float yaw, float dist) { vec3_t move, oldorigin; float delta; if (!ent) { return false; } if (!ent->inuse) { return true; } ent->ideal_yaw = yaw; M_ChangeYaw(ent); yaw = yaw * M_PI * 2 / 360; move[0] = cos(yaw) * dist; move[1] = sin(yaw) * dist; move[2] = 0; VectorCopy(ent->s.origin, oldorigin); if (SV_movestep(ent, move, false)) { ent->monsterinfo.aiflags &= ~AI_BLOCKED; if (!ent->inuse) { return true; } delta = ent->s.angles[YAW] - ent->ideal_yaw; if (strncmp(ent->classname, "monster_widow", 13)) { if ((delta > 45) && (delta < 315)) { /* not turned far enough, so don't take the step */ VectorCopy(oldorigin, ent->s.origin); } } gi.linkentity(ent); G_TouchTriggers(ent); return true; } gi.linkentity(ent); G_TouchTriggers(ent); return false; } void SV_FixCheckBottom(edict_t *ent) { if (!ent) { return; } ent->flags |= FL_PARTIALGROUND; } void SV_NewChaseDir(edict_t *actor, edict_t *enemy, float dist) { float deltax, deltay; float d[3]; float tdir, olddir, turnaround; if (!actor || !enemy) { return; } olddir = anglemod((int)(actor->ideal_yaw / 45) * 45); turnaround = anglemod(olddir - 180); deltax = enemy->s.origin[0] - actor->s.origin[0]; deltay = enemy->s.origin[1] - actor->s.origin[1]; if (deltax > 10) { d[1] = 0; } else if (deltax < -10) { d[1] = 180; } else { d[1] = DI_NODIR; } if (deltay < -10) { d[2] = 270; } else if (deltay > 10) { d[2] = 90; } else { d[2] = DI_NODIR; } /* try direct route */ if ((d[1] != DI_NODIR) && (d[2] != DI_NODIR)) { if (d[1] == 0) { tdir = d[2] == 90 ? 45 : 315; } else { tdir = d[2] == 90 ? 135 : 215; } if ((tdir != turnaround) && SV_StepDirection(actor, tdir, dist)) { return; } } /* try other directions */ if (((rand() & 3) & 1) || (fabsf(deltay) > fabsf(deltax))) { tdir = d[1]; d[1] = d[2]; d[2] = tdir; } if ((d[1] != DI_NODIR) && (d[1] != turnaround) && SV_StepDirection(actor, d[1], dist)) { return; } if ((d[2] != DI_NODIR) && (d[2] != turnaround) && SV_StepDirection(actor, d[2], dist)) { return; } if (actor->monsterinfo.blocked) { if ((actor->inuse) && (actor->health > 0)) { if ((actor->monsterinfo.blocked)(actor, dist)) { return; } } } if ((olddir != DI_NODIR) && SV_StepDirection(actor, olddir, dist)) { return; } if (rand() & 1) /*randomly determine direction of search*/ { for (tdir = 0; tdir <= 315; tdir += 45) { if ((tdir != turnaround) && SV_StepDirection(actor, tdir, dist)) { return; } } } else { for (tdir = 315; tdir >= 0; tdir -= 45) { if ((tdir != turnaround) && SV_StepDirection(actor, tdir, dist)) { return; } } } if ((turnaround != DI_NODIR) && SV_StepDirection(actor, turnaround, dist)) { return; } actor->ideal_yaw = olddir; /* can't move */ /* if a bridge was pulled out from underneath a monster, it may not have a valid standing position at all */ if (!M_CheckBottom(actor)) { SV_FixCheckBottom(actor); } } qboolean SV_CloseEnough(edict_t *ent, edict_t *goal, float dist) { int i; if (!ent || !goal) { return false; } for (i = 0; i < 3; i++) { if (goal->absmin[i] > ent->absmax[i] + dist) { return false; } if (goal->absmax[i] < ent->absmin[i] - dist) { return false; } } return true; } void M_MoveToGoal(edict_t *ent, float dist) { edict_t *goal; if (!ent) { return; } goal = ent->goalentity; if (!ent->groundentity && !(ent->flags & (FL_FLY | FL_SWIM))) { return; } /* if the next step hits the enemy, return immediately */ if (ent->enemy && SV_CloseEnough(ent, ent->enemy, dist)) { return; } if ((((rand() & 3) == 1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection(ent, ent->ideal_yaw, dist)) { if (ent->monsterinfo.aiflags & AI_BLOCKED) { ent->monsterinfo.aiflags &= ~AI_BLOCKED; return; } if (ent->inuse) { SV_NewChaseDir(ent, goal, dist); } } } qboolean M_walkmove(edict_t *ent, float yaw, float dist) { vec3_t move; qboolean retval; if (!ent) { return false; } if (!ent->groundentity && !(ent->flags & (FL_FLY | FL_SWIM))) { return false; } yaw = yaw * M_PI * 2 / 360; move[0] = cos(yaw) * dist; move[1] = sin(yaw) * dist; move[2] = 0; retval = SV_movestep(ent, move, true); ent->monsterinfo.aiflags &= ~AI_BLOCKED; return retval; } rogue-ROGUE_2_13/src/monster/misc/player.h000066400000000000000000000156261477320066100205000ustar00rootroot00000000000000/* ======================================================================= * * Player (the arm and the weapons) animation. * * ======================================================================= */ #define FRAME_stand01 0 #define FRAME_stand02 1 #define FRAME_stand03 2 #define FRAME_stand04 3 #define FRAME_stand05 4 #define FRAME_stand06 5 #define FRAME_stand07 6 #define FRAME_stand08 7 #define FRAME_stand09 8 #define FRAME_stand10 9 #define FRAME_stand11 10 #define FRAME_stand12 11 #define FRAME_stand13 12 #define FRAME_stand14 13 #define FRAME_stand15 14 #define FRAME_stand16 15 #define FRAME_stand17 16 #define FRAME_stand18 17 #define FRAME_stand19 18 #define FRAME_stand20 19 #define FRAME_stand21 20 #define FRAME_stand22 21 #define FRAME_stand23 22 #define FRAME_stand24 23 #define FRAME_stand25 24 #define FRAME_stand26 25 #define FRAME_stand27 26 #define FRAME_stand28 27 #define FRAME_stand29 28 #define FRAME_stand30 29 #define FRAME_stand31 30 #define FRAME_stand32 31 #define FRAME_stand33 32 #define FRAME_stand34 33 #define FRAME_stand35 34 #define FRAME_stand36 35 #define FRAME_stand37 36 #define FRAME_stand38 37 #define FRAME_stand39 38 #define FRAME_stand40 39 #define FRAME_run1 40 #define FRAME_run2 41 #define FRAME_run3 42 #define FRAME_run4 43 #define FRAME_run5 44 #define FRAME_run6 45 #define FRAME_attack1 46 #define FRAME_attack2 47 #define FRAME_attack3 48 #define FRAME_attack4 49 #define FRAME_attack5 50 #define FRAME_attack6 51 #define FRAME_attack7 52 #define FRAME_attack8 53 #define FRAME_pain101 54 #define FRAME_pain102 55 #define FRAME_pain103 56 #define FRAME_pain104 57 #define FRAME_pain201 58 #define FRAME_pain202 59 #define FRAME_pain203 60 #define FRAME_pain204 61 #define FRAME_pain301 62 #define FRAME_pain302 63 #define FRAME_pain303 64 #define FRAME_pain304 65 #define FRAME_jump1 66 #define FRAME_jump2 67 #define FRAME_jump3 68 #define FRAME_jump4 69 #define FRAME_jump5 70 #define FRAME_jump6 71 #define FRAME_flip01 72 #define FRAME_flip02 73 #define FRAME_flip03 74 #define FRAME_flip04 75 #define FRAME_flip05 76 #define FRAME_flip06 77 #define FRAME_flip07 78 #define FRAME_flip08 79 #define FRAME_flip09 80 #define FRAME_flip10 81 #define FRAME_flip11 82 #define FRAME_flip12 83 #define FRAME_salute01 84 #define FRAME_salute02 85 #define FRAME_salute03 86 #define FRAME_salute04 87 #define FRAME_salute05 88 #define FRAME_salute06 89 #define FRAME_salute07 90 #define FRAME_salute08 91 #define FRAME_salute09 92 #define FRAME_salute10 93 #define FRAME_salute11 94 #define FRAME_taunt01 95 #define FRAME_taunt02 96 #define FRAME_taunt03 97 #define FRAME_taunt04 98 #define FRAME_taunt05 99 #define FRAME_taunt06 100 #define FRAME_taunt07 101 #define FRAME_taunt08 102 #define FRAME_taunt09 103 #define FRAME_taunt10 104 #define FRAME_taunt11 105 #define FRAME_taunt12 106 #define FRAME_taunt13 107 #define FRAME_taunt14 108 #define FRAME_taunt15 109 #define FRAME_taunt16 110 #define FRAME_taunt17 111 #define FRAME_wave01 112 #define FRAME_wave02 113 #define FRAME_wave03 114 #define FRAME_wave04 115 #define FRAME_wave05 116 #define FRAME_wave06 117 #define FRAME_wave07 118 #define FRAME_wave08 119 #define FRAME_wave09 120 #define FRAME_wave10 121 #define FRAME_wave11 122 #define FRAME_point01 123 #define FRAME_point02 124 #define FRAME_point03 125 #define FRAME_point04 126 #define FRAME_point05 127 #define FRAME_point06 128 #define FRAME_point07 129 #define FRAME_point08 130 #define FRAME_point09 131 #define FRAME_point10 132 #define FRAME_point11 133 #define FRAME_point12 134 #define FRAME_crstnd01 135 #define FRAME_crstnd02 136 #define FRAME_crstnd03 137 #define FRAME_crstnd04 138 #define FRAME_crstnd05 139 #define FRAME_crstnd06 140 #define FRAME_crstnd07 141 #define FRAME_crstnd08 142 #define FRAME_crstnd09 143 #define FRAME_crstnd10 144 #define FRAME_crstnd11 145 #define FRAME_crstnd12 146 #define FRAME_crstnd13 147 #define FRAME_crstnd14 148 #define FRAME_crstnd15 149 #define FRAME_crstnd16 150 #define FRAME_crstnd17 151 #define FRAME_crstnd18 152 #define FRAME_crstnd19 153 #define FRAME_crwalk1 154 #define FRAME_crwalk2 155 #define FRAME_crwalk3 156 #define FRAME_crwalk4 157 #define FRAME_crwalk5 158 #define FRAME_crwalk6 159 #define FRAME_crattak1 160 #define FRAME_crattak2 161 #define FRAME_crattak3 162 #define FRAME_crattak4 163 #define FRAME_crattak5 164 #define FRAME_crattak6 165 #define FRAME_crattak7 166 #define FRAME_crattak8 167 #define FRAME_crattak9 168 #define FRAME_crpain1 169 #define FRAME_crpain2 170 #define FRAME_crpain3 171 #define FRAME_crpain4 172 #define FRAME_crdeath1 173 #define FRAME_crdeath2 174 #define FRAME_crdeath3 175 #define FRAME_crdeath4 176 #define FRAME_crdeath5 177 #define FRAME_death101 178 #define FRAME_death102 179 #define FRAME_death103 180 #define FRAME_death104 181 #define FRAME_death105 182 #define FRAME_death106 183 #define FRAME_death201 184 #define FRAME_death202 185 #define FRAME_death203 186 #define FRAME_death204 187 #define FRAME_death205 188 #define FRAME_death206 189 #define FRAME_death301 190 #define FRAME_death302 191 #define FRAME_death303 192 #define FRAME_death304 193 #define FRAME_death305 194 #define FRAME_death306 195 #define FRAME_death307 196 #define FRAME_death308 197 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/mutant/000077500000000000000000000000001477320066100173765ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/mutant/mutant.c000066400000000000000000000413531477320066100210600ustar00rootroot00000000000000/* ======================================================================= * * Mutant. * * ======================================================================= */ #include "../../header/local.h" #include "mutant.h" static int sound_swing; static int sound_hit; static int sound_hit2; static int sound_death; static int sound_idle; static int sound_pain1; static int sound_pain2; static int sound_sight; static int sound_search; static int sound_step1; static int sound_step2; static int sound_step3; static int sound_thud; void mutant_walk(edict_t *self); void mutant_step(edict_t *self) { int n; if (!self) { return; } n = (rand() + 1) % 3; if (n == 0) { gi.sound(self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0); } else if (n == 1) { gi.sound(self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0); } } void mutant_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void mutant_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); } void mutant_swing(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0); } static mframe_t mutant_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 10 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 20 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 30 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 40 */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* 50 */ {ai_stand, 0, NULL} }; mmove_t mutant_move_stand = { FRAME_stand101, FRAME_stand151, mutant_frames_stand, NULL }; void mutant_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_stand; } void mutant_idle_loop(edict_t *self) { if (!self) { return; } if (random() < 0.75) { self->monsterinfo.nextframe = FRAME_stand155; } } static mframe_t mutant_frames_idle[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, /* scratch loop start */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, mutant_idle_loop}, /* scratch loop end */ {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t mutant_move_idle = { FRAME_stand152, FRAME_stand164, mutant_frames_idle, mutant_stand }; void mutant_idle(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_idle; gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } static mframe_t mutant_frames_walk[] = { {ai_walk, 3, NULL}, {ai_walk, 1, NULL}, {ai_walk, 5, NULL}, {ai_walk, 10, NULL}, {ai_walk, 13, NULL}, {ai_walk, 10, NULL}, {ai_walk, 0, NULL}, {ai_walk, 5, NULL}, {ai_walk, 6, NULL}, {ai_walk, 16, NULL}, {ai_walk, 15, NULL}, {ai_walk, 6, NULL} }; mmove_t mutant_move_walk = { FRAME_walk05, FRAME_walk16, mutant_frames_walk, NULL }; void mutant_walk_loop(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_walk; } static mframe_t mutant_frames_start_walk[] = { {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, -2, NULL}, {ai_walk, 1, NULL} }; mmove_t mutant_move_start_walk = { FRAME_walk01, FRAME_walk04, mutant_frames_start_walk, mutant_walk_loop }; void mutant_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_start_walk; } static mframe_t mutant_frames_run[] = { {ai_run, 40, NULL}, {ai_run, 40, mutant_step}, {ai_run, 24, NULL}, {ai_run, 5, mutant_step}, {ai_run, 17, NULL}, {ai_run, 10, NULL} }; mmove_t mutant_move_run = { FRAME_run03, FRAME_run08, mutant_frames_run, NULL }; void mutant_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &mutant_move_stand; } else { self->monsterinfo.currentmove = &mutant_move_run; } } void mutant_hit_left(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->mins[0], 8); if (fire_hit(self, aim, (10 + (rand() % 5)), 100)) { gi.sound(self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); } } void mutant_hit_right(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, self->maxs[0], 8); if (fire_hit(self, aim, (10 + (rand() % 5)), 100)) { gi.sound(self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); } } void mutant_check_refire(edict_t *self) { if (!self) { return; } if (!self->enemy || !self->enemy->inuse || (self->enemy->health <= 0)) { return; } if (((skill->value == SKILL_HARDPLUS) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE)) { self->monsterinfo.nextframe = FRAME_attack09; } } static mframe_t mutant_frames_attack[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, mutant_hit_left}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, mutant_hit_right}, {ai_charge, 0, mutant_check_refire} }; mmove_t mutant_move_attack = { FRAME_attack09, FRAME_attack15, mutant_frames_attack, mutant_run }; void mutant_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_attack; } void mutant_jump_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (self->health <= 0) { self->touch = NULL; return; } if (other->takedamage) { if (VectorLength(self->velocity) > 400) { vec3_t point; vec3_t normal; int damage; VectorCopy(self->velocity, normal); VectorNormalize(normal); VectorMA(self->s.origin, self->maxs[0], normal, point); damage = 40 + 10 * random(); T_Damage(other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_UNKNOWN); } } if (!M_CheckBottom(self)) { if (self->groundentity) { self->monsterinfo.nextframe = FRAME_attack02; self->touch = NULL; } return; } self->touch = NULL; } void mutant_jump_takeoff(edict_t *self) { vec3_t forward; if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); AngleVectors(self->s.angles, forward, NULL, NULL); self->s.origin[2] += 1; VectorScale(forward, 600, self->velocity); self->velocity[2] = 250; self->groundentity = NULL; self->monsterinfo.aiflags |= AI_DUCKED; self->monsterinfo.attack_finished = level.time + 3; self->touch = mutant_jump_touch; } void mutant_check_landing(edict_t *self) { if (!self) { return; } if (self->groundentity) { gi.sound(self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0); self->monsterinfo.attack_finished = 0; self->monsterinfo.aiflags &= ~AI_DUCKED; return; } if (level.time > self->monsterinfo.attack_finished) { self->monsterinfo.nextframe = FRAME_attack02; } else { self->monsterinfo.nextframe = FRAME_attack05; } } static mframe_t mutant_frames_jump[] = { {ai_charge, 0, NULL}, {ai_charge, 17, NULL}, {ai_charge, 15, mutant_jump_takeoff}, {ai_charge, 15, NULL}, {ai_charge, 15, mutant_check_landing}, {ai_charge, 0, NULL}, {ai_charge, 3, NULL}, {ai_charge, 0, NULL} }; mmove_t mutant_move_jump = { FRAME_attack01, FRAME_attack08, mutant_frames_jump, mutant_run }; void mutant_jump(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &mutant_move_jump; } qboolean mutant_check_melee(edict_t *self) { if (!self) { return false; } if (range(self, self->enemy) == RANGE_MELEE) { return true; } return false; } qboolean mutant_check_jump(edict_t *self) { vec3_t v; float distance; if (!self) { return false; } if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2])) { return false; } if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2])) { return false; } v[0] = self->s.origin[0] - self->enemy->s.origin[0]; v[1] = self->s.origin[1] - self->enemy->s.origin[1]; v[2] = 0; distance = VectorLength(v); if (distance < 100) { return false; } if (distance > 100) { if (random() < 0.9) { return false; } } return true; } qboolean mutant_checkattack(edict_t *self) { if (!self) { return false; } if (!self->enemy || (self->enemy->health <= 0)) { return false; } if (mutant_check_melee(self)) { self->monsterinfo.attack_state = AS_MELEE; return true; } if (mutant_check_jump(self)) { self->monsterinfo.attack_state = AS_MISSILE; return true; } return false; } static mframe_t mutant_frames_pain1[] = { {ai_move, 4, NULL}, {ai_move, -3, NULL}, {ai_move, -8, NULL}, {ai_move, 2, NULL}, {ai_move, 5, NULL} }; mmove_t mutant_move_pain1 = { FRAME_pain101, FRAME_pain105, mutant_frames_pain1, mutant_run }; static mframe_t mutant_frames_pain2[] = { {ai_move, -24, NULL}, {ai_move, 11, NULL}, {ai_move, 5, NULL}, {ai_move, -2, NULL}, {ai_move, 6, NULL}, {ai_move, 4, NULL} }; mmove_t mutant_move_pain2 = { FRAME_pain201, FRAME_pain206, mutant_frames_pain2, mutant_run }; static mframe_t mutant_frames_pain3[] = { {ai_move, -22, NULL}, {ai_move, 3, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, 6, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 1, NULL} }; mmove_t mutant_move_pain3 = { FRAME_pain301, FRAME_pain311, mutant_frames_pain3, mutant_run }; void mutant_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { float r; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } r = random(); if (r < 0.33) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &mutant_move_pain1; } else if (r < 0.66) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &mutant_move_pain2; } else { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &mutant_move_pain3; } } void mutant_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; gi.linkentity(self); M_FlyCheck(self); } static mframe_t mutant_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t mutant_move_death1 = { FRAME_death101, FRAME_death109, mutant_frames_death1, mutant_dead }; static mframe_t mutant_frames_death2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t mutant_move_death2 = { FRAME_death201, FRAME_death210, mutant_frames_death2, mutant_dead }; void mutant_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unsued */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->s.skinnum = 1; if (random() < 0.5) { self->monsterinfo.currentmove = &mutant_move_death1; } else { self->monsterinfo.currentmove = &mutant_move_death2; } } void mutant_jump_down(edict_t *self) { vec3_t forward, up; if (!self) { return; } AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void mutant_jump_up(edict_t *self) { vec3_t forward, up; if (!self) { return; } AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 200, forward, self->velocity); VectorMA(self->velocity, 450, up, self->velocity); } void mutant_jump_wait_land(edict_t *self) { if (self->groundentity == NULL) { self->monsterinfo.nextframe = self->s.frame; } else { self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t mutant_frames_jump_up[] = { {ai_move, -8, NULL}, {ai_move, -8, mutant_jump_up}, {ai_move, 0, mutant_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t mutant_move_jump_up = { FRAME_jump01, FRAME_jump05, mutant_frames_jump_up, mutant_run }; static mframe_t mutant_frames_jump_down[] = { {ai_move, 0, NULL}, {ai_move, 0, mutant_jump_down}, {ai_move, 0, mutant_jump_wait_land}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t mutant_move_jump_down = { FRAME_jump01, FRAME_jump05, mutant_frames_jump_down, mutant_run }; void mutant_jump_updown(edict_t *self) { if (!self || !self->enemy) { return; } if (self->enemy->absmin[2] > self->absmin[2]) { self->monsterinfo.currentmove = &mutant_move_jump_up; } else { self->monsterinfo.currentmove = &mutant_move_jump_down; } } qboolean mutant_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkjump(self, dist, 256, 68)) { mutant_jump_updown(self); return true; } if (blocked_checkplat(self, dist)) return true; return false; } /* * QUAKED monster_mutant (1 .5 0) (-32 -32 -24) (32 32 32) Ambush Trigger_Spawn Sight */ void SP_monster_mutant(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_swing = gi.soundindex("mutant/mutatck1.wav"); sound_hit = gi.soundindex("mutant/mutatck2.wav"); sound_hit2 = gi.soundindex("mutant/mutatck3.wav"); sound_death = gi.soundindex("mutant/mutdeth1.wav"); sound_idle = gi.soundindex("mutant/mutidle1.wav"); sound_pain1 = gi.soundindex("mutant/mutpain1.wav"); sound_pain2 = gi.soundindex("mutant/mutpain2.wav"); sound_sight = gi.soundindex("mutant/mutsght1.wav"); sound_search = gi.soundindex("mutant/mutsrch1.wav"); sound_step1 = gi.soundindex("mutant/step1.wav"); sound_step2 = gi.soundindex("mutant/step2.wav"); sound_step3 = gi.soundindex("mutant/step3.wav"); sound_thud = gi.soundindex("mutant/thud1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/mutant/tris.md2"); VectorSet(self->mins, -32, -32, -24); VectorSet(self->maxs, 32, 32, 48); self->health = 300; self->gib_health = -120; self->mass = 300; self->pain = mutant_pain; self->die = mutant_die; self->monsterinfo.stand = mutant_stand; self->monsterinfo.walk = mutant_walk; self->monsterinfo.run = mutant_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = mutant_jump; self->monsterinfo.melee = mutant_melee; self->monsterinfo.sight = mutant_sight; self->monsterinfo.search = mutant_search; self->monsterinfo.idle = mutant_idle; self->monsterinfo.checkattack = mutant_checkattack; self->monsterinfo.blocked = mutant_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &mutant_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/mutant/mutant.h000066400000000000000000000125211477320066100210600ustar00rootroot00000000000000/* ======================================================================= * * Mutant animations. * * ======================================================================= */ #define FRAME_attack01 0 #define FRAME_attack02 1 #define FRAME_attack03 2 #define FRAME_attack04 3 #define FRAME_attack05 4 #define FRAME_attack06 5 #define FRAME_attack07 6 #define FRAME_attack08 7 #define FRAME_attack09 8 #define FRAME_attack10 9 #define FRAME_attack11 10 #define FRAME_attack12 11 #define FRAME_attack13 12 #define FRAME_attack14 13 #define FRAME_attack15 14 #define FRAME_death101 15 #define FRAME_death102 16 #define FRAME_death103 17 #define FRAME_death104 18 #define FRAME_death105 19 #define FRAME_death106 20 #define FRAME_death107 21 #define FRAME_death108 22 #define FRAME_death109 23 #define FRAME_death201 24 #define FRAME_death202 25 #define FRAME_death203 26 #define FRAME_death204 27 #define FRAME_death205 28 #define FRAME_death206 29 #define FRAME_death207 30 #define FRAME_death208 31 #define FRAME_death209 32 #define FRAME_death210 33 #define FRAME_pain101 34 #define FRAME_pain102 35 #define FRAME_pain103 36 #define FRAME_pain104 37 #define FRAME_pain105 38 #define FRAME_pain201 39 #define FRAME_pain202 40 #define FRAME_pain203 41 #define FRAME_pain204 42 #define FRAME_pain205 43 #define FRAME_pain206 44 #define FRAME_pain301 45 #define FRAME_pain302 46 #define FRAME_pain303 47 #define FRAME_pain304 48 #define FRAME_pain305 49 #define FRAME_pain306 50 #define FRAME_pain307 51 #define FRAME_pain308 52 #define FRAME_pain309 53 #define FRAME_pain310 54 #define FRAME_pain311 55 #define FRAME_run03 56 #define FRAME_run04 57 #define FRAME_run05 58 #define FRAME_run06 59 #define FRAME_run07 60 #define FRAME_run08 61 #define FRAME_stand101 62 #define FRAME_stand102 63 #define FRAME_stand103 64 #define FRAME_stand104 65 #define FRAME_stand105 66 #define FRAME_stand106 67 #define FRAME_stand107 68 #define FRAME_stand108 69 #define FRAME_stand109 70 #define FRAME_stand110 71 #define FRAME_stand111 72 #define FRAME_stand112 73 #define FRAME_stand113 74 #define FRAME_stand114 75 #define FRAME_stand115 76 #define FRAME_stand116 77 #define FRAME_stand117 78 #define FRAME_stand118 79 #define FRAME_stand119 80 #define FRAME_stand120 81 #define FRAME_stand121 82 #define FRAME_stand122 83 #define FRAME_stand123 84 #define FRAME_stand124 85 #define FRAME_stand125 86 #define FRAME_stand126 87 #define FRAME_stand127 88 #define FRAME_stand128 89 #define FRAME_stand129 90 #define FRAME_stand130 91 #define FRAME_stand131 92 #define FRAME_stand132 93 #define FRAME_stand133 94 #define FRAME_stand134 95 #define FRAME_stand135 96 #define FRAME_stand136 97 #define FRAME_stand137 98 #define FRAME_stand138 99 #define FRAME_stand139 100 #define FRAME_stand140 101 #define FRAME_stand141 102 #define FRAME_stand142 103 #define FRAME_stand143 104 #define FRAME_stand144 105 #define FRAME_stand145 106 #define FRAME_stand146 107 #define FRAME_stand147 108 #define FRAME_stand148 109 #define FRAME_stand149 110 #define FRAME_stand150 111 #define FRAME_stand151 112 #define FRAME_stand152 113 #define FRAME_stand153 114 #define FRAME_stand154 115 #define FRAME_stand155 116 #define FRAME_stand156 117 #define FRAME_stand157 118 #define FRAME_stand158 119 #define FRAME_stand159 120 #define FRAME_stand160 121 #define FRAME_stand161 122 #define FRAME_stand162 123 #define FRAME_stand163 124 #define FRAME_stand164 125 #define FRAME_walk01 126 #define FRAME_walk02 127 #define FRAME_walk03 128 #define FRAME_walk04 129 #define FRAME_walk05 130 #define FRAME_walk06 131 #define FRAME_walk07 132 #define FRAME_walk08 133 #define FRAME_walk09 134 #define FRAME_walk10 135 #define FRAME_walk11 136 #define FRAME_walk12 137 #define FRAME_walk13 138 #define FRAME_walk14 139 #define FRAME_walk15 140 #define FRAME_walk16 141 #define FRAME_walk17 142 #define FRAME_walk18 143 #define FRAME_walk19 144 #define FRAME_walk20 145 #define FRAME_walk21 146 #define FRAME_walk22 147 #define FRAME_walk23 148 #define FRAME_jump01 149 #define FRAME_jump02 150 #define FRAME_jump03 151 #define FRAME_jump04 152 #define FRAME_jump05 153 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/parasite/000077500000000000000000000000001477320066100176765ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/parasite/parasite.c000066400000000000000000000464761477320066100216730ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Parasite. * * ======================================================================= */ #include "../../header/local.h" #include "parasite.h" static int sound_pain1; static int sound_pain2; static int sound_die; static int sound_launch; static int sound_impact; static int sound_suck; static int sound_reelin; static int sound_sight; static int sound_tap; static int sound_scratch; static int sound_search; void parasite_stand(edict_t *self); void parasite_start_run(edict_t *self); void parasite_run(edict_t *self); void parasite_walk(edict_t *self); void parasite_start_walk(edict_t *self); void parasite_end_fidget(edict_t *self); void parasite_do_fidget(edict_t *self); void parasite_refidget(edict_t *self); void parasite_launch(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0); } void parasite_reel_in(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_reelin, 1, ATTN_NORM, 0); } void parasite_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0); } void parasite_tap(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0); } void parasite_footstep(edict_t *self) { if (g_monsterfootsteps->value) { parasite_tap(self); } } void parasite_scratch(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_scratch, 1, ATTN_IDLE, 0); } void parasite_search(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0); } static mframe_t parasite_frames_start_fidget[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t parasite_move_start_fidget = { FRAME_stand18, FRAME_stand21, parasite_frames_start_fidget, parasite_do_fidget }; static mframe_t parasite_frames_fidget[] = { {ai_stand, 0, parasite_scratch}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_scratch}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t parasite_move_fidget = { FRAME_stand22, FRAME_stand27, parasite_frames_fidget, parasite_refidget }; static mframe_t parasite_frames_end_fidget[] = { {ai_stand, 0, parasite_scratch}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t parasite_move_end_fidget = { FRAME_stand28, FRAME_stand35, parasite_frames_end_fidget, parasite_stand }; void parasite_end_fidget(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_end_fidget; } void parasite_do_fidget(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_fidget; } void parasite_refidget(edict_t *self) { if (!self) { return; } if (random() <= 0.8) { self->monsterinfo.currentmove = ¶site_move_fidget; } else { self->monsterinfo.currentmove = ¶site_move_end_fidget; } } void parasite_idle(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_start_fidget; } static mframe_t parasite_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap}, {ai_stand, 0, NULL}, {ai_stand, 0, parasite_tap} }; mmove_t parasite_move_stand = { FRAME_stand01, FRAME_stand17, parasite_frames_stand, parasite_stand }; void parasite_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_stand; } static mframe_t parasite_frames_run[] = { {ai_run, 30, NULL}, {ai_run, 30, NULL}, {ai_run, 22, parasite_footstep}, {ai_run, 19, parasite_footstep}, {ai_run, 24, NULL}, {ai_run, 28, parasite_footstep}, {ai_run, 25, NULL} }; mmove_t parasite_move_run = { FRAME_run03, FRAME_run09, parasite_frames_run, NULL }; static mframe_t parasite_frames_start_run[] = { {ai_run, 0, NULL}, {ai_run, 30, NULL}, }; mmove_t parasite_move_start_run = { FRAME_run01, FRAME_run02, parasite_frames_start_run, parasite_run }; static mframe_t parasite_frames_stop_run[] = { {ai_run, 20, NULL}, {ai_run, 20, NULL}, {ai_run, 12, parasite_footstep}, {ai_run, 10, NULL}, {ai_run, 0, NULL}, {ai_run, 0, NULL} }; mmove_t parasite_move_stop_run = { FRAME_run10, FRAME_run15, parasite_frames_stop_run, NULL }; void parasite_start_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = ¶site_move_stand; } else { self->monsterinfo.currentmove = ¶site_move_start_run; } } void parasite_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = ¶site_move_stand; } else { self->monsterinfo.currentmove = ¶site_move_run; } } static mframe_t parasite_frames_walk[] = { {ai_walk, 30, NULL}, {ai_walk, 30, NULL}, {ai_walk, 22, parasite_footstep}, {ai_walk, 19, NULL}, {ai_walk, 24, parasite_footstep}, {ai_walk, 28, parasite_footstep}, {ai_walk, 25, NULL} }; mmove_t parasite_move_walk = { FRAME_run03, FRAME_run09, parasite_frames_walk, parasite_walk }; static mframe_t parasite_frames_start_walk[] = { {ai_walk, 0, NULL}, {ai_walk, 30, parasite_walk} }; mmove_t parasite_move_start_walk = { FRAME_run01, FRAME_run02, parasite_frames_start_walk, NULL }; static mframe_t parasite_frames_stop_walk[] = { {ai_walk, 20, NULL}, {ai_walk, 20, NULL}, {ai_walk, 12, parasite_footstep}, {ai_walk, 10, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL} }; mmove_t parasite_move_stop_walk = { FRAME_run10, FRAME_run15, parasite_frames_stop_walk, NULL }; void parasite_start_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_start_walk; } void parasite_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_walk; } static mframe_t parasite_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 6, NULL}, {ai_move, 16, NULL}, {ai_move, -6, NULL}, {ai_move, -7, NULL}, {ai_move, 0, NULL} }; mmove_t parasite_move_pain1 = { FRAME_pain101, FRAME_pain111, parasite_frames_pain1, parasite_start_run }; void parasite_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage /* unused */) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); } self->monsterinfo.currentmove = ¶site_move_pain1; } qboolean parasite_drain_attack_ok(vec3_t start, vec3_t end) { vec3_t dir, angles; /* check for max distance */ VectorSubtract(start, end, dir); if (VectorLength(dir) > 256) { return false; } /* check for min/max pitch */ vectoangles(dir, angles); if (angles[0] < -180) { angles[0] += 360; } if (fabs(angles[0]) > 30) { return false; } return true; } void parasite_drain_attack(edict_t *self) { vec3_t offset, start, origStart, f, r, end, dir; trace_t tr; int damage; if (!self) { return; } AngleVectors(self->s.angles, f, r, NULL); VectorSet(offset, 24, 0, 6); G_ProjectSource(self->s.origin, offset, f, r, start); VectorCopy(self->enemy->s.origin, end); VectorSubtract(end, start, dir); { // will use the original startPoint for the actual effect etc, // the modified start is just for the traces VectorCopy(start, origStart); vec3_t dir2; // need normalized dir for offset VectorCopy(dir, dir2); VectorNormalize(dir2); // start = start - 8*dir => move start back a bit // so trace doesn't start in wall in case parasite is too close to wall VectorMA(start, -8.0f, dir2, start); } if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; if (!parasite_drain_attack_ok(start, end)) { return; } } } VectorCopy(self->enemy->s.origin, end); tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); if (tr.ent != self->enemy) { return; } if (self->s.frame == FRAME_drain03) { damage = 5; gi.sound(self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0); } else { if (self->s.frame == FRAME_drain04) { gi.sound(self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0); } damage = 2; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_PARASITE_ATTACK); gi.WriteShort(self - g_edicts); gi.WritePosition(origStart); gi.WritePosition(end); gi.multicast(self->s.origin, MULTICAST_PVS); T_Damage(self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); } static mframe_t parasite_frames_drain[] = { {ai_charge, 0, parasite_launch}, {ai_charge, 0, NULL}, {ai_charge, 15, parasite_drain_attack}, /* Target hits */ {ai_charge, 0, parasite_drain_attack}, /* drain */ {ai_charge, 0, parasite_drain_attack}, /* drain */ {ai_charge, 0, parasite_drain_attack}, /* drain */ {ai_charge, 0, parasite_drain_attack}, /* drain */ {ai_charge, -2, parasite_drain_attack}, /* drain */ {ai_charge, -2, parasite_drain_attack}, /* drain */ {ai_charge, -3, parasite_drain_attack}, /* drain */ {ai_charge, -2, parasite_drain_attack}, /* drain */ {ai_charge, 0, parasite_drain_attack}, /* drain */ {ai_charge, -1, parasite_drain_attack}, /* drain */ {ai_charge, 0, parasite_reel_in}, /* let go */ {ai_charge, -2, NULL}, {ai_charge, -2, NULL}, {ai_charge, -3, NULL}, {ai_charge, 0, NULL} }; mmove_t parasite_move_drain = { FRAME_drain01, FRAME_drain18, parasite_frames_drain, parasite_start_run }; static mframe_t parasite_frames_break[] = { {ai_charge, 0, NULL}, {ai_charge, -3, NULL}, {ai_charge, 1, NULL}, {ai_charge, 2, NULL}, {ai_charge, -3, NULL}, {ai_charge, 1, NULL}, {ai_charge, 1, NULL}, {ai_charge, 3, NULL}, {ai_charge, 0, NULL}, {ai_charge, -18, NULL}, {ai_charge, 3, NULL}, {ai_charge, 9, NULL}, {ai_charge, 6, NULL}, {ai_charge, 0, NULL}, {ai_charge, -18, NULL}, {ai_charge, 0, NULL}, {ai_charge, 8, NULL}, {ai_charge, 9, NULL}, {ai_charge, 0, NULL}, {ai_charge, -18, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* airborne */ {ai_charge, 0, NULL}, /* airborne */ {ai_charge, 0, NULL}, /* slides */ {ai_charge, 0, NULL}, /* slides */ {ai_charge, 0, NULL}, /* slides */ {ai_charge, 0, NULL}, /* slides */ {ai_charge, 4, NULL}, {ai_charge, 11, NULL}, {ai_charge, -2, NULL}, {ai_charge, -5, NULL}, {ai_charge, 1, NULL} }; mmove_t parasite_move_break = { FRAME_break01, FRAME_break32, parasite_frames_break, parasite_start_run }; void parasite_attack(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = ¶site_move_drain; } void parasite_jump_down(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void parasite_jump_up(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 200, forward, self->velocity); VectorMA(self->velocity, 450, up, self->velocity); } void parasite_jump_wait_land(edict_t *self) { if (!self) { return; } if (self->groundentity == NULL) { self->monsterinfo.nextframe = self->s.frame; if (monster_jump_finished(self)) { self->monsterinfo.nextframe = self->s.frame + 1; } } else { self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t parasite_frames_jump_up[] = { {ai_move, -8, NULL}, {ai_move, -8, NULL}, {ai_move, -8, NULL}, {ai_move, -8, parasite_jump_up}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, parasite_jump_wait_land}, {ai_move, 0, NULL} }; mmove_t parasite_move_jump_up = { FRAME_jump01, FRAME_jump08, parasite_frames_jump_up, parasite_run }; static mframe_t parasite_frames_jump_down[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, parasite_jump_down}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, parasite_jump_wait_land}, {ai_move, 0, NULL} }; mmove_t parasite_move_jump_down = { FRAME_jump01, FRAME_jump08, parasite_frames_jump_down, parasite_run }; void parasite_jump(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } if (self->enemy->absmin[2] > self->absmin[2]) { self->monsterinfo.currentmove = ¶site_move_jump_up; } else { self->monsterinfo.currentmove = ¶site_move_jump_down; } } qboolean parasite_blocked(edict_t *self, float dist) { if (!self) { return false; } if (self->enemy && self->enemy->client && random() >= (0.25 + (0.05 * skill->value))) { vec3_t f, r, offset, start, end; AngleVectors(self->s.angles, f, r, NULL); VectorSet(offset, 24, 0, 6); G_ProjectSource(self->s.origin, offset, f, r, start); VectorCopy(self->enemy->s.origin, end); if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; if (!parasite_drain_attack_ok(start, end)) { return false; } } } VectorCopy(self->enemy->s.origin, end); if (visible(self, self->enemy)) { parasite_attack(self); return true; } } if (blocked_checkjump(self, dist, 256, 68)) { parasite_jump(self); return true; } if (blocked_checkplat(self, dist)) { return true; } return false; } qboolean parasite_checkattack(edict_t *self) { vec3_t f, r, offset, start, end; trace_t tr; qboolean retval; if (!self) { return false; } retval = M_CheckAttack(self); if (!retval) { return false; } AngleVectors(self->s.angles, f, r, NULL); VectorSet(offset, 24, 0, 6); G_ProjectSource(self->s.origin, offset, f, r, start); VectorCopy(self->enemy->s.origin, end); if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; if (!parasite_drain_attack_ok(start, end)) { return false; } } } VectorCopy(self->enemy->s.origin, end); tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); if (tr.ent != self->enemy) { self->monsterinfo.aiflags |= AI_BLOCKED; if (self->monsterinfo.attack) { self->monsterinfo.attack(self); } self->monsterinfo.aiflags &= ~AI_BLOCKED; return true; } return true; } void parasite_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t parasite_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t parasite_move_death = { FRAME_death101, FRAME_death107, parasite_frames_death, parasite_dead }; void parasite_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = ¶site_move_death; } /* * QUAKED monster_parasite (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight */ void SP_monster_parasite(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("parasite/parpain1.wav"); sound_pain2 = gi.soundindex("parasite/parpain2.wav"); sound_die = gi.soundindex("parasite/pardeth1.wav"); sound_launch = gi.soundindex("parasite/paratck1.wav"); sound_impact = gi.soundindex("parasite/paratck2.wav"); sound_suck = gi.soundindex("parasite/paratck3.wav"); sound_reelin = gi.soundindex("parasite/paratck4.wav"); sound_sight = gi.soundindex("parasite/parsght1.wav"); sound_tap = gi.soundindex("parasite/paridle1.wav"); sound_scratch = gi.soundindex("parasite/paridle2.wav"); sound_search = gi.soundindex("parasite/parsrch1.wav"); self->s.modelindex = gi.modelindex("models/monsters/parasite/tris.md2"); VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 24); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->health = 175; self->gib_health = -50; self->mass = 250; self->viewheight = 16; self->pain = parasite_pain; self->die = parasite_die; self->monsterinfo.stand = parasite_stand; self->monsterinfo.walk = parasite_start_walk; self->monsterinfo.run = parasite_start_run; self->monsterinfo.attack = parasite_attack; self->monsterinfo.sight = parasite_sight; self->monsterinfo.idle = parasite_idle; self->monsterinfo.blocked = parasite_blocked; self->monsterinfo.checkattack = parasite_checkattack; gi.linkentity(self); self->monsterinfo.currentmove = ¶site_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/parasite/parasite.h000066400000000000000000000107451477320066100216660ustar00rootroot00000000000000/* ======================================================================= * * Parasite animations. * * ======================================================================= */ #define FRAME_break01 0 #define FRAME_break02 1 #define FRAME_break03 2 #define FRAME_break04 3 #define FRAME_break05 4 #define FRAME_break06 5 #define FRAME_break07 6 #define FRAME_break08 7 #define FRAME_break09 8 #define FRAME_break10 9 #define FRAME_break11 10 #define FRAME_break12 11 #define FRAME_break13 12 #define FRAME_break14 13 #define FRAME_break15 14 #define FRAME_break16 15 #define FRAME_break17 16 #define FRAME_break18 17 #define FRAME_break19 18 #define FRAME_break20 19 #define FRAME_break21 20 #define FRAME_break22 21 #define FRAME_break23 22 #define FRAME_break24 23 #define FRAME_break25 24 #define FRAME_break26 25 #define FRAME_break27 26 #define FRAME_break28 27 #define FRAME_break29 28 #define FRAME_break30 29 #define FRAME_break31 30 #define FRAME_break32 31 #define FRAME_death101 32 #define FRAME_death102 33 #define FRAME_death103 34 #define FRAME_death104 35 #define FRAME_death105 36 #define FRAME_death106 37 #define FRAME_death107 38 #define FRAME_drain01 39 #define FRAME_drain02 40 #define FRAME_drain03 41 #define FRAME_drain04 42 #define FRAME_drain05 43 #define FRAME_drain06 44 #define FRAME_drain07 45 #define FRAME_drain08 46 #define FRAME_drain09 47 #define FRAME_drain10 48 #define FRAME_drain11 49 #define FRAME_drain12 50 #define FRAME_drain13 51 #define FRAME_drain14 52 #define FRAME_drain15 53 #define FRAME_drain16 54 #define FRAME_drain17 55 #define FRAME_drain18 56 #define FRAME_pain101 57 #define FRAME_pain102 58 #define FRAME_pain103 59 #define FRAME_pain104 60 #define FRAME_pain105 61 #define FRAME_pain106 62 #define FRAME_pain107 63 #define FRAME_pain108 64 #define FRAME_pain109 65 #define FRAME_pain110 66 #define FRAME_pain111 67 #define FRAME_run01 68 #define FRAME_run02 69 #define FRAME_run03 70 #define FRAME_run04 71 #define FRAME_run05 72 #define FRAME_run06 73 #define FRAME_run07 74 #define FRAME_run08 75 #define FRAME_run09 76 #define FRAME_run10 77 #define FRAME_run11 78 #define FRAME_run12 79 #define FRAME_run13 80 #define FRAME_run14 81 #define FRAME_run15 82 #define FRAME_stand01 83 #define FRAME_stand02 84 #define FRAME_stand03 85 #define FRAME_stand04 86 #define FRAME_stand05 87 #define FRAME_stand06 88 #define FRAME_stand07 89 #define FRAME_stand08 90 #define FRAME_stand09 91 #define FRAME_stand10 92 #define FRAME_stand11 93 #define FRAME_stand12 94 #define FRAME_stand13 95 #define FRAME_stand14 96 #define FRAME_stand15 97 #define FRAME_stand16 98 #define FRAME_stand17 99 #define FRAME_stand18 100 #define FRAME_stand19 101 #define FRAME_stand20 102 #define FRAME_stand21 103 #define FRAME_stand22 104 #define FRAME_stand23 105 #define FRAME_stand24 106 #define FRAME_stand25 107 #define FRAME_stand26 108 #define FRAME_stand27 109 #define FRAME_stand28 110 #define FRAME_stand29 111 #define FRAME_stand30 112 #define FRAME_stand31 113 #define FRAME_stand32 114 #define FRAME_stand33 115 #define FRAME_stand34 116 #define FRAME_stand35 117 #define FRAME_jump01 118 #define FRAME_jump02 119 #define FRAME_jump03 120 #define FRAME_jump04 121 #define FRAME_jump05 122 #define FRAME_jump06 123 #define FRAME_jump07 124 #define FRAME_jump08 125 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/soldier/000077500000000000000000000000001477320066100175275ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/soldier/soldier.c000066400000000000000000001066371477320066100213510ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 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 the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Soldier aka "Guard". This is the most complex enemy in Quake 2, since * it uses all AI features (dodging, sight, crouching, etc) and comes * in a myriad of variants. In Rogue it's even more complex due to * the blindfire stuff. * * ======================================================================= */ #include "../../header/local.h" #include "soldier.h" static int sound_idle; static int sound_sight1; static int sound_sight2; static int sound_pain_light; static int sound_pain; static int sound_pain_ss; static int sound_death_light; static int sound_death; static int sound_death_ss; static int sound_cock; static int sound_step; static int sound_step2; static int sound_step3; static int sound_step4; void soldier_duck_up(edict_t *self); void soldier_stand(edict_t *self); void soldier_run(edict_t *self); void soldier_fire(edict_t *self, int); void soldier_blind(edict_t *self); void soldier_footstep(edict_t *self) { if (!g_monsterfootsteps->value) return; // Lazy loading for savegame compatibility. if (sound_step == 0 || sound_step2 == 0 || sound_step3 == 0 || sound_step4 == 0) { sound_step = gi.soundindex("player/step1.wav"); sound_step2 = gi.soundindex("player/step2.wav"); sound_step3 = gi.soundindex("player/step3.wav"); sound_step4 = gi.soundindex("player/step4.wav"); } int i; i = randk() % 4; if (i == 0) { gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } else if (i == 1) { gi.sound(self, CHAN_BODY, sound_step2, 1, ATTN_NORM, 0); } else if (i == 2) { gi.sound(self, CHAN_BODY, sound_step3, 1, ATTN_NORM, 0); } else if (i == 3) { gi.sound(self, CHAN_BODY, sound_step4, 1, ATTN_NORM, 0); } } void soldier_start_charge(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_CHARGING; } void soldier_stop_charge(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_CHARGING; } void soldier_idle(edict_t *self) { if (!self) { return; } if (random() > 0.8) { gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } } void soldier_cock(edict_t *self) { if (!self) { return; } if (self->s.frame == FRAME_stand322) { gi.sound(self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0); } else { gi.sound(self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0); } } static mframe_t soldier_frames_stand1[] = { {ai_stand, 0, soldier_idle}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t soldier_move_stand1 = { FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand }; static mframe_t soldier_frames_stand3[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, soldier_cock}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t soldier_move_stand3 = { FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand }; void soldier_stand(edict_t *self) { if (!self) { return; } if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8)) { self->monsterinfo.currentmove = &soldier_move_stand1; } else { self->monsterinfo.currentmove = &soldier_move_stand3; } } void soldier_walk1_random(edict_t *self) { if (!self) { return; } if (random() > 0.1) { self->monsterinfo.nextframe = FRAME_walk101; } } static mframe_t soldier_frames_walk1[] = { {ai_walk, 3, NULL}, {ai_walk, 6, NULL}, {ai_walk, 2, NULL}, {ai_walk, 2, soldier_footstep}, {ai_walk, 2, NULL}, {ai_walk, 1, NULL}, {ai_walk, 6, NULL}, {ai_walk, 5, NULL}, {ai_walk, 3, soldier_footstep}, {ai_walk, -1, soldier_walk1_random}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL} }; mmove_t soldier_move_walk1 = { FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL }; static mframe_t soldier_frames_walk2[] = { {ai_walk, 4, soldier_footstep}, {ai_walk, 4, NULL}, {ai_walk, 9, NULL}, {ai_walk, 8, NULL}, {ai_walk, 5, soldier_footstep}, {ai_walk, 1, NULL}, {ai_walk, 3, NULL}, {ai_walk, 7, NULL}, {ai_walk, 6, NULL}, {ai_walk, 7, NULL} }; mmove_t soldier_move_walk2 = { FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL }; void soldier_walk(edict_t *self) { if (!self) { return; } if (random() < 0.5) { self->monsterinfo.currentmove = &soldier_move_walk1; } else { self->monsterinfo.currentmove = &soldier_move_walk2; } } static mframe_t soldier_frames_start_run[] = { {ai_run, 7, NULL}, {ai_run, 5, NULL} }; mmove_t soldier_move_start_run = { FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run }; void soldier_fire_run(edict_t *self) { if (!self) { return; } if ((self->s.skinnum <= 1) && (self->enemy) && visible(self, self->enemy)) { soldier_fire(self, 0); } } static mframe_t soldier_frames_run[] = { {ai_run, 10, NULL}, {ai_run, 11, soldier_footstep}, {ai_run, 11, NULL}, {ai_run, 16, NULL}, {ai_run, 10, soldier_footstep}, {ai_run, 15, NULL} }; mmove_t soldier_move_run = { FRAME_run03, FRAME_run08, soldier_frames_run, NULL }; void soldier_run(edict_t *self) { if (!self) { return; } monster_done_dodge(self); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &soldier_move_stand1; return; } if ((self->monsterinfo.currentmove == &soldier_move_walk1) || (self->monsterinfo.currentmove == &soldier_move_walk2) || (self->monsterinfo.currentmove == &soldier_move_start_run)) { self->monsterinfo.currentmove = &soldier_move_run; } else { self->monsterinfo.currentmove = &soldier_move_start_run; } } static mframe_t soldier_frames_pain1[] = { {ai_move, -3, NULL}, {ai_move, 4, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_pain1 = { FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run }; static mframe_t soldier_frames_pain2[] = { {ai_move, -13, NULL}, {ai_move, -1, NULL}, {ai_move, 2, NULL}, {ai_move, 4, NULL}, {ai_move, 2, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL} }; mmove_t soldier_move_pain2 = { FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run }; static mframe_t soldier_frames_pain3[] = { {ai_move, -8, NULL}, {ai_move, 10, NULL}, {ai_move, -4, soldier_footstep}, {ai_move, -1, NULL}, {ai_move, -3, NULL}, {ai_move, 0, NULL}, {ai_move, 3, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 1, NULL}, {ai_move, 2, NULL}, {ai_move, 4, NULL}, {ai_move, 3, NULL}, {ai_move, 2, soldier_footstep} }; mmove_t soldier_move_pain3 = { FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run }; static mframe_t soldier_frames_pain4[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -10, NULL}, {ai_move, -6, NULL}, {ai_move, 8, NULL}, {ai_move, 4, NULL}, {ai_move, 1, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 5, NULL}, {ai_move, 2, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_pain4 = { FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run }; void soldier_pain(edict_t *self, edict_t *other /* unused */, float kick /* unused */, int damage /* unused */) { float r; int n; if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; } monster_done_dodge(self); soldier_stop_charge(self); /* if we're blind firing, this needs to be turned off here */ self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; if (level.time < self->pain_debounce_time) { if ((self->velocity[2] > 100) && ((self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3))) { /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } self->monsterinfo.currentmove = &soldier_move_pain4; } return; } self->pain_debounce_time = level.time + 3; n = self->s.skinnum | 1; if (n == 1) { gi.sound(self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0); } else if (n == 3) { gi.sound(self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0); } if (self->velocity[2] > 100) { /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } self->monsterinfo.currentmove = &soldier_move_pain4; return; } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } r = random(); if (r < 0.33) { self->monsterinfo.currentmove = &soldier_move_pain1; } else if (r < 0.66) { self->monsterinfo.currentmove = &soldier_move_pain2; } else { self->monsterinfo.currentmove = &soldier_move_pain3; } /* clear duck flag */ if (self->monsterinfo.aiflags & AI_DUCKED) { monster_duck_up(self); } } static int blaster_flash[] = { MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8 }; static int shotgun_flash[] = { MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8 }; static int machinegun_flash[] = { MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8 }; void soldier_fire(edict_t *self, int in_flash_number) { vec3_t start; vec3_t forward, right, up; vec3_t aim; vec3_t dir; vec3_t end; float r, u; int flash_index; int flash_number; if (!self) { return; } vec3_t aim_norm; float angle; trace_t tr; vec3_t aim_good; if ((!self->enemy) || (!self->enemy->inuse)) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; return; } if (in_flash_number < 0) { flash_number = -1 * in_flash_number; } else { flash_number = in_flash_number; } if (self->s.skinnum < 2) { flash_index = blaster_flash[flash_number]; } else if (self->s.skinnum < 4) { flash_index = shotgun_flash[flash_number]; } else { flash_index = machinegun_flash[flash_number]; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_index], forward, right, start); if ((flash_number == 5) || (flash_number == 6)) /* he's dead */ { VectorCopy(forward, aim); } else { VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, aim); VectorCopy(end, aim_good); if (in_flash_number < 0) { VectorCopy(aim, aim_norm); VectorNormalize(aim_norm); angle = DotProduct(aim_norm, forward); if (angle < 0.9) /* ~25 degree angle */ { return; } } vectoangles(aim, dir); AngleVectors(dir, forward, right, up); if (skill->value < SKILL_HARD) { r = crandom() * 1000; u = crandom() * 500; } else { r = crandom() * 500; u = crandom() * 250; } VectorMA(start, 8192, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); VectorSubtract(end, start, aim); VectorNormalize(aim); } if (!((flash_number == 5) || (flash_number == 6))) /* he's dead */ { tr = gi.trace(start, NULL, NULL, aim_good, self, MASK_SHOT); if ((tr.ent != self->enemy) && (tr.ent != world)) { return; } } if (self->s.skinnum <= 1) { monster_fire_blaster(self, start, aim, 5, 600, flash_index, EF_BLASTER); } else if (self->s.skinnum <= 3) { monster_fire_shotgun(self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index); } else { /* changed to wait from pausetime to not interfere with dodge code */ if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) { self->wait = level.time + (3 + rand() % 8) * FRAMETIME; } monster_fire_bullet(self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index); if (level.time >= self->wait) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; } else { self->monsterinfo.aiflags |= AI_HOLD_FRAME; } } } void soldier_fire1(edict_t *self) { if (!self) { return; } soldier_fire(self, 0); } void soldier_attack1_refire1(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; return; } if (!self->enemy) { return; } if (self->s.skinnum > 1) { return; } if (self->enemy->health <= 0) { return; } if (((skill->value == SKILL_HARDPLUS) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE)) { self->monsterinfo.nextframe = FRAME_attak102; } else { self->monsterinfo.nextframe = FRAME_attak110; } } void soldier_attack1_refire2(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } if (self->s.skinnum < 2) { return; } if (self->enemy->health <= 0) { return; } if (((skill->value == SKILL_HARDPLUS) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE)) { self->monsterinfo.nextframe = FRAME_attak102; } } static mframe_t soldier_frames_attack1[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_fire1}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_attack1_refire1}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_cock}, {ai_charge, 0, soldier_attack1_refire2}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t soldier_move_attack1 = { FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run }; void soldier_fire2(edict_t *self) { if (!self) { return; } soldier_fire(self, 1); } void soldier_attack2_refire1(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } if (self->s.skinnum > 1) { return; } if (self->enemy->health <= 0) { return; } if (((skill->value == SKILL_HARDPLUS) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE)) { self->monsterinfo.nextframe = FRAME_attak204; } else { self->monsterinfo.nextframe = FRAME_attak216; } } void soldier_attack2_refire2(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } if (self->s.skinnum < 2) { return; } if (self->enemy->health <= 0) { return; } if (((skill->value == SKILL_HARDPLUS) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE)) { self->monsterinfo.nextframe = FRAME_attak204; } } static mframe_t soldier_frames_attack2[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_fire2}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_attack2_refire1}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_cock}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_attack2_refire2}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t soldier_move_attack2 = { FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run }; void soldier_fire3(edict_t *self) { if (!self) { return; } monster_duck_down(self); soldier_fire(self, 2); } void soldier_attack3_refire(edict_t *self) { if (!self) { return; } if ((level.time + 0.4) < self->monsterinfo.duck_wait_time) { self->monsterinfo.nextframe = FRAME_attak303; } } static mframe_t soldier_frames_attack3[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_fire3}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_attack3_refire}, {ai_charge, 0, monster_duck_up}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t soldier_move_attack3 = { FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run }; void soldier_fire4(edict_t *self) { if (!self) { return; } soldier_fire(self, 3); } static mframe_t soldier_frames_attack4[] = { {ai_charge, 0, NULL}, {ai_charge, 0, soldier_footstep}, {ai_charge, 0, soldier_fire4}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, soldier_footstep} }; mmove_t soldier_move_attack4 = { FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run }; void soldier_fire8(edict_t *self) { if (!self) { return; } soldier_fire(self, -7); } void soldier_attack6_refire(edict_t *self) { if (!self) { return; } /* make sure dodge & charge bits are cleared */ monster_done_dodge(self); soldier_stop_charge(self); if (!self->enemy) { return; } if (self->enemy->health <= 0) { return; } if (range(self, self->enemy) < RANGE_NEAR) { return; } if ((skill->value == SKILL_HARDPLUS) || ((random() < (0.25 * ((float)skill->value))))) { self->monsterinfo.nextframe = FRAME_runs03; } } static mframe_t soldier_frames_attack6[] = { {ai_run, 10, soldier_start_charge}, {ai_run, 4, NULL}, {ai_run, 12, soldier_fire8}, {ai_run, 11, soldier_footstep}, {ai_run, 13, monster_done_dodge}, {ai_run, 18, NULL}, {ai_run, 15, NULL}, {ai_run, 14, NULL}, {ai_run, 11, NULL}, {ai_run, 8, NULL}, {ai_run, 11, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 17, soldier_attack6_refire} }; mmove_t soldier_move_attack6 = { FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run }; void soldier_attack(edict_t *self) { float r, chance; if (!self) { return; } monster_done_dodge(self); /* blindfire! */ if (self->monsterinfo.attack_state == AS_BLIND) { /* setup shot probabilities */ if (self->monsterinfo.blind_fire_delay < 1.0) { chance = 1.0; } else if (self->monsterinfo.blind_fire_delay < 7.5) { chance = 0.4; } else { chance = 0.1; } r = random(); /* minimum of 2 seconds, plus 0-3, after the shots are done */ self->monsterinfo.blind_fire_delay += 2.1 + 2.0 + random() * 3.0; /* don't shoot at the origin */ if (VectorCompare(self->monsterinfo.blind_fire_target, vec3_origin)) { return; } /* don't shoot if the dice say not to */ if (r > chance) { return; } /* turn on manual steering to signal both manual steering and blindfire */ self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->monsterinfo.currentmove = &soldier_move_attack1; self->monsterinfo.attack_finished = level.time + 1.5 + random(); return; } r = random(); if ((!(self->monsterinfo.aiflags & (AI_BLOCKED | AI_STAND_GROUND))) && (range(self, self->enemy) >= RANGE_NEAR) && ((r < (skill->value * 0.25)) && (self->s.skinnum <= 3))) { self->monsterinfo.currentmove = &soldier_move_attack6; } else { if (self->s.skinnum < 4) { if (random() < 0.5) { self->monsterinfo.currentmove = &soldier_move_attack1; } else { self->monsterinfo.currentmove = &soldier_move_attack2; } } else { self->monsterinfo.currentmove = &soldier_move_attack4; } } } void soldier_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0); } if ((skill->value > SKILL_EASY) && (self->enemy) && (range(self, self->enemy) >= RANGE_NEAR)) { /* don't let machinegunners run & shoot */ if ((random() > 0.75) && (self->s.skinnum <= 3)) { self->monsterinfo.currentmove = &soldier_move_attack6; } } } static mframe_t soldier_frames_duck[] = { {ai_move, 5, monster_duck_down}, {ai_move, -1, monster_duck_hold}, {ai_move, 1, NULL}, {ai_move, 0, monster_duck_up}, {ai_move, 5, NULL} }; mmove_t soldier_move_duck = { FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run }; qboolean soldier_blocked(edict_t *self, float dist) { if (!self) { return false; } /* don't do anything if you're dodging */ if ((self->monsterinfo.aiflags & AI_DODGING) || (self->monsterinfo.aiflags & AI_DUCKED)) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } void soldier_fire6(edict_t *self) { if (!self) { return; } soldier_fire(self, 5); } void soldier_fire7(edict_t *self) { if (!self) { return; } soldier_fire(self, 6); } void soldier_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void soldier_dead2(edict_t *self) { vec3_t tempmins, tempmaxs, temporg; trace_t tr; if (!self) { return; } VectorCopy(self->s.origin, temporg); /* this is because location traces done at the floor are guaranteed to hit the floor (inside the sv_trace code it grows the bbox by 1 in all directions) */ temporg[2] += 1; VectorSet(tempmins, -32, -32, -24); VectorSet(tempmaxs, 32, 32, -8); tr = gi.trace(temporg, tempmins, tempmaxs, temporg, self, MASK_SOLID); if (tr.startsolid || tr.allsolid) { VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, -8); } else { VectorCopy(tempmins, self->mins); VectorCopy(tempmaxs, self->maxs); } self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t soldier_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, -10, NULL}, {ai_move, -10, NULL}, {ai_move, -10, NULL}, {ai_move, -5, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, soldier_fire6}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, soldier_fire7}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_death1 = { FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead }; static mframe_t soldier_frames_death2[] = { {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_death2 = { FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead }; static mframe_t soldier_frames_death3[] = { {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, }; mmove_t soldier_move_death3 = { FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead }; static mframe_t soldier_frames_death4[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_death4 = { FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead2 }; static mframe_t soldier_frames_death5[] = { {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_death5 = { FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead }; static mframe_t soldier_frames_death6[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_death6 = { FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead }; void soldier_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 3; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->s.skinnum |= 1; if (self->s.skinnum == 1) { gi.sound(self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0); } else if (self->s.skinnum == 3) { gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0); } if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4) { /* head shot */ self->monsterinfo.currentmove = &soldier_move_death3; return; } n = rand() % 5; if (n == 0) { self->monsterinfo.currentmove = &soldier_move_death1; } else if (n == 1) { self->monsterinfo.currentmove = &soldier_move_death2; } else if (n == 2) { self->monsterinfo.currentmove = &soldier_move_death4; } else if (n == 3) { self->monsterinfo.currentmove = &soldier_move_death5; } else { self->monsterinfo.currentmove = &soldier_move_death6; } } void soldier_sidestep(edict_t *self) { if (!self) { return; } if (self->s.skinnum <= 3) { if (self->monsterinfo.currentmove != &soldier_move_attack6) { self->monsterinfo.currentmove = &soldier_move_attack6; } } else { if (self->monsterinfo.currentmove != &soldier_move_start_run) { self->monsterinfo.currentmove = &soldier_move_start_run; } } } void soldier_duck(edict_t *self, float eta) { float r; if (!self) { return; } /* has to be done immediately otherwise he can get stuck */ monster_duck_down(self); if (skill->value == SKILL_EASY) { self->monsterinfo.currentmove = &soldier_move_duck; self->monsterinfo.duck_wait_time = level.time + eta + 1; return; } r = random(); if (r > (skill->value * 0.3)) { self->monsterinfo.currentmove = &soldier_move_duck; self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); } else { self->monsterinfo.currentmove = &soldier_move_attack3; self->monsterinfo.duck_wait_time = level.time + eta + 1; } } static mframe_t soldier_frames_blind[] = { {ai_move, 0, soldier_idle}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t soldier_move_blind = { FRAME_stand101, FRAME_stand130, soldier_frames_blind, soldier_blind }; void soldier_blind(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &soldier_move_blind; } void SP_monster_soldier_x(edict_t *self) { if (!self) { return; } // Force recaching at next footstep to ensure // that the sound indices are correct. sound_step = 0; sound_step2 = 0; sound_step3 = 0; sound_step4 = 0; self->s.modelindex = gi.modelindex("models/monsters/soldier/tris.md2"); self->monsterinfo.scale = MODEL_SCALE; VectorSet(self->mins, -16, -16, -24); VectorSet(self->maxs, 16, 16, 32); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; sound_idle = gi.soundindex("soldier/solidle1.wav"); sound_sight1 = gi.soundindex("soldier/solsght1.wav"); sound_sight2 = gi.soundindex("soldier/solsrch1.wav"); sound_cock = gi.soundindex("infantry/infatck3.wav"); self->mass = 100; self->pain = soldier_pain; self->die = soldier_die; self->monsterinfo.stand = soldier_stand; self->monsterinfo.walk = soldier_walk; self->monsterinfo.run = soldier_run; self->monsterinfo.dodge = M_MonsterDodge; self->monsterinfo.attack = soldier_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = soldier_sight; self->monsterinfo.blocked = soldier_blocked; self->monsterinfo.duck = soldier_duck; self->monsterinfo.unduck = monster_duck_up; self->monsterinfo.sidestep = soldier_sidestep; if (self->spawnflags & 8) /* blind */ { self->monsterinfo.stand = soldier_blind; } gi.linkentity(self); self->monsterinfo.stand(self); walkmonster_start(self); } /* * QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind * * Blind - monster will just stand there until triggered */ void SP_monster_soldier_light(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->health = 20; self->gib_health = -30; SP_monster_soldier_x(self); sound_pain_light = gi.soundindex("soldier/solpain2.wav"); sound_death_light = gi.soundindex("soldier/soldeth2.wav"); gi.modelindex("models/objects/laser/tris.md2"); gi.soundindex("misc/lasfly.wav"); gi.soundindex("soldier/solatck2.wav"); self->s.skinnum = 0; self->monsterinfo.blindfire = true; } /* * QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind * * Blind - monster will just stand there until triggered */ void SP_monster_soldier(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->health = 30; self->gib_health = -30; SP_monster_soldier_x(self); sound_pain = gi.soundindex("soldier/solpain1.wav"); sound_death = gi.soundindex("soldier/soldeth1.wav"); gi.soundindex("soldier/solatck1.wav"); self->s.skinnum = 2; } /* * QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind * * Blind - monster will just stand there until triggered */ void SP_monster_soldier_ss(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->health = 40; self->gib_health = -30; SP_monster_soldier_x(self); sound_pain_ss = gi.soundindex("soldier/solpain3.wav"); sound_death_ss = gi.soundindex("soldier/soldeth3.wav"); gi.soundindex("soldier/solatck3.wav"); self->s.skinnum = 4; } rogue-ROGUE_2_13/src/monster/soldier/soldier.h000066400000000000000000000405501477320066100213450ustar00rootroot00000000000000/* ======================================================================= * * Soldier aka "Guard" animations. * * ======================================================================= */ #define FRAME_attak101 0 #define FRAME_attak102 1 #define FRAME_attak103 2 #define FRAME_attak104 3 #define FRAME_attak105 4 #define FRAME_attak106 5 #define FRAME_attak107 6 #define FRAME_attak108 7 #define FRAME_attak109 8 #define FRAME_attak110 9 #define FRAME_attak111 10 #define FRAME_attak112 11 #define FRAME_attak201 12 #define FRAME_attak202 13 #define FRAME_attak203 14 #define FRAME_attak204 15 #define FRAME_attak205 16 #define FRAME_attak206 17 #define FRAME_attak207 18 #define FRAME_attak208 19 #define FRAME_attak209 20 #define FRAME_attak210 21 #define FRAME_attak211 22 #define FRAME_attak212 23 #define FRAME_attak213 24 #define FRAME_attak214 25 #define FRAME_attak215 26 #define FRAME_attak216 27 #define FRAME_attak217 28 #define FRAME_attak218 29 #define FRAME_attak301 30 #define FRAME_attak302 31 #define FRAME_attak303 32 #define FRAME_attak304 33 #define FRAME_attak305 34 #define FRAME_attak306 35 #define FRAME_attak307 36 #define FRAME_attak308 37 #define FRAME_attak309 38 #define FRAME_attak401 39 #define FRAME_attak402 40 #define FRAME_attak403 41 #define FRAME_attak404 42 #define FRAME_attak405 43 #define FRAME_attak406 44 #define FRAME_duck01 45 #define FRAME_duck02 46 #define FRAME_duck03 47 #define FRAME_duck04 48 #define FRAME_duck05 49 #define FRAME_pain101 50 #define FRAME_pain102 51 #define FRAME_pain103 52 #define FRAME_pain104 53 #define FRAME_pain105 54 #define FRAME_pain201 55 #define FRAME_pain202 56 #define FRAME_pain203 57 #define FRAME_pain204 58 #define FRAME_pain205 59 #define FRAME_pain206 60 #define FRAME_pain207 61 #define FRAME_pain301 62 #define FRAME_pain302 63 #define FRAME_pain303 64 #define FRAME_pain304 65 #define FRAME_pain305 66 #define FRAME_pain306 67 #define FRAME_pain307 68 #define FRAME_pain308 69 #define FRAME_pain309 70 #define FRAME_pain310 71 #define FRAME_pain311 72 #define FRAME_pain312 73 #define FRAME_pain313 74 #define FRAME_pain314 75 #define FRAME_pain315 76 #define FRAME_pain316 77 #define FRAME_pain317 78 #define FRAME_pain318 79 #define FRAME_pain401 80 #define FRAME_pain402 81 #define FRAME_pain403 82 #define FRAME_pain404 83 #define FRAME_pain405 84 #define FRAME_pain406 85 #define FRAME_pain407 86 #define FRAME_pain408 87 #define FRAME_pain409 88 #define FRAME_pain410 89 #define FRAME_pain411 90 #define FRAME_pain412 91 #define FRAME_pain413 92 #define FRAME_pain414 93 #define FRAME_pain415 94 #define FRAME_pain416 95 #define FRAME_pain417 96 #define FRAME_run01 97 #define FRAME_run02 98 #define FRAME_run03 99 #define FRAME_run04 100 #define FRAME_run05 101 #define FRAME_run06 102 #define FRAME_run07 103 #define FRAME_run08 104 #define FRAME_run09 105 #define FRAME_run10 106 #define FRAME_run11 107 #define FRAME_run12 108 #define FRAME_runs01 109 #define FRAME_runs02 110 #define FRAME_runs03 111 #define FRAME_runs04 112 #define FRAME_runs05 113 #define FRAME_runs06 114 #define FRAME_runs07 115 #define FRAME_runs08 116 #define FRAME_runs09 117 #define FRAME_runs10 118 #define FRAME_runs11 119 #define FRAME_runs12 120 #define FRAME_runs13 121 #define FRAME_runs14 122 #define FRAME_runs15 123 #define FRAME_runs16 124 #define FRAME_runs17 125 #define FRAME_runs18 126 #define FRAME_runt01 127 #define FRAME_runt02 128 #define FRAME_runt03 129 #define FRAME_runt04 130 #define FRAME_runt05 131 #define FRAME_runt06 132 #define FRAME_runt07 133 #define FRAME_runt08 134 #define FRAME_runt09 135 #define FRAME_runt10 136 #define FRAME_runt11 137 #define FRAME_runt12 138 #define FRAME_runt13 139 #define FRAME_runt14 140 #define FRAME_runt15 141 #define FRAME_runt16 142 #define FRAME_runt17 143 #define FRAME_runt18 144 #define FRAME_runt19 145 #define FRAME_stand101 146 #define FRAME_stand102 147 #define FRAME_stand103 148 #define FRAME_stand104 149 #define FRAME_stand105 150 #define FRAME_stand106 151 #define FRAME_stand107 152 #define FRAME_stand108 153 #define FRAME_stand109 154 #define FRAME_stand110 155 #define FRAME_stand111 156 #define FRAME_stand112 157 #define FRAME_stand113 158 #define FRAME_stand114 159 #define FRAME_stand115 160 #define FRAME_stand116 161 #define FRAME_stand117 162 #define FRAME_stand118 163 #define FRAME_stand119 164 #define FRAME_stand120 165 #define FRAME_stand121 166 #define FRAME_stand122 167 #define FRAME_stand123 168 #define FRAME_stand124 169 #define FRAME_stand125 170 #define FRAME_stand126 171 #define FRAME_stand127 172 #define FRAME_stand128 173 #define FRAME_stand129 174 #define FRAME_stand130 175 #define FRAME_stand301 176 #define FRAME_stand302 177 #define FRAME_stand303 178 #define FRAME_stand304 179 #define FRAME_stand305 180 #define FRAME_stand306 181 #define FRAME_stand307 182 #define FRAME_stand308 183 #define FRAME_stand309 184 #define FRAME_stand310 185 #define FRAME_stand311 186 #define FRAME_stand312 187 #define FRAME_stand313 188 #define FRAME_stand314 189 #define FRAME_stand315 190 #define FRAME_stand316 191 #define FRAME_stand317 192 #define FRAME_stand318 193 #define FRAME_stand319 194 #define FRAME_stand320 195 #define FRAME_stand321 196 #define FRAME_stand322 197 #define FRAME_stand323 198 #define FRAME_stand324 199 #define FRAME_stand325 200 #define FRAME_stand326 201 #define FRAME_stand327 202 #define FRAME_stand328 203 #define FRAME_stand329 204 #define FRAME_stand330 205 #define FRAME_stand331 206 #define FRAME_stand332 207 #define FRAME_stand333 208 #define FRAME_stand334 209 #define FRAME_stand335 210 #define FRAME_stand336 211 #define FRAME_stand337 212 #define FRAME_stand338 213 #define FRAME_stand339 214 #define FRAME_walk101 215 #define FRAME_walk102 216 #define FRAME_walk103 217 #define FRAME_walk104 218 #define FRAME_walk105 219 #define FRAME_walk106 220 #define FRAME_walk107 221 #define FRAME_walk108 222 #define FRAME_walk109 223 #define FRAME_walk110 224 #define FRAME_walk111 225 #define FRAME_walk112 226 #define FRAME_walk113 227 #define FRAME_walk114 228 #define FRAME_walk115 229 #define FRAME_walk116 230 #define FRAME_walk117 231 #define FRAME_walk118 232 #define FRAME_walk119 233 #define FRAME_walk120 234 #define FRAME_walk121 235 #define FRAME_walk122 236 #define FRAME_walk123 237 #define FRAME_walk124 238 #define FRAME_walk125 239 #define FRAME_walk126 240 #define FRAME_walk127 241 #define FRAME_walk128 242 #define FRAME_walk129 243 #define FRAME_walk130 244 #define FRAME_walk131 245 #define FRAME_walk132 246 #define FRAME_walk133 247 #define FRAME_walk201 248 #define FRAME_walk202 249 #define FRAME_walk203 250 #define FRAME_walk204 251 #define FRAME_walk205 252 #define FRAME_walk206 253 #define FRAME_walk207 254 #define FRAME_walk208 255 #define FRAME_walk209 256 #define FRAME_walk210 257 #define FRAME_walk211 258 #define FRAME_walk212 259 #define FRAME_walk213 260 #define FRAME_walk214 261 #define FRAME_walk215 262 #define FRAME_walk216 263 #define FRAME_walk217 264 #define FRAME_walk218 265 #define FRAME_walk219 266 #define FRAME_walk220 267 #define FRAME_walk221 268 #define FRAME_walk222 269 #define FRAME_walk223 270 #define FRAME_walk224 271 #define FRAME_death101 272 #define FRAME_death102 273 #define FRAME_death103 274 #define FRAME_death104 275 #define FRAME_death105 276 #define FRAME_death106 277 #define FRAME_death107 278 #define FRAME_death108 279 #define FRAME_death109 280 #define FRAME_death110 281 #define FRAME_death111 282 #define FRAME_death112 283 #define FRAME_death113 284 #define FRAME_death114 285 #define FRAME_death115 286 #define FRAME_death116 287 #define FRAME_death117 288 #define FRAME_death118 289 #define FRAME_death119 290 #define FRAME_death120 291 #define FRAME_death121 292 #define FRAME_death122 293 #define FRAME_death123 294 #define FRAME_death124 295 #define FRAME_death125 296 #define FRAME_death126 297 #define FRAME_death127 298 #define FRAME_death128 299 #define FRAME_death129 300 #define FRAME_death130 301 #define FRAME_death131 302 #define FRAME_death132 303 #define FRAME_death133 304 #define FRAME_death134 305 #define FRAME_death135 306 #define FRAME_death136 307 #define FRAME_death201 308 #define FRAME_death202 309 #define FRAME_death203 310 #define FRAME_death204 311 #define FRAME_death205 312 #define FRAME_death206 313 #define FRAME_death207 314 #define FRAME_death208 315 #define FRAME_death209 316 #define FRAME_death210 317 #define FRAME_death211 318 #define FRAME_death212 319 #define FRAME_death213 320 #define FRAME_death214 321 #define FRAME_death215 322 #define FRAME_death216 323 #define FRAME_death217 324 #define FRAME_death218 325 #define FRAME_death219 326 #define FRAME_death220 327 #define FRAME_death221 328 #define FRAME_death222 329 #define FRAME_death223 330 #define FRAME_death224 331 #define FRAME_death225 332 #define FRAME_death226 333 #define FRAME_death227 334 #define FRAME_death228 335 #define FRAME_death229 336 #define FRAME_death230 337 #define FRAME_death231 338 #define FRAME_death232 339 #define FRAME_death233 340 #define FRAME_death234 341 #define FRAME_death235 342 #define FRAME_death301 343 #define FRAME_death302 344 #define FRAME_death303 345 #define FRAME_death304 346 #define FRAME_death305 347 #define FRAME_death306 348 #define FRAME_death307 349 #define FRAME_death308 350 #define FRAME_death309 351 #define FRAME_death310 352 #define FRAME_death311 353 #define FRAME_death312 354 #define FRAME_death313 355 #define FRAME_death314 356 #define FRAME_death315 357 #define FRAME_death316 358 #define FRAME_death317 359 #define FRAME_death318 360 #define FRAME_death319 361 #define FRAME_death320 362 #define FRAME_death321 363 #define FRAME_death322 364 #define FRAME_death323 365 #define FRAME_death324 366 #define FRAME_death325 367 #define FRAME_death326 368 #define FRAME_death327 369 #define FRAME_death328 370 #define FRAME_death329 371 #define FRAME_death330 372 #define FRAME_death331 373 #define FRAME_death332 374 #define FRAME_death333 375 #define FRAME_death334 376 #define FRAME_death335 377 #define FRAME_death336 378 #define FRAME_death337 379 #define FRAME_death338 380 #define FRAME_death339 381 #define FRAME_death340 382 #define FRAME_death341 383 #define FRAME_death342 384 #define FRAME_death343 385 #define FRAME_death344 386 #define FRAME_death345 387 #define FRAME_death401 388 #define FRAME_death402 389 #define FRAME_death403 390 #define FRAME_death404 391 #define FRAME_death405 392 #define FRAME_death406 393 #define FRAME_death407 394 #define FRAME_death408 395 #define FRAME_death409 396 #define FRAME_death410 397 #define FRAME_death411 398 #define FRAME_death412 399 #define FRAME_death413 400 #define FRAME_death414 401 #define FRAME_death415 402 #define FRAME_death416 403 #define FRAME_death417 404 #define FRAME_death418 405 #define FRAME_death419 406 #define FRAME_death420 407 #define FRAME_death421 408 #define FRAME_death422 409 #define FRAME_death423 410 #define FRAME_death424 411 #define FRAME_death425 412 #define FRAME_death426 413 #define FRAME_death427 414 #define FRAME_death428 415 #define FRAME_death429 416 #define FRAME_death430 417 #define FRAME_death431 418 #define FRAME_death432 419 #define FRAME_death433 420 #define FRAME_death434 421 #define FRAME_death435 422 #define FRAME_death436 423 #define FRAME_death437 424 #define FRAME_death438 425 #define FRAME_death439 426 #define FRAME_death440 427 #define FRAME_death441 428 #define FRAME_death442 429 #define FRAME_death443 430 #define FRAME_death444 431 #define FRAME_death445 432 #define FRAME_death446 433 #define FRAME_death447 434 #define FRAME_death448 435 #define FRAME_death449 436 #define FRAME_death450 437 #define FRAME_death451 438 #define FRAME_death452 439 #define FRAME_death453 440 #define FRAME_death501 441 #define FRAME_death502 442 #define FRAME_death503 443 #define FRAME_death504 444 #define FRAME_death505 445 #define FRAME_death506 446 #define FRAME_death507 447 #define FRAME_death508 448 #define FRAME_death509 449 #define FRAME_death510 450 #define FRAME_death511 451 #define FRAME_death512 452 #define FRAME_death513 453 #define FRAME_death514 454 #define FRAME_death515 455 #define FRAME_death516 456 #define FRAME_death517 457 #define FRAME_death518 458 #define FRAME_death519 459 #define FRAME_death520 460 #define FRAME_death521 461 #define FRAME_death522 462 #define FRAME_death523 463 #define FRAME_death524 464 #define FRAME_death601 465 #define FRAME_death602 466 #define FRAME_death603 467 #define FRAME_death604 468 #define FRAME_death605 469 #define FRAME_death606 470 #define FRAME_death607 471 #define FRAME_death608 472 #define FRAME_death609 473 #define FRAME_death610 474 #define MODEL_SCALE 1.200000 rogue-ROGUE_2_13/src/monster/stalker/000077500000000000000000000000001477320066100175335ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/stalker/stalker.c000066400000000000000000000647641477320066100213650ustar00rootroot00000000000000/* ======================================================================= * * Stalker. * * ======================================================================= */ #include "../../header/local.h" #include "stalker.h" #include static int sound_pain; static int sound_die; static int sound_sight; static int sound_punch_hit1; static int sound_punch_hit2; static int sound_idle; int stalker_do_pounce(edict_t *self, vec3_t dest); void stalker_stand(edict_t *self); void stalker_run(edict_t *self); void stalker_walk(edict_t *self); void stalker_jump(edict_t *self); void stalker_dodge_jump(edict_t *self); void stalker_swing_check_l(edict_t *self); void stalker_swing_check_r(edict_t *self); void stalker_swing_attack(edict_t *self); void stalker_jump_straightup(edict_t *self); void stalker_jump_wait_land(edict_t *self); void stalker_false_death(edict_t *self); void stalker_false_death_start(edict_t *self); qboolean stalker_ok_to_transition(edict_t *self); #define STALKER_ON_CEILING(ent) (ent->gravityVector[2] > 0 ? 1 : 0) #define PI 3.14159 #define RAD2DEG(x) (x * (float)180.0 / (float)PI) #define DEG2RAD(x) (x * (float)PI / (float)180.0) #define FAUX_GRAVITY 800.0 extern qboolean SV_PointCloseEnough(edict_t *ent, vec3_t goal, float dist); extern void drawbbox(edict_t *self); qboolean stalker_ok_to_transition(edict_t *self) { trace_t trace; vec3_t pt, start; float max_dist; float margin; float end_height; if (!self) { return false; } if (STALKER_ON_CEILING(self)) { max_dist = -384; margin = self->mins[2] - 8; } else { /* her stalkers are just better */ if (self->monsterinfo.aiflags & AI_SPAWNED_WIDOW) { max_dist = 256; } else { max_dist = 180; } margin = self->maxs[2] + 8; } VectorCopy(self->s.origin, pt); pt[2] += max_dist; trace = gi.trace(self->s.origin, self->mins, self->maxs, pt, self, MASK_MONSTERSOLID); if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world)) { if (STALKER_ON_CEILING(self)) { if (trace.plane.normal[2] < 0.9) { return false; } } else { if (trace.plane.normal[2] > -0.9) { return false; } } } end_height = trace.endpos[2]; /* check the four corners, tracing only to the endpoint of the center trace (vertically). */ pt[0] = self->absmin[0]; pt[1] = self->absmin[1]; pt[2] = trace.endpos[2] + margin; /* give a little margin of error to allow slight inclines */ VectorCopy(pt, start); start[2] = self->s.origin[2]; trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world)) { return false; } if (fabsf(end_height + margin - trace.endpos[2]) > 8) { return false; } pt[0] = self->absmax[0]; pt[1] = self->absmin[1]; VectorCopy(pt, start); start[2] = self->s.origin[2]; trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world)) { return false; } if (fabsf(end_height + margin - trace.endpos[2]) > 8) { return false; } pt[0] = self->absmax[0]; pt[1] = self->absmax[1]; VectorCopy(pt, start); start[2] = self->s.origin[2]; trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world)) { return false; } if (fabsf(end_height + margin - trace.endpos[2]) > 8) { return false; } pt[0] = self->absmin[0]; pt[1] = self->absmax[1]; VectorCopy(pt, start); start[2] = self->s.origin[2]; trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID); if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world)) { return false; } if (fabsf(end_height + margin - trace.endpos[2]) > 8) { return false; } return true; } void stalker_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0); } void stalker_idle_noise(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_idle, 0.5, ATTN_IDLE, 0); } static mframe_t stalker_frames_idle[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, stalker_idle_noise}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t stalker_move_idle = { FRAME_idle01, FRAME_idle21, stalker_frames_idle, stalker_stand }; static mframe_t stalker_frames_idle2[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t stalker_move_idle2 = { FRAME_idle201, FRAME_idle213, stalker_frames_idle2, stalker_stand }; void stalker_idle(edict_t *self) { if (!self) { return; } if (random() < 0.35) { self->monsterinfo.currentmove = &stalker_move_idle; } else { self->monsterinfo.currentmove = &stalker_move_idle2; } } static mframe_t stalker_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, stalker_idle_noise}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t stalker_move_stand = { FRAME_idle01, FRAME_idle21, stalker_frames_stand, stalker_stand }; void stalker_stand(edict_t *self) { if (!self) { return; } if (random() < 0.25) { self->monsterinfo.currentmove = &stalker_move_stand; } else { self->monsterinfo.currentmove = &stalker_move_idle2; } } static mframe_t stalker_frames_run[] = { {ai_run, 13, NULL}, {ai_run, 17, NULL}, {ai_run, 21, NULL}, {ai_run, 18, NULL} }; mmove_t stalker_move_run = { FRAME_run01, FRAME_run04, stalker_frames_run, NULL }; void stalker_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &stalker_move_stand; } else { self->monsterinfo.currentmove = &stalker_move_run; } } static mframe_t stalker_frames_walk[] = { {ai_walk, 4, NULL}, {ai_walk, 6, NULL}, {ai_walk, 8, NULL}, {ai_walk, 5, NULL}, {ai_walk, 4, NULL}, {ai_walk, 6, NULL}, {ai_walk, 8, NULL}, {ai_walk, 4, NULL} }; mmove_t stalker_move_walk = { FRAME_walk01, FRAME_walk08, stalker_frames_walk, stalker_walk }; void stalker_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &stalker_move_walk; } static mframe_t stalker_frames_reactivate[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t stalker_move_false_death_end = { FRAME_reactive01, FRAME_reactive04, stalker_frames_reactivate, stalker_run }; void stalker_reactivate(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_STAND_GROUND; self->monsterinfo.currentmove = &stalker_move_false_death_end; } void stalker_heal(edict_t *self) { if (!self) { return; } if (skill->value == SKILL_HARD) { self->health += 2; } else if (skill->value == SKILL_HARDPLUS) { self->health += 3; } else { self->health++; } if (self->health > (self->max_health / 2)) { self->s.skinnum = 0; } if (self->health >= self->max_health) { self->health = self->max_health; stalker_reactivate(self); } } static mframe_t stalker_frames_false_death[] = { {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal}, {ai_move, 0, stalker_heal} }; mmove_t stalker_move_false_death = { FRAME_twitch01, FRAME_twitch10, stalker_frames_false_death, stalker_false_death }; void stalker_false_death(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &stalker_move_false_death; } static mframe_t stalker_frames_false_death_start[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, }; mmove_t stalker_move_false_death_start = { FRAME_death01, FRAME_death09, stalker_frames_false_death_start, stalker_false_death }; void stalker_false_death_start(edict_t *self) { if (!self) { return; } self->s.angles[2] = 0; VectorSet(self->gravityVector, 0, 0, -1); self->monsterinfo.aiflags |= AI_STAND_GROUND; self->monsterinfo.currentmove = &stalker_move_false_death_start; } static mframe_t stalker_frames_pain[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t stalker_move_pain = { FRAME_pain01, FRAME_pain04, stalker_frames_pain, stalker_run }; void stalker_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->deadflag == DEAD_DEAD) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (self->groundentity == NULL) { return; } /* if we're reactivating or false dying, ignore the pain. */ if ((self->monsterinfo.currentmove == &stalker_move_false_death_end) || (self->monsterinfo.currentmove == &stalker_move_false_death_start)) { return; } if (self->monsterinfo.currentmove == &stalker_move_false_death) { stalker_reactivate(self); return; } if ((self->health > 0) && (self->health < (self->max_health / 4))) { if (random() < (0.2 * skill->value)) { if (!STALKER_ON_CEILING(self) || stalker_ok_to_transition(self)) { stalker_false_death_start(self); return; } } } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 3; if (damage > 10) /* don't react unless the damage was significant */ { /* stalker should dodge jump periodically to help avoid damage. */ if (self->groundentity && (random() < 0.5)) { stalker_dodge_jump(self); } else { self->monsterinfo.currentmove = &stalker_move_pain; } gi.sound(self, CHAN_WEAPON, sound_pain, 1, ATTN_NORM, 0); } } void stalker_shoot_attack(edict_t *self) { vec3_t offset, start, f, r, dir; vec3_t end; float time, dist; trace_t trace; if (!self) { return; } if (!has_valid_enemy(self)) { return; } if (self->groundentity && (random() < 0.33)) { VectorSubtract(self->enemy->s.origin, self->s.origin, dir); dist = VectorLength(dir); if ((dist > 256) || (random() < 0.5)) { stalker_do_pounce(self, self->enemy->s.origin); } else { stalker_jump_straightup(self); } } AngleVectors(self->s.angles, f, r, NULL); VectorSet(offset, 24, 0, 6); G_ProjectSource(self->s.origin, offset, f, r, start); VectorSubtract(self->enemy->s.origin, start, dir); if (random() < (0.20 + 0.1 * skill->value)) { dist = VectorLength(dir); time = dist / 1000; VectorMA(self->enemy->s.origin, time, self->enemy->velocity, end); VectorSubtract(end, start, dir); } else { VectorCopy(self->enemy->s.origin, end); } trace = gi.trace(start, vec3_origin, vec3_origin, end, self, MASK_SHOT); if ((trace.ent == self->enemy) || (trace.ent == world)) { monster_fire_blaster2(self, start, dir, 15, 800, MZ2_STALKER_BLASTER, EF_BLASTER); } } void stalker_shoot_attack2(edict_t *self) { if (!self) { return; } if (random() < (0.4 + (0.1 * (float)skill->value))) { stalker_shoot_attack(self); } } static mframe_t stalker_frames_shoot[] = { {ai_charge, 13, NULL}, {ai_charge, 17, stalker_shoot_attack}, {ai_charge, 21, NULL}, {ai_charge, 18, stalker_shoot_attack2} }; mmove_t stalker_move_shoot = { FRAME_run01, FRAME_run04, stalker_frames_shoot, stalker_run }; void stalker_attack_ranged(edict_t *self) { if (!self) { return; } if (!has_valid_enemy(self)) { return; } /* circle strafe stuff */ if (random() > (1.0 - (0.5 / (float)(skill->value)))) { self->monsterinfo.attack_state = AS_STRAIGHT; } else { if (random() <= 0.5) /* switch directions */ { self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; } self->monsterinfo.attack_state = AS_SLIDING; } self->monsterinfo.currentmove = &stalker_move_shoot; } void stalker_swing_attack(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, MELEE_DISTANCE, 0, 0); if (fire_hit(self, aim, (5 + (rand() % 5)), 50)) { if (self->s.frame < FRAME_attack08) { gi.sound(self, CHAN_WEAPON, sound_punch_hit2, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_WEAPON, sound_punch_hit1, 1, ATTN_NORM, 0); } } } static mframe_t stalker_frames_swing_l[] = { {ai_charge, 2, NULL}, {ai_charge, 4, NULL}, {ai_charge, 6, NULL}, {ai_charge, 10, NULL}, {ai_charge, 5, stalker_swing_attack}, {ai_charge, 5, NULL}, {ai_charge, 5, NULL}, {ai_charge, 5, NULL} /* stalker_swing_check_l */ }; mmove_t stalker_move_swing_l = { FRAME_attack01, FRAME_attack08, stalker_frames_swing_l, stalker_run }; static mframe_t stalker_frames_swing_r[] = { {ai_charge, 4, NULL}, {ai_charge, 6, NULL}, {ai_charge, 6, stalker_swing_attack}, {ai_charge, 10, NULL}, {ai_charge, 5, NULL} /* stalker_swing_check_r */ }; mmove_t stalker_move_swing_r = { FRAME_attack11, FRAME_attack15, stalker_frames_swing_r, stalker_run }; void stalker_attack_melee(edict_t *self) { if (!self) { return; } if (!has_valid_enemy(self)) { return; } if (random() < 0.5) { self->monsterinfo.currentmove = &stalker_move_swing_l; } else { self->monsterinfo.currentmove = &stalker_move_swing_r; } } void calcJumpAngle(vec3_t start, vec3_t end, float velocity, vec3_t angles) { float distV, distH; float one, cosU; float l, U; vec3_t dist; VectorSubtract(end, start, dist); distH = (float)sqrt(dist[0] * dist[0] + dist[1] * dist[1]); distV = dist[2]; if (distV < 0) { distV = 0 - distV; } if (distV) { l = (float)sqrt(distH * distH + distV * distV); U = (float)atan(distV / distH); if (dist[2] > 0) { U = (float)0.0 - U; } angles[2] = 0.0; cosU = (float)cos(U); one = l * FAUX_GRAVITY * (cosU * cosU); one = one / (velocity * velocity); one = one - (float)sin(U); angles[0] = (float)asin(one); if (_isnan(angles[0])) { angles[2] = 1.0; } angles[1] = (float)PI - angles[0]; if (_isnan(angles[1])) { angles[2] = 1.0; } angles[0] = RAD2DEG((angles[0] - U) / 2.0); angles[1] = RAD2DEG((angles[1] - U) / 2.0); } else { l = (float)sqrt(distH * distH + distV * distV); angles[2] = 0.0; one = l * FAUX_GRAVITY; one = one / (velocity * velocity); angles[0] = (float)asin(one); if (_isnan(angles[0])) { angles[2] = 1.0; } angles[1] = (float)PI - angles[0]; if (_isnan(angles[1])) { angles[2] = 1.0; } angles[0] = RAD2DEG((angles[0]) / 2.0); angles[1] = RAD2DEG((angles[1]) / 2.0); } } int stalker_check_lz(edict_t *self, edict_t *target, vec3_t dest) { vec3_t jumpLZ; if (!self || !target) { return 0; } if ((gi.pointcontents(dest) & MASK_WATER) || (target->waterlevel)) { return false; } if (!target->groundentity) { return false; } /* check under the player's four corners if they're not solid, bail. */ jumpLZ[0] = self->enemy->mins[0]; jumpLZ[1] = self->enemy->mins[1]; jumpLZ[2] = self->enemy->mins[2] - 0.25; if (!(gi.pointcontents(jumpLZ) & MASK_SOLID)) { return false; } jumpLZ[0] = self->enemy->maxs[0]; jumpLZ[1] = self->enemy->mins[1]; if (!(gi.pointcontents(jumpLZ) & MASK_SOLID)) { return false; } jumpLZ[0] = self->enemy->maxs[0]; jumpLZ[1] = self->enemy->maxs[1]; if (!(gi.pointcontents(jumpLZ) & MASK_SOLID)) { return false; } jumpLZ[0] = self->enemy->mins[0]; jumpLZ[1] = self->enemy->maxs[1]; if (!(gi.pointcontents(jumpLZ) & MASK_SOLID)) { return false; } return true; } int stalker_do_pounce(edict_t *self, vec3_t dest) { vec3_t forward, right; vec3_t dist; vec_t length; vec3_t jumpAngles; vec3_t jumpLZ; float velocity = 400.1; trace_t trace; int preferHighJump; if (!self) { return 0; } /* don't pounce when we're on the ceiling */ if (STALKER_ON_CEILING(self)) { return false; } if (!stalker_check_lz(self, self->enemy, dest)) { return false; } VectorSubtract(dest, self->s.origin, dist); /* make sure we're pointing in that direction 15deg margin of error. */ vectoangles2(dist, jumpAngles); if (fabsf(jumpAngles[YAW] - self->s.angles[YAW]) > 45) { return false; /* not facing the player... */ } self->ideal_yaw = jumpAngles[YAW]; M_ChangeYaw(self); length = VectorLength(dist); if (length > 450) { return false; /* can't jump that far... */ } VectorCopy(dest, jumpLZ); preferHighJump = 0; /* if we're having to jump up a distance, jump a little too high to compensate. */ if (dist[2] >= 32.0) { preferHighJump = 1; jumpLZ[2] += 32; } trace = gi.trace(self->s.origin, vec3_origin, vec3_origin, dest, self, MASK_MONSTERSOLID); if ((trace.fraction < 1) && (trace.ent != self->enemy)) { preferHighJump = 1; } /* find a valid angle/velocity combination */ while (velocity <= 800) { calcJumpAngle(self->s.origin, jumpLZ, velocity, jumpAngles); if ((!_isnan(jumpAngles[0])) || (!_isnan(jumpAngles[1]))) { break; } velocity += 200; } if (!preferHighJump && (!_isnan(jumpAngles[0]))) { AngleVectors(self->s.angles, forward, right, NULL); VectorNormalize(forward); VectorScale(forward, velocity * cos(DEG2RAD(jumpAngles[0])), self->velocity); self->velocity[2] = velocity * sin(DEG2RAD(jumpAngles[0])) + (0.5 * sv_gravity->value * FRAMETIME); return 1; } if (!_isnan(jumpAngles[1])) { AngleVectors(self->s.angles, forward, right, NULL); VectorNormalize(forward); VectorScale(forward, velocity * cos(DEG2RAD(jumpAngles[1])), self->velocity); self->velocity[2] = velocity * sin(DEG2RAD(jumpAngles[1])) + (0.5 * sv_gravity->value * FRAMETIME); return 1; } return 0; } void stalker_jump_straightup(edict_t *self) { if (!self) { return; } if (self->deadflag == DEAD_DEAD) { return; } if (STALKER_ON_CEILING(self)) { if (stalker_ok_to_transition(self)) { self->gravityVector[2] = -1; self->s.angles[2] += 180.0; if (self->s.angles[2] > 360.0) { self->s.angles[2] -= 360.0; } self->groundentity = NULL; } } else if (self->groundentity) /* make sure we're standing on SOMETHING... */ { self->velocity[0] += ((random() * 10) - 5); self->velocity[1] += ((random() * 10) - 5); self->velocity[2] += -400 * self->gravityVector[2]; if (stalker_ok_to_transition(self)) { self->gravityVector[2] = 1; self->s.angles[2] = 180.0; self->groundentity = NULL; } } } static mframe_t stalker_frames_jump_straightup[] = { {ai_move, 1, stalker_jump_straightup}, {ai_move, 1, stalker_jump_wait_land}, {ai_move, -1, NULL}, {ai_move, -1, NULL} }; mmove_t stalker_move_jump_straightup = { FRAME_jump04, FRAME_jump07, stalker_frames_jump_straightup, stalker_run }; void stalker_dodge_jump(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &stalker_move_jump_straightup; } static mframe_t stalker_frames_dodge_run[] = { {ai_run, 13, NULL}, {ai_run, 17, NULL}, {ai_run, 21, NULL}, {ai_run, 18, monster_done_dodge} }; mmove_t stalker_move_dodge_run = { FRAME_run01, FRAME_run04, stalker_frames_dodge_run, NULL }; void stalker_dodge(edict_t *self, edict_t *attacker, float eta, trace_t *tr /* unused */) { if (!self || !attacker) { return; } if (!self->groundentity || (self->health <= 0)) { return; } if (!self->enemy) { self->enemy = attacker; FoundTarget(self); return; } if ((eta < 0.1) || (eta > 5)) { return; } /* this will override the foundtarget call of stalker_run */ stalker_dodge_jump(self); } void stalker_jump_down(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 100, forward, self->velocity); VectorMA(self->velocity, 300, up, self->velocity); } void stalker_jump_up(edict_t *self) { vec3_t forward, up; if (!self) { return; } monster_jump_start(self); AngleVectors(self->s.angles, forward, NULL, up); VectorMA(self->velocity, 200, forward, self->velocity); VectorMA(self->velocity, 450, up, self->velocity); } void stalker_jump_wait_land(edict_t *self) { if (!self) { return; } if ((random() < (0.3 + (0.1 * (float)(skill->value)))) && (level.time >= self->monsterinfo.attack_finished)) { self->monsterinfo.attack_finished = level.time + 0.3; stalker_shoot_attack(self); } if (self->groundentity == NULL) { self->gravity = 1.3; self->monsterinfo.nextframe = self->s.frame; if (monster_jump_finished(self)) { self->gravity = 1; self->monsterinfo.nextframe = self->s.frame + 1; } } else { self->gravity = 1; self->monsterinfo.nextframe = self->s.frame + 1; } } static mframe_t stalker_frames_jump_up[] = { {ai_move, -8, NULL}, {ai_move, -8, NULL}, {ai_move, -8, NULL}, {ai_move, -8, NULL}, {ai_move, 0, stalker_jump_up}, {ai_move, 0, stalker_jump_wait_land}, {ai_move, 0, NULL} }; mmove_t stalker_move_jump_up = { FRAME_jump01, FRAME_jump07, stalker_frames_jump_up, stalker_run }; static mframe_t stalker_frames_jump_down[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, stalker_jump_down}, {ai_move, 0, stalker_jump_wait_land}, {ai_move, 0, NULL} }; mmove_t stalker_move_jump_down = { FRAME_jump01, FRAME_jump07, stalker_frames_jump_down, stalker_run }; void stalker_jump(edict_t *self) { if (!self) { return; } if (!self->enemy) { return; } if (self->enemy->absmin[2] >= self->absmin[2]) { self->monsterinfo.currentmove = &stalker_move_jump_up; } else { self->monsterinfo.currentmove = &stalker_move_jump_down; } } qboolean stalker_blocked(edict_t *self, float dist) { qboolean onCeiling; if (!self) { return false; } if (!has_valid_enemy(self)) { return false; } onCeiling = false; if (self->gravityVector[2] > 0) { onCeiling = true; } if (!onCeiling) { if (visible(self, self->enemy)) { stalker_do_pounce(self, self->enemy->s.origin); return true; } if (blocked_checkjump(self, dist, 256, 68)) { stalker_jump(self); return true; } if (blocked_checkplat(self, dist)) { return true; } } else { if (stalker_ok_to_transition(self)) { self->gravityVector[2] = -1; self->s.angles[2] += 180.0; if (self->s.angles[2] > 360.0) { self->s.angles[2] -= 360.0; } self->groundentity = NULL; return true; } } return false; } void stalker_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -28, -28, -18); VectorSet(self->maxs, 28, 28, -4); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t stalker_frames_death[] = { {ai_move, 0, NULL}, {ai_move, -5, NULL}, {ai_move, -10, NULL}, {ai_move, -20, NULL}, {ai_move, -10, NULL}, {ai_move, -10, NULL}, {ai_move, -5, NULL}, {ai_move, -5, NULL}, {ai_move, 0, NULL} }; mmove_t stalker_move_death = { FRAME_death01, FRAME_death09, stalker_frames_death, stalker_dead }; void stalker_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* dude bit it, make him fall! */ self->movetype = MOVETYPE_TOSS; self->s.angles[2] = 0; VectorSet(self->gravityVector, 0, 0, -1); /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &stalker_move_death; } /* * QUAKED monster_stalker (1 .5 0) (-28 -28 -18) (28 28 18) Ambush Trigger_Spawn Sight OnRoof * Spider Monster * * ONROOF - Monster starts sticking to the roof. */ void SP_monster_stalker(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain = gi.soundindex("stalker/pain.wav"); sound_die = gi.soundindex("stalker/death.wav"); sound_sight = gi.soundindex("stalker/sight.wav"); sound_punch_hit1 = gi.soundindex("stalker/melee1.wav"); sound_punch_hit2 = gi.soundindex("stalker/melee2.wav"); sound_idle = gi.soundindex("stalker/idle.wav"); gi.modelindex("models/proj/laser2/tris.md2"); self->s.modelindex = gi.modelindex("models/monsters/stalker/tris.md2"); VectorSet(self->mins, -28, -28, -18); VectorSet(self->maxs, 28, 28, 18); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->health = 250; self->gib_health = -50; self->mass = 250; self->viewheight = 15; self->pain = stalker_pain; self->die = stalker_die; self->monsterinfo.stand = stalker_stand; self->monsterinfo.walk = stalker_walk; self->monsterinfo.run = stalker_run; self->monsterinfo.attack = stalker_attack_ranged; self->monsterinfo.sight = stalker_sight; self->monsterinfo.idle = stalker_idle; self->monsterinfo.dodge = stalker_dodge; self->monsterinfo.blocked = stalker_blocked; self->monsterinfo.melee = stalker_attack_melee; gi.linkentity(self); self->monsterinfo.currentmove = &stalker_move_stand; self->monsterinfo.scale = MODEL_SCALE; self->monsterinfo.aiflags |= AI_WALK_WALLS; if (self->spawnflags & 8) { self->s.angles[2] = 180; self->gravityVector[2] = 1; } walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/stalker/stalker.h000066400000000000000000000064511477320066100213570ustar00rootroot00000000000000/* ======================================================================= * * Stalker animations. * * ======================================================================= */ #define FRAME_idle01 0 #define FRAME_idle02 1 #define FRAME_idle03 2 #define FRAME_idle04 3 #define FRAME_idle05 4 #define FRAME_idle06 5 #define FRAME_idle07 6 #define FRAME_idle08 7 #define FRAME_idle09 8 #define FRAME_idle10 9 #define FRAME_idle11 10 #define FRAME_idle12 11 #define FRAME_idle13 12 #define FRAME_idle14 13 #define FRAME_idle15 14 #define FRAME_idle16 15 #define FRAME_idle17 16 #define FRAME_idle18 17 #define FRAME_idle19 18 #define FRAME_idle20 19 #define FRAME_idle21 20 #define FRAME_idle201 21 #define FRAME_idle202 22 #define FRAME_idle203 23 #define FRAME_idle204 24 #define FRAME_idle205 25 #define FRAME_idle206 26 #define FRAME_idle207 27 #define FRAME_idle208 28 #define FRAME_idle209 29 #define FRAME_idle210 30 #define FRAME_idle211 31 #define FRAME_idle212 32 #define FRAME_idle213 33 #define FRAME_walk01 34 #define FRAME_walk02 35 #define FRAME_walk03 36 #define FRAME_walk04 37 #define FRAME_walk05 38 #define FRAME_walk06 39 #define FRAME_walk07 40 #define FRAME_walk08 41 #define FRAME_jump01 42 #define FRAME_jump02 43 #define FRAME_jump03 44 #define FRAME_jump04 45 #define FRAME_jump05 46 #define FRAME_jump06 47 #define FRAME_jump07 48 #define FRAME_run01 49 #define FRAME_run02 50 #define FRAME_run03 51 #define FRAME_run04 52 #define FRAME_attack01 53 #define FRAME_attack02 54 #define FRAME_attack03 55 #define FRAME_attack04 56 #define FRAME_attack05 57 #define FRAME_attack06 58 #define FRAME_attack07 59 #define FRAME_attack08 60 #define FRAME_attack11 61 #define FRAME_attack12 62 #define FRAME_attack13 63 #define FRAME_attack14 64 #define FRAME_attack15 65 #define FRAME_pain01 66 #define FRAME_pain02 67 #define FRAME_pain03 68 #define FRAME_pain04 69 #define FRAME_death01 70 #define FRAME_death02 71 #define FRAME_death03 72 #define FRAME_death04 73 #define FRAME_death05 74 #define FRAME_death06 75 #define FRAME_death07 76 #define FRAME_death08 77 #define FRAME_death09 78 #define FRAME_twitch01 79 #define FRAME_twitch02 80 #define FRAME_twitch03 81 #define FRAME_twitch04 82 #define FRAME_twitch05 83 #define FRAME_twitch06 84 #define FRAME_twitch07 85 #define FRAME_twitch08 86 #define FRAME_twitch09 87 #define FRAME_twitch10 88 #define FRAME_reactive01 89 #define FRAME_reactive02 90 #define FRAME_reactive03 91 #define FRAME_reactive04 92 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/supertank/000077500000000000000000000000001477320066100201025ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/supertank/supertank.c000066400000000000000000000414351477320066100222710ustar00rootroot00000000000000/* ======================================================================= * * Supertank aka "Boss1". * * ======================================================================= */ #include "../../header/local.h" #include "supertank.h" qboolean visible(edict_t *self, edict_t *other); static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_death; static int sound_search1; static int sound_search2; static int tread_sound; void BossExplode(edict_t *self); void supertank_dead(edict_t *self); void supertankRocket(edict_t *self); void supertankMachineGun(edict_t *self); void supertank_reattack1(edict_t *self); void TreadSound(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, tread_sound, 1, ATTN_NORM, 0); } void supertank_search(edict_t *self) { if (!self) { return; } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); } } static mframe_t supertank_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t supertank_move_stand = { FRAME_stand_1, FRAME_stand_60, supertank_frames_stand, NULL }; void supertank_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &supertank_move_stand; } static mframe_t supertank_frames_run[] = { {ai_run, 12, TreadSound}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL}, {ai_run, 12, NULL} }; mmove_t supertank_move_run = { FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_run, NULL }; static mframe_t supertank_frames_forward[] = { {ai_walk, 4, TreadSound}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, NULL} }; mmove_t supertank_move_forward = { FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_forward, NULL }; void supertank_forward(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &supertank_move_forward; } void supertank_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &supertank_move_forward; } void supertank_run(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &supertank_move_stand; } else { self->monsterinfo.currentmove = &supertank_move_run; } } static mframe_t supertank_frames_turn_right[] = { {ai_move, 0, TreadSound}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_turn_right = { FRAME_right_1, FRAME_right_18, supertank_frames_turn_right, supertank_run }; static mframe_t supertank_frames_turn_left[] = { {ai_move, 0, TreadSound}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_turn_left = { FRAME_left_1, FRAME_left_18, supertank_frames_turn_left, supertank_run }; static mframe_t supertank_frames_pain3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_pain3 = { FRAME_pain3_9, FRAME_pain3_12, supertank_frames_pain3, supertank_run }; static mframe_t supertank_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_pain2 = { FRAME_pain2_5, FRAME_pain2_8, supertank_frames_pain2, supertank_run }; static mframe_t supertank_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_pain1 = { FRAME_pain1_1, FRAME_pain1_4, supertank_frames_pain1, supertank_run }; static mframe_t supertank_frames_death1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, BossExplode} }; mmove_t supertank_move_death = { FRAME_death_1, FRAME_death_24, supertank_frames_death1, supertank_dead }; static mframe_t supertank_frames_backward[] = { {ai_walk, 0, TreadSound}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL}, {ai_walk, 0, NULL} }; mmove_t supertank_move_backward = { FRAME_backwd_1, FRAME_backwd_18, supertank_frames_backward, NULL }; static mframe_t supertank_frames_attack4[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_attack4 = { FRAME_attak4_1, FRAME_attak4_6, supertank_frames_attack4, supertank_run }; static mframe_t supertank_frames_attack3[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_attack3 = { FRAME_attak3_1, FRAME_attak3_27, supertank_frames_attack3, supertank_run }; static mframe_t supertank_frames_attack2[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, supertankRocket}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, supertankRocket}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, supertankRocket}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_attack2 = { FRAME_attak2_1, FRAME_attak2_27, supertank_frames_attack2, supertank_run }; static mframe_t supertank_frames_attack1[] = { {ai_charge, 0, supertankMachineGun}, {ai_charge, 0, supertankMachineGun}, {ai_charge, 0, supertankMachineGun}, {ai_charge, 0, supertankMachineGun}, {ai_charge, 0, supertankMachineGun}, {ai_charge, 0, supertankMachineGun}, }; mmove_t supertank_move_attack1 = { FRAME_attak1_1, FRAME_attak1_6, supertank_frames_attack1, supertank_reattack1 }; static mframe_t supertank_frames_end_attack1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t supertank_move_end_attack1 = { FRAME_attak1_7, FRAME_attak1_20, supertank_frames_end_attack1, supertank_run }; void supertank_reattack1(edict_t *self) { if (!self) { return; } if (visible(self, self->enemy)) { if (random() < 0.9) { self->monsterinfo.currentmove = &supertank_move_attack1; } else { self->monsterinfo.currentmove = &supertank_move_end_attack1; } } else { self->monsterinfo.currentmove = &supertank_move_end_attack1; } } void supertank_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (level.time < self->pain_debounce_time) { return; } /* Lessen the chance of him going into his pain frames */ if (damage <= 25) { if (random() < 0.2) { return; } } /* Don't go into pain if he's firing his rockets */ if (skill->value >= SKILL_HARD) { if ((self->s.frame >= FRAME_attak2_1) && (self->s.frame <= FRAME_attak2_14)) { return; } } self->pain_debounce_time = level.time + 3; if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (damage <= 10) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &supertank_move_pain1; } else if (damage <= 25) { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &supertank_move_pain2; } else { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &supertank_move_pain3; } } void supertankRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; int flash_number; if (!self->enemy || !self->enemy->inuse) { return; } if (self->s.frame == FRAME_attak2_8) { flash_number = MZ2_SUPERTANK_ROCKET_1; } else if (self->s.frame == FRAME_attak2_11) { flash_number = MZ2_SUPERTANK_ROCKET_2; } else { flash_number = MZ2_SUPERTANK_ROCKET_3; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, dir); VectorNormalize(dir); monster_fire_rocket(self, start, dir, 50, 500, flash_number); } void supertankMachineGun(edict_t *self) { vec3_t dir; vec3_t vec; vec3_t start; vec3_t forward, right; int flash_number; if (!self) { return; } if (!self->enemy || !self->enemy->inuse) { return; } flash_number = MZ2_SUPERTANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak1_1); dir[0] = 0; dir[1] = self->s.angles[1]; dir[2] = 0; AngleVectors(dir, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); VectorCopy(self->enemy->s.origin, vec); VectorMA(vec, 0, self->enemy->velocity, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, forward); VectorNormalize(forward); monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); } void supertank_attack(edict_t *self) { vec3_t vec; float range; if (!self) { return; } VectorSubtract(self->enemy->s.origin, self->s.origin, vec); range = VectorLength(vec); if (range <= 160) { self->monsterinfo.currentmove = &supertank_move_attack1; } else { /* fire rockets more often at distance */ if (random() < 0.3) { self->monsterinfo.currentmove = &supertank_move_attack1; } else { self->monsterinfo.currentmove = &supertank_move_attack2; } } } void supertank_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -60, -60, 0); VectorSet(self->maxs, 60, 60, 72); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void BossExplode(edict_t *self) { vec3_t org; int n; if (!self) { return; } self->think = BossExplode; VectorCopy(self->s.origin, org); org[2] += 24 + (rand() & 15); switch (self->count++) { case 0: org[0] -= 24; org[1] -= 24; break; case 1: org[0] += 24; org[1] += 24; break; case 2: org[0] += 24; org[1] -= 24; break; case 3: org[0] -= 24; org[1] += 24; break; case 4: org[0] -= 48; org[1] -= 48; break; case 5: org[0] += 48; org[1] += 48; break; case 6: org[0] -= 48; org[1] += 48; break; case 7: org[0] += 48; org[1] -= 48; break; case 8: self->s.sound = 0; for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", 500, GIB_ORGANIC); } for (n = 0; n < 8; n++) { ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", 500, GIB_METALLIC); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", 500, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/gear/tris.md2", 500, GIB_METALLIC); self->deadflag = DEAD_DEAD; return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(org); gi.multicast(self->s.origin, MULTICAST_PVS); self->nextthink = level.time + 0.1; } void supertank_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; self->monsterinfo.currentmove = &supertank_move_death; } qboolean supertank_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } /* * QUAKED monster_supertank (1 .5 0) (-64 -64 0) (64 64 72) Ambush Trigger_Spawn Sight */ void SP_monster_supertank(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("bosstank/btkpain1.wav"); sound_pain2 = gi.soundindex("bosstank/btkpain2.wav"); sound_pain3 = gi.soundindex("bosstank/btkpain3.wav"); sound_death = gi.soundindex("bosstank/btkdeth1.wav"); sound_search1 = gi.soundindex("bosstank/btkunqv1.wav"); sound_search2 = gi.soundindex("bosstank/btkunqv2.wav"); tread_sound = gi.soundindex("bosstank/btkengn1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/boss1/tris.md2"); VectorSet(self->mins, -64, -64, 0); VectorSet(self->maxs, 64, 64, 112); self->health = 1500; self->gib_health = -500; self->mass = 800; self->pain = supertank_pain; self->die = supertank_die; self->monsterinfo.stand = supertank_stand; self->monsterinfo.walk = supertank_walk; self->monsterinfo.run = supertank_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = supertank_attack; self->monsterinfo.search = supertank_search; self->monsterinfo.melee = NULL; self->monsterinfo.sight = NULL; self->monsterinfo.blocked = supertank_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &supertank_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; } rogue-ROGUE_2_13/src/monster/supertank/supertank.h000066400000000000000000000214641477320066100222760ustar00rootroot00000000000000/* ======================================================================= * * Supertank aka "Boss1" animations. * * ======================================================================= */ #define FRAME_attak1_1 0 #define FRAME_attak1_2 1 #define FRAME_attak1_3 2 #define FRAME_attak1_4 3 #define FRAME_attak1_5 4 #define FRAME_attak1_6 5 #define FRAME_attak1_7 6 #define FRAME_attak1_8 7 #define FRAME_attak1_9 8 #define FRAME_attak1_10 9 #define FRAME_attak1_11 10 #define FRAME_attak1_12 11 #define FRAME_attak1_13 12 #define FRAME_attak1_14 13 #define FRAME_attak1_15 14 #define FRAME_attak1_16 15 #define FRAME_attak1_17 16 #define FRAME_attak1_18 17 #define FRAME_attak1_19 18 #define FRAME_attak1_20 19 #define FRAME_attak2_1 20 #define FRAME_attak2_2 21 #define FRAME_attak2_3 22 #define FRAME_attak2_4 23 #define FRAME_attak2_5 24 #define FRAME_attak2_6 25 #define FRAME_attak2_7 26 #define FRAME_attak2_8 27 #define FRAME_attak2_9 28 #define FRAME_attak2_10 29 #define FRAME_attak2_11 30 #define FRAME_attak2_12 31 #define FRAME_attak2_13 32 #define FRAME_attak2_14 33 #define FRAME_attak2_15 34 #define FRAME_attak2_16 35 #define FRAME_attak2_17 36 #define FRAME_attak2_18 37 #define FRAME_attak2_19 38 #define FRAME_attak2_20 39 #define FRAME_attak2_21 40 #define FRAME_attak2_22 41 #define FRAME_attak2_23 42 #define FRAME_attak2_24 43 #define FRAME_attak2_25 44 #define FRAME_attak2_26 45 #define FRAME_attak2_27 46 #define FRAME_attak3_1 47 #define FRAME_attak3_2 48 #define FRAME_attak3_3 49 #define FRAME_attak3_4 50 #define FRAME_attak3_5 51 #define FRAME_attak3_6 52 #define FRAME_attak3_7 53 #define FRAME_attak3_8 54 #define FRAME_attak3_9 55 #define FRAME_attak3_10 56 #define FRAME_attak3_11 57 #define FRAME_attak3_12 58 #define FRAME_attak3_13 59 #define FRAME_attak3_14 60 #define FRAME_attak3_15 61 #define FRAME_attak3_16 62 #define FRAME_attak3_17 63 #define FRAME_attak3_18 64 #define FRAME_attak3_19 65 #define FRAME_attak3_20 66 #define FRAME_attak3_21 67 #define FRAME_attak3_22 68 #define FRAME_attak3_23 69 #define FRAME_attak3_24 70 #define FRAME_attak3_25 71 #define FRAME_attak3_26 72 #define FRAME_attak3_27 73 #define FRAME_attak4_1 74 #define FRAME_attak4_2 75 #define FRAME_attak4_3 76 #define FRAME_attak4_4 77 #define FRAME_attak4_5 78 #define FRAME_attak4_6 79 #define FRAME_backwd_1 80 #define FRAME_backwd_2 81 #define FRAME_backwd_3 82 #define FRAME_backwd_4 83 #define FRAME_backwd_5 84 #define FRAME_backwd_6 85 #define FRAME_backwd_7 86 #define FRAME_backwd_8 87 #define FRAME_backwd_9 88 #define FRAME_backwd_10 89 #define FRAME_backwd_11 90 #define FRAME_backwd_12 91 #define FRAME_backwd_13 92 #define FRAME_backwd_14 93 #define FRAME_backwd_15 94 #define FRAME_backwd_16 95 #define FRAME_backwd_17 96 #define FRAME_backwd_18 97 #define FRAME_death_1 98 #define FRAME_death_2 99 #define FRAME_death_3 100 #define FRAME_death_4 101 #define FRAME_death_5 102 #define FRAME_death_6 103 #define FRAME_death_7 104 #define FRAME_death_8 105 #define FRAME_death_9 106 #define FRAME_death_10 107 #define FRAME_death_11 108 #define FRAME_death_12 109 #define FRAME_death_13 110 #define FRAME_death_14 111 #define FRAME_death_15 112 #define FRAME_death_16 113 #define FRAME_death_17 114 #define FRAME_death_18 115 #define FRAME_death_19 116 #define FRAME_death_20 117 #define FRAME_death_21 118 #define FRAME_death_22 119 #define FRAME_death_23 120 #define FRAME_death_24 121 #define FRAME_death_31 122 #define FRAME_death_32 123 #define FRAME_death_33 124 #define FRAME_death_45 125 #define FRAME_death_46 126 #define FRAME_death_47 127 #define FRAME_forwrd_1 128 #define FRAME_forwrd_2 129 #define FRAME_forwrd_3 130 #define FRAME_forwrd_4 131 #define FRAME_forwrd_5 132 #define FRAME_forwrd_6 133 #define FRAME_forwrd_7 134 #define FRAME_forwrd_8 135 #define FRAME_forwrd_9 136 #define FRAME_forwrd_10 137 #define FRAME_forwrd_11 138 #define FRAME_forwrd_12 139 #define FRAME_forwrd_13 140 #define FRAME_forwrd_14 141 #define FRAME_forwrd_15 142 #define FRAME_forwrd_16 143 #define FRAME_forwrd_17 144 #define FRAME_forwrd_18 145 #define FRAME_left_1 146 #define FRAME_left_2 147 #define FRAME_left_3 148 #define FRAME_left_4 149 #define FRAME_left_5 150 #define FRAME_left_6 151 #define FRAME_left_7 152 #define FRAME_left_8 153 #define FRAME_left_9 154 #define FRAME_left_10 155 #define FRAME_left_11 156 #define FRAME_left_12 157 #define FRAME_left_13 158 #define FRAME_left_14 159 #define FRAME_left_15 160 #define FRAME_left_16 161 #define FRAME_left_17 162 #define FRAME_left_18 163 #define FRAME_pain1_1 164 #define FRAME_pain1_2 165 #define FRAME_pain1_3 166 #define FRAME_pain1_4 167 #define FRAME_pain2_5 168 #define FRAME_pain2_6 169 #define FRAME_pain2_7 170 #define FRAME_pain2_8 171 #define FRAME_pain3_9 172 #define FRAME_pain3_10 173 #define FRAME_pain3_11 174 #define FRAME_pain3_12 175 #define FRAME_right_1 176 #define FRAME_right_2 177 #define FRAME_right_3 178 #define FRAME_right_4 179 #define FRAME_right_5 180 #define FRAME_right_6 181 #define FRAME_right_7 182 #define FRAME_right_8 183 #define FRAME_right_9 184 #define FRAME_right_10 185 #define FRAME_right_11 186 #define FRAME_right_12 187 #define FRAME_right_13 188 #define FRAME_right_14 189 #define FRAME_right_15 190 #define FRAME_right_16 191 #define FRAME_right_17 192 #define FRAME_right_18 193 #define FRAME_stand_1 194 #define FRAME_stand_2 195 #define FRAME_stand_3 196 #define FRAME_stand_4 197 #define FRAME_stand_5 198 #define FRAME_stand_6 199 #define FRAME_stand_7 200 #define FRAME_stand_8 201 #define FRAME_stand_9 202 #define FRAME_stand_10 203 #define FRAME_stand_11 204 #define FRAME_stand_12 205 #define FRAME_stand_13 206 #define FRAME_stand_14 207 #define FRAME_stand_15 208 #define FRAME_stand_16 209 #define FRAME_stand_17 210 #define FRAME_stand_18 211 #define FRAME_stand_19 212 #define FRAME_stand_20 213 #define FRAME_stand_21 214 #define FRAME_stand_22 215 #define FRAME_stand_23 216 #define FRAME_stand_24 217 #define FRAME_stand_25 218 #define FRAME_stand_26 219 #define FRAME_stand_27 220 #define FRAME_stand_28 221 #define FRAME_stand_29 222 #define FRAME_stand_30 223 #define FRAME_stand_31 224 #define FRAME_stand_32 225 #define FRAME_stand_33 226 #define FRAME_stand_34 227 #define FRAME_stand_35 228 #define FRAME_stand_36 229 #define FRAME_stand_37 230 #define FRAME_stand_38 231 #define FRAME_stand_39 232 #define FRAME_stand_40 233 #define FRAME_stand_41 234 #define FRAME_stand_42 235 #define FRAME_stand_43 236 #define FRAME_stand_44 237 #define FRAME_stand_45 238 #define FRAME_stand_46 239 #define FRAME_stand_47 240 #define FRAME_stand_48 241 #define FRAME_stand_49 242 #define FRAME_stand_50 243 #define FRAME_stand_51 244 #define FRAME_stand_52 245 #define FRAME_stand_53 246 #define FRAME_stand_54 247 #define FRAME_stand_55 248 #define FRAME_stand_56 249 #define FRAME_stand_57 250 #define FRAME_stand_58 251 #define FRAME_stand_59 252 #define FRAME_stand_60 253 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/tank/000077500000000000000000000000001477320066100170235ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/tank/tank.c000066400000000000000000000563561477320066100201430ustar00rootroot00000000000000/* ======================================================================= * * Tank and Tank Commander. * * ======================================================================= */ #include "../../header/local.h" #include "tank.h" void tank_refire_rocket(edict_t *self); void tank_doattack_rocket(edict_t *self); void tank_reattack_blaster(edict_t *self); void tank_walk(edict_t *self); void tank_run(edict_t *self); static int sound_thud; static int sound_pain; static int sound_idle; static int sound_die; static int sound_step; static int sound_sight; static int sound_windup; static int sound_strike; void tank_sight(edict_t *self, edict_t *other) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); } void tank_footstep(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); } void tank_thud(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0); } void tank_windup(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0); } void tank_idle(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); } static mframe_t tank_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t tank_move_stand = { FRAME_stand01, FRAME_stand30, tank_frames_stand, NULL }; void tank_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &tank_move_stand; } static mframe_t tank_frames_start_walk[] = { {ai_walk, 0, NULL}, {ai_walk, 6, NULL}, {ai_walk, 6, NULL}, {ai_walk, 11, tank_footstep} }; mmove_t tank_move_start_walk = { FRAME_walk01, FRAME_walk04, tank_frames_start_walk, tank_walk }; static mframe_t tank_frames_walk[] = { {ai_walk, 4, NULL}, {ai_walk, 5, NULL}, {ai_walk, 3, NULL}, {ai_walk, 2, NULL}, {ai_walk, 5, NULL}, {ai_walk, 5, NULL}, {ai_walk, 4, NULL}, {ai_walk, 4, tank_footstep}, {ai_walk, 3, NULL}, {ai_walk, 5, NULL}, {ai_walk, 4, NULL}, {ai_walk, 5, NULL}, {ai_walk, 7, NULL}, {ai_walk, 7, NULL}, {ai_walk, 6, NULL}, {ai_walk, 6, tank_footstep} }; mmove_t tank_move_walk = { FRAME_walk05, FRAME_walk20, tank_frames_walk, NULL }; static mframe_t tank_frames_stop_walk[] = { {ai_walk, 3, NULL}, {ai_walk, 3, NULL}, {ai_walk, 2, NULL}, {ai_walk, 2, NULL}, {ai_walk, 4, tank_footstep} }; mmove_t tank_move_stop_walk = { FRAME_walk21, FRAME_walk25, tank_frames_stop_walk, tank_stand }; void tank_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &tank_move_walk; } static mframe_t tank_frames_start_run[] = { {ai_run, 0, NULL}, {ai_run, 6, NULL}, {ai_run, 6, NULL}, {ai_run, 11, tank_footstep} }; mmove_t tank_move_start_run = { FRAME_walk01, FRAME_walk04, tank_frames_start_run, tank_run }; static mframe_t tank_frames_run[] = { {ai_run, 4, NULL}, {ai_run, 5, NULL}, {ai_run, 3, NULL}, {ai_run, 2, NULL}, {ai_run, 5, NULL}, {ai_run, 5, NULL}, {ai_run, 4, NULL}, {ai_run, 4, tank_footstep}, {ai_run, 3, NULL}, {ai_run, 5, NULL}, {ai_run, 4, NULL}, {ai_run, 5, NULL}, {ai_run, 7, NULL}, {ai_run, 7, NULL}, {ai_run, 6, NULL}, {ai_run, 6, tank_footstep} }; mmove_t tank_move_run = { FRAME_walk05, FRAME_walk20, tank_frames_run, NULL }; static mframe_t tank_frames_stop_run[] = { {ai_run, 3, NULL}, {ai_run, 3, NULL}, {ai_run, 2, NULL}, {ai_run, 2, NULL}, {ai_run, 4, tank_footstep} }; mmove_t tank_move_stop_run = { FRAME_walk21, FRAME_walk25, tank_frames_stop_run, tank_walk }; void tank_run(edict_t *self) { if (!self) { return; } if (self->enemy && self->enemy->client) { self->monsterinfo.aiflags |= AI_BRUTAL; } else { self->monsterinfo.aiflags &= ~AI_BRUTAL; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &tank_move_stand; return; } if ((self->monsterinfo.currentmove == &tank_move_walk) || (self->monsterinfo.currentmove == &tank_move_start_run)) { self->monsterinfo.currentmove = &tank_move_run; } else { self->monsterinfo.currentmove = &tank_move_start_run; } } static mframe_t tank_frames_pain1[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t tank_move_pain1 = { FRAME_pain101, FRAME_pain104, tank_frames_pain1, tank_run }; static mframe_t tank_frames_pain2[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t tank_move_pain2 = { FRAME_pain201, FRAME_pain205, tank_frames_pain2, tank_run }; static mframe_t tank_frames_pain3[] = { {ai_move, -7, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 3, NULL}, {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, tank_footstep} }; mmove_t tank_move_pain3 = { FRAME_pain301, FRAME_pain316, tank_frames_pain3, tank_run }; void tank_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; } if (damage <= 10) { return; } if (level.time < self->pain_debounce_time) { return; } if (damage <= 30) { if (random() > 0.2) { return; } } /* If hard or nightmare, don't go into pain while attacking */ if (skill->value >= SKILL_HARD) { if ((self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330)) { return; } if ((self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116)) { return; } } self->pain_debounce_time = level.time + 3; gi.sound(self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; if (damage <= 30) { self->monsterinfo.currentmove = &tank_move_pain1; } else if (damage <= 60) { self->monsterinfo.currentmove = &tank_move_pain2; } else { self->monsterinfo.currentmove = &tank_move_pain3; } } void TankBlaster(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t end; vec3_t dir; int flash_number; if (!self) { return; } if (self->s.frame == FRAME_attak110) { flash_number = MZ2_TANK_BLASTER_1; } else if (self->s.frame == FRAME_attak113) { flash_number = MZ2_TANK_BLASTER_2; } else { flash_number = MZ2_TANK_BLASTER_3; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); VectorCopy(self->enemy->s.origin, end); end[2] += self->enemy->viewheight; VectorSubtract(end, start, dir); monster_fire_blaster(self, start, dir, 30, 800, flash_number, EF_BLASTER); } void TankStrike(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0); } void TankRocket(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t dir; vec3_t vec; int flash_number; trace_t trace; int rocketSpeed; vec3_t target; qboolean blindfire = false; if (!self || !self->enemy || !self->enemy->inuse) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { blindfire = true; } else { blindfire = false; } if (self->s.frame == FRAME_attak324) { flash_number = MZ2_TANK_ROCKET_1; } else if (self->s.frame == FRAME_attak327) { flash_number = MZ2_TANK_ROCKET_2; } else { flash_number = MZ2_TANK_ROCKET_3; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); rocketSpeed = 500 + (100 * skill->value); if (blindfire) { VectorCopy (self->monsterinfo.blind_fire_target, target); } else { VectorCopy (self->enemy->s.origin, target); } if (blindfire) { VectorCopy(target, vec); VectorSubtract(vec, start, dir); } else if(random() < 0.66 || (start[2] < self->enemy->absmin[2])) { // Don't shoot at the feed if enemy is above. VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, dir); } else { // Shoot at the feed. VectorCopy(self->enemy->s.origin, vec); vec[2] = self->enemy->absmin[2]; VectorSubtract(vec, start, dir); } // Lead target: 20, 35, 50, 65 chance of leading. if ((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15))))) { float dist; float time; dist = VectorLength(dir); time = dist/rocketSpeed; VectorMA(vec, time, self->enemy->velocity, vec); VectorSubtract(vec, start, dir); } VectorNormalize(dir); if (blindfire) { /* blindfire has different fail criteria for the trace */ if (!blind_rocket_ok(self, start, right, target, 20.0f, dir)) { return; } } else { trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); if (((trace.ent != self->enemy) && (trace.ent != world)) || ((trace.fraction <= 0.5f) && !trace.ent->client)) { return; } } monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number); } void TankMachineGun(edict_t *self) { vec3_t dir; vec3_t vec; vec3_t start; vec3_t forward, right; int flash_number; if (!self || !self->enemy || !self->enemy->inuse) { return; } flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406); AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start); if (self->enemy) { VectorCopy(self->enemy->s.origin, vec); vec[2] += self->enemy->viewheight; VectorSubtract(vec, start, vec); vectoangles(vec, vec); dir[0] = vec[0]; } else { dir[0] = 0; } if (self->s.frame <= FRAME_attak415) { dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411); } else { dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419); } dir[2] = 0; AngleVectors(dir, forward, NULL, NULL); monster_fire_bullet(self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); } static mframe_t tank_frames_attack_blast[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, -1, NULL}, {ai_charge, -2, NULL}, {ai_charge, -1, NULL}, {ai_charge, -1, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankBlaster}, /* 10 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankBlaster}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankBlaster} /* 16 */ }; mmove_t tank_move_attack_blast = { FRAME_attak101, FRAME_attak116, tank_frames_attack_blast, tank_reattack_blaster }; static mframe_t tank_frames_reattack_blast[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankBlaster}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankBlaster} /* 16 */ }; mmove_t tank_move_reattack_blast = { FRAME_attak111, FRAME_attak116, tank_frames_reattack_blast, tank_reattack_blaster }; static mframe_t tank_frames_attack_post_blast[] = { {ai_move, 0, NULL}, /* 17 */ {ai_move, 0, NULL}, {ai_move, 2, NULL}, {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, -2, tank_footstep} /* 22 */ }; mmove_t tank_move_attack_post_blast = { FRAME_attak117, FRAME_attak122, tank_frames_attack_post_blast, tank_run }; void tank_reattack_blaster(edict_t *self) { if (!self) { return; } if (skill->value >= SKILL_HARD) { if (visible(self, self->enemy)) { if (self->enemy->health > 0) { if (random() <= 0.6) { self->monsterinfo.currentmove = &tank_move_reattack_blast; return; } } } } self->monsterinfo.currentmove = &tank_move_attack_post_blast; } void tank_poststrike(edict_t *self) { if (!self) { return; } self->enemy = NULL; tank_run(self); } static mframe_t tank_frames_attack_strike[] = { {ai_move, 3, NULL}, {ai_move, 2, NULL}, {ai_move, 2, NULL}, {ai_move, 1, NULL}, {ai_move, 6, NULL}, {ai_move, 7, NULL}, {ai_move, 9, tank_footstep}, {ai_move, 2, NULL}, {ai_move, 1, NULL}, {ai_move, 2, NULL}, {ai_move, 2, tank_footstep}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, -2, NULL}, {ai_move, 0, tank_windup}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, TankStrike}, {ai_move, 0, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -1, NULL}, {ai_move, -3, NULL}, {ai_move, -10, NULL}, {ai_move, -10, NULL}, {ai_move, -2, NULL}, {ai_move, -3, NULL}, {ai_move, -2, tank_footstep} }; mmove_t tank_move_attack_strike = { FRAME_attak201, FRAME_attak238, tank_frames_attack_strike, tank_poststrike }; static mframe_t tank_frames_attack_pre_rocket[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* 10 */ {ai_charge, 0, NULL}, {ai_charge, 1, NULL}, {ai_charge, 2, NULL}, {ai_charge, 7, NULL}, {ai_charge, 7, NULL}, {ai_charge, 7, tank_footstep}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* 20 */ {ai_charge, -3, NULL} }; mmove_t tank_move_attack_pre_rocket = { FRAME_attak301, FRAME_attak321, tank_frames_attack_pre_rocket, tank_doattack_rocket }; static mframe_t tank_frames_attack_fire_rocket[] = { {ai_charge, -3, NULL}, /* Loop Start 22 */ {ai_charge, 0, NULL}, {ai_charge, 0, TankRocket}, /* 24 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, TankRocket}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, -1, TankRocket} /* 30 Loop End */ }; mmove_t tank_move_attack_fire_rocket = { FRAME_attak322, FRAME_attak330, tank_frames_attack_fire_rocket, tank_refire_rocket }; static mframe_t tank_frames_attack_post_rocket[] = { {ai_charge, 0, NULL}, /* 31 */ {ai_charge, -1, NULL}, {ai_charge, -1, NULL}, {ai_charge, 0, NULL}, {ai_charge, 2, NULL}, {ai_charge, 3, NULL}, {ai_charge, 4, NULL}, {ai_charge, 2, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* 40 */ {ai_charge, 0, NULL}, {ai_charge, -9, NULL}, {ai_charge, -8, NULL}, {ai_charge, -7, NULL}, {ai_charge, -1, NULL}, {ai_charge, -1, tank_footstep}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, /* 50 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t tank_move_attack_post_rocket = { FRAME_attak331, FRAME_attak353, tank_frames_attack_post_rocket, tank_run }; static mframe_t tank_frames_attack_chain[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {NULL, 0, TankMachineGun}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t tank_move_attack_chain = { FRAME_attak401, FRAME_attak429, tank_frames_attack_chain, tank_run }; void tank_refire_rocket(edict_t *self) { if (!self) { return; } if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.currentmove = &tank_move_attack_post_rocket; return; } /* Only on hard or nightmare */ if (skill->value >= SKILL_HARD) { if (self->enemy->health > 0) { if (visible(self, self->enemy)) { if (random() <= 0.4) { self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; return; } } } } self->monsterinfo.currentmove = &tank_move_attack_post_rocket; } void tank_doattack_rocket(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; } void tank_attack(edict_t *self) { vec3_t vec; float range; float r; float chance; if (!self || !self->enemy || !self->enemy->inuse) { return; } if (self->enemy->health < 0) { self->monsterinfo.currentmove = &tank_move_attack_strike; self->monsterinfo.aiflags &= ~AI_BRUTAL; return; } if (self->monsterinfo.attack_state == AS_BLIND) { if (self->monsterinfo.blind_fire_delay < 1.0) { chance = 1.0; } else if (self->monsterinfo.blind_fire_delay < 7.5) { chance = 0.4; } else { chance = 0.1; } r = random(); self->monsterinfo.blind_fire_delay += 3.2 + 2.0 + random() * 3.0; // Don't shoot at the origin. if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin)) { return; } // Don't shoot if the dice say not to. if (r > chance) { return; } // turn on manual steering to signal both manual steering and blindfire self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; self->monsterinfo.attack_finished = level.time + 3.0 + 2*random(); self->pain_debounce_time = level.time + 5.0; // no pain for a while return; } VectorSubtract(self->enemy->s.origin, self->s.origin, vec); range = VectorLength(vec); r = random(); if (range <= 125) { if (r < 0.4) { self->monsterinfo.currentmove = &tank_move_attack_chain; } else { self->monsterinfo.currentmove = &tank_move_attack_blast; } } else if (range <= 250) { if (r < 0.5) { self->monsterinfo.currentmove = &tank_move_attack_chain; } else { self->monsterinfo.currentmove = &tank_move_attack_blast; } } else { if (r < 0.33) { self->monsterinfo.currentmove = &tank_move_attack_chain; } else if (r < 0.66) { self->monsterinfo.currentmove = &tank_move_attack_pre_rocket; self->pain_debounce_time = level.time + 5.0; /* no pain for a while */ } else { self->monsterinfo.currentmove = &tank_move_attack_blast; } } } void tank_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -16, -16, -16); VectorSet(self->maxs, 16, 16, -0); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } static mframe_t tank_frames_death1[] = { {ai_move, -7, NULL}, {ai_move, -2, NULL}, {ai_move, -2, NULL}, {ai_move, 1, NULL}, {ai_move, 3, NULL}, {ai_move, 6, NULL}, {ai_move, 1, NULL}, {ai_move, 1, NULL}, {ai_move, 2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -2, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -3, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, -4, NULL}, {ai_move, -6, NULL}, {ai_move, -4, NULL}, {ai_move, -5, NULL}, {ai_move, -7, NULL}, {ai_move, -15, tank_thud}, {ai_move, -5, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t tank_move_death = { FRAME_death101, FRAME_death132, tank_frames_death1, tank_dead }; void tank_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 1 /*4*/; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ gi.sound(self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &tank_move_death; } qboolean tank_blocked(edict_t *self, float dist) { if (!self) { return false; } if (blocked_checkplat(self, dist)) { return true; } return false; } /* * QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight */ /* * QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight */ void SP_monster_tank(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } self->s.modelindex = gi.modelindex("models/monsters/tank/tris.md2"); VectorSet(self->mins, -32, -32, -16); VectorSet(self->maxs, 32, 32, 72); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; sound_pain = gi.soundindex("tank/tnkpain2.wav"); sound_thud = gi.soundindex("tank/tnkdeth2.wav"); sound_idle = gi.soundindex("tank/tnkidle1.wav"); sound_die = gi.soundindex("tank/death.wav"); sound_step = gi.soundindex("tank/step.wav"); sound_windup = gi.soundindex("tank/tnkatck4.wav"); sound_strike = gi.soundindex("tank/tnkatck5.wav"); sound_sight = gi.soundindex("tank/sight1.wav"); gi.soundindex("tank/tnkatck1.wav"); gi.soundindex("tank/tnkatk2a.wav"); gi.soundindex("tank/tnkatk2b.wav"); gi.soundindex("tank/tnkatk2c.wav"); gi.soundindex("tank/tnkatk2d.wav"); gi.soundindex("tank/tnkatk2e.wav"); gi.soundindex("tank/tnkatck3.wav"); if (strcmp(self->classname, "monster_tank_commander") == 0) { self->health = 1000; self->gib_health = -225; } else { self->health = 750; self->gib_health = -200; } self->mass = 500; self->pain = tank_pain; self->die = tank_die; self->monsterinfo.stand = tank_stand; self->monsterinfo.walk = tank_walk; self->monsterinfo.run = tank_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = tank_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = tank_sight; self->monsterinfo.idle = tank_idle; self->monsterinfo.blocked = tank_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &tank_move_stand; self->monsterinfo.scale = MODEL_SCALE; walkmonster_start(self); self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->monsterinfo.blindfire = true; if (strcmp(self->classname, "monster_tank_commander") == 0) { self->s.skinnum = 2; } } rogue-ROGUE_2_13/src/monster/tank/tank.h000066400000000000000000000242551477320066100201410ustar00rootroot00000000000000/* ======================================================================= * * Tank and Tank Commander animations. * * ======================================================================= */ #define FRAME_stand01 0 #define FRAME_stand02 1 #define FRAME_stand03 2 #define FRAME_stand04 3 #define FRAME_stand05 4 #define FRAME_stand06 5 #define FRAME_stand07 6 #define FRAME_stand08 7 #define FRAME_stand09 8 #define FRAME_stand10 9 #define FRAME_stand11 10 #define FRAME_stand12 11 #define FRAME_stand13 12 #define FRAME_stand14 13 #define FRAME_stand15 14 #define FRAME_stand16 15 #define FRAME_stand17 16 #define FRAME_stand18 17 #define FRAME_stand19 18 #define FRAME_stand20 19 #define FRAME_stand21 20 #define FRAME_stand22 21 #define FRAME_stand23 22 #define FRAME_stand24 23 #define FRAME_stand25 24 #define FRAME_stand26 25 #define FRAME_stand27 26 #define FRAME_stand28 27 #define FRAME_stand29 28 #define FRAME_stand30 29 #define FRAME_walk01 30 #define FRAME_walk02 31 #define FRAME_walk03 32 #define FRAME_walk04 33 #define FRAME_walk05 34 #define FRAME_walk06 35 #define FRAME_walk07 36 #define FRAME_walk08 37 #define FRAME_walk09 38 #define FRAME_walk10 39 #define FRAME_walk11 40 #define FRAME_walk12 41 #define FRAME_walk13 42 #define FRAME_walk14 43 #define FRAME_walk15 44 #define FRAME_walk16 45 #define FRAME_walk17 46 #define FRAME_walk18 47 #define FRAME_walk19 48 #define FRAME_walk20 49 #define FRAME_walk21 50 #define FRAME_walk22 51 #define FRAME_walk23 52 #define FRAME_walk24 53 #define FRAME_walk25 54 #define FRAME_attak101 55 #define FRAME_attak102 56 #define FRAME_attak103 57 #define FRAME_attak104 58 #define FRAME_attak105 59 #define FRAME_attak106 60 #define FRAME_attak107 61 #define FRAME_attak108 62 #define FRAME_attak109 63 #define FRAME_attak110 64 #define FRAME_attak111 65 #define FRAME_attak112 66 #define FRAME_attak113 67 #define FRAME_attak114 68 #define FRAME_attak115 69 #define FRAME_attak116 70 #define FRAME_attak117 71 #define FRAME_attak118 72 #define FRAME_attak119 73 #define FRAME_attak120 74 #define FRAME_attak121 75 #define FRAME_attak122 76 #define FRAME_attak201 77 #define FRAME_attak202 78 #define FRAME_attak203 79 #define FRAME_attak204 80 #define FRAME_attak205 81 #define FRAME_attak206 82 #define FRAME_attak207 83 #define FRAME_attak208 84 #define FRAME_attak209 85 #define FRAME_attak210 86 #define FRAME_attak211 87 #define FRAME_attak212 88 #define FRAME_attak213 89 #define FRAME_attak214 90 #define FRAME_attak215 91 #define FRAME_attak216 92 #define FRAME_attak217 93 #define FRAME_attak218 94 #define FRAME_attak219 95 #define FRAME_attak220 96 #define FRAME_attak221 97 #define FRAME_attak222 98 #define FRAME_attak223 99 #define FRAME_attak224 100 #define FRAME_attak225 101 #define FRAME_attak226 102 #define FRAME_attak227 103 #define FRAME_attak228 104 #define FRAME_attak229 105 #define FRAME_attak230 106 #define FRAME_attak231 107 #define FRAME_attak232 108 #define FRAME_attak233 109 #define FRAME_attak234 110 #define FRAME_attak235 111 #define FRAME_attak236 112 #define FRAME_attak237 113 #define FRAME_attak238 114 #define FRAME_attak301 115 #define FRAME_attak302 116 #define FRAME_attak303 117 #define FRAME_attak304 118 #define FRAME_attak305 119 #define FRAME_attak306 120 #define FRAME_attak307 121 #define FRAME_attak308 122 #define FRAME_attak309 123 #define FRAME_attak310 124 #define FRAME_attak311 125 #define FRAME_attak312 126 #define FRAME_attak313 127 #define FRAME_attak314 128 #define FRAME_attak315 129 #define FRAME_attak316 130 #define FRAME_attak317 131 #define FRAME_attak318 132 #define FRAME_attak319 133 #define FRAME_attak320 134 #define FRAME_attak321 135 #define FRAME_attak322 136 #define FRAME_attak323 137 #define FRAME_attak324 138 #define FRAME_attak325 139 #define FRAME_attak326 140 #define FRAME_attak327 141 #define FRAME_attak328 142 #define FRAME_attak329 143 #define FRAME_attak330 144 #define FRAME_attak331 145 #define FRAME_attak332 146 #define FRAME_attak333 147 #define FRAME_attak334 148 #define FRAME_attak335 149 #define FRAME_attak336 150 #define FRAME_attak337 151 #define FRAME_attak338 152 #define FRAME_attak339 153 #define FRAME_attak340 154 #define FRAME_attak341 155 #define FRAME_attak342 156 #define FRAME_attak343 157 #define FRAME_attak344 158 #define FRAME_attak345 159 #define FRAME_attak346 160 #define FRAME_attak347 161 #define FRAME_attak348 162 #define FRAME_attak349 163 #define FRAME_attak350 164 #define FRAME_attak351 165 #define FRAME_attak352 166 #define FRAME_attak353 167 #define FRAME_attak401 168 #define FRAME_attak402 169 #define FRAME_attak403 170 #define FRAME_attak404 171 #define FRAME_attak405 172 #define FRAME_attak406 173 #define FRAME_attak407 174 #define FRAME_attak408 175 #define FRAME_attak409 176 #define FRAME_attak410 177 #define FRAME_attak411 178 #define FRAME_attak412 179 #define FRAME_attak413 180 #define FRAME_attak414 181 #define FRAME_attak415 182 #define FRAME_attak416 183 #define FRAME_attak417 184 #define FRAME_attak418 185 #define FRAME_attak419 186 #define FRAME_attak420 187 #define FRAME_attak421 188 #define FRAME_attak422 189 #define FRAME_attak423 190 #define FRAME_attak424 191 #define FRAME_attak425 192 #define FRAME_attak426 193 #define FRAME_attak427 194 #define FRAME_attak428 195 #define FRAME_attak429 196 #define FRAME_pain101 197 #define FRAME_pain102 198 #define FRAME_pain103 199 #define FRAME_pain104 200 #define FRAME_pain201 201 #define FRAME_pain202 202 #define FRAME_pain203 203 #define FRAME_pain204 204 #define FRAME_pain205 205 #define FRAME_pain301 206 #define FRAME_pain302 207 #define FRAME_pain303 208 #define FRAME_pain304 209 #define FRAME_pain305 210 #define FRAME_pain306 211 #define FRAME_pain307 212 #define FRAME_pain308 213 #define FRAME_pain309 214 #define FRAME_pain310 215 #define FRAME_pain311 216 #define FRAME_pain312 217 #define FRAME_pain313 218 #define FRAME_pain314 219 #define FRAME_pain315 220 #define FRAME_pain316 221 #define FRAME_death101 222 #define FRAME_death102 223 #define FRAME_death103 224 #define FRAME_death104 225 #define FRAME_death105 226 #define FRAME_death106 227 #define FRAME_death107 228 #define FRAME_death108 229 #define FRAME_death109 230 #define FRAME_death110 231 #define FRAME_death111 232 #define FRAME_death112 233 #define FRAME_death113 234 #define FRAME_death114 235 #define FRAME_death115 236 #define FRAME_death116 237 #define FRAME_death117 238 #define FRAME_death118 239 #define FRAME_death119 240 #define FRAME_death120 241 #define FRAME_death121 242 #define FRAME_death122 243 #define FRAME_death123 244 #define FRAME_death124 245 #define FRAME_death125 246 #define FRAME_death126 247 #define FRAME_death127 248 #define FRAME_death128 249 #define FRAME_death129 250 #define FRAME_death130 251 #define FRAME_death131 252 #define FRAME_death132 253 #define FRAME_recln101 254 #define FRAME_recln102 255 #define FRAME_recln103 256 #define FRAME_recln104 257 #define FRAME_recln105 258 #define FRAME_recln106 259 #define FRAME_recln107 260 #define FRAME_recln108 261 #define FRAME_recln109 262 #define FRAME_recln110 263 #define FRAME_recln111 264 #define FRAME_recln112 265 #define FRAME_recln113 266 #define FRAME_recln114 267 #define FRAME_recln115 268 #define FRAME_recln116 269 #define FRAME_recln117 270 #define FRAME_recln118 271 #define FRAME_recln119 272 #define FRAME_recln120 273 #define FRAME_recln121 274 #define FRAME_recln122 275 #define FRAME_recln123 276 #define FRAME_recln124 277 #define FRAME_recln125 278 #define FRAME_recln126 279 #define FRAME_recln127 280 #define FRAME_recln128 281 #define FRAME_recln129 282 #define FRAME_recln130 283 #define FRAME_recln131 284 #define FRAME_recln132 285 #define FRAME_recln133 286 #define FRAME_recln134 287 #define FRAME_recln135 288 #define FRAME_recln136 289 #define FRAME_recln137 290 #define FRAME_recln138 291 #define FRAME_recln139 292 #define FRAME_recln140 293 #define MODEL_SCALE 1.000000 rogue-ROGUE_2_13/src/monster/turret/000077500000000000000000000000001477320066100174135ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/turret/turret.c000066400000000000000000000552321477320066100211130ustar00rootroot00000000000000/* ======================================================================= * * Wall mounted turrets. * * ======================================================================= */ #include "../../header/local.h" #include "turret.h" #define SPAWN_BLASTER 0x0008 #define SPAWN_MACHINEGUN 0x0010 #define SPAWN_ROCKET 0x0020 #define SPAWN_HEATBEAM 0x0040 #define SPAWN_WEAPONCHOICE 0x0078 #define SPAWN_INSTANT_WEAPON 0x0050 #define SPAWN_WALL_UNIT 0x0080 #define TURRET_BULLET_DAMAGE 4 #define TURRET_HEAT_DAMAGE 4 extern qboolean FindTarget(edict_t *self); void turret_run(edict_t *self); void TurretAim(edict_t *self); void turret_sight(edict_t *self, edict_t *other); void turret_search(edict_t *self); void turret_stand(edict_t *self); void turret_wake(edict_t *self); void turret_ready_gun(edict_t *self); void turret_run(edict_t *self); void turret_attack(edict_t *self); extern void Move_Calc(edict_t *ent, vec3_t dest, void (*func)(edict_t *)); mmove_t turret_move_fire; mmove_t turret_move_fire_blind; void TurretAim(edict_t *self) { vec3_t end, dir; vec3_t ang; float move, idealPitch, idealYaw, current, speed; int orientation; if (!self) { return; } if (!self->enemy || (self->enemy == world)) { if (!FindTarget(self)) { return; } } /* if turret is still in inactive mode, ready the gun, but don't aim */ if (self->s.frame < FRAME_active01) { turret_ready_gun(self); return; } /* if turret is still readying, don't aim. */ if (self->s.frame < FRAME_run01) { return; } /* blindfire aiming here */ if (self->monsterinfo.currentmove == &turret_move_fire_blind) { VectorCopy(self->monsterinfo.blind_fire_target, end); if (self->enemy->s.origin[2] < self->monsterinfo.blind_fire_target[2]) { end[2] += self->enemy->viewheight + 10; } else { end[2] += self->enemy->mins[2] - 10; } } else { VectorCopy(self->enemy->s.origin, end); if (self->enemy->client) { end[2] += self->enemy->viewheight; } } VectorSubtract(end, self->s.origin, dir); vectoangles2(dir, ang); idealPitch = ang[PITCH]; idealYaw = ang[YAW]; orientation = self->offset[1]; switch (orientation) { case -1: /* up pitch: 0 to 90 */ if (idealPitch < -90) { idealPitch += 360; } if (idealPitch > -5) { idealPitch = -5; } break; case -2: /* down pitch: -180 to -360 */ if (idealPitch > -90) { idealPitch -= 360; } if (idealPitch < -355) { idealPitch = -355; } else if (idealPitch > -185) { idealPitch = -185; } break; case 0: /* +X pitch: 0 to -90, -270 to -360 (or 0 to 90) */ if (idealPitch < -180) { idealPitch += 360; } if (idealPitch > 85) { idealPitch = 85; } else if (idealPitch < -85) { idealPitch = -85; } if (idealYaw > 180) { idealYaw -= 360; } if (idealYaw > 85) { idealYaw = 85; } else if (idealYaw < -85) { idealYaw = -85; } break; case 90: /* +Y pitch: 0 to 90, -270 to -360 (or 0 to 90) */ if (idealPitch < -180) { idealPitch += 360; } if (idealPitch > 85) { idealPitch = 85; } else if (idealPitch < -85) { idealPitch = -85; } if (idealYaw > 270) { idealYaw -= 360; } if (idealYaw > 175) { idealYaw = 175; } else if (idealYaw < 5) { idealYaw = 5; } break; case 180: /* -X pitch: 0 to 90, -270 to -360 (or 0 to 90) */ if (idealPitch < -180) { idealPitch += 360; } if (idealPitch > 85) { idealPitch = 85; } else if (idealPitch < -85) { idealPitch = -85; } if (idealYaw > 265) { idealYaw = 265; } else if (idealYaw < 95) { idealYaw = 95; } break; case 270: /* -Y pitch: 0 to 90, -270 to -360 (or 0 to 90) */ if (idealPitch < -180) { idealPitch += 360; } if (idealPitch > 85) { idealPitch = 85; } else if (idealPitch < -85) { idealPitch = -85; } if (idealYaw < 90) { idealYaw += 360; } if (idealYaw > 355) { idealYaw = 355; } else if (idealYaw < 185) { idealYaw = 185; } break; } current = self->s.angles[PITCH]; speed = self->yaw_speed; if (idealPitch != current) { move = idealPitch - current; while (move >= 360) { move -= 360; } if (move >= 90) { move = move - 360; } while (move <= -360) { move += 360; } if (move <= -90) { move = move + 360; } if (move > 0) { if (move > speed) { move = speed; } } else { if (move < -speed) { move = -speed; } } self->s.angles[PITCH] = anglemod(current + move); } current = self->s.angles[YAW]; speed = self->yaw_speed; if (idealYaw != current) { move = idealYaw - current; if (move >= 180) { move = move - 360; } if (move <= -180) { move = move + 360; } if (move > 0) { if (move > speed) { move = speed; } } else { if (move < -speed) { move = -speed; } } self->s.angles[YAW] = anglemod(current + move); } } void turret_sight(edict_t *self, edict_t *other) { } void turret_search(edict_t *self) { } static mframe_t turret_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t turret_move_stand = { FRAME_stand01, FRAME_stand02, turret_frames_stand, NULL }; void turret_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &turret_move_stand; } static mframe_t turret_frames_ready_gun[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t turret_move_ready_gun = { FRAME_active01, FRAME_run01, turret_frames_ready_gun, turret_run }; void turret_ready_gun(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &turret_move_ready_gun; } static mframe_t turret_frames_seek[] = { {ai_walk, 0, TurretAim}, {ai_walk, 0, TurretAim} }; mmove_t turret_move_seek = { FRAME_run01, FRAME_run02, turret_frames_seek, NULL }; void turret_walk(edict_t *self) { if (!self) { return; } if (self->s.frame < FRAME_run01) { turret_ready_gun(self); } else { self->monsterinfo.currentmove = &turret_move_seek; } } static mframe_t turret_frames_run[] = { {ai_run, 0, TurretAim}, {ai_run, 0, TurretAim} }; mmove_t turret_move_run = { FRAME_run01, FRAME_run02, turret_frames_run, turret_run }; void turret_run(edict_t *self) { if (!self) { return; } if (self->s.frame < FRAME_run01) { turret_ready_gun(self); } else { self->monsterinfo.currentmove = &turret_move_run; } } void TurretFire(edict_t *self) { vec3_t forward; vec3_t start, end, dir; float time, dist, chance; trace_t trace; int rocketSpeed = 0; if (!self) { return; } TurretAim(self); if (!self->enemy || !self->enemy->inuse) { return; } VectorSubtract(self->enemy->s.origin, self->s.origin, dir); VectorNormalize(dir); AngleVectors(self->s.angles, forward, NULL, NULL); chance = DotProduct(dir, forward); if (chance < 0.98) { return; } /* rockets fire less often than the others do. */ if (self->spawnflags & SPAWN_ROCKET) { rocketSpeed = 550; if (skill->value == SKILL_HARD) { rocketSpeed += 200 * random(); } else if (skill->value == SKILL_HARDPLUS) { rocketSpeed += 100 + (200 * random()); } } else if (self->spawnflags & SPAWN_BLASTER) { if (skill->value == SKILL_EASY) { rocketSpeed = 600; } else if (skill->value == SKILL_MEDIUM) { rocketSpeed = 800; } else { rocketSpeed = 1000; } } if (visible(self, self->enemy)) { VectorCopy(self->s.origin, start); VectorCopy(self->enemy->s.origin, end); /* aim for the head. */ if (self->enemy->client) { end[2] += self->enemy->viewheight; } else { end[2] += 22; } VectorSubtract(end, start, dir); dist = VectorLength(dir); /* check for predictive fire if distance less than 512 */ if (!(self->spawnflags & SPAWN_INSTANT_WEAPON) && (dist < 512)) { chance = random(); /* ramp chance. easy - 50%, avg - 60%, hard - 70%, nightmare - 80% */ chance += (3 - skill->value) * 0.1; if (chance < 0.8) { /* lead the target.... */ time = dist / 1000; VectorMA(end, time, self->enemy->velocity, end); VectorSubtract(end, start, dir); } } VectorNormalize(dir); trace = gi.trace(start, vec3_origin, vec3_origin, end, self, MASK_SHOT); if ((trace.ent == self->enemy) || (trace.ent == world)) { if (self->spawnflags & SPAWN_BLASTER) { monster_fire_blaster(self, start, dir, 20, rocketSpeed, MZ2_TURRET_BLASTER, EF_BLASTER); } else if (self->spawnflags & SPAWN_MACHINEGUN) { monster_fire_bullet(self, start, dir, TURRET_BULLET_DAMAGE, 0, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_TURRET_MACHINEGUN); } else if (self->spawnflags & SPAWN_ROCKET) { if (dist * trace.fraction > 72) { monster_fire_rocket(self, start, dir, 50, rocketSpeed, MZ2_TURRET_ROCKET); } } } } } void TurretFireBlind(edict_t *self) { vec3_t forward; vec3_t start, end, dir; float chance; int rocketSpeed = 0; if (!self) { return; } TurretAim(self); if (!self->enemy || !self->enemy->inuse) { return; } VectorSubtract(self->monsterinfo.blind_fire_target, self->s.origin, dir); VectorNormalize(dir); AngleVectors(self->s.angles, forward, NULL, NULL); chance = DotProduct(dir, forward); if (chance < 0.98) { return; } if (self->spawnflags & SPAWN_ROCKET) { rocketSpeed = 550; if (skill->value == SKILL_HARD) { rocketSpeed += 200 * random(); } else if (skill->value == SKILL_HARDPLUS) { rocketSpeed += 100 + (200 * random()); } } VectorCopy(self->s.origin, start); VectorCopy(self->monsterinfo.blind_fire_target, end); if (self->enemy->s.origin[2] < self->monsterinfo.blind_fire_target[2]) { end[2] += self->enemy->viewheight + 10; } else { end[2] += self->enemy->mins[2] - 10; } VectorSubtract(end, start, dir); VectorNormalize(dir); if (self->spawnflags & SPAWN_BLASTER) { monster_fire_blaster(self, start, dir, 20, 1000, MZ2_TURRET_BLASTER, EF_BLASTER); } else if (self->spawnflags & SPAWN_ROCKET) { monster_fire_rocket(self, start, dir, 50, rocketSpeed, MZ2_TURRET_ROCKET); } } static mframe_t turret_frames_fire[] = { {ai_run, 0, TurretFire}, {ai_run, 0, TurretAim}, {ai_run, 0, TurretAim}, {ai_run, 0, TurretAim} }; mmove_t turret_move_fire = { FRAME_pow01, FRAME_pow04, turret_frames_fire, turret_run }; /* the blind frames need to aim first */ static mframe_t turret_frames_fire_blind[] = { {ai_run, 0, TurretAim}, {ai_run, 0, TurretAim}, {ai_run, 0, TurretAim}, {ai_run, 0, TurretFireBlind} }; mmove_t turret_move_fire_blind = { FRAME_pow01, FRAME_pow04, turret_frames_fire_blind, turret_run }; void turret_attack(edict_t *self) { float r, chance; if (!self) { return; } if (self->s.frame < FRAME_run01) { turret_ready_gun(self); } else if (self->monsterinfo.attack_state != AS_BLIND) { self->monsterinfo.nextframe = FRAME_pow01; self->monsterinfo.currentmove = &turret_move_fire; } else { /* setup shot probabilities */ if (self->monsterinfo.blind_fire_delay < 1.0) { chance = 1.0; } else if (self->monsterinfo.blind_fire_delay < 7.5) { chance = 0.4; } else { chance = 0.1; } r = random(); /* minimum of 3 seconds, plus 0-4, after the shots are done - total time should be max less than 7.5 */ self->monsterinfo.blind_fire_delay += 0.4 + 3.0 + random() * 4.0; /* don't shoot at the origin */ if (VectorCompare(self->monsterinfo.blind_fire_target, vec3_origin)) { return; } /* don't shoot if the dice say not to */ if (r > chance) { return; } self->monsterinfo.nextframe = FRAME_pow01; self->monsterinfo.currentmove = &turret_move_fire_blind; } } void turret_pain(edict_t *self, edict_t *other, float kick, int damage) { return; } void turret_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { vec3_t forward; vec3_t start; edict_t *base; if (!self) { return; } gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_PLAIN_EXPLOSION); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PHS); AngleVectors(self->s.angles, forward, NULL, NULL); VectorMA(self->s.origin, 1, forward, start); ThrowDebris(self, "models/objects/debris1/tris.md2", 1, start); ThrowDebris(self, "models/objects/debris1/tris.md2", 2, start); ThrowDebris(self, "models/objects/debris1/tris.md2", 1, start); ThrowDebris(self, "models/objects/debris1/tris.md2", 2, start); if (self->teamchain) { base = self->teamchain; base->solid = SOLID_BBOX; base->takedamage = DAMAGE_NO; base->movetype = MOVETYPE_NONE; gi.linkentity(base); } if (self->target) { if (self->enemy && self->enemy->inuse) { G_UseTargets(self, self->enemy); } else { G_UseTargets(self, self); } } G_FreeEdict(self); } void turret_wall_spawn(edict_t *turret) { edict_t *ent; int angle; if (!turret) { return; } ent = G_Spawn(); VectorCopy(turret->s.origin, ent->s.origin); VectorCopy(turret->s.angles, ent->s.angles); angle = ent->s.angles[1]; if (ent->s.angles[0] == 90) { angle = -1; } else if (ent->s.angles[0] == 270) { angle = -2; } switch (angle) { case -1: VectorSet(ent->mins, -16, -16, -8); VectorSet(ent->maxs, 16, 16, 0); break; case -2: VectorSet(ent->mins, -16, -16, 0); VectorSet(ent->maxs, 16, 16, 8); break; case 0: VectorSet(ent->mins, -8, -16, -16); VectorSet(ent->maxs, 0, 16, 16); break; case 90: VectorSet(ent->mins, -16, -8, -16); VectorSet(ent->maxs, 16, 0, 16); break; case 180: VectorSet(ent->mins, 0, -16, -16); VectorSet(ent->maxs, 8, 16, 16); break; case 270: VectorSet(ent->mins, -16, 0, -16); VectorSet(ent->maxs, 16, 8, 16); break; } ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_NOT; ent->teammaster = turret; turret->teammaster = turret; turret->teamchain = ent; ent->teamchain = NULL; ent->flags |= FL_TEAMSLAVE; ent->owner = turret; ent->s.modelindex = gi.modelindex("models/monsters/turretbase/tris.md2"); gi.linkentity(ent); } void turret_wake(edict_t *self) { if (!self) { return; } /* the wall section will call this when it stops moving. */ if (self->flags & FL_TEAMSLAVE) { return; } self->monsterinfo.stand = turret_stand; self->monsterinfo.walk = turret_walk; self->monsterinfo.run = turret_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = turret_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = turret_sight; self->monsterinfo.search = turret_search; self->monsterinfo.currentmove = &turret_move_stand; self->takedamage = DAMAGE_AIM; self->movetype = MOVETYPE_NONE; self->monsterinfo.aiflags |= AI_DO_NOT_COUNT; gi.linkentity(self); stationarymonster_start(self); if (self->think) { self->think(self); } if (self->spawnflags & SPAWN_MACHINEGUN) { self->s.skinnum = 1; } else if (self->spawnflags & SPAWN_ROCKET) { self->s.skinnum = 2; } /* but we do want the death to count */ self->monsterinfo.aiflags &= ~AI_DO_NOT_COUNT; } void turret_activate(edict_t *self, edict_t *other, edict_t *activator) { vec3_t endpos; vec3_t forward; edict_t *base; if (self->movetype == MOVETYPE_PUSH) { return; } self->movetype = MOVETYPE_PUSH; if (!self->speed) { self->speed = 15; } self->moveinfo.speed = self->speed; self->moveinfo.accel = self->speed; self->moveinfo.decel = self->speed; if (self->s.angles[0] == 270) { VectorSet(forward, 0, 0, 1); } else if (self->s.angles[0] == 90) { VectorSet(forward, 0, 0, -1); } else if (self->s.angles[1] == 0) { VectorSet(forward, 1, 0, 0); } else if (self->s.angles[1] == 90) { VectorSet(forward, 0, 1, 0); } else if (self->s.angles[1] == 180) { VectorSet(forward, -1, 0, 0); } else if (self->s.angles[1] == 270) { VectorSet(forward, 0, -1, 0); } else { VectorClear(forward); } /* start up the turret */ VectorMA(self->s.origin, 32, forward, endpos); Move_Calc(self, endpos, turret_wake); base = self->teamchain; if (base) { base->movetype = MOVETYPE_PUSH; base->speed = self->speed; base->moveinfo.speed = base->speed; base->moveinfo.accel = base->speed; base->moveinfo.decel = base->speed; /* start up the wall section */ VectorMA(self->teamchain->s.origin, 32, forward, endpos); Move_Calc(self->teamchain, endpos, turret_wake); } gi.sound(self, CHAN_VOICE, gi.soundindex("world/dr_short.wav"), 1, ATTN_NORM, 0); } /* checkattack .. ignore range, just attack if available */ qboolean turret_checkattack(edict_t *self) { vec3_t spot1, spot2; float chance, nexttime; trace_t tr; if (!self) { return false; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_WINDOW); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* we want them to go ahead and shoot at info_notnulls if they can. */ if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0)) { /* if we can't see our target, and we're not blocked by a monster, go into blind fire if available */ if ((!(tr.ent->svflags & SVF_MONSTER)) && (!visible(self, self->enemy))) { if ((self->monsterinfo.blindfire) && (self->monsterinfo.blind_fire_delay <= 10.0)) { if (level.time < self->monsterinfo.attack_finished) { return false; } if (level.time < (self->monsterinfo.trail_time + self->monsterinfo.blind_fire_delay)) { /* wait for our time */ return false; } else { /* make sure we're not going to shoot something we don't want to shoot */ tr = gi.trace(spot1, NULL, NULL, self->monsterinfo.blind_fire_target, self, CONTENTS_MONSTER); if (tr.allsolid || tr.startsolid || ((tr.fraction < 1.0) && (tr.ent != self->enemy))) { return false; } self->monsterinfo.attack_state = AS_BLIND; self->monsterinfo.attack_finished = level.time + 0.5 + 2 * random(); return true; } } } return false; } } } if (level.time < self->monsterinfo.attack_finished) { return false; } if (self->spawnflags & SPAWN_ROCKET) { chance = 0.10; nexttime = (1.8 - (0.2 * skill->value)); } else if (self->spawnflags & SPAWN_BLASTER) { chance = 0.35; nexttime = (1.2 - (0.2 * skill->value)); } else { chance = 0.50; nexttime = (0.8 - (0.1 * skill->value)); } if (skill->value == SKILL_EASY) { chance *= 0.5; } else if (skill->value > SKILL_MEDIUM) { chance *= 2; } if (((random() < chance) && (visible(self, self->enemy))) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; self->monsterinfo.attack_finished = level.time + nexttime; return true; } self->monsterinfo.attack_state = AS_STRAIGHT; return false; } /*QUAKED monster_turret (1 .5 0) (-16 -16 -16) (16 16 16) Ambush Trigger_Spawn Sight Blaster MachineGun Rocket Heatbeam WallUnit * * The automated defense turret that mounts on walls. * Check the weapon you want it to use: blaster, machinegun, rocket, heatbeam. * Default weapon is blaster. * When activated, wall units move 32 units in the direction they're facing. */ void SP_monster_turret(edict_t *self) { int angle; if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } /* pre-caches */ gi.soundindex("world/dr_short.wav"); gi.modelindex("models/objects/debris1/tris.md2"); self->s.modelindex = gi.modelindex("models/monsters/turret/tris.md2"); VectorSet(self->mins, -12, -12, -12); VectorSet(self->maxs, 12, 12, 12); self->movetype = MOVETYPE_NONE; self->solid = SOLID_BBOX; self->health = 240; self->gib_health = -100; self->mass = 250; self->yaw_speed = 45; self->flags |= FL_MECHANICAL; self->pain = turret_pain; self->die = turret_die; /* map designer didn't specify weapon type. set it now. */ if (!(self->spawnflags & SPAWN_WEAPONCHOICE)) { self->spawnflags |= SPAWN_BLASTER; } if (self->spawnflags & SPAWN_HEATBEAM) { self->spawnflags &= ~SPAWN_HEATBEAM; self->spawnflags |= SPAWN_BLASTER; } if (!(self->spawnflags & SPAWN_WALL_UNIT)) { self->monsterinfo.stand = turret_stand; self->monsterinfo.walk = turret_walk; self->monsterinfo.run = turret_run; self->monsterinfo.dodge = NULL; self->monsterinfo.attack = turret_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = turret_sight; self->monsterinfo.search = turret_search; self->monsterinfo.currentmove = &turret_move_stand; } /* PMM */ self->monsterinfo.checkattack = turret_checkattack; self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->monsterinfo.scale = MODEL_SCALE; self->gravity = 0; VectorCopy(self->s.angles, self->offset); angle = (int)self->s.angles[1]; switch (angle) { case -1: /* up */ self->s.angles[0] = 270; self->s.angles[1] = 0; self->s.origin[2] += 2; break; case -2: /* down */ self->s.angles[0] = 90; self->s.angles[1] = 0; self->s.origin[2] -= 2; break; case 0: self->s.origin[0] += 2; break; case 90: self->s.origin[1] += 2; break; case 180: self->s.origin[0] -= 2; break; case 270: self->s.origin[1] -= 2; break; default: break; } gi.linkentity(self); if (self->spawnflags & SPAWN_WALL_UNIT) { if (!self->targetname) { G_FreeEdict(self); return; } self->takedamage = DAMAGE_NO; self->use = turret_activate; turret_wall_spawn(self); if ((!(self->monsterinfo.aiflags & AI_GOOD_GUY)) && (!(self->monsterinfo.aiflags & AI_DO_NOT_COUNT))) { level.total_monsters++; } } else { stationarymonster_start(self); } if (self->spawnflags & SPAWN_MACHINEGUN) { gi.soundindex("infantry/infatck1.wav"); self->s.skinnum = 1; } else if (self->spawnflags & SPAWN_ROCKET) { gi.soundindex("weapons/rockfly.wav"); gi.modelindex("models/objects/rocket/tris.md2"); gi.soundindex("chick/chkatck2.wav"); self->s.skinnum = 2; } else { if (!(self->spawnflags & SPAWN_BLASTER)) { self->spawnflags |= SPAWN_BLASTER; } gi.modelindex("models/objects/laser/tris.md2"); gi.soundindex("misc/lasfly.wav"); gi.soundindex("soldier/solatck2.wav"); } /* turrets don't get mad at monsters, and visa versa */ self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; /* blindfire */ if (self->spawnflags & (SPAWN_ROCKET | SPAWN_BLASTER)) { self->monsterinfo.blindfire = true; } } rogue-ROGUE_2_13/src/monster/turret/turret.h000066400000000000000000000013561477320066100211160ustar00rootroot00000000000000/* ======================================================================= * * Turret animations. * * ======================================================================= */ #define FRAME_stand01 0 #define FRAME_stand02 1 #define FRAME_active01 2 #define FRAME_active02 3 #define FRAME_active03 4 #define FRAME_active04 5 #define FRAME_active05 6 #define FRAME_active06 7 #define FRAME_run01 8 #define FRAME_run02 9 #define FRAME_pow01 10 #define FRAME_pow02 11 #define FRAME_pow03 12 #define FRAME_pow04 13 #define FRAME_death01 14 #define FRAME_death02 15 #define MODEL_SCALE 3.500000 rogue-ROGUE_2_13/src/monster/widow/000077500000000000000000000000001477320066100172175ustar00rootroot00000000000000rogue-ROGUE_2_13/src/monster/widow/widow.c000066400000000000000000001122541477320066100205210ustar00rootroot00000000000000/* ======================================================================= * * Black Window (stage 1). * * ======================================================================= */ #include "../../header/local.h" #include "widow.h" #define NUM_STALKERS_SPAWNED 6 /* max # of stalkers she can spawn */ #define RAIL_TIME 3 #define BLASTER_TIME 2 #define BLASTER2_DAMAGE 10 #define WIDOW_RAIL_DAMAGE 50 #define VARIANCE 15.0 void BossExplode(edict_t *self); qboolean infront(edict_t *self, edict_t *other); static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_search1; static int sound_rail; static unsigned long shotsfired; static vec3_t spawnpoints[] = { {30, 100, 16}, {30, -100, 16} }; static vec3_t beameffects[] = { {12.58, -43.71, 68.88}, {3.43, 58.72, 68.41} }; static float sweep_angles[] = { 32.0, 26.0, 20.0, 10.0, 0.0, -6.5, -13.0, -27.0, -41.0 }; vec3_t stalker_mins = {-28, -28, -18}; vec3_t stalker_maxs = {28, 28, 18}; mmove_t widow_move_attack_post_blaster; mmove_t widow_move_attack_post_blaster_r; mmove_t widow_move_attack_post_blaster_l; mmove_t widow_move_attack_blaster; mmove_t widow_move_attack_rail; mmove_t widow_move_attack_rail_l; mmove_t widow_move_attack_rail_r; unsigned int widow_damage_multiplier; void widow_run(edict_t *self); void widow_stand(edict_t *self); void widow_dead(edict_t *self); void widow_attack(edict_t *self); void widow_attack_blaster(edict_t *self); void widow_reattack_blaster(edict_t *self); void widow_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void widow_start_spawn(edict_t *self); void widow_done_spawn(edict_t *self); void widow_spawn_check(edict_t *self); void widow_prep_spawn(edict_t *self); void widow_attack_rail(edict_t *self); void widow_start_run_5(edict_t *self); void widow_start_run_10(edict_t *self); void widow_start_run_12(edict_t *self); void WidowCalcSlots(edict_t *self); void drawbbox(edict_t *self); void showme(edict_t *self) { if (!self) { return; } gi.dprintf("frame %d\n", self->s.frame); } void widow_search(edict_t *self) { } void widow_sight(edict_t *self, edict_t *other /* unused */) { if (!self) { return; } self->monsterinfo.pausetime = 0; } float target_angle(edict_t *self) { vec3_t target; float enemy_yaw; if (!self) { return 0.0; } VectorSubtract(self->s.origin, self->enemy->s.origin, target); enemy_yaw = self->s.angles[YAW] - vectoyaw2(target); if (enemy_yaw < 0) { enemy_yaw += 360.0; } enemy_yaw -= 180.0; return enemy_yaw; } int WidowTorso(edict_t *self) { float enemy_yaw; if (!self) { return 0; } enemy_yaw = target_angle(self); if (enemy_yaw >= 105) { self->monsterinfo.currentmove = &widow_move_attack_post_blaster_r; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; return 0; } if (enemy_yaw <= -75.0) { self->monsterinfo.currentmove = &widow_move_attack_post_blaster_l; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; return 0; } if (enemy_yaw >= 95) { return FRAME_fired03; } else if (enemy_yaw >= 85) { return FRAME_fired04; } else if (enemy_yaw >= 75) { return FRAME_fired05; } else if (enemy_yaw >= 65) { return FRAME_fired06; } else if (enemy_yaw >= 55) { return FRAME_fired07; } else if (enemy_yaw >= 45) { return FRAME_fired08; } else if (enemy_yaw >= 35) { return FRAME_fired09; } else if (enemy_yaw >= 25) { return FRAME_fired10; } else if (enemy_yaw >= 15) { return FRAME_fired11; } else if (enemy_yaw >= 5) { return FRAME_fired12; } else if (enemy_yaw >= -5) { return FRAME_fired13; } else if (enemy_yaw >= -15) { return FRAME_fired14; } else if (enemy_yaw >= -25) { return FRAME_fired15; } else if (enemy_yaw >= -35) { return FRAME_fired16; } else if (enemy_yaw >= -45) { return FRAME_fired17; } else if (enemy_yaw >= -55) { return FRAME_fired18; } else if (enemy_yaw >= -65) { return FRAME_fired19; } else if (enemy_yaw >= -75) { return FRAME_fired20; } return 1; } void WidowBlaster(edict_t *self) { vec3_t forward, right, target, vec, targ_angles; vec3_t start; int flashnum; int effect; if (!self) { return; } if (!self->enemy) { return; } shotsfired++; if (!(shotsfired % 4)) { effect = EF_BLASTER; } else { effect = 0; } AngleVectors(self->s.angles, forward, right, NULL); if ((self->s.frame >= FRAME_spawn05) && (self->s.frame <= FRAME_spawn13)) { /* sweep */ flashnum = MZ2_WIDOW_BLASTER_SWEEP1 + self->s.frame - FRAME_spawn05; G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorSubtract(self->enemy->s.origin, start, target); vectoangles2(target, targ_angles); VectorCopy(self->s.angles, vec); vec[PITCH] += targ_angles[PITCH]; vec[YAW] -= sweep_angles[flashnum - MZ2_WIDOW_BLASTER_SWEEP1]; AngleVectors(vec, forward, NULL, NULL); monster_fire_blaster2(self, start, forward, BLASTER2_DAMAGE * widow_damage_multiplier, 1000, flashnum, effect); } else if ((self->s.frame >= FRAME_fired02a) && (self->s.frame <= FRAME_fired20)) { vec3_t angles; float aim_angle, target_angle; float error; self->monsterinfo.aiflags |= AI_MANUAL_STEERING; self->monsterinfo.nextframe = WidowTorso(self); if (!self->monsterinfo.nextframe) { self->monsterinfo.nextframe = self->s.frame; } if (self->s.frame == FRAME_fired02a) { flashnum = MZ2_WIDOW_BLASTER_0; } else { flashnum = MZ2_WIDOW_BLASTER_100 + self->s.frame - FRAME_fired03; } G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); PredictAim(self->enemy, start, 1000, true, ((random() * 0.1) - 0.05), forward, NULL); /* clamp it to within 10 degrees of the aiming angle (where she's facing) */ vectoangles2(forward, angles); aim_angle = 100 - (10 * (flashnum - MZ2_WIDOW_BLASTER_100)); if (aim_angle <= 0) { aim_angle += 360; } target_angle = self->s.angles[YAW] - angles[YAW]; if (target_angle <= 0) { target_angle += 360; } error = aim_angle - target_angle; /* positive error is to entity's left, aka positive direction in engine unfortunately, I decided that for the aim_angle, positive was right. *sigh* */ if (error > VARIANCE) { angles[YAW] = (self->s.angles[YAW] - aim_angle) + VARIANCE; AngleVectors(angles, forward, NULL, NULL); } else if (error < -VARIANCE) { angles[YAW] = (self->s.angles[YAW] - aim_angle) - VARIANCE; AngleVectors(angles, forward, NULL, NULL); } monster_fire_blaster2(self, start, forward, BLASTER2_DAMAGE * widow_damage_multiplier, 1000, flashnum, effect); } else if ((self->s.frame >= FRAME_run01) && (self->s.frame <= FRAME_run08)) { flashnum = MZ2_WIDOW_RUN_1 + self->s.frame - FRAME_run01; G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorSubtract(self->enemy->s.origin, start, target); target[2] += self->enemy->viewheight; monster_fire_blaster2(self, start, target, BLASTER2_DAMAGE * widow_damage_multiplier, 1000, flashnum, effect); } } void WidowSpawn(edict_t *self) { vec3_t f, r, u, offset, startpoint, spawnpoint; edict_t *ent, *designated_enemy; int i; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); for (i = 0; i < 2; i++) { VectorCopy(spawnpoints[i], offset); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); if (FindSpawnPoint(startpoint, stalker_mins, stalker_maxs, spawnpoint, 64)) { ent = CreateGroundMonster(spawnpoint, self->s.angles, stalker_mins, stalker_maxs, "monster_stalker", 256); if (!ent) { continue; } self->monsterinfo.monster_used++; ent->monsterinfo.commander = self; ent->nextthink = level.time; ent->think(ent); ent->monsterinfo.aiflags |= AI_SPAWNED_WIDOW | AI_DO_NOT_COUNT | AI_IGNORE_SHOTS; designated_enemy = self->enemy; if ((designated_enemy->inuse) && (designated_enemy->health > 0)) { ent->enemy = designated_enemy; FoundTarget(ent); ent->monsterinfo.attack(ent); } } } } void widow_spawn_check(edict_t *self) { if (!self) { return; } WidowBlaster(self); WidowSpawn(self); } void widow_ready_spawn(edict_t *self) { vec3_t f, r, u, offset, startpoint, spawnpoint; int i; if (!self) { return; } WidowBlaster(self); AngleVectors(self->s.angles, f, r, u); for (i = 0; i < 2; i++) { VectorCopy(spawnpoints[i], offset); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); if (FindSpawnPoint(startpoint, stalker_mins, stalker_maxs, spawnpoint, 64)) { SpawnGrow_Spawn(spawnpoint, 1); } } } void widow_step(edict_t *self) { gi.sound(self, CHAN_BODY, gi.soundindex("widow/bwstep3.wav"), 1, ATTN_NORM, 0); } static mframe_t widow_frames_stand[] = { {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL}, {ai_stand, 0, NULL} }; mmove_t widow_move_stand = { FRAME_idle01, FRAME_idle11, widow_frames_stand, NULL }; static mframe_t widow_frames_walk[] = { /* auto generated numbers */ {ai_walk, 2.79, widow_step}, {ai_walk, 2.77, NULL}, {ai_walk, 3.53, NULL}, {ai_walk, 3.97, NULL}, {ai_walk, 4.13, NULL}, /* 5 */ {ai_walk, 4.09, NULL}, {ai_walk, 3.84, NULL}, {ai_walk, 3.62, widow_step}, {ai_walk, 3.29, NULL}, {ai_walk, 6.08, NULL}, /* 10 */ {ai_walk, 6.94, NULL}, {ai_walk, 5.73, NULL}, {ai_walk, 2.85, NULL} }; mmove_t widow_move_walk = { FRAME_walk01, FRAME_walk13, widow_frames_walk, NULL }; static mframe_t widow_frames_run[] = { {ai_run, 2.79, widow_step}, {ai_run, 2.77, NULL}, {ai_run, 3.53, NULL}, {ai_run, 3.97, NULL}, {ai_run, 4.13, NULL}, /* 5 */ {ai_run, 4.09, NULL}, {ai_run, 3.84, NULL}, {ai_run, 3.62, widow_step}, {ai_run, 3.29, NULL}, {ai_run, 6.08, NULL}, /* 10 */ {ai_run, 6.94, NULL}, {ai_run, 5.73, NULL}, {ai_run, 2.85, NULL} }; mmove_t widow_move_run = { FRAME_walk01, FRAME_walk13, widow_frames_run, NULL }; void widow_stepshoot(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_BODY, gi.soundindex("widow/bwstep2.wav"), 1, ATTN_NORM, 0); WidowBlaster(self); } static mframe_t widow_frames_run_attack[] = { {ai_charge, 13, widow_stepshoot}, {ai_charge, 11.72, WidowBlaster}, {ai_charge, 18.04, WidowBlaster}, {ai_charge, 14.58, WidowBlaster}, {ai_charge, 13, widow_stepshoot}, /* 5 */ {ai_charge, 12.12, WidowBlaster}, {ai_charge, 19.63, WidowBlaster}, {ai_charge, 11.37, WidowBlaster} }; mmove_t widow_move_run_attack = { FRAME_run01, FRAME_run08, widow_frames_run_attack, widow_run }; /* These three allow specific entry into the run sequence */ void widow_start_run_5(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow_move_run; self->monsterinfo.nextframe = FRAME_walk05; } void widow_start_run_10(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow_move_run; self->monsterinfo.nextframe = FRAME_walk10; } void widow_start_run_12(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow_move_run; self->monsterinfo.nextframe = FRAME_walk12; } static mframe_t widow_frames_attack_pre_blaster[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_attack_blaster} }; mmove_t widow_move_attack_pre_blaster = { FRAME_fired01, FRAME_fired02a, widow_frames_attack_pre_blaster, NULL }; static mframe_t widow_frames_attack_blaster[] = { {ai_charge, 0, widow_reattack_blaster}, /* straight ahead */ {ai_charge, 0, widow_reattack_blaster}, /* 100 degrees right */ {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, /* 50 degrees right */ {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, /* straight */ {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster}, /* 50 degrees left */ {ai_charge, 0, widow_reattack_blaster}, {ai_charge, 0, widow_reattack_blaster} /* 70 degrees left */ }; mmove_t widow_move_attack_blaster = { FRAME_fired02a, FRAME_fired20, widow_frames_attack_blaster, NULL }; static mframe_t widow_frames_attack_post_blaster[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL} }; mmove_t widow_move_attack_post_blaster = { FRAME_fired21, FRAME_fired22, widow_frames_attack_post_blaster, widow_run }; static mframe_t widow_frames_attack_post_blaster_r[] = { {ai_charge, -2, NULL}, {ai_charge, -10, NULL}, {ai_charge, -2, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_start_run_12} }; mmove_t widow_move_attack_post_blaster_r = { FRAME_transa01, FRAME_transa05, widow_frames_attack_post_blaster_r, NULL }; static mframe_t widow_frames_attack_post_blaster_l[] = { {ai_charge, 0, NULL}, {ai_charge, 14, NULL}, {ai_charge, -2, NULL}, {ai_charge, 10, NULL}, {ai_charge, 10, widow_start_run_12} }; mmove_t widow_move_attack_post_blaster_l = { FRAME_transb01, FRAME_transb05, widow_frames_attack_post_blaster_l, NULL }; void WidowRail(edict_t *self) { vec3_t start; vec3_t dir; vec3_t forward, right; int flash = 0; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); if (self->monsterinfo.currentmove == &widow_move_attack_rail) { flash = MZ2_WIDOW_RAIL; } else if (self->monsterinfo.currentmove == &widow_move_attack_rail_l) { flash = MZ2_WIDOW_RAIL_LEFT; } else if (self->monsterinfo.currentmove == &widow_move_attack_rail_r) { flash = MZ2_WIDOW_RAIL_RIGHT; } G_ProjectSource(self->s.origin, monster_flash_offset[flash], forward, right, start); /* calc direction to where we targeted */ VectorSubtract(self->pos1, start, dir); VectorNormalize(dir); monster_fire_railgun(self, start, dir, WIDOW_RAIL_DAMAGE * widow_damage_multiplier, 100, flash); self->timestamp = level.time + RAIL_TIME; } void WidowSaveLoc(edict_t *self) { if (!self) { return; } VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; } void widow_start_rail(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_MANUAL_STEERING; } void widow_rail_done(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; } static mframe_t widow_frames_attack_pre_rail[] = { {ai_charge, 0, widow_start_rail}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_attack_rail} }; mmove_t widow_move_attack_pre_rail = { FRAME_transc01, FRAME_transc04, widow_frames_attack_pre_rail, NULL }; static mframe_t widow_frames_attack_rail[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, WidowSaveLoc}, {ai_charge, -10, WidowRail}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_rail_done} }; mmove_t widow_move_attack_rail = { FRAME_firea01, FRAME_firea09, widow_frames_attack_rail, widow_run }; static mframe_t widow_frames_attack_rail_r[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, WidowSaveLoc}, {ai_charge, -10, WidowRail}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_rail_done} }; mmove_t widow_move_attack_rail_r = { FRAME_fireb01, FRAME_fireb09, widow_frames_attack_rail_r, widow_run }; static mframe_t widow_frames_attack_rail_l[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, WidowSaveLoc}, {ai_charge, -10, WidowRail}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_rail_done} }; mmove_t widow_move_attack_rail_l = { FRAME_firec01, FRAME_firec09, widow_frames_attack_rail_l, widow_run }; void widow_attack_rail(edict_t *self) { float enemy_angle; if (!self) { return; } enemy_angle = target_angle(self); if (enemy_angle < -15) { self->monsterinfo.currentmove = &widow_move_attack_rail_l; } else if (enemy_angle > 15) { self->monsterinfo.currentmove = &widow_move_attack_rail_r; } else { self->monsterinfo.currentmove = &widow_move_attack_rail; } } void widow_start_spawn(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_MANUAL_STEERING; } void widow_done_spawn(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; } static mframe_t widow_frames_spawn[] = { {ai_charge, 0, NULL}, /* 1 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_start_spawn}, {ai_charge, 0, NULL}, /* 5 */ {ai_charge, 0, WidowBlaster}, /* 6 */ {ai_charge, 0, widow_ready_spawn}, /* 7 */ {ai_charge, 0, WidowBlaster}, {ai_charge, 0, WidowBlaster}, /* 9 */ {ai_charge, 0, widow_spawn_check}, {ai_charge, 0, WidowBlaster}, /* 11 */ {ai_charge, 0, WidowBlaster}, {ai_charge, 0, WidowBlaster}, /* 13 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_done_spawn} }; mmove_t widow_move_spawn = { FRAME_spawn01, FRAME_spawn18, widow_frames_spawn, widow_run }; static mframe_t widow_frames_pain_heavy[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t widow_move_pain_heavy = { FRAME_pain01, FRAME_pain13, widow_frames_pain_heavy, widow_run }; static mframe_t widow_frames_pain_light[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t widow_move_pain_light = { FRAME_pain201, FRAME_pain203, widow_frames_pain_light, widow_run }; void spawn_out_start(edict_t *self) { vec3_t startpoint, f, r, u; if (!self) { return; } self->wait = level.time + 2.0; AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, beameffects[0], f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_WIDOWBEAMOUT); gi.WriteShort(20001); gi.WritePosition(startpoint); gi.multicast(startpoint, MULTICAST_ALL); G_ProjectSource2(self->s.origin, beameffects[1], f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_WIDOWBEAMOUT); gi.WriteShort(20002); gi.WritePosition(startpoint); gi.multicast(startpoint, MULTICAST_ALL); gi.sound(self, CHAN_VOICE, gi.soundindex("misc/bwidowbeamout.wav"), 1, ATTN_NORM, 0); } void spawn_out_do(edict_t *self) { vec3_t startpoint, f, r, u; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, beameffects[0], f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_WIDOWSPLASH); gi.WritePosition(startpoint); gi.multicast(startpoint, MULTICAST_ALL); G_ProjectSource2(self->s.origin, beameffects[1], f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_WIDOWSPLASH); gi.WritePosition(startpoint); gi.multicast(startpoint, MULTICAST_ALL); VectorCopy(self->s.origin, startpoint); startpoint[2] += 36; gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BOSSTPORT); gi.WritePosition(startpoint); gi.multicast(startpoint, MULTICAST_PVS); Widowlegs_Spawn(self->s.origin, self->s.angles); G_FreeEdict(self); } static mframe_t widow_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 5 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, spawn_out_start}, /* 10 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 15 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 20 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 25 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 30 */ {ai_move, 0, spawn_out_do} }; mmove_t widow_move_death = { FRAME_death01, FRAME_death31, widow_frames_death, NULL }; void widow_attack_kick(edict_t *self) { vec3_t aim; if (!self) { return; } VectorSet(aim, 100, 0, 4); if (self->enemy->groundentity) { fire_hit(self, aim, (50 + (rand() % 6)), 500); } else /* not as much kick if they're in the air .. makes it harder to land on her head */ { fire_hit(self, aim, (50 + (rand() % 6)), 250); } } static mframe_t widow_frames_attack_kick[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, widow_attack_kick}, {ai_move, 0, NULL}, /* 5 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t widow_move_attack_kick = { FRAME_kick01, FRAME_kick08, widow_frames_attack_kick, widow_run }; void widow_stand(edict_t *self) { if (!self) { return; } gi.sound(self, CHAN_WEAPON, gi.soundindex("widow/laugh.wav"), 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_stand; } void widow_run(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &widow_move_stand; } else { self->monsterinfo.currentmove = &widow_move_run; } } void widow_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow_move_walk; } void widow_attack(edict_t *self) { float luck; qboolean rail_frames = false, blaster_frames = false, blocked = false, anger = false; if (!self) { return; } self->movetarget = NULL; if (self->monsterinfo.aiflags & AI_BLOCKED) { blocked = true; self->monsterinfo.aiflags &= ~AI_BLOCKED; } if (self->monsterinfo.aiflags & AI_TARGET_ANGER) { anger = true; self->monsterinfo.aiflags &= ~AI_TARGET_ANGER; } if ((!self->enemy) || (!self->enemy->inuse)) { return; } if (self->bad_area) { if ((random() < 0.1) || (level.time < self->timestamp)) { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; } else { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } return; } if ((self->s.frame == FRAME_walk13) || ((self->s.frame >= FRAME_walk01) && (self->s.frame <= FRAME_walk03))) { rail_frames = true; } if ((self->s.frame >= FRAME_walk09) && (self->s.frame <= FRAME_walk12)) { blaster_frames = true; } WidowCalcSlots(self); /* if we can't see the target, spawn stuff regardless of frame */ if ((self->monsterinfo.attack_state == AS_BLIND) && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow_move_spawn; return; } /* accept bias towards spawning regardless of frame */ if (blocked && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow_move_spawn; return; } if ((realrange(self, self->enemy) > 300) && (!anger) && (random() < 0.5) && (!blocked)) { self->monsterinfo.currentmove = &widow_move_run_attack; return; } if (blaster_frames) { if (SELF_SLOTS_LEFT >= 2) { self->monsterinfo.currentmove = &widow_move_spawn; return; } else if (self->monsterinfo.pausetime + BLASTER_TIME <= level.time) { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; return; } } if (rail_frames) { if (!(level.time < self->timestamp)) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } } if ((rail_frames) || (blaster_frames)) { return; } luck = random(); if (SELF_SLOTS_LEFT >= 2) { if ((luck <= 0.40) && (self->monsterinfo.pausetime + BLASTER_TIME <= level.time)) { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; } else if ((luck <= 0.7) && !(level.time < self->timestamp)) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } else { self->monsterinfo.currentmove = &widow_move_spawn; } } else { if (level.time < self->timestamp) { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; } else if ((luck <= 0.50) || (level.time + BLASTER_TIME >= self->monsterinfo.pausetime)) { gi.sound(self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } else /* holdout to blaster */ { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; } } } void widow_attack_blaster(edict_t *self) { if (!self) { return; } self->monsterinfo.pausetime = level.time + 1.0 + (2.0 * random()); self->monsterinfo.currentmove = &widow_move_attack_blaster; self->monsterinfo.nextframe = WidowTorso(self); } void widow_reattack_blaster(edict_t *self) { if (!self) { return; } WidowBlaster(self); if ((self->monsterinfo.currentmove == &widow_move_attack_post_blaster_l) || (self->monsterinfo.currentmove == &widow_move_attack_post_blaster_r)) { return; } /* if we're not done with the attack, don't leave the sequence */ if (self->monsterinfo.pausetime >= level.time) { return; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.currentmove = &widow_move_attack_post_blaster; } void widow_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (level.time < self->pain_debounce_time) { return; } if (self->monsterinfo.pausetime == 100000000) { self->monsterinfo.pausetime = 0; } self->pain_debounce_time = level.time + 5; if (damage < 15) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); } else if (damage < 75) { if ((skill->value < SKILL_HARDPLUS) && (random() < (0.6 - (0.2 * ((float)skill->value))))) { self->monsterinfo.currentmove = &widow_move_pain_light; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; } gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); } else { if ((skill->value < SKILL_HARDPLUS) && (random() < (0.75 - (0.1 * ((float)skill->value))))) { self->monsterinfo.currentmove = &widow_move_pain_heavy; self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; } gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); } } void widow_dead(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -56, -56, 0); VectorSet(self->maxs, 56, 56, 80); self->movetype = MOVETYPE_TOSS; self->svflags |= SVF_DEADMONSTER; self->nextthink = 0; gi.linkentity(self); } void widow_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage /* unused */, vec3_t point /* unused */) { if (!self) { return; } self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; self->monsterinfo.quad_framenum = 0; self->monsterinfo.double_framenum = 0; self->monsterinfo.invincible_framenum = 0; self->monsterinfo.currentmove = &widow_move_death; } void widow_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow_move_attack_kick; } void WidowGoinQuad(edict_t *self, float framenum) { if (!self) { return; } self->monsterinfo.quad_framenum = framenum; widow_damage_multiplier = 4; } void WidowDouble(edict_t *self, float framenum) { if (!self) { return; } self->monsterinfo.double_framenum = framenum; widow_damage_multiplier = 2; } void WidowPent(edict_t *self, float framenum) { if (!self) { return; } self->monsterinfo.invincible_framenum = framenum; } void WidowPowerArmor(edict_t *self) { if (!self) { return; } self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; /* I don't like this, but it works */ if (self->monsterinfo.power_armor_power <= 0) { self->monsterinfo.power_armor_power += 250 * skill->value; } } void WidowRespondPowerup(edict_t *self, edict_t *other) { if (!self || !other) { return; } if (other->s.effects & EF_QUAD) { if (skill->value == SKILL_MEDIUM) { WidowDouble(self, other->client->quad_framenum); } else if (skill->value == SKILL_HARD) { WidowGoinQuad(self, other->client->quad_framenum); } else if (skill->value == SKILL_HARDPLUS) { WidowGoinQuad(self, other->client->quad_framenum); WidowPowerArmor(self); } } else if (other->s.effects & EF_DOUBLE) { if (skill->value == SKILL_HARD) { WidowDouble(self, other->client->double_framenum); } else if (skill->value == SKILL_HARDPLUS) { WidowDouble(self, other->client->double_framenum); WidowPowerArmor(self); } } else { widow_damage_multiplier = 1; } if (other->s.effects & EF_PENT) { if (skill->value == SKILL_MEDIUM) { WidowPowerArmor(self); } else if (skill->value == SKILL_HARD) { WidowPent(self, other->client->invincible_framenum); } else if (skill->value == SKILL_HARDPLUS) { WidowPent(self, other->client->invincible_framenum); WidowPowerArmor(self); } } } void WidowPowerups(edict_t *self) { int player; edict_t *ent; if (!self) { return; } if (!(coop && coop->value)) { WidowRespondPowerup(self, self->enemy); } else { /* in coop, check for pents, then quads, then doubles */ for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (ent->s.effects & EF_PENT) { WidowRespondPowerup(self, ent); return; } } for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (ent->s.effects & EF_QUAD) { WidowRespondPowerup(self, ent); return; } } for (player = 1; player <= game.maxclients; player++) { ent = &g_edicts[player]; if (!ent->inuse) { continue; } if (!ent->client) { continue; } if (ent->s.effects & EF_DOUBLE) { WidowRespondPowerup(self, ent); return; } } } } qboolean Widow_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance = 0; trace_t tr; int enemy_range; float enemy_yaw; float real_enemy_range; if (!self) { return false; } if (!self->enemy) { return false; } WidowPowerups(self); if (self->monsterinfo.currentmove == &widow_move_run) { /* if we're in run, make sure we're in a good frame for attacking before doing anything else */ switch (self->s.frame) { case FRAME_walk04: case FRAME_walk05: case FRAME_walk06: case FRAME_walk07: case FRAME_walk08: case FRAME_walk12: { return false; } default: break; } } /* give a LARGE bias to spawning things when we have room use AI_BLOCKED as a signal to attack to spawn */ if ((random() < 0.8) && (SELF_SLOTS_LEFT >= 2) && (realrange(self, self->enemy) > 150)) { self->monsterinfo.aiflags |= AI_BLOCKED; self->monsterinfo.attack_state = AS_MISSILE; return true; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* go ahead and spawn stuff if we're mad a a client */ if (self->enemy->client && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.attack_state = AS_BLIND; return true; } /* PGM - we want them to go ahead and shoot at info_notnulls if they can. */ if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0)) { return false; } } } enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw2(temp); self->ideal_yaw = enemy_yaw; real_enemy_range = realrange(self, self->enemy); if (real_enemy_range <= (MELEE_DISTANCE + 20)) { /* don't always melee in easy mode */ if ((skill->value == SKILL_EASY) && (rand() & 3)) { return false; } if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } if (level.time < self->monsterinfo.attack_finished) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_MELEE) { chance = 0.8; } else if (enemy_range == RANGE_NEAR) { chance = 0.7; } else if (enemy_range == RANGE_MID) { chance = 0.6; } else if (enemy_range == RANGE_FAR) { chance = 0.5; } /* go ahead and shoot every time if it's a info_notnull */ if ((random() < chance) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; return true; } return false; } qboolean widow_blocked(edict_t *self, float dist) { if (!self) { return false; } if (self->monsterinfo.currentmove == &widow_move_run_attack) { self->monsterinfo.aiflags |= AI_TARGET_ANGER; if (self->monsterinfo.checkattack(self)) { self->monsterinfo.attack(self); } else { self->monsterinfo.run(self); } return true; } return false; } void WidowCalcSlots(edict_t *self) { if (!self) { return; } switch ((int)skill->value) { case SKILL_EASY: case SKILL_MEDIUM: self->monsterinfo.monster_slots = 3; break; case SKILL_HARD: self->monsterinfo.monster_slots = 4; break; case SKILL_HARDPLUS: self->monsterinfo.monster_slots = 6; break; default: self->monsterinfo.monster_slots = 3; break; } if (coop->value) { self->monsterinfo.monster_slots = min(6, self->monsterinfo.monster_slots + ((skill->value) * (CountPlayers() - 1))); } } void WidowPrecache() { /* cache in all of the stalker stuff, widow stuff, spawngro stuff, gibs */ gi.soundindex("stalker/pain.wav"); gi.soundindex("stalker/death.wav"); gi.soundindex("stalker/sight.wav"); gi.soundindex("stalker/melee1.wav"); gi.soundindex("stalker/melee2.wav"); gi.soundindex("stalker/idle.wav"); gi.soundindex("tank/tnkatck3.wav"); gi.modelindex("models/proj/laser2/tris.md2"); gi.modelindex("models/monsters/stalker/tris.md2"); gi.modelindex("models/items/spawngro2/tris.md2"); gi.modelindex("models/objects/gibs/sm_metal/tris.md2"); gi.modelindex("models/objects/gibs/gear/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib1/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib2/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib3/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib4/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib1/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib2/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib3/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib4/tris.md2"); gi.modelindex("models/monsters/legs/tris.md2"); gi.soundindex("misc/bwidowbeamout.wav"); gi.soundindex("misc/bigtele.wav"); gi.soundindex("widow/bwstep3.wav"); gi.soundindex("widow/bwstep2.wav"); } /* * QUAKED monster_widow (1 .5 0) (-40 -40 0) (40 40 144) Ambush Trigger_Spawn Sight */ void SP_monster_widow(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("widow/bw1pain1.wav"); sound_pain2 = gi.soundindex("widow/bw1pain2.wav"); sound_pain3 = gi.soundindex("widow/bw1pain3.wav"); sound_search1 = gi.soundindex("bosshovr/bhvunqv1.wav"); sound_rail = gi.soundindex("gladiator/railgun.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/blackwidow/tris.md2"); VectorSet(self->mins, -40, -40, 0); VectorSet(self->maxs, 40, 40, 144); self->health = 2000 + 1000 * (skill->value); if (coop->value) { self->health += 500 * (skill->value); } self->gib_health = -5000; self->mass = 1500; if (skill->value == SKILL_HARDPLUS) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 500; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow_pain; self->die = widow_die; self->monsterinfo.melee = widow_melee; self->monsterinfo.stand = widow_stand; self->monsterinfo.walk = widow_walk; self->monsterinfo.run = widow_run; self->monsterinfo.attack = widow_attack; self->monsterinfo.search = widow_search; self->monsterinfo.checkattack = Widow_CheckAttack; self->monsterinfo.sight = widow_sight; self->monsterinfo.blocked = widow_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &widow_move_stand; self->monsterinfo.scale = MODEL_SCALE; WidowPrecache(); WidowCalcSlots(self); widow_damage_multiplier = 1; walkmonster_start(self); } rogue-ROGUE_2_13/src/monster/widow/widow.h000066400000000000000000000136241477320066100205270ustar00rootroot00000000000000/* ======================================================================= * * Black Widow (stage 1) animations. * * ======================================================================= */ #define FRAME_idle01 0 #define FRAME_idle02 1 #define FRAME_idle03 2 #define FRAME_idle04 3 #define FRAME_idle05 4 #define FRAME_idle06 5 #define FRAME_idle07 6 #define FRAME_idle08 7 #define FRAME_idle09 8 #define FRAME_idle10 9 #define FRAME_idle11 10 #define FRAME_walk01 11 #define FRAME_walk02 12 #define FRAME_walk03 13 #define FRAME_walk04 14 #define FRAME_walk05 15 #define FRAME_walk06 16 #define FRAME_walk07 17 #define FRAME_walk08 18 #define FRAME_walk09 19 #define FRAME_walk10 20 #define FRAME_walk11 21 #define FRAME_walk12 22 #define FRAME_walk13 23 #define FRAME_run01 24 #define FRAME_run02 25 #define FRAME_run03 26 #define FRAME_run04 27 #define FRAME_run05 28 #define FRAME_run06 29 #define FRAME_run07 30 #define FRAME_run08 31 #define FRAME_firea01 32 #define FRAME_firea02 33 #define FRAME_firea03 34 #define FRAME_firea04 35 #define FRAME_firea05 36 #define FRAME_firea06 37 #define FRAME_firea07 38 #define FRAME_firea08 39 #define FRAME_firea09 40 #define FRAME_fireb01 41 #define FRAME_fireb02 42 #define FRAME_fireb03 43 #define FRAME_fireb04 44 #define FRAME_fireb05 45 #define FRAME_fireb06 46 #define FRAME_fireb07 47 #define FRAME_fireb08 48 #define FRAME_fireb09 49 #define FRAME_firec01 50 #define FRAME_firec02 51 #define FRAME_firec03 52 #define FRAME_firec04 53 #define FRAME_firec05 54 #define FRAME_firec06 55 #define FRAME_firec07 56 #define FRAME_firec08 57 #define FRAME_firec09 58 #define FRAME_fired01 59 #define FRAME_fired02 60 #define FRAME_fired02a 61 #define FRAME_fired03 62 #define FRAME_fired04 63 #define FRAME_fired05 64 #define FRAME_fired06 65 #define FRAME_fired07 66 #define FRAME_fired08 67 #define FRAME_fired09 68 #define FRAME_fired10 69 #define FRAME_fired11 70 #define FRAME_fired12 71 #define FRAME_fired13 72 #define FRAME_fired14 73 #define FRAME_fired15 74 #define FRAME_fired16 75 #define FRAME_fired17 76 #define FRAME_fired18 77 #define FRAME_fired19 78 #define FRAME_fired20 79 #define FRAME_fired21 80 #define FRAME_fired22 81 #define FRAME_spawn01 82 #define FRAME_spawn02 83 #define FRAME_spawn03 84 #define FRAME_spawn04 85 #define FRAME_spawn05 86 #define FRAME_spawn06 87 #define FRAME_spawn07 88 #define FRAME_spawn08 89 #define FRAME_spawn09 90 #define FRAME_spawn10 91 #define FRAME_spawn11 92 #define FRAME_spawn12 93 #define FRAME_spawn13 94 #define FRAME_spawn14 95 #define FRAME_spawn15 96 #define FRAME_spawn16 97 #define FRAME_spawn17 98 #define FRAME_spawn18 99 #define FRAME_pain01 100 #define FRAME_pain02 101 #define FRAME_pain03 102 #define FRAME_pain04 103 #define FRAME_pain05 104 #define FRAME_pain06 105 #define FRAME_pain07 106 #define FRAME_pain08 107 #define FRAME_pain09 108 #define FRAME_pain10 109 #define FRAME_pain11 110 #define FRAME_pain12 111 #define FRAME_pain13 112 #define FRAME_pain201 113 #define FRAME_pain202 114 #define FRAME_pain203 115 #define FRAME_transa01 116 #define FRAME_transa02 117 #define FRAME_transa03 118 #define FRAME_transa04 119 #define FRAME_transa05 120 #define FRAME_transb01 121 #define FRAME_transb02 122 #define FRAME_transb03 123 #define FRAME_transb04 124 #define FRAME_transb05 125 #define FRAME_transc01 126 #define FRAME_transc02 127 #define FRAME_transc03 128 #define FRAME_transc04 129 #define FRAME_death01 130 #define FRAME_death02 131 #define FRAME_death03 132 #define FRAME_death04 133 #define FRAME_death05 134 #define FRAME_death06 135 #define FRAME_death07 136 #define FRAME_death08 137 #define FRAME_death09 138 #define FRAME_death10 139 #define FRAME_death11 140 #define FRAME_death12 141 #define FRAME_death13 142 #define FRAME_death14 143 #define FRAME_death15 144 #define FRAME_death16 145 #define FRAME_death17 146 #define FRAME_death18 147 #define FRAME_death19 148 #define FRAME_death20 149 #define FRAME_death21 150 #define FRAME_death22 151 #define FRAME_death23 152 #define FRAME_death24 153 #define FRAME_death25 154 #define FRAME_death26 155 #define FRAME_death27 156 #define FRAME_death28 157 #define FRAME_death29 158 #define FRAME_death30 159 #define FRAME_death31 160 #define FRAME_kick01 161 #define FRAME_kick02 162 #define FRAME_kick03 163 #define FRAME_kick04 164 #define FRAME_kick05 165 #define FRAME_kick06 166 #define FRAME_kick07 167 #define FRAME_kick08 168 #define MODEL_SCALE 2.000000 rogue-ROGUE_2_13/src/monster/widow/widow2.c000066400000000000000000001310601477320066100205770ustar00rootroot00000000000000/* ======================================================================= * * Black Window (stage 2). * * ======================================================================= */ #include "../../header/local.h" #include "widow2.h" #define NUM_STALKERS_SPAWNED 6 /* max # of stalkers she can spawn */ #define DISRUPT_TIME 3 static int sound_pain1; static int sound_pain2; static int sound_pain3; static int sound_death; static int sound_search1; static int sound_tentacles_retract; static vec3_t spawnpoints[] = { {30, 135, 0}, {30, -135, 0} }; static float sweep_angles[] = { -40.0, -32.0, -24.0, -16.0, -8.0, 0.0, 8.0, 16.0, 24.0, 32.0, 40.0 }; extern vec3_t stalker_mins, stalker_maxs; qboolean infront(edict_t *self, edict_t *other); void WidowCalcSlots(edict_t *self); void WidowPowerups(edict_t *self); void widow2_run(edict_t *self); void widow2_stand(edict_t *self); void widow2_dead(edict_t *self); void widow2_attack(edict_t *self); void widow2_attack_beam(edict_t *self); void widow2_reattack_beam(edict_t *self); void widow2_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void widow_start_spawn(edict_t *self); void widow_done_spawn(edict_t *self); void widow2_spawn_check(edict_t *self); void widow2_prep_spawn(edict_t *self); void Widow2SaveBeamTarget(edict_t *self); void widow2_start_searching(edict_t *self); void widow2_keep_searching(edict_t *self); void widow2_finaldeath(edict_t *self); void WidowExplode(edict_t *self); void gib_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); void gib_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); void ThrowWidowGibReal(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, qboolean large, int hitsound, qboolean fade); void ThrowWidowGibSized(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, int hitsound, qboolean fade); void ThrowWidowGibLoc(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, qboolean fade); void WidowExplosion1(edict_t *self); void WidowExplosion2(edict_t *self); void WidowExplosion3(edict_t *self); void WidowExplosion4(edict_t *self); void WidowExplosion5(edict_t *self); void WidowExplosion6(edict_t *self); void WidowExplosion7(edict_t *self); void WidowExplosionLeg(edict_t *self); void ThrowArm1(edict_t *self); void ThrowArm2(edict_t *self); void ClipGibVelocity(edict_t *ent); void showme(edict_t *self); /* these offsets used by the tongue */ static vec3_t offsets[] = { {17.48, 0.10, 68.92}, {17.47, 0.29, 68.91}, {17.45, 0.53, 68.87}, {17.42, 0.78, 68.81}, {17.39, 1.02, 68.75}, {17.37, 1.20, 68.70}, {17.36, 1.24, 68.71}, {17.37, 1.21, 68.72}, }; void pauseme(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags |= AI_HOLD_FRAME; } void widow2_search(edict_t *self) { if (!self) { return; } if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0); } } void Widow2Beam(edict_t *self) { vec3_t forward, right, target; vec3_t start, targ_angles, vec; int flashnum; if (!self) { return; } if ((!self->enemy) || (!self->enemy->inuse)) { return; } AngleVectors(self->s.angles, forward, right, NULL); if ((self->s.frame >= FRAME_fireb05) && (self->s.frame <= FRAME_fireb09)) { /* regular beam attack */ Widow2SaveBeamTarget(self); flashnum = MZ2_WIDOW2_BEAMER_1 + self->s.frame - FRAME_fireb05; G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorCopy(self->pos2, target); target[2] += self->enemy->viewheight - 10; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_heat(self, start, forward, vec3_origin, 10, 50, flashnum); } else if ((self->s.frame >= FRAME_spawn04) && (self->s.frame <= FRAME_spawn14)) { /* sweep */ flashnum = MZ2_WIDOW2_BEAM_SWEEP_1 + self->s.frame - FRAME_spawn04; G_ProjectSource(self->s.origin, monster_flash_offset[flashnum], forward, right, start); VectorSubtract(self->enemy->s.origin, start, target); vectoangles2(target, targ_angles); VectorCopy(self->s.angles, vec); vec[PITCH] += targ_angles[PITCH]; vec[YAW] -= sweep_angles[flashnum - MZ2_WIDOW2_BEAM_SWEEP_1]; AngleVectors(vec, forward, NULL, NULL); monster_fire_heat(self, start, forward, vec3_origin, 10, 50, flashnum); } else { Widow2SaveBeamTarget(self); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_WIDOW2_BEAMER_1], forward, right, start); VectorCopy(self->pos2, target); target[2] += self->enemy->viewheight - 10; VectorSubtract(target, start, forward); VectorNormalize(forward); monster_fire_heat(self, start, forward, vec3_origin, 10, 50, 0); } } void Widow2Spawn(edict_t *self) { vec3_t f, r, u, offset, startpoint, spawnpoint; edict_t *ent, *designated_enemy; int i; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); for (i = 0; i < 2; i++) { VectorCopy(spawnpoints[i], offset); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); if (FindSpawnPoint(startpoint, stalker_mins, stalker_maxs, spawnpoint, 64)) { ent = CreateGroundMonster(spawnpoint, self->s.angles, stalker_mins, stalker_maxs, "monster_stalker", 256); if (!ent) { continue; } self->monsterinfo.monster_used++; ent->monsterinfo.commander = self; ent->nextthink = level.time; ent->think(ent); ent->monsterinfo.aiflags |= AI_SPAWNED_WIDOW | AI_DO_NOT_COUNT | AI_IGNORE_SHOTS; if (!(coop && coop->value)) { designated_enemy = self->enemy; } else { designated_enemy = PickCoopTarget(ent); if (designated_enemy) { /* try to avoid using my enemy */ if (designated_enemy == self->enemy) { designated_enemy = PickCoopTarget(ent); if (designated_enemy) { } else { designated_enemy = self->enemy; } } } else { designated_enemy = self->enemy; } } if ((designated_enemy->inuse) && (designated_enemy->health > 0)) { ent->enemy = designated_enemy; FoundTarget(ent); ent->monsterinfo.attack(ent); } } } } void widow2_spawn_check(edict_t *self) { if (!self) { return; } Widow2Beam(self); Widow2Spawn(self); } void widow2_ready_spawn(edict_t *self) { vec3_t f, r, u, offset, startpoint, spawnpoint; int i; if (!self) { return; } Widow2Beam(self); AngleVectors(self->s.angles, f, r, u); for (i = 0; i < 2; i++) { VectorCopy(spawnpoints[i], offset); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); if (FindSpawnPoint(startpoint, stalker_mins, stalker_maxs, spawnpoint, 64)) { SpawnGrow_Spawn(spawnpoint, 1); } } } static mframe_t widow2_frames_stand[] = { {ai_stand, 0, NULL} }; mmove_t widow2_move_stand = { FRAME_blackwidow3, FRAME_blackwidow3, widow2_frames_stand, NULL }; static mframe_t widow2_frames_walk[] = { {ai_walk, 9.01, NULL}, {ai_walk, 7.55, NULL}, {ai_walk, 7.01, NULL}, {ai_walk, 6.66, NULL}, {ai_walk, 6.20, NULL}, {ai_walk, 5.78, NULL}, {ai_walk, 7.25, NULL}, {ai_walk, 8.37, NULL}, {ai_walk, 10.41, NULL} }; mmove_t widow2_move_walk = { FRAME_walk01, FRAME_walk09, widow2_frames_walk, NULL }; static mframe_t widow2_frames_run[] = { {ai_run, 9.01, NULL}, {ai_run, 7.55, NULL}, {ai_run, 7.01, NULL}, {ai_run, 6.66, NULL}, {ai_run, 6.20, NULL}, {ai_run, 5.78, NULL}, {ai_run, 7.25, NULL}, {ai_run, 8.37, NULL}, {ai_run, 10.41, NULL} }; mmove_t widow2_move_run = { FRAME_walk01, FRAME_walk09, widow2_frames_run, NULL }; static mframe_t widow2_frames_attack_pre_beam[] = { {ai_charge, 4, NULL}, {ai_charge, 4, NULL}, {ai_charge, 4, NULL}, {ai_charge, 4, widow2_attack_beam} }; mmove_t widow2_move_attack_pre_beam = { FRAME_fireb01, FRAME_fireb04, widow2_frames_attack_pre_beam, NULL }; /* Loop this */ static mframe_t widow2_frames_attack_beam[] = { {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, widow2_reattack_beam} }; mmove_t widow2_move_attack_beam = { FRAME_fireb05, FRAME_fireb09, widow2_frames_attack_beam, NULL }; static mframe_t widow2_frames_attack_post_beam[] = { {ai_charge, 4, NULL}, {ai_charge, 4, NULL}, {ai_charge, 4, NULL} }; mmove_t widow2_move_attack_post_beam = { FRAME_fireb06, FRAME_fireb07, widow2_frames_attack_post_beam, widow2_run }; void WidowDisrupt(edict_t *self) { vec3_t start; vec3_t dir; vec3_t forward, right; float len; if (!self) { return; } AngleVectors(self->s.angles, forward, right, NULL); G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_WIDOW_DISRUPTOR], forward, right, start); VectorSubtract(self->pos1, self->enemy->s.origin, dir); len = VectorLength(dir); if (len < 30) { VectorSubtract(self->pos1, start, dir); VectorNormalize(dir); monster_fire_tracker(self, start, dir, 20, 500, self->enemy, MZ2_WIDOW_DISRUPTOR); } else { PredictAim(self->enemy, start, 1200, true, 0, dir, NULL); monster_fire_tracker(self, start, dir, 20, 1200, NULL, MZ2_WIDOW_DISRUPTOR); } } void Widow2SaveDisruptLoc(edict_t *self) { if (!self) { return; } if (self->enemy && self->enemy->inuse) { VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ self->pos1[2] += self->enemy->viewheight; } else { VectorCopy(vec3_origin, self->pos1); } } void widow2_disrupt_reattack(edict_t *self) { float luck; if (!self) { return; } luck = random(); if (luck < (0.25 + ((float)(skill->value)) * 0.15)) { self->monsterinfo.nextframe = FRAME_firea01; } } static mframe_t widow2_frames_attack_disrupt[] = { {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, Widow2SaveDisruptLoc}, {ai_charge, -20, WidowDisrupt}, {ai_charge, 2, NULL}, {ai_charge, 2, NULL}, {ai_charge, 2, widow2_disrupt_reattack} }; mmove_t widow2_move_attack_disrupt = { FRAME_firea01, FRAME_firea07, widow2_frames_attack_disrupt, widow2_run }; void Widow2SaveBeamTarget(edict_t *self) { if (!self) { return; } if (self->enemy && self->enemy->inuse) { VectorCopy(self->pos1, self->pos2); VectorCopy(self->enemy->s.origin, self->pos1); /* save for aiming the shot */ } else { VectorCopy(vec3_origin, self->pos1); VectorCopy(vec3_origin, self->pos2); } } void Widow2BeamTargetRemove(edict_t *self) { if (!self) { return; } VectorCopy(vec3_origin, self->pos1); VectorCopy(vec3_origin, self->pos2); } void Widow2StartSweep(edict_t *self) { if (!self) { return; } Widow2SaveBeamTarget(self); } static mframe_t widow2_frames_spawn[] = { {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow_start_spawn}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, /* 5 */ {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, widow2_ready_spawn}, /* 10 */ {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, Widow2Beam}, {ai_charge, 0, widow2_spawn_check}, {ai_charge, 0, NULL}, /* 15 */ {ai_charge, 0, NULL}, {ai_charge, 0, NULL}, {ai_charge, 0, widow2_reattack_beam} }; mmove_t widow2_move_spawn = { FRAME_spawn01, FRAME_spawn18, widow2_frames_spawn, NULL }; qboolean widow2_tongue_attack_ok(vec3_t start, vec3_t end, float range) { vec3_t dir, angles; /* check for max distance */ VectorSubtract(start, end, dir); if (VectorLength(dir) > range) { return false; } /* check for min/max pitch */ vectoangles(dir, angles); if (angles[0] < -180) { angles[0] += 360; } if (fabs(angles[0]) > 30) { return false; } return true; } void Widow2Tongue(edict_t *self) { vec3_t f, r, u; vec3_t start, end, dir; trace_t tr; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offsets[self->s.frame - FRAME_tongs01], f, r, u, start); VectorCopy(self->enemy->s.origin, end); if (!widow2_tongue_attack_ok(start, end, 256)) { end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; if (!widow2_tongue_attack_ok(start, end, 256)) { end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; if (!widow2_tongue_attack_ok(start, end, 256)) { return; } } } VectorCopy(self->enemy->s.origin, end); tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); if (tr.ent != self->enemy) { return; } gi.sound(self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_PARASITE_ATTACK); gi.WriteShort(self - g_edicts); gi.WritePosition(start); gi.WritePosition(end); gi.multicast(self->s.origin, MULTICAST_PVS); VectorSubtract(start, end, dir); T_Damage(self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, 2, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); } void Widow2TonguePull(edict_t *self) { vec3_t vec; vec3_t f, r, u; vec3_t start, end; if (!self) { return; } if ((!self->enemy) || (!self->enemy->inuse)) { self->monsterinfo.run(self); return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offsets[self->s.frame - FRAME_tongs01], f, r, u, start); VectorCopy(self->enemy->s.origin, end); if (!widow2_tongue_attack_ok(start, end, 256)) { return; } if (self->enemy->groundentity) { self->enemy->s.origin[2] += 1; self->enemy->groundentity = NULL; } VectorSubtract(self->s.origin, self->enemy->s.origin, vec); if (self->enemy->client) { VectorNormalize(vec); VectorMA(self->enemy->velocity, 1000, vec, self->enemy->velocity); } else { self->enemy->ideal_yaw = vectoyaw(vec); M_ChangeYaw(self->enemy); VectorScale(f, 1000, self->enemy->velocity); } } void Widow2Crunch(edict_t *self) { vec3_t aim; if (!self) { return; } if ((!self->enemy) || (!self->enemy->inuse)) { self->monsterinfo.run(self); return; } Widow2TonguePull(self); /* 70 + 32 */ VectorSet(aim, 150, 0, 4); if (self->s.frame != FRAME_tongs07) { fire_hit(self, aim, 20 + (rand() % 6), 0); } else { if (self->enemy->groundentity) { fire_hit(self, aim, (20 + (rand() % 6)), 500); } else /* not as much kick if they're in the air .. makes it harder to land on her head */ { fire_hit(self, aim, (20 + (rand() % 6)), 250); } } } void Widow2Toss(edict_t *self) { if (!self) { return; } self->timestamp = level.time + 3; return; } static mframe_t widow2_frames_tongs[] = { {ai_charge, 0, Widow2Tongue}, {ai_charge, 0, Widow2Tongue}, {ai_charge, 0, Widow2Tongue}, {ai_charge, 0, Widow2TonguePull}, {ai_charge, 0, Widow2TonguePull}, /* 5 */ {ai_charge, 0, Widow2TonguePull}, {ai_charge, 0, Widow2Crunch}, {ai_charge, 0, Widow2Toss} }; mmove_t widow2_move_tongs = { FRAME_tongs01, FRAME_tongs08, widow2_frames_tongs, widow2_run }; static mframe_t widow2_frames_pain[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL} }; mmove_t widow2_move_pain = { FRAME_pain01, FRAME_pain05, widow2_frames_pain, widow2_run }; static mframe_t widow2_frames_death[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion1}, /* 3 boom */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 5 */ {ai_move, 0, WidowExplosion2}, /* 6 boom */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 10 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 12 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 15 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion3}, /* 18 */ {ai_move, 0, NULL}, /* 19 */ {ai_move, 0, NULL}, /* 20 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion4}, /* 25 */ {ai_move, 0, NULL}, /* 26 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion5}, {ai_move, 0, WidowExplosionLeg}, /* 30 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion6}, {ai_move, 0, NULL}, /* 35 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplosion7}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, /* 40 */ {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, WidowExplode} /* 44 */ }; mmove_t widow2_move_death = { FRAME_death01, FRAME_death44, widow2_frames_death, NULL }; static mframe_t widow2_frames_dead[] = { {ai_move, 0, widow2_start_searching}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, widow2_keep_searching} }; mmove_t widow2_move_dead = { FRAME_dthsrh01, FRAME_dthsrh15, widow2_frames_dead, NULL }; static mframe_t widow2_frames_really_dead[] = { {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, NULL}, {ai_move, 0, widow2_finaldeath} }; mmove_t widow2_move_really_dead = { FRAME_dthsrh16, FRAME_dthsrh22, widow2_frames_really_dead, NULL }; void widow2_start_searching(edict_t *self) { if (!self) { return; } self->count = 0; } void widow2_keep_searching(edict_t *self) { if (!self) { return; } if (self->count <= 2) { self->monsterinfo.currentmove = &widow2_move_dead; self->s.frame = FRAME_dthsrh01; self->count++; return; } self->monsterinfo.currentmove = &widow2_move_really_dead; } void widow2_finaldeath(edict_t *self) { if (!self) { return; } VectorSet(self->mins, -70, -70, 0); VectorSet(self->maxs, 70, 70, 80); self->movetype = MOVETYPE_TOSS; self->takedamage = DAMAGE_YES; self->nextthink = 0; gi.linkentity(self); } void widow2_stand(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow2_move_stand; } void widow2_run(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &widow2_move_stand; } else { self->monsterinfo.currentmove = &widow2_move_run; } } void widow2_walk(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow2_move_walk; } void widow2_melee(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow2_move_tongs; } void widow2_attack(edict_t *self) { float range, luck; qboolean blocked = false; if (!self) { return; } if (self->monsterinfo.aiflags & AI_BLOCKED) { blocked = true; self->monsterinfo.aiflags &= ~AI_BLOCKED; } if (!self->enemy) { return; } if (self->bad_area) { if ((random() < 0.75) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } return; } WidowCalcSlots(self); /* if we can't see the target, spawn stuff */ if ((self->monsterinfo.attack_state == AS_BLIND) && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow2_move_spawn; return; } /* accept bias towards spawning */ if (blocked && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow2_move_spawn; return; } range = realrange(self, self->enemy); if (range < 600) { luck = random(); if (SELF_SLOTS_LEFT >= 2) { if (luck <= 0.40) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else if ((luck <= 0.7) && !(level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } else { self->monsterinfo.currentmove = &widow2_move_spawn; } } else { if ((luck <= 0.50) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } } else { luck = random(); if (SELF_SLOTS_LEFT >= 2) { if (luck < 0.3) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else if ((luck < 0.65) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_spawn; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } else { if ((luck < 0.45) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } } } void widow2_attack_beam(edict_t *self) { if (!self) { return; } self->monsterinfo.currentmove = &widow2_move_attack_beam; } void widow2_reattack_beam(edict_t *self) { if (!self) { return; } self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; if (infront(self, self->enemy)) { if (random() <= 0.5) { if ((random() < 0.7) || (SELF_SLOTS_LEFT < 2)) { self->monsterinfo.currentmove = &widow2_move_attack_beam; } else { self->monsterinfo.currentmove = &widow2_move_spawn; } } else { self->monsterinfo.currentmove = &widow2_move_attack_post_beam; } } else { self->monsterinfo.currentmove = &widow2_move_attack_post_beam; } } void widow2_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage) { if (!self) { return; } if (self->health < (self->max_health / 2)) { self->s.skinnum = 1; } if (skill->value == SKILL_HARDPLUS) { return; /* no pain anims in nightmare */ } if (level.time < self->pain_debounce_time) { return; } self->pain_debounce_time = level.time + 5; if (damage < 15) { gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); } else if (damage < 75) { gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); if ((skill->value < SKILL_HARDPLUS) && (random() < (0.6 - (0.2 * ((float)skill->value))))) { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.currentmove = &widow2_move_pain; } } else { gi.sound(self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); if ((skill->value < SKILL_HARDPLUS) && (random() < (0.75 - (0.1 * ((float)skill->value))))) { self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; self->monsterinfo.currentmove = &widow2_move_pain; } } } void widow2_dead(edict_t *self) { } void KillChildren(edict_t *self) { edict_t *ent; int field; if (!self) { return; } ent = NULL; field = FOFS(classname); while (1) { ent = G_Find(ent, field, "monster_stalker"); if (!ent) { return; } if ((ent->inuse) && (ent->health > 0)) { T_Damage(ent, self, self, vec3_origin, self->enemy->s.origin, vec3_origin, (ent->health + 1), 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); } } } void widow2_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; int clipped; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { clipped = min(damage, 100); gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/bone/tris.md2", clipped, GIB_ORGANIC, NULL, false); } for (n = 0; n < 3; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", clipped, GIB_ORGANIC, NULL, false); } for (n = 0; n < 3; n++) { ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib1/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib2/tris.md2", clipped, GIB_METALLIC, NULL, gi.soundindex("misc/fhit3.wav"), false); } for (n = 0; n < 2; n++) { ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib3/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib3/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", clipped, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/head2/tris.md2", clipped, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; KillChildren(self); self->monsterinfo.quad_framenum = 0; self->monsterinfo.double_framenum = 0; self->monsterinfo.invincible_framenum = 0; self->monsterinfo.currentmove = &widow2_move_death; } qboolean Widow2_CheckAttack(edict_t *self) { vec3_t spot1, spot2; vec3_t temp; float chance = 0; trace_t tr; int enemy_range; float enemy_yaw; float real_enemy_range; vec3_t f, r, u; if (!self) { return false; } if (!self->enemy) { return false; } WidowPowerups(self); if ((random() < 0.8) && (SELF_SLOTS_LEFT >= 2) && (realrange(self, self->enemy) > 150)) { self->monsterinfo.aiflags |= AI_BLOCKED; self->monsterinfo.attack_state = AS_MISSILE; return true; } if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(self->enemy->s.origin, spot2); spot2[2] += self->enemy->viewheight; tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA); /* do we have a clear shot? */ if (tr.ent != self->enemy) { /* go ahead and spawn stuff if we're mad a a client */ if (self->enemy->client && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.attack_state = AS_BLIND; return true; } if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0)) { return false; } } } enemy_range = range(self, self->enemy); VectorSubtract(self->enemy->s.origin, self->s.origin, temp); enemy_yaw = vectoyaw2(temp); self->ideal_yaw = enemy_yaw; /* melee attack */ if (self->timestamp < level.time) { real_enemy_range = realrange(self, self->enemy); if (real_enemy_range < 300) { AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offsets[0], f, r, u, spot1); VectorCopy(self->enemy->s.origin, spot2); if (widow2_tongue_attack_ok(spot1, spot2, 256)) { /* be nice in easy mode */ if ((skill->value == SKILL_EASY) && (rand() & 3)) { return false; } if (self->monsterinfo.melee) { self->monsterinfo.attack_state = AS_MELEE; } else { self->monsterinfo.attack_state = AS_MISSILE; } return true; } } } if (level.time < self->monsterinfo.attack_finished) { return false; } if (self->monsterinfo.aiflags & AI_STAND_GROUND) { chance = 0.4; } else if (enemy_range == RANGE_NEAR) { chance = 0.8; } else if (enemy_range == RANGE_MID) { chance = 0.8; } else if (enemy_range == RANGE_FAR) { chance = 0.5; } if ((random() < chance) || (self->enemy->solid == SOLID_NOT)) { self->monsterinfo.attack_state = AS_MISSILE; return true; } return false; } void Widow2Precache() { /* cache in all of the stalker stuff, widow stuff, spawngro stuff, gibs */ gi.soundindex("parasite/parpain1.wav"); gi.soundindex("parasite/parpain2.wav"); gi.soundindex("parasite/pardeth1.wav"); gi.soundindex("parasite/paratck1.wav"); gi.soundindex("parasite/parsght1.wav"); gi.soundindex("infantry/melee2.wav"); gi.soundindex("misc/fhit3.wav"); gi.soundindex("tank/tnkatck3.wav"); gi.soundindex("weapons/disrupt.wav"); gi.soundindex("weapons/disint2.wav"); gi.modelindex("models/monsters/stalker/tris.md2"); gi.modelindex("models/items/spawngro2/tris.md2"); gi.modelindex("models/objects/gibs/sm_metal/tris.md2"); gi.modelindex("models/proj/laser2/tris.md2"); gi.modelindex("models/proj/disintegrator/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib1/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib2/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib3/tris.md2"); gi.modelindex("models/monsters/blackwidow/gib4/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib1/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib2/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib3/tris.md2"); gi.modelindex("models/monsters/blackwidow2/gib4/tris.md2"); } /* * QUAKED monster_widow2 (1 .5 0) (-70 -70 0) (70 70 144) Ambush Trigger_Spawn Sight */ void SP_monster_widow2(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("widow/bw2pain1.wav"); sound_pain2 = gi.soundindex("widow/bw2pain2.wav"); sound_pain3 = gi.soundindex("widow/bw2pain3.wav"); sound_death = gi.soundindex("widow/death.wav"); sound_search1 = gi.soundindex("bosshovr/bhvunqv1.wav"); sound_tentacles_retract = gi.soundindex("brain/brnatck3.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/blackwidow2/tris.md2"); VectorSet(self->mins, -70, -70, 0); VectorSet(self->maxs, 70, 70, 144); self->health = 2000 + 800 + 1000 * (skill->value); if (coop->value) { self->health += 500 * (skill->value); } self->gib_health = -900; self->mass = 2500; if (skill->value == SKILL_HARDPLUS) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 750; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow2_pain; self->die = widow2_die; self->monsterinfo.melee = widow2_melee; self->monsterinfo.stand = widow2_stand; self->monsterinfo.walk = widow2_walk; self->monsterinfo.run = widow2_run; self->monsterinfo.attack = widow2_attack; self->monsterinfo.search = widow2_search; self->monsterinfo.checkattack = Widow2_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &widow2_move_stand; self->monsterinfo.scale = MODEL_SCALE; Widow2Precache(); WidowCalcSlots(self); walkmonster_start(self); } void WidowVelocityForDamage(int damage, vec3_t v) { v[0] = damage * crandom(); v[1] = damage * crandom(); v[2] = damage * crandom() + 200.0; } void widow_gib_touch(edict_t *self, edict_t *other /* unused */, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self) { return; } self->solid = SOLID_NOT; self->touch = NULL; self->s.angles[PITCH] = 0; self->s.angles[ROLL] = 0; VectorClear(self->avelocity); if (self->plat2flags) { gi.sound(self, CHAN_VOICE, self->plat2flags, 1, ATTN_NORM, 0); } } void ThrowWidowGib(edict_t *self, char *gibname, int damage, int type) { if (!self || !gibname) { return; } ThrowWidowGibReal(self, gibname, damage, type, NULL, false, 0, true); } void ThrowWidowGibLoc(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, qboolean fade) { if (!self || !gibname) { return; } ThrowWidowGibReal(self, gibname, damage, type, startpos, false, 0, fade); } void ThrowWidowGibSized(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, int hitsound, qboolean fade) { if (!self || !gibname) { return; } ThrowWidowGibReal(self, gibname, damage, type, startpos, true, hitsound, fade); } void ThrowWidowGibReal(edict_t *self, char *gibname, int damage, int type, vec3_t startpos, qboolean sized, int hitsound, qboolean fade) { edict_t *gib; vec3_t vd; vec3_t origin; vec3_t size; float vscale; if (!self || !gibname) { return; } gib = G_Spawn(); if (startpos) { VectorCopy(startpos, gib->s.origin); } else { VectorScale(self->size, 0.5, size); VectorAdd(self->absmin, size, origin); gib->s.origin[0] = origin[0] + crandom() * size[0]; gib->s.origin[1] = origin[1] + crandom() * size[1]; gib->s.origin[2] = origin[2] + crandom() * size[2]; } gib->solid = SOLID_NOT; gib->s.effects |= EF_GIB; gib->flags |= FL_NO_KNOCKBACK; gib->takedamage = DAMAGE_YES; gib->die = gib_die; gib->s.renderfx |= RF_IR_VISIBLE; if (fade) { gib->think = G_FreeEdict; /* sized gibs last longer */ if (sized) { gib->nextthink = level.time + 20 + random() * 15; } else { gib->nextthink = level.time + 5 + random() * 10; } } else { gib->think = G_FreeEdict; /* sized gibs last longer */ if (sized) { gib->nextthink = level.time + 60 + random() * 15; } else { gib->nextthink = level.time + 25 + random() * 10; } } if (type == GIB_ORGANIC) { gib->movetype = MOVETYPE_TOSS; gib->touch = gib_touch; vscale = 0.5; } else { gib->movetype = MOVETYPE_BOUNCE; vscale = 1.0; } WidowVelocityForDamage(damage, vd); VectorMA(self->velocity, vscale, vd, gib->velocity); ClipGibVelocity(gib); gi.setmodel(gib, gibname); if (sized) { gib->plat2flags = hitsound; gib->solid = SOLID_BBOX; gib->avelocity[0] = random() * 400; gib->avelocity[1] = random() * 400; gib->avelocity[2] = random() * 200; if (gib->velocity[2] < 0) { gib->velocity[2] *= -1; } gib->velocity[0] *= 2; gib->velocity[1] *= 2; ClipGibVelocity(gib); gib->velocity[2] = max((350 + (random() * 100.0)), gib->velocity[2]); gib->gravity = 0.25; gib->touch = widow_gib_touch; gib->owner = self; if (gib->s.modelindex == gi.modelindex("models/monsters/blackwidow2/gib2/tris.md2")) { VectorSet(gib->mins, -10, -10, 0); VectorSet(gib->maxs, 10, 10, 10); } else { VectorSet(gib->mins, -5, -5, 0); VectorSet(gib->maxs, 5, 5, 5); } } else { gib->velocity[0] *= 2; gib->velocity[1] *= 2; gib->avelocity[0] = random() * 600; gib->avelocity[1] = random() * 600; gib->avelocity[2] = random() * 600; } gi.linkentity(gib); } void ThrowSmallStuff(edict_t *self, vec3_t point) { int n; if (!self) { return; } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, point, false); } ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, point, false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, point, false); } void ThrowMoreStuff(edict_t *self, vec3_t point) { int n; if (!self) { return; } if (coop && coop->value) { ThrowSmallStuff(self, point); return; } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, point, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, point, false); } for (n = 0; n < 3; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, point, false); } } void WidowExplode(edict_t *self) { vec3_t org; int n; if (!self) { return; } self->think = WidowExplode; VectorCopy(self->s.origin, org); org[2] += 24 + (rand() & 15); if (self->count < 8) { org[2] += 24 + (rand() & 31); } switch (self->count) { case 0: org[0] -= 24; org[1] -= 24; break; case 1: org[0] += 24; org[1] += 24; ThrowSmallStuff(self, org); break; case 2: org[0] += 24; org[1] -= 24; break; case 3: org[0] -= 24; org[1] += 24; ThrowMoreStuff(self, org); break; case 4: org[0] -= 48; org[1] -= 48; break; case 5: org[0] += 48; org[1] += 48; ThrowArm1(self); break; case 6: org[0] -= 48; org[1] += 48; ThrowArm2(self); break; case 7: org[0] += 48; org[1] -= 48; ThrowSmallStuff(self, org); break; case 8: org[0] += 18; org[1] += 18; org[2] = self->s.origin[2] + 48; ThrowMoreStuff(self, org); break; case 9: org[0] -= 18; org[1] += 18; org[2] = self->s.origin[2] + 48; break; case 10: org[0] += 18; org[1] -= 18; org[2] = self->s.origin[2] + 48; break; case 11: org[0] -= 18; org[1] -= 18; org[2] = self->s.origin[2] + 48; break; case 12: self->s.sound = 0; for (n = 0; n < 1; n++) { ThrowWidowGib(self, "models/objects/gibs/sm_meat/tris.md2", 400, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowWidowGib(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC); } for (n = 0; n < 2; n++) { ThrowWidowGib(self, "models/objects/gibs/sm_metal/tris.md2", 400, GIB_METALLIC); } self->deadflag = DEAD_DEAD; self->think = monster_think; self->nextthink = level.time + 0.1; self->monsterinfo.currentmove = &widow2_move_dead; return; } self->count++; if ((self->count >= 9) && (self->count <= 12)) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1_BIG); gi.WritePosition(org); gi.multicast(self->s.origin, MULTICAST_ALL); } else { gi.WriteByte(svc_temp_entity); if (self->count % 2) { gi.WriteByte(TE_EXPLOSION1); } else { gi.WriteByte(TE_EXPLOSION1_NP); } gi.WritePosition(org); gi.multicast(self->s.origin, MULTICAST_ALL); } self->nextthink = level.time + 0.1; } void WidowExplosion1(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {23.74, -37.67, 76.96}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion2(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {-20.49, 36.92, 73.52}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion3(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {2.11, 0.05, 92.20}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion4(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {-28.04, -35.57, -77.56}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion5(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {-20.11, -1.11, 40.76}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion6(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {-20.11, -1.11, 40.76}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosion7(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset = {-20.11, -1.11, 40.76}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } for (n = 0; n < 1; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 300, GIB_METALLIC, startpoint, false); } } void WidowExplosionLeg(edict_t *self) { vec3_t f, r, u, startpoint; vec3_t offset1 = {-31.89, -47.86, 67.02}; vec3_t offset2 = {-44.9, -82.14, 54.72}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset1, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1_BIG); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib2/tris.md2", 200, GIB_METALLIC, startpoint, gi.soundindex("misc/fhit3.wav"), false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); G_ProjectSource2(self->s.origin, offset2, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib1/tris.md2", 300, GIB_METALLIC, startpoint, gi.soundindex("misc/fhit3.wav"), false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } void ThrowArm1(edict_t *self) { int n; vec3_t f, r, u, startpoint; vec3_t offset1 = {65.76, 17.52, 7.56}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset1, f, r, u, startpoint); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION1_BIG); gi.WritePosition(startpoint); gi.multicast(self->s.origin, MULTICAST_ALL); for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_metal/tris.md2", 100, GIB_METALLIC, startpoint, false); } } void ThrowArm2(edict_t *self) { vec3_t f, r, u, startpoint; vec3_t offset1 = {65.76, 17.52, 7.56}; if (!self) { return; } AngleVectors(self->s.angles, f, r, u); G_ProjectSource2(self->s.origin, offset1, f, r, u, startpoint); ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib4/tris.md2", 200, GIB_METALLIC, startpoint, gi.soundindex("misc/fhit3.wav"), false); ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", 300, GIB_ORGANIC, startpoint, false); } rogue-ROGUE_2_13/src/monster/widow/widow2.h000066400000000000000000000106631477320066100206110ustar00rootroot00000000000000/* ======================================================================= * * Black Widow (stage 2) animations. * * ======================================================================= */ #define FRAME_blackwidow3 0 #define FRAME_walk01 1 #define FRAME_walk02 2 #define FRAME_walk03 3 #define FRAME_walk04 4 #define FRAME_walk05 5 #define FRAME_walk06 6 #define FRAME_walk07 7 #define FRAME_walk08 8 #define FRAME_walk09 9 #define FRAME_spawn01 10 #define FRAME_spawn02 11 #define FRAME_spawn03 12 #define FRAME_spawn04 13 #define FRAME_spawn05 14 #define FRAME_spawn06 15 #define FRAME_spawn07 16 #define FRAME_spawn08 17 #define FRAME_spawn09 18 #define FRAME_spawn10 19 #define FRAME_spawn11 20 #define FRAME_spawn12 21 #define FRAME_spawn13 22 #define FRAME_spawn14 23 #define FRAME_spawn15 24 #define FRAME_spawn16 25 #define FRAME_spawn17 26 #define FRAME_spawn18 27 #define FRAME_firea01 28 #define FRAME_firea02 29 #define FRAME_firea03 30 #define FRAME_firea04 31 #define FRAME_firea05 32 #define FRAME_firea06 33 #define FRAME_firea07 34 #define FRAME_fireb01 35 #define FRAME_fireb02 36 #define FRAME_fireb03 37 #define FRAME_fireb04 38 #define FRAME_fireb05 39 #define FRAME_fireb06 40 #define FRAME_fireb07 41 #define FRAME_fireb08 42 #define FRAME_fireb09 43 #define FRAME_fireb10 44 #define FRAME_fireb11 45 #define FRAME_fireb12 46 #define FRAME_tongs01 47 #define FRAME_tongs02 48 #define FRAME_tongs03 49 #define FRAME_tongs04 50 #define FRAME_tongs05 51 #define FRAME_tongs06 52 #define FRAME_tongs07 53 #define FRAME_tongs08 54 #define FRAME_pain01 55 #define FRAME_pain02 56 #define FRAME_pain03 57 #define FRAME_pain04 58 #define FRAME_pain05 59 #define FRAME_death01 60 #define FRAME_death02 61 #define FRAME_death03 62 #define FRAME_death04 63 #define FRAME_death05 64 #define FRAME_death06 65 #define FRAME_death07 66 #define FRAME_death08 67 #define FRAME_death09 68 #define FRAME_death10 69 #define FRAME_death11 70 #define FRAME_death12 71 #define FRAME_death13 72 #define FRAME_death14 73 #define FRAME_death15 74 #define FRAME_death16 75 #define FRAME_death17 76 #define FRAME_death18 77 #define FRAME_death19 78 #define FRAME_death20 79 #define FRAME_death21 80 #define FRAME_death22 81 #define FRAME_death23 82 #define FRAME_death24 83 #define FRAME_death25 84 #define FRAME_death26 85 #define FRAME_death27 86 #define FRAME_death28 87 #define FRAME_death29 88 #define FRAME_death30 89 #define FRAME_death31 90 #define FRAME_death32 91 #define FRAME_death33 92 #define FRAME_death34 93 #define FRAME_death35 94 #define FRAME_death36 95 #define FRAME_death37 96 #define FRAME_death38 97 #define FRAME_death39 98 #define FRAME_death40 99 #define FRAME_death41 100 #define FRAME_death42 101 #define FRAME_death43 102 #define FRAME_death44 103 #define FRAME_dthsrh01 104 #define FRAME_dthsrh02 105 #define FRAME_dthsrh03 106 #define FRAME_dthsrh04 107 #define FRAME_dthsrh05 108 #define FRAME_dthsrh06 109 #define FRAME_dthsrh07 110 #define FRAME_dthsrh08 111 #define FRAME_dthsrh09 112 #define FRAME_dthsrh10 113 #define FRAME_dthsrh11 114 #define FRAME_dthsrh12 115 #define FRAME_dthsrh13 116 #define FRAME_dthsrh14 117 #define FRAME_dthsrh15 118 #define FRAME_dthsrh16 119 #define FRAME_dthsrh17 120 #define FRAME_dthsrh18 121 #define FRAME_dthsrh19 122 #define FRAME_dthsrh20 123 #define FRAME_dthsrh21 124 #define FRAME_dthsrh22 125 #define MODEL_SCALE 2.000000 rogue-ROGUE_2_13/src/player/000077500000000000000000000000001477320066100156735ustar00rootroot00000000000000rogue-ROGUE_2_13/src/player/client.c000066400000000000000000001362621477320066100173270ustar00rootroot00000000000000/* ======================================================================= * * Interface between client <-> game and client calculations. * * ======================================================================= */ #include "../header/local.h" #include "../monster/misc/player.h" edict_t *pm_passent; void ClientUserinfoChanged(edict_t *ent, char *userinfo); void SP_misc_teleporter_dest(edict_t *ent); void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); /* * QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32) * * The normal starting point for a level. */ void SP_info_player_start(edict_t *self) { if (!self) { return; } if (!coop->value) { return; } } /* * QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32) * * potential spawning position for deathmatch games */ void SP_info_player_deathmatch(edict_t *self) { if (!self) { return; } if (!deathmatch->value) { G_FreeEdict(self); return; } SP_misc_teleporter_dest(self); } /* * QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32) * potential spawning position for coop games */ void SP_info_player_coop(edict_t *self) { if (!self) { return; } if (!coop->value) { G_FreeEdict(self); return; } } /* * QUAKED info_player_coop_lava (1 0 1) (-16 -16 -24) (16 16 32) * * potential spawning position for coop games on rmine2 where lava level * needs to be checked */ void SP_info_player_coop_lava(edict_t *self) { if (!self) { return; } if (!coop->value) { G_FreeEdict(self); return; } } /* * QUAKED info_player_intermission (1 0 1) (-16 -16 -24) (16 16 32) * * The deathmatch intermission point will be at one of these * Use 'angles' instead of 'angle', so you can set pitch or roll * as well as yaw. 'pitch yaw roll' */ void SP_info_player_intermission(edict_t *ent) { } /* ======================================================================= */ void player_pain(edict_t *self, edict_t *other, float kick, int damage) { } qboolean IsFemale(edict_t *ent) { char *info; if (!ent) { return false; } if (!ent->client) { return false; } info = Info_ValueForKey(ent->client->pers.userinfo, "gender"); if ((info[0] == 'f') || (info[0] == 'F')) { return true; } return false; } qboolean IsNeutral(edict_t *ent) { char *info; if (!ent) { return false; } if (!ent->client) { return false; } info = Info_ValueForKey(ent->client->pers.userinfo, "gender"); if ((info[0] != 'f') && (info[0] != 'F') && (info[0] != 'm') && (info[0] != 'M')) { return true; } return false; } void ClientObituary(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker) { int mod; char *message; char *message2; qboolean ff; if (!self || !attacker) { return; } if (coop->value && attacker->client) { meansOfDeath |= MOD_FRIENDLY_FIRE; } if (deathmatch->value || coop->value) { ff = meansOfDeath & MOD_FRIENDLY_FIRE; mod = meansOfDeath & ~MOD_FRIENDLY_FIRE; message = NULL; message2 = ""; switch (mod) { case MOD_SUICIDE: message = "suicides"; break; case MOD_FALLING: message = "cratered"; break; case MOD_CRUSH: message = "was squished"; break; case MOD_WATER: message = "sank like a rock"; break; case MOD_SLIME: message = "melted"; break; case MOD_LAVA: message = "does a back flip into the lava"; break; case MOD_EXPLOSIVE: case MOD_BARREL: message = "blew up"; break; case MOD_EXIT: message = "found a way out"; break; case MOD_TARGET_LASER: message = "saw the light"; break; case MOD_TARGET_BLASTER: message = "got blasted"; break; case MOD_BOMB: case MOD_SPLASH: case MOD_TRIGGER_HURT: message = "was in the wrong place"; break; default: break; } if (attacker == self) { switch (mod) { case MOD_HELD_GRENADE: message = "tried to put the pin back in"; break; case MOD_HG_SPLASH: case MOD_G_SPLASH: if (IsNeutral(self)) { message = "tripped on its own grenade"; } else if (IsFemale(self)) { message = "tripped on her own grenade"; } else { message = "tripped on his own grenade"; } break; case MOD_R_SPLASH: if (IsNeutral(self)) { message = "blew itself up"; } else if (IsFemale(self)) { message = "blew herself up"; } else { message = "blew himself up"; } break; case MOD_BFG_BLAST: message = "should have used a smaller gun"; break; case MOD_DOPPLE_EXPLODE: if (IsNeutral(self)) { message = "got caught in it's own trap"; } else if (IsFemale(self)) { message = "got caught in her own trap"; } else { message = "got caught in his own trap"; } break; default: if (IsNeutral(self)) { message = "killed itself"; } else if (IsFemale(self)) { message = "killed herself"; } else { message = "killed himself"; } break; } } if (message) { gi.bprintf(PRINT_MEDIUM, "%s %s.\n", self->client->pers.netname, message); if (deathmatch->value) { self->client->resp.score--; } self->enemy = NULL; return; } self->enemy = attacker; if (attacker->client) { switch (mod) { case MOD_BLASTER: message = "was blasted by"; break; case MOD_SHOTGUN: message = "was gunned down by"; break; case MOD_SSHOTGUN: message = "was blown away by"; message2 = "'s super shotgun"; break; case MOD_MACHINEGUN: message = "was machinegunned by"; break; case MOD_CHAINGUN: message = "was cut in half by"; message2 = "'s chaingun"; break; case MOD_GRENADE: message = "was popped by"; message2 = "'s grenade"; break; case MOD_G_SPLASH: message = "was shredded by"; message2 = "'s shrapnel"; break; case MOD_ROCKET: message = "ate"; message2 = "'s rocket"; break; case MOD_R_SPLASH: message = "almost dodged"; message2 = "'s rocket"; break; case MOD_HYPERBLASTER: message = "was melted by"; message2 = "'s hyperblaster"; break; case MOD_RAILGUN: message = "was railed by"; break; case MOD_BFG_LASER: message = "saw the pretty lights from"; message2 = "'s BFG"; break; case MOD_BFG_BLAST: message = "was disintegrated by"; message2 = "'s BFG blast"; break; case MOD_BFG_EFFECT: message = "couldn't hide from"; message2 = "'s BFG"; break; case MOD_HANDGRENADE: message = "caught"; message2 = "'s handgrenade"; break; case MOD_HG_SPLASH: message = "didn't see"; message2 = "'s handgrenade"; break; case MOD_HELD_GRENADE: message = "feels"; message2 = "'s pain"; break; case MOD_TELEFRAG: message = "tried to invade"; message2 = "'s personal space"; break; case MOD_CHAINFIST: message = "was shredded by"; message2 = "'s ripsaw"; break; case MOD_DISINTEGRATOR: message = "lost his grip courtesy of"; message2 = "'s disintegrator"; break; case MOD_ETF_RIFLE: message = "was perforated by"; break; case MOD_HEATBEAM: message = "was scorched by"; message2 = "'s plasma beam"; break; case MOD_TESLA: message = "was enlightened by"; message2 = "'s tesla mine"; break; case MOD_PROX: message = "got too close to"; message2 = "'s proximity mine"; break; case MOD_NUKE: message = "was nuked by"; message2 = "'s antimatter bomb"; break; case MOD_VENGEANCE_SPHERE: message = "was purged by"; message2 = "'s vengeance sphere"; break; case MOD_DEFENDER_SPHERE: message = "had a blast with"; message2 = "'s defender sphere"; break; case MOD_HUNTER_SPHERE: message = "was killed like a dog by"; message2 = "'s hunter sphere"; break; case MOD_TRACKER: message = "was annihilated by"; message2 = "'s disruptor"; break; case MOD_DOPPLE_EXPLODE: message = "was blown up by"; message2 = "'s doppleganger"; break; case MOD_DOPPLE_VENGEANCE: message = "was purged by"; message2 = "'s doppleganger"; break; case MOD_DOPPLE_HUNTER: message = "was hunted down by"; message2 = "'s doppleganger"; break; default: break; } if (message) { gi.bprintf(PRINT_MEDIUM, "%s %s %s%s\n", self->client->pers.netname, message, attacker->client->pers.netname, message2); if (gamerules && gamerules->value) { if (DMGame.Score) { if (ff) { DMGame.Score(attacker, self, -1); } else { DMGame.Score(attacker, self, 1); } } return; } if (deathmatch->value) { if (ff) { attacker->client->resp.score--; } else { attacker->client->resp.score++; } } return; } } } gi.bprintf(PRINT_MEDIUM, "%s died.\n", self->client->pers.netname); if (deathmatch->value) { if (gamerules && gamerules->value) { if (DMGame.Score) { DMGame.Score(self, self, -1); } return; } else { self->client->resp.score--; } } } void TossClientWeapon(edict_t *self) { gitem_t *item; edict_t *drop; qboolean quad; float spread; if (!self) { return; } if (!deathmatch->value) { return; } item = self->client->pers.weapon; if (!self->client->pers.inventory[self->client->ammo_index]) { item = NULL; } if (item && (strcmp(item->pickup_name, "Blaster") == 0)) { item = NULL; } if (!((int)(dmflags->value) & DF_QUAD_DROP)) { quad = false; } else { quad = (self->client->quad_framenum > (level.framenum + 10)); } if (item && quad) { spread = 22.5; } else { spread = 0.0; } if (item) { self->client->v_angle[YAW] -= spread; drop = Drop_Item(self, item); self->client->v_angle[YAW] += spread; drop->spawnflags = DROPPED_PLAYER_ITEM; } if (quad) { self->client->v_angle[YAW] += spread; drop = Drop_Item(self, FindItemByClassname("item_quad")); self->client->v_angle[YAW] -= spread; drop->spawnflags |= DROPPED_PLAYER_ITEM; drop->touch = Touch_Item; drop->nextthink = level.time + (self->client->quad_framenum - level.framenum) * FRAMETIME; drop->think = G_FreeEdict; } } void LookAtKiller(edict_t *self, edict_t *inflictor, edict_t *attacker) { vec3_t dir; if (!self) { return; } if (attacker && (attacker != world) && (attacker != self)) { VectorSubtract(attacker->s.origin, self->s.origin, dir); } else if (inflictor && (inflictor != world) && (inflictor != self)) { VectorSubtract(inflictor->s.origin, self->s.origin, dir); } else { self->client->killer_yaw = self->s.angles[YAW]; return; } if (dir[0]) { self->client->killer_yaw = 180 / M_PI * atan2(dir[1], dir[0]); } else if (dir[1] > 0) { self->client->killer_yaw = 90; } else if (dir[1] < 0) { self->client->killer_yaw = 270; } else { self->client->killer_yaw = 0; } } void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; if (!self || !inflictor || !attacker) { return; } VectorClear(self->avelocity); self->takedamage = DAMAGE_YES; self->movetype = MOVETYPE_TOSS; self->s.modelindex2 = 0; /* remove linked weapon model */ self->s.angles[0] = 0; self->s.angles[2] = 0; self->s.sound = 0; self->client->weapon_sound = 0; self->maxs[2] = -8; self->svflags |= SVF_DEADMONSTER; if (!self->deadflag) { self->client->respawn_time = level.time + 1.0; LookAtKiller(self, inflictor, attacker); self->client->ps.pmove.pm_type = PM_DEAD; ClientObituary(self, inflictor, attacker); TossClientWeapon(self); if (deathmatch->value) { Cmd_Help_f(self); /* show scores */ } /* clear inventory. this is kind of ugly, but it's how we want to handle keys in coop */ for (n = 0; n < game.num_items; n++) { if (coop->value && itemlist[n].flags & IT_KEY) { self->client->resp.coop_respawn.inventory[n] = self->client->pers.inventory[n]; } self->client->pers.inventory[n] = 0; } } if (gamerules && gamerules->value) /* if we're in a dm game, alert the game */ { if (DMGame.PlayerDeath) { DMGame.PlayerDeath(self, inflictor, attacker); } } /* remove powerups */ self->client->quad_framenum = 0; self->client->invincible_framenum = 0; self->client->breather_framenum = 0; self->client->enviro_framenum = 0; self->flags &= ~FL_POWER_ARMOR; self->client->double_framenum = 0; if (self->client->owned_sphere) { edict_t *sphere; sphere = self->client->owned_sphere; sphere->die(sphere, self, self, 0, vec3_origin); } /* if we've been killed by the tracker, GIB! */ if ((meansOfDeath & ~MOD_FRIENDLY_FIRE) == MOD_TRACKER) { self->health = -100; damage = 400; } /* make sure no trackers are still hurting us. */ if (self->client->tracker_pain_framenum) { RemoveAttackingPainDaemons(self); } /* if we got obliterated by the nuke, don't gib */ if ((self->health < -80) && (meansOfDeath == MOD_NUKE)) { self->flags |= FL_NOGIB; } if (self->health < -40) { /* don't toss gibs if we got vaped by the nuke */ if (!(self->flags & FL_NOGIB)) { /* gib (play sound at end of server frame) */ self->sounds = gi.soundindex( "misc/udeath.wav"); /* more meaty gibs for your dollar! */ if ((deathmatch->value) && (self->health < -80)) { for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } } self->flags &= ~FL_NOGIB; ThrowClientHead(self, damage); self->takedamage = DAMAGE_NO; } else { /* normal death */ if (!self->deadflag) { static int i; i = (i + 1) % 3; /* start a death animation */ self->client->anim_priority = ANIM_DEATH; if (self->client->ps.pmove.pm_flags & PMF_DUCKED) { self->s.frame = FRAME_crdeath1 - 1; self->client->anim_end = FRAME_crdeath5; } else { switch (i) { case 0: self->s.frame = FRAME_death101 - 1; self->client->anim_end = FRAME_death106; break; case 1: self->s.frame = FRAME_death201 - 1; self->client->anim_end = FRAME_death206; break; case 2: self->s.frame = FRAME_death301 - 1; self->client->anim_end = FRAME_death308; break; } } /* play sound at end of server frame */ if (!self->sounds) { self->sounds = gi.soundindex(va("*death%i.wav", (rand() % 4) + 1)); } } } self->deadflag = DEAD_DEAD; gi.linkentity(self); } /* ======================================================================= */ /* * This is only called when the game first initializes in single player, * but is called after each death and level change in deathmatch */ void InitClientPersistant(gclient_t *client) { gitem_t *item; if (!client) { return; } memset(&client->pers, 0, sizeof(client->pers)); item = FindItem("Blaster"); client->pers.selected_item = ITEM_INDEX(item); client->pers.inventory[client->pers.selected_item] = 1; client->pers.weapon = item; client->pers.health = 100; client->pers.max_health = 100; client->pers.max_bullets = 200; client->pers.max_shells = 100; client->pers.max_rockets = 50; client->pers.max_grenades = 50; client->pers.max_cells = 200; client->pers.max_slugs = 50; client->pers.max_prox = 50; client->pers.max_tesla = 50; client->pers.max_flechettes = 200; client->pers.max_rounds = 100; client->pers.connected = true; } void InitClientResp(gclient_t *client) { if (!client) { return; } memset(&client->resp, 0, sizeof(client->resp)); client->resp.enterframe = level.framenum; client->resp.coop_respawn = client->pers; } /* * Some information that should be persistant, like health, * is still stored in the edict structure, so it needs to * be mirrored out to the client structure before all the * edicts are wiped. */ void SaveClientData(void) { int i; edict_t *ent; for (i = 0; i < game.maxclients; i++) { ent = &g_edicts[1 + i]; if (!ent->inuse) { continue; } game.clients[i].pers.health = ent->health; game.clients[i].pers.max_health = ent->max_health; game.clients[i].pers.savedFlags = (ent->flags & (FL_GODMODE | FL_NOTARGET | FL_POWER_ARMOR | FL_DISGUISED)); if (coop->value) { game.clients[i].pers.score = ent->client->resp.score; } } } void FetchClientEntData(edict_t *ent) { if (!ent) { return; } ent->health = ent->client->pers.health; ent->max_health = ent->client->pers.max_health; ent->flags |= ent->client->pers.savedFlags; if (coop->value) { ent->client->resp.score = ent->client->pers.score; } } /* * Returns the distance to the nearest player from the given spot */ float PlayersRangeFromSpot(edict_t *spot) { edict_t *player; float bestplayerdistance; vec3_t v; int n; float playerdistance; if (!spot) { return 0.0; } bestplayerdistance = 9999999; for (n = 1; n <= maxclients->value; n++) { player = &g_edicts[n]; if (!player->inuse) { continue; } if (player->health <= 0) { continue; } VectorSubtract(spot->s.origin, player->s.origin, v); playerdistance = VectorLength(v); if (playerdistance < bestplayerdistance) { bestplayerdistance = playerdistance; } } return bestplayerdistance; } /* * go to a random point, but NOT the two points closest * to other players */ edict_t * SelectRandomDeathmatchSpawnPoint(void) { edict_t *spot, *spot1, *spot2; int count = 0; int selection; float range, range1, range2; spot = NULL; range1 = range2 = 99999; spot1 = spot2 = NULL; while ((spot = G_Find(spot, FOFS(classname), "info_player_deathmatch")) != NULL) { count++; range = PlayersRangeFromSpot(spot); if (range < range1) { range1 = range; spot1 = spot; } else if (range < range2) { range2 = range; spot2 = spot; } } if (!count) { return NULL; } if (count <= 2) { spot1 = spot2 = NULL; } else { count -= 2; } selection = rand() % count; spot = NULL; do { spot = G_Find(spot, FOFS(classname), "info_player_deathmatch"); if ((spot == spot1) || (spot == spot2)) { selection++; } } while (selection--); return spot; } edict_t * SelectFarthestDeathmatchSpawnPoint(void) { edict_t *bestspot; float bestdistance, bestplayerdistance; edict_t *spot; spot = NULL; bestspot = NULL; bestdistance = 0; while ((spot = G_Find(spot, FOFS(classname), "info_player_deathmatch")) != NULL) { bestplayerdistance = PlayersRangeFromSpot(spot); if (bestplayerdistance > bestdistance) { bestspot = spot; bestdistance = bestplayerdistance; } } if (bestspot) { return bestspot; } /* if there is a player just spawned on each and every start spot we have no choice to turn one into a telefrag meltdown */ spot = G_Find(NULL, FOFS(classname), "info_player_deathmatch"); return spot; } edict_t * SelectDeathmatchSpawnPoint(void) { if ((int)(dmflags->value) & DF_SPAWN_FARTHEST) { return SelectFarthestDeathmatchSpawnPoint(); } else { return SelectRandomDeathmatchSpawnPoint(); } } edict_t * SelectLavaCoopSpawnPoint(edict_t *ent) { int index; edict_t *spot = NULL; float lavatop; edict_t *lava; edict_t *pointWithLeastLava; float lowest; edict_t *spawnPoints[64]; vec3_t center; int numPoints; edict_t *highestlava; if (!ent) { return NULL; } lavatop = -99999; highestlava = NULL; lava = NULL; while (1) { lava = G_Find(lava, FOFS(classname), "func_door"); if (!lava) { break; } VectorAdd(lava->absmax, lava->absmin, center); VectorScale(center, 0.5, center); if (lava->spawnflags & 2 && (gi.pointcontents(center) & MASK_WATER)) { if (lava->absmax[2] > lavatop) { lavatop = lava->absmax[2]; highestlava = lava; } } } /* if we didn't find ANY lava, then return NULL */ if (!highestlava) { return NULL; } /* find the top of the lava and include a small margin of error (plus bbox size) */ lavatop = highestlava->absmax[2] + 64; /* find all the lava spawn points and store them in spawnPoints[] */ spot = NULL; numPoints = 0; while ((spot = (G_Find(spot, FOFS(classname), "info_player_coop_lava")))) { if (numPoints == 64) { break; } spawnPoints[numPoints++] = spot; } if (numPoints < 1) { return NULL; } /* walk up the sorted list and return the lowest, open, non-lava spawn point */ spot = NULL; lowest = 999999; pointWithLeastLava = NULL; for (index = 0; index < numPoints; index++) { if (spawnPoints[index]->s.origin[2] < lavatop) { continue; } if (PlayersRangeFromSpot(spawnPoints[index]) > 32) { if (spawnPoints[index]->s.origin[2] < lowest) { /* save the last point */ pointWithLeastLava = spawnPoints[index]; lowest = spawnPoints[index]->s.origin[2]; } } } /* well, we may telefrag someone, but oh well... */ if (pointWithLeastLava) { return pointWithLeastLava; } return NULL; } edict_t * SelectCoopSpawnPoint(edict_t *ent) { int index; edict_t *spot = NULL; char *target; if (!ent) { return NULL; } if (!Q_stricmp(level.mapname, "rmine2p") || !Q_stricmp(level.mapname, "rmine2")) { return SelectLavaCoopSpawnPoint(ent); } index = ent->client - game.clients; /* player 0 starts in normal player spawn point */ if (!index) { return NULL; } spot = NULL; /* assume there are four coop spots at each spawnpoint */ while (1) { spot = G_Find(spot, FOFS(classname), "info_player_coop"); if (!spot) { return NULL; /* we didn't have enough... */ } target = spot->targetname; if (!target) { target = ""; } if (Q_stricmp(game.spawnpoint, target) == 0) { /* this is a coop spawn point for one of the clients here */ index--; if (!index) { return spot; /* this is it */ } } } return spot; } /* * Chooses a player start, deathmatch start, coop start, etc */ void SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles) { edict_t *spot = NULL; edict_t *coopspot = NULL; int index; int counter = 0; vec3_t d; if (!ent) { return; } if (deathmatch->value) { spot = SelectDeathmatchSpawnPoint(); } else if (coop->value) { spot = SelectCoopSpawnPoint(ent); } /* find a single player start spot */ if (!spot) { while ((spot = G_Find(spot, FOFS(classname), "info_player_start")) != NULL) { if (!game.spawnpoint[0] && !spot->targetname) { break; } if (!game.spawnpoint[0] || !spot->targetname) { continue; } if (Q_stricmp(game.spawnpoint, spot->targetname) == 0) { break; } } if (!spot) { if (!game.spawnpoint[0]) { /* there wasn't a spawnpoint without a target, so use any */ spot = G_Find(spot, FOFS(classname), "info_player_start"); } if (!spot) { gi.error("Couldn't find spawn point %s\n", game.spawnpoint); } } } /* If we are in coop and we didn't find a coop spawnpoint due to map bugs (not correctly connected or the map was loaded via console and thus no previously map is known to the client) use one in 550 units radius. */ if (coop->value) { index = ent->client - game.clients; if (Q_stricmp(spot->classname, "info_player_start") == 0 && index != 0) { while(counter < 3) { coopspot = G_Find(coopspot, FOFS(classname), "info_player_coop"); if (!coopspot) { break; } VectorSubtract(coopspot->s.origin, spot->s.origin, d); if ((VectorLength(d) < 550)) { if (index == counter) { spot = coopspot; break; } else { counter++; } } } } } VectorCopy(spot->s.origin, origin); origin[2] += 9; VectorCopy(spot->s.angles, angles); } /* ====================================================================== */ void InitBodyQue(void) { int i; edict_t *ent; level.body_que = 0; for (i = 0; i < BODY_QUEUE_SIZE; i++) { ent = G_Spawn(); ent->classname = "bodyque"; } } void body_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point) { int n; if (!self) { return; } if (self->health < -40) { gi.sound(self, CHAN_BODY, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } self->s.origin[2] -= 48; ThrowClientHead(self, damage); self->takedamage = DAMAGE_NO; } } void CopyToBodyQue(edict_t *ent) { edict_t *body; if (!ent) { return; } /* grab a body que and cycle to the next one */ body = &g_edicts[(int)maxclients->value + level.body_que + 1]; level.body_que = (level.body_que + 1) % BODY_QUEUE_SIZE; gi.unlinkentity(ent); gi.unlinkentity(body); body->s = ent->s; body->s.number = body - g_edicts; body->svflags = ent->svflags; VectorCopy(ent->mins, body->mins); VectorCopy(ent->maxs, body->maxs); VectorCopy(ent->absmin, body->absmin); VectorCopy(ent->absmax, body->absmax); VectorCopy(ent->size, body->size); body->solid = ent->solid; body->clipmask = ent->clipmask; body->owner = ent->owner; body->movetype = ent->movetype; body->die = body_die; body->takedamage = DAMAGE_YES; gi.linkentity(body); } void respawn(edict_t *self) { if (!self) { return; } if (deathmatch->value || coop->value) { /* spectators don't leave bodies */ if (self->movetype != MOVETYPE_NOCLIP) { CopyToBodyQue(self); } self->svflags &= ~SVF_NOCLIENT; PutClientInServer(self); /* add a teleportation effect */ self->s.event = EV_PLAYER_TELEPORT; /* hold in place briefly */ self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; self->client->ps.pmove.pm_time = 14; self->client->respawn_time = level.time; return; } /* restart the entire server */ gi.AddCommandString("menu_loadgame\n"); } /* * only called when pers.spectator changes * note that resp.spectator should be the * opposite of pers.spectator here */ void spectator_respawn(edict_t *ent) { int i, numspec; if (!ent) { return; } /* if the user wants to become a spectator, make sure he doesn't exceed max_spectators */ if (ent->client->pers.spectator) { char *value = Info_ValueForKey(ent->client->pers.userinfo, "spectator"); if (*spectator_password->string && strcmp(spectator_password->string, "none") && strcmp(spectator_password->string, value)) { gi.cprintf(ent, PRINT_HIGH, "Spectator password incorrect.\n"); ent->client->pers.spectator = false; gi.WriteByte(svc_stufftext); gi.WriteString("spectator 0\n"); gi.unicast(ent, true); return; } /* count spectators */ for (i = 1, numspec = 0; i <= maxclients->value; i++) { if (g_edicts[i].inuse && g_edicts[i].client->pers.spectator) { numspec++; } } if (numspec >= maxspectators->value) { gi.cprintf(ent, PRINT_HIGH, "Server spectator limit is full."); ent->client->pers.spectator = false; gi.WriteByte(svc_stufftext); gi.WriteString("spectator 0\n"); gi.unicast(ent, true); return; } } else { char *value = Info_ValueForKey(ent->client->pers.userinfo, "password"); if (*password->string && strcmp(password->string, "none") && strcmp(password->string, value)) { gi.cprintf(ent, PRINT_HIGH, "Password incorrect.\n"); ent->client->pers.spectator = true; gi.WriteByte(svc_stufftext); gi.WriteString("spectator 1\n"); gi.unicast(ent, true); return; } } /* clear score on respawn */ ent->client->pers.score = ent->client->resp.score = 0; ent->svflags &= ~SVF_NOCLIENT; PutClientInServer(ent); /* add a teleportation effect */ if (!ent->client->pers.spectator) { /* send effect */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_LOGIN); gi.multicast(ent->s.origin, MULTICAST_PVS); /* hold in place briefly */ ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; ent->client->ps.pmove.pm_time = 14; } ent->client->respawn_time = level.time; if (ent->client->pers.spectator) { gi.bprintf(PRINT_HIGH, "%s has moved to the sidelines\n", ent->client->pers.netname); } else { gi.bprintf(PRINT_HIGH, "%s joined the game\n", ent->client->pers.netname); } } /* ============================================================== */ /* * Called when a player connects to a * server or respawns in a deathmatch. */ void PutClientInServer(edict_t *ent) { vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; int index; vec3_t spawn_origin, spawn_angles; gclient_t *client; int i; client_persistant_t saved; client_respawn_t resp; if (!ent) { return; } /* find a spawn point. do it before setting health back up, so farthest ranging doesn't count this client */ if (gamerules && gamerules->value && DMGame.SelectSpawnPoint) { DMGame.SelectSpawnPoint(ent, spawn_origin, spawn_angles); } else { SelectSpawnPoint(ent, spawn_origin, spawn_angles); } index = ent - g_edicts - 1; client = ent->client; /* deathmatch wipes most client data every spawn */ if (deathmatch->value) { char userinfo[MAX_INFO_STRING]; resp = client->resp; memcpy(userinfo, client->pers.userinfo, sizeof(userinfo)); InitClientPersistant(client); ClientUserinfoChanged(ent, userinfo); } else if (coop->value) { char userinfo[MAX_INFO_STRING]; resp = client->resp; memcpy(userinfo, client->pers.userinfo, sizeof(userinfo)); resp.coop_respawn.game_helpchanged = client->pers.game_helpchanged; resp.coop_respawn.helpchanged = client->pers.helpchanged; client->pers = resp.coop_respawn; ClientUserinfoChanged(ent, userinfo); if (resp.score > client->pers.score) { client->pers.score = resp.score; } } else { memset(&resp, 0, sizeof(resp)); } /* clear everything but the persistant data */ saved = client->pers; memset(client, 0, sizeof(*client)); client->pers = saved; if (client->pers.health <= 0) { InitClientPersistant(client); } client->resp = resp; /* copy some data from the client to the entity */ FetchClientEntData(ent); /* clear entity values */ ent->groundentity = NULL; ent->client = &game.clients[index]; ent->takedamage = DAMAGE_AIM; ent->movetype = MOVETYPE_WALK; ent->viewheight = 22; ent->inuse = true; ent->classname = "player"; ent->mass = 200; ent->solid = SOLID_BBOX; ent->deadflag = DEAD_NO; ent->air_finished = level.time + 12; ent->clipmask = MASK_PLAYERSOLID; ent->model = "players/male/tris.md2"; ent->pain = player_pain; ent->die = player_die; ent->waterlevel = 0; ent->watertype = 0; ent->flags &= ~FL_NO_KNOCKBACK; ent->svflags = 0; VectorCopy(mins, ent->mins); VectorCopy(maxs, ent->maxs); VectorClear(ent->velocity); /* clear playerstate values */ memset(&ent->client->ps, 0, sizeof(client->ps)); client->ps.pmove.origin[0] = spawn_origin[0] * 8; client->ps.pmove.origin[1] = spawn_origin[1] * 8; client->ps.pmove.origin[2] = spawn_origin[2] * 8; if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV)) { client->ps.fov = 90; } else { client->ps.fov = atoi(Info_ValueForKey(client->pers.userinfo, "fov")); if (client->ps.fov < 1) { client->ps.fov = 90; } else if (client->ps.fov > 160) { client->ps.fov = 160; } } if (client->pers.weapon) { client->ps.gunindex = gi.modelindex(client->pers.weapon->view_model); } else { client->ps.gunindex = 0; } /* clear entity state values */ ent->s.effects = 0; ent->s.modelindex = 255; /* will use the skin specified model */ ent->s.modelindex2 = 255; /* custom gun model */ ent->s.skinnum = ent - g_edicts - 1; ent->s.frame = 0; VectorCopy(spawn_origin, ent->s.origin); ent->s.origin[2] += 1; /* make sure off ground */ VectorCopy(ent->s.origin, ent->s.old_origin); /* set the delta angle */ for (i = 0; i < 3; i++) { client->ps.pmove.delta_angles[i] = ANGLE2SHORT(spawn_angles[i] - client->resp.cmd_angles[i]); } ent->s.angles[PITCH] = 0; ent->s.angles[YAW] = spawn_angles[YAW]; ent->s.angles[ROLL] = 0; VectorCopy(ent->s.angles, client->ps.viewangles); VectorCopy(ent->s.angles, client->v_angle); /* spawn a spectator */ if (client->pers.spectator) { client->chase_target = NULL; client->resp.spectator = true; ent->movetype = MOVETYPE_NOCLIP; ent->solid = SOLID_NOT; ent->svflags |= SVF_NOCLIENT; ent->client->ps.gunindex = 0; gi.linkentity(ent); return; } else { client->resp.spectator = false; } if (!KillBox(ent)) { /* could't spawn in? */ } gi.linkentity(ent); /* my tribute to cash's level-specific hacks. I hope * live up to his trailblazing cheese. */ if (Q_stricmp(level.mapname, "rboss") == 0) { /* if you get on to rboss in single player or coop, ensure the player has the nuke key. (not in DM) */ if (!(deathmatch->value)) { gitem_t *item; item = FindItem("Antimatter Bomb"); client->pers.selected_item = ITEM_INDEX(item); client->pers.inventory[client->pers.selected_item] = 1; } } /* force the current weapon up */ client->newweapon = client->pers.weapon; ChangeWeapon(ent); } /* * A client has just connected to the server in * deathmatch mode, so clear everything out before * starting them. */ void ClientBeginDeathmatch(edict_t *ent) { if (!ent) { return; } G_InitEdict(ent); InitClientResp(ent->client); if (gamerules && gamerules->value && DMGame.ClientBegin) { DMGame.ClientBegin(ent); } /* locate ent at a spawn point */ PutClientInServer(ent); if (level.intermissiontime) { MoveClientToIntermission(ent); } else { /* send effect */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_LOGIN); gi.multicast(ent->s.origin, MULTICAST_PVS); } gi.bprintf(PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); /* make sure all view stuff is valid */ ClientEndServerFrame(ent); } /* * called when a client has finished connecting, and is ready * to be placed into the game. This will happen every level load. */ void ClientBegin(edict_t *ent) { int i; if (!ent) { return; } ent->client = game.clients + (ent - g_edicts - 1); if (deathmatch->value) { ClientBeginDeathmatch(ent); return; } /* if there is already a body waiting for us (a loadgame), just take it, otherwise spawn one from scratch */ if (ent->inuse == true) { /* the client has cleared the client side viewangles upon connecting to the server, which is different than the state when the game is saved, so we need to compensate with deltaangles */ for (i = 0; i < 3; i++) { ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->ps.viewangles[i]); } } else { /* a spawn point will completely reinitialize the entity except for the persistant data that was initialized at ClientConnect() time */ G_InitEdict(ent); ent->classname = "player"; InitClientResp(ent->client); PutClientInServer(ent); } if (level.intermissiontime) { MoveClientToIntermission(ent); } else { /* send effect if in a multiplayer game */ if (game.maxclients > 1) { gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_LOGIN); gi.multicast(ent->s.origin, MULTICAST_PVS); gi.bprintf(PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); } } /* make sure all view stuff is valid */ ClientEndServerFrame(ent); } /* * called whenever the player updates a userinfo variable. * * The game can override any of the settings in place * (forcing skins or names, etc) before copying it off. */ void ClientUserinfoChanged(edict_t *ent, char *userinfo) { char *s; int playernum; if (!ent || !userinfo) { return; } /* check for malformed or illegal info strings */ if (!Info_Validate(userinfo)) { strcpy(userinfo, "\\name\\badinfo\\skin\\male/grunt"); } /* set name */ s = Info_ValueForKey(userinfo, "name"); strncpy(ent->client->pers.netname, s, sizeof(ent->client->pers.netname) - 1); /* set spectator */ s = Info_ValueForKey(userinfo, "spectator"); /* spectators are only supported in deathmatch */ if (deathmatch->value && *s && strcmp(s, "0")) { ent->client->pers.spectator = true; } else { ent->client->pers.spectator = false; } /* set skin */ s = Info_ValueForKey(userinfo, "skin"); playernum = ent - g_edicts - 1; /* combine name and skin into a configstring */ gi.configstring(CS_PLAYERSKINS + playernum, va("%s\\%s", ent->client->pers.netname, s)); /* fov */ if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV)) { ent->client->ps.fov = 90; } else { ent->client->ps.fov = atoi(Info_ValueForKey(userinfo, "fov")); if (ent->client->ps.fov < 1) { ent->client->ps.fov = 90; } else if (ent->client->ps.fov > 160) { ent->client->ps.fov = 160; } } /* handedness */ s = Info_ValueForKey(userinfo, "hand"); if (strlen(s)) { ent->client->pers.hand = atoi(s); } /* save off the userinfo in case we want to check something later */ strncpy(ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo) - 1); } /* * Called when a player begins connecting to the server. * The game can refuse entrance to a client by returning false. * If the client is allowed, the connection process will continue * and eventually get to ClientBegin() * Changing levels will NOT cause this to be called again, but * loadgames will. */ qboolean ClientConnect(edict_t *ent, char *userinfo) { char *value; if (!ent || !userinfo) { return false; } /* check to see if they are on the banned IP list */ value = Info_ValueForKey(userinfo, "ip"); if (SV_FilterPacket(value)) { Info_SetValueForKey(userinfo, "rejmsg", "Banned."); return false; } /* check for a spectator */ value = Info_ValueForKey(userinfo, "spectator"); if (deathmatch->value && *value && strcmp(value, "0")) { int i, numspec; if (*spectator_password->string && strcmp(spectator_password->string, "none") && strcmp(spectator_password->string, value)) { Info_SetValueForKey(userinfo, "rejmsg", "Spectator password required or incorrect."); return false; } /* count spectators */ for (i = numspec = 0; i < maxclients->value; i++) { if (g_edicts[i + 1].inuse && g_edicts[i + 1].client->pers.spectator) { numspec++; } } if (numspec >= maxspectators->value) { Info_SetValueForKey(userinfo, "rejmsg", "Server spectator limit is full."); return false; } } else { /* check for a password */ value = Info_ValueForKey(userinfo, "password"); if (*password->string && strcmp(password->string, "none") && strcmp(password->string, value)) { Info_SetValueForKey(userinfo, "rejmsg", "Password required or incorrect."); return false; } } /* they can connect */ ent->client = game.clients + (ent - g_edicts - 1); /* if there is already a body waiting for us (a loadgame), just take it, otherwise spawn one from scratch */ if (ent->inuse == false) { /* clear the respawning variables */ InitClientResp(ent->client); if (!game.autosaved || !ent->client->pers.weapon) { InitClientPersistant(ent->client); } } ClientUserinfoChanged(ent, userinfo); if (game.maxclients > 1) { gi.dprintf("%s connected\n", ent->client->pers.netname); } ent->svflags = 0; /* make sure we start with known default */ ent->client->pers.connected = true; return true; } /* * Called when a player drops from the server. * Will not be called between levels. */ void ClientDisconnect(edict_t *ent) { int playernum; if (!ent) { return; } if (!ent->client) { return; } gi.bprintf(PRINT_HIGH, "%s disconnected\n", ent->client->pers.netname); /* make sure no trackers are still hurting us. */ if (ent->client->tracker_pain_framenum) { RemoveAttackingPainDaemons(ent); } if (ent->client->owned_sphere) { if (ent->client->owned_sphere->inuse) { G_FreeEdict(ent->client->owned_sphere); } ent->client->owned_sphere = NULL; } if (gamerules && gamerules->value) { if (DMGame.PlayerDisconnect) { DMGame.PlayerDisconnect(ent); } } /* send effect */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_LOGOUT); gi.multicast(ent->s.origin, MULTICAST_PVS); gi.unlinkentity(ent); ent->s.modelindex = 0; ent->solid = SOLID_NOT; ent->inuse = false; ent->classname = "disconnected"; ent->client->pers.connected = false; playernum = ent - g_edicts - 1; gi.configstring(CS_PLAYERSKINS + playernum, ""); } /* ============================================================== */ trace_t PM_trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) { if (pm_passent->health > 0) { return gi.trace(start, mins, maxs, end, pm_passent, MASK_PLAYERSOLID); } else { return gi.trace(start, mins, maxs, end, pm_passent, MASK_DEADSOLID); } } unsigned CheckBlock(void *b, int c) { int v, i; if (!b) { return 0; } v = 0; for (i = 0; i < c; i++) { v += ((byte *)b)[i]; } return v; } void PrintPmove(pmove_t *pm) { unsigned c1, c2; if (!pm) { return; } c1 = CheckBlock(&pm->s, sizeof(pm->s)); c2 = CheckBlock(&pm->cmd, sizeof(pm->cmd)); Com_Printf("sv %3i:%i %i\n", pm->cmd.impulse, c1, c2); } /* * This will be called once for each client frame, which will * usually be a couple times for each server frame. */ void ClientThink(edict_t *ent, usercmd_t *ucmd) { gclient_t *client; edict_t *other; int i, j; pmove_t pm; if (!ent || !ucmd) { return; } level.current_entity = ent; client = ent->client; if (level.intermissiontime) { client->ps.pmove.pm_type = PM_FREEZE; /* can exit intermission after five seconds */ if ((level.time > level.intermissiontime + 5.0) && (ucmd->buttons & BUTTON_ANY)) { level.exitintermission = true; } return; } pm_passent = ent; if (ent->client->chase_target) { client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); } else { /* set up for pmove */ memset(&pm, 0, sizeof(pm)); if (ent->movetype == MOVETYPE_NOCLIP) { client->ps.pmove.pm_type = PM_SPECTATOR; } else if (ent->s.modelindex != 255) { client->ps.pmove.pm_type = PM_GIB; } else if (ent->deadflag) { client->ps.pmove.pm_type = PM_DEAD; } else { client->ps.pmove.pm_type = PM_NORMAL; } client->ps.pmove.gravity = sv_gravity->value * ent->gravity; pm.s = client->ps.pmove; for (i = 0; i < 3; i++) { pm.s.origin[i] = ent->s.origin[i] * 8; /* save to an int first, in case the short overflows * so we get defined behavior (at least with -fwrapv) */ int tmpVel = ent->velocity[i] * 8; pm.s.velocity[i] = tmpVel; } if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s))) { pm.snapinitial = true; } pm.cmd = *ucmd; pm.trace = PM_trace; /* adds default parms */ pm.pointcontents = gi.pointcontents; /* perform a pmove */ gi.Pmove(&pm); /* save results of pmove */ client->ps.pmove = pm.s; client->old_pmove = pm.s; for (i = 0; i < 3; i++) { ent->s.origin[i] = pm.s.origin[i] * 0.125; ent->velocity[i] = pm.s.velocity[i] * 0.125; } VectorCopy(pm.mins, ent->mins); VectorCopy(pm.maxs, ent->maxs); client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0)) { gi.sound(ent, CHAN_VOICE, gi.soundindex( "*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); } if (ent->flags & FL_SAM_RAIMI) { ent->viewheight = 8; } else { ent->viewheight = pm.viewheight; } ent->waterlevel = pm.waterlevel; ent->watertype = pm.watertype; ent->groundentity = pm.groundentity; if (pm.groundentity) { ent->groundentity_linkcount = pm.groundentity->linkcount; } if (ent->deadflag) { client->ps.viewangles[ROLL] = 40; client->ps.viewangles[PITCH] = -15; client->ps.viewangles[YAW] = client->killer_yaw; } else { VectorCopy(pm.viewangles, client->v_angle); VectorCopy(pm.viewangles, client->ps.viewangles); } gi.linkentity(ent); ent->gravity = 1.0; if (ent->movetype != MOVETYPE_NOCLIP) { G_TouchTriggers(ent); } /* touch other objects */ for (i = 0; i < pm.numtouch; i++) { other = pm.touchents[i]; for (j = 0; j < i; j++) { if (pm.touchents[j] == other) { break; } } if (j != i) { continue; /* duplicated */ } if (!other->touch) { continue; } other->touch(other, ent, NULL, NULL); } } client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; client->latched_buttons |= client->buttons & ~client->oldbuttons; /* save light level the player is tanding on for monster sighting AI */ ent->light_level = ucmd->lightlevel; /* fire weapon from final position if needed */ if (client->latched_buttons & BUTTON_ATTACK) { if (client->resp.spectator) { client->latched_buttons = 0; if (client->chase_target) { client->chase_target = NULL; client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; } else { GetChaseTarget(ent); } } else if (!client->weapon_thunk) { client->weapon_thunk = true; Think_Weapon(ent); } } if (client->resp.spectator) { if (ucmd->upmove >= 10) { if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { client->ps.pmove.pm_flags |= PMF_JUMP_HELD; if (client->chase_target) { ChaseNext(ent); } else { GetChaseTarget(ent); } } } else { client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; } } /* update chase cam if being followed */ for (i = 1; i <= maxclients->value; i++) { other = g_edicts + i; if (other->inuse && (other->client->chase_target == ent)) { UpdateChaseCam(other); } } } /* * This will be called once for each server frame, * before running any other entities in the world. */ void ClientBeginServerFrame(edict_t *ent) { gclient_t *client; int buttonMask; if (!ent) { return; } if (level.intermissiontime) { return; } client = ent->client; if (deathmatch->value && (client->pers.spectator != client->resp.spectator) && ((level.time - client->respawn_time) >= 5)) { spectator_respawn(ent); return; } /* run weapon animations if it hasn't been done by a ucmd_t */ if (!client->weapon_thunk && !client->resp.spectator) { Think_Weapon(ent); } else { client->weapon_thunk = false; } if (ent->deadflag) { /* wait for any button just going down */ if (level.time > client->respawn_time) { /* in deathmatch, only wait for attack button */ if (deathmatch->value) { buttonMask = BUTTON_ATTACK; } else { buttonMask = -1; } if ((client->latched_buttons & buttonMask) || (deathmatch->value && ((int)dmflags->value & DF_FORCE_RESPAWN))) { respawn(ent); client->latched_buttons = 0; } } return; } /* add player trail so monsters can follow */ if (!deathmatch->value) { if (!visible(ent, PlayerTrail_LastSpot())) { PlayerTrail_Add(ent->s.old_origin); } } client->latched_buttons = 0; } /* * This is called to clean up the pain daemons that * the disruptor attaches to clients to damage them. */ void RemoveAttackingPainDaemons(edict_t *self) { edict_t *tracker; if (!self) { return; } tracker = G_Find(NULL, FOFS(classname), "pain daemon"); while (tracker) { if (tracker->enemy == self) { G_FreeEdict(tracker); } tracker = G_Find(tracker, FOFS(classname), "pain daemon"); } if (self->client) { self->client->tracker_pain_framenum = 0; } } rogue-ROGUE_2_13/src/player/hud.c000066400000000000000000000324461477320066100166300ustar00rootroot00000000000000/* ======================================================================= * * HUD, deathmatch scoreboard, help computer and intermission stuff. * * ======================================================================= */ #include "../header/local.h" void MoveClientToIntermission(edict_t *ent) { if (!ent) { return; } if (deathmatch->value || coop->value) { ent->client->showscores = true; } VectorCopy(level.intermission_origin, ent->s.origin); ent->client->ps.pmove.origin[0] = level.intermission_origin[0] * 8; ent->client->ps.pmove.origin[1] = level.intermission_origin[1] * 8; ent->client->ps.pmove.origin[2] = level.intermission_origin[2] * 8; VectorCopy(level.intermission_angle, ent->client->ps.viewangles); ent->client->ps.pmove.pm_type = PM_FREEZE; ent->client->ps.gunindex = 0; ent->client->ps.blend[3] = 0; ent->client->ps.rdflags &= ~RDF_UNDERWATER; /* clean up powerup info */ ent->client->quad_framenum = 0; ent->client->invincible_framenum = 0; ent->client->breather_framenum = 0; ent->client->enviro_framenum = 0; ent->client->grenade_blew_up = false; ent->client->grenade_time = 0; ent->client->ps.rdflags &= ~RDF_IRGOGGLES; ent->client->ir_framenum = 0; ent->client->nuke_framenum = 0; ent->client->double_framenum = 0; ent->viewheight = 0; ent->s.modelindex = 0; ent->s.modelindex2 = 0; ent->s.modelindex3 = 0; ent->s.modelindex = 0; ent->s.effects = 0; ent->s.sound = 0; ent->solid = SOLID_NOT; gi.linkentity(ent); /* add the layout */ if (deathmatch->value || coop->value) { DeathmatchScoreboardMessage(ent, NULL); gi.unicast(ent, true); } } void BeginIntermission(edict_t *targ) { int i, n; edict_t *ent, *client; if (!targ) { return; } if (level.intermissiontime) { return; /* already activated */ } game.autosaved = false; /* respawn any dead clients */ for (i = 0; i < maxclients->value; i++) { client = g_edicts + 1 + i; if (!client->inuse) { continue; } if (client->health <= 0) { respawn(client); } } level.intermissiontime = level.time; level.changemap = targ->map; if (strstr(level.changemap, "*")) { if (coop->value) { for (i = 0; i < maxclients->value; i++) { client = g_edicts + 1 + i; if (!client->inuse) { continue; } /* strip players of all keys between units */ for (n = 0; n < game.num_items; n++) { if (itemlist[n].flags & IT_KEY) { client->client->pers.inventory[n] = 0; } } client->client->pers.power_cubes = 0; } } } else { if (!deathmatch->value) { level.exitintermission = 1; /* go immediately to the next level */ return; } } level.exitintermission = 0; /* find an intermission spot */ ent = G_Find(NULL, FOFS(classname), "info_player_intermission"); if (!ent) { /* the map creator forgot to put in an intermission point... */ ent = G_Find(NULL, FOFS(classname), "info_player_start"); if (!ent) { ent = G_Find(NULL, FOFS(classname), "info_player_deathmatch"); } } else { /* chose one of four spots */ i = rand() & 3; while (i--) { ent = G_Find(ent, FOFS(classname), "info_player_intermission"); if (!ent) /* wrap around the list */ { ent = G_Find(ent, FOFS(classname), "info_player_intermission"); } } } VectorCopy(ent->s.origin, level.intermission_origin); VectorCopy(ent->s.angles, level.intermission_angle); /* move all clients to the intermission point */ for (i = 0; i < maxclients->value; i++) { client = g_edicts + 1 + i; if (!client->inuse) { continue; } MoveClientToIntermission(client); } } void DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer /* can be NULL */) { char entry[1024]; char string[1400]; int stringlength; int i, j, k; int sorted[MAX_CLIENTS]; int sortedscores[MAX_CLIENTS]; int score, total; int x, y; gclient_t *cl; edict_t *cl_ent; char *tag; if (!ent) { return; } /* sort the clients by score */ total = 0; for (i = 0; i < game.maxclients; i++) { cl_ent = g_edicts + 1 + i; if (!cl_ent->inuse || game.clients[i].resp.spectator) { continue; } score = game.clients[i].resp.score; for (j = 0; j < total; j++) { if (score > sortedscores[j]) { break; } } for (k = total; k > j; k--) { sorted[k] = sorted[k - 1]; sortedscores[k] = sortedscores[k - 1]; } sorted[j] = i; sortedscores[j] = score; total++; } /* print level name and exit rules */ string[0] = 0; stringlength = strlen(string); /* add the clients in sorted order */ if (total > 12) { total = 12; } for (i = 0; i < total; i++) { cl = &game.clients[sorted[i]]; cl_ent = g_edicts + 1 + sorted[i]; x = (i >= 6) ? 160 : 0; y = 32 + 32 * (i % 6); /* add a dogtag */ if (cl_ent == ent) { tag = "tag1"; } else if (cl_ent == killer) { tag = "tag2"; } else { tag = NULL; } /* allow new DM games to override the tag picture */ if (gamerules && gamerules->value) { if (DMGame.DogTag) { DMGame.DogTag(cl_ent, killer, &tag); } } if (tag) { Com_sprintf(entry, sizeof(entry), "xv %i yv %i picn %s ", x + 32, y, tag); j = strlen(entry); if (stringlength + j > 1024) { break; } strcpy(string + stringlength, entry); stringlength += j; } /* send the layout */ Com_sprintf(entry, sizeof(entry), "client %i %i %i %i %i %i ", x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe) / 600); j = strlen(entry); if (stringlength + j > 1024) { break; } strcpy(string + stringlength, entry); stringlength += j; } gi.WriteByte(svc_layout); gi.WriteString(string); } /* * Draw help computer. */ void HelpComputerMessage(edict_t *ent) { char string[1024]; char *sk; if (!ent) { return; } if (skill->value == SKILL_EASY) { sk = "easy"; } else if (skill->value == SKILL_MEDIUM) { sk = "medium"; } else if (skill->value == SKILL_HARD) { sk = "hard"; } else { sk = "hard+"; } /* send the layout */ Com_sprintf(string, sizeof(string), "xv 32 yv 8 picn help " /* background */ "xv 202 yv 12 string2 \"%s\" " /* skill */ "xv 0 yv 24 cstring2 \"%s\" " /* level name */ "xv 0 yv 54 cstring2 \"%s\" " /* help 1 */ "xv 0 yv 110 cstring2 \"%s\" " /* help 2 */ "xv 50 yv 164 string2 \" kills goals secrets\" " "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ", sk, level.level_name, game.helpmessage1, game.helpmessage2, level.killed_monsters, level.total_monsters, level.found_goals, level.total_goals, level.found_secrets, level.total_secrets); gi.WriteByte(svc_layout); gi.WriteString(string); } /* * Display the current help message */ void InventoryMessage(edict_t *ent) { int i; if (!ent) { return; } gi.WriteByte(svc_inventory); for (i = 0; i < MAX_ITEMS; i++) { gi.WriteShort(ent->client->pers.inventory[i]); } } /* ======================================================================= */ void G_SetStats(edict_t *ent) { gitem_t *item; int index, cells; int power_armor_type; if (!ent) { return; } /* health */ ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health; ent->client->ps.stats[STAT_HEALTH] = (ent->health < -99) ? -99 : ent->health; /* ammo */ if (!ent->client->ammo_index) { ent->client->ps.stats[STAT_AMMO_ICON] = 0; ent->client->ps.stats[STAT_AMMO] = 0; } else { item = &itemlist[ent->client->ammo_index]; ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex(item->icon); ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index]; } /* armor */ power_armor_type = PowerArmorType(ent); if (power_armor_type) { cells = ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]; if (cells == 0) { /* ran out of cells for power armor */ ent->flags &= ~FL_POWER_ARMOR; gi.sound(ent, CHAN_ITEM, gi.soundindex( "misc/power2.wav"), 1, ATTN_NORM, 0); power_armor_type = 0; } } index = ArmorIndex(ent); if (power_armor_type && (!index || (level.framenum & 8))) { /* flash between power armor and other armor icon */ ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex("i_powershield"); ent->client->ps.stats[STAT_ARMOR] = cells; } else if (index) { item = GetItemByIndex(index); ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex(item->icon); ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index]; } else { ent->client->ps.stats[STAT_ARMOR_ICON] = 0; ent->client->ps.stats[STAT_ARMOR] = 0; } /* pickup message */ if (level.time > ent->client->pickup_msg_time) { ent->client->ps.stats[STAT_PICKUP_ICON] = 0; ent->client->ps.stats[STAT_PICKUP_STRING] = 0; } /* timers */ if (ent->client->quad_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_quad"); ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum) / 10; } else if (ent->client->double_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_double"); ent->client->ps.stats[STAT_TIMER] = (ent->client->double_framenum - level.framenum) / 10; } else if (ent->client->invincible_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex( "p_invulnerability"); ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum) / 10; } else if (ent->client->enviro_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_envirosuit"); ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum) / 10; } else if (ent->client->breather_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_rebreather"); ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum) / 10; } else if (ent->client->owned_sphere) { if (ent->client->owned_sphere->spawnflags == 1) /* defender */ { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_defender"); } else if (ent->client->owned_sphere->spawnflags == 2) /* hunter */ { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_hunter"); } else if (ent->client->owned_sphere->spawnflags == 4) /* vengeance */ { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_vengeance"); } else /* error case */ { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("i_fixme"); } ent->client->ps.stats[STAT_TIMER] = (int)(ent->client->owned_sphere->wait - level.time); } else if (ent->client->ir_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_ir"); ent->client->ps.stats[STAT_TIMER] = (ent->client->ir_framenum - level.framenum) / 10; } else { ent->client->ps.stats[STAT_TIMER_ICON] = 0; ent->client->ps.stats[STAT_TIMER] = 0; } /* selected item */ if (ent->client->pers.selected_item == -1) { ent->client->ps.stats[STAT_SELECTED_ICON] = 0; } else { ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex(itemlist[ent->client->pers.selected_item].icon); } ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item; /* layouts */ ent->client->ps.stats[STAT_LAYOUTS] = 0; if (deathmatch->value) { if ((ent->client->pers.health <= 0) || level.intermissiontime || ent->client->showscores) { ent->client->ps.stats[STAT_LAYOUTS] |= 1; } if (ent->client->showinventory && (ent->client->pers.health > 0)) { ent->client->ps.stats[STAT_LAYOUTS] |= 2; } } else { if (ent->client->showscores || ent->client->showhelp) { ent->client->ps.stats[STAT_LAYOUTS] |= 1; } if (ent->client->showinventory && (ent->client->pers.health > 0)) { ent->client->ps.stats[STAT_LAYOUTS] |= 2; } } /* frags */ ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score; /* help icon / current weapon if not shown */ if (ent->client->pers.helpchanged && (level.framenum & 8)) { ent->client->ps.stats[STAT_HELPICON] = gi.imageindex("i_help"); } else if (((ent->client->pers.hand == CENTER_HANDED) || (ent->client->ps.fov > 91)) && ent->client->pers.weapon) { cvar_t *gun; gun = gi.cvar("cl_gun", "2", 0); if (gun->value != 2) { ent->client->ps.stats[STAT_HELPICON] = gi.imageindex(ent->client->pers.weapon->icon); } else { ent->client->ps.stats[STAT_HELPICON] = 0; } } else { ent->client->ps.stats[STAT_HELPICON] = 0; } ent->client->ps.stats[STAT_SPECTATOR] = 0; } void G_CheckChaseStats(edict_t *ent) { int i; gclient_t *cl; if (!ent) { return; } for (i = 1; i <= maxclients->value; i++) { cl = g_edicts[i].client; if (!g_edicts[i].inuse || (cl->chase_target != ent)) { continue; } memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats)); G_SetSpectatorStats(g_edicts + i); } } void G_SetSpectatorStats(edict_t *ent) { if (!ent) { return; } gclient_t *cl = ent->client; if (!cl->chase_target) { G_SetStats(ent); } cl->ps.stats[STAT_SPECTATOR] = 1; /* layouts are independant in spectator */ cl->ps.stats[STAT_LAYOUTS] = 0; if ((cl->pers.health <= 0) || level.intermissiontime || cl->showscores) { cl->ps.stats[STAT_LAYOUTS] |= 1; } if (cl->showinventory && (cl->pers.health > 0)) { cl->ps.stats[STAT_LAYOUTS] |= 2; } if (cl->chase_target && cl->chase_target->inuse) { cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + (cl->chase_target - g_edicts) - 1; } else { cl->ps.stats[STAT_CHASE] = 0; } } rogue-ROGUE_2_13/src/player/trail.c000066400000000000000000000043531477320066100171570ustar00rootroot00000000000000/* ======================================================================= * * The player trail, used by monsters to locate the player. * * ======================================================================= */ #include "../header/local.h" /* * This is a circular list containing the a list of points of where * the player has been recently. It is used by monsters for pursuit. * * .origin the spot * .owner forward link * .aiment backward link */ #define NEXT(n) (((n) + 1) & (TRAIL_LENGTH - 1)) #define PREV(n) (((n) - 1) & (TRAIL_LENGTH - 1)) #define TRAIL_LENGTH 8 edict_t *trail[TRAIL_LENGTH]; int trail_head; qboolean trail_active = false; void PlayerTrail_Init(void) { int n; if (deathmatch->value) { return; } for (n = 0; n < TRAIL_LENGTH; n++) { trail[n] = G_Spawn(); trail[n]->classname = "player_trail"; } trail_head = 0; trail_active = true; } void PlayerTrail_Add(vec3_t spot) { vec3_t temp; if (!trail_active) { return; } VectorCopy(spot, trail[trail_head]->s.origin); trail[trail_head]->timestamp = level.time; VectorSubtract(spot, trail[PREV(trail_head)]->s.origin, temp); trail[trail_head]->s.angles[1] = vectoyaw(temp); trail_head = NEXT(trail_head); } void PlayerTrail_New(vec3_t spot) { if (!trail_active) { return; } PlayerTrail_Init(); PlayerTrail_Add(spot); } edict_t * PlayerTrail_PickFirst(edict_t *self) { int marker; int n; if (!self) { return NULL; } if (!trail_active) { return NULL; } for (marker = trail_head, n = TRAIL_LENGTH; n; n--) { if (trail[marker]->timestamp <= self->monsterinfo.trail_time) { marker = NEXT(marker); } else { break; } } if (visible(self, trail[marker])) { return trail[marker]; } if (visible(self, trail[PREV(marker)])) { return trail[PREV(marker)]; } return trail[marker]; } edict_t * PlayerTrail_PickNext(edict_t *self) { int marker; int n; if (!self) { return NULL; } if (!trail_active) { return NULL; } for (marker = trail_head, n = TRAIL_LENGTH; n; n--) { if (trail[marker]->timestamp <= self->monsterinfo.trail_time) { marker = NEXT(marker); } else { break; } } return trail[marker]; } edict_t * PlayerTrail_LastSpot(void) { return trail[PREV(trail_head)]; } rogue-ROGUE_2_13/src/player/view.c000066400000000000000000000720271477320066100170210ustar00rootroot00000000000000/* ======================================================================= * * The "camera" through that the player looks into the game. * * ======================================================================= */ #include "../header/local.h" #include "../monster/misc/player.h" static edict_t *current_player; static gclient_t *current_client; static vec3_t forward, right, up; float xyspeed; float bobmove; int bobcycle; float bobfracsin; float SV_CalcRoll(vec3_t angles, vec3_t velocity) { float sign; float side; float value; side = DotProduct(velocity, right); sign = side < 0 ? -1 : 1; side = fabs(side); value = sv_rollangle->value; if (side < sv_rollspeed->value) { side = side * value / sv_rollspeed->value; } else { side = value; } return side * sign; } /* * Handles color blends and view kicks */ void P_DamageFeedback(edict_t *player) { gclient_t *client; float side; float realcount, count, kick; vec3_t v; int r, l; static vec3_t power_color = {0.0, 1.0, 0.0}; static vec3_t acolor = {1.0, 1.0, 1.0}; static vec3_t bcolor = {1.0, 0.0, 0.0}; if (!player) { return; } /* death/gib sound is now aggregated and played here */ if (player->sounds) { gi.sound (player, CHAN_VOICE, player->sounds, 1, ATTN_NORM, 0); player->sounds = 0; } client = player->client; /* flash the backgrounds behind the status numbers */ client->ps.stats[STAT_FLASHES] = 0; if (client->damage_blood) { client->ps.stats[STAT_FLASHES] |= 1; } if (client->damage_armor && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum)) { client->ps.stats[STAT_FLASHES] |= 2; } /* total points of damage shot at the player this frame */ count = (client->damage_blood + client->damage_armor + client->damage_parmor); if (count == 0) { return; /* didn't take any damage */ } /* start a pain animation if still in the player model */ if ((client->anim_priority < ANIM_PAIN) && (player->s.modelindex == 255)) { static int i; client->anim_priority = ANIM_PAIN; if (client->ps.pmove.pm_flags & PMF_DUCKED) { player->s.frame = FRAME_crpain1 - 1; client->anim_end = FRAME_crpain4; } else { i = (i + 1) % 3; switch (i) { case 0: player->s.frame = FRAME_pain101 - 1; client->anim_end = FRAME_pain104; break; case 1: player->s.frame = FRAME_pain201 - 1; client->anim_end = FRAME_pain204; break; case 2: player->s.frame = FRAME_pain301 - 1; client->anim_end = FRAME_pain304; break; } } } realcount = count; if (count < 10) { count = 10; /* always make a visible effect */ } /* play an apropriate pain sound */ if ((level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum) && player->health > 0) { r = 1 + (rand() & 1); player->pain_debounce_time = level.time + 0.7; if (player->health < 25) { l = 25; } else if (player->health < 50) { l = 50; } else if (player->health < 75) { l = 75; } else { l = 100; } gi.sound(player, CHAN_VOICE, gi.soundindex(va("*pain%i_%i.wav", l, r)), 1, ATTN_NORM, 0); } /* the total alpha of the blend is always proportional to count */ if (client->damage_alpha < 0) { client->damage_alpha = 0; } client->damage_alpha += count * 0.01; if (client->damage_alpha < 0.2) { client->damage_alpha = 0.2; } if (client->damage_alpha > 0.6) { client->damage_alpha = 0.6; /* don't go too saturated */ } /* the color of the blend will vary based on how much was absorbed by different armors */ VectorClear(v); if (client->damage_parmor) { VectorMA(v, (float)client->damage_parmor / realcount, power_color, v); } if (client->damage_armor) { VectorMA(v, (float)client->damage_armor / realcount, acolor, v); } if (client->damage_blood) { VectorMA(v, (float)client->damage_blood / realcount, bcolor, v); } VectorCopy(v, client->damage_blend); /* calculate view angle kicks */ kick = abs(client->damage_knockback); if (kick && (player->health > 0)) /* kick of 0 means no view adjust at all */ { kick = kick * 100 / player->health; if (kick < count * 0.5) { kick = count * 0.5; } if (kick > 50) { kick = 50; } VectorSubtract(client->damage_from, player->s.origin, v); VectorNormalize(v); side = DotProduct(v, right); client->v_dmg_roll = kick * side * 0.3; side = -DotProduct(v, forward); client->v_dmg_pitch = kick * side * 0.3; client->v_dmg_time = level.time + DAMAGE_TIME; } /* clear totals */ client->damage_blood = 0; client->damage_armor = 0; client->damage_parmor = 0; client->damage_knockback = 0; } /* * Auto pitching on slopes? * * fall from 128: 400 = 160000 * fall from 256: 580 = 336400 * fall from 384: 720 = 518400 * fall from 512: 800 = 640000 * fall from 640: 960 = * * damage = deltavelocity*deltavelocity * 0.0001 */ void SV_CalcViewOffset(edict_t *ent) { float *angles; float bob; float ratio; float delta; vec3_t v; if (!ent) { return; } /* base angles */ angles = ent->client->ps.kick_angles; /* if dead, fix the angle and don't add any kick */ if (ent->deadflag) { VectorClear(angles); if (ent->flags & FL_SAM_RAIMI) { ent->client->ps.viewangles[ROLL] = 0; ent->client->ps.viewangles[PITCH] = 0; } else { ent->client->ps.viewangles[ROLL] = 40; ent->client->ps.viewangles[PITCH] = -15; } ent->client->ps.viewangles[YAW] = ent->client->killer_yaw; } else { /* add angles based on weapon kick */ VectorCopy(ent->client->kick_angles, angles); /* add angles based on damage kick */ ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME; if (ratio < 0) { ratio = 0; ent->client->v_dmg_pitch = 0; ent->client->v_dmg_roll = 0; } angles[PITCH] += ratio * ent->client->v_dmg_pitch; angles[ROLL] += ratio * ent->client->v_dmg_roll; /* add pitch based on fall kick */ ratio = (ent->client->fall_time - level.time) / FALL_TIME; if (ratio < 0) { ratio = 0; } angles[PITCH] += ratio * ent->client->fall_value; /* add angles based on velocity */ delta = DotProduct(ent->velocity, forward); angles[PITCH] += delta * run_pitch->value; delta = DotProduct(ent->velocity, right); angles[ROLL] += delta * run_roll->value; /* add angles based on bob */ delta = bobfracsin * bob_pitch->value * xyspeed; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { delta *= 6; /* crouching */ } angles[PITCH] += delta; delta = bobfracsin * bob_roll->value * xyspeed; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { delta *= 6; /* crouching */ } if (bobcycle & 1) { delta = -delta; } angles[ROLL] += delta; } /* =================================== */ /* base origin */ VectorClear(v); /* add view height */ v[2] += ent->viewheight; /* add fall height */ ratio = (ent->client->fall_time - level.time) / FALL_TIME; if (ratio < 0) { ratio = 0; } v[2] -= ratio * ent->client->fall_value * 0.4; /* add bob height */ bob = bobfracsin * xyspeed * bob_up->value; if (bob > 6) { bob = 6; } v[2] += bob; /* add kick offset */ VectorAdd(v, ent->client->kick_origin, v); /* absolutely bound offsets so the view can never be outside the player box */ if (v[0] < -14) { v[0] = -14; } else if (v[0] > 14) { v[0] = 14; } if (v[1] < -14) { v[1] = -14; } else if (v[1] > 14) { v[1] = 14; } if (v[2] < -22) { v[2] = -22; } else if (v[2] > 30) { v[2] = 30; } VectorCopy(v, ent->client->ps.viewoffset); } void SV_CalcGunOffset(edict_t *ent) { int i; float delta; static gitem_t *heatbeam; if (!ent) { return; } if (!heatbeam) { heatbeam = FindItemByClassname("weapon_plasmabeam"); } /* heatbeam shouldn't bob so the beam looks right */ if (ent->client->pers.weapon != heatbeam) { /* gun angles from bobbing */ ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; if (bobcycle & 1) { ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL]; ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW]; } ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005; /* gun angles from delta movement */ for (i = 0; i < 3; i++) { delta = ent->client->oldviewangles[i] - ent->client->ps.viewangles[i]; if (delta > 180) { delta -= 360; } if (delta < -180) { delta += 360; } if (delta > 45) { delta = 45; } if (delta < -45) { delta = -45; } if (i == YAW) { ent->client->ps.gunangles[ROLL] += 0.1 * delta; } ent->client->ps.gunangles[i] += 0.2 * delta; } } else { for (i = 0; i < 3; i++) { ent->client->ps.gunangles[i] = 0; } } /* gun height */ VectorClear(ent->client->ps.gunoffset); /* gun_x / gun_y / gun_z are development tools */ for (i = 0; i < 3; i++) { ent->client->ps.gunoffset[i] += forward[i] * (gun_y->value); ent->client->ps.gunoffset[i] += right[i] * gun_x->value; ent->client->ps.gunoffset[i] += up[i] * (-gun_z->value); } } void SV_AddBlend(float r, float g, float b, float a, float *v_blend) { float a2, a3; if (!v_blend) { return; } if (a <= 0) { return; } a2 = v_blend[3] + (1 - v_blend[3]) * a; /* new total alpha */ a3 = v_blend[3] / a2; /* fraction of color from old */ v_blend[0] = v_blend[0] * a3 + r * (1 - a3); v_blend[1] = v_blend[1] * a3 + g * (1 - a3); v_blend[2] = v_blend[2] * a3 + b * (1 - a3); v_blend[3] = a2; } void SV_CalcBlend(edict_t *ent) { int contents; vec3_t vieworg; int remaining; if (!ent) { return; } ent->client->ps.blend[0] = ent->client->ps.blend[1] = ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0; /* add for contents */ VectorAdd(ent->s.origin, ent->client->ps.viewoffset, vieworg); contents = gi.pointcontents(vieworg); if (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) { ent->client->ps.rdflags |= RDF_UNDERWATER; } else { ent->client->ps.rdflags &= ~RDF_UNDERWATER; } if (contents & (CONTENTS_SOLID | CONTENTS_LAVA)) { SV_AddBlend(1.0, 0.3, 0.0, 0.6, ent->client->ps.blend); } else if (contents & CONTENTS_SLIME) { SV_AddBlend(0.0, 0.1, 0.05, 0.6, ent->client->ps.blend); } else if (contents & CONTENTS_WATER) { SV_AddBlend(0.5, 0.3, 0.2, 0.4, ent->client->ps.blend); } /* add for powerups */ if (ent->client->quad_framenum > level.framenum) { remaining = ent->client->quad_framenum - level.framenum; if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) { SV_AddBlend(0, 0, 1, 0.08, ent->client->ps.blend); } } else if (ent->client->double_framenum > level.framenum) { remaining = ent->client->double_framenum - level.framenum; if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage2.wav"), 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) { SV_AddBlend(0.9, 0.7, 0, 0.08, ent->client->ps.blend); } } else if (ent->client->invincible_framenum > level.framenum) { remaining = ent->client->invincible_framenum - level.framenum; if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) { SV_AddBlend(1, 1, 0, 0.08, ent->client->ps.blend); } } else if (ent->client->enviro_framenum > level.framenum) { remaining = ent->client->enviro_framenum - level.framenum; if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) { SV_AddBlend(0, 1, 0, 0.08, ent->client->ps.blend); } } else if (ent->client->breather_framenum > level.framenum) { remaining = ent->client->breather_framenum - level.framenum; if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) { SV_AddBlend(0.4, 1, 0.4, 0.04, ent->client->ps.blend); } } if (ent->client->nuke_framenum > level.framenum) { float brightness; brightness = (ent->client->nuke_framenum - level.framenum) / 20.0; SV_AddBlend(1, 1, 1, brightness, ent->client->ps.blend); } if (ent->client->ir_framenum > level.framenum) { remaining = ent->client->ir_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->client->ps.rdflags |= RDF_IRGOGGLES; SV_AddBlend(1, 0, 0, 0.2, ent->client->ps.blend); } else { ent->client->ps.rdflags &= ~RDF_IRGOGGLES; } } else { ent->client->ps.rdflags &= ~RDF_IRGOGGLES; } /* add for damage */ if (ent->client->damage_alpha > 0) { SV_AddBlend(ent->client->damage_blend[0], ent->client->damage_blend[1], ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend); } if (ent->client->bonus_alpha > 0) { SV_AddBlend(0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend); } /* drop the damage value */ ent->client->damage_alpha -= 0.06; if (ent->client->damage_alpha < 0) { ent->client->damage_alpha = 0; } /* drop the bonus value */ ent->client->bonus_alpha -= 0.1; if (ent->client->bonus_alpha < 0) { ent->client->bonus_alpha = 0; } } void P_FallingDamage(edict_t *ent) { float delta; int damage; vec3_t dir; if (!ent) { return; } if (ent->s.modelindex != 255) { return; /* not in the player model */ } if (ent->movetype == MOVETYPE_NOCLIP) { return; } if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity)) { delta = ent->client->oldvelocity[2]; } else { if (!ent->groundentity) { return; } delta = ent->velocity[2] - ent->client->oldvelocity[2]; } delta = delta * delta * 0.0001; /* never take falling damage if completely underwater */ if (ent->waterlevel == 3) { return; } if (ent->waterlevel == 2) { delta *= 0.25; } if (ent->waterlevel == 1) { delta *= 0.5; } if (delta < 1) { return; } if (delta < 15) { ent->s.event = EV_FOOTSTEP; return; } ent->client->fall_value = delta * 0.5; if (ent->client->fall_value > 40) { ent->client->fall_value = 40; } ent->client->fall_time = level.time + FALL_TIME; if (delta > 30) { if (ent->health > 0) { if (delta >= 55) { ent->s.event = EV_FALLFAR; } else { ent->s.event = EV_FALL; } } ent->pain_debounce_time = level.time; /* no normal pain sound */ damage = (delta - 30) / 2; if (damage < 1) { damage = 1; } VectorSet(dir, 0, 0, 1); if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING)) { T_Damage(ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); } } else { ent->s.event = EV_FALLSHORT; return; } } void P_WorldEffects(void) { qboolean breather; qboolean envirosuit; int waterlevel, old_waterlevel; if (current_player->movetype == MOVETYPE_NOCLIP) { current_player->air_finished = level.time + 12; /* don't need air */ return; } waterlevel = current_player->waterlevel; old_waterlevel = current_client->old_waterlevel; current_client->old_waterlevel = waterlevel; breather = current_client->breather_framenum > level.framenum; envirosuit = current_client->enviro_framenum > level.framenum; /* if just entered a water volume, play a sound */ if (!old_waterlevel && waterlevel) { PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); if (current_player->watertype & CONTENTS_LAVA) { gi.sound(current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0); } else if (current_player->watertype & CONTENTS_SLIME) { gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); } else if (current_player->watertype & CONTENTS_WATER) { gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); } current_player->flags |= FL_INWATER; /* clear damage_debounce, so the pain sound will play immediately */ current_player->damage_debounce_time = level.time - 1; } /* if just completely exited a water volume, play a sound */ if (old_waterlevel && !waterlevel) { PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); current_player->flags &= ~FL_INWATER; } /* check for head just going under water */ if ((old_waterlevel != 3) && (waterlevel == 3)) { gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0); } /* check for head just coming out of water */ if ((old_waterlevel == 3) && (waterlevel != 3)) { if (current_player->air_finished < level.time) { /* gasp for air */ gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0); PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); } else if (current_player->air_finished < level.time + 11) { /* just break surface */ gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0); } } /* check for drowning */ if (waterlevel == 3) { /* breather or envirosuit give air */ if (breather || envirosuit) { current_player->air_finished = level.time + 10; if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0) { if (!current_client->breather_sound) { gi.sound(current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0); } else { gi.sound(current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0); } current_client->breather_sound ^= 1; PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); } } /* if out of air, start drowning */ if (current_player->air_finished < level.time) { /* drown! */ if ((current_player->client->next_drown_time < level.time) && (current_player->health > 0)) { current_player->client->next_drown_time = level.time + 1; /* take more damage the longer underwater */ current_player->dmg += 2; if (current_player->dmg > 15) { current_player->dmg = 15; } /* play a gurp sound instead of a normal pain sound */ if (current_player->health <= current_player->dmg) { gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0); } else if (rand() & 1) { gi.sound(current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0); } else { gi.sound(current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0); } current_player->pain_debounce_time = level.time; T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); } } } else { current_player->air_finished = level.time + 12; current_player->dmg = 2; } /* check for sizzle damage */ if (waterlevel && (current_player->watertype & (CONTENTS_LAVA | CONTENTS_SLIME))) { if (current_player->watertype & CONTENTS_LAVA) { if ((current_player->health > 0) && (current_player->pain_debounce_time <= level.time) && (current_client->invincible_framenum < level.framenum) && !(current_player->flags & FL_GODMODE)) { if (rand() & 1) { gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0); } else { gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0); } current_player->pain_debounce_time = level.time + 1; } if (envirosuit) /* take 1/3 damage with envirosuit */ { T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1 * waterlevel, 0, 0, MOD_LAVA); } else { T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3 * waterlevel, 0, 0, MOD_LAVA); } } if (current_player->watertype & CONTENTS_SLIME) { if (!envirosuit) { /* no damage from slime with envirosuit */ T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1 * waterlevel, 0, 0, MOD_SLIME); } } } } void G_SetClientEffects(edict_t *ent) { int pa_type; int remaining; if (!ent) { return; } ent->s.effects = 0; /* player is always ir visible, even dead. */ ent->s.renderfx = RF_IR_VISIBLE; if ((ent->health <= 0) || level.intermissiontime) { return; } if (ent->flags & FL_DISGUISED) { ent->s.renderfx |= RF_USE_DISGUISE; } if (gamerules && gamerules->value) { if (DMGame.PlayerEffects) { DMGame.PlayerEffects(ent); } } if (ent->powerarmor_time > level.time) { pa_type = PowerArmorType(ent); if (pa_type == POWER_ARMOR_SCREEN) { ent->s.effects |= EF_POWERSCREEN; } else if (pa_type == POWER_ARMOR_SHIELD) { ent->s.effects |= EF_COLOR_SHELL; ent->s.renderfx |= RF_SHELL_GREEN; } } if (ent->client->quad_framenum > level.framenum) { remaining = ent->client->quad_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_QUAD; } } if (ent->client->double_framenum > level.framenum) { remaining = ent->client->double_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_DOUBLE; } } if ((ent->client->owned_sphere) && (ent->client->owned_sphere->spawnflags == 1)) { ent->s.effects |= EF_HALF_DAMAGE; } if (ent->client->tracker_pain_framenum > level.framenum) { ent->s.effects |= EF_TRACKERTRAIL; } if (ent->client->invincible_framenum > level.framenum) { remaining = ent->client->invincible_framenum - level.framenum; if ((remaining > 30) || (remaining & 4)) { ent->s.effects |= EF_PENT; } } /* show cheaters!!! */ if (ent->flags & FL_GODMODE) { ent->s.effects |= EF_COLOR_SHELL; ent->s.renderfx |= (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE); } } void G_SetClientEvent(edict_t *ent) { if (!ent) { return; } if (ent->s.event) { return; } if (ent->health <= 0) { return; } if (g_footsteps->value == 1) { if (ent->groundentity && (xyspeed > 225)) { if ((int)(current_client->bobtime + bobmove) != bobcycle) { ent->s.event = EV_FOOTSTEP; } } } else if (g_footsteps->value == 2) { if (ent->groundentity) { if ((int)(current_client->bobtime + bobmove) != bobcycle) { ent->s.event = EV_FOOTSTEP; } } } else if (g_footsteps->value >= 3) { if ((int)(current_client->bobtime + bobmove) != bobcycle) { ent->s.event = EV_FOOTSTEP; } } } void G_SetClientSound(edict_t *ent) { char *weap; if (!ent) { return; } if (ent->client->pers.game_helpchanged != game.helpchanged) { ent->client->pers.game_helpchanged = game.helpchanged; ent->client->pers.helpchanged = 1; } /* help beep (no more than three times) */ if (ent->client->pers.helpchanged && (ent->client->pers.helpchanged <= 3) && !(level.framenum & 63)) { ent->client->pers.helpchanged++; gi.sound(ent, CHAN_VOICE, gi.soundindex("misc/pc_up.wav"), 1, ATTN_STATIC, 0); } if (ent->client->pers.weapon) { weap = ent->client->pers.weapon->classname; } else { weap = ""; } if (ent->waterlevel && (ent->watertype & (CONTENTS_LAVA | CONTENTS_SLIME))) { ent->s.sound = snd_fry; } else if (strcmp(weap, "weapon_railgun") == 0) { ent->s.sound = gi.soundindex("weapons/rg_hum.wav"); } else if (strcmp(weap, "weapon_bfg") == 0) { ent->s.sound = gi.soundindex("weapons/bfg_hum.wav"); } else if (ent->client->weapon_sound) { ent->s.sound = ent->client->weapon_sound; } else { ent->s.sound = 0; } } void G_SetClientFrame(edict_t *ent) { gclient_t *client; qboolean duck, run; if (!ent) { return; } if (ent->s.modelindex != 255) { return; /* not in the player model */ } client = ent->client; if (client->ps.pmove.pm_flags & PMF_DUCKED) { duck = true; } else { duck = false; } if (xyspeed) { run = true; } else { run = false; } /* check for stand/duck and stop/go transitions */ if ((duck != client->anim_duck) && (client->anim_priority < ANIM_DEATH)) { goto newanim; } if ((run != client->anim_run) && (client->anim_priority == ANIM_BASIC)) { goto newanim; } if (!ent->groundentity && (client->anim_priority <= ANIM_WAVE)) { goto newanim; } if (client->anim_priority == ANIM_REVERSE) { if (ent->s.frame > client->anim_end) { ent->s.frame--; return; } } else if (ent->s.frame < client->anim_end) { /* continue an animation */ ent->s.frame++; return; } if (client->anim_priority == ANIM_DEATH) { return; /* stay there */ } if (client->anim_priority == ANIM_JUMP) { if (!ent->groundentity) { return; /* stay there */ } ent->client->anim_priority = ANIM_WAVE; ent->s.frame = FRAME_jump3; ent->client->anim_end = FRAME_jump6; return; } newanim: /* return to either a running or standing frame */ client->anim_priority = ANIM_BASIC; client->anim_duck = duck; client->anim_run = run; if (!ent->groundentity) { client->anim_priority = ANIM_JUMP; if (ent->s.frame != FRAME_jump2) { ent->s.frame = FRAME_jump1; } client->anim_end = FRAME_jump2; } else if (run) { /* running */ if (duck) { ent->s.frame = FRAME_crwalk1; client->anim_end = FRAME_crwalk6; } else { ent->s.frame = FRAME_run1; client->anim_end = FRAME_run6; } } else { /* standing */ if (duck) { ent->s.frame = FRAME_crstnd01; client->anim_end = FRAME_crstnd19; } else { ent->s.frame = FRAME_stand01; client->anim_end = FRAME_stand40; } } } /* * Called for each player at the end of * the server frame and right after spawning */ void ClientEndServerFrame(edict_t *ent) { float bobtime; int i; if (!ent) { return; } current_player = ent; current_client = ent->client; /* If the origin or velocity have changed since ClientThink(), update the pmove values. This will happen when the client is pushed by a bmodel or kicked by an explosion. If it wasn't updated here, the view position would lag a frame behind the body position when pushed -- "sinking into plats" */ for (i = 0; i < 3; i++) { current_client->ps.pmove.origin[i] = ent->s.origin[i] * 8.0; current_client->ps.pmove.velocity[i] = ent->velocity[i] * 8.0; } /* If the end of unit layout is displayed, don't give the player any normal movement attributes */ if (level.intermissiontime) { current_client->ps.blend[3] = 0; current_client->ps.fov = 90; G_SetStats(ent); return; } AngleVectors(ent->client->v_angle, forward, right, up); /* burn from lava, etc */ P_WorldEffects(); /* set model angles from view angles so other things in the world can tell which direction you are looking */ if (ent->client->v_angle[PITCH] > 180) { ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH]) / 3; } else { ent->s.angles[PITCH] = ent->client->v_angle[PITCH] / 3; } ent->s.angles[YAW] = ent->client->v_angle[YAW]; ent->s.angles[ROLL] = 0; ent->s.angles[ROLL] = SV_CalcRoll(ent->s.angles, ent->velocity) * 4; /* calculate speed and cycle to be used for all cyclic walking effects */ xyspeed = sqrt( ent->velocity[0] * ent->velocity[0] + ent->velocity[1] * ent->velocity[1]); if (xyspeed < 5) { bobmove = 0; current_client->bobtime = 0; /* start at beginning of cycle again */ } else if (ent->groundentity) { /* so bobbing only cycles when on ground */ if (xyspeed > 210) { bobmove = 0.25; } else if (xyspeed > 100) { bobmove = 0.125; } else { bobmove = 0.0625; } } bobtime = (current_client->bobtime += bobmove); if (current_client->ps.pmove.pm_flags & PMF_DUCKED) { bobtime *= 4; } bobcycle = (int)bobtime; bobfracsin = fabs(sin(bobtime * M_PI)); /* detect hitting the floor */ P_FallingDamage(ent); /* apply all the damage taken this frame */ P_DamageFeedback(ent); /* determine the view offsets */ SV_CalcViewOffset(ent); /* determine the gun offsets */ SV_CalcGunOffset(ent); /* determine the full screen color blend must be after viewoffset, so eye contents can be accurately determined */ SV_CalcBlend(ent); /* chase cam stuff */ if (ent->client->resp.spectator) { G_SetSpectatorStats(ent); } else { G_SetStats(ent); } G_CheckChaseStats(ent); G_SetClientEvent(ent); G_SetClientEffects(ent); G_SetClientSound(ent); G_SetClientFrame(ent); VectorCopy(ent->velocity, ent->client->oldvelocity); VectorCopy(ent->client->ps.viewangles, ent->client->oldviewangles); /* clear weapon kicks */ VectorClear(ent->client->kick_origin); VectorClear(ent->client->kick_angles); if (!(level.framenum & 31)) { /* if the scoreboard is up, update it */ if (ent->client->showscores) { DeathmatchScoreboardMessage(ent, ent->enemy); gi.unicast(ent, false); } /* if the help computer is up, update it */ if (ent->client->showhelp) { ent->client->pers.helpchanged = 0; HelpComputerMessage(ent); gi.unicast(ent, false); } } /* if the inventory is up, update it */ if (ent->client->showinventory) { InventoryMessage(ent); gi.unicast(ent, false); } } rogue-ROGUE_2_13/src/player/weapon.c000066400000000000000000001463721477320066100173450ustar00rootroot00000000000000/* ======================================================================= * * Player weapons. * * ======================================================================= */ #include "../header/local.h" #include "../monster/misc/player.h" #include #define PLAYER_NOISE_SELF 0 #define PLAYER_NOISE_IMPACT 1 #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1) #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1) #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1) #define GRENADE_TIMER 3.0 #define GRENADE_MINSPEED 400 #define GRENADE_MAXSPEED 800 #define CHAINFIST_REACH 64 #define HEATBEAM_DM_DMG 15 #define HEATBEAM_SP_DMG 15 static qboolean is_quad; static byte damage_multiplier; static byte is_silenced; void weapon_grenade_fire(edict_t *ent, qboolean held); byte P_DamageModifier(edict_t *ent) { is_quad = 0; damage_multiplier = 1; if (!ent) { return 0; } if (ent->client->quad_framenum > level.framenum) { damage_multiplier *= 4; is_quad = 1; /* if we're quad and DF_NO_STACK_DOUBLE is on, return now. */ if (((int)(dmflags->value) & DF_NO_STACK_DOUBLE)) { return damage_multiplier; } } if (ent->client->double_framenum > level.framenum) { if ((deathmatch->value) || (damage_multiplier == 1)) { damage_multiplier *= 2; is_quad = 1; } } return damage_multiplier; } void P_ProjectSource(edict_t *ent, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) { gclient_t *client = ent->client; float *point = ent->s.origin; vec3_t _distance; if (!client) { return; } VectorCopy(distance, _distance); if (client->pers.hand == LEFT_HANDED) { _distance[1] *= -1; } else if (client->pers.hand == CENTER_HANDED) { _distance[1] = 0; } G_ProjectSource(point, _distance, forward, right, result); // Berserker: fix - now the projectile hits exactly where the scope is pointing. if (aimfix->value) { vec3_t start, end; VectorSet(start, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] + ent->viewheight); VectorMA(start, 8192, forward, end); trace_t tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); if (tr.fraction < 1) { VectorSubtract(tr.endpos, result, forward); VectorNormalize(forward); } } } void P_ProjectSource2(edict_t *ent, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t up, vec3_t result) { gclient_t *client = ent->client; vec3_t _distance; if (!client) { return; } VectorCopy(distance, _distance); if (client->pers.hand == LEFT_HANDED) { _distance[1] *= -1; } else if (client->pers.hand == CENTER_HANDED) { _distance[1] = 0; } G_ProjectSource2(point, _distance, forward, right, up, result); // Berserker: fix - now the projectile hits exactly where the scope is pointing. if (aimfix->value) { vec3_t start, end; VectorSet(start, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] + ent->viewheight); VectorMA(start, 8192, forward, end); trace_t tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); if (tr.fraction < 1) { VectorSubtract(tr.endpos, result, forward); VectorNormalize(forward); } } } /* * Each player can have two noise objects associated with it: * a personal noise (jumping, pain, weapon firing), and a weapon * target noise (bullet wall impacts) * * Monsters that don't directly see the player can move * to a noise in hopes of seeing the player from there. */ static edict_t * PlayerNoise_Spawn(edict_t *who, int type) { edict_t *noise; if (!who) { return NULL; } noise = G_SpawnOptional(); if (!noise) { return NULL; } noise->classname = "player_noise"; noise->spawnflags = type; VectorSet (noise->mins, -8, -8, -8); VectorSet (noise->maxs, 8, 8, 8); noise->owner = who; noise->svflags = SVF_NOCLIENT; return noise; } static void PlayerNoise_Verify(edict_t *who) { edict_t *e; edict_t *n1; edict_t *n2; if (!who) { return; } n1 = who->mynoise; n2 = who->mynoise2; if (n1 && !n1->inuse) { n1 = NULL; } if (n2 && !n2->inuse) { n2 = NULL; } if (n1 && n2) { return; } for (e = g_edicts + 1 + game.maxclients; e < &g_edicts[globals.num_edicts]; e++) { if (!e->inuse || strcmp(e->classname, "player_noise") != 0) { continue; } if (e->owner && e->owner != who) { continue; } e->owner = who; if (!n2 && (e->spawnflags == PLAYER_NOISE_IMPACT || n1)) { n2 = e; } else { n1 = e; } if (n1 && n2) { break; } } if (!n1) { n1 = PlayerNoise_Spawn(who, PLAYER_NOISE_SELF); } if (!n2) { n2 = PlayerNoise_Spawn(who, PLAYER_NOISE_IMPACT); } who->mynoise = n1; who->mynoise2 = n2; } void PlayerNoise(edict_t *who, vec3_t where, int type) { edict_t *noise; if (!who || !who->client) { return; } if (type == PNOISE_WEAPON) { if (who->client->silencer_shots) { who->client->silencer_shots--; return; } } if (deathmatch->value) { return; } if (who->flags & FL_NOTARGET) { return; } if (who->flags & FL_DISGUISED) { if (type == PNOISE_WEAPON) { level.disguise_violator = who; level.disguise_violation_framenum = level.framenum + 5; } else { return; } } PlayerNoise_Verify(who); if ((type == PNOISE_SELF) || (type == PNOISE_WEAPON)) { if (level.framenum <= (level.sound_entity_framenum + 3)) { return; } if (!who->mynoise) { return; } noise = who->mynoise; level.sound_entity = noise; level.sound_entity_framenum = level.framenum; } else { if (level.framenum <= (level.sound2_entity_framenum + 3)) { return; } if (!who->mynoise2) { return; } noise = who->mynoise2; level.sound2_entity = noise; level.sound2_entity_framenum = level.framenum; } VectorCopy(where, noise->s.origin); VectorSubtract(where, noise->maxs, noise->absmin); VectorAdd(where, noise->maxs, noise->absmax); noise->last_sound_time = level.time; gi.linkentity(noise); } qboolean Pickup_Weapon(edict_t *ent, edict_t *other) { int index; gitem_t *ammo; if (!ent || !other) { return false; } index = ITEM_INDEX(ent->item); if ((((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) && other->client->pers.inventory[index]) { if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)) && (!coop_pickup_weapons->value || (ent->flags & FL_COOP_TAKEN))) { return false; /* leave the weapon for others to pickup */ } } other->client->pers.inventory[index]++; if (!(ent->spawnflags & DROPPED_ITEM)) { /* give them some ammo with it */ if (ent->item->ammo) { ammo = FindItem(ent->item->ammo); if ((int)dmflags->value & DF_INFINITE_AMMO) { Add_Ammo(other, ammo, 1000); } else { Add_Ammo(other, ammo, ammo->quantity); } } if (!(ent->spawnflags & DROPPED_PLAYER_ITEM)) { if (deathmatch->value) { if ((int)(dmflags->value) & DF_WEAPONS_STAY) { ent->flags |= FL_RESPAWN; } else { SetRespawn(ent, 30); } } if (coop->value) { ent->flags |= FL_RESPAWN; ent->flags |= FL_COOP_TAKEN; } } } if ((other->client->pers.weapon != ent->item) && (other->client->pers.inventory[index] == 1) && (!deathmatch->value || (other->client->pers.weapon == FindItem("blaster")))) { other->client->newweapon = ent->item; } return true; } /* * The old weapon has been dropped all the * way, so make the new one current */ void ChangeWeapon(edict_t *ent) { int i; if (!ent) { return; } if (ent->client->grenade_time) { ent->client->grenade_time = level.time; ent->client->weapon_sound = 0; weapon_grenade_fire(ent, false); ent->client->grenade_time = 0; } ent->client->pers.lastweapon = ent->client->pers.weapon; ent->client->pers.weapon = ent->client->newweapon; ent->client->newweapon = NULL; ent->client->machinegun_shots = 0; /* set visible model */ if (ent->s.modelindex == 255) { if (ent->client->pers.weapon) { i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8); } else { i = 0; } ent->s.skinnum = (ent - g_edicts - 1) | i; } if (ent->client->pers.weapon && ent->client->pers.weapon->ammo) { ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo)); } else { ent->client->ammo_index = 0; } if (!ent->client->pers.weapon) { /* dead */ ent->client->ps.gunindex = 0; return; } ent->client->weaponstate = WEAPON_ACTIVATING; ent->client->ps.gunframe = 0; ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); ent->client->anim_priority = ANIM_PAIN; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crpain1; ent->client->anim_end = FRAME_crpain4; } else { ent->s.frame = FRAME_pain301; ent->client->anim_end = FRAME_pain304; } } void NoAmmoWeaponChange(edict_t *ent) { if (!ent) { return; } if (ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))]) { ent->client->newweapon = FindItem("railgun"); return; } if ((ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] >= 2) && ent->client->pers.inventory[ITEM_INDEX(FindItem("Plasma Beam"))]) { ent->client->newweapon = FindItem("Plasma Beam"); return; } if (ent->client->pers.inventory[ITEM_INDEX(FindItem("flechettes"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("etf rifle"))]) { ent->client->newweapon = FindItem("etf rifle"); return; } if (ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))]) { ent->client->newweapon = FindItem("chaingun"); return; } if (ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))]) { ent->client->newweapon = FindItem("machinegun"); return; } if ((ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1) && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))]) { ent->client->newweapon = FindItem("super shotgun"); return; } if (ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))]) { ent->client->newweapon = FindItem("shotgun"); return; } ent->client->newweapon = FindItem("blaster"); } /* * Called by ClientBeginServerFrame and ClientThink */ void Think_Weapon(edict_t *ent) { if (!ent) { return; } /* if just died, put the weapon away */ if (ent->health < 1) { ent->client->newweapon = NULL; ChangeWeapon(ent); } /* call active weapon think routine */ if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) { P_DamageModifier(ent); if (ent->client->silencer_shots) { is_silenced = MZ_SILENCED; } else { is_silenced = 0; } ent->client->pers.weapon->weaponthink(ent); } } /* * Client (player) animation for changing weapon */ static void Change_Weap_Animation(edict_t *ent) { if (!ent) { return; } ent->client->anim_priority = ANIM_REVERSE; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crpain4 + 1; ent->client->anim_end = FRAME_crpain1; } else { ent->s.frame = FRAME_pain304 + 1; ent->client->anim_end = FRAME_pain301; } } /* * Make the weapon ready if there is ammo */ void Use_Weapon(edict_t *ent, gitem_t *item) { int ammo_index; gitem_t *ammo_item; if (!ent || !item) { return; } /* see if we're already using it */ if (item == ent->client->pers.weapon) { return; } if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) { ammo_item = FindItem(item->ammo); ammo_index = ITEM_INDEX(ammo_item); if (!ent->client->pers.inventory[ammo_index]) { gi.cprintf(ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name); return; } if (ent->client->pers.inventory[ammo_index] < item->quantity) { gi.cprintf(ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name); return; } } /* change to this weapon when down */ ent->client->newweapon = item; } void Drop_Weapon(edict_t *ent, gitem_t *item) { int index; if (!ent || !item) { return; } if ((int)(dmflags->value) & DF_WEAPONS_STAY) { return; } index = ITEM_INDEX(item); /* see if we're already using it */ if (((item == ent->client->pers.weapon) || (item == ent->client->newweapon)) && (ent->client->pers.inventory[index] == 1)) { gi.cprintf(ent, PRINT_HIGH, "Can't drop current weapon\n"); return; } Drop_Item(ent, item); ent->client->pers.inventory[index]--; } /* * A generic function to handle the basics of weapon thinking */ void Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent)) { int n; const unsigned short int change_speed = (g_swap_speed->value > 1)? (g_swap_speed->value < USHRT_MAX)? (unsigned short int)g_swap_speed->value : 1 : 1; if (!ent || !fire) { return; } if (ent->deadflag || (ent->s.modelindex != 255)) /* VWep animations screw up corpses */ { return; } if (ent->client->weaponstate == WEAPON_DROPPING) { if (ent->client->ps.gunframe >= FRAME_DEACTIVATE_LAST - change_speed + 1) { ChangeWeapon(ent); return; } else if ( (FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) >= (4 * change_speed) ) { unsigned short int remainder = FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe; // "if (remainder == 4)" at change_speed == 1 if ( ( remainder <= (4 * change_speed) ) && ( remainder > (3 * change_speed) ) ) { Change_Weap_Animation(ent); } } ent->client->ps.gunframe += change_speed; return; } if (ent->client->weaponstate == WEAPON_ACTIVATING) { if (ent->client->ps.gunframe >= FRAME_ACTIVATE_LAST - change_speed + 1) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } ent->client->ps.gunframe += change_speed; return; } if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) { ent->client->weaponstate = WEAPON_DROPPING; ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; if ( (FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < (4 * change_speed) ) { Change_Weap_Animation(ent); } return; } if (ent->client->weaponstate == WEAPON_READY) { if (((ent->client->latched_buttons | ent->client->buttons) & BUTTON_ATTACK)) { ent->client->latched_buttons &= ~BUTTON_ATTACK; if ((!ent->client->ammo_index) || (ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; /* start the animation */ ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - 1; ent->client->anim_end = FRAME_attack8; } } else { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); } } else { if (ent->client->ps.gunframe == FRAME_IDLE_LAST) { ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } if (pause_frames) { for (n = 0; pause_frames[n]; n++) { if (ent->client->ps.gunframe == pause_frames[n]) { if (rand() & 15) { return; } } } } ent->client->ps.gunframe++; return; } } if (ent->client->weaponstate == WEAPON_FIRING) { for (n = 0; fire_frames[n]; n++) { if (ent->client->ps.gunframe == fire_frames[n]) { if (ent->client->quad_framenum > level.framenum) { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (ent->client->double_framenum > level.framenum) { gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } fire(ent); break; } } if (!fire_frames[n]) { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == FRAME_IDLE_FIRST + 1) { ent->client->weaponstate = WEAPON_READY; } } } /* * ====================================================================== * * GRENADE * * ====================================================================== */ void weapon_grenade_fire(edict_t *ent, qboolean held) { vec3_t offset; vec3_t forward, right, up; vec3_t start; int damage = 125; float timer; int speed; float radius; if (!ent) { return; } radius = damage + 40; if (is_quad) { damage *= damage_multiplier; if (damage_multiplier >= 4) { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); } else if (damage_multiplier == 2) { gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0); } } AngleVectors(ent->client->v_angle, forward, right, up); if (ent->client->pers.weapon->tag == AMMO_TESLA) { VectorSet(offset, 0, -4, ent->viewheight - 22); } else { VectorSet(offset, 2, 6, ent->viewheight - 14); } P_ProjectSource2(ent, ent->s.origin, offset, forward, right, up, start); timer = ent->client->grenade_time - level.time; speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); if (speed > GRENADE_MAXSPEED) { speed = GRENADE_MAXSPEED; } switch (ent->client->pers.weapon->tag) { case AMMO_GRENADES: fire_grenade2(ent, start, forward, damage, speed, timer, radius, held); break; default: fire_tesla(ent, start, forward, damage_multiplier, speed); break; } if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } ent->client->grenade_time = level.time + 1.0; if (ent->deadflag || (ent->s.modelindex != 255)) /* VWep animations screw up corpses */ { return; } if (ent->health <= 0) { return; } if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->client->anim_priority = ANIM_ATTACK; ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak3; } else { ent->client->anim_priority = ANIM_REVERSE; ent->s.frame = FRAME_wave08; ent->client->anim_end = FRAME_wave01; } } void Throw_Generic(edict_t *ent, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_THROW_SOUND, int FRAME_THROW_HOLD, int FRAME_THROW_FIRE, int *pause_frames, int EXPLODE, void (*fire)(edict_t *ent, qboolean held)) { int n; if (!ent || !pause_frames || !fire) { return; } if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) { ChangeWeapon(ent); return; } if (ent->client->weaponstate == WEAPON_ACTIVATING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } if (ent->client->weaponstate == WEAPON_READY) { if (((ent->client->latched_buttons | ent->client->buttons) & BUTTON_ATTACK)) { ent->client->latched_buttons &= ~BUTTON_ATTACK; if (ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 1; ent->client->weaponstate = WEAPON_FIRING; ent->client->grenade_time = 0; } else { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); } return; } if (ent->client->ps.gunframe == FRAME_IDLE_LAST) { ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } if (pause_frames) { for (n = 0; pause_frames[n]; n++) { if (ent->client->ps.gunframe == pause_frames[n]) { if (rand() & 15) { return; } } } } ent->client->ps.gunframe++; return; } if (ent->client->weaponstate == WEAPON_FIRING) { if (ent->client->ps.gunframe == FRAME_THROW_SOUND) { gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); } if (ent->client->ps.gunframe == FRAME_THROW_HOLD) { if (!ent->client->grenade_time) { ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; switch (ent->client->pers.weapon->tag) { case AMMO_GRENADES: ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); break; } } /* they waited too long, detonate it in their hand */ if (EXPLODE && !ent->client->grenade_blew_up && (level.time >= ent->client->grenade_time)) { ent->client->weapon_sound = 0; fire(ent, true); ent->client->grenade_blew_up = true; } if (ent->client->buttons & BUTTON_ATTACK) { return; } if (ent->client->grenade_blew_up) { if (level.time >= ent->client->grenade_time) { ent->client->ps.gunframe = FRAME_FIRE_LAST; ent->client->grenade_blew_up = false; } else { return; } } } if (ent->client->ps.gunframe == FRAME_THROW_FIRE) { ent->client->weapon_sound = 0; fire(ent, true); } if ((ent->client->ps.gunframe == FRAME_FIRE_LAST) && (level.time < ent->client->grenade_time)) { return; } ent->client->ps.gunframe++; if (ent->client->ps.gunframe == FRAME_IDLE_FIRST) { ent->client->grenade_time = 0; ent->client->weaponstate = WEAPON_READY; } } } void Weapon_Grenade(edict_t *ent) { static int pause_frames[] = {29, 34, 39, 48, 0}; if (!ent) { return; } Throw_Generic(ent, 15, 48, 5, 11, 12, pause_frames, GRENADE_TIMER, weapon_grenade_fire); } void Weapon_Tesla(edict_t *ent) { static int pause_frames[] = {21, 0}; if (!ent) { return; } if ((ent->client->ps.gunframe > 1) && (ent->client->ps.gunframe < 9)) { ent->client->ps.gunindex = gi.modelindex("models/weapons/v_tesla2/tris.md2"); } else { ent->client->ps.gunindex = gi.modelindex("models/weapons/v_tesla/tris.md2"); } Throw_Generic(ent, 8, 32, 99, 1, 2, pause_frames, 0, weapon_grenade_fire); } /* * ====================================================================== * * GRENADE LAUNCHER * * ====================================================================== */ void weapon_grenadelauncher_fire(edict_t *ent) { vec3_t offset; vec3_t forward, right; vec3_t start; int damage; float radius; if (!ent) { return; } switch (ent->client->pers.weapon->tag) { case AMMO_PROX: damage = 90; break; default: damage = 120; break; } radius = damage + 40; if (is_quad) { damage *= damage_multiplier; } VectorSet(offset, 8, 8, ent->viewheight - 8); AngleVectors(ent->client->v_angle, forward, right, NULL); P_ProjectSource(ent, offset, forward, right, start); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; switch (ent->client->pers.weapon->tag) { case AMMO_PROX: fire_prox(ent, start, forward, damage_multiplier, 600); break; default: fire_grenade(ent, start, forward, damage, 600, 2.5, radius); break; } gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte(MZ_GRENADE | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } } void Weapon_GrenadeLauncher(edict_t *ent) { static int pause_frames[] = {34, 51, 59, 0}; static int fire_frames[] = {6, 0}; if (!ent) { return; } Weapon_Generic(ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); } void Weapon_ProxLauncher(edict_t *ent) { static int pause_frames[] = {34, 51, 59, 0}; static int fire_frames[] = {6, 0}; if (!ent) { return; } Weapon_Generic(ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); } /* * ====================================================================== * * ROCKET * * ====================================================================== */ void Weapon_RocketLauncher_Fire(edict_t *ent) { vec3_t offset, start; vec3_t forward, right; int damage; float damage_radius; int radius_damage; if (!ent) { return; } damage = 100 + (int)(random() * 20.0); radius_damage = 120; damage_radius = 120; if (is_quad) { damage *= damage_multiplier; radius_damage *= damage_multiplier; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 8, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); fire_rocket(ent, start, forward, damage, 650, damage_radius, radius_damage); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_ROCKET | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } } void Weapon_RocketLauncher(edict_t *ent) { static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; if (!ent) { return; } Weapon_Generic(ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); } /* * ====================================================================== * * BLASTER / HYPERBLASTER * * ====================================================================== */ void Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect) { vec3_t forward, right; vec3_t start; vec3_t offset; if (!ent) { return; } if (is_quad) { damage *= damage_multiplier; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorSet(offset, 24, 8, ent->viewheight - 8); VectorAdd(offset, g_offset, offset); P_ProjectSource(ent, offset, forward, right, start); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; fire_blaster(ent, start, forward, damage, 1000, effect, hyper); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); if (hyper) { gi.WriteByte(MZ_HYPERBLASTER | is_silenced); } else { gi.WriteByte(MZ_BLASTER | is_silenced); } gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); } void Weapon_Blaster_Fire(edict_t *ent) { int damage; if (!ent) { return; } if (deathmatch->value) { damage = 15; } else { damage = 10; } Blaster_Fire(ent, vec3_origin, damage, false, EF_BLASTER); ent->client->ps.gunframe++; } void Weapon_Blaster(edict_t *ent) { static int pause_frames[] = {19, 32, 0}; static int fire_frames[] = {5, 0}; if (!ent) { return; } Weapon_Generic(ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); } void Weapon_HyperBlaster_Fire(edict_t *ent) { float rotation; vec3_t offset; int effect; int damage; if (!ent) { return; } ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe++; } else { if (!ent->client->pers.inventory[ent->client->ammo_index]) { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); } else { rotation = (ent->client->ps.gunframe - 5) * 2 * M_PI / 6; offset[0] = -4 * sin(rotation); offset[1] = 0; offset[2] = 4 * cos(rotation); if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) { effect = EF_HYPERBLASTER; } else { effect = 0; } if (deathmatch->value) { damage = 15; } else { damage = 20; } Blaster_Fire(ent, offset, damage, true, effect); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - 1; ent->client->anim_end = FRAME_attack8; } } ent->client->ps.gunframe++; if ((ent->client->ps.gunframe == 12) && ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 6; } } if (ent->client->ps.gunframe == 12) { gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); ent->client->weapon_sound = 0; } } void Weapon_HyperBlaster(edict_t *ent) { static int pause_frames[] = {0}; static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; if (!ent) { return; } Weapon_Generic(ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); } /* * ====================================================================== * * MACHINEGUN / CHAINGUN * * ====================================================================== */ void Machinegun_Fire(edict_t *ent) { int i; vec3_t start; vec3_t forward, right; vec3_t angles; int damage = 8; int kick = 2; vec3_t offset; if (!ent) { return; } if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->machinegun_shots = 0; ent->client->ps.gunframe++; return; } if (ent->client->ps.gunframe == 5) { ent->client->ps.gunframe = 4; } else { ent->client->ps.gunframe = 5; } if (ent->client->pers.inventory[ent->client->ammo_index] < 1) { ent->client->ps.gunframe = 6; if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); return; } if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } for (i = 1; i < 3; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } ent->client->kick_origin[0] = crandom() * 0.35; ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; /* raise the gun as it is firing */ if (!(deathmatch->value || g_machinegun_norecoil->value)) { ent->client->machinegun_shots++; if (ent->client->machinegun_shots > 9) { ent->client->machinegun_shots = 9; } } /* get start / end positions */ VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles); AngleVectors(angles, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); fire_bullet(ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_MACHINEGUN | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (int)(random() + 0.25); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (int)(random() + 0.25); ent->client->anim_end = FRAME_attack8; } } void Weapon_Machinegun(edict_t *ent) { static int pause_frames[] = {23, 45, 0}; static int fire_frames[] = {4, 5, 0}; if (!ent) { return; } Weapon_Generic(ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); } void Chaingun_Fire(edict_t *ent) { int i; int shots; vec3_t start; vec3_t forward, right, up; float r, u; vec3_t offset; int damage; int kick = 2; if (!ent) { return; } if (deathmatch->value) { damage = 6; } else { damage = 8; } if (ent->client->ps.gunframe == 5) { gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); } if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe = 32; ent->client->weapon_sound = 0; return; } else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) && ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 15; } else { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == 22) { ent->client->weapon_sound = 0; gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); } else { ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_attack8; } if (ent->client->ps.gunframe <= 9) { shots = 1; } else if (ent->client->ps.gunframe <= 14) { if (ent->client->buttons & BUTTON_ATTACK) { shots = 2; } else { shots = 1; } } else { shots = 3; } if (ent->client->pers.inventory[ent->client->ammo_index] < shots) { shots = ent->client->pers.inventory[ent->client->ammo_index]; } if (!shots) { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); return; } if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } for (i = 0; i < 3; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } for (i = 0; i < shots; i++) { /* get start / end positions */ AngleVectors(ent->client->v_angle, forward, right, up); r = 7 + crandom() * 4; u = crandom() * 4; VectorSet(offset, 0, r, u + ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); fire_bullet(ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); } /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte((MZ_CHAINGUN1 + shots - 1) | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= shots; } } void Weapon_Chaingun(edict_t *ent) { static int pause_frames[] = {38, 43, 51, 61, 0}; static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; if (!ent) { return; } Weapon_Generic(ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); } /* * ====================================================================== * * SHOTGUN / SUPERSHOTGUN * * ====================================================================== */ void weapon_shotgun_fire(edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage = 4; int kick = 8; if (!ent) { return; } if (ent->client->ps.gunframe == 9) { ent->client->ps.gunframe++; return; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } fire_shotgun(ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_SHOTGUN | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } } void Weapon_Shotgun(edict_t *ent) { static int pause_frames[] = {22, 28, 34, 0}; static int fire_frames[] = {8, 9, 0}; if (!ent) { return; } Weapon_Generic(ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); } void weapon_supershotgun_fire(edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; vec3_t v; int damage = 6; int kick = 12; if (!ent) { return; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } v[PITCH] = ent->client->v_angle[PITCH]; v[YAW] = ent->client->v_angle[YAW] - 5; v[ROLL] = ent->client->v_angle[ROLL]; AngleVectors(v, forward, NULL, NULL); if (aimfix->value) { AngleVectors(v, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); } fire_shotgun(ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN); v[YAW] = ent->client->v_angle[YAW] + 5; AngleVectors(v, forward, NULL, NULL); if (aimfix->value) { AngleVectors(v, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); } fire_shotgun(ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_SSHOTGUN | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= 2; } } void Weapon_SuperShotgun(edict_t *ent) { static int pause_frames[] = {29, 42, 57, 0}; static int fire_frames[] = {7, 0}; if (!ent) { return; } Weapon_Generic(ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); } /* * ====================================================================== * * RAILGUN * * ====================================================================== */ void weapon_railgun_fire(edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage; int kick; if (!ent) { return; } if (deathmatch->value) { /* normal damage is too extreme in dm */ damage = 100; kick = 200; } else { damage = 150; kick = 250; } if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -3, ent->client->kick_origin); ent->client->kick_angles[0] = -3; VectorSet(offset, 0, 7, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); fire_rail(ent, start, forward, damage, kick); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_RAILGUN | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } } void Weapon_Railgun(edict_t *ent) { static int pause_frames[] = {56, 0}; static int fire_frames[] = {4, 0}; if (!ent) { return; } Weapon_Generic(ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); } /* * ====================================================================== * * BFG10K * * ====================================================================== */ void weapon_bfg_fire(edict_t *ent) { vec3_t offset, start; vec3_t forward, right; int damage; float damage_radius = 1000; if (!ent) { return; } if (deathmatch->value) { damage = 200; } else { damage = 500; } if (ent->client->ps.gunframe == 9) { /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_BFG | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); return; } /* cells can go down during windup (from power armor hits), so check again and abort firing if we don't have enough now */ if (ent->client->pers.inventory[ent->client->ammo_index] < 50) { ent->client->ps.gunframe++; return; } if (is_quad) { damage *= damage_multiplier; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); /* make a big pitch kick with an inverse fall */ ent->client->v_dmg_pitch = -40; ent->client->v_dmg_roll = crandom() * 8; ent->client->v_dmg_time = level.time + DAMAGE_TIME; VectorSet(offset, 8, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); fire_bfg(ent, start, forward, damage, 400, damage_radius); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= 50; } } void Weapon_BFG(edict_t *ent) { static int pause_frames[] = {39, 45, 50, 55, 0}; static int fire_frames[] = {9, 17, 0}; if (!ent) { return; } Weapon_Generic(ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); } /* CHAINFIST */ void weapon_chainfist_fire(edict_t *ent) { vec3_t offset; vec3_t forward, right, up; vec3_t start; int damage; if (!ent) { return; } damage = 15; if (deathmatch->value) { damage = 30; } if (is_quad) { damage *= damage_multiplier; } AngleVectors(ent->client->v_angle, forward, right, up); /* kick back */ VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; /* set start point */ VectorSet(offset, 0, 8, ent->viewheight - 4); P_ProjectSource(ent, offset, forward, right, start); fire_player_melee(ent, start, forward, CHAINFIST_REACH, damage, 100, 1, MOD_CHAINFIST); PlayerNoise(ent, start, PNOISE_WEAPON); ent->client->ps.gunframe++; ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; } /* * this spits out some smoke from the motor. it's a two-stroke, you know. */ void chainfist_smoke(edict_t *ent) { vec3_t tempVec, forward, right, up; vec3_t offset; if (!ent) { return; } AngleVectors(ent->client->v_angle, forward, right, up); VectorSet(offset, 8, 8, ent->viewheight - 4); P_ProjectSource(ent, offset, forward, right, tempVec); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_CHAINFIST_SMOKE); gi.WritePosition(tempVec); gi.unicast(ent, 0); } void Weapon_ChainFist(edict_t *ent) { static int pause_frames[] = {0}; static int fire_frames[] = {8, 9, 16, 17, 18, 30, 31, 0}; /* these are caches for the sound index. there's probably a better way to do this. */ float chance; int last_sequence; last_sequence = 0; if ((ent->client->ps.gunframe == 13) || (ent->client->ps.gunframe == 23)) /* end of attack, go idle */ { ent->client->ps.gunframe = 32; } /* holds for idle sequence */ else if ((ent->client->ps.gunframe == 42) && (rand() & 7)) { if ((ent->client->pers.hand != CENTER_HANDED) && (random() < 0.4)) { chainfist_smoke(ent); } } else if ((ent->client->ps.gunframe == 51) && (rand() & 7)) { if ((ent->client->pers.hand != CENTER_HANDED) && (random() < 0.4)) { chainfist_smoke(ent); } } /* set the appropriate weapon sound. */ if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weapon_sound = gi.soundindex("weapons/sawhit.wav"); } else if (ent->client->weaponstate == WEAPON_DROPPING) { ent->client->weapon_sound = 0; } else { ent->client->weapon_sound = gi.soundindex("weapons/sawidle.wav"); } Weapon_Generic(ent, 4, 32, 57, 60, pause_frames, fire_frames, weapon_chainfist_fire); if ((ent->client->buttons) & BUTTON_ATTACK) { if ((ent->client->ps.gunframe == 13) || (ent->client->ps.gunframe == 23) || (ent->client->ps.gunframe == 32)) { last_sequence = ent->client->ps.gunframe; ent->client->ps.gunframe = 6; } } if (ent->client->ps.gunframe == 6) { chance = random(); if (last_sequence == 13) /* if we just did sequence 1, do 2 or 3. */ { chance -= 0.34; } else if (last_sequence == 23) /* if we just did sequence 2, do 1 or 3 */ { chance += 0.33; } else if (last_sequence == 32) /* if we just did sequence 3, do 1 or 2 */ { if (chance >= 0.33) { chance += 0.34; } } if (chance < 0.33) { ent->client->ps.gunframe = 14; } else if (chance < 0.66) { ent->client->ps.gunframe = 24; } } } /* Disintegrator */ void weapon_tracker_fire(edict_t *self) { vec3_t forward, right; vec3_t start; vec3_t end; vec3_t offset; edict_t *enemy; trace_t tr; int damage; vec3_t mins, maxs; if (!self) { return; } if (deathmatch->value) { damage = 30; } else { damage = 45; } if (is_quad) { damage *= damage_multiplier; } VectorSet(mins, -16, -16, -16); VectorSet(maxs, 16, 16, 16); AngleVectors(self->client->v_angle, forward, right, NULL); VectorSet(offset, 24, 8, self->viewheight - 8); P_ProjectSource(self, offset, forward, right, start); VectorMA(start, 8192, forward, end); enemy = NULL; tr = gi.trace(start, vec3_origin, vec3_origin, end, self, MASK_SHOT); if (tr.ent != world) { if (tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE) { if (tr.ent->health > 0) { enemy = tr.ent; } } } else { tr = gi.trace(start, mins, maxs, end, self, MASK_SHOT); if (tr.ent != world) { if (tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE) { if (tr.ent->health > 0) { enemy = tr.ent; } } } } VectorScale(forward, -2, self->client->kick_origin); self->client->kick_angles[0] = -1; fire_tracker(self, start, forward, damage, 1000, enemy); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(self - g_edicts); gi.WriteByte(MZ_TRACKER); gi.multicast(self->s.origin, MULTICAST_PVS); PlayerNoise(self, start, PNOISE_WEAPON); self->client->ps.gunframe++; self->client->pers.inventory[self->client->ammo_index] -= self->client->pers.weapon->quantity; } void Weapon_Disintegrator(edict_t *ent) { static int pause_frames[] = {14, 19, 23, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic(ent, 4, 9, 29, 34, pause_frames, fire_frames, weapon_tracker_fire); } /* * ====================================================================== * * ETF RIFLE * * ====================================================================== */ void weapon_etf_rifle_fire(edict_t *ent) { vec3_t forward, right, up; vec3_t start, tempPt; int damage = 10; int kick = 3; int i; vec3_t offset; if (!ent) { return; } if (ent->client->pers.inventory[ent->client->ammo_index] < ent->client->pers.weapon->quantity) { VectorClear(ent->client->kick_origin); VectorClear(ent->client->kick_angles); ent->client->ps.gunframe = 8; if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); return; } if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } for (i = 0; i < 3; i++) { ent->client->kick_origin[i] = crandom() * 0.85; ent->client->kick_angles[i] = crandom() * 0.85; } /* get start / end positions */ AngleVectors(ent->client->v_angle, forward, right, up); if (ent->client->ps.gunframe == 6) /* right barrel */ { VectorSet(offset, 15, 8, -8); } else /* left barrel */ { VectorSet(offset, 15, 6, -8); } VectorCopy(ent->s.origin, tempPt); tempPt[2] += ent->viewheight; P_ProjectSource2(ent, tempPt, offset, forward, right, up, start); fire_flechette(ent, start, forward, damage, 750, kick); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_ETF_RIFLE); gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); ent->client->ps.gunframe++; if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - 1; ent->client->anim_end = FRAME_attack8; } } void Weapon_ETF_Rifle(edict_t *ent) { static int pause_frames[] = {18, 28, 0}; static int fire_frames[] = {6, 7, 0}; if (!ent) { return; } if (ent->client->weaponstate == WEAPON_FIRING) { if (ent->client->pers.inventory[ent->client->ammo_index] <= 0) { ent->client->ps.gunframe = 8; } } Weapon_Generic(ent, 4, 7, 37, 41, pause_frames, fire_frames, weapon_etf_rifle_fire); if ((ent->client->ps.gunframe == 8) && (ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe = 6; } } void Heatbeam_Fire(edict_t *ent) { vec3_t start; vec3_t forward, right, up; vec3_t offset; int damage; int kick; if (!ent) { return; } if (deathmatch->value) { damage = HEATBEAM_DM_DMG; kick = 75; /* really knock 'em around in deathmatch */ } else { damage = HEATBEAM_SP_DMG; kick = 30; } ent->client->ps.gunframe++; ent->client->ps.gunindex = gi.modelindex("models/weapons/v_beamer2/tris.md2"); if (is_quad) { damage *= damage_multiplier; kick *= damage_multiplier; } VectorClear(ent->client->kick_origin); VectorClear(ent->client->kick_angles); /* get start / end positions */ AngleVectors(ent->client->v_angle, forward, right, up); /* This offset is the "view" offset for the beam start (used by trace) */ VectorSet(offset, 7, 2, ent->viewheight - 3); P_ProjectSource(ent, offset, forward, right, start); /* This offset is the entity offset */ VectorSet(offset, 2, 7, -3); fire_heat(ent, start, forward, offset, damage, kick, false); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_HEATBEAM | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - 1; ent->client->anim_end = FRAME_attack8; } } void Weapon_Heatbeam(edict_t *ent) { static int pause_frames[] = {35, 0}; static int fire_frames[] = {9, 10, 11, 12, 0}; if (!ent) { return; } if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weapon_sound = gi.soundindex("weapons/bfg__l1a.wav"); if ((ent->client->pers.inventory[ent->client->ammo_index] >= 2) && ((ent->client->buttons) & BUTTON_ATTACK)) { if (ent->client->ps.gunframe >= 13) { ent->client->ps.gunframe = 9; ent->client->ps.gunindex = gi.modelindex("models/weapons/v_beamer2/tris.md2"); } else { ent->client->ps.gunindex = gi.modelindex("models/weapons/v_beamer2/tris.md2"); } } else { ent->client->ps.gunframe = 13; ent->client->ps.gunindex = gi.modelindex("models/weapons/v_beamer/tris.md2"); } } else { ent->client->ps.gunindex = gi.modelindex("models/weapons/v_beamer/tris.md2"); ent->client->weapon_sound = 0; } Weapon_Generic(ent, 8, 12, 39, 44, pause_frames, fire_frames, Heatbeam_Fire); } rogue-ROGUE_2_13/src/savegame/000077500000000000000000000000001477320066100161675ustar00rootroot00000000000000rogue-ROGUE_2_13/src/savegame/savegame.c000066400000000000000000000561011477320066100201260ustar00rootroot00000000000000/* * ======================================================================= * * The savegame system. * * ======================================================================= */ /* * This is the Quake 2 savegame system, fixed by Yamagi * based on an idea by Knightmare of kmquake2. This major * rewrite of the original g_save.c is much more robust * and portable since it doesn't use any function pointers. * * Inner workings: * When the game is saved all function pointers are * translated into human readable function definition strings. * The same way all mmove_t pointers are translated. This * human readable strings are then written into the file. * At game load the human readable strings are retranslated * into the actual function pointers and struct pointers. The * pointers are generated at each compilation / start of the * client, thus the pointers are always correct. * * Limitations: * While savegames survive recompilations of the game source * and bigger changes in the source, there are some limitation * which a nearly impossible to fix without a object orientated * rewrite of the game. * - If functions or mmove_t structs that a referencenced * inside savegames are added or removed (e.g. the files * in tables/ are altered) the load functions cannot * reconnect all pointers and thus not restore the game. * - If the operating system is changed internal structures * may change in an unrepairable way. * - If the architecture is changed pointer length and * other internal datastructures change in an * incompatible way. * - If the edict_t struct is changed, savegames * will break. * This is not so bad as it looks since functions and * struct won't be added and edict_t won't be changed * if no big, sweeping changes are done. The operating * system and architecture are in the hands of the user. */ #include "../header/local.h" /* * When ever the savegame version is changed, q2 will refuse to * load older savegames. This should be bumped if the files * in tables/ are changed, otherwise strange things may happen. */ #define SAVEGAMEVER "YQ2-6" #ifndef BUILD_DATE #define BUILD_DATE __DATE__ #endif /* * This macros are used to prohibit loading of savegames * created on other systems or architectures. This will * crash q2 in spectacular ways */ #ifndef YQ2OSTYPE #error YQ2OSTYPE should be defined by the build system #endif #ifndef YQ2ARCH #error YQ2ARCH should be defined by the build system #endif /* * Older operating systen and architecture detection * macros, implemented by savegame version YQ2-2. */ #if defined(__APPLE__) #define YQ2OSTYPE_1 "MacOS X" #elif defined(__FreeBSD__) #define YQ2OSTYPE_1 "FreeBSD" #elif defined(__OpenBSD__) #define YQ2OSTYPE_1 "OpenBSD" #elif defined(__linux__) #define YQ2OSTYPE_1 "Linux" #elif defined(_WIN32) #define YQ2OSTYPE_1 "Windows" #else #define YQ2OSTYPE_1 "Unknown" #endif #if defined(__i386__) #define YQ2ARCH_1 "i386" #elif defined(__x86_64__) #define YQ2ARCH_1 "amd64" #elif defined(__sparc__) #define YQ2ARCH_1 "sparc64" #elif defined(__ia64__) #define YQ2ARCH_1 "ia64" #else #define YQ2ARCH_1 "unknown" #endif /* * Connects a human readable * function signature with * the corresponding pointer */ typedef struct { char *funcStr; byte *funcPtr; } functionList_t; /* * Connects a human readable * mmove_t string with the * correspondig pointer * */ typedef struct { char *mmoveStr; mmove_t *mmovePtr; } mmoveList_t; typedef struct { char ver[32]; char game[32]; char os[32]; char arch[32]; } savegameHeader_t; /* ========================================================= */ /* * Prototypes for forward * declaration for all game * functions. */ #include "tables/gamefunc_decs.h" /* * List with function pointer * to each of the functions * prototyped above. */ static functionList_t functionList[] = { #include "tables/gamefunc_list.h" }; /* * Prototypes for forward * declaration for all game * mmove_t functions. */ #include "tables/gamemmove_decs.h" /* * List with pointers to * each of the mmove_t * functions prototyped * above. */ static mmoveList_t mmoveList[] = { #include "tables/gamemmove_list.h" }; /* * Fields to be saved (used in g_spawn.c) */ field_t fields[] = { #include "tables/fields.h" }; /* * Level fields to * be saved */ static field_t levelfields[] = { #include "tables/levelfields.h" }; /* * Client fields to * be saved */ static field_t clientfields[] = { #include "tables/clientfields.h" }; /* ========================================================= */ /* * This will be called when the dll is first loaded, * which only happens when a new game is started or * a save game is loaded. */ void InitGame(void) { gi.dprintf("Game is starting up.\n"); gi.dprintf("Game is %s built on %s.\n", GAMEVERSION, BUILD_DATE); gun_x = gi.cvar ("gun_x", "0", 0); gun_y = gi.cvar ("gun_y", "0", 0); gun_z = gi.cvar ("gun_z", "0", 0); sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0); sv_rollangle = gi.cvar ("sv_rollangle", "2", 0); sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0); sv_gravity = gi.cvar ("sv_gravity", "800", 0); sv_stopspeed = gi.cvar ("sv_stopspeed", "100", 0); g_showlogic = gi.cvar ("g_showlogic", "0", 0); huntercam = gi.cvar ("huntercam", "1", CVAR_SERVERINFO|CVAR_LATCH); strong_mines = gi.cvar ("strong_mines", "0", 0); randomrespawn = gi.cvar ("randomrespawn", "0", 0); /* noset vars */ dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET); /* latched vars */ sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH); gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH); gi.cvar ("gamedate", BUILD_DATE, CVAR_SERVERINFO | CVAR_LATCH); maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH); maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO); deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH); coop = gi.cvar ("coop", "0", CVAR_LATCH); coop_baseq2 = gi.cvar ("coop_baseq2", "0", CVAR_LATCH); coop_elevator_delay = gi.cvar("coop_elevator_delay", "1.0", CVAR_ARCHIVE); coop_pickup_weapons = gi.cvar("coop_pickup_weapons", "0", CVAR_ARCHIVE); skill = gi.cvar ("skill", "1", CVAR_LATCH); maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH); gamerules = gi.cvar ("gamerules", "0", CVAR_LATCH); //PGM g_footsteps = gi.cvar ("g_footsteps", "1", CVAR_LATCH); g_monsterfootsteps = gi.cvar("g_monsterfootsteps", "0", CVAR_ARCHIVE); g_fix_triggered = gi.cvar ("g_fix_triggered", "0", 0); /* change anytime vars */ dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO); fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO); timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO); password = gi.cvar ("password", "", CVAR_USERINFO); spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO); filterban = gi.cvar ("filterban", "1", 0); g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); run_pitch = gi.cvar ("run_pitch", "0.002", 0); run_roll = gi.cvar ("run_roll", "0.005", 0); bob_up = gi.cvar ("bob_up", "0.005", 0); bob_pitch = gi.cvar ("bob_pitch", "0.002", 0); bob_roll = gi.cvar ("bob_roll", "0.002", 0); /* flood control */ flood_msgs = gi.cvar ("flood_msgs", "4", 0); flood_persecond = gi.cvar ("flood_persecond", "4", 0); flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0); /* dm map list */ sv_maplist = gi.cvar ("sv_maplist", "", 0); /* disruptor availability */ g_disruptor = gi.cvar ("g_disruptor", "0", 0); /* others */ aimfix = gi.cvar("aimfix", "0", CVAR_ARCHIVE); g_machinegun_norecoil = gi.cvar("g_machinegun_norecoil", "0", CVAR_ARCHIVE); g_quick_weap = gi.cvar("g_quick_weap", "1", CVAR_ARCHIVE); g_swap_speed = gi.cvar("g_swap_speed", "1", CVAR_ARCHIVE); /* items */ InitItems (); game.helpmessage1[0] = 0; game.helpmessage2[0] = 0; /* initialize all entities for this game */ game.maxentities = maxentities->value; g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); globals.edicts = g_edicts; globals.max_edicts = game.maxentities; /* initialize all clients for this game */ game.maxclients = maxclients->value; game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); globals.num_edicts = game.maxclients+1; if (gamerules) { InitGameRules(); } } /* ========================================================= */ /* * Helper function to get * the human readable function * definition by an address. * Called by WriteField1 and * WriteField2. */ functionList_t * GetFunctionByAddress(byte *adr) { int i; for (i = 0; functionList[i].funcStr; i++) { if (functionList[i].funcPtr == adr) { return &functionList[i]; } } return NULL; } /* * Helper function to get the * pointer to a function by * it's human readable name. * Called by WriteField1 and * WriteField2. */ byte * FindFunctionByName(char *name) { int i; for (i = 0; functionList[i].funcStr; i++) { if (!strcmp(name, functionList[i].funcStr)) { return functionList[i].funcPtr; } } return NULL; } /* * Helper function to get the * human readable definition of * a mmove_t struct by a pointer. */ mmoveList_t * GetMmoveByAddress(mmove_t *adr) { int i; for (i = 0; mmoveList[i].mmoveStr; i++) { if (mmoveList[i].mmovePtr == adr) { return &mmoveList[i]; } } return NULL; } /* * Helper function to get the * pointer to a mmove_t struct * by a human readable definition. */ mmove_t * FindMmoveByName(char *name) { int i; for (i = 0; mmoveList[i].mmoveStr; i++) { if (!strcmp(name, mmoveList[i].mmoveStr)) { return mmoveList[i].mmovePtr; } } return NULL; } /* ========================================================= */ /* * The following two functions are * doing the dirty work to write the * data generated by the functions * below this block into files. */ void WriteField1(FILE *f, field_t *field, byte *base) { void *p; int len; int index; functionList_t *func; mmoveList_t *mmove; if (field->flags & FFL_SPAWNTEMP) { return; } p = (void *)(base + field->ofs); switch (field->type) { case F_INT: case F_FLOAT: case F_ANGLEHACK: case F_VECTOR: case F_IGNORE: break; case F_LSTRING: case F_GSTRING: if (*(char **)p) { len = strlen(*(char **)p) + 1; } else { len = 0; } *(int *)p = len; break; case F_EDICT: if (*(edict_t **)p == NULL) { index = -1; } else { index = *(edict_t **)p - g_edicts; } *(int *)p = index; break; case F_CLIENT: if (*(gclient_t **)p == NULL) { index = -1; } else { index = *(gclient_t **)p - game.clients; } *(int *)p = index; break; case F_ITEM: if (*(edict_t **)p == NULL) { index = -1; } else { index = *(gitem_t **)p - itemlist; } *(int *)p = index; break; case F_FUNCTION: if (*(byte **)p == NULL) { len = 0; } else { func = GetFunctionByAddress (*(byte **)p); if (!func) { gi.error ("WriteField1: function not in list, can't save game"); } len = strlen(func->funcStr)+1; } *(int *)p = len; break; case F_MMOVE: if (*(byte **)p == NULL) { len = 0; } else { mmove = GetMmoveByAddress (*(mmove_t **)p); if (!mmove) { gi.error ("WriteField1: mmove not in list, can't save game"); } len = strlen(mmove->mmoveStr)+1; } *(int *)p = len; break; default: gi.error("WriteEdict: unknown field type"); } } void WriteField2(FILE *f, field_t *field, byte *base) { int len; void *p; functionList_t *func; mmoveList_t *mmove; if (field->flags & FFL_SPAWNTEMP) { return; } p = (void *)(base + field->ofs); switch (field->type) { case F_LSTRING: if (*(char **)p) { len = strlen(*(char **)p) + 1; fwrite(*(char **)p, len, 1, f); } break; case F_FUNCTION: if (*(byte **)p) { func = GetFunctionByAddress (*(byte **)p); if (!func) { gi.error ("WriteField2: function not in list, can't save game"); } len = strlen(func->funcStr)+1; fwrite (func->funcStr, len, 1, f); } break; case F_MMOVE: if (*(byte **)p) { mmove = GetMmoveByAddress (*(mmove_t **)p); if (!mmove) { gi.error ("WriteField2: mmove not in list, can't save game"); } len = strlen(mmove->mmoveStr)+1; fwrite (mmove->mmoveStr, len, 1, f); } break; default: break; } } /* ========================================================= */ /* * This function does the dirty * work to read the data from a * file. The processing of the * data is done in the functions * below */ void ReadField(FILE *f, field_t *field, byte *base) { void *p; int len; int index; char funcStr[2048]; if (field->flags & FFL_SPAWNTEMP) { return; } p = (void *)(base + field->ofs); switch (field->type) { case F_INT: case F_FLOAT: case F_ANGLEHACK: case F_VECTOR: case F_IGNORE: break; case F_LSTRING: len = *(int *)p; if (!len) { *(char **)p = NULL; } else { *(char **)p = gi.TagMalloc(32 + len, TAG_LEVEL); fread(*(char **)p, len, 1, f); } break; case F_EDICT: index = *(int *)p; if (index == -1) { *(edict_t **)p = NULL; } else { *(edict_t **)p = &g_edicts[index]; } break; case F_CLIENT: index = *(int *)p; if (index == -1) { *(gclient_t **)p = NULL; } else { *(gclient_t **)p = &game.clients[index]; } break; case F_ITEM: index = *(int *)p; if (index == -1) { *(gitem_t **)p = NULL; } else { *(gitem_t **)p = &itemlist[index]; } break; case F_FUNCTION: len = *(int *)p; if (!len) { *(byte **)p = NULL; } else { if (len > sizeof(funcStr)) { gi.error ("ReadField: function name is longer than buffer (%i chars)", (int)sizeof(funcStr)); } fread (funcStr, len, 1, f); if ( !(*(byte **)p = FindFunctionByName (funcStr)) ) { gi.error ("ReadField: function %s not found in table, can't load game", funcStr); } } break; case F_MMOVE: len = *(int *)p; if (!len) { *(byte **)p = NULL; } else { if (len > sizeof(funcStr)) { gi.error ("ReadField: mmove name is longer than buffer (%i chars)", (int)sizeof(funcStr)); } fread (funcStr, len, 1, f); if ( !(*(mmove_t **)p = FindMmoveByName (funcStr)) ) { gi.error ("ReadField: mmove %s not found in table, can't load game", funcStr); } } break; default: gi.error("ReadEdict: unknown field type"); } } /* ========================================================= */ /* * Write the client struct into a file. */ void WriteClient(FILE *f, gclient_t *client) { field_t *field; gclient_t temp; /* all of the ints, floats, and vectors stay as they are */ temp = *client; /* change the pointers to indexes */ for (field = clientfields; field->name; field++) { WriteField1(f, field, (byte *)&temp); } /* write the block */ fwrite(&temp, sizeof(temp), 1, f); /* now write any allocated data following the edict */ for (field = clientfields; field->name; field++) { WriteField2(f, field, (byte *)client); } } /* * Read the client struct from a file */ void ReadClient(FILE *f, gclient_t *client, short save_ver) { field_t *field; fread(client, sizeof(*client), 1, f); for (field = clientfields; field->name; field++) { if (field->save_ver <= save_ver) { ReadField(f, field, (byte *)client); } } if (save_ver < 4) { InitClientResp(client); } } /* ========================================================= */ /* * Writes the game struct into * a file. This is called when * ever the games goes to e new * level or the user saves the * game. Saved informations are: * - cross level data * - client states * - help computer info */ void WriteGame(const char *filename, qboolean autosave) { savegameHeader_t sv; FILE *f; int i; if (!autosave) { SaveClientData(); } f = fopen(filename, "wb"); if (!f) { gi.error("Couldn't open %s", filename); } /* Savegame identification */ memset(&sv, 0, sizeof(sv)); Q_strlcpy(sv.ver, SAVEGAMEVER, sizeof(sv.ver) - 1); Q_strlcpy(sv.game, GAMEVERSION, sizeof(sv.game) - 1); Q_strlcpy(sv.os, YQ2OSTYPE, sizeof(sv.os) - 1); Q_strlcpy(sv.arch, YQ2ARCH, sizeof(sv.arch) - 1); fwrite(&sv, sizeof(sv), 1, f); game.autosaved = autosave; fwrite(&game, sizeof(game), 1, f); game.autosaved = false; for (i = 0; i < game.maxclients; i++) { WriteClient(f, &game.clients[i]); } fclose(f); } /* * Read the game structs from * a file. Called when ever a * savegames is loaded. */ void ReadGame(const char *filename) { savegameHeader_t sv; FILE *f; int i; short save_ver = 0; gi.FreeTags(TAG_GAME); f = fopen(filename, "rb"); if (!f) { gi.error("Couldn't open %s", filename); } /* Sanity checks */ fread(&sv, sizeof(sv), 1, f); static const struct { const char* verstr; int vernum; } version_mappings[] = { {"YQ2-1", 1}, {"YQ2-2", 2}, {"YQ2-3", 3}, {"YQ2-4", 4}, {"YQ2-5", 5}, {"YQ2-6", 6}, }; for (i=0; i < sizeof(version_mappings)/sizeof(version_mappings[0]); ++i) { if (strcmp(version_mappings[i].verstr, sv.ver) == 0) { save_ver = version_mappings[i].vernum; break; } } if(save_ver < 2) { fclose(f); gi.error("Savegame from an incompatible version.\n"); } else if (save_ver == 2) { if (strcmp(sv.game, GAMEVERSION)) { fclose(f); gi.error("Savegame from an other game.so.\n"); } else if (strcmp(sv.os, YQ2OSTYPE_1)) { fclose(f); gi.error("Savegame from an other os.\n"); } #ifdef _WIN32 /* Windows was forced to i386 */ if (strcmp(sv.arch, "i386") != 0) { fclose(f); gi.error("Savegame from another architecture.\n"); } #else if (strcmp(sv.arch, YQ2ARCH_1) != 0) { fclose(f); gi.error("Savegame from another architecture.\n"); } #endif } else // all newer savegame versions { if (strcmp(sv.game, GAMEVERSION) != 0) { fclose(f); gi.error("Savegame from another game.so.\n"); } else if (strcmp(sv.os, YQ2OSTYPE) != 0) { fclose(f); gi.error("Savegame from another os.\n"); } else if (strcmp(sv.arch, YQ2ARCH) != 0) { #if defined(_WIN32) && (defined(__i386__) || defined(_M_IX86)) // before savegame version "YQ2-5" (and after version 2), // the official Win32 binaries accidentally had the YQ2ARCH "AMD64" // instead of "i386" set due to a bug in the Makefile. // This quirk allows loading those savegames anyway if (save_ver >= 5 || strcmp(sv.arch, "AMD64") != 0) #endif { fclose(f); gi.error("Savegame from another architecture.\n"); } } } g_edicts = gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME); globals.edicts = g_edicts; fread(&game, sizeof(game), 1, f); game.clients = gi.TagMalloc(game.maxclients * sizeof(game.clients[0]), TAG_GAME); for (i = 0; i < game.maxclients; i++) { ReadClient(f, &game.clients[i], save_ver); } fclose(f); } /* ========================================================== */ /* * Helper function to write the * edict into a file. Called by * WriteLevel. */ void WriteEdict(FILE *f, edict_t *ent) { field_t *field; edict_t temp; /* all of the ints, floats, and vectors stay as they are */ temp = *ent; /* change the pointers to lengths or indexes */ for (field = fields; field->name; field++) { WriteField1(f, field, (byte *)&temp); } /* write the block */ fwrite(&temp, sizeof(temp), 1, f); /* now write any allocated data following the edict */ for (field = fields; field->name; field++) { WriteField2(f, field, (byte *)ent); } } /* * Helper function to write the * level local data into a file. * Called by WriteLevel. */ void WriteLevelLocals(FILE *f) { field_t *field; level_locals_t temp; /* all of the ints, floats, and vectors stay as they are */ temp = level; /* change the pointers to lengths or indexes */ for (field = levelfields; field->name; field++) { WriteField1(f, field, (byte *)&temp); } /* write the block */ fwrite(&temp, sizeof(temp), 1, f); /* now write any allocated data following the edict */ for (field = levelfields; field->name; field++) { WriteField2(f, field, (byte *)&level); } } /* * Writes the current level * into a file. */ void WriteLevel(const char *filename) { int i; edict_t *ent; FILE *f; f = fopen(filename, "wb"); if (!f) { gi.error("Couldn't open %s", filename); } /* write out edict size for checking */ i = sizeof(edict_t); fwrite(&i, sizeof(i), 1, f); /* write out level_locals_t */ WriteLevelLocals(f); /* write out all the entities */ for (i = 0; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (!ent->inuse) { continue; } fwrite(&i, sizeof(i), 1, f); WriteEdict(f, ent); } i = -1; fwrite(&i, sizeof(i), 1, f); fclose(f); } /* ========================================================== */ /* * A helper function to * read the edict back * into the memory. Called * by ReadLevel. */ void ReadEdict(FILE *f, edict_t *ent) { field_t *field; fread(ent, sizeof(*ent), 1, f); for (field = fields; field->name; field++) { ReadField(f, field, (byte *)ent); } } /* * A helper function to * read the level local * data from a file. * Called by ReadLevel. */ void ReadLevelLocals(FILE *f) { field_t *field; fread(&level, sizeof(level), 1, f); for (field = levelfields; field->name; field++) { ReadField(f, field, (byte *)&level); } } /* * Reads a level back into the memory. * SpawnEntities were already called * in the same way when the level was * saved. All world links were cleared * before this function was called. When * this function is called, no clients * are connected to the server. */ void ReadLevel(const char *filename) { int entnum; FILE *f; int i; edict_t *ent; f = fopen(filename, "rb"); if (!f) { gi.error("Couldn't open %s", filename); } /* free any dynamic memory allocated by loading the level base state */ gi.FreeTags(TAG_LEVEL); /* wipe all the entities */ memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); globals.num_edicts = maxclients->value + 1; /* check edict size */ fread(&i, sizeof(i), 1, f); if (i != sizeof(edict_t)) { fclose(f); gi.error("ReadLevel: mismatched edict size"); } /* load the level locals */ ReadLevelLocals(f); /* load all the entities */ while (1) { if (fread(&entnum, sizeof(entnum), 1, f) != 1) { fclose(f); gi.error("ReadLevel: failed to read entnum"); } if (entnum == -1) { break; } if (entnum >= globals.num_edicts) { globals.num_edicts = entnum + 1; } ent = &g_edicts[entnum]; ReadEdict(f, ent); /* let the server rebuild world links for this ent */ memset(&ent->area, 0, sizeof(ent->area)); gi.linkentity(ent); } fclose(f); /* mark all clients as unconnected */ for (i = 0; i < maxclients->value; i++) { ent = &g_edicts[i + 1]; ent->client = game.clients + i; ent->client->pers.connected = false; } /* do any load time things at this point */ for (i = 0; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (!ent->inuse) { continue; } /* fire any cross-level triggers */ if (ent->classname) { if (strcmp(ent->classname, "target_crosslevel_target") == 0) { ent->nextthink = level.time + ent->delay; } } } } rogue-ROGUE_2_13/src/savegame/tables/000077500000000000000000000000001477320066100174415ustar00rootroot00000000000000rogue-ROGUE_2_13/src/savegame/tables/clientfields.h000066400000000000000000000010671477320066100222630ustar00rootroot00000000000000/* * ======================================================================= * * Fields of the client to be saved. * * ======================================================================= */ {"pers.weapon", CLOFS(pers.weapon), F_ITEM}, {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM}, {"newweapon", CLOFS(newweapon), F_ITEM}, {"owned_sphere", CLOFS(owned_sphere), F_EDICT}, {"resp.coop_respawn.weapon", CLOFS(resp.coop_respawn.weapon), F_ITEM, 0, 4}, {"resp.coop_respawn.lastweapon", CLOFS(resp.coop_respawn.lastweapon), F_ITEM, 0, 4}, {NULL, 0, F_INT} rogue-ROGUE_2_13/src/savegame/tables/fields.h000066400000000000000000000111511477320066100210570ustar00rootroot00000000000000/* * ======================================================================= * * Game fields to be saved. * * ======================================================================= */ {"classname", FOFS(classname), F_LSTRING}, {"model", FOFS(model), F_LSTRING}, {"spawnflags", FOFS(spawnflags), F_INT}, {"speed", FOFS(speed), F_FLOAT}, {"accel", FOFS(accel), F_FLOAT}, {"decel", FOFS(decel), F_FLOAT}, {"target", FOFS(target), F_LSTRING}, {"targetname", FOFS(targetname), F_LSTRING}, {"pathtarget", FOFS(pathtarget), F_LSTRING}, {"deathtarget", FOFS(deathtarget), F_LSTRING}, {"killtarget", FOFS(killtarget), F_LSTRING}, {"combattarget", FOFS(combattarget), F_LSTRING}, {"message", FOFS(message), F_LSTRING}, {"team", FOFS(team), F_LSTRING}, {"wait", FOFS(wait), F_FLOAT}, {"delay", FOFS(delay), F_FLOAT}, {"random", FOFS(random), F_FLOAT}, {"move_origin", FOFS(move_origin), F_VECTOR}, {"move_angles", FOFS(move_angles), F_VECTOR}, {"style", FOFS(style), F_INT}, {"count", FOFS(count), F_INT}, {"health", FOFS(health), F_INT}, {"sounds", FOFS(sounds), F_INT}, {"light", 0, F_IGNORE}, {"dmg", FOFS(dmg), F_INT}, {"mass", FOFS(mass), F_INT}, {"volume", FOFS(volume), F_FLOAT}, {"attenuation", FOFS(attenuation), F_FLOAT}, {"map", FOFS(map), F_LSTRING}, {"origin", FOFS(s.origin), F_VECTOR}, {"angles", FOFS(s.angles), F_VECTOR}, {"angle", FOFS(s.angles), F_ANGLEHACK}, {"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN}, {"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN}, {"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN}, {"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN}, {"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN}, {"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN}, {"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN}, {"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN}, {"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN}, {"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN}, {"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN}, {"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN}, {"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN}, {"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN}, {"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN}, {"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN}, {"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN}, {"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN}, {"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN}, {"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN}, {"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN}, {"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN}, {"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN}, {"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN}, {"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN}, {"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN}, {"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN}, {"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN}, {"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN}, {"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN}, {"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN}, {"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN}, {"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP}, {"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP}, {"height", STOFS(height), F_INT, FFL_SPAWNTEMP}, {"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP}, {"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP}, {"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP}, {"item", FOFS(item), F_ITEM}, {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP}, {"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP}, {"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP}, {"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP}, {"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP}, {"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP}, {"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP}, {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP}, {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}, {"bad_area", FOFS(bad_area), F_EDICT}, {"hint_chain", FOFS(hint_chain), F_EDICT}, {"monster_hint_chain", FOFS(monster_hint_chain), F_EDICT}, {"target_hint_chain", FOFS(target_hint_chain), F_EDICT}, {"goal_hint", FOFS(monsterinfo.goal_hint), F_EDICT}, {"badMedic1", FOFS(monsterinfo.badMedic1), F_EDICT}, {"badMedic2", FOFS(monsterinfo.badMedic2), F_EDICT}, {"last_player_enemy", FOFS(monsterinfo.last_player_enemy), F_EDICT}, {"commander", FOFS(monsterinfo.commander), F_EDICT}, {"blocked", FOFS(monsterinfo.blocked), F_FUNCTION, FFL_NOSPAWN}, {"duck", FOFS(monsterinfo.duck), F_FUNCTION, FFL_NOSPAWN}, {"unduck", FOFS(monsterinfo.unduck), F_FUNCTION, FFL_NOSPAWN}, {"sidestep", FOFS(monsterinfo.sidestep), F_FUNCTION, FFL_NOSPAWN}, {0, 0, 0, 0} rogue-ROGUE_2_13/src/savegame/tables/gamefunc_decs.h000066400000000000000000002646631477320066100224160ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 Id Software, Inc. * Copyright (C) 2011 Yamagi Burmeister * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Prototypes for every function in the game.so. * * ======================================================================= */ extern void ReadLevel ( const char * filename ) ; extern void ReadLevelLocals ( FILE * f ) ; extern void ReadEdict ( FILE * f , edict_t * ent ) ; extern void WriteLevel ( const char * filename ) ; extern void WriteLevelLocals ( FILE * f ) ; extern void WriteEdict ( FILE * f , edict_t * ent ) ; extern void ReadGame ( const char * filename ) ; extern void WriteGame ( const char * filename , qboolean autosave ) ; extern void ReadClient ( FILE * f , gclient_t * client , short save_ver ) ; extern void WriteClient ( FILE * f , gclient_t * client ) ; extern void ReadField ( FILE * f , field_t * field , byte * base ) ; extern void WriteField2 ( FILE * f , field_t * field , byte * base ) ; extern void WriteField1 ( FILE * f , field_t * field , byte * base ) ; extern mmove_t * FindMmoveByName ( char * name ) ; extern mmoveList_t * GetMmoveByAddress ( mmove_t * adr ) ; extern byte * FindFunctionByName ( char * name ) ; extern functionList_t * GetFunctionByAddress ( byte * adr ) ; extern void InitGame ( void ) ; extern void Info_SetValueForKey ( char * s , char * key , char * value ) ; extern qboolean Info_Validate ( char * s ) ; extern void Info_RemoveKey ( char * s , char * key ) ; extern char * Info_ValueForKey ( char * s , char * key ) ; extern void Com_sprintf ( char * dest , int size , char * fmt , ... ) ; extern int Q_strcasecmp ( char * s1 , char * s2 ) ; extern int Q_strncasecmp ( char * s1 , char * s2 , int n ) ; extern int Q_stricmp ( const char * s1 , const char * s2 ) ; extern void Com_PageInMemory ( byte * buffer , int size ) ; extern char * COM_Parse ( char * * data_p ) ; extern char * va ( const char * format , ... ) ; extern void Swap_Init ( void ) ; extern float FloatNoSwap ( float f ) ; extern float FloatSwap ( float f ) ; extern int LongNoSwap ( int l ) ; extern int LongSwap ( int l ) ; extern short ShortNoSwap ( short l ) ; extern short ShortSwap ( short l ) ; extern float LittleFloat ( float l ) ; extern float BigFloat ( float l ) ; extern int LittleLong ( int l ) ; extern int BigLong ( int l ) ; extern short LittleShort ( short l ) ; extern short BigShort ( short l ) ; extern void COM_DefaultExtension ( char * path , const char * extension ) ; extern void COM_FilePath ( const char * in , char * out ) ; extern void COM_FileBase ( char * in , char * out ) ; extern const char * COM_FileExtension ( const char * in ) ; extern void COM_StripExtension ( char * in , char * out ) ; extern char * COM_SkipPath ( char * pathname ) ; extern int Q_log2 ( int val ) ; extern void VectorScale ( vec3_t in , vec_t scale , vec3_t out ) ; extern void VectorInverse ( vec3_t v ) ; extern vec_t VectorLength ( vec3_t v ) ; extern void CrossProduct ( vec3_t v1 , vec3_t v2 , vec3_t cross ) ; extern void _VectorCopy ( vec3_t in , vec3_t out ) ; extern void _VectorAdd ( vec3_t veca , vec3_t vecb , vec3_t out ) ; extern void _VectorSubtract ( vec3_t veca , vec3_t vecb , vec3_t out ) ; extern vec_t _DotProduct ( vec3_t v1 , vec3_t v2 ) ; extern void VectorMA ( vec3_t veca , float scale , vec3_t vecb , vec3_t vecc ) ; extern vec_t VectorNormalize2 ( vec3_t v , vec3_t out ) ; extern vec_t VectorNormalize ( vec3_t v ) ; extern int VectorCompare ( vec3_t v1 , vec3_t v2 ) ; extern void AddPointToBounds ( vec3_t v , vec3_t mins , vec3_t maxs ) ; extern void ClearBounds ( vec3_t mins , vec3_t maxs ) ; extern int BoxOnPlaneSide2 ( vec3_t emins , vec3_t emaxs , struct cplane_s * p ) ; extern float anglemod ( float a ) ; extern float LerpAngle ( float a2 , float a1 , float frac ) ; extern float Q_fabs ( float f ) ; extern void R_ConcatTransforms ( float in1 [ 3 ] [ 4 ] , float in2 [ 3 ] [ 4 ] , float out [ 3 ] [ 4 ] ) ; extern void R_ConcatRotations ( float in1 [ 3 ] [ 3 ] , float in2 [ 3 ] [ 3 ] , float out [ 3 ] [ 3 ] ) ; extern void PerpendicularVector ( vec3_t dst , const vec3_t src ) ; extern void ProjectPointOnPlane ( vec3_t dst , const vec3_t p , const vec3_t normal ) ; extern void AngleVectors ( vec3_t angles , vec3_t forward , vec3_t right , vec3_t up ) ; extern void RotatePointAroundVector ( vec3_t dst , const vec3_t dir , const vec3_t point , float degrees ) ; extern void Weapon_Heatbeam ( edict_t * ent ) ; extern void Heatbeam_Fire ( edict_t * ent ) ; extern void Weapon_ETF_Rifle ( edict_t * ent ) ; extern void weapon_etf_rifle_fire ( edict_t * ent ) ; extern void Weapon_Disintegrator ( edict_t * ent ) ; extern void weapon_tracker_fire ( edict_t * self ) ; extern void Weapon_ChainFist ( edict_t * ent ) ; extern void chainfist_smoke ( edict_t * ent ) ; extern void weapon_chainfist_fire ( edict_t * ent ) ; extern void Weapon_BFG ( edict_t * ent ) ; extern void weapon_bfg_fire ( edict_t * ent ) ; extern void Weapon_Railgun ( edict_t * ent ) ; extern void weapon_railgun_fire ( edict_t * ent ) ; extern void Weapon_SuperShotgun ( edict_t * ent ) ; extern void weapon_supershotgun_fire ( edict_t * ent ) ; extern void Weapon_Shotgun ( edict_t * ent ) ; extern void weapon_shotgun_fire ( edict_t * ent ) ; extern void Weapon_Chaingun ( edict_t * ent ) ; extern void Chaingun_Fire ( edict_t * ent ) ; extern void Weapon_Machinegun ( edict_t * ent ) ; extern void Machinegun_Fire ( edict_t * ent ) ; extern void Weapon_HyperBlaster ( edict_t * ent ) ; extern void Weapon_HyperBlaster_Fire ( edict_t * ent ) ; extern void Weapon_Blaster ( edict_t * ent ) ; extern void Weapon_Blaster_Fire ( edict_t * ent ) ; extern void Blaster_Fire ( edict_t * ent , vec3_t g_offset , int damage , qboolean hyper , int effect ) ; extern void Weapon_RocketLauncher ( edict_t * ent ) ; extern void Weapon_RocketLauncher_Fire ( edict_t * ent ) ; extern void Weapon_ProxLauncher ( edict_t * ent ) ; extern void Weapon_GrenadeLauncher ( edict_t * ent ) ; extern void weapon_grenadelauncher_fire ( edict_t * ent ) ; extern void Weapon_Tesla ( edict_t * ent ) ; extern void Weapon_Grenade ( edict_t * ent ) ; extern void Throw_Generic ( edict_t * ent , int FRAME_FIRE_LAST , int FRAME_IDLE_LAST , int FRAME_THROW_SOUND , int FRAME_THROW_HOLD , int FRAME_THROW_FIRE , int * pause_frames , int EXPLODE , void ( * fire ) ( edict_t * ent , qboolean held ) ) ; extern void weapon_grenade_fire ( edict_t * ent , qboolean held ) ; extern void Weapon_Generic ( edict_t * ent , int FRAME_ACTIVATE_LAST , int FRAME_FIRE_LAST , int FRAME_IDLE_LAST , int FRAME_DEACTIVATE_LAST , int * pause_frames , int * fire_frames , void ( * fire ) ( edict_t * ent ) ) ; extern void Drop_Weapon ( edict_t * ent , gitem_t * item ) ; extern void Use_Weapon ( edict_t * ent , gitem_t * item ) ; extern void Think_Weapon ( edict_t * ent ) ; extern void NoAmmoWeaponChange ( edict_t * ent ) ; extern void ChangeWeapon ( edict_t * ent ) ; extern qboolean Pickup_Weapon ( edict_t * ent , edict_t * other ) ; extern void PlayerNoise ( edict_t * who , vec3_t where , int type ) ; extern void P_ProjectSource2 ( gclient_t * client , vec3_t point , vec3_t distance , vec3_t forward , vec3_t right , vec3_t up , vec3_t result ) ; extern void P_ProjectSource(edict_t *ent, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result); extern byte P_DamageModifier ( edict_t * ent ) ; extern void ClientEndServerFrame ( edict_t * ent ) ; extern void G_SetClientFrame ( edict_t * ent ) ; extern void G_SetClientSound ( edict_t * ent ) ; extern void G_SetClientEvent ( edict_t * ent ) ; extern void G_SetClientEffects ( edict_t * ent ) ; extern void P_WorldEffects ( void ) ; extern void P_FallingDamage ( edict_t * ent ) ; extern void SV_CalcBlend ( edict_t * ent ) ; extern void SV_AddBlend ( float r , float g , float b , float a , float * v_blend ) ; extern void SV_CalcGunOffset ( edict_t * ent ) ; extern void SV_CalcViewOffset ( edict_t * ent ) ; extern void P_DamageFeedback ( edict_t * player ) ; extern float SV_CalcRoll ( vec3_t angles , vec3_t velocity ) ; extern edict_t * PlayerTrail_LastSpot ( void ) ; extern edict_t * PlayerTrail_PickNext ( edict_t * self ) ; extern edict_t * PlayerTrail_PickFirst ( edict_t * self ) ; extern void PlayerTrail_New ( vec3_t spot ) ; extern void PlayerTrail_Add ( vec3_t spot ) ; extern void PlayerTrail_Init ( void ) ; extern void G_SetSpectatorStats ( edict_t * ent ) ; extern void G_CheckChaseStats ( edict_t * ent ) ; extern void G_SetStats ( edict_t * ent ) ; extern void InventoryMessage ( edict_t * ent ) ; extern void HelpComputerMessage ( edict_t * ent ) ; extern void DeathmatchScoreboardMessage ( edict_t * ent , edict_t * killer ) ; extern void BeginIntermission ( edict_t * targ ) ; extern void MoveClientToIntermission ( edict_t * ent ) ; extern void RemoveAttackingPainDaemons ( edict_t * self ) ; extern void ClientBeginServerFrame ( edict_t * ent ) ; extern void ClientThink ( edict_t * ent , usercmd_t * ucmd ) ; extern void PrintPmove ( pmove_t * pm ) ; extern unsigned CheckBlock ( void * b , int c ) ; extern trace_t PM_trace ( vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end ) ; extern void ClientDisconnect ( edict_t * ent ) ; extern qboolean ClientConnect ( edict_t * ent , char * userinfo ) ; extern void ClientUserinfoChanged ( edict_t * ent , char * userinfo ) ; extern void ClientBegin ( edict_t * ent ) ; extern void ClientBeginDeathmatch ( edict_t * ent ) ; extern void PutClientInServer ( edict_t * ent ) ; extern void spectator_respawn ( edict_t * ent ) ; extern void respawn ( edict_t * self ) ; extern void CopyToBodyQue ( edict_t * ent ) ; extern void body_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void InitBodyQue ( void ) ; extern void SelectSpawnPoint ( edict_t * ent , vec3_t origin , vec3_t angles ) ; extern edict_t * SelectCoopSpawnPoint ( edict_t * ent ) ; extern edict_t * SelectLavaCoopSpawnPoint ( edict_t * ent ) ; extern edict_t * SelectDeathmatchSpawnPoint ( void ) ; extern edict_t * SelectFarthestDeathmatchSpawnPoint ( void ) ; extern edict_t * SelectRandomDeathmatchSpawnPoint ( void ) ; extern float PlayersRangeFromSpot ( edict_t * spot ) ; extern void FetchClientEntData ( edict_t * ent ) ; extern void SaveClientData ( void ) ; extern void InitClientResp ( gclient_t * client ) ; extern void InitClientPersistant ( gclient_t * client ) ; extern void player_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void LookAtKiller ( edict_t * self , edict_t * inflictor , edict_t * attacker ) ; extern void TossClientWeapon ( edict_t * self ) ; extern void ClientObituary ( edict_t * self , edict_t * inflictor , edict_t * attacker ) ; extern qboolean IsNeutral ( edict_t * ent ) ; extern qboolean IsFemale ( edict_t * ent ) ; extern void player_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void SP_info_player_intermission ( edict_t *ent ); extern void SP_info_player_coop_lava ( edict_t * self ) ; extern void SP_info_player_coop ( edict_t * self ) ; extern void SP_info_player_deathmatch ( edict_t * self ) ; extern void SP_info_player_start ( edict_t * self ) ; extern void ThrowArm2 ( edict_t * self ) ; extern void ThrowArm1 ( edict_t * self ) ; extern void WidowExplosionLeg ( edict_t * self ) ; extern void WidowExplosion7 ( edict_t * self ) ; extern void WidowExplosion6 ( edict_t * self ) ; extern void WidowExplosion5 ( edict_t * self ) ; extern void WidowExplosion4 ( edict_t * self ) ; extern void WidowExplosion3 ( edict_t * self ) ; extern void WidowExplosion2 ( edict_t * self ) ; extern void WidowExplosion1 ( edict_t * self ) ; extern void WidowExplode ( edict_t * self ) ; extern void ThrowMoreStuff ( edict_t * self , vec3_t point ) ; extern void ThrowSmallStuff ( edict_t * self , vec3_t point ) ; extern void ThrowWidowGibReal ( edict_t * self , char * gibname , int damage , int type , vec3_t startpos , qboolean sized , int hitsound , qboolean fade ) ; extern void ThrowWidowGibSized ( edict_t * self , char * gibname , int damage , int type , vec3_t startpos , int hitsound , qboolean fade ) ; extern void ThrowWidowGibLoc ( edict_t * self , char * gibname , int damage , int type , vec3_t startpos , qboolean fade ) ; extern void ThrowWidowGib ( edict_t * self , char * gibname , int damage , int type ) ; extern void widow_gib_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void WidowVelocityForDamage ( int damage , vec3_t v ) ; extern void SP_monster_widow2 ( edict_t * self ) ; extern void Widow2Precache ( ) ; extern qboolean Widow2_CheckAttack ( edict_t * self ) ; extern void widow2_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void KillChildren ( edict_t * self ) ; extern void widow2_dead ( edict_t * self ) ; extern void widow2_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void widow2_reattack_beam ( edict_t * self ) ; extern void widow2_attack_beam ( edict_t * self ) ; extern void widow2_attack ( edict_t * self ) ; extern void widow2_melee ( edict_t * self ) ; extern void widow2_walk ( edict_t * self ) ; extern void widow2_run ( edict_t * self ) ; extern void widow2_stand ( edict_t * self ) ; extern void widow2_finaldeath ( edict_t * self ) ; extern void widow2_keep_searching ( edict_t * self ) ; extern void widow2_start_searching ( edict_t * self ) ; extern void Widow2Toss ( edict_t * self ) ; extern void Widow2Crunch ( edict_t * self ) ; extern void Widow2TonguePull ( edict_t * self ) ; extern void Widow2Tongue ( edict_t * self ) ; extern qboolean widow2_tongue_attack_ok ( vec3_t start , vec3_t end , float range ) ; extern void Widow2StartSweep ( edict_t * self ) ; extern void Widow2BeamTargetRemove ( edict_t * self ) ; extern void Widow2SaveBeamTarget ( edict_t * self ) ; extern void widow2_disrupt_reattack ( edict_t * self ) ; extern void Widow2SaveDisruptLoc ( edict_t * self ) ; extern void WidowDisrupt ( edict_t * self ) ; extern void widow2_ready_spawn ( edict_t * self ) ; extern void widow2_spawn_check ( edict_t * self ) ; extern void Widow2Spawn ( edict_t * self ) ; extern void Widow2Beam ( edict_t * self ) ; extern void widow2_search ( edict_t * self ) ; extern void pauseme ( edict_t * self ) ; extern void SP_monster_widow ( edict_t * self ) ; extern void WidowPrecache ( ) ; extern void WidowCalcSlots ( edict_t * self ) ; extern qboolean widow_blocked ( edict_t * self , float dist ) ; extern qboolean Widow_CheckAttack ( edict_t * self ) ; extern void WidowPowerups ( edict_t * self ) ; extern void WidowRespondPowerup ( edict_t * self , edict_t * other ) ; extern void WidowPowerArmor ( edict_t * self ) ; extern void WidowPent ( edict_t * self , float framenum ) ; extern void WidowDouble ( edict_t * self , float framenum ) ; extern void WidowGoinQuad ( edict_t * self , float framenum ) ; extern void widow_melee ( edict_t * self ) ; extern void widow_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void widow_dead ( edict_t * self ) ; extern void widow_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void widow_reattack_blaster ( edict_t * self ) ; extern void widow_attack_blaster ( edict_t * self ) ; extern void widow_attack ( edict_t * self ) ; extern void widow_walk ( edict_t * self ) ; extern void widow_run ( edict_t * self ) ; extern void widow_stand ( edict_t * self ) ; extern void widow_attack_kick ( edict_t * self ) ; extern void spawn_out_do ( edict_t * self ) ; extern void spawn_out_start ( edict_t * self ) ; extern void widow_done_spawn ( edict_t * self ) ; extern void widow_start_spawn ( edict_t * self ) ; extern void widow_attack_rail ( edict_t * self ) ; extern void widow_rail_done ( edict_t * self ) ; extern void widow_start_rail ( edict_t * self ) ; extern void WidowSaveLoc ( edict_t * self ) ; extern void WidowRail ( edict_t * self ) ; extern void widow_start_run_12 ( edict_t * self ) ; extern void widow_start_run_10 ( edict_t * self ) ; extern void widow_start_run_5 ( edict_t * self ) ; extern void widow_stepshoot ( edict_t * self ) ; extern void widow_step ( edict_t * self ) ; extern void widow_ready_spawn ( edict_t * self ) ; extern void widow_spawn_check ( edict_t * self ) ; extern void WidowSpawn ( edict_t * self ) ; extern void WidowBlaster ( edict_t * self ) ; extern int WidowTorso ( edict_t * self ) ; extern float target_angle ( edict_t * self ) ; extern void widow_sight ( edict_t * self , edict_t * other ) ; extern void widow_search ( edict_t * self ) ; extern void showme ( edict_t * self ) ; extern void SP_monster_turret ( edict_t * self ) ; extern qboolean turret_checkattack ( edict_t * self ) ; extern void turret_activate ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void turret_wake ( edict_t * self ) ; extern void turret_wall_spawn ( edict_t * turret ) ; extern void turret_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void turret_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void turret_attack ( edict_t * self ) ; extern void TurretFireBlind ( edict_t * self ) ; extern void TurretFire ( edict_t * self ) ; extern void turret_run ( edict_t * self ) ; extern void turret_walk ( edict_t * self ) ; extern void turret_ready_gun ( edict_t * self ) ; extern void turret_stand ( edict_t * self ) ; extern void turret_search ( edict_t * self ) ; extern void turret_sight ( edict_t * self , edict_t * other ) ; extern void TurretAim ( edict_t * self ) ; extern void SP_monster_tank ( edict_t * self ) ; extern void tank_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void tank_dead ( edict_t * self ) ; extern void tank_attack ( edict_t * self ) ; extern void tank_doattack_rocket ( edict_t * self ) ; extern void tank_refire_rocket ( edict_t * self ) ; extern void tank_poststrike ( edict_t * self ) ; extern void tank_reattack_blaster ( edict_t * self ) ; extern void TankMachineGun ( edict_t * self ) ; extern void TankRocket ( edict_t * self ) ; extern void TankStrike ( edict_t * self ) ; extern void TankBlaster ( edict_t * self ) ; extern void tank_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void tank_run ( edict_t * self ) ; extern void tank_walk ( edict_t * self ) ; extern void tank_stand ( edict_t * self ) ; extern void tank_idle ( edict_t * self ) ; extern void tank_windup ( edict_t * self ) ; extern void tank_thud ( edict_t * self ) ; extern void tank_footstep ( edict_t * self ) ; extern void tank_sight ( edict_t * self , edict_t * other ) ; extern qboolean tank_blocked( edict_t *self, float dist ); extern void SP_monster_supertank ( edict_t * self ) ; extern qboolean supertank_blocked ( edict_t * self , float dist ) ; extern void supertank_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void BossExplode ( edict_t * self ) ; extern void supertank_dead ( edict_t * self ) ; extern void supertank_attack ( edict_t * self ) ; extern void supertankMachineGun ( edict_t * self ) ; extern void supertankRocket ( edict_t * self ) ; extern void supertank_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void supertank_reattack1 ( edict_t * self ) ; extern void supertank_run ( edict_t * self ) ; extern void supertank_walk ( edict_t * self ) ; extern void supertank_forward ( edict_t * self ) ; extern void supertank_stand ( edict_t * self ) ; extern void supertank_search ( edict_t * self ) ; extern void TreadSound ( edict_t * self ) ; extern void SP_monster_stalker ( edict_t * self ) ; extern void stalker_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void stalker_dead ( edict_t * self ) ; extern qboolean stalker_blocked ( edict_t * self , float dist ) ; extern void stalker_jump ( edict_t * self ) ; extern void stalker_jump_wait_land ( edict_t * self ) ; extern void stalker_jump_up ( edict_t * self ) ; extern void stalker_jump_down ( edict_t * self ) ; extern void stalker_dodge ( edict_t * self , edict_t * attacker , float eta , trace_t * tr ) ; extern void stalker_dodge_jump ( edict_t * self ) ; extern void stalker_jump_straightup ( edict_t * self ) ; extern int stalker_do_pounce ( edict_t * self , vec3_t dest ) ; extern int stalker_check_lz ( edict_t * self , edict_t * target , vec3_t dest ) ; extern void calcJumpAngle ( vec3_t start , vec3_t end , float velocity , vec3_t angles ) ; extern void stalker_attack_melee ( edict_t * self ) ; extern void stalker_swing_attack ( edict_t * self ) ; extern void stalker_attack_ranged ( edict_t * self ) ; extern void stalker_shoot_attack2 ( edict_t * self ) ; extern void stalker_shoot_attack ( edict_t * self ) ; extern void stalker_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void stalker_false_death_start ( edict_t * self ) ; extern void stalker_false_death ( edict_t * self ) ; extern void stalker_heal ( edict_t * self ) ; extern void stalker_reactivate ( edict_t * self ) ; extern void stalker_walk ( edict_t * self ) ; extern void stalker_run ( edict_t * self ) ; extern void stalker_stand ( edict_t * self ) ; extern void stalker_idle ( edict_t * self ) ; extern void stalker_idle_noise ( edict_t * self ) ; extern void stalker_sight ( edict_t * self , edict_t * other ) ; extern qboolean stalker_ok_to_transition ( edict_t * self ) ; extern void SP_monster_soldier_ss ( edict_t * self ) ; extern void SP_monster_soldier ( edict_t * self ) ; extern void SP_monster_soldier_light ( edict_t * self ) ; extern void SP_monster_soldier_x ( edict_t * self ) ; extern void soldier_footstep( edict_t *self ) ; extern void soldier_blind ( edict_t * self ) ; extern void soldier_duck ( edict_t * self , float eta ) ; extern void soldier_sidestep ( edict_t * self ) ; extern void soldier_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void soldier_dead2 ( edict_t * self ) ; extern void soldier_dead ( edict_t * self ) ; extern void soldier_fire7 ( edict_t * self ) ; extern void soldier_fire6 ( edict_t * self ) ; extern qboolean soldier_blocked ( edict_t * self , float dist ) ; extern void soldier_sight ( edict_t * self , edict_t * other ) ; extern void soldier_attack ( edict_t * self ) ; extern void soldier_attack6_refire ( edict_t * self ) ; extern void soldier_fire8 ( edict_t * self ) ; extern void soldier_fire4 ( edict_t * self ) ; extern void soldier_attack3_refire ( edict_t * self ) ; extern void soldier_fire3 ( edict_t * self ) ; extern void soldier_attack2_refire2 ( edict_t * self ) ; extern void soldier_attack2_refire1 ( edict_t * self ) ; extern void soldier_fire2 ( edict_t * self ) ; extern void soldier_attack1_refire2 ( edict_t * self ) ; extern void soldier_attack1_refire1 ( edict_t * self ) ; extern void soldier_fire1 ( edict_t * self ) ; extern void soldier_fire ( edict_t * self , int in_flash_number ) ; extern void soldier_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void soldier_run ( edict_t * self ) ; extern void soldier_fire_run ( edict_t * self ) ; extern void soldier_walk ( edict_t * self ) ; extern void soldier_walk1_random ( edict_t * self ) ; extern void soldier_stand ( edict_t * self ) ; extern void soldier_cock ( edict_t * self ) ; extern void soldier_idle ( edict_t * self ) ; extern void soldier_stop_charge ( edict_t * self ) ; extern void soldier_start_charge ( edict_t * self ) ; extern void SP_monster_parasite ( edict_t * self ) ; extern void parasite_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void parasite_dead ( edict_t * self ) ; extern qboolean parasite_checkattack ( edict_t * self ) ; extern qboolean parasite_blocked ( edict_t * self , float dist ) ; extern void parasite_jump ( edict_t * self ) ; extern void parasite_jump_wait_land ( edict_t * self ) ; extern void parasite_jump_up ( edict_t * self ) ; extern void parasite_jump_down ( edict_t * self ) ; extern void parasite_attack ( edict_t * self ) ; extern void parasite_drain_attack ( edict_t * self ) ; extern qboolean parasite_drain_attack_ok ( vec3_t start , vec3_t end ) ; extern void parasite_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void parasite_walk ( edict_t * self ) ; extern void parasite_start_walk ( edict_t * self ) ; extern void parasite_run ( edict_t * self ) ; extern void parasite_start_run ( edict_t * self ) ; extern void parasite_stand ( edict_t * self ) ; extern void parasite_idle ( edict_t * self ) ; extern void parasite_refidget ( edict_t * self ) ; extern void parasite_do_fidget ( edict_t * self ) ; extern void parasite_end_fidget ( edict_t * self ) ; extern void parasite_search ( edict_t * self ) ; extern void parasite_scratch ( edict_t * self ) ; extern void parasite_tap ( edict_t * self ) ; extern void parasite_sight ( edict_t * self , edict_t * other ) ; extern void parasite_reel_in ( edict_t * self ) ; extern void parasite_launch ( edict_t * self ) ; extern void SP_monster_mutant ( edict_t * self ) ; extern qboolean mutant_blocked ( edict_t * self , float dist ) ; extern void mutant_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void mutant_dead ( edict_t * self ) ; extern void mutant_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern qboolean mutant_checkattack ( edict_t * self ) ; extern qboolean mutant_check_jump ( edict_t * self ) ; extern qboolean mutant_check_melee ( edict_t * self ) ; extern void mutant_jump ( edict_t * self ) ; extern void mutant_check_landing ( edict_t * self ) ; extern void mutant_jump_takeoff ( edict_t * self ) ; extern void mutant_jump_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void mutant_melee ( edict_t * self ) ; extern void mutant_check_refire ( edict_t * self ) ; extern void mutant_hit_right ( edict_t * self ) ; extern void mutant_hit_left ( edict_t * self ) ; extern void mutant_run ( edict_t * self ) ; extern void mutant_walk ( edict_t * self ) ; extern void mutant_walk_loop ( edict_t * self ) ; extern void mutant_idle ( edict_t * self ) ; extern void mutant_idle_loop ( edict_t * self ) ; extern void mutant_stand ( edict_t * self ) ; extern void mutant_swing ( edict_t * self ) ; extern void mutant_search ( edict_t * self ) ; extern void mutant_sight ( edict_t * self , edict_t * other ) ; extern void mutant_step ( edict_t * self ) ; extern qboolean M_walkmove ( edict_t * ent , float yaw , float dist ) ; extern void M_MoveToGoal ( edict_t * ent , float dist ) ; extern qboolean SV_CloseEnough ( edict_t * ent , edict_t * goal , float dist ) ; extern void SV_NewChaseDir ( edict_t * actor , edict_t * enemy , float dist ) ; extern void SV_FixCheckBottom ( edict_t * ent ) ; extern qboolean SV_StepDirection ( edict_t * ent , float yaw , float dist ) ; extern void M_ChangeYaw ( edict_t * ent ) ; extern qboolean SV_movestep ( edict_t * ent , vec3_t move , qboolean relink ) ; extern qboolean IsBadAhead ( edict_t * self , edict_t * bad , vec3_t move ) ; extern qboolean M_CheckBottom ( edict_t * ent ) ; extern void SP_monster_medic ( edict_t * self ) ; extern qboolean medic_blocked ( edict_t *self, float dist ) ; extern void medic_sidestep( edict_t *self ) ; extern void medic_duck( edict_t *self, float eta ) ; extern void medic_footstep( edict_t *self ) ; extern qboolean medic_checkattack ( edict_t * self ) ; extern void medic_finish_spawn ( edict_t *self ); extern void medic_spawngrows ( edict_t *self ); extern void medic_determine_spawn ( edict_t *self ) ; extern void medic_start_spawn ( edict_t *self ) ; extern void medic_attack ( edict_t * self ) ; extern void medic_hook_retract ( edict_t * self ) ; extern void medic_cable_attack ( edict_t * self ) ; extern void medic_hook_launch ( edict_t * self ) ; extern void medic_continue ( edict_t * self ) ; extern void medic_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void medic_dead ( edict_t * self ) ; extern void medic_fire_blaster ( edict_t * self ) ; extern void medic_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void medic_run ( edict_t * self ) ; extern void medic_walk ( edict_t * self ) ; extern void medic_stand ( edict_t * self ) ; extern void medic_sight ( edict_t * self , edict_t * other ) ; extern void medic_search ( edict_t * self ) ; extern void medic_idle ( edict_t * self ) ; extern void cleanupHeal( edict_t *self, qboolean change_frame ) ; extern void abortHeal( edict_t *self, qboolean change_frame, qboolean gib, qboolean mark ) ; extern qboolean canReach ( edict_t *self, edict_t *other ) ; extern edict_t * medic_FindDeadMonster ( edict_t * self ) ; extern void SP_misc_insane ( edict_t * self ) ; extern void insane_footstep( edict_t *self ) ; extern void insane_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void insane_dead ( edict_t * self ) ; extern void insane_stand ( edict_t * self ) ; extern void insane_checkup ( edict_t * self ) ; extern void insane_checkdown ( edict_t * self ) ; extern void insane_onground ( edict_t * self ) ; extern void insane_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void insane_run ( edict_t * self ) ; extern void insane_walk ( edict_t * self ) ; extern void insane_cross ( edict_t * self ) ; extern void insane_scream ( edict_t * self ) ; extern void insane_moan ( edict_t * self ) ; extern void insane_shake ( edict_t * self ) ; extern void insane_fist ( edict_t * self ) ; extern void SP_monster_infantry ( edict_t * self ) ; extern void infantry_footstep( edict_t *self ) ; extern void infantry_sidestep ( edict_t * self ) ; extern void infantry_duck ( edict_t * self , float eta ) ; extern qboolean infantry_blocked ( edict_t * self , float dist ) ; extern void infantry_jump ( edict_t * self ) ; extern void infantry_jump_wait_land ( edict_t * self ) ; extern void infantry_jump2_now ( edict_t * self ) ; extern void infantry_jump_now ( edict_t * self ) ; extern void infantry_attack ( edict_t * self ) ; extern void infantry_smack ( edict_t * self ) ; extern void infantry_swing ( edict_t * self ) ; extern void infantry_fire_prep ( edict_t * self ) ; extern void infantry_fire ( edict_t * self ) ; extern void infantry_cock_gun ( edict_t * self ) ; extern void infantry_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void infantry_dead ( edict_t * self ) ; extern void infantry_sight ( edict_t * self , edict_t * other ) ; extern void InfantryMachineGun ( edict_t * self ) ; extern void infantry_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void infantry_run ( edict_t * self ) ; extern void infantry_walk ( edict_t * self ) ; extern void infantry_fidget ( edict_t * self ) ; extern void infantry_stand ( edict_t * self ) ; extern void SP_monster_hover ( edict_t * self ) ; extern qboolean hover_blocked ( edict_t *self, float dist ) ; extern void hover_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void hover_dead ( edict_t * self ) ; extern void hover_deadthink ( edict_t * self ) ; extern void hover_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void hover_attack ( edict_t * self ) ; extern void hover_start_attack ( edict_t * self ) ; extern void hover_walk ( edict_t * self ) ; extern void hover_run ( edict_t * self ) ; extern void hover_stand ( edict_t * self ) ; extern void hover_fire_blaster ( edict_t * self ) ; extern void hover_reattack ( edict_t * self ) ; extern void hover_search ( edict_t * self ) ; extern void hover_sight ( edict_t * self , edict_t * other ) ; extern void SP_monster_gunner ( edict_t * self ) ; extern void gunner_footstep( edict_t *self ) ; extern void gunner_sidestep ( edict_t * self ) ; extern void gunner_duck ( edict_t * self , float eta ) ; extern qboolean gunner_blocked ( edict_t * self , float dist ) ; extern void gunner_jump ( edict_t * self ) ; extern void gunner_jump_wait_land ( edict_t * self ) ; extern void gunner_jump2_now ( edict_t * self ) ; extern void gunner_jump_now ( edict_t * self ) ; extern void gunner_refire_chain ( edict_t * self ) ; extern void gunner_fire_chain ( edict_t * self ) ; extern void gunner_attack ( edict_t * self ) ; extern void gunner_blind_check ( edict_t * self ) ; extern void GunnerGrenade ( edict_t * self ) ; extern qboolean gunner_grenade_check ( edict_t * self ) ; extern void GunnerFire ( edict_t * self ) ; extern void gunner_opengun ( edict_t * self ) ; extern void gunner_duck_down ( edict_t * self ) ; extern void gunner_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void gunner_dead ( edict_t * self ) ; extern void gunner_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void gunner_runandshoot ( edict_t * self ) ; extern void gunner_run ( edict_t * self ) ; extern void gunner_walk ( edict_t * self ) ; extern void gunner_stand ( edict_t * self ) ; extern void gunner_fidget ( edict_t * self ) ; extern void gunner_search ( edict_t * self ) ; extern void gunner_sight ( edict_t * self , edict_t * other ) ; extern void gunner_idlesound ( edict_t * self ) ; extern void SP_monster_gladiator ( edict_t * self ) ; qboolean gladiator_blocked ( edict_t *self , float dist ) ; extern void gladiator_footstep( edict_t *self ) ; extern void gladiator_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void gladiator_dead ( edict_t * self ) ; extern void gladiator_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void gladiator_attack ( edict_t * self ) ; extern void GladiatorGun ( edict_t * self ) ; extern void gladiator_melee ( edict_t * self ) ; extern void GaldiatorMelee ( edict_t * self ) ; extern void gladiator_run ( edict_t * self ) ; extern void gladiator_walk ( edict_t * self ) ; extern void gladiator_stand ( edict_t * self ) ; extern void gladiator_cleaver_swing ( edict_t * self ) ; extern void gladiator_search ( edict_t * self ) ; extern void gladiator_sight ( edict_t * self , edict_t * other ) ; extern void gladiator_idle ( edict_t * self ) ; extern void SP_monster_kamikaze ( edict_t * self ) ; extern void SP_monster_flyer ( edict_t * self ) ; extern int flyer_blocked ( edict_t * self , float dist ) ; extern void flyer_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void flyer_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void flyer_check_melee ( edict_t * self ) ; extern void flyer_melee ( edict_t * self ) ; extern void flyer_nextmove ( edict_t * self ) ; extern void flyer_setstart ( edict_t * self ) ; extern void flyer_attack ( edict_t * self ) ; extern void flyer_loop_melee ( edict_t * self ) ; extern void flyer_slash_right ( edict_t * self ) ; extern void flyer_slash_left ( edict_t * self ) ; extern void flyer_fireright ( edict_t * self ) ; extern void flyer_fireleft ( edict_t * self ) ; extern void flyer_fire ( edict_t * self , int flash_number ) ; extern void flyer_start ( edict_t * self ) ; extern void flyer_stop ( edict_t * self ) ; extern void flyer_kamikaze_check ( edict_t * self ) ; extern void flyer_kamikaze ( edict_t * self ) ; extern void flyer_kamikaze_explode ( edict_t * self ) ; extern void flyer_stand ( edict_t * self ) ; extern void flyer_walk ( edict_t * self ) ; extern void flyer_run ( edict_t * self ) ; extern void flyer_pop_blades ( edict_t * self ) ; extern void flyer_idle ( edict_t * self ) ; extern void flyer_sight ( edict_t * self , edict_t * other ) ; extern void SP_monster_floater ( edict_t * self ) ; extern qboolean floater_blocked ( edict_t * self , float dist ) ; extern void floater_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void floater_dead ( edict_t * self ) ; extern void floater_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void floater_melee ( edict_t * self ) ; extern void floater_attack ( edict_t * self ) ; extern void floater_zap ( edict_t * self ) ; extern void floater_wham ( edict_t * self ) ; extern void floater_walk ( edict_t * self ) ; extern void floater_run ( edict_t * self ) ; extern void floater_stand ( edict_t * self ) ; extern void floater_fire_blaster ( edict_t * self ) ; extern void floater_idle ( edict_t * self ) ; extern void floater_sight ( edict_t * self , edict_t * other ) ; extern void SP_monster_flipper ( edict_t * self ) ; extern void flipper_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void flipper_sight ( edict_t * self , edict_t * other ) ; extern void flipper_dead ( edict_t * self ) ; extern void flipper_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void flipper_melee ( edict_t * self ) ; extern void flipper_preattack ( edict_t * self ) ; extern void flipper_bite ( edict_t * self ) ; extern void flipper_start_run ( edict_t * self ) ; extern void flipper_walk ( edict_t * self ) ; extern void flipper_run ( edict_t * self ) ; extern void flipper_run_loop ( edict_t * self ) ; extern void flipper_stand ( edict_t * self ) ; extern void SP_monster_chick ( edict_t * self ) ; extern void chick_footstep( edict_t *self ) ; extern void chick_sidestep ( edict_t * self ) ; extern void chick_duck ( edict_t * self , float eta ) ; extern qboolean chick_blocked ( edict_t * self , float dist ) ; extern void chick_sight ( edict_t * self , edict_t * other ) ; extern void chick_attack ( edict_t * self ) ; extern void chick_melee ( edict_t * self ) ; extern void chick_slash ( edict_t * self ) ; extern void chick_reslash ( edict_t * self ) ; extern void chick_attack1 ( edict_t * self ) ; extern void chick_rerocket ( edict_t * self ) ; extern void ChickReload ( edict_t * self ) ; extern void Chick_PreAttack1 ( edict_t * self ) ; extern void ChickRocket ( edict_t * self ) ; extern void ChickSlash ( edict_t * self ) ; extern void chick_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void chick_dead ( edict_t * self ) ; extern void chick_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void chick_run ( edict_t * self ) ; extern void chick_walk ( edict_t * self ) ; extern void chick_stand ( edict_t * self ) ; extern void chick_fidget ( edict_t * self ) ; extern void ChickMoan ( edict_t * self ) ; extern void SP_monster_carrier ( edict_t * self ) ; extern void CarrierPrecache ( ) ; extern qboolean Carrier_CheckAttack ( edict_t * self ) ; extern void carrier_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void carrier_dead ( edict_t * self ) ; extern void carrier_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void carrier_reattack_gren ( edict_t * self ) ; extern void carrier_attack_gren ( edict_t * self ) ; extern void carrier_reattack_mg ( edict_t * self ) ; extern void carrier_attack_mg ( edict_t * self ) ; extern void carrier_attack ( edict_t * self ) ; extern void CarrierMachineGunHold ( edict_t * self ) ; extern void carrier_walk ( edict_t * self ) ; extern void carrier_run ( edict_t * self ) ; extern void carrier_stand ( edict_t * self ) ; extern void CarrierSaveLoc ( edict_t * self ) ; extern void CarrierRail ( edict_t * self ) ; extern void carrier_start_spawn ( edict_t * self ) ; extern void carrier_ready_spawn ( edict_t * self ) ; extern void carrier_spawn_check ( edict_t * self ) ; extern void carrier_prep_spawn ( edict_t * self ) ; extern void CarrierSpawn ( edict_t * self ) ; extern void CarrierMachineGun ( edict_t * self ) ; extern void carrier_firebullet_left ( edict_t * self ) ; extern void carrier_firebullet_right ( edict_t * self ) ; extern void CarrierRocket ( edict_t * self ) ; extern void CarrierPredictiveRocket ( edict_t * self ) ; extern void CarrierGrenade ( edict_t * self ) ; extern void CarrierCoopCheck ( edict_t * self ) ; extern void carrier_sight ( edict_t * self , edict_t * other ) ; extern void SP_monster_brain ( edict_t * self ) ; extern void brain_footstep( edict_t *self ) ; extern void brain_duck ( edict_t * self , float eta ) ; extern void brain_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void brain_dead ( edict_t * self ) ; extern void brain_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void brain_run ( edict_t * self ) ; extern void brain_melee ( edict_t * self ) ; extern void brain_chest_closed ( edict_t * self ) ; extern void brain_tentacle_attack ( edict_t * self ) ; extern void brain_chest_open ( edict_t * self ) ; extern void brain_hit_left ( edict_t * self ) ; extern void brain_swing_left ( edict_t * self ) ; extern void brain_hit_right ( edict_t * self ) ; extern void brain_swing_right ( edict_t * self ) ; extern void brain_walk ( edict_t * self ) ; extern void brain_idle ( edict_t * self ) ; extern void brain_stand ( edict_t * self ) ; extern void brain_search ( edict_t * self ) ; extern void brain_sight ( edict_t * self , edict_t * other ) ; extern void MakronToss ( edict_t * self ) ; extern void MakronSpawn ( edict_t * self ) ; extern void SP_monster_makron ( edict_t * self ) ; extern void MakronPrecache ( void ) ; extern qboolean Makron_CheckAttack ( edict_t * self ) ; extern void makron_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void makron_torso_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void makron_dead ( edict_t * self ) ; extern void makron_torso ( edict_t * ent ) ; extern void makron_torso_think ( edict_t * self ) ; extern void makron_attack ( edict_t * self ) ; extern void makron_sight ( edict_t * self , edict_t * other ) ; extern void makron_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void MakronHyperblaster ( edict_t * self ) ; extern void MakronRailgun ( edict_t * self ) ; extern void MakronSaveloc ( edict_t * self ) ; extern void makronBFG ( edict_t * self ) ; extern void makron_run ( edict_t * self ) ; extern void makron_walk ( edict_t * self ) ; extern void makron_prerailgun ( edict_t * self ) ; extern void makron_brainsplorch ( edict_t * self ) ; extern void makron_step_right ( edict_t * self ) ; extern void makron_step_left ( edict_t * self ) ; extern void makron_popup ( edict_t * self ) ; extern void makron_hit ( edict_t * self ) ; extern void makron_stand ( edict_t * self ) ; extern void makron_taunt ( edict_t * self ) ; extern void SP_monster_jorg ( edict_t * self ) ; extern qboolean Jorg_CheckAttack ( edict_t * self ) ; extern void jorg_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void jorg_dead ( edict_t * self ) ; extern void jorg_attack ( edict_t * self ) ; extern void jorg_firebullet ( edict_t * self ) ; extern void jorg_firebullet_left ( edict_t * self ) ; extern void jorg_firebullet_right ( edict_t * self ) ; extern void jorgBFG ( edict_t * self ) ; extern void jorg_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void jorg_attack1 ( edict_t * self ) ; extern void jorg_reattack1 ( edict_t * self ) ; extern void jorg_run ( edict_t * self ) ; extern void jorg_walk ( edict_t * self ) ; extern void jorg_stand ( edict_t * self ) ; extern void jorg_step_right ( edict_t * self ) ; extern void jorg_step_left ( edict_t * self ) ; extern void jorg_death_hit ( edict_t * self ) ; extern void jorg_idle ( edict_t * self ) ; extern void jorg_search ( edict_t * self ) ; extern void SP_monster_boss3_stand ( edict_t * self ) ; extern void Think_Boss3Stand ( edict_t * ent ) ; extern void Use_Boss3 ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void SP_monster_boss2 ( edict_t * self ) ; extern qboolean Boss2_CheckAttack ( edict_t * self ) ; extern void boss2_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void boss2_dead ( edict_t * self ) ; extern void boss2_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void boss2_reattack_mg ( edict_t * self ) ; extern void boss2_attack_mg ( edict_t * self ) ; extern void boss2_attack ( edict_t * self ) ; extern void boss2_walk ( edict_t * self ) ; extern void boss2_run ( edict_t * self ) ; extern void boss2_stand ( edict_t * self ) ; extern void Boss2MachineGun ( edict_t * self ) ; extern void boss2_firebullet_left ( edict_t * self ) ; extern void boss2_firebullet_right ( edict_t * self ) ; extern void Boss2Rocket ( edict_t * self ) ; extern void boss2_search ( edict_t * self ) ; extern void SP_monster_berserk ( edict_t * self ) ; extern void berserk_footstep( edict_t *self ) ; extern void berserk_sidestep ( edict_t * self ) ; extern qboolean berserk_blocked ( edict_t * self , float dist ) ; extern void berserk_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void berserk_dead ( edict_t * self ) ; extern void berserk_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void berserk_melee ( edict_t * self ) ; extern void berserk_strike ( edict_t * self ) ; extern void berserk_attack_club ( edict_t * self ) ; extern void berserk_swing ( edict_t * self ) ; extern void berserk_attack_spike ( edict_t * self ) ; extern void berserk_run ( edict_t * self ) ; extern void berserk_walk ( edict_t * self ) ; extern void berserk_fidget ( edict_t * self ) ; extern void berserk_stand ( edict_t * self ) ; extern void berserk_search ( edict_t * self ) ; extern void berserk_sight ( edict_t * self , edict_t * other ) ; extern void fire_bfg ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , float damage_radius ) ; extern void bfg_think ( edict_t * self ) ; extern void bfg_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void bfg_explode ( edict_t * self ) ; extern void fire_rail ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick ) ; extern void fire_rocket ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , float damage_radius , int radius_damage ) ; extern void rocket_touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void fire_grenade2 ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int speed , float timer , float damage_radius , qboolean held ) ; extern void fire_grenade ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int speed , float timer , float damage_radius ) ; extern void Grenade_Touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Grenade_Explode ( edict_t * ent ) ; extern void fire_blaster ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int effect , qboolean hyper ) ; extern void blaster_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void fire_shotgun ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int hspread , int vspread , int count , int mod ) ; extern void fire_bullet ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int hspread , int vspread , int mod ) ; extern void fire_lead ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int te_impact , int hspread , int vspread , int mod ) ; extern qboolean fire_hit ( edict_t * self , vec3_t aim , int damage , int kick ) ; extern void check_dodge ( edict_t * self , vec3_t start , vec3_t dir , int speed ) ; extern qboolean KillBox ( edict_t * ent ) ; extern void G_TouchSolids ( edict_t * ent ) ; extern void G_TouchTriggers ( edict_t * ent ) ; extern void G_FreeEdict ( edict_t * ed ) ; extern edict_t * G_Spawn ( void ) ; extern void G_InitEdict ( edict_t * e ) ; extern char * G_CopyString ( char * in ) ; extern void vectoangles2 ( vec3_t value1 , vec3_t angles ) ; extern void vectoangles ( vec3_t value1 , vec3_t angles ) ; extern float vectoyaw2 ( vec3_t vec ) ; extern float vectoyaw ( vec3_t vec ) ; extern void G_SetMovedir ( vec3_t angles , vec3_t movedir ) ; extern char * vtos ( vec3_t v ) ; extern float * tv ( float x , float y , float z ) ; extern void G_UseTargets ( edict_t * ent , edict_t * activator ) ; extern void Think_Delay ( edict_t * ent ) ; extern edict_t * G_PickTarget ( char * targetname ) ; extern edict_t * findradius2 ( edict_t * from , vec3_t org , float rad ) ; extern edict_t * findradius ( edict_t * from , vec3_t org , float rad ) ; extern edict_t * G_Find ( edict_t * from , int fieldofs , char * match ) ; extern void G_ProjectSource2 ( vec3_t point , vec3_t distance , vec3_t forward , vec3_t right , vec3_t up , vec3_t result ) ; extern void G_ProjectSource ( vec3_t point , vec3_t distance , vec3_t forward , vec3_t right , vec3_t result ) ; extern void SP_turret_invisible_brain ( edict_t * self ) ; extern void turret_brain_activate ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void turret_brain_deactivate ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void turret_brain_link ( edict_t * self ) ; extern void turret_brain_think ( edict_t * self ) ; extern void SP_turret_driver ( edict_t * self ) ; extern void turret_driver_link ( edict_t * self ) ; extern void turret_driver_think ( edict_t * self ) ; extern void turret_driver_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void SP_turret_base ( edict_t * self ) ; extern void SP_turret_breach ( edict_t * self ) ; extern void turret_breach_finish_init ( edict_t * self ) ; extern void turret_breach_think ( edict_t * self ) ; extern void turret_breach_fire ( edict_t * self ) ; extern void turret_blocked ( edict_t * self , edict_t * other ) ; extern float SnapToEights ( float x ) ; extern void AnglesNormalize ( vec3_t vec ) ; extern void SP_trigger_monsterjump ( edict_t * self ) ; extern void trigger_monsterjump_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_trigger_gravity ( edict_t * self ) ; extern void trigger_gravity_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void trigger_gravity_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_trigger_hurt ( edict_t * self ) ; extern void hurt_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void hurt_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_trigger_push ( edict_t * self ) ; extern void trigger_push_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void trigger_push_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_trigger_always ( edict_t * ent ) ; extern void SP_trigger_counter ( edict_t * self ) ; extern void trigger_counter_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_trigger_key ( edict_t * self ) ; extern void trigger_key_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_trigger_relay ( edict_t * self ) ; extern void trigger_relay_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_trigger_once ( edict_t * ent ) ; extern void SP_trigger_multiple ( edict_t * ent ) ; extern void trigger_enable ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void Touch_Multi ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Use_Multi ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void multi_trigger ( edict_t * ent ) ; extern void multi_wait ( edict_t * ent ) ; extern void InitTrigger ( edict_t * self ) ; extern void SP_target_earthquake ( edict_t * self ) ; extern void target_earthquake_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void target_earthquake_think ( edict_t * self ) ; extern void SP_target_lightramp ( edict_t * self ) ; extern void target_lightramp_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void target_lightramp_think ( edict_t * self ) ; extern void SP_target_laser ( edict_t * self ) ; extern void target_laser_start ( edict_t * self ) ; extern void target_laser_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void target_laser_off ( edict_t * self ) ; extern void target_laser_on ( edict_t * self ) ; extern void target_laser_think ( edict_t * self ) ; extern void SP_target_crosslevel_target ( edict_t * self ) ; extern void target_crosslevel_target_think ( edict_t * self ) ; extern void SP_target_crosslevel_trigger ( edict_t * self ) ; extern void trigger_crosslevel_trigger_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_blaster ( edict_t * self ) ; extern void use_target_blaster ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_spawner ( edict_t * self ) ; extern void use_target_spawner ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_splash ( edict_t * self ) ; extern void use_target_splash ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_changelevel ( edict_t * ent ) ; extern void use_target_changelevel ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_explosion ( edict_t * ent ) ; extern void use_target_explosion ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void target_explosion_explode ( edict_t * self ) ; extern void SP_target_goal ( edict_t * ent ) ; extern void use_target_goal ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void SP_target_secret ( edict_t * ent ) ; extern void use_target_secret ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void SP_target_help ( edict_t * ent ) ; extern void Use_Target_Help ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void Target_Help_Think ( edict_t * ent ); extern void SP_target_speaker ( edict_t * ent ) ; extern void Use_Target_Speaker ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void SP_target_temp_entity ( edict_t * ent ) ; extern void Use_Target_Tent ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void ServerCommand ( void ) ; extern void SVCmd_WriteIP_f ( void ) ; extern void SVCmd_ListIP_f ( void ) ; extern void SVCmd_RemoveIP_f ( void ) ; extern void SVCmd_AddIP_f ( void ) ; extern qboolean SV_FilterPacket ( char * from ) ; extern void Svcmd_Test_f ( void ) ; extern void Vengeance_Launch ( edict_t * self ) ; extern void Hunter_Launch ( edict_t * self ) ; extern void Defender_Launch ( edict_t * self ) ; extern void Own_Sphere ( edict_t * self , edict_t * sphere ) ; extern edict_t * Sphere_Spawn ( edict_t * owner , int spawnflags ) ; extern void vengeance_think ( edict_t * self ) ; extern void hunter_think ( edict_t * self ) ; extern void defender_think ( edict_t * self ) ; extern void vengeance_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void defender_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void hunter_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void body_gib ( edict_t * self ) ; extern void defender_shoot ( edict_t * self , edict_t * enemy ) ; extern void hunter_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void vengeance_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void sphere_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf , int mod ) ; extern void sphere_fire ( edict_t * self , edict_t * enemy ) ; extern void sphere_chase ( edict_t * self , int stupidChase ) ; extern void sphere_fly ( edict_t * self ) ; extern void sphere_if_idle_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void sphere_explode ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void sphere_think_explode ( edict_t * self ) ; extern void Widowlegs_Spawn ( vec3_t startpos , vec3_t angles ) ; extern void widowlegs_think ( edict_t * self ) ; extern void SpawnGrow_Spawn ( vec3_t startpos , int size ) ; extern void spawngrow_think ( edict_t * self ) ; extern void DetermineBBox ( char * classname , vec3_t mins , vec3_t maxs ) ; extern qboolean CheckGroundSpawnPoint ( vec3_t origin , vec3_t entMins , vec3_t entMaxs , float height , float gravity ) ; extern qboolean CheckSpawnPoint ( vec3_t origin , vec3_t mins , vec3_t maxs ) ; extern qboolean FindSpawnPoint ( vec3_t startpoint , vec3_t mins , vec3_t maxs , vec3_t spawnpoint , float maxMoveUp ) ; extern edict_t * CreateGroundMonster ( vec3_t origin , vec3_t angles , vec3_t entMins , vec3_t entMaxs , char * classname , int height ) ; extern edict_t * CreateFlyMonster ( vec3_t origin , vec3_t angles , vec3_t mins , vec3_t maxs , char * classname ) ; extern edict_t * CreateMonster ( vec3_t origin , vec3_t angles , char * classname ) ; extern void SP_worldspawn ( edict_t * ent ) ; extern void SpawnEntities ( const char * mapname , char * entities , const char * spawnpoint ) ; extern void G_FindTeams ( void ) ; extern void G_FixTeams ( void ) ; extern char * ED_ParseEdict ( char * data , edict_t * ent ) ; extern void ED_ParseField ( const char * key , const char * value , edict_t * ent ) ; extern char * ED_NewString ( const char * string ) ; extern void ED_CallSpawn ( edict_t * ent ) ; extern void SV_Physics_NewToss ( edict_t * ent ) ; extern void G_RunEntity ( edict_t * ent ) ; extern void SV_Physics_Step ( edict_t * ent ) ; extern void SV_AddRotationalFriction ( edict_t * ent ) ; extern void SV_Physics_Toss ( edict_t * ent ) ; extern void SV_Physics_Noclip ( edict_t * ent ) ; extern void SV_Physics_None ( edict_t * ent ) ; extern void SV_Physics_Pusher ( edict_t * ent ) ; extern qboolean SV_Push ( edict_t * pusher , vec3_t move , vec3_t amove ) ; extern trace_t SV_PushEntity ( edict_t * ent , vec3_t push ) ; extern void RealBoundingBox ( edict_t * ent , vec3_t mins , vec3_t maxs ) ; extern void SV_AddGravity ( edict_t * ent ) ; extern int SV_FlyMove ( edict_t * ent , float time , int mask ) ; extern int ClipVelocity ( vec3_t in , vec3_t normal , vec3_t out , float overbounce ) ; extern void SV_Impact ( edict_t * e1 , trace_t * trace ) ; extern qboolean SV_RunThink ( edict_t * ent ) ; extern void SV_CheckVelocity ( edict_t * ent ) ; extern edict_t * SV_TestEntityPosition ( edict_t * ent ) ; extern void fire_tracker ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , edict_t * enemy ) ; extern void tracker_fly ( edict_t * self ) ; extern void tracker_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void tracker_explode ( edict_t * self ) ; extern void tracker_pain_daemon_spawn ( edict_t * owner , edict_t * enemy , int damage ) ; extern void tracker_pain_daemon_think ( edict_t * self ) ; extern void fire_blaster2 ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int effect , qboolean hyper ) ; extern void blaster2_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void fire_heat ( edict_t * self , vec3_t start , vec3_t aimdir , vec3_t offset , int damage , int kick , qboolean monster ) ; extern void fire_beams ( edict_t * self , vec3_t start , vec3_t aimdir , vec3_t offset , int damage , int kick , int te_beam , int te_impact , int mod ) ; extern void fire_tesla ( edict_t * self , vec3_t start , vec3_t aimdir , int damage_multiplier , int speed ) ; extern void tesla_lava ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void tesla_think ( edict_t * ent ) ; extern void tesla_activate ( edict_t * self ) ; extern void tesla_think_active ( edict_t * self ) ; extern void tesla_zap ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void tesla_blow ( edict_t * self ) ; extern void tesla_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void tesla_remove ( edict_t * self ) ; extern void fire_nuke ( edict_t * self , vec3_t start , vec3_t aimdir , int speed ) ; extern void nuke_bounce ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Nuke_Think ( edict_t * ent ) ; extern void nuke_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void Nuke_Explode ( edict_t * ent ) ; extern void Nuke_Quake ( edict_t * self ) ; extern void fire_player_melee ( edict_t * self , vec3_t start , vec3_t aim , int reach , int damage , int kick , int quiet , int mod ) ; extern void fire_prox ( edict_t * self , vec3_t start , vec3_t aimdir , int damage_multiplier , int speed ) ; extern void prox_land ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void prox_open ( edict_t * ent ) ; extern void prox_seek ( edict_t * ent ) ; extern void Prox_Field_Touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void prox_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void Prox_Explode ( edict_t * ent ) ; extern void fire_flechette ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int kick ) ; extern void flechette_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_trigger_disguise ( edict_t * self ) ; extern void trigger_disguise_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void trigger_disguise_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_trigger_teleport ( edict_t * self ) ; extern void trigger_teleport_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void trigger_teleport_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_info_teleport_destination ( edict_t * self ) ; extern void SP_target_orb ( edict_t * ent ) ; extern void orb_think ( edict_t * self ) ; extern void SP_target_blacklight ( edict_t * ent ) ; extern void blacklight_think ( edict_t * self ) ; extern void SP_target_killplayers ( edict_t * self ) ; extern void target_killplayers_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_anger ( edict_t * self ) ; extern void target_anger_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_steam ( edict_t * self ) ; extern void target_steam_start ( edict_t * self ) ; extern void use_target_steam ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_force_wall ( edict_t * ent ) ; extern void force_wall_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void force_wall_think ( edict_t * self ) ; extern void SP_func_door_secret2 ( edict_t * ent ) ; extern void secret_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void secret_blocked ( edict_t * self , edict_t * other ) ; extern void fd_secret_done ( edict_t * self ) ; extern void fd_secret_move6 ( edict_t * self ) ; extern void fd_secret_move5 ( edict_t * self ) ; extern void fd_secret_move4 ( edict_t * self ) ; extern void fd_secret_move3 ( edict_t * self ) ; extern void fd_secret_move2 ( edict_t * self ) ; extern void fd_secret_move1 ( edict_t * self ) ; extern void fd_secret_killed ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void fd_secret_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void fire_doppleganger ( edict_t * ent , vec3_t start , vec3_t aimdir ) ; extern void body_think ( edict_t * self ) ; extern void doppleganger_timeout ( edict_t * self ) ; extern void doppleganger_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void doppleganger_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void PrecacheForRandomRespawn ( void ) ; extern edict_t * DoRandomRespawn ( edict_t * ent ) ; extern char * FindSubstituteItem ( edict_t * ent ) ; extern void InitGameRules ( void ) ; extern qboolean monster_jump_finished ( edict_t * self ) ; extern void monster_jump_start ( edict_t * self ) ; extern int CountPlayers ( void ) ; extern edict_t * PickCoopTarget ( edict_t * self ) ; extern void TargetTesla ( edict_t * self , edict_t * tesla ) ; extern qboolean has_valid_enemy ( edict_t * self ) ; extern void monster_duck_up ( edict_t * self ) ; extern void monster_duck_hold ( edict_t * self ) ; extern void monster_duck_down ( edict_t * self ) ; extern void M_MonsterDodge ( edict_t * self , edict_t * attacker , float eta , trace_t * tr ) ; extern void drawbbox ( edict_t * self ) ; extern qboolean below ( edict_t * self , edict_t * other ) ; extern void PredictAim ( edict_t * target , vec3_t start , float bolt_speed , qboolean eye_height , float offset , vec3_t aimdir , vec3_t aimpoint ) ; extern qboolean MarkTeslaArea ( edict_t * self , edict_t * tesla ) ; extern edict_t * CheckForBadArea ( edict_t * ent ) ; extern edict_t * SpawnBadArea ( vec3_t mins , vec3_t maxs , float lifespan , edict_t * owner ) ; extern void badarea_touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern qboolean face_wall ( edict_t * self ) ; extern float realrange ( edict_t * self , edict_t * other ) ; extern qboolean inback ( edict_t * self , edict_t * other ) ; extern void InitHintPaths ( void ) ; extern void SP_hint_path ( edict_t * self ) ; extern void hint_path_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern qboolean monsterlost_checkhint ( edict_t * self ) ; extern void hintpath_stop ( edict_t * self ) ; extern void hintpath_go ( edict_t * self , edict_t * point ) ; extern edict_t * hintpath_other_end ( edict_t * ent ) ; extern edict_t * hintpath_findstart ( edict_t * ent ) ; extern qboolean blocked_checknewenemy ( edict_t * self ) ; extern qboolean blocked_checkjump ( edict_t * self , float dist , float maxDown , float maxUp ) ; extern qboolean blocked_checkplat ( edict_t * self , float dist ) ; extern void monster_done_dodge ( edict_t * self ) ; extern void stationarymonster_start ( edict_t * self ) ; extern void stationarymonster_start_go ( edict_t * self ) ; extern void stationarymonster_triggered_start ( edict_t * self ) ; extern void stationarymonster_triggered_spawn_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void stationarymonster_triggered_spawn ( edict_t * self ) ; extern void swimmonster_start ( edict_t * self ) ; extern void swimmonster_start_go ( edict_t * self ) ; extern void flymonster_start ( edict_t * self ) ; extern void flymonster_start_go ( edict_t * self ) ; extern void walkmonster_start ( edict_t * self ) ; extern void walkmonster_start_go ( edict_t * self ) ; extern void monster_start_go ( edict_t * self ) ; extern qboolean monster_start ( edict_t * self ) ; extern void monster_death_use ( edict_t * self ) ; extern void monster_triggered_start ( edict_t * self ) ; extern void monster_triggered_spawn_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void monster_triggered_spawn ( edict_t * self ) ; extern void monster_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void monster_think ( edict_t * self ) ; extern void M_MoveFrame ( edict_t * self ) ; extern void M_SetEffects ( edict_t * ent ) ; extern void M_droptofloor ( edict_t * ent ) ; extern void M_WorldEffects ( edict_t * ent ) ; extern void M_CatagorizePosition ( edict_t * ent ) ; extern void M_CheckGround ( edict_t * ent ) ; extern void AttackFinished ( edict_t * self , float time ) ; extern void M_FlyCheck ( edict_t * self ) ; extern void M_FliesOn ( edict_t * self ) ; extern void M_FliesOff ( edict_t * self ) ; extern void monster_fire_bfg ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int speed , int kick , float damage_radius , int flashtype ) ; extern void monster_fire_railgun ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int flashtype ) ; extern void monster_fire_rocket ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int flashtype ) ; extern void monster_fire_grenade ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int speed , int flashtype ) ; extern void monster_fire_heat ( edict_t * self , vec3_t start , vec3_t dir , vec3_t offset , int damage , int kick , int flashtype ) ; extern void monster_fire_tracker ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , edict_t * enemy , int flashtype ) ; extern void monster_fire_blaster2 ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int flashtype , int effect ) ; extern void monster_fire_blaster ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int flashtype , int effect ) ; extern void monster_fire_shotgun ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int hspread , int vspread , int count , int flashtype ) ; extern void monster_fire_bullet ( edict_t * self , vec3_t start , vec3_t dir , int damage , int kick , int hspread , int vspread , int flashtype ) ; extern void SP_misc_nuke_core ( edict_t * ent ) ; extern void misc_nuke_core_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_misc_teleporter_dest ( edict_t * ent ) ; extern void SP_misc_teleporter ( edict_t * ent ) ; extern void teleporter_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_func_clock ( edict_t * self ) ; extern void func_clock_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_clock_think ( edict_t * self ) ; extern void func_clock_format_countdown ( edict_t * self ) ; extern void func_clock_reset ( edict_t * self ) ; extern void SP_target_string ( edict_t * self ) ; extern void target_string_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_target_character ( edict_t * self ) ; extern void SP_misc_gib_head ( edict_t * ent ) ; extern void SP_misc_gib_leg ( edict_t * ent ) ; extern void SP_misc_gib_arm ( edict_t * ent ) ; extern void SP_light_mine2 ( edict_t * ent ) ; extern void SP_light_mine1 ( edict_t * ent ) ; extern void SP_misc_satellite_dish ( edict_t * ent ) ; extern void misc_satellite_dish_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void misc_satellite_dish_think ( edict_t * self ) ; extern void SP_misc_strogg_ship ( edict_t * ent ) ; extern void misc_strogg_ship_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_misc_viper_bomb ( edict_t * self ) ; extern void misc_viper_bomb_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void misc_viper_bomb_prethink ( edict_t * self ) ; extern void misc_viper_bomb_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_misc_bigviper ( edict_t * ent ) ; extern void SP_misc_viper ( edict_t * ent ) ; extern void misc_viper_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_misc_deadsoldier ( edict_t * ent ) ; extern void misc_deadsoldier_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void SP_misc_banner ( edict_t * ent ) ; extern void misc_banner_think ( edict_t * ent ) ; extern void SP_monster_commander_body ( edict_t * self ) ; extern void commander_body_drop ( edict_t * self ) ; extern void commander_body_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void commander_body_think ( edict_t * self ) ; extern void SP_misc_easterchick2 ( edict_t * ent ) ; extern void misc_easterchick2_think ( edict_t * self ) ; extern void SP_misc_easterchick ( edict_t * ent ) ; extern void misc_easterchick_think ( edict_t * self ) ; extern void SP_misc_eastertank ( edict_t * ent ) ; extern void misc_eastertank_think ( edict_t * self ) ; extern void SP_misc_blackhole ( edict_t * ent ) ; extern void misc_blackhole_think ( edict_t * self ) ; extern void misc_blackhole_use ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void SP_misc_explobox ( edict_t * self ) ; extern void barrel_start ( edict_t * self ) ; extern void barrel_think ( edict_t * self ) ; extern void barrel_delay ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void barrel_explode ( edict_t * self ) ; extern void barrel_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_func_explosive ( edict_t * self ) ; extern void func_explosive_spawn ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_explosive_activate ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_explosive_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_explosive_explode ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void SP_func_object ( edict_t * self ) ; extern void func_object_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_object_release ( edict_t * self ) ; extern void func_object_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_func_wall ( edict_t * self ) ; extern void func_wall_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_light ( edict_t * self ) ; extern void light_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_info_notnull ( edict_t * self ) ; extern void SP_info_null ( edict_t * self ) ; extern void SP_viewthing ( edict_t * ent ) ; extern void TH_viewthing ( edict_t * ent ) ; extern void SP_point_combat ( edict_t * self ) ; extern void point_combat_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void SP_path_corner ( edict_t * self ) ; extern void path_corner_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void BecomeExplosion2 ( edict_t * self ) ; extern void BecomeExplosion1 ( edict_t * self ) ; extern void ThrowDebris ( edict_t * self , char * modelname , float speed , vec3_t origin ) ; extern void debris_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void ThrowClientHead ( edict_t * self , int damage ) ; extern void ThrowHead ( edict_t * self , char * gibname , int damage , int type ) ; extern void ThrowGib ( edict_t * self , char * gibname , int damage , int type ) ; extern void gib_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void gib_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void gib_think ( edict_t * self ) ; extern void ClipGibVelocity ( edict_t * ent ) ; extern void VelocityForDamage ( int damage , vec3_t v ) ; extern void SP_func_areaportal ( edict_t * ent ) ; extern void Use_Areaportal ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void G_RunFrame ( void ) ; extern void ExitLevel ( void ) ; extern void CheckDMRules ( void ) ; extern void CheckNeedPass ( void ) ; extern void EndDMLevel ( void ) ; extern edict_t * CreateTargetChangeLevel ( char * map ) ; extern void ClientEndServerFrames ( void ) ; extern void Com_Printf ( char * msg , ... ) ; extern void Sys_Error ( char * error , ... ) ; extern game_export_t * GetGameAPI ( game_import_t * import ) ; extern void ShutdownGame ( void ) ; extern void SP_xatrix_item ( edict_t * self ) ; extern void SetItemNames ( void ) ; extern void InitItems ( void ) ; extern void SP_item_health_mega ( edict_t * self ) ; extern void SP_item_health_large ( edict_t * self ) ; extern void SP_item_health_small ( edict_t * self ) ; extern void SP_item_health ( edict_t * self ) ; extern void SpawnItem ( edict_t * ent , gitem_t * item ) ; extern void SetTriggeredSpawn ( edict_t * ent ) ; extern void Item_TriggeredSpawn ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void PrecacheItem ( gitem_t * it ) ; extern void droptofloor ( edict_t * ent ) ; extern void Use_Item ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern edict_t * Drop_Item ( edict_t * ent , gitem_t * item ) ; extern void drop_make_touchable ( edict_t * ent ) ; extern void drop_temp_touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Touch_Item ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Drop_PowerArmor ( edict_t * ent , gitem_t * item ) ; extern qboolean Pickup_PowerArmor ( edict_t * ent , edict_t * other ) ; extern void Use_PowerArmor ( edict_t * ent , gitem_t * item ) ; extern int PowerArmorType ( edict_t * ent ) ; extern qboolean Pickup_Armor ( edict_t * ent , edict_t * other ) ; extern int ArmorIndex ( edict_t * ent ) ; extern qboolean Pickup_Health ( edict_t * ent , edict_t * other ) ; extern void MegaHealth_think ( edict_t * self ) ; extern void Drop_Ammo ( edict_t * ent , gitem_t * item ) ; extern qboolean Pickup_Ammo ( edict_t * ent , edict_t * other ) ; extern qboolean Add_Ammo ( edict_t * ent , gitem_t * item , int count ) ; extern qboolean Pickup_Key ( edict_t * ent , edict_t * other ) ; extern void Use_Silencer ( edict_t * ent , gitem_t * item ) ; extern void Use_Invulnerability ( edict_t * ent , gitem_t * item ) ; extern void Use_Envirosuit ( edict_t * ent , gitem_t * item ) ; extern void Use_Breather ( edict_t * ent , gitem_t * item ) ; extern void Use_Quad ( edict_t * ent , gitem_t * item ) ; extern void Use_Vengeance ( edict_t * ent , gitem_t * item ) ; extern void Use_Hunter ( edict_t * ent , gitem_t * item ) ; extern void Use_Defender ( edict_t * ent , gitem_t * item ) ; extern qboolean Pickup_Sphere ( edict_t * ent , edict_t * other ) ; extern qboolean Pickup_Doppleganger ( edict_t * ent , edict_t * other ) ; extern void Use_Doppleganger ( edict_t * ent , gitem_t * item ) ; extern void Use_Nuke ( edict_t * ent , gitem_t * item ) ; extern void Use_Compass ( edict_t * ent , gitem_t * item ) ; extern void Use_Double ( edict_t * ent , gitem_t * item ) ; extern void Use_IR ( edict_t * ent , gitem_t * item ) ; extern qboolean Pickup_Nuke ( edict_t * ent , edict_t * other ) ; extern qboolean Pickup_Pack ( edict_t * ent , edict_t * other ) ; extern qboolean Pickup_Bandolier ( edict_t * ent , edict_t * other ) ; extern qboolean Pickup_AncientHead ( edict_t * ent , edict_t * other ) ; extern qboolean Pickup_Adrenaline ( edict_t * ent , edict_t * other ) ; extern void Drop_General ( edict_t * ent , gitem_t * item ) ; extern qboolean Pickup_Powerup ( edict_t * ent , edict_t * other ) ; extern void SetRespawn ( edict_t * ent , float delay ) ; extern void DoRespawn ( edict_t * ent ) ; extern gitem_t * FindItem ( char * pickup_name ) ; extern gitem_t * FindItemByClassname ( char * classname ) ; extern gitem_t * GetItemByIndex ( int index ) ; extern void SP_func_killbox ( edict_t * ent ) ; extern void use_killbox ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_door_secret ( edict_t * ent ) ; extern void door_secret_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void door_secret_blocked ( edict_t * self , edict_t * other ) ; extern void door_secret_done ( edict_t * self ) ; extern void door_secret_move6 ( edict_t * self ) ; extern void door_secret_move5 ( edict_t * self ) ; extern void door_secret_move4 ( edict_t * self ) ; extern void door_secret_move3 ( edict_t * self ) ; extern void door_secret_move2 ( edict_t * self ) ; extern void door_secret_move1 ( edict_t * self ) ; extern void door_secret_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_conveyor ( edict_t * self ) ; extern void func_conveyor_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_timer ( edict_t * self ) ; extern void func_timer_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_timer_think ( edict_t * self ) ; extern void SP_trigger_elevator ( edict_t * self ) ; extern void trigger_elevator_init ( edict_t * self ) ; extern void trigger_elevator_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_train ( edict_t * self ) ; extern void train_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void func_train_find ( edict_t * self ) ; extern void train_resume ( edict_t * self ) ; extern void train_next ( edict_t * self ) ; extern void train_piece_wait ( edict_t * self ) ; extern void train_wait ( edict_t * self ) ; extern void train_blocked ( edict_t * self , edict_t * other ) ; extern void SP_func_water ( edict_t * self ) ; extern void smart_water_blocked ( edict_t * self , edict_t * other ) ; extern void SP_func_door_rotating ( edict_t * ent ) ; extern void Door_Activate ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void SP_func_door ( edict_t * ent ) ; extern void door_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void door_killed ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void door_blocked ( edict_t * self , edict_t * other ) ; extern void Think_SpawnDoorTrigger ( edict_t * ent ) ; extern void Think_CalcMoveSpeed ( edict_t * self ) ; extern void Touch_DoorTrigger ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void door_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void smart_water_go_up ( edict_t * self ) ; extern void door_go_up ( edict_t * self , edict_t * activator ) ; extern void door_go_down ( edict_t * self ) ; extern void door_hit_bottom ( edict_t * self ) ; extern void door_hit_top ( edict_t * self ) ; extern void door_use_areaportals ( edict_t * self , qboolean open ) ; extern void SP_func_button ( edict_t * ent ) ; extern void button_killed ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void button_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void button_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void button_fire ( edict_t * self ) ; extern void button_wait ( edict_t * self ) ; extern void button_return ( edict_t * self ) ; extern void button_done ( edict_t * self ) ; extern void SP_func_rotating ( edict_t * ent ) ; extern void rotating_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void rotating_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void rotating_blocked ( edict_t * self , edict_t * other ) ; extern void rotating_decel ( edict_t * self ) ; extern void rotating_accel ( edict_t * self ) ; extern void SP_func_plat2 ( edict_t * ent ) ; extern void plat2_activate ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void Use_Plat2 ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void plat2_blocked ( edict_t * self , edict_t * other ) ; extern void Touch_Plat_Center2 ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void plat2_operate ( edict_t * ent , edict_t * other ) ; extern void plat2_go_up ( edict_t * ent ) ; extern void plat2_go_down ( edict_t * ent ) ; extern void plat2_hit_bottom ( edict_t * ent ) ; extern void plat2_hit_top ( edict_t * ent ) ; extern void plat2_kill_danger_area ( edict_t * ent ) ; extern void plat2_spawn_danger_area ( edict_t * ent ) ; extern void SP_func_plat ( edict_t * ent ) ; extern edict_t * plat_spawn_inside_trigger ( edict_t * ent ) ; extern void Touch_Plat_Center ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void Use_Plat ( edict_t * ent , edict_t * other , edict_t * activator ) ; extern void plat_blocked ( edict_t * self , edict_t * other ) ; extern void plat_go_up ( edict_t * ent ) ; extern void plat_go_down ( edict_t * ent ) ; extern void plat_hit_bottom ( edict_t * ent ) ; extern void plat_hit_top ( edict_t * ent ) ; extern void Think_AccelMove ( edict_t * ent ) ; extern void plat_Accelerate ( moveinfo_t * moveinfo ) ; extern void plat_CalcAcceleratedMove ( moveinfo_t * moveinfo ) ; extern void AngleMove_Calc ( edict_t * ent , void ( * func ) ( edict_t * ) ) ; extern void AngleMove_Begin ( edict_t * ent ) ; extern void AngleMove_Final ( edict_t * ent ) ; extern void AngleMove_Done ( edict_t * ent ) ; extern void Move_Calc ( edict_t * ent , vec3_t dest , void ( * func ) ( edict_t * ) ) ; extern void Move_Begin ( edict_t * ent ) ; extern void Move_Final ( edict_t * ent ) ; extern void Move_Done ( edict_t * ent ) ; extern void T_RadiusClassDamage ( edict_t * inflictor , edict_t * attacker , float damage , char * ignoreClass , float radius , int mod ) ; extern void T_RadiusNukeDamage ( edict_t * inflictor , edict_t * attacker , float damage , edict_t * ignore , float radius , int mod ) ; extern void T_RadiusDamage ( edict_t * inflictor , edict_t * attacker , float damage , edict_t * ignore , float radius , int mod ) ; extern void T_Damage ( edict_t * targ , edict_t * inflictor , edict_t * attacker , vec3_t dir , vec3_t point , vec3_t normal , int damage , int knockback , int dflags , int mod ) ; extern qboolean CheckTeamDamage ( edict_t * targ , edict_t * attacker ) ; extern void M_ReactToDamage ( edict_t * targ , edict_t * attacker , edict_t * inflictor ) ; extern int CheckArmor ( edict_t * ent , vec3_t point , vec3_t normal , int damage , int te_sparks , int dflags ) ; extern int CheckPowerArmor ( edict_t * ent , vec3_t point , vec3_t normal , int damage , int dflags ) ; extern void SpawnDamage ( int type , vec3_t origin , vec3_t normal , int damage ) ; extern void Killed ( edict_t * targ , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern qboolean CanDamage ( edict_t * targ , edict_t * inflictor ) ; extern void cleanupHealTarget ( edict_t * ent ) ; extern void ClientCommand ( edict_t * ent ) ; extern void Cmd_PlayerList_f ( edict_t * ent ) ; extern void Cmd_Ent_Count_f ( edict_t * ent ) ; extern void Cmd_Say_f ( edict_t * ent , qboolean team , qboolean arg0 ) ; extern void Cmd_Wave_f ( edict_t * ent ) ; extern void Cmd_Players_f ( edict_t * ent ) ; extern int PlayerSort ( void const * a , void const * b ) ; extern void Cmd_PutAway_f ( edict_t * ent ) ; extern void Cmd_Kill_f ( edict_t * ent ) ; extern void Cmd_InvDrop_f ( edict_t * ent ) ; extern void Cmd_WeapLast_f ( edict_t * ent ) ; extern void Cmd_WeapNext_f ( edict_t * ent ) ; extern void Cmd_WeapPrev_f ( edict_t * ent ) ; extern void Cmd_InvUse_f ( edict_t * ent ) ; extern void Cmd_Inven_f ( edict_t * ent ) ; extern void Cmd_Drop_f ( edict_t * ent ) ; extern void Cmd_Use_f ( edict_t * ent ) ; extern void Cmd_Noclip_f ( edict_t * ent ) ; extern void Cmd_Notarget_f ( edict_t * ent ) ; extern void Cmd_God_f ( edict_t * ent ) ; extern void Cmd_Give_f ( edict_t * ent ) ; extern void ValidateSelectedItem ( edict_t * ent ) ; extern void SelectPrevItem ( edict_t * ent , int itflags ) ; extern void SelectNextItem ( edict_t * ent , int itflags ) ; extern qboolean OnSameTeam ( edict_t * ent1 , edict_t * ent2 ) ; extern void GetChaseTarget ( edict_t * ent ) ; extern void ChasePrev ( edict_t * ent ) ; extern void ChaseNext ( edict_t * ent ) ; extern void UpdateChaseCam ( edict_t * ent ) ; extern void ai_run ( edict_t * self , float dist ) ; extern qboolean ai_checkattack ( edict_t * self , float dist ) ; extern void ai_run_slide ( edict_t * self , float distance ) ; extern void ai_run_missile ( edict_t * self ) ; extern void ai_run_melee ( edict_t * self ) ; extern qboolean M_CheckAttack ( edict_t * self ) ; extern qboolean FacingIdeal ( edict_t * self ) ; extern qboolean FindTarget ( edict_t * self ) ; extern void FoundTarget ( edict_t * self ) ; extern void HuntTarget ( edict_t * self ) ; extern qboolean infront ( edict_t * self , edict_t * other ) ; extern qboolean visible ( edict_t * self , edict_t * other ) ; extern int range ( edict_t * self , edict_t * other ) ; extern void ai_turn ( edict_t * self , float dist ) ; extern void ai_charge ( edict_t * self , float dist ) ; extern void ai_walk ( edict_t * self , float dist ) ; extern void ai_stand ( edict_t * self , float dist ) ; extern void ai_move ( edict_t * self , float dist ) ; extern void AI_SetSightClient ( void ) ; extern void SP_dm_tag_token ( edict_t * self ) ; extern void Tag_PostInitSetup ( void ) ; extern void Tag_GameInit ( void ) ; extern int Tag_ChangeDamage ( edict_t * targ , edict_t * attacker , int damage , int mod ) ; extern void Tag_DogTag ( edict_t * ent , edict_t * killer , char * * pic ) ; extern void Tag_PlayerEffects ( edict_t * ent ) ; extern void Tag_DropToken ( edict_t * ent , gitem_t * item ) ; extern void Tag_MakeTouchable ( edict_t * ent ) ; extern void Tag_Respawn ( edict_t * ent ) ; extern qboolean Tag_PickupToken ( edict_t * ent , edict_t * other ) ; extern void Tag_Score ( edict_t * attacker , edict_t * victim , int scoreChange ) ; extern void Tag_PlayerDisconnect ( edict_t * self ) ; extern void Tag_KillItBonus ( edict_t * self ) ; extern void Tag_PlayerDeath ( edict_t * targ , edict_t * inflictor , edict_t * attacker ) ; extern void SP_dm_dball_goal ( edict_t * self ) ; extern void SP_dm_dball_speed_change ( edict_t * self ) ; extern void SP_dm_dball_ball_start ( edict_t * self ) ; extern void SP_dm_dball_team2_start ( edict_t * self ) ; extern void SP_dm_dball_team1_start ( edict_t * self ) ; extern void SP_dm_dball_ball ( edict_t * self ) ; extern void DBall_SpeedTouch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void DBall_BallRespawn ( edict_t * self ) ; extern void DBall_BallDie ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void DBall_BallPain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void DBall_BallTouch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern edict_t * PickBallStart ( edict_t * ent ) ; extern void DBall_GoalTouch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern int DBall_ChangeKnockback ( edict_t * targ , edict_t * attacker , int knockback , int mod ) ; extern int DBall_ChangeDamage ( edict_t * targ , edict_t * attacker , int damage , int mod ) ; extern void DBall_PostInitSetup ( void ) ; extern void DBall_GameInit ( void ) ; extern void DBall_SelectSpawnPoint ( edict_t * ent , vec3_t origin , vec3_t angles ) ; extern void DBall_ClientBegin ( edict_t * ent ) ; extern int DBall_CheckDMRules ( void ) ; extern void wait_and_change_think(edict_t* ent); rogue-ROGUE_2_13/src/savegame/tables/gamefunc_list.h000066400000000000000000002054361477320066100224440ustar00rootroot00000000000000/* * Copyright (C) 1997-2001 Id Software, Inc. * Copyright (C) 2011 Yamagi Burmeister * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * ======================================================================= * * Functionpointers to every function in the game.so. * * ======================================================================= */ {"ReadLevel", (byte *)ReadLevel}, {"ReadLevelLocals", (byte *)ReadLevelLocals}, {"ReadEdict", (byte *)ReadEdict}, {"WriteLevel", (byte *)WriteLevel}, {"WriteLevelLocals", (byte *)WriteLevelLocals}, {"WriteEdict", (byte *)WriteEdict}, {"ReadGame", (byte *)ReadGame}, {"WriteGame", (byte *)WriteGame}, {"ReadClient", (byte *)ReadClient}, {"WriteClient", (byte *)WriteClient}, {"ReadField", (byte *)ReadField}, {"WriteField2", (byte *)WriteField2}, {"WriteField1", (byte *)WriteField1}, {"FindMmoveByName", (byte *)FindMmoveByName}, {"GetMmoveByAddress", (byte *)GetMmoveByAddress}, {"FindFunctionByName", (byte *)FindFunctionByName}, {"GetFunctionByAddress", (byte *)GetFunctionByAddress}, {"InitGame", (byte *)InitGame}, {"Info_SetValueForKey", (byte *)Info_SetValueForKey}, {"Info_Validate", (byte *)Info_Validate}, {"Info_RemoveKey", (byte *)Info_RemoveKey}, {"Info_ValueForKey", (byte *)Info_ValueForKey}, {"Com_sprintf", (byte *)Com_sprintf}, {"Q_strcasecmp", (byte *)Q_strcasecmp}, {"Q_strncasecmp", (byte *)Q_strncasecmp}, {"Q_stricmp", (byte *)Q_stricmp}, {"Com_PageInMemory", (byte *)Com_PageInMemory}, {"COM_Parse", (byte *)COM_Parse}, {"va", (byte *)va}, {"Swap_Init", (byte *)Swap_Init}, {"FloatNoSwap", (byte *)FloatNoSwap}, {"FloatSwap", (byte *)FloatSwap}, {"LongNoSwap", (byte *)LongNoSwap}, {"LongSwap", (byte *)LongSwap}, {"ShortNoSwap", (byte *)ShortNoSwap}, {"ShortSwap", (byte *)ShortSwap}, {"LittleFloat", (byte *)LittleFloat}, {"BigFloat", (byte *)BigFloat}, {"LittleLong", (byte *)LittleLong}, {"BigLong", (byte *)BigLong}, {"LittleShort", (byte *)LittleShort}, {"BigShort", (byte *)BigShort}, {"COM_DefaultExtension", (byte *)COM_DefaultExtension}, {"COM_FilePath", (byte *)COM_FilePath}, {"COM_FileBase", (byte *)COM_FileBase}, {"COM_FileExtension", (byte *)COM_FileExtension}, {"COM_StripExtension", (byte *)COM_StripExtension}, {"COM_SkipPath", (byte *)COM_SkipPath}, {"Q_log2", (byte *)Q_log2}, {"VectorScale", (byte *)VectorScale}, {"VectorInverse", (byte *)VectorInverse}, {"VectorLength", (byte *)VectorLength}, {"CrossProduct", (byte *)CrossProduct}, {"_VectorCopy", (byte *)_VectorCopy}, {"_VectorAdd", (byte *)_VectorAdd}, {"_VectorSubtract", (byte *)_VectorSubtract}, {"_DotProduct", (byte *)_DotProduct}, {"VectorMA", (byte *)VectorMA}, {"VectorNormalize2", (byte *)VectorNormalize2}, {"VectorNormalize", (byte *)VectorNormalize}, {"VectorCompare", (byte *)VectorCompare}, {"AddPointToBounds", (byte *)AddPointToBounds}, {"ClearBounds", (byte *)ClearBounds}, {"BoxOnPlaneSide2", (byte *)BoxOnPlaneSide2}, {"anglemod", (byte *)anglemod}, {"LerpAngle", (byte *)LerpAngle}, {"Q_fabs", (byte *)Q_fabs}, {"R_ConcatTransforms", (byte *)R_ConcatTransforms}, {"R_ConcatRotations", (byte *)R_ConcatRotations}, {"PerpendicularVector", (byte *)PerpendicularVector}, {"ProjectPointOnPlane", (byte *)ProjectPointOnPlane}, {"AngleVectors", (byte *)AngleVectors}, {"RotatePointAroundVector", (byte *)RotatePointAroundVector}, {"Weapon_Heatbeam", (byte *)Weapon_Heatbeam}, {"Heatbeam_Fire", (byte *)Heatbeam_Fire}, {"Weapon_ETF_Rifle", (byte *)Weapon_ETF_Rifle}, {"weapon_etf_rifle_fire", (byte *)weapon_etf_rifle_fire}, {"Weapon_Disintegrator", (byte *)Weapon_Disintegrator}, {"weapon_tracker_fire", (byte *)weapon_tracker_fire}, {"Weapon_ChainFist", (byte *)Weapon_ChainFist}, {"chainfist_smoke", (byte *)chainfist_smoke}, {"weapon_chainfist_fire", (byte *)weapon_chainfist_fire}, {"Weapon_BFG", (byte *)Weapon_BFG}, {"weapon_bfg_fire", (byte *)weapon_bfg_fire}, {"Weapon_Railgun", (byte *)Weapon_Railgun}, {"weapon_railgun_fire", (byte *)weapon_railgun_fire}, {"Weapon_SuperShotgun", (byte *)Weapon_SuperShotgun}, {"weapon_supershotgun_fire", (byte *)weapon_supershotgun_fire}, {"Weapon_Shotgun", (byte *)Weapon_Shotgun}, {"weapon_shotgun_fire", (byte *)weapon_shotgun_fire}, {"Weapon_Chaingun", (byte *)Weapon_Chaingun}, {"Chaingun_Fire", (byte *)Chaingun_Fire}, {"Weapon_Machinegun", (byte *)Weapon_Machinegun}, {"Machinegun_Fire", (byte *)Machinegun_Fire}, {"Weapon_HyperBlaster", (byte *)Weapon_HyperBlaster}, {"Weapon_HyperBlaster_Fire", (byte *)Weapon_HyperBlaster_Fire}, {"Weapon_Blaster", (byte *)Weapon_Blaster}, {"Weapon_Blaster_Fire", (byte *)Weapon_Blaster_Fire}, {"Blaster_Fire", (byte *)Blaster_Fire}, {"Weapon_RocketLauncher", (byte *)Weapon_RocketLauncher}, {"Weapon_RocketLauncher_Fire", (byte *)Weapon_RocketLauncher_Fire}, {"Weapon_ProxLauncher", (byte *)Weapon_ProxLauncher}, {"Weapon_GrenadeLauncher", (byte *)Weapon_GrenadeLauncher}, {"weapon_grenadelauncher_fire", (byte *)weapon_grenadelauncher_fire}, {"Weapon_Tesla", (byte *)Weapon_Tesla}, {"Weapon_Grenade", (byte *)Weapon_Grenade}, {"Throw_Generic", (byte *)Throw_Generic}, {"weapon_grenade_fire", (byte *)weapon_grenade_fire}, {"Weapon_Generic", (byte *)Weapon_Generic}, {"Drop_Weapon", (byte *)Drop_Weapon}, {"Use_Weapon", (byte *)Use_Weapon}, {"Think_Weapon", (byte *)Think_Weapon}, {"NoAmmoWeaponChange", (byte *)NoAmmoWeaponChange}, {"ChangeWeapon", (byte *)ChangeWeapon}, {"Pickup_Weapon", (byte *)Pickup_Weapon}, {"PlayerNoise", (byte *)PlayerNoise}, {"P_ProjectSource2", (byte *)P_ProjectSource2}, {"P_ProjectSource", (byte *)P_ProjectSource}, {"P_DamageModifier", (byte *)P_DamageModifier}, {"ClientEndServerFrame", (byte *)ClientEndServerFrame}, {"G_SetClientFrame", (byte *)G_SetClientFrame}, {"G_SetClientSound", (byte *)G_SetClientSound}, {"G_SetClientEvent", (byte *)G_SetClientEvent}, {"G_SetClientEffects", (byte *)G_SetClientEffects}, {"P_WorldEffects", (byte *)P_WorldEffects}, {"P_FallingDamage", (byte *)P_FallingDamage}, {"SV_CalcBlend", (byte *)SV_CalcBlend}, {"SV_AddBlend", (byte *)SV_AddBlend}, {"SV_CalcGunOffset", (byte *)SV_CalcGunOffset}, {"SV_CalcViewOffset", (byte *)SV_CalcViewOffset}, {"P_DamageFeedback", (byte *)P_DamageFeedback}, {"SV_CalcRoll", (byte *)SV_CalcRoll}, {"PlayerTrail_LastSpot", (byte *)PlayerTrail_LastSpot}, {"PlayerTrail_PickNext", (byte *)PlayerTrail_PickNext}, {"PlayerTrail_PickFirst", (byte *)PlayerTrail_PickFirst}, {"PlayerTrail_New", (byte *)PlayerTrail_New}, {"PlayerTrail_Add", (byte *)PlayerTrail_Add}, {"PlayerTrail_Init", (byte *)PlayerTrail_Init}, {"G_SetSpectatorStats", (byte *)G_SetSpectatorStats}, {"G_CheckChaseStats", (byte *)G_CheckChaseStats}, {"G_SetStats", (byte *)G_SetStats}, {"InventoryMessage", (byte *)InventoryMessage}, {"HelpComputerMessage", (byte *)HelpComputerMessage}, {"DeathmatchScoreboardMessage", (byte *)DeathmatchScoreboardMessage}, {"BeginIntermission", (byte *)BeginIntermission}, {"MoveClientToIntermission", (byte *)MoveClientToIntermission}, {"RemoveAttackingPainDaemons", (byte *)RemoveAttackingPainDaemons}, {"ClientBeginServerFrame", (byte *)ClientBeginServerFrame}, {"ClientThink", (byte *)ClientThink}, {"PrintPmove", (byte *)PrintPmove}, {"CheckBlock", (byte *)CheckBlock}, {"PM_trace", (byte *)PM_trace}, {"ClientDisconnect", (byte *)ClientDisconnect}, {"ClientConnect", (byte *)ClientConnect}, {"ClientUserinfoChanged", (byte *)ClientUserinfoChanged}, {"ClientBegin", (byte *)ClientBegin}, {"ClientBeginDeathmatch", (byte *)ClientBeginDeathmatch}, {"PutClientInServer", (byte *)PutClientInServer}, {"spectator_respawn", (byte *)spectator_respawn}, {"respawn", (byte *)respawn}, {"CopyToBodyQue", (byte *)CopyToBodyQue}, {"body_die", (byte *)body_die}, {"InitBodyQue", (byte *)InitBodyQue}, {"SelectSpawnPoint", (byte *)SelectSpawnPoint}, {"SelectCoopSpawnPoint", (byte *)SelectCoopSpawnPoint}, {"SelectLavaCoopSpawnPoint", (byte *)SelectLavaCoopSpawnPoint}, {"SelectDeathmatchSpawnPoint", (byte *)SelectDeathmatchSpawnPoint}, {"SelectFarthestDeathmatchSpawnPoint", (byte *)SelectFarthestDeathmatchSpawnPoint}, {"SelectRandomDeathmatchSpawnPoint", (byte *)SelectRandomDeathmatchSpawnPoint}, {"PlayersRangeFromSpot", (byte *)PlayersRangeFromSpot}, {"FetchClientEntData", (byte *)FetchClientEntData}, {"SaveClientData", (byte *)SaveClientData}, {"InitClientResp", (byte *)InitClientResp}, {"InitClientPersistant", (byte *)InitClientPersistant}, {"player_die", (byte *)player_die}, {"LookAtKiller", (byte *)LookAtKiller}, {"TossClientWeapon", (byte *)TossClientWeapon}, {"ClientObituary", (byte *)ClientObituary}, {"IsNeutral", (byte *)IsNeutral}, {"IsFemale", (byte *)IsFemale}, {"player_pain", (byte *)player_pain}, {"SP_info_player_intermission", (byte *)SP_info_player_intermission}, {"SP_info_player_coop_lava", (byte *)SP_info_player_coop_lava}, {"SP_info_player_coop", (byte *)SP_info_player_coop}, {"SP_info_player_deathmatch", (byte *)SP_info_player_deathmatch}, {"SP_info_player_start", (byte *)SP_info_player_start}, {"ThrowArm2", (byte *)ThrowArm2}, {"ThrowArm1", (byte *)ThrowArm1}, {"WidowExplosionLeg", (byte *)WidowExplosionLeg}, {"WidowExplosion7", (byte *)WidowExplosion7}, {"WidowExplosion6", (byte *)WidowExplosion6}, {"WidowExplosion5", (byte *)WidowExplosion5}, {"WidowExplosion4", (byte *)WidowExplosion4}, {"WidowExplosion3", (byte *)WidowExplosion3}, {"WidowExplosion2", (byte *)WidowExplosion2}, {"WidowExplosion1", (byte *)WidowExplosion1}, {"WidowExplode", (byte *)WidowExplode}, {"ThrowMoreStuff", (byte *)ThrowMoreStuff}, {"ThrowSmallStuff", (byte *)ThrowSmallStuff}, {"ThrowWidowGibReal", (byte *)ThrowWidowGibReal}, {"ThrowWidowGibSized", (byte *)ThrowWidowGibSized}, {"ThrowWidowGibLoc", (byte *)ThrowWidowGibLoc}, {"ThrowWidowGib", (byte *)ThrowWidowGib}, {"widow_gib_touch", (byte *)widow_gib_touch}, {"WidowVelocityForDamage", (byte *)WidowVelocityForDamage}, {"SP_monster_widow2", (byte *)SP_monster_widow2}, {"Widow2Precache", (byte *)Widow2Precache}, {"Widow2_CheckAttack", (byte *)Widow2_CheckAttack}, {"widow2_die", (byte *)widow2_die}, {"KillChildren", (byte *)KillChildren}, {"widow2_dead", (byte *)widow2_dead}, {"widow2_pain", (byte *)widow2_pain}, {"widow2_reattack_beam", (byte *)widow2_reattack_beam}, {"widow2_attack_beam", (byte *)widow2_attack_beam}, {"widow2_attack", (byte *)widow2_attack}, {"widow2_melee", (byte *)widow2_melee}, {"widow2_walk", (byte *)widow2_walk}, {"widow2_run", (byte *)widow2_run}, {"widow2_stand", (byte *)widow2_stand}, {"widow2_finaldeath", (byte *)widow2_finaldeath}, {"widow2_keep_searching", (byte *)widow2_keep_searching}, {"widow2_start_searching", (byte *)widow2_start_searching}, {"Widow2Toss", (byte *)Widow2Toss}, {"Widow2Crunch", (byte *)Widow2Crunch}, {"Widow2TonguePull", (byte *)Widow2TonguePull}, {"Widow2Tongue", (byte *)Widow2Tongue}, {"widow2_tongue_attack_ok", (byte *)widow2_tongue_attack_ok}, {"Widow2StartSweep", (byte *)Widow2StartSweep}, {"Widow2BeamTargetRemove", (byte *)Widow2BeamTargetRemove}, {"Widow2SaveBeamTarget", (byte *)Widow2SaveBeamTarget}, {"widow2_disrupt_reattack", (byte *)widow2_disrupt_reattack}, {"Widow2SaveDisruptLoc", (byte *)Widow2SaveDisruptLoc}, {"WidowDisrupt", (byte *)WidowDisrupt}, {"widow2_ready_spawn", (byte *)widow2_ready_spawn}, {"widow2_spawn_check", (byte *)widow2_spawn_check}, {"Widow2Spawn", (byte *)Widow2Spawn}, {"Widow2Beam", (byte *)Widow2Beam}, {"widow2_search", (byte *)widow2_search}, {"pauseme", (byte *)pauseme}, {"SP_monster_widow", (byte *)SP_monster_widow}, {"WidowPrecache", (byte *)WidowPrecache}, {"WidowCalcSlots", (byte *)WidowCalcSlots}, {"widow_blocked", (byte *)widow_blocked}, {"Widow_CheckAttack", (byte *)Widow_CheckAttack}, {"WidowPowerups", (byte *)WidowPowerups}, {"WidowRespondPowerup", (byte *)WidowRespondPowerup}, {"WidowPowerArmor", (byte *)WidowPowerArmor}, {"WidowPent", (byte *)WidowPent}, {"WidowDouble", (byte *)WidowDouble}, {"WidowGoinQuad", (byte *)WidowGoinQuad}, {"widow_melee", (byte *)widow_melee}, {"widow_die", (byte *)widow_die}, {"widow_dead", (byte *)widow_dead}, {"widow_pain", (byte *)widow_pain}, {"widow_reattack_blaster", (byte *)widow_reattack_blaster}, {"widow_attack_blaster", (byte *)widow_attack_blaster}, {"widow_attack", (byte *)widow_attack}, {"widow_walk", (byte *)widow_walk}, {"widow_run", (byte *)widow_run}, {"widow_stand", (byte *)widow_stand}, {"widow_attack_kick", (byte *)widow_attack_kick}, {"spawn_out_do", (byte *)spawn_out_do}, {"spawn_out_start", (byte *)spawn_out_start}, {"widow_done_spawn", (byte *)widow_done_spawn}, {"widow_start_spawn", (byte *)widow_start_spawn}, {"widow_attack_rail", (byte *)widow_attack_rail}, {"widow_rail_done", (byte *)widow_rail_done}, {"widow_start_rail", (byte *)widow_start_rail}, {"WidowSaveLoc", (byte *)WidowSaveLoc}, {"WidowRail", (byte *)WidowRail}, {"widow_start_run_12", (byte *)widow_start_run_12}, {"widow_start_run_10", (byte *)widow_start_run_10}, {"widow_start_run_5", (byte *)widow_start_run_5}, {"widow_stepshoot", (byte *)widow_stepshoot}, {"widow_step", (byte *)widow_step}, {"widow_ready_spawn", (byte *)widow_ready_spawn}, {"widow_spawn_check", (byte *)widow_spawn_check}, {"WidowSpawn", (byte *)WidowSpawn}, {"WidowBlaster", (byte *)WidowBlaster}, {"WidowTorso", (byte *)WidowTorso}, {"target_angle", (byte *)target_angle}, {"widow_sight", (byte *)widow_sight}, {"widow_search", (byte *)widow_search}, {"showme", (byte *)showme}, {"SP_monster_turret", (byte *)SP_monster_turret}, {"turret_checkattack", (byte *)turret_checkattack}, {"turret_activate", (byte *)turret_activate}, {"turret_wake", (byte *)turret_wake}, {"turret_wall_spawn", (byte *)turret_wall_spawn}, {"turret_die", (byte *)turret_die}, {"turret_pain", (byte *)turret_pain}, {"turret_attack", (byte *)turret_attack}, {"TurretFireBlind", (byte *)TurretFireBlind}, {"TurretFire", (byte *)TurretFire}, {"turret_run", (byte *)turret_run}, {"turret_walk", (byte *)turret_walk}, {"turret_ready_gun", (byte *)turret_ready_gun}, {"turret_stand", (byte *)turret_stand}, {"turret_search", (byte *)turret_search}, {"turret_sight", (byte *)turret_sight}, {"TurretAim", (byte *)TurretAim}, {"SP_monster_tank", (byte *)SP_monster_tank}, {"tank_die", (byte *)tank_die}, {"tank_dead", (byte *)tank_dead}, {"tank_attack", (byte *)tank_attack}, {"tank_doattack_rocket", (byte *)tank_doattack_rocket}, {"tank_refire_rocket", (byte *)tank_refire_rocket}, {"tank_poststrike", (byte *)tank_poststrike}, {"tank_reattack_blaster", (byte *)tank_reattack_blaster}, {"TankMachineGun", (byte *)TankMachineGun}, {"TankRocket", (byte *)TankRocket}, {"TankStrike", (byte *)TankStrike}, {"TankBlaster", (byte *)TankBlaster}, {"tank_pain", (byte *)tank_pain}, {"tank_run", (byte *)tank_run}, {"tank_walk", (byte *)tank_walk}, {"tank_stand", (byte *)tank_stand}, {"tank_idle", (byte *)tank_idle}, {"tank_windup", (byte *)tank_windup}, {"tank_thud", (byte *)tank_thud}, {"tank_footstep", (byte *)tank_footstep}, {"tank_sight", (byte *)tank_sight}, {"tank_blocked", (byte *)tank_blocked}, {"SP_monster_supertank", (byte *)SP_monster_supertank}, {"supertank_blocked", (byte *)supertank_blocked}, {"supertank_die", (byte *)supertank_die}, {"BossExplode", (byte *)BossExplode}, {"supertank_dead", (byte *)supertank_dead}, {"supertank_attack", (byte *)supertank_attack}, {"supertankMachineGun", (byte *)supertankMachineGun}, {"supertankRocket", (byte *)supertankRocket}, {"supertank_pain", (byte *)supertank_pain}, {"supertank_reattack1", (byte *)supertank_reattack1}, {"supertank_run", (byte *)supertank_run}, {"supertank_walk", (byte *)supertank_walk}, {"supertank_forward", (byte *)supertank_forward}, {"supertank_stand", (byte *)supertank_stand}, {"supertank_search", (byte *)supertank_search}, {"TreadSound", (byte *)TreadSound}, {"SP_monster_stalker", (byte *)SP_monster_stalker}, {"stalker_die", (byte *)stalker_die}, {"stalker_dead", (byte *)stalker_dead}, {"stalker_blocked", (byte *)stalker_blocked}, {"stalker_jump", (byte *)stalker_jump}, {"stalker_jump_wait_land", (byte *)stalker_jump_wait_land}, {"stalker_jump_up", (byte *)stalker_jump_up}, {"stalker_jump_down", (byte *)stalker_jump_down}, {"stalker_dodge", (byte *)stalker_dodge}, {"stalker_dodge_jump", (byte *)stalker_dodge_jump}, {"stalker_jump_straightup", (byte *)stalker_jump_straightup}, {"stalker_do_pounce", (byte *)stalker_do_pounce}, {"stalker_check_lz", (byte *)stalker_check_lz}, {"calcJumpAngle", (byte *)calcJumpAngle}, {"stalker_attack_melee", (byte *)stalker_attack_melee}, {"stalker_swing_attack", (byte *)stalker_swing_attack}, {"stalker_attack_ranged", (byte *)stalker_attack_ranged}, {"stalker_shoot_attack2", (byte *)stalker_shoot_attack2}, {"stalker_shoot_attack", (byte *)stalker_shoot_attack}, {"stalker_pain", (byte *)stalker_pain}, {"stalker_false_death_start", (byte *)stalker_false_death_start}, {"stalker_false_death", (byte *)stalker_false_death}, {"stalker_heal", (byte *)stalker_heal}, {"stalker_reactivate", (byte *)stalker_reactivate}, {"stalker_walk", (byte *)stalker_walk}, {"stalker_run", (byte *)stalker_run}, {"stalker_stand", (byte *)stalker_stand}, {"stalker_idle", (byte *)stalker_idle}, {"stalker_idle_noise", (byte *)stalker_idle_noise}, {"stalker_sight", (byte *)stalker_sight}, {"stalker_ok_to_transition", (byte *)stalker_ok_to_transition}, {"SP_monster_soldier_ss", (byte *)SP_monster_soldier_ss}, {"SP_monster_soldier", (byte *)SP_monster_soldier}, {"SP_monster_soldier_light", (byte *)SP_monster_soldier_light}, {"SP_monster_soldier_x", (byte *)SP_monster_soldier_x}, {"soldier_footstep", (byte *)soldier_footstep}, {"soldier_blind", (byte *)soldier_blind}, {"soldier_duck", (byte *)soldier_duck}, {"soldier_sidestep", (byte *)soldier_sidestep}, {"soldier_die", (byte *)soldier_die}, {"soldier_dead2", (byte *)soldier_dead2}, {"soldier_dead", (byte *)soldier_dead}, {"soldier_fire7", (byte *)soldier_fire7}, {"soldier_fire6", (byte *)soldier_fire6}, {"soldier_blocked", (byte *)soldier_blocked}, {"soldier_sight", (byte *)soldier_sight}, {"soldier_attack", (byte *)soldier_attack}, {"soldier_attack6_refire", (byte *)soldier_attack6_refire}, {"soldier_fire8", (byte *)soldier_fire8}, {"soldier_fire4", (byte *)soldier_fire4}, {"soldier_attack3_refire", (byte *)soldier_attack3_refire}, {"soldier_fire3", (byte *)soldier_fire3}, {"soldier_attack2_refire2", (byte *)soldier_attack2_refire2}, {"soldier_attack2_refire1", (byte *)soldier_attack2_refire1}, {"soldier_fire2", (byte *)soldier_fire2}, {"soldier_attack1_refire2", (byte *)soldier_attack1_refire2}, {"soldier_attack1_refire1", (byte *)soldier_attack1_refire1}, {"soldier_fire1", (byte *)soldier_fire1}, {"soldier_fire", (byte *)soldier_fire}, {"soldier_pain", (byte *)soldier_pain}, {"soldier_run", (byte *)soldier_run}, {"soldier_fire_run", (byte *)soldier_fire_run}, {"soldier_walk", (byte *)soldier_walk}, {"soldier_walk1_random", (byte *)soldier_walk1_random}, {"soldier_stand", (byte *)soldier_stand}, {"soldier_cock", (byte *)soldier_cock}, {"soldier_idle", (byte *)soldier_idle}, {"soldier_stop_charge", (byte *)soldier_stop_charge}, {"soldier_start_charge", (byte *)soldier_start_charge}, {"SP_monster_parasite", (byte *)SP_monster_parasite}, {"parasite_die", (byte *)parasite_die}, {"parasite_dead", (byte *)parasite_dead}, {"parasite_checkattack", (byte *)parasite_checkattack}, {"parasite_blocked", (byte *)parasite_blocked}, {"parasite_jump", (byte *)parasite_jump}, {"parasite_jump_wait_land", (byte *)parasite_jump_wait_land}, {"parasite_jump_up", (byte *)parasite_jump_up}, {"parasite_jump_down", (byte *)parasite_jump_down}, {"parasite_attack", (byte *)parasite_attack}, {"parasite_drain_attack", (byte *)parasite_drain_attack}, {"parasite_drain_attack_ok", (byte *)parasite_drain_attack_ok}, {"parasite_pain", (byte *)parasite_pain}, {"parasite_walk", (byte *)parasite_walk}, {"parasite_start_walk", (byte *)parasite_start_walk}, {"parasite_run", (byte *)parasite_run}, {"parasite_start_run", (byte *)parasite_start_run}, {"parasite_stand", (byte *)parasite_stand}, {"parasite_idle", (byte *)parasite_idle}, {"parasite_refidget", (byte *)parasite_refidget}, {"parasite_do_fidget", (byte *)parasite_do_fidget}, {"parasite_end_fidget", (byte *)parasite_end_fidget}, {"parasite_search", (byte *)parasite_search}, {"parasite_scratch", (byte *)parasite_scratch}, {"parasite_tap", (byte *)parasite_tap}, {"parasite_sight", (byte *)parasite_sight}, {"parasite_reel_in", (byte *)parasite_reel_in}, {"parasite_launch", (byte *)parasite_launch}, {"SP_monster_mutant", (byte *)SP_monster_mutant}, {"mutant_blocked", (byte *)mutant_blocked}, {"mutant_die", (byte *)mutant_die}, {"mutant_dead", (byte *)mutant_dead}, {"mutant_pain", (byte *)mutant_pain}, {"mutant_checkattack", (byte *)mutant_checkattack}, {"mutant_check_jump", (byte *)mutant_check_jump}, {"mutant_check_melee", (byte *)mutant_check_melee}, {"mutant_jump", (byte *)mutant_jump}, {"mutant_check_landing", (byte *)mutant_check_landing}, {"mutant_jump_takeoff", (byte *)mutant_jump_takeoff}, {"mutant_jump_touch", (byte *)mutant_jump_touch}, {"mutant_melee", (byte *)mutant_melee}, {"mutant_check_refire", (byte *)mutant_check_refire}, {"mutant_hit_right", (byte *)mutant_hit_right}, {"mutant_hit_left", (byte *)mutant_hit_left}, {"mutant_run", (byte *)mutant_run}, {"mutant_walk", (byte *)mutant_walk}, {"mutant_walk_loop", (byte *)mutant_walk_loop}, {"mutant_idle", (byte *)mutant_idle}, {"mutant_idle_loop", (byte *)mutant_idle_loop}, {"mutant_stand", (byte *)mutant_stand}, {"mutant_swing", (byte *)mutant_swing}, {"mutant_search", (byte *)mutant_search}, {"mutant_sight", (byte *)mutant_sight}, {"mutant_step", (byte *)mutant_step}, {"M_walkmove", (byte *)M_walkmove}, {"M_MoveToGoal", (byte *)M_MoveToGoal}, {"SV_CloseEnough", (byte *)SV_CloseEnough}, {"SV_NewChaseDir", (byte *)SV_NewChaseDir}, {"SV_FixCheckBottom", (byte *)SV_FixCheckBottom}, {"SV_StepDirection", (byte *)SV_StepDirection}, {"M_ChangeYaw", (byte *)M_ChangeYaw}, {"SV_movestep", (byte *)SV_movestep}, {"IsBadAhead", (byte *)IsBadAhead}, {"M_CheckBottom", (byte *)M_CheckBottom}, {"SP_monster_medic", (byte *)SP_monster_medic}, {"medic_blocked", (byte *)medic_blocked}, {"medic_sidestep", (byte *)medic_sidestep}, {"medic_duck", (byte *)medic_duck}, {"medic_footstep", (byte *)medic_footstep}, {"medic_checkattack", (byte *)medic_checkattack}, {"medic_attack", (byte *)medic_attack}, {"medic_finish_spawn", (byte *)medic_finish_spawn}, {"medic_spawngrows", (byte *)medic_spawngrows}, {"medic_determine_spawn", (byte *)medic_determine_spawn}, {"medic_start_spawn", (byte *)medic_start_spawn}, {"medic_hook_retract", (byte *)medic_hook_retract}, {"medic_cable_attack", (byte *)medic_cable_attack}, {"medic_hook_launch", (byte *)medic_hook_launch}, {"medic_continue", (byte *)medic_continue}, {"medic_die", (byte *)medic_die}, {"medic_dead", (byte *)medic_dead}, {"medic_fire_blaster", (byte *)medic_fire_blaster}, {"medic_pain", (byte *)medic_pain}, {"medic_run", (byte *)medic_run}, {"medic_walk", (byte *)medic_walk}, {"medic_stand", (byte *)medic_stand}, {"medic_sight", (byte *)medic_sight}, {"medic_search", (byte *)medic_search}, {"medic_idle", (byte *)medic_idle}, {"cleanupHeal", (byte *)cleanupHeal}, {"abortHeal", (byte *)abortHeal}, {"canReach", (byte *)canReach}, {"medic_FindDeadMonster", (byte *)medic_FindDeadMonster}, {"SP_misc_insane", (byte *)SP_misc_insane}, {"insane_footstep", (byte *)insane_footstep}, {"insane_die", (byte *)insane_die}, {"insane_dead", (byte *)insane_dead}, {"insane_stand", (byte *)insane_stand}, {"insane_checkup", (byte *)insane_checkup}, {"insane_checkdown", (byte *)insane_checkdown}, {"insane_onground", (byte *)insane_onground}, {"insane_pain", (byte *)insane_pain}, {"insane_run", (byte *)insane_run}, {"insane_walk", (byte *)insane_walk}, {"insane_cross", (byte *)insane_cross}, {"insane_scream", (byte *)insane_scream}, {"insane_moan", (byte *)insane_moan}, {"insane_shake", (byte *)insane_shake}, {"insane_fist", (byte *)insane_fist}, {"SP_monster_infantry", (byte *)SP_monster_infantry}, {"infantry_footstep", (byte *)infantry_footstep}, {"infantry_sidestep", (byte *)infantry_sidestep}, {"infantry_duck", (byte *)infantry_duck}, {"infantry_blocked", (byte *)infantry_blocked}, {"infantry_jump", (byte *)infantry_jump}, {"infantry_jump_wait_land", (byte *)infantry_jump_wait_land}, {"infantry_jump2_now", (byte *)infantry_jump2_now}, {"infantry_jump_now", (byte *)infantry_jump_now}, {"infantry_attack", (byte *)infantry_attack}, {"infantry_smack", (byte *)infantry_smack}, {"infantry_swing", (byte *)infantry_swing}, {"infantry_fire_prep", (byte *)infantry_fire_prep}, {"infantry_fire", (byte *)infantry_fire}, {"infantry_cock_gun", (byte *)infantry_cock_gun}, {"infantry_die", (byte *)infantry_die}, {"infantry_dead", (byte *)infantry_dead}, {"infantry_sight", (byte *)infantry_sight}, {"InfantryMachineGun", (byte *)InfantryMachineGun}, {"infantry_pain", (byte *)infantry_pain}, {"infantry_run", (byte *)infantry_run}, {"infantry_walk", (byte *)infantry_walk}, {"infantry_fidget", (byte *)infantry_fidget}, {"infantry_stand", (byte *)infantry_stand}, {"SP_monster_hover", (byte *)SP_monster_hover}, {"hover_blocked", (byte *)hover_blocked}, {"hover_die", (byte *)hover_die}, {"hover_dead", (byte *)hover_dead}, {"hover_deadthink", (byte *)hover_deadthink}, {"hover_pain", (byte *)hover_pain}, {"hover_attack", (byte *)hover_attack}, {"hover_start_attack", (byte *)hover_start_attack}, {"hover_walk", (byte *)hover_walk}, {"hover_run", (byte *)hover_run}, {"hover_stand", (byte *)hover_stand}, {"hover_fire_blaster", (byte *)hover_fire_blaster}, {"hover_reattack", (byte *)hover_reattack}, {"hover_search", (byte *)hover_search}, {"hover_sight", (byte *)hover_sight}, {"SP_monster_gunner", (byte *)SP_monster_gunner}, {"gunner_footstep", (byte *)gunner_footstep}, {"gunner_sidestep", (byte *)gunner_sidestep}, {"gunner_duck", (byte *)gunner_duck}, {"gunner_blocked", (byte *)gunner_blocked}, {"gunner_jump", (byte *)gunner_jump}, {"gunner_jump_wait_land", (byte *)gunner_jump_wait_land}, {"gunner_jump2_now", (byte *)gunner_jump2_now}, {"gunner_jump_now", (byte *)gunner_jump_now}, {"gunner_refire_chain", (byte *)gunner_refire_chain}, {"gunner_fire_chain", (byte *)gunner_fire_chain}, {"gunner_attack", (byte *)gunner_attack}, {"gunner_blind_check", (byte *)gunner_blind_check}, {"GunnerGrenade", (byte *)GunnerGrenade}, {"gunner_grenade_check", (byte *)gunner_grenade_check}, {"GunnerFire", (byte *)GunnerFire}, {"gunner_opengun", (byte *)gunner_opengun}, {"gunner_duck_down", (byte *)gunner_duck_down}, {"gunner_die", (byte *)gunner_die}, {"gunner_dead", (byte *)gunner_dead}, {"gunner_pain", (byte *)gunner_pain}, {"gunner_runandshoot", (byte *)gunner_runandshoot}, {"gunner_run", (byte *)gunner_run}, {"gunner_walk", (byte *)gunner_walk}, {"gunner_stand", (byte *)gunner_stand}, {"gunner_fidget", (byte *)gunner_fidget}, {"gunner_search", (byte *)gunner_search}, {"gunner_sight", (byte *)gunner_sight}, {"gunner_idlesound", (byte *)gunner_idlesound}, {"SP_monster_gladiator", (byte *)SP_monster_gladiator}, {"gladiator_footstep", (byte *)gladiator_footstep}, {"gladiator_blocked", (byte *)gladiator_blocked}, {"gladiator_die", (byte *)gladiator_die}, {"gladiator_dead", (byte *)gladiator_dead}, {"gladiator_pain", (byte *)gladiator_pain}, {"gladiator_attack", (byte *)gladiator_attack}, {"GladiatorGun", (byte *)GladiatorGun}, {"gladiator_melee", (byte *)gladiator_melee}, {"GaldiatorMelee", (byte *)GaldiatorMelee}, {"gladiator_run", (byte *)gladiator_run}, {"gladiator_walk", (byte *)gladiator_walk}, {"gladiator_stand", (byte *)gladiator_stand}, {"gladiator_cleaver_swing", (byte *)gladiator_cleaver_swing}, {"gladiator_search", (byte *)gladiator_search}, {"gladiator_sight", (byte *)gladiator_sight}, {"gladiator_idle", (byte *)gladiator_idle}, {"SP_monster_kamikaze", (byte *)SP_monster_kamikaze}, {"SP_monster_flyer", (byte *)SP_monster_flyer}, {"flyer_blocked", (byte *)flyer_blocked}, {"flyer_die", (byte *)flyer_die}, {"flyer_pain", (byte *)flyer_pain}, {"flyer_check_melee", (byte *)flyer_check_melee}, {"flyer_melee", (byte *)flyer_melee}, {"flyer_nextmove", (byte *)flyer_nextmove}, {"flyer_setstart", (byte *)flyer_setstart}, {"flyer_attack", (byte *)flyer_attack}, {"flyer_loop_melee", (byte *)flyer_loop_melee}, {"flyer_slash_right", (byte *)flyer_slash_right}, {"flyer_slash_left", (byte *)flyer_slash_left}, {"flyer_fireright", (byte *)flyer_fireright}, {"flyer_fireleft", (byte *)flyer_fireleft}, {"flyer_fire", (byte *)flyer_fire}, {"flyer_start", (byte *)flyer_start}, {"flyer_stop", (byte *)flyer_stop}, {"flyer_kamikaze_check", (byte *)flyer_kamikaze_check}, {"flyer_kamikaze", (byte *)flyer_kamikaze}, {"flyer_kamikaze_explode", (byte *)flyer_kamikaze_explode}, {"flyer_stand", (byte *)flyer_stand}, {"flyer_walk", (byte *)flyer_walk}, {"flyer_run", (byte *)flyer_run}, {"flyer_pop_blades", (byte *)flyer_pop_blades}, {"flyer_idle", (byte *)flyer_idle}, {"flyer_sight", (byte *)flyer_sight}, {"SP_monster_floater", (byte *)SP_monster_floater}, {"floater_blocked", (byte *)floater_blocked}, {"floater_die", (byte *)floater_die}, {"floater_dead", (byte *)floater_dead}, {"floater_pain", (byte *)floater_pain}, {"floater_melee", (byte *)floater_melee}, {"floater_attack", (byte *)floater_attack}, {"floater_zap", (byte *)floater_zap}, {"floater_wham", (byte *)floater_wham}, {"floater_walk", (byte *)floater_walk}, {"floater_run", (byte *)floater_run}, {"floater_stand", (byte *)floater_stand}, {"floater_fire_blaster", (byte *)floater_fire_blaster}, {"floater_idle", (byte *)floater_idle}, {"floater_sight", (byte *)floater_sight}, {"SP_monster_flipper", (byte *)SP_monster_flipper}, {"flipper_die", (byte *)flipper_die}, {"flipper_sight", (byte *)flipper_sight}, {"flipper_dead", (byte *)flipper_dead}, {"flipper_pain", (byte *)flipper_pain}, {"flipper_melee", (byte *)flipper_melee}, {"flipper_preattack", (byte *)flipper_preattack}, {"flipper_bite", (byte *)flipper_bite}, {"flipper_start_run", (byte *)flipper_start_run}, {"flipper_walk", (byte *)flipper_walk}, {"flipper_run", (byte *)flipper_run}, {"flipper_run_loop", (byte *)flipper_run_loop}, {"flipper_stand", (byte *)flipper_stand}, {"SP_monster_chick", (byte *)SP_monster_chick}, {"chick_footstep", (byte *)chick_footstep}, {"chick_sidestep", (byte *)chick_sidestep}, {"chick_duck", (byte *)chick_duck}, {"chick_blocked", (byte *)chick_blocked}, {"chick_sight", (byte *)chick_sight}, {"chick_attack", (byte *)chick_attack}, {"chick_melee", (byte *)chick_melee}, {"chick_slash", (byte *)chick_slash}, {"chick_reslash", (byte *)chick_reslash}, {"chick_attack1", (byte *)chick_attack1}, {"chick_rerocket", (byte *)chick_rerocket}, {"ChickReload", (byte *)ChickReload}, {"Chick_PreAttack1", (byte *)Chick_PreAttack1}, {"ChickRocket", (byte *)ChickRocket}, {"ChickSlash", (byte *)ChickSlash}, {"chick_die", (byte *)chick_die}, {"chick_dead", (byte *)chick_dead}, {"chick_pain", (byte *)chick_pain}, {"chick_run", (byte *)chick_run}, {"chick_walk", (byte *)chick_walk}, {"chick_stand", (byte *)chick_stand}, {"chick_fidget", (byte *)chick_fidget}, {"ChickMoan", (byte *)ChickMoan}, {"SP_monster_carrier", (byte *)SP_monster_carrier}, {"CarrierPrecache", (byte *)CarrierPrecache}, {"Carrier_CheckAttack", (byte *)Carrier_CheckAttack}, {"carrier_die", (byte *)carrier_die}, {"carrier_dead", (byte *)carrier_dead}, {"carrier_pain", (byte *)carrier_pain}, {"carrier_reattack_gren", (byte *)carrier_reattack_gren}, {"carrier_attack_gren", (byte *)carrier_attack_gren}, {"carrier_reattack_mg", (byte *)carrier_reattack_mg}, {"carrier_attack_mg", (byte *)carrier_attack_mg}, {"carrier_attack", (byte *)carrier_attack}, {"CarrierMachineGunHold", (byte *)CarrierMachineGunHold}, {"carrier_walk", (byte *)carrier_walk}, {"carrier_run", (byte *)carrier_run}, {"carrier_stand", (byte *)carrier_stand}, {"CarrierSaveLoc", (byte *)CarrierSaveLoc}, {"CarrierRail", (byte *)CarrierRail}, {"carrier_start_spawn", (byte *)carrier_start_spawn}, {"carrier_ready_spawn", (byte *)carrier_ready_spawn}, {"carrier_spawn_check", (byte *)carrier_spawn_check}, {"carrier_prep_spawn", (byte *)carrier_prep_spawn}, {"CarrierSpawn", (byte *)CarrierSpawn}, {"CarrierMachineGun", (byte *)CarrierMachineGun}, {"carrier_firebullet_left", (byte *)carrier_firebullet_left}, {"carrier_firebullet_right", (byte *)carrier_firebullet_right}, {"CarrierRocket", (byte *)CarrierRocket}, {"CarrierPredictiveRocket", (byte *)CarrierPredictiveRocket}, {"CarrierGrenade", (byte *)CarrierGrenade}, {"CarrierCoopCheck", (byte *)CarrierCoopCheck}, {"carrier_sight", (byte *)carrier_sight}, {"SP_monster_brain", (byte *)SP_monster_brain}, {"brain_footstep", (byte *)brain_footstep}, {"brain_duck", (byte *)brain_duck}, {"brain_die", (byte *)brain_die}, {"brain_dead", (byte *)brain_dead}, {"brain_pain", (byte *)brain_pain}, {"brain_run", (byte *)brain_run}, {"brain_melee", (byte *)brain_melee}, {"brain_chest_closed", (byte *)brain_chest_closed}, {"brain_tentacle_attack", (byte *)brain_tentacle_attack}, {"brain_chest_open", (byte *)brain_chest_open}, {"brain_hit_left", (byte *)brain_hit_left}, {"brain_swing_left", (byte *)brain_swing_left}, {"brain_hit_right", (byte *)brain_hit_right}, {"brain_swing_right", (byte *)brain_swing_right}, {"brain_walk", (byte *)brain_walk}, {"brain_idle", (byte *)brain_idle}, {"brain_stand", (byte *)brain_stand}, {"brain_search", (byte *)brain_search}, {"brain_sight", (byte *)brain_sight}, {"MakronToss", (byte *)MakronToss}, {"MakronSpawn", (byte *)MakronSpawn}, {"SP_monster_makron", (byte *)SP_monster_makron}, {"MakronPrecache", (byte *)MakronPrecache}, {"Makron_CheckAttack", (byte *)Makron_CheckAttack}, {"makron_die", (byte *)makron_die}, {"makron_torso_die", (byte *)makron_torso_die}, {"makron_dead", (byte *)makron_dead}, {"makron_torso", (byte *)makron_torso}, {"makron_torso_think", (byte *)makron_torso_think}, {"makron_attack", (byte *)makron_attack}, {"makron_sight", (byte *)makron_sight}, {"makron_pain", (byte *)makron_pain}, {"MakronHyperblaster", (byte *)MakronHyperblaster}, {"MakronRailgun", (byte *)MakronRailgun}, {"MakronSaveloc", (byte *)MakronSaveloc}, {"makronBFG", (byte *)makronBFG}, {"makron_run", (byte *)makron_run}, {"makron_walk", (byte *)makron_walk}, {"makron_prerailgun", (byte *)makron_prerailgun}, {"makron_brainsplorch", (byte *)makron_brainsplorch}, {"makron_step_right", (byte *)makron_step_right}, {"makron_step_left", (byte *)makron_step_left}, {"makron_popup", (byte *)makron_popup}, {"makron_hit", (byte *)makron_hit}, {"makron_stand", (byte *)makron_stand}, {"makron_taunt", (byte *)makron_taunt}, {"SP_monster_jorg", (byte *)SP_monster_jorg}, {"Jorg_CheckAttack", (byte *)Jorg_CheckAttack}, {"jorg_die", (byte *)jorg_die}, {"jorg_dead", (byte *)jorg_dead}, {"jorg_attack", (byte *)jorg_attack}, {"jorg_firebullet", (byte *)jorg_firebullet}, {"jorg_firebullet_left", (byte *)jorg_firebullet_left}, {"jorg_firebullet_right", (byte *)jorg_firebullet_right}, {"jorgBFG", (byte *)jorgBFG}, {"jorg_pain", (byte *)jorg_pain}, {"jorg_attack1", (byte *)jorg_attack1}, {"jorg_reattack1", (byte *)jorg_reattack1}, {"jorg_run", (byte *)jorg_run}, {"jorg_walk", (byte *)jorg_walk}, {"jorg_stand", (byte *)jorg_stand}, {"jorg_step_right", (byte *)jorg_step_right}, {"jorg_step_left", (byte *)jorg_step_left}, {"jorg_death_hit", (byte *)jorg_death_hit}, {"jorg_idle", (byte *)jorg_idle}, {"jorg_search", (byte *)jorg_search}, {"SP_monster_boss3_stand", (byte *)SP_monster_boss3_stand}, {"Think_Boss3Stand", (byte *)Think_Boss3Stand}, {"Use_Boss3", (byte *)Use_Boss3}, {"SP_monster_boss2", (byte *)SP_monster_boss2}, {"Boss2_CheckAttack", (byte *)Boss2_CheckAttack}, {"boss2_die", (byte *)boss2_die}, {"boss2_dead", (byte *)boss2_dead}, {"boss2_pain", (byte *)boss2_pain}, {"boss2_reattack_mg", (byte *)boss2_reattack_mg}, {"boss2_attack_mg", (byte *)boss2_attack_mg}, {"boss2_attack", (byte *)boss2_attack}, {"boss2_walk", (byte *)boss2_walk}, {"boss2_run", (byte *)boss2_run}, {"boss2_stand", (byte *)boss2_stand}, {"Boss2MachineGun", (byte *)Boss2MachineGun}, {"boss2_firebullet_left", (byte *)boss2_firebullet_left}, {"boss2_firebullet_right", (byte *)boss2_firebullet_right}, {"Boss2Rocket", (byte *)Boss2Rocket}, {"boss2_search", (byte *)boss2_search}, {"SP_monster_berserk", (byte *)SP_monster_berserk}, {"berserk_footstep", (byte *)berserk_footstep}, {"berserk_sidestep", (byte *)berserk_sidestep}, {"berserk_blocked", (byte *)berserk_blocked}, {"berserk_die", (byte *)berserk_die}, {"berserk_dead", (byte *)berserk_dead}, {"berserk_pain", (byte *)berserk_pain}, {"berserk_melee", (byte *)berserk_melee}, {"berserk_strike", (byte *)berserk_strike}, {"berserk_attack_club", (byte *)berserk_attack_club}, {"berserk_swing", (byte *)berserk_swing}, {"berserk_attack_spike", (byte *)berserk_attack_spike}, {"berserk_run", (byte *)berserk_run}, {"berserk_walk", (byte *)berserk_walk}, {"berserk_fidget", (byte *)berserk_fidget}, {"berserk_stand", (byte *)berserk_stand}, {"berserk_search", (byte *)berserk_search}, {"berserk_sight", (byte *)berserk_sight}, {"fire_bfg", (byte *)fire_bfg}, {"bfg_think", (byte *)bfg_think}, {"bfg_touch", (byte *)bfg_touch}, {"bfg_explode", (byte *)bfg_explode}, {"fire_rail", (byte *)fire_rail}, {"fire_rocket", (byte *)fire_rocket}, {"rocket_touch", (byte *)rocket_touch}, {"fire_grenade2", (byte *)fire_grenade2}, {"fire_grenade", (byte *)fire_grenade}, {"Grenade_Touch", (byte *)Grenade_Touch}, {"Grenade_Explode", (byte *)Grenade_Explode}, {"fire_blaster", (byte *)fire_blaster}, {"blaster_touch", (byte *)blaster_touch}, {"fire_shotgun", (byte *)fire_shotgun}, {"fire_bullet", (byte *)fire_bullet}, {"fire_lead", (byte *)fire_lead}, {"fire_hit", (byte *)fire_hit}, {"check_dodge", (byte *)check_dodge}, {"KillBox", (byte *)KillBox}, {"G_TouchSolids", (byte *)G_TouchSolids}, {"G_TouchTriggers", (byte *)G_TouchTriggers}, {"G_FreeEdict", (byte *)G_FreeEdict}, {"G_Spawn", (byte *)G_Spawn}, {"G_InitEdict", (byte *)G_InitEdict}, {"G_CopyString", (byte *)G_CopyString}, {"vectoangles2", (byte *)vectoangles2}, {"vectoangles", (byte *)vectoangles}, {"vectoyaw2", (byte *)vectoyaw2}, {"vectoyaw", (byte *)vectoyaw}, {"G_SetMovedir", (byte *)G_SetMovedir}, {"vtos", (byte *)vtos}, {"tv", (byte *)tv}, {"G_UseTargets", (byte *)G_UseTargets}, {"Think_Delay", (byte *)Think_Delay}, {"G_PickTarget", (byte *)G_PickTarget}, {"findradius2", (byte *)findradius2}, {"findradius", (byte *)findradius}, {"G_Find", (byte *)G_Find}, {"G_ProjectSource2", (byte *)G_ProjectSource2}, {"G_ProjectSource", (byte *)G_ProjectSource}, {"SP_turret_invisible_brain", (byte *)SP_turret_invisible_brain}, {"turret_brain_activate", (byte *)turret_brain_activate}, {"turret_brain_deactivate", (byte *)turret_brain_deactivate}, {"turret_brain_link", (byte *)turret_brain_link}, {"turret_brain_think", (byte *)turret_brain_think}, {"SP_turret_driver", (byte *)SP_turret_driver}, {"turret_driver_link", (byte *)turret_driver_link}, {"turret_driver_think", (byte *)turret_driver_think}, {"turret_driver_die", (byte *)turret_driver_die}, {"SP_turret_base", (byte *)SP_turret_base}, {"SP_turret_breach", (byte *)SP_turret_breach}, {"turret_breach_finish_init", (byte *)turret_breach_finish_init}, {"turret_breach_think", (byte *)turret_breach_think}, {"turret_breach_fire", (byte *)turret_breach_fire}, {"turret_blocked", (byte *)turret_blocked}, {"SnapToEights", (byte *)SnapToEights}, {"AnglesNormalize", (byte *)AnglesNormalize}, {"SP_trigger_monsterjump", (byte *)SP_trigger_monsterjump}, {"trigger_monsterjump_touch", (byte *)trigger_monsterjump_touch}, {"SP_trigger_gravity", (byte *)SP_trigger_gravity}, {"trigger_gravity_touch", (byte *)trigger_gravity_touch}, {"trigger_gravity_use", (byte *)trigger_gravity_use}, {"SP_trigger_hurt", (byte *)SP_trigger_hurt}, {"hurt_touch", (byte *)hurt_touch}, {"hurt_use", (byte *)hurt_use}, {"SP_trigger_push", (byte *)SP_trigger_push}, {"trigger_push_use", (byte *)trigger_push_use}, {"trigger_push_touch", (byte *)trigger_push_touch}, {"SP_trigger_always", (byte *)SP_trigger_always}, {"SP_trigger_counter", (byte *)SP_trigger_counter}, {"trigger_counter_use", (byte *)trigger_counter_use}, {"SP_trigger_key", (byte *)SP_trigger_key}, {"trigger_key_use", (byte *)trigger_key_use}, {"SP_trigger_relay", (byte *)SP_trigger_relay}, {"trigger_relay_use", (byte *)trigger_relay_use}, {"SP_trigger_once", (byte *)SP_trigger_once}, {"SP_trigger_multiple", (byte *)SP_trigger_multiple}, {"trigger_enable", (byte *)trigger_enable}, {"Touch_Multi", (byte *)Touch_Multi}, {"Use_Multi", (byte *)Use_Multi}, {"multi_trigger", (byte *)multi_trigger}, {"multi_wait", (byte *)multi_wait}, {"InitTrigger", (byte *)InitTrigger}, {"SP_target_earthquake", (byte *)SP_target_earthquake}, {"target_earthquake_use", (byte *)target_earthquake_use}, {"target_earthquake_think", (byte *)target_earthquake_think}, {"SP_target_lightramp", (byte *)SP_target_lightramp}, {"target_lightramp_use", (byte *)target_lightramp_use}, {"target_lightramp_think", (byte *)target_lightramp_think}, {"SP_target_laser", (byte *)SP_target_laser}, {"target_laser_start", (byte *)target_laser_start}, {"target_laser_use", (byte *)target_laser_use}, {"target_laser_off", (byte *)target_laser_off}, {"target_laser_on", (byte *)target_laser_on}, {"target_laser_think", (byte *)target_laser_think}, {"SP_target_crosslevel_target", (byte *)SP_target_crosslevel_target}, {"target_crosslevel_target_think", (byte *)target_crosslevel_target_think}, {"SP_target_crosslevel_trigger", (byte *)SP_target_crosslevel_trigger}, {"trigger_crosslevel_trigger_use", (byte *)trigger_crosslevel_trigger_use}, {"SP_target_blaster", (byte *)SP_target_blaster}, {"use_target_blaster", (byte *)use_target_blaster}, {"SP_target_spawner", (byte *)SP_target_spawner}, {"use_target_spawner", (byte *)use_target_spawner}, {"SP_target_splash", (byte *)SP_target_splash}, {"use_target_splash", (byte *)use_target_splash}, {"SP_target_changelevel", (byte *)SP_target_changelevel}, {"use_target_changelevel", (byte *)use_target_changelevel}, {"SP_target_explosion", (byte *)SP_target_explosion}, {"use_target_explosion", (byte *)use_target_explosion}, {"target_explosion_explode", (byte *)target_explosion_explode}, {"SP_target_goal", (byte *)SP_target_goal}, {"use_target_goal", (byte *)use_target_goal}, {"SP_target_secret", (byte *)SP_target_secret}, {"use_target_secret", (byte *)use_target_secret}, {"SP_target_help", (byte *)SP_target_help}, {"Use_Target_Help", (byte *)Use_Target_Help}, {"Target_Help_Think", (byte *)Target_Help_Think}, {"SP_target_speaker", (byte *)SP_target_speaker}, {"Use_Target_Speaker", (byte *)Use_Target_Speaker}, {"SP_target_temp_entity", (byte *)SP_target_temp_entity}, {"Use_Target_Tent", (byte *)Use_Target_Tent}, {"ServerCommand", (byte *)ServerCommand}, {"SVCmd_WriteIP_f", (byte *)SVCmd_WriteIP_f}, {"SVCmd_ListIP_f", (byte *)SVCmd_ListIP_f}, {"SVCmd_RemoveIP_f", (byte *)SVCmd_RemoveIP_f}, {"SVCmd_AddIP_f", (byte *)SVCmd_AddIP_f}, {"SV_FilterPacket", (byte *)SV_FilterPacket}, {"Svcmd_Test_f", (byte *)Svcmd_Test_f}, {"Vengeance_Launch", (byte *)Vengeance_Launch}, {"Hunter_Launch", (byte *)Hunter_Launch}, {"Defender_Launch", (byte *)Defender_Launch}, {"Own_Sphere", (byte *)Own_Sphere}, {"Sphere_Spawn", (byte *)Sphere_Spawn}, {"vengeance_think", (byte *)vengeance_think}, {"hunter_think", (byte *)hunter_think}, {"defender_think", (byte *)defender_think}, {"vengeance_pain", (byte *)vengeance_pain}, {"defender_pain", (byte *)defender_pain}, {"hunter_pain", (byte *)hunter_pain}, {"body_gib", (byte *)body_gib}, {"defender_shoot", (byte *)defender_shoot}, {"hunter_touch", (byte *)hunter_touch}, {"vengeance_touch", (byte *)vengeance_touch}, {"sphere_touch", (byte *)sphere_touch}, {"sphere_fire", (byte *)sphere_fire}, {"sphere_chase", (byte *)sphere_chase}, {"sphere_fly", (byte *)sphere_fly}, {"sphere_if_idle_die", (byte *)sphere_if_idle_die}, {"sphere_explode", (byte *)sphere_explode}, {"sphere_think_explode", (byte *)sphere_think_explode}, {"Widowlegs_Spawn", (byte *)Widowlegs_Spawn}, {"widowlegs_think", (byte *)widowlegs_think}, {"SpawnGrow_Spawn", (byte *)SpawnGrow_Spawn}, {"spawngrow_think", (byte *)spawngrow_think}, {"DetermineBBox", (byte *)DetermineBBox}, {"CheckGroundSpawnPoint", (byte *)CheckGroundSpawnPoint}, {"CheckSpawnPoint", (byte *)CheckSpawnPoint}, {"FindSpawnPoint", (byte *)FindSpawnPoint}, {"CreateGroundMonster", (byte *)CreateGroundMonster}, {"CreateFlyMonster", (byte *)CreateFlyMonster}, {"CreateMonster", (byte *)CreateMonster}, {"SP_worldspawn", (byte *)SP_worldspawn}, {"SpawnEntities", (byte *)SpawnEntities}, {"G_FindTeams", (byte *)G_FindTeams}, {"G_FixTeams", (byte *)G_FixTeams}, {"ED_ParseEdict", (byte *)ED_ParseEdict}, {"ED_ParseField", (byte *)ED_ParseField}, {"ED_NewString", (byte *)ED_NewString}, {"ED_CallSpawn", (byte *)ED_CallSpawn}, {"SV_Physics_NewToss", (byte *)SV_Physics_NewToss}, {"G_RunEntity", (byte *)G_RunEntity}, {"SV_Physics_Step", (byte *)SV_Physics_Step}, {"SV_AddRotationalFriction", (byte *)SV_AddRotationalFriction}, {"SV_Physics_Toss", (byte *)SV_Physics_Toss}, {"SV_Physics_Noclip", (byte *)SV_Physics_Noclip}, {"SV_Physics_None", (byte *)SV_Physics_None}, {"SV_Physics_Pusher", (byte *)SV_Physics_Pusher}, {"SV_Push", (byte *)SV_Push}, {"SV_PushEntity", (byte *)SV_PushEntity}, {"RealBoundingBox", (byte *)RealBoundingBox}, {"SV_AddGravity", (byte *)SV_AddGravity}, {"SV_FlyMove", (byte *)SV_FlyMove}, {"ClipVelocity", (byte *)ClipVelocity}, {"SV_Impact", (byte *)SV_Impact}, {"SV_RunThink", (byte *)SV_RunThink}, {"SV_CheckVelocity", (byte *)SV_CheckVelocity}, {"SV_TestEntityPosition", (byte *)SV_TestEntityPosition}, {"fire_tracker", (byte *)fire_tracker}, {"tracker_fly", (byte *)tracker_fly}, {"tracker_touch", (byte *)tracker_touch}, {"tracker_explode", (byte *)tracker_explode}, {"tracker_pain_daemon_spawn", (byte *)tracker_pain_daemon_spawn}, {"tracker_pain_daemon_think", (byte *)tracker_pain_daemon_think}, {"fire_blaster2", (byte *)fire_blaster2}, {"blaster2_touch", (byte *)blaster2_touch}, {"fire_heat", (byte *)fire_heat}, {"fire_beams", (byte *)fire_beams}, {"fire_tesla", (byte *)fire_tesla}, {"tesla_lava", (byte *)tesla_lava}, {"tesla_think", (byte *)tesla_think}, {"tesla_activate", (byte *)tesla_activate}, {"tesla_think_active", (byte *)tesla_think_active}, {"tesla_zap", (byte *)tesla_zap}, {"tesla_blow", (byte *)tesla_blow}, {"tesla_die", (byte *)tesla_die}, {"tesla_remove", (byte *)tesla_remove}, {"fire_nuke", (byte *)fire_nuke}, {"nuke_bounce", (byte *)nuke_bounce}, {"Nuke_Think", (byte *)Nuke_Think}, {"nuke_die", (byte *)nuke_die}, {"Nuke_Explode", (byte *)Nuke_Explode}, {"Nuke_Quake", (byte *)Nuke_Quake}, {"fire_player_melee", (byte *)fire_player_melee}, {"fire_prox", (byte *)fire_prox}, {"prox_land", (byte *)prox_land}, {"prox_open", (byte *)prox_open}, {"prox_seek", (byte *)prox_seek}, {"Prox_Field_Touch", (byte *)Prox_Field_Touch}, {"prox_die", (byte *)prox_die}, {"Prox_Explode", (byte *)Prox_Explode}, {"fire_flechette", (byte *)fire_flechette}, {"flechette_touch", (byte *)flechette_touch}, {"SP_trigger_disguise", (byte *)SP_trigger_disguise}, {"trigger_disguise_use", (byte *)trigger_disguise_use}, {"trigger_disguise_touch", (byte *)trigger_disguise_touch}, {"SP_trigger_teleport", (byte *)SP_trigger_teleport}, {"trigger_teleport_use", (byte *)trigger_teleport_use}, {"trigger_teleport_touch", (byte *)trigger_teleport_touch}, {"SP_info_teleport_destination", (byte *)SP_info_teleport_destination}, {"SP_target_orb", (byte *)SP_target_orb}, {"orb_think", (byte *)orb_think}, {"SP_target_blacklight", (byte *)SP_target_blacklight}, {"blacklight_think", (byte *)blacklight_think}, {"SP_target_killplayers", (byte *)SP_target_killplayers}, {"target_killplayers_use", (byte *)target_killplayers_use}, {"SP_target_anger", (byte *)SP_target_anger}, {"target_anger_use", (byte *)target_anger_use}, {"SP_target_steam", (byte *)SP_target_steam}, {"target_steam_start", (byte *)target_steam_start}, {"use_target_steam", (byte *)use_target_steam}, {"SP_func_force_wall", (byte *)SP_func_force_wall}, {"force_wall_use", (byte *)force_wall_use}, {"force_wall_think", (byte *)force_wall_think}, {"SP_func_door_secret2", (byte *)SP_func_door_secret2}, {"secret_touch", (byte *)secret_touch}, {"secret_blocked", (byte *)secret_blocked}, {"fd_secret_done", (byte *)fd_secret_done}, {"fd_secret_move6", (byte *)fd_secret_move6}, {"fd_secret_move5", (byte *)fd_secret_move5}, {"fd_secret_move4", (byte *)fd_secret_move4}, {"fd_secret_move3", (byte *)fd_secret_move3}, {"fd_secret_move2", (byte *)fd_secret_move2}, {"fd_secret_move1", (byte *)fd_secret_move1}, {"fd_secret_killed", (byte *)fd_secret_killed}, {"fd_secret_use", (byte *)fd_secret_use}, {"fire_doppleganger", (byte *)fire_doppleganger}, {"body_think", (byte *)body_think}, {"doppleganger_timeout", (byte *)doppleganger_timeout}, {"doppleganger_pain", (byte *)doppleganger_pain}, {"doppleganger_die", (byte *)doppleganger_die}, {"PrecacheForRandomRespawn", (byte *)PrecacheForRandomRespawn}, {"DoRandomRespawn", (byte *)DoRandomRespawn}, {"FindSubstituteItem", (byte *)FindSubstituteItem}, {"InitGameRules", (byte *)InitGameRules}, {"monster_jump_finished", (byte *)monster_jump_finished}, {"monster_jump_start", (byte *)monster_jump_start}, {"CountPlayers", (byte *)CountPlayers}, {"PickCoopTarget", (byte *)PickCoopTarget}, {"TargetTesla", (byte *)TargetTesla}, {"has_valid_enemy", (byte *)has_valid_enemy}, {"monster_duck_up", (byte *)monster_duck_up}, {"monster_duck_hold", (byte *)monster_duck_hold}, {"monster_duck_down", (byte *)monster_duck_down}, {"M_MonsterDodge", (byte *)M_MonsterDodge}, {"drawbbox", (byte *)drawbbox}, {"below", (byte *)below}, {"PredictAim", (byte *)PredictAim}, {"MarkTeslaArea", (byte *)MarkTeslaArea}, {"CheckForBadArea", (byte *)CheckForBadArea}, {"SpawnBadArea", (byte *)SpawnBadArea}, {"badarea_touch", (byte *)badarea_touch}, {"face_wall", (byte *)face_wall}, {"realrange", (byte *)realrange}, {"inback", (byte *)inback}, {"InitHintPaths", (byte *)InitHintPaths}, {"SP_hint_path", (byte *)SP_hint_path}, {"hint_path_touch", (byte *)hint_path_touch}, {"monsterlost_checkhint", (byte *)monsterlost_checkhint}, {"hintpath_stop", (byte *)hintpath_stop}, {"hintpath_go", (byte *)hintpath_go}, {"hintpath_other_end", (byte *)hintpath_other_end}, {"hintpath_findstart", (byte *)hintpath_findstart}, {"blocked_checknewenemy", (byte *)blocked_checknewenemy}, {"blocked_checkjump", (byte *)blocked_checkjump}, {"blocked_checkplat", (byte *)blocked_checkplat}, {"monster_done_dodge", (byte *)monster_done_dodge}, {"stationarymonster_start", (byte *)stationarymonster_start}, {"stationarymonster_start_go", (byte *)stationarymonster_start_go}, {"stationarymonster_triggered_start", (byte *)stationarymonster_triggered_start}, {"stationarymonster_triggered_spawn_use", (byte *)stationarymonster_triggered_spawn_use}, {"stationarymonster_triggered_spawn", (byte *)stationarymonster_triggered_spawn}, {"swimmonster_start", (byte *)swimmonster_start}, {"swimmonster_start_go", (byte *)swimmonster_start_go}, {"flymonster_start", (byte *)flymonster_start}, {"flymonster_start_go", (byte *)flymonster_start_go}, {"walkmonster_start", (byte *)walkmonster_start}, {"walkmonster_start_go", (byte *)walkmonster_start_go}, {"monster_start_go", (byte *)monster_start_go}, {"monster_start", (byte *)monster_start}, {"monster_death_use", (byte *)monster_death_use}, {"monster_triggered_start", (byte *)monster_triggered_start}, {"monster_triggered_spawn_use", (byte *)monster_triggered_spawn_use}, {"monster_triggered_spawn", (byte *)monster_triggered_spawn}, {"monster_use", (byte *)monster_use}, {"monster_think", (byte *)monster_think}, {"M_MoveFrame", (byte *)M_MoveFrame}, {"M_SetEffects", (byte *)M_SetEffects}, {"M_droptofloor", (byte *)M_droptofloor}, {"M_WorldEffects", (byte *)M_WorldEffects}, {"M_CatagorizePosition", (byte *)M_CatagorizePosition}, {"M_CheckGround", (byte *)M_CheckGround}, {"AttackFinished", (byte *)AttackFinished}, {"M_FlyCheck", (byte *)M_FlyCheck}, {"M_FliesOn", (byte *)M_FliesOn}, {"M_FliesOff", (byte *)M_FliesOff}, {"monster_fire_bfg", (byte *)monster_fire_bfg}, {"monster_fire_railgun", (byte *)monster_fire_railgun}, {"monster_fire_rocket", (byte *)monster_fire_rocket}, {"monster_fire_grenade", (byte *)monster_fire_grenade}, {"monster_fire_heat", (byte *)monster_fire_heat}, {"monster_fire_tracker", (byte *)monster_fire_tracker}, {"monster_fire_blaster2", (byte *)monster_fire_blaster2}, {"monster_fire_blaster", (byte *)monster_fire_blaster}, {"monster_fire_shotgun", (byte *)monster_fire_shotgun}, {"monster_fire_bullet", (byte *)monster_fire_bullet}, {"SP_misc_nuke_core", (byte *)SP_misc_nuke_core}, {"misc_nuke_core_use", (byte *)misc_nuke_core_use}, {"SP_misc_teleporter_dest", (byte *)SP_misc_teleporter_dest}, {"SP_misc_teleporter", (byte *)SP_misc_teleporter}, {"teleporter_touch", (byte *)teleporter_touch}, {"SP_func_clock", (byte *)SP_func_clock}, {"func_clock_use", (byte *)func_clock_use}, {"func_clock_think", (byte *)func_clock_think}, {"func_clock_format_countdown", (byte *)func_clock_format_countdown}, {"func_clock_reset", (byte *)func_clock_reset}, {"SP_target_string", (byte *)SP_target_string}, {"target_string_use", (byte *)target_string_use}, {"SP_target_character", (byte *)SP_target_character}, {"SP_misc_gib_head", (byte *)SP_misc_gib_head}, {"SP_misc_gib_leg", (byte *)SP_misc_gib_leg}, {"SP_misc_gib_arm", (byte *)SP_misc_gib_arm}, {"SP_light_mine2", (byte *)SP_light_mine2}, {"SP_light_mine1", (byte *)SP_light_mine1}, {"SP_misc_satellite_dish", (byte *)SP_misc_satellite_dish}, {"misc_satellite_dish_use", (byte *)misc_satellite_dish_use}, {"misc_satellite_dish_think", (byte *)misc_satellite_dish_think}, {"SP_misc_strogg_ship", (byte *)SP_misc_strogg_ship}, {"misc_strogg_ship_use", (byte *)misc_strogg_ship_use}, {"SP_misc_viper_bomb", (byte *)SP_misc_viper_bomb}, {"misc_viper_bomb_use", (byte *)misc_viper_bomb_use}, {"misc_viper_bomb_prethink", (byte *)misc_viper_bomb_prethink}, {"misc_viper_bomb_touch", (byte *)misc_viper_bomb_touch}, {"SP_misc_bigviper", (byte *)SP_misc_bigviper}, {"SP_misc_viper", (byte *)SP_misc_viper}, {"misc_viper_use", (byte *)misc_viper_use}, {"SP_misc_deadsoldier", (byte *)SP_misc_deadsoldier}, {"misc_deadsoldier_die", (byte *)misc_deadsoldier_die}, {"SP_misc_banner", (byte *)SP_misc_banner}, {"misc_banner_think", (byte *)misc_banner_think}, {"SP_monster_commander_body", (byte *)SP_monster_commander_body}, {"commander_body_drop", (byte *)commander_body_drop}, {"commander_body_use", (byte *)commander_body_use}, {"commander_body_think", (byte *)commander_body_think}, {"SP_misc_easterchick2", (byte *)SP_misc_easterchick2}, {"misc_easterchick2_think", (byte *)misc_easterchick2_think}, {"SP_misc_easterchick", (byte *)SP_misc_easterchick}, {"misc_easterchick_think", (byte *)misc_easterchick_think}, {"SP_misc_eastertank", (byte *)SP_misc_eastertank}, {"misc_eastertank_think", (byte *)misc_eastertank_think}, {"SP_misc_blackhole", (byte *)SP_misc_blackhole}, {"misc_blackhole_think", (byte *)misc_blackhole_think}, {"misc_blackhole_use", (byte *)misc_blackhole_use}, {"SP_misc_explobox", (byte *)SP_misc_explobox}, {"barrel_start", (byte *)barrel_start}, {"barrel_think", (byte *)barrel_think}, {"barrel_delay", (byte *)barrel_delay}, {"barrel_explode", (byte *)barrel_explode}, {"barrel_touch", (byte *)barrel_touch}, {"SP_func_explosive", (byte *)SP_func_explosive}, {"func_explosive_spawn", (byte *)func_explosive_spawn}, {"func_explosive_activate", (byte *)func_explosive_activate}, {"func_explosive_use", (byte *)func_explosive_use}, {"func_explosive_explode", (byte *)func_explosive_explode}, {"SP_func_object", (byte *)SP_func_object}, {"func_object_use", (byte *)func_object_use}, {"func_object_release", (byte *)func_object_release}, {"func_object_touch", (byte *)func_object_touch}, {"SP_func_wall", (byte *)SP_func_wall}, {"func_wall_use", (byte *)func_wall_use}, {"SP_light", (byte *)SP_light}, {"light_use", (byte *)light_use}, {"SP_info_notnull", (byte *)SP_info_notnull}, {"SP_info_null", (byte *)SP_info_null}, {"SP_viewthing", (byte *)SP_viewthing}, {"TH_viewthing", (byte *)TH_viewthing}, {"SP_point_combat", (byte *)SP_point_combat}, {"point_combat_touch", (byte *)point_combat_touch}, {"SP_path_corner", (byte *)SP_path_corner}, {"path_corner_touch", (byte *)path_corner_touch}, {"BecomeExplosion2", (byte *)BecomeExplosion2}, {"BecomeExplosion1", (byte *)BecomeExplosion1}, {"ThrowDebris", (byte *)ThrowDebris}, {"debris_die", (byte *)debris_die}, {"ThrowClientHead", (byte *)ThrowClientHead}, {"ThrowHead", (byte *)ThrowHead}, {"ThrowGib", (byte *)ThrowGib}, {"gib_die", (byte *)gib_die}, {"gib_touch", (byte *)gib_touch}, {"gib_think", (byte *)gib_think}, {"ClipGibVelocity", (byte *)ClipGibVelocity}, {"VelocityForDamage", (byte *)VelocityForDamage}, {"SP_func_areaportal", (byte *)SP_func_areaportal}, {"Use_Areaportal", (byte *)Use_Areaportal}, {"G_RunFrame", (byte *)G_RunFrame}, {"ExitLevel", (byte *)ExitLevel}, {"CheckDMRules", (byte *)CheckDMRules}, {"CheckNeedPass", (byte *)CheckNeedPass}, {"EndDMLevel", (byte *)EndDMLevel}, {"CreateTargetChangeLevel", (byte *)CreateTargetChangeLevel}, {"ClientEndServerFrames", (byte *)ClientEndServerFrames}, {"Com_Printf", (byte *)Com_Printf}, {"Sys_Error", (byte *)Sys_Error}, {"GetGameAPI", (byte *)GetGameAPI}, {"ShutdownGame", (byte *)ShutdownGame}, {"SP_xatrix_item", (byte *)SP_xatrix_item}, {"SetItemNames", (byte *)SetItemNames}, {"InitItems", (byte *)InitItems}, {"SP_item_health_mega", (byte *)SP_item_health_mega}, {"SP_item_health_large", (byte *)SP_item_health_large}, {"SP_item_health_small", (byte *)SP_item_health_small}, {"SP_item_health", (byte *)SP_item_health}, {"SpawnItem", (byte *)SpawnItem}, {"SetTriggeredSpawn", (byte *)SetTriggeredSpawn}, {"Item_TriggeredSpawn", (byte *)Item_TriggeredSpawn}, {"PrecacheItem", (byte *)PrecacheItem}, {"droptofloor", (byte *)droptofloor}, {"Use_Item", (byte *)Use_Item}, {"Drop_Item", (byte *)Drop_Item}, {"drop_make_touchable", (byte *)drop_make_touchable}, {"drop_temp_touch", (byte *)drop_temp_touch}, {"Touch_Item", (byte *)Touch_Item}, {"Drop_PowerArmor", (byte *)Drop_PowerArmor}, {"Pickup_PowerArmor", (byte *)Pickup_PowerArmor}, {"Use_PowerArmor", (byte *)Use_PowerArmor}, {"PowerArmorType", (byte *)PowerArmorType}, {"Pickup_Armor", (byte *)Pickup_Armor}, {"ArmorIndex", (byte *)ArmorIndex}, {"Pickup_Health", (byte *)Pickup_Health}, {"MegaHealth_think", (byte *)MegaHealth_think}, {"Drop_Ammo", (byte *)Drop_Ammo}, {"Pickup_Ammo", (byte *)Pickup_Ammo}, {"Add_Ammo", (byte *)Add_Ammo}, {"Pickup_Key", (byte *)Pickup_Key}, {"Use_Silencer", (byte *)Use_Silencer}, {"Use_Invulnerability", (byte *)Use_Invulnerability}, {"Use_Envirosuit", (byte *)Use_Envirosuit}, {"Use_Breather", (byte *)Use_Breather}, {"Use_Quad", (byte *)Use_Quad}, {"Use_Vengeance", (byte *)Use_Vengeance}, {"Use_Hunter", (byte *)Use_Hunter}, {"Use_Defender", (byte *)Use_Defender}, {"Pickup_Sphere", (byte *)Pickup_Sphere}, {"Pickup_Doppleganger", (byte *)Pickup_Doppleganger}, {"Use_Doppleganger", (byte *)Use_Doppleganger}, {"Use_Nuke", (byte *)Use_Nuke}, {"Use_Compass", (byte *)Use_Compass}, {"Use_Double", (byte *)Use_Double}, {"Use_IR", (byte *)Use_IR}, {"Pickup_Nuke", (byte *)Pickup_Nuke}, {"Pickup_Pack", (byte *)Pickup_Pack}, {"Pickup_Bandolier", (byte *)Pickup_Bandolier}, {"Pickup_AncientHead", (byte *)Pickup_AncientHead}, {"Pickup_Adrenaline", (byte *)Pickup_Adrenaline}, {"Drop_General", (byte *)Drop_General}, {"Pickup_Powerup", (byte *)Pickup_Powerup}, {"SetRespawn", (byte *)SetRespawn}, {"DoRespawn", (byte *)DoRespawn}, {"FindItem", (byte *)FindItem}, {"FindItemByClassname", (byte *)FindItemByClassname}, {"GetItemByIndex", (byte *)GetItemByIndex}, {"SP_func_killbox", (byte *)SP_func_killbox}, {"use_killbox", (byte *)use_killbox}, {"SP_func_door_secret", (byte *)SP_func_door_secret}, {"door_secret_die", (byte *)door_secret_die}, {"door_secret_blocked", (byte *)door_secret_blocked}, {"door_secret_done", (byte *)door_secret_done}, {"door_secret_move6", (byte *)door_secret_move6}, {"door_secret_move5", (byte *)door_secret_move5}, {"door_secret_move4", (byte *)door_secret_move4}, {"door_secret_move3", (byte *)door_secret_move3}, {"door_secret_move2", (byte *)door_secret_move2}, {"door_secret_move1", (byte *)door_secret_move1}, {"door_secret_use", (byte *)door_secret_use}, {"SP_func_conveyor", (byte *)SP_func_conveyor}, {"func_conveyor_use", (byte *)func_conveyor_use}, {"SP_func_timer", (byte *)SP_func_timer}, {"func_timer_use", (byte *)func_timer_use}, {"func_timer_think", (byte *)func_timer_think}, {"SP_trigger_elevator", (byte *)SP_trigger_elevator}, {"trigger_elevator_init", (byte *)trigger_elevator_init}, {"trigger_elevator_use", (byte *)trigger_elevator_use}, {"SP_func_train", (byte *)SP_func_train}, {"train_use", (byte *)train_use}, {"func_train_find", (byte *)func_train_find}, {"train_resume", (byte *)train_resume}, {"train_next", (byte *)train_next}, {"train_piece_wait", (byte *)train_piece_wait}, {"train_wait", (byte *)train_wait}, {"train_blocked", (byte *)train_blocked}, {"SP_func_water", (byte *)SP_func_water}, {"smart_water_blocked", (byte *)smart_water_blocked}, {"SP_func_door_rotating", (byte *)SP_func_door_rotating}, {"Door_Activate", (byte *)Door_Activate}, {"SP_func_door", (byte *)SP_func_door}, {"door_touch", (byte *)door_touch}, {"door_killed", (byte *)door_killed}, {"door_blocked", (byte *)door_blocked}, {"Think_SpawnDoorTrigger", (byte *)Think_SpawnDoorTrigger}, {"Think_CalcMoveSpeed", (byte *)Think_CalcMoveSpeed}, {"Touch_DoorTrigger", (byte *)Touch_DoorTrigger}, {"door_use", (byte *)door_use}, {"smart_water_go_up", (byte *)smart_water_go_up}, {"door_go_up", (byte *)door_go_up}, {"door_go_down", (byte *)door_go_down}, {"door_hit_bottom", (byte *)door_hit_bottom}, {"door_hit_top", (byte *)door_hit_top}, {"door_use_areaportals", (byte *)door_use_areaportals}, {"SP_func_button", (byte *)SP_func_button}, {"button_killed", (byte *)button_killed}, {"button_touch", (byte *)button_touch}, {"button_use", (byte *)button_use}, {"button_fire", (byte *)button_fire}, {"button_wait", (byte *)button_wait}, {"button_return", (byte *)button_return}, {"button_done", (byte *)button_done}, {"SP_func_rotating", (byte *)SP_func_rotating}, {"rotating_use", (byte *)rotating_use}, {"rotating_touch", (byte *)rotating_touch}, {"rotating_blocked", (byte *)rotating_blocked}, {"rotating_decel", (byte *)rotating_decel}, {"rotating_accel", (byte *)rotating_accel}, {"SP_func_plat2", (byte *)SP_func_plat2}, {"plat2_activate", (byte *)plat2_activate}, {"Use_Plat2", (byte *)Use_Plat2}, {"plat2_blocked", (byte *)plat2_blocked}, {"Touch_Plat_Center2", (byte *)Touch_Plat_Center2}, {"plat2_operate", (byte *)plat2_operate}, {"plat2_go_up", (byte *)plat2_go_up}, {"plat2_go_down", (byte *)plat2_go_down}, {"plat2_hit_bottom", (byte *)plat2_hit_bottom}, {"plat2_hit_top", (byte *)plat2_hit_top}, {"plat2_kill_danger_area", (byte *)plat2_kill_danger_area}, {"plat2_spawn_danger_area", (byte *)plat2_spawn_danger_area}, {"SP_func_plat", (byte *)SP_func_plat}, {"plat_spawn_inside_trigger", (byte *)plat_spawn_inside_trigger}, {"Touch_Plat_Center", (byte *)Touch_Plat_Center}, {"Use_Plat", (byte *)Use_Plat}, {"plat_blocked", (byte *)plat_blocked}, {"plat_go_up", (byte *)plat_go_up}, {"plat_go_down", (byte *)plat_go_down}, {"plat_hit_bottom", (byte *)plat_hit_bottom}, {"plat_hit_top", (byte *)plat_hit_top}, {"Think_AccelMove", (byte *)Think_AccelMove}, {"plat_Accelerate", (byte *)plat_Accelerate}, {"plat_CalcAcceleratedMove", (byte *)plat_CalcAcceleratedMove}, {"AngleMove_Calc", (byte *)AngleMove_Calc}, {"AngleMove_Begin", (byte *)AngleMove_Begin}, {"AngleMove_Final", (byte *)AngleMove_Final}, {"AngleMove_Done", (byte *)AngleMove_Done}, {"Move_Calc", (byte *)Move_Calc}, {"Move_Begin", (byte *)Move_Begin}, {"Move_Final", (byte *)Move_Final}, {"Move_Done", (byte *)Move_Done}, {"T_RadiusClassDamage", (byte *)T_RadiusClassDamage}, {"T_RadiusNukeDamage", (byte *)T_RadiusNukeDamage}, {"T_RadiusDamage", (byte *)T_RadiusDamage}, {"T_Damage", (byte *)T_Damage}, {"CheckTeamDamage", (byte *)CheckTeamDamage}, {"M_ReactToDamage", (byte *)M_ReactToDamage}, {"CheckArmor", (byte *)CheckArmor}, {"CheckPowerArmor", (byte *)CheckPowerArmor}, {"SpawnDamage", (byte *)SpawnDamage}, {"Killed", (byte *)Killed}, {"CanDamage", (byte *)CanDamage}, {"cleanupHealTarget", (byte *)cleanupHealTarget}, {"ClientCommand", (byte *)ClientCommand}, {"Cmd_PlayerList_f", (byte *)Cmd_PlayerList_f}, {"Cmd_Ent_Count_f", (byte *)Cmd_Ent_Count_f}, {"Cmd_Say_f", (byte *)Cmd_Say_f}, {"Cmd_Wave_f", (byte *)Cmd_Wave_f}, {"Cmd_Players_f", (byte *)Cmd_Players_f}, {"PlayerSort", (byte *)PlayerSort}, {"Cmd_PutAway_f", (byte *)Cmd_PutAway_f}, {"Cmd_Kill_f", (byte *)Cmd_Kill_f}, {"Cmd_InvDrop_f", (byte *)Cmd_InvDrop_f}, {"Cmd_WeapLast_f", (byte *)Cmd_WeapLast_f}, {"Cmd_WeapNext_f", (byte *)Cmd_WeapNext_f}, {"Cmd_WeapPrev_f", (byte *)Cmd_WeapPrev_f}, {"Cmd_InvUse_f", (byte *)Cmd_InvUse_f}, {"Cmd_Inven_f", (byte *)Cmd_Inven_f}, {"Cmd_Help_f", (byte *)Cmd_Help_f}, {"Cmd_Drop_f", (byte *)Cmd_Drop_f}, {"Cmd_Use_f", (byte *)Cmd_Use_f}, {"Cmd_Noclip_f", (byte *)Cmd_Noclip_f}, {"Cmd_Notarget_f", (byte *)Cmd_Notarget_f}, {"Cmd_God_f", (byte *)Cmd_God_f}, {"Cmd_Give_f", (byte *)Cmd_Give_f}, {"ValidateSelectedItem", (byte *)ValidateSelectedItem}, {"SelectPrevItem", (byte *)SelectPrevItem}, {"SelectNextItem", (byte *)SelectNextItem}, {"OnSameTeam", (byte *)OnSameTeam}, {"GetChaseTarget", (byte *)GetChaseTarget}, {"ChasePrev", (byte *)ChasePrev}, {"ChaseNext", (byte *)ChaseNext}, {"UpdateChaseCam", (byte *)UpdateChaseCam}, {"ai_run", (byte *)ai_run}, {"ai_checkattack", (byte *)ai_checkattack}, {"ai_run_slide", (byte *)ai_run_slide}, {"ai_run_missile", (byte *)ai_run_missile}, {"ai_run_melee", (byte *)ai_run_melee}, {"M_CheckAttack", (byte *)M_CheckAttack}, {"FacingIdeal", (byte *)FacingIdeal}, {"FindTarget", (byte *)FindTarget}, {"FoundTarget", (byte *)FoundTarget}, {"HuntTarget", (byte *)HuntTarget}, {"infront", (byte *)infront}, {"visible", (byte *)visible}, {"range", (byte *)range}, {"ai_turn", (byte *)ai_turn}, {"ai_charge", (byte *)ai_charge}, {"ai_walk", (byte *)ai_walk}, {"ai_stand", (byte *)ai_stand}, {"ai_move", (byte *)ai_move}, {"AI_SetSightClient", (byte *)AI_SetSightClient}, {"SP_dm_tag_token", (byte *)SP_dm_tag_token}, {"Tag_PostInitSetup", (byte *)Tag_PostInitSetup}, {"Tag_GameInit", (byte *)Tag_GameInit}, {"Tag_ChangeDamage", (byte *)Tag_ChangeDamage}, {"Tag_DogTag", (byte *)Tag_DogTag}, {"Tag_PlayerEffects", (byte *)Tag_PlayerEffects}, {"Tag_DropToken", (byte *)Tag_DropToken}, {"Tag_MakeTouchable", (byte *)Tag_MakeTouchable}, {"Tag_Respawn", (byte *)Tag_Respawn}, {"Tag_PickupToken", (byte *)Tag_PickupToken}, {"Tag_Score", (byte *)Tag_Score}, {"Tag_PlayerDisconnect", (byte *)Tag_PlayerDisconnect}, {"Tag_KillItBonus", (byte *)Tag_KillItBonus}, {"Tag_PlayerDeath", (byte *)Tag_PlayerDeath}, {"SP_dm_dball_goal", (byte *)SP_dm_dball_goal}, {"SP_dm_dball_speed_change", (byte *)SP_dm_dball_speed_change}, {"SP_dm_dball_ball_start", (byte *)SP_dm_dball_ball_start}, {"SP_dm_dball_team2_start", (byte *)SP_dm_dball_team2_start}, {"SP_dm_dball_team1_start", (byte *)SP_dm_dball_team1_start}, {"SP_dm_dball_ball", (byte *)SP_dm_dball_ball}, {"DBall_SpeedTouch", (byte *)DBall_SpeedTouch}, {"DBall_BallRespawn", (byte *)DBall_BallRespawn}, {"DBall_BallDie", (byte *)DBall_BallDie}, {"DBall_BallPain", (byte *)DBall_BallPain}, {"DBall_BallTouch", (byte *)DBall_BallTouch}, {"PickBallStart", (byte *)PickBallStart}, {"DBall_GoalTouch", (byte *)DBall_GoalTouch}, {"DBall_ChangeKnockback", (byte *)DBall_ChangeKnockback}, {"DBall_ChangeDamage", (byte *)DBall_ChangeDamage}, {"DBall_PostInitSetup", (byte *)DBall_PostInitSetup}, {"DBall_GameInit", (byte *)DBall_GameInit}, {"DBall_SelectSpawnPoint", (byte *)DBall_SelectSpawnPoint}, {"DBall_ClientBegin", (byte *)DBall_ClientBegin}, {"DBall_CheckDMRules", (byte *)DBall_CheckDMRules}, {"wait_and_change_think", (byte *)wait_and_change_think}, {0, 0} rogue-ROGUE_2_13/src/savegame/tables/gamemmove_decs.h000066400000000000000000000323511477320066100225710ustar00rootroot00000000000000/* * ======================================================================= * * Prototypes for every mmove_t in the game.so. * * ======================================================================= */ extern mmove_t widow2_move_really_dead ; extern mmove_t widow2_move_dead ; extern mmove_t widow2_move_death ; extern mmove_t widow2_move_pain ; extern mmove_t widow2_move_tongs ; extern mmove_t widow2_move_spawn ; extern mmove_t widow2_move_attack_disrupt ; extern mmove_t widow2_move_attack_post_beam ; extern mmove_t widow2_move_attack_beam ; extern mmove_t widow2_move_attack_pre_beam ; extern mmove_t widow2_move_run ; extern mmove_t widow2_move_walk ; extern mmove_t widow2_move_stand ; extern mmove_t widow_move_attack_kick ; extern mmove_t widow_move_death ; extern mmove_t widow_move_pain_light ; extern mmove_t widow_move_pain_heavy ; extern mmove_t widow_move_spawn ; extern mmove_t widow_move_attack_pre_rail ; extern mmove_t widow_move_attack_rail_r ; extern mmove_t widow_move_attack_rail_l ; extern mmove_t widow_move_attack_rail ; extern mmove_t widow_move_attack_pre_blaster ; extern mmove_t widow_move_run_attack ; extern mmove_t widow_move_run ; extern mmove_t widow_move_walk ; extern mmove_t widow_move_stand ; extern mmove_t widow_move_attack_blaster ; extern mmove_t widow_move_attack_post_blaster_l ; extern mmove_t widow_move_attack_post_blaster_r ; extern mmove_t widow_move_attack_post_blaster ; extern mmove_t turret_move_run ; extern mmove_t turret_move_seek ; extern mmove_t turret_move_ready_gun ; extern mmove_t turret_move_stand ; extern mmove_t turret_move_fire_blind ; extern mmove_t turret_move_fire ; extern mmove_t tank_move_death ; extern mmove_t tank_move_attack_chain ; extern mmove_t tank_move_attack_post_rocket ; extern mmove_t tank_move_attack_fire_rocket ; extern mmove_t tank_move_attack_pre_rocket ; extern mmove_t tank_move_attack_strike ; extern mmove_t tank_move_attack_post_blast ; extern mmove_t tank_move_reattack_blast ; extern mmove_t tank_move_attack_blast ; extern mmove_t tank_move_pain3 ; extern mmove_t tank_move_pain2 ; extern mmove_t tank_move_pain1 ; extern mmove_t tank_move_stop_run ; extern mmove_t tank_move_run ; extern mmove_t tank_move_start_run ; extern mmove_t tank_move_stop_walk ; extern mmove_t tank_move_walk ; extern mmove_t tank_move_start_walk ; extern mmove_t tank_move_stand ; extern mmove_t supertank_move_end_attack1 ; extern mmove_t supertank_move_attack1 ; extern mmove_t supertank_move_attack2 ; extern mmove_t supertank_move_attack3 ; extern mmove_t supertank_move_attack4 ; extern mmove_t supertank_move_backward ; extern mmove_t supertank_move_death ; extern mmove_t supertank_move_pain1 ; extern mmove_t supertank_move_pain2 ; extern mmove_t supertank_move_pain3 ; extern mmove_t supertank_move_turn_left ; extern mmove_t supertank_move_turn_right ; extern mmove_t supertank_move_forward ; extern mmove_t supertank_move_run ; extern mmove_t supertank_move_stand ; extern mmove_t stalker_move_death ; extern mmove_t stalker_move_jump_down ; extern mmove_t stalker_move_jump_up ; extern mmove_t stalker_move_dodge_run ; extern mmove_t stalker_move_jump_straightup ; extern mmove_t stalker_move_swing_r ; extern mmove_t stalker_move_swing_l ; extern mmove_t stalker_move_shoot ; extern mmove_t stalker_move_pain ; extern mmove_t stalker_move_false_death_start ; extern mmove_t stalker_move_false_death ; extern mmove_t stalker_move_false_death_end ; extern mmove_t stalker_move_walk ; extern mmove_t stalker_move_run ; extern mmove_t stalker_move_stand ; extern mmove_t stalker_move_idle2 ; extern mmove_t stalker_move_idle ; extern mmove_t soldier_move_blind ; extern mmove_t soldier_move_death6 ; extern mmove_t soldier_move_death5 ; extern mmove_t soldier_move_death4 ; extern mmove_t soldier_move_death3 ; extern mmove_t soldier_move_death2 ; extern mmove_t soldier_move_death1 ; extern mmove_t soldier_move_duck ; extern mmove_t soldier_move_attack6 ; extern mmove_t soldier_move_attack4 ; extern mmove_t soldier_move_attack3 ; extern mmove_t soldier_move_attack2 ; extern mmove_t soldier_move_attack1 ; extern mmove_t soldier_move_pain4 ; extern mmove_t soldier_move_pain3 ; extern mmove_t soldier_move_pain2 ; extern mmove_t soldier_move_pain1 ; extern mmove_t soldier_move_run ; extern mmove_t soldier_move_start_run ; extern mmove_t soldier_move_walk2 ; extern mmove_t soldier_move_walk1 ; extern mmove_t soldier_move_stand3 ; extern mmove_t soldier_move_stand1 ; extern mmove_t parasite_move_death ; extern mmove_t parasite_move_jump_down ; extern mmove_t parasite_move_jump_up ; extern mmove_t parasite_move_break ; extern mmove_t parasite_move_drain ; extern mmove_t parasite_move_pain1 ; extern mmove_t parasite_move_stop_walk ; extern mmove_t parasite_move_start_walk ; extern mmove_t parasite_move_walk ; extern mmove_t parasite_move_stop_run ; extern mmove_t parasite_move_start_run ; extern mmove_t parasite_move_run ; extern mmove_t parasite_move_stand ; extern mmove_t parasite_move_end_fidget ; extern mmove_t parasite_move_fidget ; extern mmove_t parasite_move_start_fidget ; extern mmove_t mutant_move_jump_down ; extern mmove_t mutant_move_jump_up ; extern mmove_t mutant_move_death2 ; extern mmove_t mutant_move_death1 ; extern mmove_t mutant_move_pain3 ; extern mmove_t mutant_move_pain2 ; extern mmove_t mutant_move_pain1 ; extern mmove_t mutant_move_jump ; extern mmove_t mutant_move_attack ; extern mmove_t mutant_move_run ; extern mmove_t mutant_move_start_walk ; extern mmove_t mutant_move_walk ; extern mmove_t mutant_move_idle ; extern mmove_t mutant_move_stand ; extern mmove_t medic_move_callReinforcements; extern mmove_t medic_move_attackCable ; extern mmove_t medic_move_attackBlaster ; extern mmove_t medic_move_attackHyperBlaster ; extern mmove_t medic_move_duck ; extern mmove_t medic_move_death ; extern mmove_t medic_move_pain2 ; extern mmove_t medic_move_pain1 ; extern mmove_t medic_move_run ; extern mmove_t medic_move_walk ; extern mmove_t medic_move_stand ; extern mmove_t insane_move_struggle_cross ; extern mmove_t insane_move_cross ; extern mmove_t insane_move_crawl_death ; extern mmove_t insane_move_crawl_pain ; extern mmove_t insane_move_runcrawl ; extern mmove_t insane_move_crawl ; extern mmove_t insane_move_stand_death ; extern mmove_t insane_move_stand_pain ; extern mmove_t insane_move_run_insane ; extern mmove_t insane_move_walk_insane ; extern mmove_t insane_move_run_normal ; extern mmove_t insane_move_walk_normal ; extern mmove_t insane_move_down ; extern mmove_t insane_move_jumpdown ; extern mmove_t insane_move_downtoup ; extern mmove_t insane_move_uptodown ; extern mmove_t insane_move_stand_insane ; extern mmove_t insane_move_stand_normal ; extern mmove_t infantry_move_jump2 ; extern mmove_t infantry_move_jump ; extern mmove_t infantry_move_attack2 ; extern mmove_t infantry_move_attack1 ; extern mmove_t infantry_move_duck ; extern mmove_t infantry_move_death3 ; extern mmove_t infantry_move_death2 ; extern mmove_t infantry_move_death1 ; extern mmove_t infantry_move_pain2 ; extern mmove_t infantry_move_pain1 ; extern mmove_t infantry_move_run ; extern mmove_t infantry_move_walk ; extern mmove_t infantry_move_fidget ; extern mmove_t infantry_move_stand ; extern mmove_t hover_move_start_attack2; extern mmove_t hover_move_attack2; extern mmove_t hover_move_end_attack2; extern mmove_t hover_move_end_attack ; extern mmove_t hover_move_attack1 ; extern mmove_t hover_move_start_attack ; extern mmove_t hover_move_death1 ; extern mmove_t hover_move_run ; extern mmove_t hover_move_walk ; extern mmove_t hover_move_pain1 ; extern mmove_t hover_move_pain2 ; extern mmove_t hover_move_pain3 ; extern mmove_t hover_move_stand ; extern mmove_t gunner_move_jump2 ; extern mmove_t gunner_move_jump ; extern mmove_t gunner_move_attack_grenade ; extern mmove_t gunner_move_endfire_chain ; extern mmove_t gunner_move_fire_chain ; extern mmove_t gunner_move_attack_chain ; extern mmove_t gunner_move_duck ; extern mmove_t gunner_move_death ; extern mmove_t gunner_move_pain1 ; extern mmove_t gunner_move_pain2 ; extern mmove_t gunner_move_pain3 ; extern mmove_t gunner_move_runandshoot ; extern mmove_t gunner_move_run ; extern mmove_t gunner_move_walk ; extern mmove_t gunner_move_stand ; extern mmove_t gunner_move_fidget ; extern mmove_t gladiator_move_death ; extern mmove_t gladiator_move_pain_air ; extern mmove_t gladiator_move_pain ; extern mmove_t gladiator_move_attack_gun ; extern mmove_t gladiator_move_attack_melee ; extern mmove_t gladiator_move_run ; extern mmove_t gladiator_move_walk ; extern mmove_t gladiator_move_stand ; extern mmove_t flyer_move_loop_melee ; extern mmove_t flyer_move_end_melee ; extern mmove_t flyer_move_start_melee ; extern mmove_t flyer_move_attack3 ; extern mmove_t flyer_move_attack2 ; extern mmove_t flyer_move_bankleft ; extern mmove_t flyer_move_bankright ; extern mmove_t flyer_move_defense ; extern mmove_t flyer_move_pain1 ; extern mmove_t flyer_move_pain2 ; extern mmove_t flyer_move_pain3 ; extern mmove_t flyer_move_rollleft ; extern mmove_t flyer_move_rollright ; extern mmove_t flyer_move_stop ; extern mmove_t flyer_move_start ; extern mmove_t flyer_move_kamikaze ; extern mmove_t flyer_move_run ; extern mmove_t flyer_move_walk ; extern mmove_t flyer_move_stand ; extern mmove_t floater_move_run ; extern mmove_t floater_move_walk ; extern mmove_t floater_move_pain3 ; extern mmove_t floater_move_pain2 ; extern mmove_t floater_move_pain1 ; extern mmove_t floater_move_death ; extern mmove_t floater_move_attack3 ; extern mmove_t floater_move_attack2 ; extern mmove_t floater_move_attack1a ; extern mmove_t floater_move_attack1 ; extern mmove_t floater_move_activate ; extern mmove_t floater_move_stand2 ; extern mmove_t floater_move_stand1 ; extern mmove_t flipper_move_death ; extern mmove_t flipper_move_attack ; extern mmove_t flipper_move_pain1 ; extern mmove_t flipper_move_pain2 ; extern mmove_t flipper_move_start_run ; extern mmove_t flipper_move_walk ; extern mmove_t flipper_move_run_start ; extern mmove_t flipper_move_run_loop ; extern mmove_t flipper_move_stand ; extern mmove_t chick_move_start_slash ; extern mmove_t chick_move_end_slash ; extern mmove_t chick_move_slash ; extern mmove_t chick_move_end_attack1 ; extern mmove_t chick_move_attack1 ; extern mmove_t chick_move_start_attack1 ; extern mmove_t chick_move_duck ; extern mmove_t chick_move_death1 ; extern mmove_t chick_move_death2 ; extern mmove_t chick_move_pain3 ; extern mmove_t chick_move_pain2 ; extern mmove_t chick_move_pain1 ; extern mmove_t chick_move_walk ; extern mmove_t chick_move_run ; extern mmove_t chick_move_start_run ; extern mmove_t chick_move_stand ; extern mmove_t chick_move_fidget ; extern mmove_t carrier_move_death ; extern mmove_t carrier_move_pain_light ; extern mmove_t carrier_move_pain_heavy ; extern mmove_t carrier_move_spawn ; extern mmove_t carrier_move_attack_rail ; extern mmove_t carrier_move_attack_rocket ; extern mmove_t carrier_move_attack_post_gren ; extern mmove_t carrier_move_attack_gren ; extern mmove_t carrier_move_attack_pre_gren ; extern mmove_t carrier_move_attack_post_mg ; extern mmove_t carrier_move_attack_mg ; extern mmove_t carrier_move_attack_pre_mg ; extern mmove_t carrier_move_run ; extern mmove_t carrier_move_walk ; extern mmove_t carrier_move_stand ; extern mmove_t brain_move_run ; extern mmove_t brain_move_attack2 ; extern mmove_t brain_move_attack1 ; extern mmove_t brain_move_death1 ; extern mmove_t brain_move_death2 ; extern mmove_t brain_move_duck ; extern mmove_t brain_move_pain1 ; extern mmove_t brain_move_pain2 ; extern mmove_t brain_move_pain3 ; extern mmove_t brain_move_defense ; extern mmove_t brain_move_walk1 ; extern mmove_t brain_move_idle ; extern mmove_t brain_move_stand ; extern mmove_t makron_move_attack5 ; extern mmove_t makron_move_attack4 ; extern mmove_t makron_move_attack3 ; extern mmove_t makron_move_sight ; extern mmove_t makron_move_death3 ; extern mmove_t makron_move_death2 ; extern mmove_t makron_move_pain4 ; extern mmove_t makron_move_pain5 ; extern mmove_t makron_move_pain6 ; extern mmove_t makron_move_walk ; extern mmove_t makron_move_run ; extern mmove_t makron_move_stand ; extern mmove_t jorg_move_end_attack1 ; extern mmove_t jorg_move_attack1 ; extern mmove_t jorg_move_start_attack1 ; extern mmove_t jorg_move_attack2 ; extern mmove_t jorg_move_death ; extern mmove_t jorg_move_pain1 ; extern mmove_t jorg_move_pain2 ; extern mmove_t jorg_move_pain3 ; extern mmove_t jorg_move_end_walk ; extern mmove_t jorg_move_walk ; extern mmove_t jorg_move_start_walk ; extern mmove_t jorg_move_run ; extern mmove_t jorg_move_stand ; extern mmove_t boss2_move_death ; extern mmove_t boss2_move_pain_light ; extern mmove_t boss2_move_pain_heavy ; extern mmove_t boss2_move_attack_rocket ; extern mmove_t boss2_move_attack_post_mg ; extern mmove_t boss2_move_attack_mg ; extern mmove_t boss2_move_attack_pre_mg ; extern mmove_t boss2_move_run ; extern mmove_t boss2_move_walk ; extern mmove_t boss2_move_fidget ; extern mmove_t boss2_move_stand ; extern mmove_t berserk_move_jump2 ; extern mmove_t berserk_move_jump ; extern mmove_t berserk_move_death2 ; extern mmove_t berserk_move_death1 ; extern mmove_t berserk_move_pain2 ; extern mmove_t berserk_move_pain1 ; extern mmove_t berserk_move_attack_strike ; extern mmove_t berserk_move_attack_club ; extern mmove_t berserk_move_attack_spike ; extern mmove_t berserk_move_run1 ; extern mmove_t berserk_move_walk ; extern mmove_t berserk_move_stand_fidget ; extern mmove_t berserk_move_stand ; rogue-ROGUE_2_13/src/savegame/tables/gamemmove_list.h000066400000000000000000000415761477320066100226370ustar00rootroot00000000000000/* * ======================================================================= * * Pointers to every mmove_t in the game.so. * * ======================================================================= */ {"widow2_move_really_dead", &widow2_move_really_dead}, {"widow2_move_dead", &widow2_move_dead}, {"widow2_move_death", &widow2_move_death}, {"widow2_move_pain", &widow2_move_pain}, {"widow2_move_tongs", &widow2_move_tongs}, {"widow2_move_spawn", &widow2_move_spawn}, {"widow2_move_attack_disrupt", &widow2_move_attack_disrupt}, {"widow2_move_attack_post_beam", &widow2_move_attack_post_beam}, {"widow2_move_attack_beam", &widow2_move_attack_beam}, {"widow2_move_attack_pre_beam", &widow2_move_attack_pre_beam}, {"widow2_move_run", &widow2_move_run}, {"widow2_move_walk", &widow2_move_walk}, {"widow2_move_stand", &widow2_move_stand}, {"widow_move_attack_kick", &widow_move_attack_kick}, {"widow_move_death", &widow_move_death}, {"widow_move_pain_light", &widow_move_pain_light}, {"widow_move_pain_heavy", &widow_move_pain_heavy}, {"widow_move_spawn", &widow_move_spawn}, {"widow_move_attack_pre_rail", &widow_move_attack_pre_rail}, {"widow_move_attack_rail_r", &widow_move_attack_rail_r}, {"widow_move_attack_rail_l", &widow_move_attack_rail_l}, {"widow_move_attack_rail", &widow_move_attack_rail}, {"widow_move_attack_pre_blaster", &widow_move_attack_pre_blaster}, {"widow_move_run_attack", &widow_move_run_attack}, {"widow_move_run", &widow_move_run}, {"widow_move_walk", &widow_move_walk}, {"widow_move_stand", &widow_move_stand}, {"widow_move_attack_blaster", &widow_move_attack_blaster}, {"widow_move_attack_post_blaster_l", &widow_move_attack_post_blaster_l}, {"widow_move_attack_post_blaster_r", &widow_move_attack_post_blaster_r}, {"widow_move_attack_post_blaster", &widow_move_attack_post_blaster}, {"turret_move_run", &turret_move_run}, {"turret_move_seek", &turret_move_seek}, {"turret_move_ready_gun", &turret_move_ready_gun}, {"turret_move_stand", &turret_move_stand}, {"turret_move_fire_blind", &turret_move_fire_blind}, {"turret_move_fire", &turret_move_fire}, {"tank_move_death", &tank_move_death}, {"tank_move_attack_chain", &tank_move_attack_chain}, {"tank_move_attack_post_rocket", &tank_move_attack_post_rocket}, {"tank_move_attack_fire_rocket", &tank_move_attack_fire_rocket}, {"tank_move_attack_pre_rocket", &tank_move_attack_pre_rocket}, {"tank_move_attack_strike", &tank_move_attack_strike}, {"tank_move_attack_post_blast", &tank_move_attack_post_blast}, {"tank_move_reattack_blast", &tank_move_reattack_blast}, {"tank_move_attack_blast", &tank_move_attack_blast}, {"tank_move_pain3", &tank_move_pain3}, {"tank_move_pain2", &tank_move_pain2}, {"tank_move_pain1", &tank_move_pain1}, {"tank_move_stop_run", &tank_move_stop_run}, {"tank_move_run", &tank_move_run}, {"tank_move_start_run", &tank_move_start_run}, {"tank_move_stop_walk", &tank_move_stop_walk}, {"tank_move_walk", &tank_move_walk}, {"tank_move_start_walk", &tank_move_start_walk}, {"tank_move_stand", &tank_move_stand}, {"supertank_move_end_attack1", &supertank_move_end_attack1}, {"supertank_move_attack1", &supertank_move_attack1}, {"supertank_move_attack2", &supertank_move_attack2}, {"supertank_move_attack3", &supertank_move_attack3}, {"supertank_move_attack4", &supertank_move_attack4}, {"supertank_move_backward", &supertank_move_backward}, {"supertank_move_death", &supertank_move_death}, {"supertank_move_pain1", &supertank_move_pain1}, {"supertank_move_pain2", &supertank_move_pain2}, {"supertank_move_pain3", &supertank_move_pain3}, {"supertank_move_turn_left", &supertank_move_turn_left}, {"supertank_move_turn_right", &supertank_move_turn_right}, {"supertank_move_forward", &supertank_move_forward}, {"supertank_move_run", &supertank_move_run}, {"supertank_move_stand", &supertank_move_stand}, {"stalker_move_death", &stalker_move_death}, {"stalker_move_jump_down", &stalker_move_jump_down}, {"stalker_move_jump_up", &stalker_move_jump_up}, {"stalker_move_dodge_run", &stalker_move_dodge_run}, {"stalker_move_jump_straightup", &stalker_move_jump_straightup}, {"stalker_move_swing_r", &stalker_move_swing_r}, {"stalker_move_swing_l", &stalker_move_swing_l}, {"stalker_move_shoot", &stalker_move_shoot}, {"stalker_move_pain", &stalker_move_pain}, {"stalker_move_false_death_start", &stalker_move_false_death_start}, {"stalker_move_false_death", &stalker_move_false_death}, {"stalker_move_false_death_end", &stalker_move_false_death_end}, {"stalker_move_walk", &stalker_move_walk}, {"stalker_move_run", &stalker_move_run}, {"stalker_move_stand", &stalker_move_stand}, {"stalker_move_idle2", &stalker_move_idle2}, {"stalker_move_idle", &stalker_move_idle}, {"soldier_move_blind", &soldier_move_blind}, {"soldier_move_death6", &soldier_move_death6}, {"soldier_move_death5", &soldier_move_death5}, {"soldier_move_death4", &soldier_move_death4}, {"soldier_move_death3", &soldier_move_death3}, {"soldier_move_death2", &soldier_move_death2}, {"soldier_move_death1", &soldier_move_death1}, {"soldier_move_duck", &soldier_move_duck}, {"soldier_move_attack6", &soldier_move_attack6}, {"soldier_move_attack4", &soldier_move_attack4}, {"soldier_move_attack3", &soldier_move_attack3}, {"soldier_move_attack2", &soldier_move_attack2}, {"soldier_move_attack1", &soldier_move_attack1}, {"soldier_move_pain4", &soldier_move_pain4}, {"soldier_move_pain3", &soldier_move_pain3}, {"soldier_move_pain2", &soldier_move_pain2}, {"soldier_move_pain1", &soldier_move_pain1}, {"soldier_move_run", &soldier_move_run}, {"soldier_move_start_run", &soldier_move_start_run}, {"soldier_move_walk2", &soldier_move_walk2}, {"soldier_move_walk1", &soldier_move_walk1}, {"soldier_move_stand3", &soldier_move_stand3}, {"soldier_move_stand1", &soldier_move_stand1}, {"parasite_move_death", ¶site_move_death}, {"parasite_move_jump_down", ¶site_move_jump_down}, {"parasite_move_jump_up", ¶site_move_jump_up}, {"parasite_move_break", ¶site_move_break}, {"parasite_move_drain", ¶site_move_drain}, {"parasite_move_pain1", ¶site_move_pain1}, {"parasite_move_stop_walk", ¶site_move_stop_walk}, {"parasite_move_start_walk", ¶site_move_start_walk}, {"parasite_move_walk", ¶site_move_walk}, {"parasite_move_stop_run", ¶site_move_stop_run}, {"parasite_move_start_run", ¶site_move_start_run}, {"parasite_move_run", ¶site_move_run}, {"parasite_move_stand", ¶site_move_stand}, {"parasite_move_end_fidget", ¶site_move_end_fidget}, {"parasite_move_fidget", ¶site_move_fidget}, {"parasite_move_start_fidget", ¶site_move_start_fidget}, {"mutant_move_jump_down", &mutant_move_jump_down}, {"mutant_move_jump_up", &mutant_move_jump_up}, {"mutant_move_death2", &mutant_move_death2}, {"mutant_move_death1", &mutant_move_death1}, {"mutant_move_pain3", &mutant_move_pain3}, {"mutant_move_pain2", &mutant_move_pain2}, {"mutant_move_pain1", &mutant_move_pain1}, {"mutant_move_jump", &mutant_move_jump}, {"mutant_move_attack", &mutant_move_attack}, {"mutant_move_run", &mutant_move_run}, {"mutant_move_start_walk", &mutant_move_start_walk}, {"mutant_move_walk", &mutant_move_walk}, {"mutant_move_idle", &mutant_move_idle}, {"mutant_move_stand", &mutant_move_stand}, {"medic_move_callReinforcements", &medic_move_callReinforcements}, {"medic_move_attackCable", &medic_move_attackCable}, {"medic_move_attackBlaster", &medic_move_attackBlaster}, {"medic_move_attackHyperBlaster", &medic_move_attackHyperBlaster}, {"medic_move_duck", &medic_move_duck}, {"medic_move_death", &medic_move_death}, {"medic_move_pain2", &medic_move_pain2}, {"medic_move_pain1", &medic_move_pain1}, {"medic_move_run", &medic_move_run}, {"medic_move_walk", &medic_move_walk}, {"medic_move_stand", &medic_move_stand}, {"insane_move_struggle_cross", &insane_move_struggle_cross}, {"insane_move_cross", &insane_move_cross}, {"insane_move_crawl_death", &insane_move_crawl_death}, {"insane_move_crawl_pain", &insane_move_crawl_pain}, {"insane_move_runcrawl", &insane_move_runcrawl}, {"insane_move_crawl", &insane_move_crawl}, {"insane_move_stand_death", &insane_move_stand_death}, {"insane_move_stand_pain", &insane_move_stand_pain}, {"insane_move_run_insane", &insane_move_run_insane}, {"insane_move_walk_insane", &insane_move_walk_insane}, {"insane_move_run_normal", &insane_move_run_normal}, {"insane_move_walk_normal", &insane_move_walk_normal}, {"insane_move_down", &insane_move_down}, {"insane_move_jumpdown", &insane_move_jumpdown}, {"insane_move_downtoup", &insane_move_downtoup}, {"insane_move_uptodown", &insane_move_uptodown}, {"insane_move_stand_insane", &insane_move_stand_insane}, {"insane_move_stand_normal", &insane_move_stand_normal}, {"infantry_move_jump2", &infantry_move_jump2}, {"infantry_move_jump", &infantry_move_jump}, {"infantry_move_attack2", &infantry_move_attack2}, {"infantry_move_attack1", &infantry_move_attack1}, {"infantry_move_duck", &infantry_move_duck}, {"infantry_move_death3", &infantry_move_death3}, {"infantry_move_death2", &infantry_move_death2}, {"infantry_move_death1", &infantry_move_death1}, {"infantry_move_pain2", &infantry_move_pain2}, {"infantry_move_pain1", &infantry_move_pain1}, {"infantry_move_run", &infantry_move_run}, {"infantry_move_walk", &infantry_move_walk}, {"infantry_move_fidget", &infantry_move_fidget}, {"infantry_move_stand", &infantry_move_stand}, {"hover_move_start_attack2", &hover_move_start_attack2}, {"hover_move_attack2", &hover_move_attack2}, {"hover_move_end_attack2", &hover_move_end_attack2}, {"hover_move_end_attack", &hover_move_end_attack}, {"hover_move_attack1", &hover_move_attack1}, {"hover_move_start_attack", &hover_move_start_attack}, {"hover_move_death1", &hover_move_death1}, {"hover_move_run", &hover_move_run}, {"hover_move_walk", &hover_move_walk}, {"hover_move_pain1", &hover_move_pain1}, {"hover_move_pain2", &hover_move_pain2}, {"hover_move_pain3", &hover_move_pain3}, {"hover_move_stand", &hover_move_stand}, {"gunner_move_jump2", &gunner_move_jump2}, {"gunner_move_jump", &gunner_move_jump}, {"gunner_move_attack_grenade", &gunner_move_attack_grenade}, {"gunner_move_endfire_chain", &gunner_move_endfire_chain}, {"gunner_move_fire_chain", &gunner_move_fire_chain}, {"gunner_move_attack_chain", &gunner_move_attack_chain}, {"gunner_move_duck", &gunner_move_duck}, {"gunner_move_death", &gunner_move_death}, {"gunner_move_pain1", &gunner_move_pain1}, {"gunner_move_pain2", &gunner_move_pain2}, {"gunner_move_pain3", &gunner_move_pain3}, {"gunner_move_runandshoot", &gunner_move_runandshoot}, {"gunner_move_run", &gunner_move_run}, {"gunner_move_walk", &gunner_move_walk}, {"gunner_move_stand", &gunner_move_stand}, {"gunner_move_fidget", &gunner_move_fidget}, {"gladiator_move_death", &gladiator_move_death}, {"gladiator_move_pain_air", &gladiator_move_pain_air}, {"gladiator_move_pain", &gladiator_move_pain}, {"gladiator_move_attack_gun", &gladiator_move_attack_gun}, {"gladiator_move_attack_melee", &gladiator_move_attack_melee}, {"gladiator_move_run", &gladiator_move_run}, {"gladiator_move_walk", &gladiator_move_walk}, {"gladiator_move_stand", &gladiator_move_stand}, {"flyer_move_loop_melee", &flyer_move_loop_melee}, {"flyer_move_end_melee", &flyer_move_end_melee}, {"flyer_move_start_melee", &flyer_move_start_melee}, {"flyer_move_attack3", &flyer_move_attack3}, {"flyer_move_attack2", &flyer_move_attack2}, {"flyer_move_bankleft", &flyer_move_bankleft}, {"flyer_move_bankright", &flyer_move_bankright}, {"flyer_move_defense", &flyer_move_defense}, {"flyer_move_pain1", &flyer_move_pain1}, {"flyer_move_pain2", &flyer_move_pain2}, {"flyer_move_pain3", &flyer_move_pain3}, {"flyer_move_rollleft", &flyer_move_rollleft}, {"flyer_move_rollright", &flyer_move_rollright}, {"flyer_move_stop", &flyer_move_stop}, {"flyer_move_start", &flyer_move_start}, {"flyer_move_kamikaze", &flyer_move_kamikaze}, {"flyer_move_run", &flyer_move_run}, {"flyer_move_walk", &flyer_move_walk}, {"flyer_move_stand", &flyer_move_stand}, {"floater_move_run", &floater_move_run}, {"floater_move_walk", &floater_move_walk}, {"floater_move_pain3", &floater_move_pain3}, {"floater_move_pain2", &floater_move_pain2}, {"floater_move_pain1", &floater_move_pain1}, {"floater_move_death", &floater_move_death}, {"floater_move_attack3", &floater_move_attack3}, {"floater_move_attack2", &floater_move_attack2}, {"floater_move_attack1a", &floater_move_attack1a}, {"floater_move_attack1", &floater_move_attack1}, {"floater_move_activate", &floater_move_activate}, {"floater_move_stand2", &floater_move_stand2}, {"floater_move_stand1", &floater_move_stand1}, {"flipper_move_death", &flipper_move_death}, {"flipper_move_attack", &flipper_move_attack}, {"flipper_move_pain1", &flipper_move_pain1}, {"flipper_move_pain2", &flipper_move_pain2}, {"flipper_move_start_run", &flipper_move_start_run}, {"flipper_move_walk", &flipper_move_walk}, {"flipper_move_run_start", &flipper_move_run_start}, {"flipper_move_run_loop", &flipper_move_run_loop}, {"flipper_move_stand", &flipper_move_stand}, {"chick_move_start_slash", &chick_move_start_slash}, {"chick_move_end_slash", &chick_move_end_slash}, {"chick_move_slash", &chick_move_slash}, {"chick_move_end_attack1", &chick_move_end_attack1}, {"chick_move_attack1", &chick_move_attack1}, {"chick_move_start_attack1", &chick_move_start_attack1}, {"chick_move_duck", &chick_move_duck}, {"chick_move_death1", &chick_move_death1}, {"chick_move_death2", &chick_move_death2}, {"chick_move_pain3", &chick_move_pain3}, {"chick_move_pain2", &chick_move_pain2}, {"chick_move_pain1", &chick_move_pain1}, {"chick_move_walk", &chick_move_walk}, {"chick_move_run", &chick_move_run}, {"chick_move_start_run", &chick_move_start_run}, {"chick_move_stand", &chick_move_stand}, {"chick_move_fidget", &chick_move_fidget}, {"carrier_move_death", &carrier_move_death}, {"carrier_move_pain_light", &carrier_move_pain_light}, {"carrier_move_pain_heavy", &carrier_move_pain_heavy}, {"carrier_move_spawn", &carrier_move_spawn}, {"carrier_move_attack_rail", &carrier_move_attack_rail}, {"carrier_move_attack_rocket", &carrier_move_attack_rocket}, {"carrier_move_attack_post_gren", &carrier_move_attack_post_gren}, {"carrier_move_attack_gren", &carrier_move_attack_gren}, {"carrier_move_attack_pre_gren", &carrier_move_attack_pre_gren}, {"carrier_move_attack_post_mg", &carrier_move_attack_post_mg}, {"carrier_move_attack_mg", &carrier_move_attack_mg}, {"carrier_move_attack_pre_mg", &carrier_move_attack_pre_mg}, {"carrier_move_run", &carrier_move_run}, {"carrier_move_walk", &carrier_move_walk}, {"carrier_move_stand", &carrier_move_stand}, {"brain_move_run", &brain_move_run}, {"brain_move_attack2", &brain_move_attack2}, {"brain_move_attack1", &brain_move_attack1}, {"brain_move_death1", &brain_move_death1}, {"brain_move_death2", &brain_move_death2}, {"brain_move_duck", &brain_move_duck}, {"brain_move_pain1", &brain_move_pain1}, {"brain_move_pain2", &brain_move_pain2}, {"brain_move_pain3", &brain_move_pain3}, {"brain_move_defense", &brain_move_defense}, {"brain_move_walk1", &brain_move_walk1}, {"brain_move_idle", &brain_move_idle}, {"brain_move_stand", &brain_move_stand}, {"makron_move_attack5", &makron_move_attack5}, {"makron_move_attack4", &makron_move_attack4}, {"makron_move_attack3", &makron_move_attack3}, {"makron_move_sight", &makron_move_sight}, {"makron_move_death3", &makron_move_death3}, {"makron_move_death2", &makron_move_death2}, {"makron_move_pain4", &makron_move_pain4}, {"makron_move_pain5", &makron_move_pain5}, {"makron_move_pain6", &makron_move_pain6}, {"makron_move_walk", &makron_move_walk}, {"makron_move_run", &makron_move_run}, {"makron_move_stand", &makron_move_stand}, {"jorg_move_end_attack1", &jorg_move_end_attack1}, {"jorg_move_attack1", &jorg_move_attack1}, {"jorg_move_start_attack1", &jorg_move_start_attack1}, {"jorg_move_attack2", &jorg_move_attack2}, {"jorg_move_death", &jorg_move_death}, {"jorg_move_pain1", &jorg_move_pain1}, {"jorg_move_pain2", &jorg_move_pain2}, {"jorg_move_pain3", &jorg_move_pain3}, {"jorg_move_end_walk", &jorg_move_end_walk}, {"jorg_move_walk", &jorg_move_walk}, {"jorg_move_start_walk", &jorg_move_start_walk}, {"jorg_move_run", &jorg_move_run}, {"jorg_move_stand", &jorg_move_stand}, {"boss2_move_death", &boss2_move_death}, {"boss2_move_pain_light", &boss2_move_pain_light}, {"boss2_move_pain_heavy", &boss2_move_pain_heavy}, {"boss2_move_attack_rocket", &boss2_move_attack_rocket}, {"boss2_move_attack_post_mg", &boss2_move_attack_post_mg}, {"boss2_move_attack_mg", &boss2_move_attack_mg}, {"boss2_move_attack_pre_mg", &boss2_move_attack_pre_mg}, {"boss2_move_run", &boss2_move_run}, {"boss2_move_walk", &boss2_move_walk}, {"boss2_move_fidget", &boss2_move_fidget}, {"boss2_move_stand", &boss2_move_stand}, {"berserk_move_jump2", &berserk_move_jump2}, {"berserk_move_jump", &berserk_move_jump}, {"berserk_move_death2", &berserk_move_death2}, {"berserk_move_death1", &berserk_move_death1}, {"berserk_move_pain2", &berserk_move_pain2}, {"berserk_move_pain1", &berserk_move_pain1}, {"berserk_move_attack_strike", &berserk_move_attack_strike}, {"berserk_move_attack_club", &berserk_move_attack_club}, {"berserk_move_attack_spike", &berserk_move_attack_spike}, {"berserk_move_run1", &berserk_move_run1}, {"berserk_move_walk", &berserk_move_walk}, {"berserk_move_stand_fidget", &berserk_move_stand_fidget}, {"berserk_move_stand", &berserk_move_stand}, {0, 0} rogue-ROGUE_2_13/src/savegame/tables/levelfields.h000066400000000000000000000010051477320066100221040ustar00rootroot00000000000000/* * ======================================================================= * * Fields inside a level to be saved. * * ======================================================================= */ {"changemap", LLOFS(changemap), F_LSTRING}, {"sight_client", LLOFS(sight_client), F_EDICT}, {"sight_entity", LLOFS(sight_entity), F_EDICT}, {"sound_entity", LLOFS(sound_entity), F_EDICT}, {"sound2_entity", LLOFS(sound2_entity), F_EDICT}, {"disguise_violator", LLOFS(disguise_violator), F_EDICT}, {NULL, 0, F_INT} rogue-ROGUE_2_13/src/shared/000077500000000000000000000000001477320066100156455ustar00rootroot00000000000000rogue-ROGUE_2_13/src/shared/flash.c000066400000000000000000000305661477320066100171200ustar00rootroot00000000000000/* * ======================================================================= * * Muzzle flash posititions. * * ======================================================================= */ #include "../header/shared.h" vec3_t monster_flash_offset[] = { /* flash 0 is not used */ {0.0, 0.0, 0.0}, /* MZ2_TANK_BLASTER_1 1 */ {20.7, -18.5, 28.7}, /* MZ2_TANK_BLASTER_2 2 */ {16.6, -21.5, 30.1}, /* MZ2_TANK_BLASTER_3 3 */ {11.8, -23.9, 32.1}, /* MZ2_TANK_MACHINEGUN_1 4 */ {22.9, -0.7, 25.3}, /* MZ2_TANK_MACHINEGUN_2 5 */ {22.2, 6.2, 22.3}, /* MZ2_TANK_MACHINEGUN_3 6 */ {19.4, 13.1, 18.6}, /* MZ2_TANK_MACHINEGUN_4 7 */ {19.4, 18.8, 18.6}, /* MZ2_TANK_MACHINEGUN_5 8 */ {17.9, 25.0, 18.6}, /* MZ2_TANK_MACHINEGUN_6 9 */ {14.1, 30.5, 20.6}, /* MZ2_TANK_MACHINEGUN_7 10 */ {9.3, 35.3, 22.1}, /* MZ2_TANK_MACHINEGUN_8 11 */ {4.7, 38.4, 22.1}, /* MZ2_TANK_MACHINEGUN_9 12 */ {-1.1, 40.4, 24.1}, /* MZ2_TANK_MACHINEGUN_10 13 */ {-6.5, 41.2, 24.1}, /* MZ2_TANK_MACHINEGUN_11 14 */ {3.2, 40.1, 24.7}, /* MZ2_TANK_MACHINEGUN_12 15 */ {11.7, 36.7, 26.0}, /* MZ2_TANK_MACHINEGUN_13 16 */ {18.9, 31.3, 26.0}, /* MZ2_TANK_MACHINEGUN_14 17 */ {24.4, 24.4, 26.4}, /* MZ2_TANK_MACHINEGUN_15 18 */ {27.1, 17.1, 27.2}, /* MZ2_TANK_MACHINEGUN_16 19 */ {28.5, 9.1, 28.0}, /* MZ2_TANK_MACHINEGUN_17 20 */ {27.1, 2.2, 28.0}, /* MZ2_TANK_MACHINEGUN_18 21 */ {24.9, -2.8, 28.0}, /* MZ2_TANK_MACHINEGUN_19 22 */ {21.6, -7.0, 26.4}, /* MZ2_TANK_ROCKET_1 23 */ {6.2, 29.1, 49.1}, /* MZ2_TANK_ROCKET_2 24 */ {6.9, 23.8, 49.1}, /* MZ2_TANK_ROCKET_3 25 */ {8.3, 17.8, 49.5}, /* MZ2_INFANTRY_MACHINEGUN_1 26 */ {26.6, 7.1, 13.1}, /* MZ2_INFANTRY_MACHINEGUN_2 27 */ {18.2, 7.5, 15.4}, /* MZ2_INFANTRY_MACHINEGUN_3 28 */ {17.2, 10.3, 17.9}, /* MZ2_INFANTRY_MACHINEGUN_4 29 */ {17.0, 12.8, 20.1}, /* MZ2_INFANTRY_MACHINEGUN_5 30 */ {15.1, 14.1, 21.8}, /* MZ2_INFANTRY_MACHINEGUN_6 31 */ {11.8, 17.2, 23.1}, /* MZ2_INFANTRY_MACHINEGUN_7 32 */ {11.4, 20.2, 21.0}, /* MZ2_INFANTRY_MACHINEGUN_8 33 */ {9.0, 23.0, 18.9}, /* MZ2_INFANTRY_MACHINEGUN_9 34 */ {13.9, 18.6, 17.7}, /* MZ2_INFANTRY_MACHINEGUN_10 35 */ {15.4, 15.6, 15.8}, /* MZ2_INFANTRY_MACHINEGUN_11 36 */ {10.2, 15.2, 25.1}, /* MZ2_INFANTRY_MACHINEGUN_12 37 */ {-1.9, 15.1, 28.2}, /* MZ2_INFANTRY_MACHINEGUN_13 38 */ {-12.4, 13.0, 20.2}, /* MZ2_SOLDIER_BLASTER_1 39 */ {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, /* MZ2_SOLDIER_BLASTER_2 40 */ {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_1 41 */ {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_2 42 */ {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_1 43 */ {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_2 44 */ {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, /* MZ2_GUNNER_MACHINEGUN_1 45 */ {30.1 * 1.15, 3.9 * 1.15, 19.6 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_2 46 */ {29.1 * 1.15, 2.5 * 1.15, 20.7 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_3 47 */ {28.2 * 1.15, 2.5 * 1.15, 22.2 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_4 48 */ {28.2 * 1.15, 3.6 * 1.15, 22.0 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_5 49 */ {26.9 * 1.15, 2.0 * 1.15, 23.4 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_6 50 */ {26.5 * 1.15, 0.6 * 1.15, 20.8 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_7 51 */ {26.9 * 1.15, 0.5 * 1.15, 21.5 * 1.15}, /* MZ2_GUNNER_MACHINEGUN_8 52 */ {29.0 * 1.15, 2.4 * 1.15, 19.5 * 1.15}, /* MZ2_GUNNER_GRENADE_1 53 */ {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, /* MZ2_GUNNER_GRENADE_2 54 */ {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, /* MZ2_GUNNER_GRENADE_3 55 */ {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, /* MZ2_GUNNER_GRENADE_4 56 */ {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, /* MZ2_CHICK_ROCKET_1 57 */ {24.8, -9.0, 39.0}, /* MZ2_FLYER_BLASTER_1 58 */ {12.1, 13.4, -14.5}, /* MZ2_FLYER_BLASTER_2 59 */ {12.1, -7.4, -14.5}, /* MZ2_MEDIC_BLASTER_1 60 */ {12.1, 5.4, 16.5}, /* MZ2_GLADIATOR_RAILGUN_1 61 */ {30.0, 18.0, 28.0}, /* MZ2_HOVER_BLASTER_1 62 */ {32.5, -0.8, 10.0}, /* MZ2_ACTOR_MACHINEGUN_1 63 */ {18.4, 7.4, 9.6}, /* MZ2_SUPERTANK_MACHINEGUN_1 64 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_MACHINEGUN_2 65 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_MACHINEGUN_3 66 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_MACHINEGUN_4 67 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_MACHINEGUN_5 68 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_MACHINEGUN_6 69 */ {30.0, 30.0, 88.5}, /* MZ2_SUPERTANK_ROCKET_1 70 */ {16.0, -22.5, 91.2}, /* MZ2_SUPERTANK_ROCKET_2 71 */ {16.0, -33.4, 86.7}, /* MZ2_SUPERTANK_ROCKET_3 72 */ {16.0, -42.8, 83.3}, /* MZ2_BOSS2_MACHINEGUN_L1 73 */ {32, -40, 70}, /* MZ2_BOSS2_MACHINEGUN_L2 74 */ {32, -40, 70}, /* MZ2_BOSS2_MACHINEGUN_L3 75 */ {32, -40, 70}, /* MZ2_BOSS2_MACHINEGUN_L4 76 */ {32, -40, 70}, /* MZ2_BOSS2_MACHINEGUN_L5 77 */ {32, -40, 70}, /* MZ2_BOSS2_ROCKET_1 78 */ {22.0, 16.0, 10.0}, /* MZ2_BOSS2_ROCKET_2 79 */ {22.0, 8.0, 10.0}, /* MZ2_BOSS2_ROCKET_3 80 */ {22.0, -8.0, 10.0}, /* MZ2_BOSS2_ROCKET_4 81 */ {22.0, -16.0, 10.0}, /* MZ2_FLOAT_BLASTER_1 82 */ {32.5, -0.8, 10}, /* MZ2_SOLDIER_BLASTER_3 83 */ {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_3 84 */ {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_3 85 */ {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, /* MZ2_SOLDIER_BLASTER_4 86 */ {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_4 87 */ {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_4 88 */ {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, /* MZ2_SOLDIER_BLASTER_5 89 */ {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_5 90 */ {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_5 91 */ {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, /* MZ2_SOLDIER_BLASTER_6 92 */ {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_6 93 */ {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_6 94 */ {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, /* MZ2_SOLDIER_BLASTER_7 95 */ {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_7 96 */ {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_7 97 */ {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, /* MZ2_SOLDIER_BLASTER_8 98 */ {31.5 * 1.2, 9.6 * 1.2, 10.1 * 1.2}, /* MZ2_SOLDIER_SHOTGUN_8 99 */ {34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2}, /* MZ2_SOLDIER_MACHINEGUN_8 100 */ {34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2}, /* MZ2_MAKRON_BFG 101 */ {17, -19.5, 62.9}, /* MZ2_MAKRON_BLASTER_1 102 */ {-3.6, -24.1, 59.5}, /* MZ2_MAKRON_BLASTER_2 103 */ {-1.6, -19.3, 59.5}, /* MZ2_MAKRON_BLASTER_3 104 */ {-0.1, -14.4, 59.5}, /* MZ2_MAKRON_BLASTER_4 105 */ {2.0, -7.6, 59.5}, /* MZ2_MAKRON_BLASTER_5 106 */ {3.4, 1.3, 59.5}, /* MZ2_MAKRON_BLASTER_6 107 */ {3.7, 11.1, 59.5}, /* MZ2_MAKRON_BLASTER_7 108 */ {-0.3, 22.3, 59.5}, /* MZ2_MAKRON_BLASTER_8 109 */ {-6, 33, 59.5}, /* MZ2_MAKRON_BLASTER_9 110 */ {-9.3, 36.4, 59.5}, /* MZ2_MAKRON_BLASTER_10 111 */ {-7, 35, 59.5}, /* MZ2_MAKRON_BLASTER_11 112 */ {-2.1, 29, 59.5}, /* MZ2_MAKRON_BLASTER_12 113 */ {3.9, 17.3, 59.5}, /* MZ2_MAKRON_BLASTER_13 114 */ {6.1, 5.8, 59.5}, /* MZ2_MAKRON_BLASTER_14 115 */ {5.9, -4.4, 59.5}, /* MZ2_MAKRON_BLASTER_15 116 */ {4.2, -14.1, 59.5}, /* MZ2_MAKRON_BLASTER_16 117 */ {2.4, -18.8, 59.5}, /* MZ2_MAKRON_BLASTER_17 118 */ {-1.8, -25.5, 59.5}, /* MZ2_MAKRON_RAILGUN_1 119 */ {-17.3, 7.8, 72.4}, /* MZ2_JORG_MACHINEGUN_L1 120 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_L2 121 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_L3 122 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_L4 123 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_L5 124 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_L6 125 */ {78.5, -47.1, 96}, /* MZ2_JORG_MACHINEGUN_R1 126 */ {78.5, 46.7, 96}, /* MZ2_JORG_MACHINEGUN_R2 127 */ {78.5, 46.7, 96}, /* MZ2_JORG_MACHINEGUN_R3 128 */ {78.5, 46.7, 96}, /* MZ2_JORG_MACHINEGUN_R4 129 */ {78.5, 46.7, 96}, /* MZ2_JORG_MACHINEGUN_R5 130 */ {78.5, 46.7, 96}, /* MZ2_JORG_MACHINEGUN_R6 131 */ {78.5, 46.7, 96}, /* MZ2_JORG_BFG_1 132 */ {6.3, -9, 111.2}, /* MZ2_BOSS2_MACHINEGUN_R1 73 */ {32, 40, 70}, /* MZ2_BOSS2_MACHINEGUN_R2 74 */ {32, 40, 70}, /* MZ2_BOSS2_MACHINEGUN_R3 75 */ {32, 40, 70}, /* MZ2_BOSS2_MACHINEGUN_R4 76 */ {32, 40, 70}, /* MZ2_BOSS2_MACHINEGUN_R5 77 */ {32, 40, 70}, /* MZ2_CARRIER_MACHINEGUN_L1 */ {56, -32, 32}, /* MZ2_CARRIER_MACHINEGUN_R1 */ {56, 32, 32}, /* MZ2_CARRIER_GRENADE */ {42, 24, 50}, /* MZ2_TURRET_MACHINEGUN 141 */ {16, 0, 0}, /* MZ2_TURRET_ROCKET 142 */ {16, 0, 0}, /* MZ2_TURRET_BLASTER 143 */ {16, 0, 0}, /* MZ2_STALKER_BLASTER 144 */ {24, 0, 6}, /* MZ2_DAEDALUS_BLASTER 145 */ {32.5, -0.8, 10.0}, /* MZ2_MEDIC_BLASTER_2 146 */ {12.1, 5.4, 16.5}, /* MZ2_CARRIER_RAILGUN 147 */ {32, 0, 6}, /* MZ2_WIDOW_DISRUPTOR 148 */ {57.72, 14.50, 88.81}, /* MZ2_WIDOW_BLASTER 149 */ {56, 32, 32}, /* MZ2_WIDOW_RAIL 150 */ {62, -20, 84}, /* MZ2_WIDOW_PLASMABEAM 151 */ {32, 0, 6}, /* MZ2_CARRIER_MACHINEGUN_L2 152 */ {61, -32, 12}, /* MZ2_CARRIER_MACHINEGUN_R2 153 */ {61, 32, 12}, /* MZ2_WIDOW_RAIL_LEFT 154 */ {17, -62, 91}, /* MZ2_WIDOW_RAIL_RIGHT 155 */ {68, 12, 86}, /* MZ2_WIDOW_BLASTER_SWEEP1 156 */ {47.5, 56, 89}, /* MZ2_WIDOW_BLASTER_SWEEP2 157 */ {54, 52, 91}, /* MZ2_WIDOW_BLASTER_SWEEP3 158 */ {58, 40, 91}, /* MZ2_WIDOW_BLASTER_SWEEP4 159 */ {68, 30, 88}, /* MZ2_WIDOW_BLASTER_SWEEP5 160 */ {74, 20, 88}, /* MZ2_WIDOW_BLASTER_SWEEP6 161 */ {73, 11, 87}, /* MZ2_WIDOW_BLASTER_SWEEP7 162 */ {73, 3, 87}, /* MZ2_WIDOW_BLASTER_SWEEP8 163 */ {70, -12, 87}, /* MZ2_WIDOW_BLASTER_SWEEP9 164 */ {67, -20, 90}, /* MZ2_WIDOW_BLASTER_100 165 */ {-20, 76, 90}, /* MZ2_WIDOW_BLASTER_90 166 */ {-8, 74, 90}, /* MZ2_WIDOW_BLASTER_80 167 */ {0, 72, 90}, /* MZ2_WIDOW_BLASTER_70 168 d06 */ {10, 71, 89}, /* MZ2_WIDOW_BLASTER_60 169 d07 */ {23, 70, 87}, /* MZ2_WIDOW_BLASTER_50 170 d08 */ {32, 64, 85}, /* MZ2_WIDOW_BLASTER_40 171 */ {40, 58, 84}, /* MZ2_WIDOW_BLASTER_30 172 d10 */ {48, 50, 83}, /* MZ2_WIDOW_BLASTER_20 173 */ {54, 42, 82}, /* MZ2_WIDOW_BLASTER_10 174 d12 */ {56, 34, 82}, /* MZ2_WIDOW_BLASTER_0 175 */ {58, 26, 82}, /* MZ2_WIDOW_BLASTER_10L 176 d14 */ {60, 16, 82}, /* MZ2_WIDOW_BLASTER_20L 177 */ {59, 6, 81}, /* MZ2_WIDOW_BLASTER_30L 178 d16 */ {58, -2, 80}, /* MZ2_WIDOW_BLASTER_40L 179 */ {57, -10, 79}, /* MZ2_WIDOW_BLASTER_50L 180 d18 */ {54, -18, 78}, /* MZ2_WIDOW_BLASTER_60L 181 */ {42, -32, 80}, /* MZ2_WIDOW_BLASTER_70L 182 d20 */ {36, -40, 78}, /* MZ2_WIDOW_RUN_1 183 */ {68.4, 10.88, 82.08}, /* MZ2_WIDOW_RUN_2 184 */ {68.51, 8.64, 85.14}, /* MZ2_WIDOW_RUN_3 185 */ {68.66, 6.38, 88.78}, /* MZ2_WIDOW_RUN_4 186 */ {68.73, 5.1, 84.47}, /* MZ2_WIDOW_RUN_5 187 */ {68.82, 4.79, 80.52}, /* MZ2_WIDOW_RUN_6 188 */ {68.77, 6.11, 85.37}, /* MZ2_WIDOW_RUN_7 189 */ {68.67, 7.99, 90.24}, /* MZ2_WIDOW_RUN_8 190 */ {68.55, 9.54, 87.36}, /* MZ2_CARRIER_ROCKET_1 191 */ {0, 0, -5}, /* MZ2_CARRIER_ROCKET_2 192 */ {0, 0, -5}, /* MZ2_CARRIER_ROCKET_3 193 */ {0, 0, -5}, /* MZ2_CARRIER_ROCKET_4 194 */ {0, 0, -5}, /* MZ2_WIDOW2_BEAMER_1 195 */ /* { 72.13, -17.63, 93.77 }, */ {69.00, -17.63, 93.77}, /* MZ2_WIDOW2_BEAMER_2 196 */ /* { 71.46, -17.08, 89.82 }, */ {69.00, -17.08, 89.82}, /* MZ2_WIDOW2_BEAMER_3 197 */ /* { 71.47, -18.40, 90.70 }, */ {69.00, -18.40, 90.70}, /* MZ2_WIDOW2_BEAMER_4 198 */ /* { 71.96, -18.34, 94.32 }, */ {69.00, -18.34, 94.32}, /* MZ2_WIDOW2_BEAMER_5 199 */ /* { 72.25, -18.30, 97.98 }, */ {69.00, -18.30, 97.98}, /* MZ2_WIDOW2_BEAM_SWEEP_1 200 */ {45.04, -59.02, 92.24}, /* MZ2_WIDOW2_BEAM_SWEEP_2 201 */ {50.68, -54.70, 91.96}, /* MZ2_WIDOW2_BEAM_SWEEP_3 202 */ {56.57, -47.72, 91.65}, /* MZ2_WIDOW2_BEAM_SWEEP_4 203 */ {61.75, -38.75, 91.38}, /* MZ2_WIDOW2_BEAM_SWEEP_5 204 */ {65.55, -28.76, 91.24}, /* MZ2_WIDOW2_BEAM_SWEEP_6 205 */ {67.79, -18.90, 91.22}, /* MZ2_WIDOW2_BEAM_SWEEP_7 206 */ {68.60, -9.52, 91.23}, /* MZ2_WIDOW2_BEAM_SWEEP_8 207 */ {68.08, 0.18, 91.32}, /* MZ2_WIDOW2_BEAM_SWEEP_9 208 */ {66.14, 9.79, 91.44}, /* MZ2_WIDOW2_BEAM_SWEEP_10 209 */ {62.77, 18.91, 91.65}, /* MZ2_WIDOW2_BEAM_SWEEP_11 210 */ {58.29, 27.11, 92.00}, /* end of table */ {0.0, 0.0, 0.0} }; rogue-ROGUE_2_13/src/shared/rand.c000066400000000000000000000027411477320066100167410ustar00rootroot00000000000000/* * KISS PRNG (c) 2011 Shinobu * * This file was optained from zuttobenkyou.wordpress.com * and modified by the Yamagi Quake II developers. * * LICENSE: Public domain * * ======================================================================= * * KISS PRNG, as devised by Dr. George Marsaglia * * ======================================================================= */ #include #define QSIZE 0x200000 #define CNG (cng = 6906969069ULL * cng + 13579) #define XS (xs ^= (xs << 13), xs ^= (xs >> 17), xs ^= (xs << 43)) #define KISS (B64MWC() + CNG + XS) static uint64_t QARY[QSIZE]; static int j; static uint64_t carry; static uint64_t xs; static uint64_t cng; uint64_t B64MWC(void) { uint64_t t, x; j = (j + 1) & (QSIZE - 1); x = QARY[j]; t = (x << 28) + carry; carry = (x >> 36) - (t < x); return QARY[j] = t - x; } /* * Generate a pseudorandom * integer >0. */ int randk(void) { int r; r = (int)KISS; r = (r < 0) ? (r * -1) : r; return r; } /* * Generate a pseudorandom * signed float between * 0 and 1. */ float frandk(void) { return (randk()&32767)* (1.0/32767); } /* Generate a pseudorandom * float between -1 and 1. */ float crandk(void) { return (randk()&32767)* (2.0/32767) - 1; } /* * Seeds the PRNG */ void randk_seed(void) { uint64_t i; /* Seed QARY[] with CNG+XS: */ for (i = 0; i < QSIZE; i++) { QARY[i] = CNG + XS; } /* Run through several rounds to warm up the state */ for (i = 0; i < 256; i++) { randk(); } } rogue-ROGUE_2_13/src/shared/shared.c000066400000000000000000000510001477320066100172530ustar00rootroot00000000000000/* * ======================================================================= * * Support functions, linked into client, server, renderer and game. * * ======================================================================= */ #include #include "../header/shared.h" #define DEG2RAD(a) (a * M_PI) / 180.0F vec3_t vec3_origin = {0, 0, 0}; /* ============================================================================ */ void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees) { float m[3][3]; float im[3][3]; float zrot[3][3]; float tmpmat[3][3]; float rot[3][3]; int i; vec3_t vr, vup, vf; vf[0] = dir[0]; vf[1] = dir[1]; vf[2] = dir[2]; PerpendicularVector(vr, dir); CrossProduct(vr, vf, vup); m[0][0] = vr[0]; m[1][0] = vr[1]; m[2][0] = vr[2]; m[0][1] = vup[0]; m[1][1] = vup[1]; m[2][1] = vup[2]; m[0][2] = vf[0]; m[1][2] = vf[1]; m[2][2] = vf[2]; memcpy(im, m, sizeof(im)); im[0][1] = m[1][0]; im[0][2] = m[2][0]; im[1][0] = m[0][1]; im[1][2] = m[2][1]; im[2][0] = m[0][2]; im[2][1] = m[1][2]; memset(zrot, 0, sizeof(zrot)); zrot[1][1] = zrot[2][2] = 1.0F; zrot[0][0] = (float)cos(DEG2RAD(degrees)); zrot[0][1] = (float)sin(DEG2RAD(degrees)); zrot[1][0] = (float)-sin(DEG2RAD(degrees)); zrot[1][1] = (float)cos(DEG2RAD(degrees)); R_ConcatRotations(m, zrot, tmpmat); R_ConcatRotations(tmpmat, im, rot); for (i = 0; i < 3; i++) { dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; } } void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { float angle; static float sr, sp, sy, cr, cp, cy; angle = angles[YAW] * (M_PI * 2 / 360); sy = (float)sin(angle); cy = (float)cos(angle); angle = angles[PITCH] * (M_PI * 2 / 360); sp = (float)sin(angle); cp = (float)cos(angle); angle = angles[ROLL] * (M_PI * 2 / 360); sr = (float)sin(angle); cr = (float)cos(angle); if (forward) { forward[0] = cp * cy; forward[1] = cp * sy; forward[2] = -sp; } if (right) { right[0] = (-1 * sr * sp * cy + - 1 * cr * -sy); right[1] = (-1 * sr * sp * sy + - 1 * cr * cy); right[2] = -1 * sr * cp; } if (up) { up[0] = (cr * sp * cy + - sr * -sy); up[1] = (cr * sp * sy + - sr * cy); up[2] = cr * cp; } } void AngleVectors2(vec3_t value1, vec3_t angles) { float forward; float yaw, pitch; if ((value1[1] == 0) && (value1[0] == 0)) { yaw = 0; if (value1[2] > 0) { pitch = 90; } else { pitch = 270; } } else { if (value1[0]) { yaw = ((float)atan2(value1[1], value1[0]) * 180 / M_PI); } else if (value1[1] > 0) { yaw = 90; } else { yaw = 270; } if (yaw < 0) { yaw += 360; } forward = (float)sqrt(value1[0] * value1[0] + value1[1] * value1[1]); pitch = ((float)atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) { pitch += 360; } } angles[PITCH] = -pitch; angles[YAW] = yaw; angles[ROLL] = 0; } void ProjectPointOnPlane(vec3_t dst, const vec3_t p, const vec3_t normal) { float d; vec3_t n; float inv_denom; inv_denom = 1.0F / DotProduct(normal, normal); d = DotProduct(normal, p) * inv_denom; n[0] = normal[0] * inv_denom; n[1] = normal[1] * inv_denom; n[2] = normal[2] * inv_denom; dst[0] = p[0] - d * n[0]; dst[1] = p[1] - d * n[1]; dst[2] = p[2] - d * n[2]; } /* assumes "src" is normalized */ void PerpendicularVector(vec3_t dst, const vec3_t src) { int pos; int i; float minelem = 1.0F; vec3_t tempvec; /* find the smallest magnitude axially aligned vector */ for (pos = 0, i = 0; i < 3; i++) { if (fabs(src[i]) < minelem) { pos = i; minelem = (float)fabs(src[i]); } } tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; tempvec[pos] = 1.0F; /* project the point onto the plane defined by src */ ProjectPointOnPlane(dst, tempvec, src); /* normalize the result */ VectorNormalize(dst); } void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; } void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3]; out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3]; out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; } /* ============================================================================ */ float Q_fabs(float f) { int tmp = *(int *)&f; tmp &= 0x7FFFFFFF; return *(float *)&tmp; } float LerpAngle(float a2, float a1, float frac) { if (a1 - a2 > 180) { a1 -= 360; } if (a1 - a2 < -180) { a1 += 360; } return a2 + frac * (a1 - a2); } float anglemod(float a) { a = (360.0 / 65536) * ((int)(a * (65536 / 360.0)) & 65535); return a; } /* * This is the slow, general version */ int BoxOnPlaneSide2(vec3_t emins, vec3_t emaxs, struct cplane_s *p) { int i; float dist1, dist2; int sides; vec3_t corners[2]; for (i = 0; i < 3; i++) { if (p->normal[i] < 0) { corners[0][i] = emins[i]; corners[1][i] = emaxs[i]; } else { corners[1][i] = emins[i]; corners[0][i] = emaxs[i]; } } dist1 = DotProduct(p->normal, corners[0]) - p->dist; dist2 = DotProduct(p->normal, corners[1]) - p->dist; sides = 0; if (dist1 >= 0) { sides = 1; } if (dist2 < 0) { sides |= 2; } return sides; } /* * Returns 1, 2, or 1 + 2 */ int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p) { float dist1, dist2; int sides; /* fast axial cases */ if (p->type < 3) { if (p->dist <= emins[p->type]) { return 1; } if (p->dist >= emaxs[p->type]) { return 2; } return 3; } /* general case */ switch (p->signbits) { case 0: dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; break; case 1: dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; break; case 2: dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; break; case 3: dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; break; case 4: dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; break; case 5: dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; break; case 6: dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; break; case 7: dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; break; default: dist1 = dist2 = 0; break; } sides = 0; if (dist1 >= p->dist) { sides = 1; } if (dist2 < p->dist) { sides |= 2; } return sides; } void ClearBounds(vec3_t mins, vec3_t maxs) { mins[0] = mins[1] = mins[2] = 99999; maxs[0] = maxs[1] = maxs[2] = -99999; } void AddPointToBounds(vec3_t v, vec3_t mins, vec3_t maxs) { int i; vec_t val; for (i = 0; i < 3; i++) { val = v[i]; if (val < mins[i]) { mins[i] = val; } if (val > maxs[i]) { maxs[i] = val; } } } int VectorCompare(vec3_t v1, vec3_t v2) { if ((v1[0] != v2[0]) || (v1[1] != v2[1]) || (v1[2] != v2[2])) { return 0; } return 1; } vec_t VectorNormalize(vec3_t v) { float length, ilength; length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; length = (float)sqrt(length); if (length) { ilength = 1 / length; v[0] *= ilength; v[1] *= ilength; v[2] *= ilength; } return length; } vec_t VectorNormalize2(vec3_t v, vec3_t out) { VectorCopy(v, out); return VectorNormalize(out); } void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) { vecc[0] = veca[0] + scale * vecb[0]; vecc[1] = veca[1] + scale * vecb[1]; vecc[2] = veca[2] + scale * vecb[2]; } vec_t _DotProduct(vec3_t v1, vec3_t v2) { return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; } void _VectorSubtract(vec3_t veca, vec3_t vecb, vec3_t out) { out[0] = veca[0] - vecb[0]; out[1] = veca[1] - vecb[1]; out[2] = veca[2] - vecb[2]; } void _VectorAdd(vec3_t veca, vec3_t vecb, vec3_t out) { out[0] = veca[0] + vecb[0]; out[1] = veca[1] + vecb[1]; out[2] = veca[2] + vecb[2]; } void _VectorCopy(vec3_t in, vec3_t out) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross) { cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; } double sqrt(double x); vec_t VectorLength(vec3_t v) { int i; float length; length = 0; for (i = 0; i < 3; i++) { length += v[i] * v[i]; } length = (float)sqrt(length); return length; } void VectorInverse(vec3_t v) { v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; } void VectorScale(vec3_t in, vec_t scale, vec3_t out) { out[0] = in[0] * scale; out[1] = in[1] * scale; out[2] = in[2] * scale; } int Q_log2(int val) { int answer = 0; while (val >>= 1) { answer++; } return answer; } /* ==================================================================================== */ char * COM_SkipPath(char *pathname) { char *last; last = pathname; while (*pathname) { if (*pathname == '/') { last = pathname + 1; } pathname++; } return last; } void COM_StripExtension(char *in, char *out) { while (*in && *in != '.') { *out++ = *in++; } *out = 0; } const char * COM_FileExtension(const char *in) { const char *ext = strrchr(in, '.'); if (!ext || ext == in) { return ""; } return ext + 1; } void COM_FileBase(char *in, char *out) { char *s, *s2; s = in + strlen(in) - 1; while (s != in && *s != '.') { s--; } for (s2 = s; s2 != in && *s2 != '/'; s2--) { } if (s - s2 < 2) { out[0] = 0; } else { s--; strncpy(out, s2 + 1, s - s2); out[s - s2] = 0; } } /* * Returns the path up to, but not including the last / */ void COM_FilePath(const char *in, char *out) { const char *s; s = in + strlen(in) - 1; while (s != in && *s != '/') { s--; } strncpy(out, in, s - in); out[s - in] = 0; } void COM_DefaultExtension(char *path, const char *extension) { char *src; /* */ /* if path doesn't have a .EXT, append extension */ /* (extension should include the .) */ /* */ src = path + strlen(path) - 1; while (*src != '/' && src != path) { if (*src == '.') { return; /* it has an extension */ } src--; } strcat(path, extension); } /* * ============================================================================ * * BYTE ORDER FUNCTIONS * * ============================================================================ */ qboolean bigendien; /* can't just use function pointers, or dll linkage can mess up when qcommon is included in multiple places */ short (*_BigShort)(short l); short (*_LittleShort)(short l); int (*_BigLong)(int l); int (*_LittleLong)(int l); float (*_BigFloat)(float l); float (*_LittleFloat)(float l); short BigShort(short l) { return _BigShort(l); } short LittleShort(short l) { return _LittleShort(l); } int BigLong(int l) { return _BigLong(l); } int LittleLong(int l) { return _LittleLong(l); } float BigFloat(float l) { return _BigFloat(l); } float LittleFloat(float l) { return _LittleFloat(l); } short ShortSwap(short l) { byte b1, b2; b1 = l & 255; b2 = (l >> 8) & 255; return (b1 << 8) + b2; } short ShortNoSwap(short l) { return l; } int LongSwap(int l) { byte b1, b2, b3, b4; b1 = l & 255; b2 = (l >> 8) & 255; b3 = (l >> 16) & 255; b4 = (l >> 24) & 255; return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4; } int LongNoSwap(int l) { return l; } float FloatSwap(float f) { union { float f; byte b[4]; } dat1, dat2; dat1.f = f; dat2.b[0] = dat1.b[3]; dat2.b[1] = dat1.b[2]; dat2.b[2] = dat1.b[1]; dat2.b[3] = dat1.b[0]; return dat2.f; } float FloatNoSwap(float f) { return f; } void Swap_Init(void) { byte swaptest[2] = {1, 0}; /* set the byte swapping variables in a portable manner */ /* PVS NOTE: maybe use memcpy instead? */ if (*(short *)swaptest == 1) { bigendien = false; _BigShort = ShortSwap; _LittleShort = ShortNoSwap; _BigLong = LongSwap; _LittleLong = LongNoSwap; _BigFloat = FloatSwap; _LittleFloat = FloatNoSwap; Com_Printf("Byte ordering: little endian\n\n"); } else { bigendien = true; _BigShort = ShortNoSwap; _LittleShort = ShortSwap; _BigLong = LongNoSwap; _LittleLong = LongSwap; _BigFloat = FloatNoSwap; _LittleFloat = FloatSwap; Com_Printf("Byte ordering: big endian\n\n"); } if (LittleShort(*(short *)swaptest) != 1) assert("Error in the endian conversion!"); } /* * does a varargs printf into a temp buffer, so I don't * need to have varargs versions of all text functions. */ char * va(const char *format, ...) { va_list argptr; static char string[1024]; va_start(argptr, format); vsnprintf(string, 1024, format, argptr); va_end(argptr); return string; } char com_token[MAX_TOKEN_CHARS]; /* * Parse a token out of a string */ char * COM_Parse(char **data_p) { int c; int len; char *data; data = *data_p; len = 0; com_token[0] = 0; if (!data) { *data_p = NULL; return ""; } skipwhite: while ((c = *data) <= ' ') { if (c == 0) { *data_p = NULL; return ""; } data++; } /* skip // comments */ if ((c == '/') && (data[1] == '/')) { while (*data && *data != '\n') { data++; } goto skipwhite; } /* handle quoted strings specially */ if (c == '\"') { data++; while (1) { c = *data++; if ((c == '\"') || !c) { com_token[len] = 0; *data_p = data; return com_token; } if (len < MAX_TOKEN_CHARS) { com_token[len] = c; len++; } } } /* parse a regular word */ do { if (len < MAX_TOKEN_CHARS) { com_token[len] = c; len++; } data++; c = *data; } while (c > 32); if (len == MAX_TOKEN_CHARS) { len = 0; } com_token[len] = 0; *data_p = data; return com_token; } int paged_total; void Com_PageInMemory(byte *buffer, int size) { int i; for (i = size - 1; i > 0; i -= 4096) { paged_total += buffer[i]; } } /* * ============================================================================ * * LIBRARY REPLACEMENT FUNCTIONS * * ============================================================================ */ int Q_stricmp(const char *s1, const char *s2) { return strcasecmp(s1, s2); } int Q_strncasecmp(char *s1, char *s2, int n) { int c1, c2; do { c1 = *s1++; c2 = *s2++; if (!n--) { return 0; /* strings are equal until end point */ } if (c1 != c2) { if ((c1 >= 'a') && (c1 <= 'z')) { c1 -= ('a' - 'A'); } if ((c2 >= 'a') && (c2 <= 'z')) { c2 -= ('a' - 'A'); } if (c1 != c2) { return -1; /* strings not equal */ } } } while (c1); return 0; /* strings are equal */ } int Q_strcasecmp(char *s1, char *s2) { return Q_strncasecmp(s1, s2, 99999); } void Com_sprintf(char *dest, int size, char *fmt, ...) { int len; va_list argptr; static char bigbuffer[0x10000]; va_start(argptr, fmt); len = vsnprintf(bigbuffer, 0x10000, fmt, argptr); va_end(argptr); if (len >= size) { Com_Printf("Com_sprintf: overflow\n"); dest = NULL; return; } bigbuffer[size - 1] = '\0'; strcpy(dest, bigbuffer); } char * strlwr ( char *s ) { char *p = s; while ( *s ) { *s = tolower( *s ); s++; } return ( p ); } int Q_strlcpy(char *dst, const char *src, int size) { const char *s = src; while (*s) { if (size > 1) { *dst++ = *s; size--; } s++; } if (size > 0) { *dst = '\0'; } return s - src; } int Q_strlcat(char *dst, const char *src, int size) { char *d = dst; while (size > 0 && *d) { size--; d++; } return (d - dst) + Q_strlcpy(d, src, size); } /* * ===================================================================== * * INFO STRINGS * * ===================================================================== */ /* * Searches the string for the given * key and returns the associated value, * or an empty string. */ char * Info_ValueForKey(char *s, char *key) { char pkey[512]; static char value[2][512]; /* use two buffers so compares work without stomping on each other */ static int valueindex; char *o; valueindex ^= 1; if (*s == '\\') { s++; } while (1) { o = pkey; while (*s != '\\') { if (!*s) { return ""; } *o++ = *s++; } *o = 0; s++; o = value[valueindex]; while (*s != '\\' && *s) { if (!*s) { return ""; } *o++ = *s++; } *o = 0; if (!strcmp(key, pkey)) { return value[valueindex]; } if (!*s) { return ""; } s++; } } void Info_RemoveKey(char *s, char *key) { char *start; char pkey[512]; char value[512]; char *o; if (strstr(key, "\\")) { return; } while (1) { start = s; if (*s == '\\') { s++; } o = pkey; while (*s != '\\') { if (!*s) { return; } *o++ = *s++; } *o = 0; s++; o = value; while (*s != '\\' && *s) { if (!*s) { return; } *o++ = *s++; } *o = 0; if (!strcmp(key, pkey)) { memmove(start, s, strlen(s) + 1); /* remove this part */ return; } if (!*s) { return; } } } /* * Some characters are illegal in info strings * because they can mess up the server's parsing */ qboolean Info_Validate(char *s) { if (strstr(s, "\"")) { return false; } if (strstr(s, ";")) { return false; } return true; } void Info_SetValueForKey(char *s, char *key, char *value) { char newi[MAX_INFO_STRING], *v; int c; int maxsize = MAX_INFO_STRING; if (strstr(key, "\\") || strstr(value, "\\")) { Com_Printf("Can't use keys or values with a \\\n"); return; } if (strstr(key, ";")) { Com_Printf("Can't use keys or values with a semicolon\n"); return; } if (strstr(key, "\"") || strstr(value, "\"")) { Com_Printf("Can't use keys or values with a \"\n"); return; } if ((strlen(key) > MAX_INFO_KEY - 1) || (strlen(value) > MAX_INFO_KEY - 1)) { Com_Printf("Keys and values must be < 64 characters.\n"); return; } Info_RemoveKey(s, key); if (*value == '\0') { return; } Com_sprintf(newi, sizeof(newi), "\\%s\\%s", key, value); if (strlen(newi) + strlen(s) >= maxsize) { Com_Printf("Info string length exceeded\n"); return; } /* only copy ascii values */ s += strlen(s); v = newi; while (*v) { c = *v++; c &= 127; /* strip high bits */ if ((c >= 32) && (c < 127)) { *s++ = c; } } *s = 0; } rogue-ROGUE_2_13/stuff/000077500000000000000000000000001477320066100147375ustar00rootroot00000000000000rogue-ROGUE_2_13/stuff/mapfixes/000077500000000000000000000000001477320066100165535ustar00rootroot00000000000000rogue-ROGUE_2_13/stuff/mapfixes/rammo1.ent000066400000000000000000002713171477320066100204720ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Fixed unreachable monster_soldier (2803) // // He is triggered spawn but has no targetname. Gave him // targetname t153, so he triggers when you return from rammo2. // // 2. Removed target-less trigger_relay (2423) // // Changed its spawnflags from 2048 to 7936 (never spawns). // // 3. Removed target-less trigger_once (2401) // // Changed its spawnflags from 2048 to 7936 (never spawns). { "sounds" "2" "sky" "rogue2" "nextmap" "rammo2" "message" "Munitions Plant" "classname" "worldspawn" } { "classname" "info_player_coop" "angle" "270" "origin" "-592 -744 1448" } { "angle" "270" "classname" "info_player_coop" "origin" "-624 -708 1448" } { "classname" "info_player_coop" "angle" "270" "origin" "-592 -664 1448" } { "spawnflags" "1536" "classname" "item_health_large" "origin" "-488 -896 1424" } { "classname" "item_health_large" "spawnflags" "1024" "origin" "-488 -856 1424" } { "classname" "func_timer" "target" "t237" "wait" "5" "random" "2.5" "targetname" "t108" "origin" "512 -464 1760" } { "classname" "target_splash" "angle" "90" "targetname" "t237" "origin" "552 -448 1760" } { "model" "*1" "classname" "func_explosive" "dmg" "100" "health" "5" } { "targetname" "lasers" "spawnflags" "1" "classname" "target_speaker" "noise" "world/fan1.wav" "origin" "-1792 144 1568" } { "origin" "-1920 152 1544" "targetname" "t236" "spawnflags" "1" "classname" "point_combat" } { "origin" "-1792 288 1856" "classname" "misc_explobox" } { "targetname" "t235" "classname" "target_explosion" "origin" "-352 1336 928" } { "targetname" "t235" "origin" "-360 1272 876" "classname" "target_explosion" } { "targetname" "lasers" "origin" "-1952 120 1568" "noise" "world/lasoff1.wav" "classname" "target_speaker" } { "targetname" "lasers" "origin" "-1744 144 1568" "noise" "world/lasoff1.wav" "classname" "target_speaker" } { "targetname" "lasers" "classname" "target_speaker" "noise" "world/lasoff1.wav" "origin" "-1152 104 1568" } { "targetname" "lasers" "classname" "target_speaker" "noise" "world/lasoff1.wav" "origin" "-1952 128 1624" } { "targetname" "lasers" "classname" "target_speaker" "noise" "world/lasoff1.wav" "origin" "-1832 144 1568" } { "origin" "-1152 112 1608" "targetname" "lasers" "noise" "world/lasoff1.wav" "classname" "target_speaker" } { "targetname" "lasers" "spawnflags" "0" "origin" "-1768 80 1568" "random" "2" "wait" "4" "target" "t234" "classname" "func_timer" } { "origin" "-1780 104 1568" "dmg" "5" "sounds" "1" "targetname" "t234" "angle" "135" "classname" "target_splash" } { "classname" "func_group" } { "model" "*2" "spawnflags" "5888" "target" "t233" "classname" "trigger_once" } { "model" "*3" "spawnflags" "5888" "target" "t233" "classname" "trigger_once" } { "origin" "-888 1272 1016" "angle" "315" "classname" "info_player_deathmatch" } { "model" "*4" "target" "t233" "classname" "trigger_once" "spawnflags" "5888" } { "model" "*5" "target" "t233" "spawnflags" "5888" "classname" "trigger_once" } { "model" "*6" "spawnflags" "5888" "target" "t233" "classname" "trigger_once" } { "model" "*7" "targetname" "t233" "target" "t153" "spawnflags" "5888" "classname" "trigger_once" } { "origin" "-624 -708 1448" "targetname" "unitstart" "classname" "info_player_coop" "angle" "270" } { "origin" "-592 -744 1448" "angle" "270" "targetname" "unitstart" "classname" "info_player_coop" } { "origin" "-592 -664 1448" "targetname" "unitstart" "angle" "270" "classname" "info_player_coop" } { "targetname" "t167" "message" "Use Anti-matter Bomb\nto destroy Gravity Well." "origin" "920 616 1528" "spawnflags" "2049" "classname" "target_help" } { "origin" "-1192 -332 1624" "targetname" "t143" "spawnflags" "256" "target" "t142" "angle" "180" "classname" "monster_gunner" } { "model" "*8" "target" "t232" "spawnflags" "256" "classname" "trigger_once" } { "origin" "1048 -104 1496" "targetname" "t232" "spawnflags" "257" "angle" "180" "classname" "monster_gunner" } { "targetname" "t153" "origin" "408 376 1624" "angle" "315" "spawnflags" "770" "classname" "monster_gunner" } { "origin" "-960 1696 880" "spawnflags" "5888" "classname" "ammo_shells" } { "origin" "-968 1800 912" "spawnflags" "5888" "classname" "weapon_supershotgun" } { "origin" "-608 -712 1440" "spawnflags" "5888" "classname" "weapon_heatbeam" } { "origin" "-1056 -352 1616" "spawnflags" "5888" "classname" "weapon_chainfist" } { "origin" "-1184 704 1552" "spawnflags" "5888" "classname" "item_double" } { "angle" "90" "origin" "-736 928 1008" "spawnflags" "5888" "classname" "item_health_mega" } { "origin" "376 536 1488" "spawnflags" "5888" "classname" "ammo_slugs" } { "origin" "928 352 1488" "spawnflags" "5888" "classname" "ammo_cells" } { "origin" "888 288 1496" "spawnflags" "5888" "classname" "weapon_hyperblaster" } { "origin" "608 1568 1496" "target" "t231" "spawnflags" "5888" "classname" "misc_teleporter" } { "origin" "152 104 1872" "spawnflags" "5888" "classname" "ammo_grenades" } { "origin" "224 -224 1872" "spawnflags" "5888" "classname" "weapon_grenadelauncher" } { "origin" "-488 -232 1360" "spawnflags" "5888" "classname" "ammo_flechettes" } { "origin" "-1376 -64 1560" "targetname" "t230" "angle" "0" "spawnflags" "5888" "classname" "misc_teleporter_dest" } { "angle" "270" "origin" "-736 2592 844" "target" "t230" "spawnflags" "5888" "classname" "misc_teleporter" } { "origin" "-736 2784 836" "classname" "ammo_nuke" } { "angle" "90" "origin" "-736 1872 884" "target" "t229" "spawnflags" "5888" "classname" "misc_teleporter" } { "origin" "832 -480 1768" "spawnflags" "5888" "classname" "item_sphere_defender" } { "angle" "0" "targetname" "t231" "origin" "160 896 1656" "spawnflags" "5888" "classname" "misc_teleporter_dest" } { "origin" "768 896 1648" "spawnflags" "5888" "classname" "item_sphere_hunter" } { "model" "*9" "spawnflags" "5888" "classname" "func_water" } { "origin" "-432 -280 1360" "spawnflags" "5888" "classname" "weapon_etf_rifle" } { "origin" "-736 1288 1008" "spawnflags" "5888" "classname" "weapon_bfg" } { "origin" "-1664 632 1872" "spawnflags" "5888" "classname" "weapon_railgun" } { "origin" "-2016 224 1552" "spawnflags" "5888" "classname" "ammo_shells" } { "origin" "-2016 288 1552" "spawnflags" "5888" "classname" "weapon_supershotgun" } { "angle" "180" "classname" "info_player_deathmatch" "origin" "832 288 1624" } { "origin" "-1056 -224 1560" "classname" "info_player_deathmatch" "angle" "90" } { "origin" "952 -328 1768" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "-864 -1056 1624" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "608 568 1496" } { "angle" "90" "classname" "info_player_deathmatch" "origin" "-288 -1184 1432" } { "angle" "45" "classname" "info_player_deathmatch" "origin" "288 -256 1768" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "-224 -288 1368" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "-1504 288 1560" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "-1632 288 1880" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "-1184 -224 1880" } { "origin" "-384 1504 888" "classname" "info_player_deathmatch" "angle" "180" } { "origin" "-544 480 1368" "classname" "info_player_deathmatch" "angle" "0" } { "origin" "480 96 1624" "classname" "info_player_deathmatch" "angle" "0" } { "origin" "-608 -632 1448" "classname" "info_player_deathmatch" "angle" "270" } { "origin" "96 800 1592" "angle" "315" "classname" "info_player_deathmatch" } { "origin" "-224 -936 1616" "spawnflags" "5888" "classname" "ammo_cells" } { "model" "*10" "spawnflags" "5888" "classname" "func_wall" } { "model" "*11" "spawnflags" "5888" "classname" "func_wall" } { "model" "*12" "spawnflags" "2048" "classname" "func_wall" } { "targetname" "t229" "angle" "270" "origin" "-736 2944 844" "spawnflags" "5888" "classname" "misc_teleporter_dest" } { "origin" "-744 2776 984" "classname" "light" } { "model" "*13" "spawnflags" "5888" "classname" "func_wall" } { "model" "*14" "spawnflags" "2048" "classname" "func_wall" } { "model" "*15" "spawnflags" "2048" "classname" "func_wall" } { "origin" "1120 -312 1760" "spawnflags" "5888" "classname" "ammo_rockets" } { "model" "*16" "spawnflags" "2048" "classname" "func_wall" } { "classname" "light" "origin" "704 -480 1808" "light" "125" "spawnflags" "5888" } { "classname" "light" "origin" "832 -480 1808" "light" "125" "spawnflags" "5888" } { "spawnflags" "5888" "light" "125" "origin" "576 -480 1808" "classname" "light" } { "origin" "576 -480 1768" "spawnflags" "5888" "classname" "item_bandolier" } { "model" "*17" "spawnflags" "5888" "classname" "func_wall" } { "model" "*18" "classname" "func_wall" "spawnflags" "5888" } { "model" "*19" "spawnflags" "5888" "classname" "func_wall" } { "model" "*20" "spawnflags" "2048" "classname" "func_wall" } { "model" "*21" "spawnflags" "2048" "classname" "func_wall" } { "origin" "-1376 -640 1624" "angle" "270" "spawnflags" "771" "targetname" "t1" "classname" "monster_parasite" } { "spawnflags" "2048" "origin" "-624 -616 1448" "angle" "270" "targetname" "unitstart" "classname" "info_player_start" } { "origin" "224 -256 1880" "item" "ammo_grenades" "angle" "135" "spawnflags" "3" "targetname" "t153" "classname" "monster_gunner" } { "spawnflags" "1" "angle" "90" "classname" "monster_daedalus" "origin" "-1376 -168 1936" } { "origin" "160 896 1808" "classname" "monster_daedalus" "angle" "270" "spawnflags" "1" } { "item" "ammo_cells" "origin" "-224 544 1560" "targetname" "t228" "spawnflags" "769" "angle" "180" "classname" "monster_daedalus" } { "model" "*22" "spawnflags" "2816" "classname" "func_wall" } { "origin" "704 1072 1552" "classname" "item_armor_combat" } { "angles" "-20 135 0" "origin" "-96 352 1376" "classname" "info_player_intermission" } { "origin" "-1112 1152 1024" "target" "t227" "spawnflags" "2048" "targetname" "t226" "classname" "hint_path" } { "origin" "-1104 1560 896" "targetname" "t227" "spawnflags" "2049" "classname" "hint_path" } { "origin" "-712 1152 1024" "target" "t226" "spawnflags" "2049" "classname" "hint_path" } { "target" "t224" "targetname" "t223" "spawnflags" "2048" "classname" "hint_path" "origin" "352 -96 1632" } { "target" "t225" "targetname" "t224" "spawnflags" "2048" "classname" "hint_path" "origin" "1048 -104 1504" } { "targetname" "t225" "spawnflags" "2049" "classname" "hint_path" "origin" "1064 328 1504" } { "target" "t223" "origin" "440 336 1632" "classname" "hint_path" "spawnflags" "2049" } { "target" "t217" "targetname" "t216" "origin" "704 64 1640" "classname" "hint_path" "spawnflags" "2048" } { "target" "t218" "targetname" "t217" "origin" "1040 56 1640" "classname" "hint_path" "spawnflags" "2048" } { "target" "t219" "targetname" "t218" "origin" "1056 -168 1640" "classname" "hint_path" "spawnflags" "2048" } { "target" "t220" "targetname" "t219" "origin" "360 -144 1760" "classname" "hint_path" "spawnflags" "2048" } { "target" "t221" "targetname" "t220" "origin" "376 64 1824" "classname" "hint_path" "spawnflags" "2048" } { "target" "t222" "targetname" "t221" "origin" "160 -32 1872" "classname" "hint_path" "spawnflags" "2048" } { "targetname" "t222" "origin" "-480 -32 1872" "classname" "hint_path" "spawnflags" "2049" } { "target" "t213" "targetname" "t212" "spawnflags" "2048" "classname" "hint_path" "origin" "-552 200 1872" } { "target" "t216" "spawnflags" "2049" "classname" "hint_path" "origin" "680 336 1640" } { "targetname" "t213" "spawnflags" "2049" "classname" "hint_path" "origin" "-512 -24 1872" } { "target" "t214" "spawnflags" "2049" "classname" "hint_path" "origin" "-512 -40 1872" } { "target" "t215" "targetname" "t214" "origin" "-536 -288 1872" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t215" "origin" "-1072 -304 1872" "spawnflags" "2049" "classname" "hint_path" } { "target" "t212" "origin" "-1928 240 1872" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-1952 -272 1872" "target" "t209" "targetname" "t208" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1960 -184 1568" "target" "t210" "targetname" "t209" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1984 224 1560" "target" "t211" "targetname" "t210" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1184 208 1560" "targetname" "t211" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-1064 -288 1872" "target" "t208" "spawnflags" "2049" "classname" "hint_path" } { "target" "t207" "targetname" "t206" "origin" "-320 816 1376" "classname" "hint_path" "spawnflags" "2048" } { "targetname" "t207" "origin" "-320 440 1376" "classname" "hint_path" "spawnflags" "2049" } { "target" "t206" "spawnflags" "1" "classname" "hint_path" "origin" "-320 1136 1376" } { "targetname" "t205" "origin" "616 688 1504" "classname" "hint_path" "spawnflags" "2049" } { "target" "t205" "spawnflags" "2049" "classname" "hint_path" "origin" "608 1144 1504" } { "origin" "168 576 1504" "target" "t203" "targetname" "t202" "spawnflags" "2048" "classname" "hint_path" } { "origin" "152 -144 1376" "target" "t204" "targetname" "t203" "spawnflags" "2048" "classname" "hint_path" } { "origin" "-112 -136 1376" "targetname" "t204" "spawnflags" "2049" "classname" "hint_path" } { "origin" "664 696 1504" "target" "t202" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-160 448 1376" "target" "t199" "targetname" "t198" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-464 456 1376" "target" "t200" "targetname" "t199" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-528 -104 1376" "target" "t201" "targetname" "t200" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-160 -136 1376" "target" "t198" "spawnflags" "2049" "classname" "hint_path" } { "origin" "-1344 -88 1576" "targetname" "t201" "spawnflags" "2049" "classname" "hint_path" } { "origin" "-1664 -72 1576" "target" "t193" "targetname" "t192" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1664 -320 1616" "target" "t194" "targetname" "t193" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1376 -320 1640" "target" "t195" "targetname" "t194" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1376 -832 1640" "target" "t196" "targetname" "t195" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-800 -832 1640" "targetname" "t196" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-1344 -64 1576" "target" "t192" "spawnflags" "2049" "classname" "hint_path" } { "pathtarget" "medic" "spawnflags" "2049" "origin" "608 728 1480" "targetname" "t162" "classname" "point_combat" } { "classname" "item_health_large" "origin" "-88 -360 1360" } { "classname" "item_health_large" "origin" "-424 224 1360" } { "origin" "-1144 1856 880" "classname" "item_health" } { "origin" "-1096 1856 880" "classname" "item_health" } { "spawnflags" "2048" "origin" "-392 1320 872" "targetname" "t191" "classname" "target_secret" } { "model" "*23" "spawnflags" "2048" "message" "You found a secret!" "target" "t191" "classname" "trigger_once" } { "origin" "-320 1272 880" "classname" "item_armor_body" } { "origin" "-320 1352 880" "classname" "item_power_shield" } { "model" "*24" "target" "t235" "spawnflags" "2048" "health" "1" "classname" "func_explosive" } { "origin" "-392 1672 880" "classname" "item_armor_shard" } { "origin" "-392 1712 880" "classname" "item_armor_shard" } { "origin" "-392 1752 880" "classname" "item_armor_shard" } { "origin" "-392 1632 880" "classname" "item_armor_shard" } { "origin" "-912 1056 1008" "classname" "item_health_large" } { "origin" "-872 1056 1008" "classname" "item_health_large" } { "origin" "-960 1352 880" "classname" "ammo_slugs" } { "origin" "-1152 1120 1008" "classname" "ammo_rockets" } { "origin" "-832 1320 1008" "classname" "ammo_prox" } { "origin" "-552 1248 1008" "classname" "ammo_flechettes" } { "origin" "-936 1232 1008" "classname" "ammo_cells" } { "targetname" "t153" "spawnflags" "1" "origin" "-272 856 1392" "classname" "ammo_tesla" } { "volume" ".5" "spawnflags" "1" "classname" "target_speaker" "origin" "1128 288 1512" "noise" "world/comp_hum2.wav" } { "volume" ".5" "spawnflags" "1" "classname" "target_speaker" "origin" "1056 400 1512" "noise" "world/comp_hum3.wav" } { "noise" "world/comp_hum1.wav" "origin" "912 288 1512" "classname" "target_speaker" "spawnflags" "2049" "volume" ".5" } { "noise" "world/comp_hum2.wav" "origin" "576 272 1632" "classname" "target_speaker" "spawnflags" "1" "volume" ".5" } { "noise" "world/comp_hum3.wav" "origin" "296 320 1672" "classname" "target_speaker" "spawnflags" "1" "volume" ".5" } { "noise" "world/train1.wav" "origin" "1120 -480 1760" "classname" "target_speaker" "spawnflags" "2049" "volume" ".25" } { "noise" "world/train1.wav" "origin" "896 -328 1760" "classname" "target_speaker" "spawnflags" "2049" "volume" ".25" } { "noise" "world/train1.wav" "origin" "512 -328 1760" "classname" "target_speaker" "spawnflags" "2049" "volume" ".25" } { "noise" "world/train1.wav" "origin" "160 -416 1760" "classname" "target_speaker" "spawnflags" "2049" "volume" ".25" } { "spawnflags" "2048" "targetname" "red1" "noise" "world/land.wav" "origin" "576 -424 1800" "classname" "target_speaker" } { "spawnflags" "2048" "targetname" "red2" "classname" "target_speaker" "origin" "704 -424 1800" "noise" "world/land.wav" } { "volume" ".5" "spawnflags" "2049" "classname" "target_speaker" "origin" "608 480 1624" "noise" "world/comp_hum1.wav" } { "spawnflags" "2048" "targetname" "red3" "noise" "world/land.wav" "origin" "832 -424 1800" "classname" "target_speaker" } { "spawnflags" "1" "targetname" "t153" "origin" "680 480 1616" "classname" "ammo_bullets" } { "origin" "840 -64 1528" "classname" "item_armor_shard" } { "origin" "880 -64 1520" "classname" "item_armor_shard" } { "origin" "800 -64 1536" "classname" "item_armor_shard" } { "origin" "1072 384 1472" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "targetname" "t153" "spawnflags" "1" "origin" "1120 352 1488" "classname" "item_silencer" } { "origin" "1120 48 1632" "classname" "item_health" } { "origin" "1120 96 1632" "classname" "item_health" } { "targetname" "t153" "spawnflags" "1" "origin" "352 320 1616" "classname" "weapon_chaingun" } { "origin" "304 336 1600" "spawnflags" "2052" "classname" "misc_deadsoldier" } { "origin" "608 32 1616" "classname" "ammo_flechettes" } { "origin" "496 32 1616" "classname" "weapon_nailgun" } { "origin" "496 96 1600" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "1104 96 1488" "classname" "item_health" } { "origin" "1104 48 1488" "classname" "item_health" } { "origin" "992 -288 1632" "classname" "ammo_grenades" } { "origin" "1120 -352 1632" "classname" "item_armor_combat" } { "origin" "288 -128 1760" "classname" "ammo_rockets" } { "origin" "1120 -224 1760" "classname" "item_health_large" } { "origin" "576 -224 1760" "classname" "item_health_small" } { "origin" "528 -224 1760" "classname" "item_health_small" } { "origin" "480 -224 1760" "classname" "item_health_small" } { "origin" "624 -224 1760" "classname" "item_health_small" } { "origin" "96 96 1872" "classname" "ammo_bullets" } { "origin" "96 -352 1936" "classname" "item_ir_goggles" } { "origin" "-32 -72 1872" "classname" "ammo_flechettes" } { "origin" "-352 8 1872" "classname" "ammo_prox" } { "targetname" "t153" "spawnflags" "1" "origin" "-1400 152 1872" "classname" "ammo_tesla" } { "spawnflags" "1" "targetname" "t153" "origin" "-1736 160 1872" "classname" "item_armor_shard" } { "spawnflags" "1" "targetname" "t153" "origin" "-1776 160 1872" "classname" "item_armor_shard" } { "spawnflags" "1" "targetname" "t153" "origin" "-1816 160 1872" "classname" "item_armor_shard" } { "classname" "ammo_cells" "origin" "-1400 296 1552" } { "targetname" "t153" "spawnflags" "1" "classname" "item_health_large" "origin" "-1768 296 1552" } { "targetname" "t153" "spawnflags" "1" "classname" "item_health" "origin" "-1728 296 1552" } { "origin" "-640 264 1872" "classname" "item_health_large" } { "origin" "-688 264 1872" "classname" "item_health_large" } { "origin" "-544 -328 1872" "classname" "item_health_small" } { "origin" "-584 -328 1872" "classname" "item_health_small" } { "targetname" "t153" "spawnflags" "1" "origin" "-624 -328 1872" "classname" "item_health_small" } { "origin" "-504 -328 1872" "classname" "item_health_small" } { "targetname" "t153" "spawnflags" "1" "origin" "-1008 -224 1872" "classname" "ammo_prox" } { "targetname" "t153" "spawnflags" "1" "origin" "-1120 -320 1872" "classname" "weapon_proxlauncher" } { "origin" "-1056 -352 1856" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "model" "*25" "spawnflags" "2048" "target" "t190" "message" "Secondary Ammo Depot entrance opened." "wait" "-1" "angle" "90" "classname" "func_button" } { "targetname" "t153" "spawnflags" "1" "origin" "-1824 -352 1872" "classname" "item_health" } { "targetname" "t153" "origin" "-1384 -216 1872" "classname" "item_health" } { "targetname" "t153" "spawnflags" "1" "origin" "-1728 296 1872" "classname" "item_health" } { "targetname" "t153" "spawnflags" "1" "origin" "-1768 296 1872" "classname" "item_health_large" } { "targetname" "t153" "origin" "-2008 -344 1936" "classname" "ammo_prox" } { "targetname" "t153" "spawnflags" "1" "origin" "-2024 32 1552" "classname" "ammo_slugs" } { "targetname" "t153" "spawnflags" "1" "origin" "-1400 296 1872" "classname" "ammo_cells" } { "origin" "-1200 152 1552" "classname" "item_armor_shard" } { "origin" "-1248 152 1552" "classname" "item_armor_shard" } { "origin" "-1152 152 1552" "classname" "item_armor_shard" } { "origin" "-992 240 1584" "classname" "item_adrenaline" } { "origin" "496 1272 1488" "classname" "ammo_grenades" } { "origin" "496 1320 1488" "classname" "ammo_grenades" } { "origin" "712 1304 1488" "classname" "ammo_tesla" } { "origin" "712 1168 1488" "classname" "item_health_large" } { "origin" "1128 640 1488" "classname" "item_health" } { "origin" "1128 592 1488" "classname" "item_health_large" } { "origin" "864 472 1488" "classname" "ammo_prox" } { "origin" "552 560 1488" "classname" "ammo_flechettes" } { "origin" "272 808 1488" "classname" "ammo_cells" } { "origin" "320 808 1488" "classname" "ammo_cells" } { "origin" "320 480 1488" "classname" "weapon_railgun" } { "origin" "88 320 1460" "classname" "item_health_small" } { "origin" "88 368 1472" "classname" "item_health_small" } { "origin" "88 416 1488" "classname" "item_health_small" } { "origin" "88 272 1444" "classname" "item_health_small" } { "origin" "224 -160 1360" "classname" "ammo_bullets" } { "origin" "224 -112 1360" "classname" "ammo_bullets" } { "origin" "-96 560 1360" "classname" "ammo_prox" } { "origin" "-552 568 1360" "classname" "ammo_nails" } { "origin" "-216 -352 1360" "classname" "ammo_tesla" } { "origin" "-216 -104 1360" "classname" "ammo_shells" } { "origin" "-96 128 1360" "classname" "item_armor_shard" } { "origin" "-96 176 1360" "classname" "item_armor_shard" } { "origin" "-96 80 1360" "classname" "item_armor_shard" } { "origin" "-96 224 1360" "classname" "item_armor_shard" } { "classname" "item_health_large" "origin" "-424 288 1360" } { "targetname" "t153" "spawnflags" "2049" "origin" "-360 1016 1392" "classname" "weapon_bfg" } { "origin" "-352 968 1376" "spawnflags" "2056" "classname" "misc_deadsoldier" } { "targetname" "t153" "spawnflags" "1" "origin" "-400 1104 1392" "classname" "item_health_small" } { "targetname" "t153" "spawnflags" "1" "origin" "-400 1200 1392" "classname" "item_health_small" } { "targetname" "t153" "spawnflags" "1" "origin" "-240 1200 1392" "classname" "item_health_small" } { "targetname" "t153" "spawnflags" "1" "origin" "-240 1104 1392" "classname" "item_health_small" } { "origin" "-136 -360 1360" "classname" "item_health_large" } { "origin" "-544 -352 1424" "classname" "item_pack" } { "origin" "-320 504 1360" "classname" "weapon_rocketlauncher" } { "origin" "-496 32 1344" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "spawnflags" "2048" "origin" "-536 8 1360" "classname" "weapon_supershotgun" } { "origin" "-304 464 1344" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "-992 -168 1524" "classname" "item_health" } { "origin" "-944 -168 1508" "classname" "item_health" } { "origin" "-1072 48 1536" "angle" "270" "spawnflags" "2052" "classname" "misc_deadsoldier" } { "origin" "-1120 48 1552" "classname" "item_armor_shard" } { "origin" "-1032 32 1552" "classname" "item_armor_shard" } { "origin" "-1088 16 1552" "classname" "item_armor_shard" } { "origin" "-1688 -168 1584" "classname" "ammo_grenades" } { "origin" "-1000 72 1552" "classname" "ammo_bullets" } { "origin" "-1696 72 1552" "classname" "ammo_slugs" } { "spawnflags" "2048" "origin" "-1440 -280 1616" "classname" "item_armor_combat" } { "origin" "-1480 -280 1600" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "origin" "-1080 -280 1616" "classname" "item_health_small" } { "origin" "-1112 -280 1616" "classname" "item_health_small" } { "origin" "-1144 -280 1616" "classname" "item_health_small" } { "origin" "-1408 -592 1616" "classname" "item_health" } { "origin" "-1408 -544 1616" "classname" "item_health_large" } { "targetname" "t1" "spawnflags" "1" "origin" "-1128 -800 1616" "classname" "ammo_nails" } { "targetname" "t1" "spawnflags" "1" "origin" "-1184 -800 1616" "classname" "ammo_nails" } { "origin" "-32 -1128 1616" "classname" "ammo_prox" } { "origin" "-864 -608 1616" "classname" "ammo_tesla" } { "style" "32" "spawnflags" "2048" "origin" "-1792 112 1568" "targetname" "lasers" "_color" "1.000000 0.000000 0.000000" "light" "150" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1792 160 1608" } { "classname" "light" "light" "100" "origin" "-1880 0 1592" } { "origin" "-120 -1008 1616" "classname" "weapon_hyperblaster" } { "spawnflags" "2048" "origin" "-88 -1048 1600" "classname" "misc_deadsoldier" } { "spawnflags" "2048" "origin" "-800 -496 1616" "classname" "weapon_heatbeam" } { "origin" "-848 -464 1600" "angle" "270" "spawnflags" "2064" "classname" "misc_deadsoldier" } { "origin" "-544 -472 1616" "classname" "item_armor_shard" } { "origin" "-592 -472 1616" "classname" "item_armor_shard" } { "origin" "-640 -472 1616" "classname" "item_armor_shard" } { "origin" "-496 -472 1616" "classname" "item_armor_shard" } { "origin" "-112 -784 1488" "classname" "ammo_rockets" } { "origin" "-56 -920 1424" "classname" "item_health" } { "origin" "-96 -920 1424" "classname" "item_health" } { "origin" "-488 -1048 1424" "classname" "item_health_large" } { "origin" "608 1360 1736" "classname" "light" "light" "100" } { "origin" "-32 -928 1488" "light" "75" "classname" "light" } { "targetname" "t153" "item" "ammo_bullets" "origin" "-216 796 1400" "spawnflags" "259" "classname" "monster_soldier_ss" "angle" "180" } { "targetname" "t153" "item" "ammo_bullets" "origin" "-424 796 1400" "spawnflags" "771" "angle" "0" "classname" "monster_soldier_ss" } { "spawnflags" "2048" "targetname" "t189" "classname" "target_help" "origin" "-1472 744 1576" "message" "Return to Anti-matter\nCore creator for\nCore." } { "target" "t189" "classname" "target_crosslevel_target" "spawnflags" "2050" "origin" "-1440 752 1544" } { "spawnflags" "2048" "origin" "-1424 656 1552" "targetname" "t188" "target" "t172" "classname" "trigger_relay" } { "spawnflags" "2049" "message" "Use Containment\nPod to house\n Anti-matter Core." "origin" "-1512 744 1568" "targetname" "t189" "classname" "target_help" } { "origin" "1144 352 1528" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "origin" "1056 400 1568" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "light" "125" "classname" "light" "origin" "888 352 1568" } { "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "1144 224 1528" } { "light" "100" "classname" "light" "origin" "680 928 1552" } { "light" "100" "classname" "light" "origin" "536 928 1552" } { "targetname" "t153" "origin" "992 -352 1640" "spawnflags" "771" "angle" "90" "classname" "monster_parasite" } { "spawnflags" "2048" "origin" "-1768 168 1576" "message" "Laser power interrupted." "targetname" "lasers" "classname" "trigger_relay" } { "model" "*26" "_minlight" ".2" "spawnflags" "2048" "target" "lasers" "health" "1" "classname" "func_explosive" } { "model" "*27" "spawnflags" "2048" "targetname" "t187" "classname" "func_explosive" } { "spawnflags" "2048" "target" "t186" "targetname" "t185" "classname" "trigger_relay" "origin" "-1352 680 1600" } { "spawnflags" "2048" "target" "t186" "delay" "4" "targetname" "t185" "origin" "-1312 680 1600" "classname" "trigger_relay" } { "model" "*28" "spawnflags" "2048" "target" "t185" "targetname" "t172" "classname" "trigger_once" } { "targetname" "t186" "origin" "-1184 280 1584" "attenuation" "-1" "spawnflags" "2050" "noise" "world/fish.wav" "classname" "target_speaker" } { "origin" "-32 -1024 1664" "classname" "light" "light" "125" } { "origin" "-544 -1024 1808" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-192 -1248 1664" } { "model" "*29" "classname" "func_explosive" "dmg" "75" "health" "5" } { "classname" "monster_parasite" "angle" "0" "spawnflags" "258" "origin" "-1264 -832 1624" "targetname" "t1" } { "target" "t228" "classname" "monster_parasite" "spawnflags" "769" "angle" "270" "origin" "-544 528 1368" } { "spawnflags" "1" "angle" "315" "classname" "monster_parasite" "origin" "-632 1296 1016" } { "classname" "monster_parasite" "angle" "0" "spawnflags" "769" "origin" "-928 1120 1016" } { "model" "*30" "classname" "trigger_multiple" "target" "t21" "spawnflags" "2048" } { "origin" "552 540 1656" "classname" "light" "light" "100" } { "origin" "608 548 1528" "classname" "light" "light" "100" } { "classname" "monster_turret" "spawnflags" "32" "angle" "-2" "origin" "512 64 1720" } { "model" "*31" "classname" "func_wall" "spawnflags" "2816" } { "origin" "352 -96 1720" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "classname" "target_explosion" "targetname" "t177" "origin" "-1896 304 1864" } { "model" "*32" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t177" "target" "walloff" } { "style" "32" "spawnflags" "2048" "origin" "-1192 96 1636" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1192 96 1596" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1192 96 1556" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-1208 96 1592" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-1176 96 1592" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-1128 96 1592" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1112 96 1596" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "spawnflags" "2049" "origin" "-1096 96 1592" "noise" "world/l_hum1.wav" "classname" "target_speaker" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1112 96 1636" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1112 96 1556" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1992 112 1636" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1992 112 1596" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1992 112 1556" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-2008 112 1592" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-1976 112 1592" "targetname" "lasers" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "-1928 112 1592" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1912 112 1596" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "spawnflags" "2049" "origin" "-1896 112 1592" "noise" "world/l_hum1.wav" "classname" "target_speaker" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1912 112 1636" "_color" "1.000000 0.501961 0.000000" "light" "100" "classname" "light" "targetname" "lasers" } { "style" "32" "spawnflags" "2048" "origin" "-1912 112 1556" "classname" "light" "light" "100" "_color" "1.000000 0.501961 0.000000" "targetname" "lasers" } { "model" "*33" "targetname" "lasers" "spawnflags" "7" "classname" "func_wall" } { "model" "*34" "spawnflags" "7" "classname" "func_wall" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1096 96 1556" "dmg" "10000" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1096 96 1596" "dmg" "10000" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1096 96 1636" "dmg" "10000" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1864 112 1596" "dmg" "10000" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1864 112 1636" "dmg" "10000" } { "targetname" "lasers" "classname" "target_laser" "angle" "180" "spawnflags" "2145" "origin" "-1864 112 1556" "dmg" "10000" } { "model" "*35" "classname" "func_wall" "spawnflags" "2816" } { "origin" "-1376 -184 1824" "angle" "90" "spawnflags" "776" "classname" "monster_turret" } { "targetname" "t153" "origin" "-544 -80 1896" "spawnflags" "3" "angle" "270" "classname" "monster_parasite" } { "spawnflags" "2049" "origin" "-1232 384 1608" "noise" "world/scan1.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/scan1.wav" "origin" "-1136 384 1608" "spawnflags" "2049" } { "model" "*36" "message" "Lift activated." "classname" "func_button" "angle" "90" "target" "t183" } { "model" "*37" "message" "Lift activated." "classname" "func_button" "angle" "0" "target" "t183" } { "targetname" "t153" "classname" "monster_parasite" "angle" "45" "spawnflags" "3" "origin" "-1440 160 1880" } { "targetname" "t153" "classname" "monster_parasite" "angle" "90" "spawnflags" "3" "origin" "-1952 -160 1560" } { "model" "*38" "spawnflags" "768" "classname" "func_wall" } { "classname" "monster_turret" "spawnflags" "800" "angle" "-2" "origin" "-480 -320 1528" } { "model" "*39" "spawnflags" "2816" "classname" "func_wall" } { "classname" "monster_turret" "spawnflags" "776" "angle" "180" "origin" "-968 160 2024" } { "model" "*40" "classname" "func_explosive" "targetname" "t144" } { "classname" "monster_turret" "angle" "0" "spawnflags" "160" "targetname" "t144" "origin" "-1760 -96 1824" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t179" "killtarget" "boxe" "origin" "-496 -528 1632" } { "spawnflags" "2048" "classname" "info_notnull" "targetname" "boxe" "origin" "-388 -548 1628" } { "spawnflags" "2048" "classname" "target_anger" "killtarget" "boxe" "targetname" "t180" "target" "t181" "origin" "-464 -488 1608" } { "model" "*41" "spawnflags" "2048" "classname" "trigger_once" "target" "t180" } { "model" "*42" "classname" "func_wall" "spawnflags" "2816" } { "origin" "-384 -544 1720" "classname" "monster_turret" "spawnflags" "32" "angle" "-2" } { "model" "*43" "spawnflags" "768" "classname" "func_wall" } { "classname" "monster_turret" "spawnflags" "800" "angle" "-2" "origin" "-128 -32 1976" } { "model" "*44" "classname" "func_wall" "spawnflags" "2816" } { "targetname" "t153" "classname" "monster_turret" "spawnflags" "10" "angle" "-2" "origin" "-544 -32 1976" } { "classname" "monster_parasite" "angle" "180" "origin" "-1056 -352 1624" } { "model" "*45" "classname" "func_wall" "spawnflags" "2816" } { "classname" "monster_turret" "spawnflags" "8" "angle" "90" "origin" "-1376 -376 1768" } { "classname" "monster_parasite" "angle" "225" "spawnflags" "769" "origin" "-56 -952 1624" } { "classname" "monster_hover" "spawnflags" "1025" "angle" "0" "origin" "-984 -832 1680" } { "item" "ammo_cells" "classname" "monster_daedalus" "spawnflags" "769" "angle" "0" "origin" "-984 -832 1680" } { "target" "t178" "origin" "-1864 360 1896" "random" ".5" "wait" "2" "targetname" "t177" "classname" "func_timer" } { "targetname" "t178" "origin" "-1896 312 1904" "sounds" "1" "angle" "180" "classname" "target_splash" } { "model" "*46" "spawnflags" "2055" "classname" "trigger_disguise" } { "model" "*47" "item" "ammo_rockets" "target" "t187" "health" "5" "dmg" "75" "classname" "func_explosive" } { "model" "*48" "target" "t173" "targetname" "t177" "classname" "func_explosive" } { "spawnflags" "2048" "origin" "-1944 360 1592" "target" "t176" "targetname" "t172" "classname" "trigger_relay" } { "model" "*49" "spawnflags" "2048" "targetname" "t174" "target" "t173" "classname" "trigger_once" } { "model" "*50" "spawnflags" "7936" "targetname" "t176" "classname" "trigger_once" } { "target" "t188" "origin" "-1424 712 1544" "spawnflags" "2049" "classname" "target_crosslevel_target" } { "spawnflags" "2048" "target" "t168" "targetname" "t174" "origin" "-1496 680 1544" "classname" "trigger_relay" } { "spawnflags" "7936" "origin" "-496 -600 1480" "classname" "trigger_relay" } { "spawnflags" "2048" "targetname" "t174" "target" "exiter" "classname" "trigger_relay" "delay" "2" "message" "Security forcefields activated." "origin" "-1520 656 1544" } { "spawnflags" "2048" "target" "t175" "targetname" "t174" "origin" "-1488 712 1544" "classname" "trigger_relay" } { "spawnflags" "2048" "target" "t174" "origin" "-1520 712 1544" "delay" "2" "targetname" "t172" "classname" "trigger_relay" } { "model" "*51" "spawnflags" "2048" "target" "t172" "message" "Humanoid life form detected..." "classname" "trigger_once" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t137" "target" "exiter" "origin" "-480 -584 1480" } { "model" "*52" "targetname" "t175" "spawnflags" "2051" "classname" "func_wall" } { "classname" "item_armor_body" "targetname" "armor" "origin" "-1760 -64 1552" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t153" "target" "t168" "origin" "-1480 680 1568" } { "model" "*53" "spawnflags" "2055" "classname" "func_wall" "targetname" "walloff" } { "model" "*54" "targetname" "t175" "classname" "func_wall" "spawnflags" "2051" } { "classname" "monster_soldier_ss" "angle" "270" "spawnflags" "1" "origin" "-1536 -240 1880" } { "classname" "target_help" "targetname" "t167" "spawnflags" "2048" "origin" "888 664 1528" "message" "Find entrance to\nGravity Well." } { "spawnflags" "2048" "classname" "target_help" "targetname" "key" "message" "Anti-matter Core created.\nContainment Pod needed." "origin" "496 432 1696" } { "model" "*55" "classname" "func_wall" "spawnflags" "2048" } { "model" "*56" "classname" "func_wall" "spawnflags" "5888" } { "classname" "target_help" "origin" "976 352 1696" "spawnflags" "2049" "message" "Use Security Pass\nto retrieve\nContainment Pod." "targetname" "t166" } { "classname" "target_help" "origin" "984 272 1696" "spawnflags" "2048" "message" "Use secondary exit\nto return to\nAmmo Depot." "targetname" "t166" } { "spawnflags" "2048" "targetname" "t166" "classname" "target_goal" "origin" "936 304 1552" } { "spawnflags" "2048" "origin" "-112 -936 1624" "classname" "trigger_relay" "target" "t165" "targetname" "t1" } { "spawnflags" "2048" "message" "Security Pass accessible." "origin" "744 424 1624" "target" "t164" "delay" "2" "classname" "trigger_relay" "targetname" "key" } { "style" "33" "spawnflags" "2048" "origin" "888 296 1496" "targetname" "t164" "light" "150" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "model" "*57" "targetname" "t164" "spawnflags" "2055" "classname" "func_wall" } { "spawnflags" "2048" "origin" "888 288 1496" "classname" "key_pass" "target" "t166" } { "classname" "monster_turret" "spawnflags" "32" "angle" "180" "origin" "1144 544 1696" } { "targetname" "t163" "classname" "point_combat" "origin" "-1536 104 1864" "spawnflags" "1" "wait" "10" } { "targetname" "t153" "item" "ammo_shells" "angle" "90" "classname" "monster_soldier" "origin" "-1632 152 1560" "spawnflags" "3" } { "model" "*58" "spawnflags" "2816" "classname" "func_wall" } { "classname" "monster_turret" "spawnflags" "8" "angle" "0" "origin" "72 544 1696" } { "item" "ammo_bullets" "classname" "monster_soldier_ss" "spawnflags" "1" "angle" "270" "origin" "504 1368 1496" } { "classname" "monster_soldier_ss" "spawnflags" "1" "angle" "180" "origin" "368 480 1496" } { "targetname" "medic" "origin" "1056 496 1496" "spawnflags" "1" "angle" "135" "classname" "monster_medic_commander" } { "spawnflags" "2048" "origin" "168 600 1504" "target" "t161" "targetname" "t160" "classname" "path_corner" } { "spawnflags" "2048" "origin" "160 -96 1360" "targetname" "t161" "target" "t160" "classname" "path_corner" } { "item" "ammo_bullets" "origin" "168 632 1496" "spawnflags" "1" "target" "t160" "classname" "monster_soldier_ss" } { "item" "ammo_bullets" "origin" "496 1200 1496" "angle" "0" "spawnflags" "257" "classname" "monster_soldier_ss" } { "origin" "-464 -1088 1432" "spawnflags" "769" "angle" "45" "classname" "monster_soldier_ss" } { "origin" "-1536 -352 1664" "light" "125" "classname" "light" } { "targetname" "t153" "item" "ammo_slugs" "classname" "monster_gladiator" "angle" "270" "origin" "-544 216 1880" "spawnflags" "259" } { "classname" "monster_turret" "spawnflags" "800" "angle" "-2" "origin" "-864 -1184 1720" } { "spawnflags" "2049" "origin" "-536 -1200 1608" "targetname" "t156" "classname" "point_combat" } { "spawnflags" "3" "targetname" "t153" "item" "ammo_bullets" "classname" "monster_soldier_ss" "angle" "45" "origin" "912 224 1496" } { "origin" "496 -144 1976" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "item" "ammo_cells" "classname" "monster_daedalus" "angle" "225" "spawnflags" "1" "origin" "288 96 1992" } { "origin" "1056 120 1800" "angle" "270" "spawnflags" "32" "classname" "monster_turret" } { "model" "*59" "spawnflags" "2048" "classname" "trigger_once" "target" "t154" } { "classname" "monster_gladiator" "angle" "90" "targetname" "t154" "origin" "1056 -344 1640" "target" "t155" "spawnflags" "1" } { "origin" "608 584 1760" "angle" "90" "spawnflags" "776" "classname" "monster_turret" } { "classname" "monster_medic_commander" "angle" "0" "spawnflags" "1" "origin" "736 64 1624" "targetname" "t155" } { "spawnflags" "3" "targetname" "t153" "item" "ammo_shells" "angle" "180" "classname" "monster_soldier_ss" "origin" "832 224 1624" } { "targetname" "t153" "classname" "monster_soldier_ss" "angle" "270" "spawnflags" "802" "origin" "608 424 1624" } { "origin" "608 1200 1784" "angle" "-2" "spawnflags" "800" "classname" "monster_turret" } { "origin" "-160 -128 1528" "angle" "-2" "spawnflags" "32" "classname" "monster_turret" } { "classname" "target_help" "origin" "-1392 744 1568" "targetname" "t153" "spawnflags" "2049" "message" "Activate Anti-matter\nCore creator." "lip" "12" } { "classname" "target_help" "targetname" "t153" "message" "Find Security Pass\nfor Ammo Depot." "origin" "-1344 736 1568" "spawnflags" "2048" } { "model" "*60" "spawnflags" "2048" "classname" "trigger_once" "target" "t153" } { "target" "t236" "targetname" "t153" "item" "ammo_shells" "spawnflags" "3" "origin" "-2008 248 1560" "classname" "monster_soldier" "angle" "0" } { "targetname" "t153" "target" "t163" "spawnflags" "34" "origin" "-1744 280 1880" "classname" "monster_soldier" "angle" "0" } { "targetname" "t153" "spawnflags" "3" "item" "ammo_shells" "origin" "-1936 280 1560" "angle" "0" "classname" "monster_soldier" } { "origin" "608 1496 1568" "light" "100" "classname" "light" } { "origin" "608 1632 1568" "light" "100" "classname" "light" } { "item" "ammo_cells" "origin" "-816 224 1880" "targetname" "t153" "spawnflags" "3" "angle" "0" "classname" "monster_medic_commander" } { "model" "*61" "spawnflags" "2048" "target" "t149" "classname" "trigger_once" } { "targetname" "t153" "item" "ammo_slugs" "spawnflags" "3" "origin" "-1952 624 1880" "angle" "270" "classname" "monster_gladiator" } { "origin" "-1048 -280 1600" "classname" "misc_explobox" } { "origin" "264 -192 1784" "angle" "0" "spawnflags" "800" "classname" "monster_turret" } { "origin" "-432 -328 1368" "spawnflags" "257" "angle" "135" "classname" "monster_soldier_ss" } { "origin" "-320 376 1440" "angle" "90" "spawnflags" "776" "classname" "monster_turret" } { "origin" "-1112 1512 888" "targetname" "t146" "angle" "270" "classname" "monster_medic_commander" } { "origin" "-1120 1952 1344" "classname" "monster_daedalus" "angle" "315" "spawnflags" "1" } { "origin" "-352 1952 1344" "spawnflags" "1" "angle" "225" "classname" "monster_daedalus" } { "targetname" "t153" "classname" "monster_turret" "spawnflags" "802" "angle" "-2" "origin" "1056 288 1720" } { "targetname" "t153" "classname" "monster_turret" "spawnflags" "34" "angle" "-2" "origin" "-1952 224 2040" } { "item" "ammo_cells" "origin" "-160 -288 1368" "targetname" "t145" "classname" "monster_medic_commander" "spawnflags" "1" "angle" "90" } { "model" "*62" "spawnflags" "2048" "target" "t144" "classname" "trigger_once" } { "item" "ammo_slugs" "origin" "-496 128 1368" "targetname" "t144" "spawnflags" "1" "angle" "270" "classname" "monster_gladiator" } { "targetname" "t153" "origin" "-1792 -288 1872" "spawnflags" "3" "angle" "180" "classname" "monster_tank" } { "item" "ammo_shells" "origin" "-1664 -320 1592" "spawnflags" "1" "angle" "0" "classname" "monster_soldier" } { "model" "*63" "spawnflags" "2048" "target" "t143" "classname" "trigger_once" } { "origin" "-1376 -376 1608" "targetname" "t142" "spawnflags" "2049" "classname" "point_combat" } { "item" "ammo_bullets" "origin" "-1192 -336 1624" "spawnflags" "1537" "targetname" "t143" "angle" "180" "target" "t142" "classname" "monster_soldier_ss" } { "targetname" "t153" "origin" "-1536 256 1920" "classname" "monster_daedalus" "angle" "270" "spawnflags" "3" } { "origin" "-1024 0 1920" "spawnflags" "769" "angle" "225" "classname" "monster_daedalus" } { "origin" "-320 992 1544" "angle" "-2" "spawnflags" "32" "classname" "monster_turret" } { "angle" "-2" "spawnflags" "776" "classname" "monster_turret" "origin" "-32 -928 1528" } { "origin" "-864 -1184 1720" "angle" "-2" "spawnflags" "1032" "classname" "monster_turret" "targetname" "t181" } { "model" "*64" "classname" "func_door" "angle" "-2" } { "item" "ammo_rockets" "target" "t162" "spawnflags" "1" "origin" "608 904 1488" "angle" "270" "classname" "monster_tank" } { "item" "ammo_rockets" "spawnflags" "1" "target" "t145" "origin" "-160 480 1360" "angle" "180" "classname" "monster_tank_commander" } { "item" "ammo_slugs" "target" "t156" "origin" "-160 -1216 1624" "spawnflags" "257" "angle" "180" "classname" "monster_gladiator" } { "spawnflags" "2048" "target" "t140" "targetname" "t139" "origin" "-216 -800 1416" "classname" "path_corner" } { "spawnflags" "2048" "target" "t139" "targetname" "t138" "origin" "-424 -752 1416" "classname" "path_corner" } { "spawnflags" "2048" "targetname" "t141" "target" "t138" "origin" "-416 -1088 1416" "classname" "path_corner" } { "spawnflags" "2048" "target" "t141" "targetname" "t140" "origin" "-424 -768 1416" "classname" "path_corner" } { "item" "ammo_bullets" "target" "t141" "origin" "-416 -1120 1432" "angle" "90" "classname" "monster_soldier_ss" } { "item" "ammo_shells" "origin" "-400 -672 1728" "spawnflags" "257" "angle" "270" "classname" "monster_soldier" } { "origin" "-1376 -696 1720" "angle" "-2" "spawnflags" "264" "classname" "monster_turret" } { "origin" "-480 -808 1440" "message" "Obtain Anti-matter\nPod from Ammo Depot." "spawnflags" "2049" "targetname" "t137" "classname" "target_help" } { "spawnflags" "2048" "origin" "-400 -736 1440" "message" "Find Entrance to\nAmmo Depot." "targetname" "t137" "classname" "target_help" } { "model" "*65" "spawnflags" "2048" "target" "t137" "classname" "trigger_once" } { "model" "*66" "spawnflags" "2048" "wait" "-1" "message" "Shuttle inactive." "classname" "trigger_multiple" } { "origin" "-1880 632 1960" "light" "100" "classname" "light" } { "origin" "-1952 560 1960" "light" "100" "classname" "light" } { "origin" "-1952 400 1960" "light" "100" "classname" "light" } { "origin" "-1856 152 1912" "light" "100" "classname" "light" } { "spawnflags" "2048" "origin" "-1768 600 1880" "targetname" "rammo2c" "angle" "180" "classname" "info_player_coop" } { "spawnflags" "2048" "origin" "-1720 664 1880" "targetname" "rammo2c" "angle" "180" "classname" "info_player_coop" } { "spawnflags" "2048" "origin" "-1816 664 1880" "targetname" "rammo2c" "classname" "info_player_coop" "angle" "180" } { "spawnflags" "2048" "origin" "-1680 600 1880" "targetname" "rammo2c" "angle" "180" "classname" "info_player_coop" } { "spawnflags" "2048" "origin" "-1648 640 1880" "classname" "info_player_start" "angle" "180" "targetname" "rammo2c" } { "spawnflags" "2048" "map" "rammo2$rammo1c" "origin" "-1656 632 1928" "targetname" "t136" "classname" "target_changelevel" } { "model" "*67" "spawnflags" "2048" "target" "t136" "classname" "trigger_multiple" } { "spawnflags" "2048" "origin" "-1216 584 1560" "targetname" "rammo2b" "classname" "info_player_coop" "angle" "270" } { "spawnflags" "2048" "origin" "-1152 624 1560" "targetname" "rammo2b" "classname" "info_player_coop" "angle" "270" } { "targetname" "rammo2b" "spawnflags" "2048" "origin" "-1216 664 1560" "classname" "info_player_coop" "angle" "270" } { "spawnflags" "2048" "origin" "-1160 528 1560" "targetname" "rammo2b" "angle" "270" "classname" "info_player_coop" } { "spawnflags" "2048" "origin" "-1168 680 1560" "targetname" "rammo2b" "angle" "270" "classname" "info_player_start" } { "spawnflags" "2048" "origin" "-1184 712 1600" "map" "rammo2$rammo1b" "targetname" "t135" "classname" "target_changelevel" } { "model" "*68" "target" "t135" "angle" "90" "classname" "trigger_multiple" "spawnflags" "2056" "targetname" "t168" } { "classname" "misc_explobox" "origin" "-1248 -360 1600" } { "classname" "misc_explobox" "origin" "-1336 -216 1856" } { "model" "*69" "classname" "func_plat2" "lip" "80" "targetname" "t183" "spawnflags" "2" } { "model" "*70" "health" "5" "dmg" "75" "classname" "func_explosive" } { "model" "*71" "item" "ammo_grenades" "dmg" "75" "health" "1" "classname" "func_explosive" } { "origin" "-720 -288 1952" "classname" "light" "light" "75" } { "origin" "-880 -288 1952" "classname" "light" "light" "75" } { "origin" "-880 224 1952" "classname" "light" "light" "75" } { "origin" "-720 224 1952" "classname" "light" "light" "75" } { "origin" "-544 224 1952" "classname" "light" "light" "75" } { "origin" "-544 48 1952" "classname" "light" "light" "75" } { "origin" "-368 -32 1952" "classname" "light" "light" "75" } { "origin" "544 -96 1672" "classname" "light" "light" "75" } { "origin" "696 -96 1632" "classname" "light" "light" "75" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "-448 1152 1088" } { "light" "100" "classname" "light" "origin" "-864 1216 1076" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "-320 384 1504" } { "light" "100" "classname" "light" "origin" "-320 800 1608" } { "origin" "-1116 1724 900" "classname" "misc_banner" "angle" "0" } { "classname" "light" "light" "100" "origin" "-704 1808 976" } { "classname" "light" "light" "100" "origin" "-760 1808 976" } { "model" "*72" "classname" "func_wall" "spawnflags" "3" "team" "beamer" "targetname" "t130" } { "model" "*73" "spawnflags" "2048" "classname" "func_train" "target" "t111" "targetname" "t130" "team" "beamer" } { "model" "*74" "classname" "func_wall" "spawnflags" "2051" "targetname" "t127" } { "spawnflags" "2048" "classname" "target_changelevel" "targetname" "t133" "map" "reu4_.cin+*rboss$unitstart" "origin" "-736 2760 1072" } { "model" "*75" "spawnflags" "2048" "classname" "trigger_once" "target" "t133" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t129" "delay" "1.5" "target" "t132" "origin" "-640 1512 1016" } { "model" "*76" "wait" "3" "angle" "180" "classname" "func_button" "target" "t131" "message" "Lift activated." } { "model" "*77" "classname" "func_button" "angle" "90" "wait" "3" "target" "t131" "message" "Lift activated." } { "origin" "-320 1152 1208" "classname" "light" "light" "100" } { "origin" "-320 1152 1336" "classname" "light" "light" "100" } { "origin" "-320 1088 1528" "classname" "light" "light" "100" } { "model" "*78" "classname" "trigger_once" "spawnflags" "2052" "target" "t130" "targetname" "t129" "message" "Gondola activated." } { "spawnflags" "2048" "origin" "-688 1172 1000" "classname" "trigger_relay" "delay" "4" "targetname" "t123" "target" "t128" } { "spawnflags" "2048" "origin" "-660 1436 1000" "classname" "trigger_relay" "targetname" "t123" "delay" "6" "target" "t129" "message" "Gondola prep sequence complete." } { "classname" "target_speaker" "origin" "-608 1460 1100" "noise" "world/l_hum2.wav" "spawnflags" "2050" "targetname" "t129" } { "classname" "target_speaker" "origin" "-608 1264 1100" "noise" "world/l_hum2.wav" "spawnflags" "2050" "targetname" "t128" } { "origin" "-864 1268 1100" "classname" "target_speaker" "noise" "world/l_hum2.wav" "spawnflags" "2050" "targetname" "t128" } { "origin" "-864 1120 968" "classname" "target_speaker" "spawnflags" "2050" "targetname" "t123" "noise" "world/l_hum2.wav" } { "classname" "target_speaker" "origin" "-608 1116 968" "spawnflags" "2050" "targetname" "t123" "noise" "world/l_hum2.wav" } { "origin" "-736 1480 1100" "classname" "target_speaker" "noise" "world/l_hum2.wav" "spawnflags" "2050" } { "style" "34" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "200" "spawnflags" "2049" "origin" "-608 1440 1100" "targetname" "t129" } { "style" "35" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "200" "spawnflags" "2049" "origin" "-608 1308 1100" "targetname" "t128" } { "style" "35" "light" "200" "_color" "0.000000 0.501961 1.000000" "classname" "light" "spawnflags" "2049" "origin" "-864 1316 1100" "targetname" "t128" } { "style" "35" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "200" "spawnflags" "1" "origin" "-608 1056 1100" "targetname" "t128" } { "style" "35" "light" "200" "_color" "0.000000 0.501961 1.000000" "classname" "light" "spawnflags" "1" "origin" "-864 1064 1100" "targetname" "t128" } { "style" "36" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "200" "targetname" "t123" "spawnflags" "1" "origin" "-608 1144 968" } { "style" "36" "light" "200" "_color" "0.000000 0.501961 1.000000" "classname" "light" "targetname" "t123" "spawnflags" "2049" "origin" "-864 1152 968" } { "style" "34" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "200" "spawnflags" "2049" "origin" "-864 1448 1100" "targetname" "t129" } { "classname" "target_speaker" "origin" "-864 1464 1100" "noise" "world/l_hum2.wav" "spawnflags" "2050" "targetname" "t129" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lason1.wav" "origin" "-664 1592 992" "targetname" "t123" } { "spawnflags" "2048" "origin" "-816 1592 992" "noise" "world/lason1.wav" "classname" "target_speaker" "targetname" "t123" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lason1.wav" "origin" "-816 1760 992" "targetname" "t123" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lason1.wav" "origin" "-736 1280 1056" "targetname" "t123" } { "spawnflags" "2048" "origin" "-664 1760 992" "noise" "world/lason1.wav" "classname" "target_speaker" "targetname" "t123" } { "spawnflags" "2048" "classname" "target_speaker" "targetname" "t127" "noise" "world/fusein.wav" "origin" "-736 912 1056" } { "spawnflags" "2048" "classname" "target_speaker" "targetname" "t127" "noise" "world/fusein.wav" "origin" "-736 968 1056" } { "spawnflags" "2048" "classname" "target_speaker" "targetname" "t127" "noise" "world/fusein.wav" "origin" "-728 1064 1056" } { "spawnflags" "2048" "classname" "trigger_key" "targetname" "t126" "item" "key_power_cube" "target" "t127" "origin" "-720 920 1040" } { "model" "*79" "spawnflags" "2048" "wait" "10" "classname" "trigger_multiple" "target" "t126" } { "spawnflags" "2048" "origin" "-72 -1016 1624" "classname" "trigger_relay" "target" "t134" "targetname" "t1" } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "-656 1320 1024" "target" "t134" "targetname" "t127" } { "spawnflags" "2048" "classname" "target_goal" "targetname" "t123" "origin" "-792 1312 1000" } { "classname" "target_help" "targetname" "t123" "origin" "-664 1280 1016" "spawnflags" "2048" "message" "Use Gondola to enter\n Gravity Well." } { "model" "*80" "targetname" "t127" "classname" "trigger_once" "message" "Gondola systems activated." "target" "t123" "spawnflags" "2052" } { "model" "*81" "classname" "trigger_multiple" "message" "Console inactive, insufficient power." "spawnflags" "2056" "wait" "15" "targetname" "t134" } { "model" "*82" "spawnflags" "2048" "wait" "-1" "classname" "func_button" "angle" "90" "targetname" "t123" } { "model" "*83" "classname" "func_door" "angle" "-2" "spawnflags" "2049" "lip" "32" "wait" "-1" "_minlight" ".2" "targetname" "t123" "speed" "50" } { "model" "*84" "spawnflags" "2048" "classname" "func_button" "angle" "270" "target" "t122" "wait" "-1" "message" "Power center opened." } { "model" "*85" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "wait" "-1" "speed" "15" "targetname" "t122" } { "origin" "-1120 1280 1076" "classname" "light" "light" "100" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t120" "speed" "280" "target" "t121" "origin" "-888 2704 860" } { "spawnflags" "2048" "classname" "path_corner" "speed" "260" "targetname" "t119" "target" "t120" "origin" "-888 2576 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t118" "speed" "240" "target" "t119" "origin" "-888 2448 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t117" "speed" "220" "target" "t118" "origin" "-888 2320 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t116" "speed" "200" "target" "t117" "origin" "-888 2192 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t115" "speed" "180" "target" "t116" "origin" "-888 2064 860" } { "spawnflags" "2048" "pathtarget" "holer" "classname" "path_corner" "speed" "160" "targetname" "t114" "target" "t115" "origin" "-888 1936 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t113" "speed" "140" "target" "t114" "origin" "-888 1808 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t111" "speed" "120" "target" "t113" "origin" "-888 1680 860" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t121" "speed" "300" "origin" "-888 2832 860" "wait" "-1" } { "angle" "90" "classname" "target_laser" "origin" "-608 1416 1100" "spawnflags" "2120" "dmg" "5000" "targetname" "t129" } { "angle" "90" "classname" "target_laser" "origin" "-608 1032 1100" "targetname" "t128" "spawnflags" "2120" "dmg" "5000" } { "classname" "target_laser" "angle" "90" "origin" "-864 1032 1100" "spawnflags" "2120" "dmg" "5000" "targetname" "t128" } { "angle" "90" "classname" "target_laser" "origin" "-864 1416 1100" "spawnflags" "2120" "dmg" "5000" "targetname" "t129" } { "classname" "target_laser" "angle" "90" "origin" "-736 1528 956" "spawnflags" "2120" "dmg" "5000" "targetname" "t129" } { "angle" "270" "classname" "target_laser" "origin" "-608 1208 968" "targetname" "t123" "spawnflags" "2120" "dmg" "5000" } { "classname" "target_laser" "angle" "270" "origin" "-864 1208 968" "targetname" "t123" "spawnflags" "2120" "dmg" "5000" } { "origin" "-544 1440 1140" "classname" "light" "light" "100" } { "light" "100" "classname" "light" "origin" "-736 1632 1140" } { "light" "100" "classname" "light" "origin" "-480 1696 1140" } { "light" "100" "classname" "light" "origin" "-992 1696 1140" } { "light" "100" "classname" "light" "origin" "-608 1216 1076" } { "model" "*86" "origin" "-256 672 1472" "distance" "-90" "classname" "func_door_rotating" "spawnflags" "2050" "message" "Gravity Well Access denied!" "wait" "-1" "targetname" "t167" "team" "chapel" } { "model" "*87" "origin" "-736 1536 846" "classname" "func_door_rotating" "spawnflags" "64" "distance" "-90" "targetname" "t132" "wait" "-1" } { "model" "*88" "origin" "-928 1802 900" "classname" "func_door_rotating" "spawnflags" "2177" "distance" "-90" "targetname" "t123" "wait" "-1" } { "model" "*89" "lip" "16" "classname" "func_plat2" "_minlight" ".3" "targetname" "t131" "spawnflags" "2" } { "spawnflags" "0" "angle" "180" "classname" "misc_banner" "origin" "-356 1724 900" } { "model" "*90" "origin" "-384 672 1472" "classname" "func_door_rotating" "distance" "-90" "spawnflags" "2048" "message" "Gravity Well Access denied!" "wait" "-1" "targetname" "t167" "team" "chapel" } { "origin" "-320 608 1608" "classname" "light" "light" "100" } { "light" "100" "classname" "light" "origin" "-120 632 1368" } { "light" "100" "classname" "light" "origin" "-160 600 1368" } { "light" "100" "classname" "light" "origin" "-480 600 1368" } { "light" "100" "classname" "light" "origin" "-320 1152 1080" } { "light" "100" "classname" "light" "origin" "192 640 1808" } { "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "-432 616 1600" } { "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "-528 616 1600" } { "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "-208 616 1600" } { "_color" "1.000000 0.000000 0.000000" "light" "175" "classname" "light" "origin" "-480 592 1600" } { "_color" "1.000000 0.000000 0.000000" "light" "175" "classname" "light" "origin" "-160 592 1600" } { "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "-112 616 1600" } { "light" "100" "classname" "light" "origin" "664 540 1656" } { "light" "100" "classname" "light" "origin" "608 384 1684" } { "spawnflags" "2048" "origin" "680 -328 1768" "target" "t109" "targetname" "red2" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "824 -328 1768" "target" "t110" "targetname" "red3" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "584 -312 1768" "target" "t108" "targetname" "red1" "classname" "trigger_relay" } { "style" "37" "spawnflags" "2049" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "175" "targetname" "red2" "origin" "688 -432 1836" } { "style" "38" "spawnflags" "2048" "targetname" "t109" "_color" "0.436170 1.000000 0.356383" "light" "175" "classname" "light" "origin" "720 -432 1836" } { "style" "39" "spawnflags" "2049" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "175" "targetname" "red1" "origin" "560 -432 1836" } { "style" "40" "spawnflags" "2048" "targetname" "t108" "_color" "0.436170 1.000000 0.356383" "light" "175" "classname" "light" "origin" "592 -432 1836" } { "style" "41" "light" "175" "_color" "1.000000 0.000000 0.000000" "classname" "light" "spawnflags" "2049" "targetname" "red3" "origin" "816 -432 1836" } { "style" "42" "spawnflags" "2048" "targetname" "t110" "classname" "light" "light" "175" "_color" "0.436170 1.000000 0.356383" "origin" "848 -432 1836" } { "spawnflags" "2048" "classname" "trigger_relay" "target" "t107" "targetname" "t50" "origin" "840 164 1480" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t1" "target" "t107" "origin" "-48 -928 1624" } { "targetname" "rammo2a" "spawnflags" "2048" "angle" "270" "classname" "info_player_coop" "origin" "632 1512 1496" } { "targetname" "rammo2a" "spawnflags" "2048" "angle" "270" "classname" "info_player_coop" "origin" "640 1592 1496" } { "targetname" "rammo2a" "spawnflags" "2048" "angle" "270" "classname" "info_player_coop" "origin" "584 1624 1496" } { "spawnflags" "2048" "classname" "info_player_coop" "targetname" "rammo2a" "angle" "270" "origin" "584 1544 1496" } { "targetname" "rammo2a" "spawnflags" "2048" "origin" "608 1584 1496" "angle" "270" "classname" "info_player_start" } { "spawnflags" "2048" "classname" "target_changelevel" "targetname" "t106" "map" "rammo2$rammo1a" "origin" "608 1632 1568" } { "model" "*91" "classname" "trigger_multiple" "target" "t106" "angle" "90" "spawnflags" "2056" "targetname" "exiter" } { "origin" "608 1040 1736" "classname" "light" "light" "100" } { "origin" "568 1400 1592" "classname" "light" "light" "100" } { "origin" "648 1400 1592" "classname" "light" "light" "100" } { "origin" "736 1072 1688" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "736 1200 1688" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "736 1328 1688" } { "origin" "480 1200 1688" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "origin" "480 1328 1688" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "origin" "888 224 1568" "classname" "light" "light" "125" } { "light" "75" "classname" "light" "origin" "608 1208 1736" } { "light" "100" "classname" "light" "origin" "768 672 1808" } { "light" "100" "classname" "light" "origin" "160 -96 1492" } { "origin" "160 384 1528" "classname" "light" "light" "100" } { "origin" "-1952 -288 1760" "classname" "light" "light" "100" } { "origin" "-1952 -288 1928" "classname" "light" "light" "100" } { "origin" "-1632 -64 1936" "classname" "light" "light" "100" } { "origin" "160 176 1492" "classname" "light" "light" "100" } { "origin" "-640 -96 1492" "classname" "light" "light" "100" } { "origin" "160 32 2004" "classname" "light" "light" "100" } { "light" "100" "classname" "light" "origin" "-192 -364 1464" } { "light" "100" "classname" "light" "origin" "-84 -256 1464" } { "light" "100" "classname" "light" "origin" "-84 448 1464" } { "origin" "-84 256 1464" "classname" "light" "light" "100" } { "origin" "-84 64 1464" "classname" "light" "light" "100" } { "origin" "1056 -364 1660" "classname" "light" "light" "100" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t50" "target" "t105" "delay" "5" "origin" "680 480 1624" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t50" "target" "t105" "origin" "536 480 1624" } { "classname" "target_speaker" "origin" "552 448 1640" "noise" "world/klaxon2.wav" "targetname" "t105" "spawnflags" "2050" } { "classname" "target_speaker" "origin" "664 448 1640" "noise" "world/klaxon2.wav" "targetname" "t105" "spawnflags" "2050" } { "model" "*92" "spawnflags" "2048" "classname" "func_button" "target" "t50" "wait" "-1" "message" "Anti-matter core creation initiated." "angle" "90" "lip" "12" } { "light" "100" "classname" "light" "origin" "-556 64 1464" } { "light" "100" "classname" "light" "origin" "-556 256 1464" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "480 1072 1688" } { "origin" "-556 448 1464" "classname" "light" "light" "100" } { "origin" "-556 -256 1464" "classname" "light" "light" "100" } { "origin" "-448 -364 1464" "classname" "light" "light" "100" } { "origin" "0 -20 1464" "classname" "light" "light" "100" } { "origin" "84 608 1528" "classname" "light" "light" "100" } { "light" "75" "classname" "light" "origin" "352 -40 1704" } { "light" "75" "classname" "light" "origin" "408 -96 1696" } { "light" "75" "classname" "light" "origin" "-544 -288 1952" } { "light" "75" "classname" "light" "origin" "-208 -32 1952" } { "light" "75" "classname" "light" "origin" "848 -96 1600" } { "light" "75" "classname" "light" "origin" "1000 -96 1568" } { "light" "75" "classname" "light" "origin" "1056 -40 1568" } { "light" "75" "classname" "light" "origin" "1056 120 1568" } { "classname" "light" "light" "75" "origin" "352 120 1704" } { "light" "100" "classname" "light" "origin" "448 672 1808" } { "light" "100" "classname" "light" "origin" "1132 608 1528" } { "light" "100" "classname" "light" "origin" "1132 288 1524" } { "origin" "352 288 1684" "classname" "light" "light" "100" } { "origin" "-928 1440 1140" "classname" "light" "light" "100" } { "origin" "832 20 1660" "classname" "light" "light" "150" } { "origin" "-736 1380 920" "classname" "light" "light" "100" } { "origin" "768 -68 1780" "classname" "light" "light" "100" } { "light" "100" "classname" "light" "origin" "-864 -96 1544" } { "origin" "160 -288 2004" "classname" "light" "light" "100" } { "light" "150" "classname" "light" "origin" "576 20 1660" } { "origin" "776 -288 1796" "classname" "light" "light" "100" } { "origin" "1088 48 1812" "classname" "light" "light" "100" } { "origin" "896 -328 1824" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "origin" "512 -328 1824" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "origin" "352 -328 1824" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" } { "_color" "1.000000 0.000000 0.000000" "origin" "-320 928 1520" "classname" "light" "light" "150" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "280 320 1656" } { "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "1056 -328 1824" } { "light" "100" "classname" "light" "origin" "512 -68 1780" } { "light" "100" "classname" "light" "origin" "912 -160 1940" } { "model" "*93" "classname" "func_wall" "spawnflags" "2048" } { "model" "*94" "classname" "func_wall" "spawnflags" "2048" } { "light" "100" "classname" "light" "origin" "640 -160 1940" } { "light" "100" "classname" "light" "origin" "1088 -192 1812" } { "light" "100" "classname" "light" "origin" "352 -64 2004" } { "light" "100" "classname" "light" "origin" "864 288 1692" } { "origin" "416 816 1520" "classname" "light" "light" "100" } { "model" "*95" "spawnflags" "2048" "angle" "-2" "classname" "func_door" } { "classname" "misc_explobox" "origin" "-288 -992 1408" } { "classname" "misc_explobox" "origin" "-368 -1192 1408" } { "classname" "misc_explobox" "origin" "-168 -600 1600" } { "origin" "-1216 -288 1600" "classname" "misc_explobox" } { "model" "*96" "classname" "func_explosive" "health" "5" "dmg" "100" "target" "t179" } { "model" "*97" "health" "5" "dmg" "100" "classname" "func_explosive" } { "model" "*98" "dmg" "75" "health" "1" "classname" "func_explosive" } { "classname" "misc_explobox" "origin" "-864 -1248 1600" } { "model" "*99" "classname" "trigger_hurt" "targetname" "t52" "spawnflags" "2059" "dmg" "25" } { "origin" "304 896 1744" "classname" "light" "light" "100" } { "spawnflags" "2048" "classname" "path_corner" "origin" "561 855 1632" "pathtarget" "oredor3" "targetname" "t38" "target" "t57" "wait" "3" } { "model" "*100" "classname" "func_wall" "targetname" "t52" "spawnflags" "7" } { "_color" "1.000000 0.679487 0.089744" "light" "100" "classname" "light" "origin" "1040 752 1614" } { "model" "*101" "spawnflags" "2080" "classname" "func_door" "angle" "-1" "targetname" "oredor2" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/fusein.wav" "targetname" "t48" "origin" "1088 772 1520" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t30" "delay" "6" "target" "t56" "origin" "872 1048 1696" } { "spawnflags" "2048" "delay" "3.25" "killtarget" "t165" "classname" "trigger_relay" "origin" "996 1056 1496" "targetname" "t46" } { "style" "43" "light" "150" "classname" "light" "targetname" "t55" "spawnflags" "2049" "origin" "928 759 1576" "_color" "1.000000 0.000000 0.000000" "wait" "4.5" } { "style" "43" "classname" "light" "light" "150" "targetname" "t55" "spawnflags" "2049" "origin" "928 759 1528" "_color" "1.000000 0.000000 0.000000" } { "style" "43" "light" "150" "classname" "light" "targetname" "t55" "spawnflags" "2049" "origin" "736 759 1528" "_color" "1.000000 0.000000 0.000000" } { "style" "43" "classname" "light" "light" "150" "targetname" "t55" "spawnflags" "2049" "origin" "736 759 1576" "_color" "1.000000 0.000000 0.000000" "wait" "4.5" } { "spawnflags" "2048" "speed" "3" "message" "za" "classname" "target_lightramp" "origin" "712 696 1720" "target" "t55" "targetname" "steam2" } { "spawnflags" "2048" "message" "az" "speed" "3" "classname" "target_lightramp" "origin" "952 696 1720" "target" "t55" "targetname" "steamage" } { "spawnflags" "2048" "classname" "trigger_relay" "message" "Core creation complete." "origin" "1072 1072 1488" "targetname" "core" "target" "t165" } { "spawnflags" "2050" "noise" "world/lasburn1.wav" "origin" "576 648 1664" "classname" "target_speaker" "targetname" "t53" } { "spawnflags" "2050" "noise" "world/lasburn1.wav" "origin" "640 648 1664" "classname" "target_speaker" "targetname" "t53" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/x_light.wav" "targetname" "core" "origin" "1064 688 1568" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/x_light.wav" "targetname" "core" "origin" "1112 688 1568" } { "spawnflags" "2048" "classname" "trigger_relay" "delay" "4.5" "targetname" "steamage" "target" "t54" "origin" "1048 1076 1488" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "steamage" "origin" "1052 1056 1488" "target" "t54" "message" "Compression chamber activated." } { "classname" "target_speaker" "noise" "world/airhiss1.wav" "origin" "792 799 1488" "targetname" "t54" "spawnflags" "2050" } { "classname" "target_speaker" "noise" "world/airhiss1.wav" "origin" "872 799 1488" "targetname" "t54" "spawnflags" "2050" } { "classname" "target_speaker" "noise" "world/airhiss1.wav" "targetname" "t54" "origin" "920 632 1488" "spawnflags" "2050" } { "noise" "world/airhiss1.wav" "classname" "target_speaker" "origin" "728 632 1488" "targetname" "t54" "spawnflags" "2050" } { "spawnflags" "2048" "noise" "world/electro.wav" "classname" "target_speaker" "targetname" "t37" "origin" "776 743 1552" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/electro.wav" "targetname" "t37" "origin" "976 616 1552" } { "spawnflags" "2048" "noise" "world/electro.wav" "classname" "target_speaker" "targetname" "t37" "origin" "888 744 1552" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/electro.wav" "targetname" "t37" "origin" "696 616 1552" } { "spawnflags" "2048" "origin" "848 1076 1516" "wait" "7" "classname" "trigger_relay" "target" "t53" "delay" "7" "targetname" "t56" } { "classname" "target_speaker" "origin" "640 840 1696" "noise" "world/lasburn1.wav" "spawnflags" "2050" "targetname" "t53" } { "classname" "target_speaker" "origin" "576 840 1696" "noise" "world/lasburn1.wav" "spawnflags" "2050" "targetname" "t53" } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "872 1076 1664" "targetname" "t56" "target" "t53" "message" "Ore cleansing in progress." } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "windor1" "target" "t52" "origin" "408 896 1664" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "windor1" "delay" "11" "target" "t52" "origin" "424 896 1664" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/amb14.wav" "targetname" "t52" "origin" "448 768 1672" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/amb14.wav" "targetname" "t52" "origin" "384 768 1672" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/amb14.wav" "targetname" "t52" "origin" "384 624 1616" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/amb14.wav" "targetname" "t52" "origin" "448 624 1616" } { "spawnflags" "2048" "delay" "25" "origin" "-40 984 1632" "classname" "trigger_relay" "target" "t51" "targetname" "t50" } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "-72 984 1632" "target" "t51" "targetname" "t50" } { "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" "team" "nuker" "origin" "-80 900 1664" "targetname" "t51" } { "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" "team" "nuker" "origin" "-56 900 1664" "targetname" "t51" } { "light" "100" "classname" "light" "origin" "80 896 1744" } { "light" "100" "classname" "light" "origin" "648 1000 1592" } { "classname" "light" "light" "150" "origin" "832 896 1528" } { "classname" "light" "light" "125" "origin" "1088 808 1520" } { "spawnflags" "2048" "origin" "996 1076 1496" "classname" "trigger_relay" "killtarget" "t44" "targetname" "t46" "delay" "4" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t46" "target" "t47" "origin" "1024 1076 1560" } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "1000 1036 1504" "targetname" "t44" "target" "t43" "delay" "1" "message" "Core insertion module activated." } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "972 1076 1496" "targetname" "tain" "target" "t46" } { "spawnflags" "2048" "classname" "path_corner" "wait" "-1" "origin" "1064 720 1496" "targetname" "t40" "target" "t45" } { "model" "*102" "spawnflags" "2048" "classname" "func_train" "target" "t40" "targetname" "t43" } { "spawnflags" "2048" "classname" "path_corner" "wait" "6.5" "origin" "1064 772 1496" "targetname" "t45" "target" "t40" "pathtarget" "tain" } { "spawnflags" "2048" "delay" "3.5" "origin" "972 1056 1520" "classname" "trigger_relay" "targetname" "t46" "target" "t48" "message" "Core insertion complete." } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "windor2" "target" "t37" "origin" "848 1048 1520" "delay" "3.5" } { "spawnflags" "2048" "classname" "path_corner" "origin" "-104 856 1296" "targetname" "t36" "target" "t23" "speed" "1000" "pathtarget" "key" } { "spawnflags" "2048" "classname" "path_corner" "origin" "384 856 1632" "pathtarget" "oredor3" "targetname" "t31" "target" "t32" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "windor1" "origin" "928 1076 1720" "target" "t29" "message" "Ore stabilization in progress." } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "windor1" "origin" "904 1076 1720" "target" "t30" "delay" "7" } { "spawnflags" "2048" "pathtarget" "oredor3" "origin" "512 856 1632" "classname" "path_corner" "targetname" "t32" "target" "t38" } { "spawnflags" "2048" "classname" "target_steam" "angle" "270" "origin" "576 944 1696" "speed" "150" "sounds" "208" "wait" "7" "targetname" "t56" } { "spawnflags" "2048" "classname" "target_steam" "angle" "0" "origin" "776 799 1488" "targetname" "steamage" "sounds" "4" "wait" "5" } { "spawnflags" "2048" "origin" "640 944 1696" "angle" "270" "classname" "target_steam" "speed" "150" "sounds" "208" "wait" "7" "targetname" "t56" } { "model" "*103" "_minlight" ".2" "spawnflags" "2048" "classname" "func_train" "target" "t23" "targetname" "t50" "speed" "50" "team" "nuker" } { "spawnflags" "2048" "classname" "path_corner" "origin" "-72 856 1632" "targetname" "t24" "pathtarget" "oredor1" "target" "t25" } { "spawnflags" "2048" "origin" "64 856 1632" "classname" "path_corner" "pathtarget" "oredor1" "targetname" "t25" "target" "t26" } { "model" "*104" "origin" "1116 770 1544" "classname" "func_door_rotating" "spawnflags" "2055" "distance" "-115" "_minlight" ".3" "targetname" "t47" "sounds" "3" } { "spawnflags" "2048" "classname" "trigger_key" "targetname" "t21" "item" "key_nuke_container" "origin" "972 1036 1504" "target" "t44" } { "classname" "key_nuke" "spawnflags" "2049" "origin" "1088 808 1524" "targetname" "t48" "target" "t167" } { "classname" "key_nuke_container" "spawnflags" "2049" "origin" "1088 744 1524" "targetname" "t44" } { "spawnflags" "2048" "classname" "misc_nuke_core" "origin" "1088 808 1572" "targetname" "t165" } { "spawnflags" "2048" "origin" "832 896 1480" "count" "48" "speed" "200" "angle" "-1" "classname" "target_steam" "targetname" "steam2" "wait" "16" "sounds" "230" } { "spawnflags" "2048" "classname" "path_corner" "origin" "792 856 1480" "targetname" "t34" "pathtarget" "windor2" "wait" "10" "target" "t35" } { "spawnflags" "2048" "classname" "path_corner" "origin" "792 856 1632" "target" "t34" "targetname" "t57" } { "spawnflags" "2048" "classname" "path_corner" "origin" "376 856 1632" "targetname" "t28" "pathtarget" "windor1" "wait" "12" "target" "t31" } { "spawnflags" "2048" "classname" "path_corner" "origin" "344 856 1632" "targetname" "t27" "pathtarget" "oredor2" "target" "t28" } { "model" "*105" "spawnflags" "2048" "angle" "-1" "classname" "func_door" "targetname" "oredor3" "speed" "125" } { "model" "*106" "angle" "-1" "classname" "func_door" "targetname" "oredor1" "spawnflags" "32" "speed" "125" } { "spawnflags" "2048" "origin" "216 856 1632" "classname" "path_corner" "pathtarget" "oredor2" "targetname" "t26" "target" "t27" } { "spawnflags" "2048" "origin" "-104 856 1632" "classname" "path_corner" "targetname" "t23" "target" "t24" "wait" "-1" "speed" "100" } { "spawnflags" "2048" "origin" "792 856 1296" "classname" "path_corner" "targetname" "t35" "target" "t36" "pathtarget" "core" } { "origin" "1136 752 1614" "classname" "light" "light" "100" "_color" "1.000000 0.679487 0.089744" } { "light" "100" "classname" "light" "origin" "568 1000 1592" } { "spawnflags" "2048" "origin" "432 936 1720" "target" "t18" "classname" "target_lightramp" "message" "za" "speed" "2" "targetname" "t30" } { "spawnflags" "2048" "origin" "400 936 1720" "target" "t18" "classname" "target_lightramp" "speed" "2" "message" "az" "targetname" "t29" } { "style" "44" "origin" "448 896 1720" "targetname" "t18" "spawnflags" "1" "light" "175" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "style" "44" "origin" "384 896 1720" "targetname" "t18" "spawnflags" "1" "light" "175" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "spawnflags" "0" "light" "100" "classname" "light" "origin" "-1344 -64 1936" } { "classname" "light" "light" "100" "origin" "-1056 -64 1936" } { "light" "100" "classname" "light" "origin" "-1952 -288 1632" } { "spawnflags" "2048" "classname" "target_steam" "angle" "270" "origin" "928 759 1488" "targetname" "steamage" "sounds" "4" "wait" "5" } { "spawnflags" "2048" "origin" "888 799 1488" "angle" "180" "classname" "target_steam" "targetname" "steamage" "sounds" "4" "wait" "5" } { "model" "*107" "origin" "416 804 1712" "classname" "func_door_rotating" "spawnflags" "2119" "distance" "120" "_minlight" ".3" "targetname" "windor1" "speed" "50" "wait" "6" "sounds" "4" } { "model" "*108" "team" "mush1" "target" "t17" "classname" "func_train" "targetname" "t37" } { "origin" "704 767 1536" "targetname" "t17" "target" "t15" "classname" "path_corner" } { "origin" "704 767 1536" "target" "t17" "targetname" "t16" "classname" "path_corner" "wait" "-1" "speed" "15" } { "origin" "704 767 1600" "target" "t16" "targetname" "t15" "classname" "path_corner" "speed" "150" "wait" ".5" } { "origin" "896 767 1536" "speed" "15" "target" "t14" "wait" "-1" "targetname" "t13" "classname" "path_corner" "pathtarget" "steam2" } { "origin" "896 767 1600" "speed" "150" "target" "t13" "targetname" "t12" "classname" "path_corner" "pathtarget" "steamage" "wait" ".5" } { "origin" "896 767 1536" "targetname" "t14" "target" "t12" "classname" "path_corner" } { "model" "*109" "team" "mush2" "target" "t14" "classname" "func_train" "targetname" "t37" } { "spawnflags" "2048" "origin" "736 759 1488" "angle" "270" "classname" "target_steam" "targetname" "steamage" "sounds" "4" "wait" "5" } { "model" "*110" "origin" "832 836 1560" "distance" "120" "spawnflags" "2119" "classname" "func_door_rotating" "_minlight" ".3" "targetname" "windor2" "speed" "50" "wait" "10" "sounds" "4" } { "origin" "-1632 152 1912" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1632 152 1592" } { "spawnflags" "2048" "origin" "-1760 -76 1544" "targetname" "t11" "classname" "target_secret" } { "model" "*111" "spawnflags" "2048" "target" "t11" "classname" "trigger_once" } { "model" "*112" "target" "t10" "angle" "90" "message" "You've opened a secret." "wait" "-1" "health" "1" "classname" "func_button" } { "model" "*113" "spawnflags" "2048" "health" "25" "classname" "func_explosive" } { "model" "*114" "spawnflags" "2048" "targetname" "t10" "lip" "-1" "angle" "-2" "classname" "func_door" "wait" "-1" } { "classname" "light" "light" "100" "origin" "-1248 152 1592" } { "origin" "-1440 152 1592" "light" "100" "classname" "light" } { "origin" "-1528 256 1608" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1056 152 1592" } { "origin" "-1248 152 1912" "light" "100" "classname" "light" } { "classname" "light" "light" "125" "origin" "-1216 -352 1664" } { "classname" "light" "light" "100" "origin" "-1440 152 1912" } { "origin" "-1472 -216 1912" "light" "100" "classname" "light" } { "origin" "-1280 -216 1912" "light" "100" "classname" "light" } { "origin" "-1056 152 1912" "light" "100" "classname" "light" } { "origin" "-1184 520 1632" "light" "125" "classname" "light" } { "model" "*115" "spawnflags" "2048" "target" "t1" "classname" "func_button" "angle" "0" "wait" "-1" "message" "Plant access granted." } { "spawnflags" "2048" "classname" "light" "light" "75" "origin" "-24 -960 1632" } { "origin" "-520 632 1368" "classname" "light" "light" "100" } { "origin" "640 -288 1796" "classname" "light" "light" "100" } { "origin" "-544 -704 1808" "classname" "light" "light" "125" } { "origin" "-192 -704 1808" "classname" "light" "light" "125" } { "origin" "1024 640 1808" "light" "100" "classname" "light" } { "model" "*116" "spawnflags" "2048" "classname" "func_door" "angle" "-2" "wait" "-1" } { "classname" "light" "light" "125" "origin" "-1184 680 1632" } { "classname" "light" "light" "100" "origin" "-1720 632 1960" } { "model" "*117" "spawnflags" "2048" "targetname" "t190" "message" "This door is locked." "wait" "-1" "angle" "-2" "classname" "func_door" } { "model" "*118" "spawnflags" "2048" "message" "Plant door is locked." "targetname" "t1" "classname" "func_door" "angle" "-2" "wait" "-1" } { "model" "*119" "classname" "func_plat2" "lip" "16" "spawnflags" "1" } { "origin" "-608 -608 1464" "classname" "light" "light" "75" } { "origin" "-608 -732 1464" "light" "75" "classname" "light" } { "origin" "-552 352 1344" "classname" "misc_explobox" } { "model" "*120" "classname" "func_explosive" "dmg" "75" "health" "5" } { "model" "*121" "target" "t177" "classname" "func_explosive" "dmg" "125" "health" "5" "mass" "200" } { "origin" "-552 296 1344" "classname" "misc_explobox" } { "origin" "-80 -1216 1416" "spawnflags" "1" "noise" "world/comp_hum1.wav" "classname" "target_speaker" } { "model" "*122" "classname" "trigger_hurt" "spawnflags" "4" "dmg" "1000" } { "model" "*123" "classname" "trigger_push" "angle" "270" } { "model" "*124" "origin" "-960 2522 1016" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*125" "origin" "-932 2522 1128" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*126" "origin" "-736 2522 1240" "team" "hole" "spawnflags" "2208" "_minlight" ".2" "distance" "77.5" "speed" "110" "classname" "func_door_rotating" "targetname" "holer" } { "model" "*127" "origin" "-540 2522 1128" "team" "hole" "spawnflags" "2208" "_minlight" ".2" "distance" "77.5" "speed" "110" "classname" "func_door_rotating" "targetname" "holer" } { "model" "*128" "origin" "-540 2522 904" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*129" "origin" "-624 2522 1212" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*130" "origin" "-512 2522 1016" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*131" "origin" "-848 2522 1212" "team" "hole" "spawnflags" "2208" "_minlight" ".2" "distance" "77.5" "speed" "110" "classname" "func_door_rotating" "targetname" "holer" } { "model" "*132" "origin" "-848 2522 820" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "model" "*133" "origin" "-932 2522 904" "team" "hole" "spawnflags" "2208" "_minlight" ".2" "distance" "77.5" "speed" "110" "classname" "func_door_rotating" "targetname" "holer" } { "model" "*134" "origin" "-624 2522 820" "team" "hole" "spawnflags" "2208" "_minlight" ".2" "distance" "77.5" "speed" "110" "classname" "func_door_rotating" "targetname" "holer" } { "model" "*135" "origin" "-736 2522 792" "targetname" "holer" "classname" "func_door_rotating" "speed" "110" "distance" "77.5" "_minlight" ".2" "spawnflags" "2208" "team" "hole" } { "origin" "-1280 384 1560" "classname" "light" "light" "125" "_color" "1.000000 0.148649 0.148649" } { "origin" "-1264 384 1632" "classname" "light" "light" "125" "_color" "1.000000 0.148649 0.148649" } { "origin" "-1184 384 1632" "classname" "light" "light" "125" "_color" "1.000000 0.148649 0.148649" } { "origin" "-1104 384 1632" "classname" "light" "light" "125" "_color" "1.000000 0.148649 0.148649" } { "origin" "-1088 384 1560" "_color" "1.000000 0.148649 0.148649" "light" "125" "classname" "light" } { "spawnflags" "2048" "target" "t171" "targetname" "t170" "origin" "-1280 340 1638" "classname" "path_corner" } { "spawnflags" "2048" "target" "t170" "targetname" "t171" "origin" "-1280 340 1540" "classname" "path_corner" } { "model" "*136" "target" "t170" "spawnflags" "2049" "classname" "func_train" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t59" "target" "t60" "origin" "128 -448 1746" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t60" "target" "t61" "origin" "128 -360 1746" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t69" "target" "t59" "origin" "128 -448 1632" } { "spawnflags" "2048" "origin" "128 -360 1746" "classname" "path_corner" "targetname" "t70" "target" "t71" } { "spawnflags" "2048" "origin" "128 -448 1746" "classname" "path_corner" "target" "t70" "targetname" "t80" } { "spawnflags" "2048" "origin" "128 -512 1632" "classname" "path_corner" "targetname" "t78" "target" "t79" } { "spawnflags" "2048" "origin" "128 -448 1632" "classname" "path_corner" "targetname" "t79" "target" "t80" } { "spawnflags" "2048" "classname" "path_corner" "origin" "128 -360 1746" "targetname" "t81" "target" "t82" } { "spawnflags" "2048" "classname" "path_corner" "origin" "128 -448 1746" "target" "t81" "targetname" "t91" } { "spawnflags" "2048" "classname" "path_corner" "origin" "128 -448 1632" "targetname" "t90" "target" "t91" } { "spawnflags" "2048" "classname" "path_corner" "origin" "128 -512 1632" "targetname" "t89" "target" "t90" } { "spawnflags" "2048" "origin" "16 -352 1392" "targetname" "t1" "target" "t92" "classname" "trigger_relay" } { "model" "*137" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t92" "target" "t94" } { "model" "*138" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t92" "target" "t93" } { "model" "*139" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t92" "target" "t97" } { "spawnflags" "2048" "delay" "1" "origin" "136 -176 1880" "classname" "trigger_relay" "targetname" "t97" "target" "t98" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t93" "origin" "136 -200 1880" "delay" "4" "target" "t95" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t94" "origin" "136 -232 1880" "delay" "6" "target" "t96" } { "spawnflags" "2048" "delay" "22" "origin" "368 -200 1880" "classname" "trigger_relay" "targetname" "t101" "target" "t102" } { "spawnflags" "2048" "delay" "24" "origin" "408 -200 1880" "classname" "trigger_relay" "targetname" "t103" "target" "t104" } { "model" "*140" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t92" "target" "t103" } { "model" "*141" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t92" "target" "t101" } { "model" "*142" "spawnflags" "2048" "classname" "func_train" "targetname" "t98" "target" "t59" "_minlight" ".2" } { "model" "*143" "spawnflags" "2048" "classname" "func_train" "target" "t80" "targetname" "t102" "_minlight" ".2" } { "model" "*144" "classname" "func_train" "target" "t91" "spawnflags" "2048" "targetname" "t96" "_minlight" ".2" } { "model" "*145" "classname" "func_train" "target" "t80" "spawnflags" "2048" "targetname" "t95" "_minlight" ".2" } { "model" "*146" "spawnflags" "2048" "classname" "func_train" "target" "t91" "targetname" "t104" "_minlight" ".2" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t62" "wait" "-1" "target" "t63" "origin" "544 -512 1746" "pathtarget" "red1" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t61" "target" "t62" "origin" "544 -360 1746" } { "spawnflags" "2048" "origin" "672 -360 1746" "classname" "path_corner" "targetname" "t73" "target" "t74" "pathtarget" "red2" } { "spawnflags" "2048" "origin" "672 -360 1746" "classname" "path_corner" "targetname" "t71" "target" "t72" } { "spawnflags" "2048" "origin" "672 -512 1746" "wait" "4" "classname" "path_corner" "targetname" "t72" "target" "t73" "pathtarget" "red2" } { "spawnflags" "2048" "classname" "path_corner" "origin" "800 -360 1746" "targetname" "t84" "target" "t85" "pathtarget" "red3" } { "spawnflags" "2048" "classname" "path_corner" "origin" "800 -360 1746" "targetname" "t82" "target" "t83" } { "spawnflags" "2048" "classname" "path_corner" "wait" "4" "origin" "800 -512 1746" "targetname" "t83" "target" "t84" "pathtarget" "red3" } { "spawnflags" "2048" "origin" "1024 -360 1746" "classname" "path_corner" "targetname" "t74" "target" "t75" } { "spawnflags" "2048" "origin" "1024 -512 1746" "classname" "path_corner" "targetname" "t75" "target" "t76" } { "spawnflags" "2048" "classname" "path_corner" "origin" "1024 -512 1746" "targetname" "t86" "target" "t87" } { "spawnflags" "2048" "classname" "path_corner" "origin" "1024 -360 1746" "targetname" "t85" "target" "t86" } { "spawnflags" "2048" "origin" "1200 -512 1746" "classname" "path_corner" "targetname" "t76" "target" "t77" } { "spawnflags" "2048" "classname" "path_corner" "origin" "1200 -512 1746" "targetname" "t87" "target" "t88" } { "spawnflags" "2048" "classname" "path_corner" "origin" "1200 -512 1632" "targetname" "t77" "target" "t78" } { "spawnflags" "2048" "origin" "1200 -512 1632" "classname" "path_corner" "targetname" "t88" "target" "t89" }rogue-ROGUE_2_13/stuff/mapfixes/rbase1.ent000066400000000000000000002413021477320066100204420ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Fixed "WARNING: Entity used itself." // appearing during gameplay (b#1) // // A trigger_once that targets some monsters // also targets itself for some reason. // // 2. Fixed old classnames (b#2) // // 3. Fixed wrong/overlapping secret sound effects (b#3) // // 4. Added missing targetname to target_explosion (b#4) { "sounds" "10" "message" "Logistics Complex" "nextmap" "rbase2" "sky" "rogue1" "classname" "worldspawn" } { "classname" "misc_teleporter_dest" "spawnflags" "5888" "angle" "180" "targetname" "t221" "origin" "-1120 1216 216" } { "classname" "misc_teleporter" "spawnflags" "5888" "target" "t221" "origin" "2560 128 -296" } { "classname" "misc_teleporter_dest" "spawnflags" "5888" "angle" "270" "targetname" "t220" "origin" "-2144 2336 -232" } { "classname" "misc_teleporter" "spawnflags" "5888" "target" "t220" "origin" "1984 1792 24" } { "model" "*1" "message" "Doors locked." "wait" "4" "targetname" "t218" "spawnflags" "2052" "classname" "trigger_multiple" } { "model" "*2" "wait" "4" "target" "t219" "targetname" "t218" "spawnflags" "2052" "classname" "trigger_multiple" } { "killtarget" "4idiots" "target" "t218" "origin" "2184 128 -208" "targetname" "t39" "spawnflags" "2048" "classname" "trigger_relay" } { "classname" "item_sphere_vengeance" "spawnflags" "5888" "origin" "-416 -32 -496" } { "classname" "ammo_cells" "origin" "176 64 -496" } { "classname" "ammo_cells" "origin" "-264 -32 -496" } { "classname" "weapon_plasmabeam" "spawnflags" "5888" "origin" "0 128 -496" } { "spawnflags" "5888" "classname" "ammo_shells" "origin" "2272 -40 -304" } { "classname" "ammo_shells" "spawnflags" "5888" "origin" "2280 360 -304" } { "classname" "weapon_supershotgun" "spawnflags" "5888" "origin" "2272 128 -304" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "1504 416 -296" } { "classname" "weapon_etf_rifle" "spawnflags" "5888" "origin" "1392 336 -296" } { "classname" "ammo_flechettes" "spawnflags" "5888" "origin" "1360 400 -296" } { "classname" "ammo_shells" "spawnflags" "5888" "origin" "-1440 2216 -240" } { "classname" "weapon_supershotgun" "spawnflags" "5888" "origin" "-1504 2200 -240" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "1504 -224 -296" } { "spawnflags" "5888" "classname" "ammo_rockets" "origin" "1592 -96 -496" } { "classname" "ammo_rockets" "spawnflags" "5888" "origin" "1216 -80 -496" } { "classname" "weapon_rocketlauncher" "origin" "1408 -72 -496" "spawnflags" "5888" } { "spawnflags" "5888" "classname" "ammo_prox" "origin" "-224 448 -304" } { "classname" "ammo_prox" "spawnflags" "5888" "origin" "160 536 -304" } { "classname" "weapon_proxlauncher" "spawnflags" "5888" "origin" "0 376 -304" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "0 -168 -488" } { "classname" "info_player_deathmatch" "angle" "45" "spawnflags" "5888" "origin" "-1248 456 -232" } { "classname" "misc_teleporter" "spawnflags" "5888" "target" "t217" "origin" "928 72 -232" } { "classname" "misc_teleporter_dest" "spawnflags" "5888" "origin" "-672 760 24" "targetname" "t217" "angle" "90" } { "classname" "item_double" "spawnflags" "5888" "origin" "-672 840 24" } { "spawnflags" "5888" "classname" "ammo_cells" "origin" "-664 1576 -240" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "-832 912 -240" } { "classname" "weapon_hyperblaster" "spawnflags" "5888" "origin" "-680 1256 -240" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "1096 1464 -8" } { "classname" "info_player_deathmatch" "angle" "135" "origin" "1568 1672 24" } { "angle" "315" "classname" "info_player_deathmatch" "origin" "-840 1696 -232" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-384 888 -232" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "-1696 1368 -232" } { "classname" "item_sphere_defender" "spawnflags" "5888" "origin" "-1760 1312 16" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "-1760 1472 24" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-1024 1216 24" } { "spawnflags" "5888" "classname" "ammo_cells" "origin" "-1048 1320 208" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "-992 1880 112" } { "classname" "weapon_plasmabeam" "spawnflags" "5888" "origin" "-1208 1192 208" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-1856 1696 24" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "-2432 2080 -232" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-1696 1688 -232" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-1184 2048 -40" } { "classname" "weapon_rocketlauncher" "spawnflags" "5888" "origin" "-560 1696 16" } { "spawnflags" "5888" "classname" "ammo_rockets" "origin" "-680 1680 16" } { "classname" "weapon_chaingun" "spawnflags" "5888" "origin" "1312 1824 16" } { "spawnflags" "5888" "classname" "ammo_bullets" "origin" "1248 1768 16" } { "classname" "ammo_bullets" "spawnflags" "5888" "origin" "1632 2048 16" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "1632 2208 24" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "1848 -120 -296" } { "classname" "ammo_nuke" "spawnflags" "5888" "origin" "1024 376 -504" } { "model" "*3" "classname" "func_wall" "spawnflags" "2048" } { "model" "*4" "classname" "func_wall" "spawnflags" "2048" } { "target" "t216" "targetname" "t215" "origin" "-1472 1216 208" "spawnflags" "2048" "classname" "hint_path" } { "target" "t215" "targetname" "t214" "origin" "-1472 1560 208" "spawnflags" "2048" "classname" "hint_path" } { "target" "t214" "targetname" "t213" "origin" "-1472 1856 208" "spawnflags" "2048" "classname" "hint_path" } { "target" "t213" "targetname" "t212" "origin" "-1256 1856 208" "spawnflags" "2048" "classname" "hint_path" } { "target" "t212" "targetname" "t211" "origin" "-1024 1856 112" "spawnflags" "2048" "classname" "hint_path" } { "target" "t211" "targetname" "t210" "origin" "-1024 1712 64" "spawnflags" "2048" "classname" "hint_path" } { "target" "t210" "targetname" "t209" "origin" "-1056 1472 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t209" "targetname" "t208" "origin" "-1296 1472 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t208" "targetname" "t207" "origin" "-1472 1472 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t207" "origin" "-1616 1480 16" "spawnflags" "2049" "classname" "hint_path" } { "target" "t205" "targetname" "t204" "classname" "hint_path" "spawnflags" "2048" "origin" "-1856 1792 16" } { "target" "t206" "targetname" "t205" "classname" "hint_path" "spawnflags" "2048" "origin" "-1664 1792 16" } { "targetname" "t206" "classname" "hint_path" "spawnflags" "2049" "origin" "-1664 1544 16" } { "target" "t204" "origin" "-2304 1792 16" "spawnflags" "2049" "classname" "hint_path" } { "targetname" "t203" "origin" "-1664 1408 16" "spawnflags" "2049" "classname" "hint_path" } { "target" "t203" "targetname" "t202" "origin" "-1664 1216 -48" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t216" "classname" "hint_path" "spawnflags" "2049" "origin" "-1216 1216 208" } { "target" "t201" "targetname" "t200" "classname" "hint_path" "spawnflags" "2048" "origin" "-1944 1208 -128" } { "target" "t200" "targetname" "t199" "classname" "hint_path" "spawnflags" "2048" "origin" "-2056 1344 -176" } { "target" "t199" "targetname" "t198" "classname" "hint_path" "spawnflags" "2048" "origin" "-1944 1472 -224" } { "target" "t198" "targetname" "t197" "classname" "hint_path" "spawnflags" "2048" "origin" "-1664 1472 -240" } { "target" "t197" "targetname" "t196" "classname" "hint_path" "spawnflags" "2048" "origin" "-1472 1408 -240" } { "target" "t196" "classname" "hint_path" "spawnflags" "2049" "origin" "-1192 1408 -240" } { "targetname" "t195" "classname" "hint_path" "spawnflags" "2049" "origin" "-1152 1472 -240" } { "target" "t195" "targetname" "t194" "classname" "hint_path" "spawnflags" "2048" "origin" "-1152 1792 -240" } { "target" "t194" "classname" "hint_path" "spawnflags" "2049" "origin" "-1408 1792 -240" } { "target" "t193" "targetname" "t192" "origin" "-584 2056 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t192" "targetname" "t191" "origin" "-960 2048 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t191" "targetname" "t190" "origin" "-960 2176 16" "spawnflags" "2048" "classname" "hint_path" } { "target" "t190" "targetname" "t189" "origin" "-1256 2144 -48" "spawnflags" "2048" "classname" "hint_path" } { "target" "t189" "targetname" "t188" "origin" "-1472 2144 -240" "spawnflags" "2048" "classname" "hint_path" } { "target" "t188" "origin" "-1472 1832 -240" "spawnflags" "2049" "classname" "hint_path" } { "targetname" "t193" "classname" "hint_path" "spawnflags" "2049" "origin" "-576 1728 16" } { "targetname" "t187" "classname" "hint_path" "spawnflags" "2049" "origin" "-1536 1792 -240" } { "target" "t187" "targetname" "t186" "classname" "hint_path" "spawnflags" "2048" "origin" "-1856 1792 -240" } { "target" "t186" "targetname" "t185" "origin" "-2224 1792 -240" "classname" "hint_path" "spawnflags" "2048" } { "target" "t185" "origin" "-2144 2088 -240" "classname" "hint_path" "spawnflags" "2049" } { "target" "t202" "targetname" "t201" "origin" "-1792 1216 -48" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1536 -448 -456" "target" "t184" "targetname" "t183" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1408 -528 -432" "target" "t183" "targetname" "t182" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1304 -456 -400" "target" "t182" "targetname" "t181" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1280 -184 -304" "target" "t181" "targetname" "t180" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1536 -200 -496" "targetname" "t184" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1408 -40 -304" "targetname" "t179" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1408 256 -304" "target" "t179" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1408 -88 -304" "target" "t180" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1088 -64 -304" "targetname" "t178" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1368 -64 -304" "target" "t178" "spawnflags" "2049" "classname" "hint_path" } { "target" "t174" "targetname" "t173" "origin" "1856 512 -304" "classname" "hint_path" "spawnflags" "2048" } { "target" "t175" "targetname" "t174" "origin" "1696 640 -304" "classname" "hint_path" "spawnflags" "2048" } { "target" "t176" "targetname" "t175" "origin" "1216 640 -304" "classname" "hint_path" "spawnflags" "2048" } { "target" "t177" "targetname" "t176" "origin" "960 576 -304" "classname" "hint_path" "spawnflags" "2048" } { "targetname" "t177" "origin" "896 256 -304" "classname" "hint_path" "spawnflags" "2049" } { "target" "t173" "origin" "1856 256 -304" "spawnflags" "2049" "classname" "hint_path" } { "origin" "384 408 -304" "target" "t171" "targetname" "t170" "classname" "hint_path" "spawnflags" "2048" } { "origin" "400 104 -304" "target" "t172" "targetname" "t171" "classname" "hint_path" "spawnflags" "2048" } { "origin" "624 96 -304" "targetname" "t172" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-48 424 -304" "target" "t170" "spawnflags" "2049" "classname" "hint_path" } { "target" "t169" "targetname" "t168" "origin" "688 568 -424" "classname" "hint_path" "spawnflags" "2048" } { "target" "t168" "targetname" "t167" "origin" "248 560 -496" "classname" "hint_path" "spawnflags" "2048" } { "target" "t167" "origin" "32 560 -496" "classname" "hint_path" "spawnflags" "2049" } { "targetname" "t166" "spawnflags" "2049" "classname" "hint_path" "origin" "0 512 -496" } { "targetname" "t169" "spawnflags" "2049" "classname" "hint_path" "origin" "696 192 -304" } { "targetname" "t165" "spawnflags" "2049" "classname" "hint_path" "origin" "-24 560 -496" } { "target" "t165" "targetname" "t164" "origin" "-200 560 -496" "spawnflags" "2048" "classname" "hint_path" } { "target" "t164" "origin" "-416 512 -496" "spawnflags" "2049" "classname" "hint_path" } { "origin" "-488 152 -496" "target" "t163" "targetname" "t162" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-416 416 -496" "targetname" "t163" "classname" "hint_path" "spawnflags" "2049" } { "target" "t166" "origin" "0 216 -496" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-800 512 -240" "targetname" "t161" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-1216 512 -240" "target" "t161" "targetname" "t160" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1152 832 -240" "target" "t160" "targetname" "t159" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1152 1184 -240" "target" "t159" "targetname" "t158" "classname" "hint_path" "spawnflags" "2048" } { "origin" "-1152 1352 -240" "target" "t158" "classname" "hint_path" "spawnflags" "2049" } { "origin" "-424 -32 -496" "target" "t162" "spawnflags" "2049" "classname" "hint_path" } { "classname" "info_player_intermission" "angles" "10 135 0" "origin" "-128 1000 88" "spawnflags" "0" } { "classname" "monster_turret" "spawnflags" "6945" "angle" "0" "origin" "-1720 1792 -96" } { "angle" "0" "spawnflags" "7177" "classname" "monster_turret" "origin" "520 576 -344" } { "classname" "light" "light" "80" "origin" "2016 1792 160" } { "origin" "-672 1728 24" "message" "Return and collect\n data disk." "targetname" "t12" "spawnflags" "2048" "classname" "target_help" } { "origin" "-1432 1664 280" "angle" "0" "spawnflags" "3841" "classname" "monster_daedalus" } { "origin" "-1624 1176 164" "targetname" "t126" "angle" "-2" "spawnflags" "4001" "classname" "monster_turret" } { "origin" "-1968 1464 -40" "angle" "180" "target" "t126" "item" "ammo_cells" "spawnflags" "6913" "classname" "monster_daedalus" } { "angle" "-2" "origin" "-1440 1376 -72" "spawnflags" "2057" "classname" "monster_turret" } { "item" "ammo_grenades" "classname" "monster_gunner" "angle" "180" "spawnflags" "6913" "origin" "-1304 2144 -224" } { "targetname" "t118" "classname" "monster_turret" "angle" "-2" "spawnflags" "7073" "origin" "-1568 2080 100" } { "origin" "-1928 1832 -224" "targetname" "t113" "target" "t115" "angle" "180" "spawnflags" "3841" "classname" "monster_gunner" } { "origin" "-2048 1760 -80" "spawnflags" "3841" "angle" "90" "classname" "monster_daedalus" } { "origin" "1488 400 -288" "angle" "270" "spawnflags" "3841" "target" "t141" "item" "ammo_slugs" "classname" "monster_gladiator" } { "classname" "monster_turret" "spawnflags" "6945" "origin" "1408 32 -136" "angle" "-2" } { "item" "ammo_grenades" "origin" "1216 -80 -480" "angle" "45" "classname" "monster_gunner" "spawnflags" "6913" } { "classname" "monster_turret" "angle" "270" "spawnflags" "6945" "origin" "1408 128 -424" } { "item" "ammo_grenades" "origin" "472 344 -288" "spawnflags" "6913" "angle" "180" "classname" "monster_gunner" } { "origin" "872 648 -80" "angle" "270" "spawnflags" "3841" "classname" "monster_daedalus" } { "origin" "872 648 -80" "angle" "270" "spawnflags" "6913" "classname" "monster_hover" } { "angle" "90" "target" "t65" "spawnflags" "3841" "origin" "656 -136 -288" "classname" "monster_gladiator" } { "origin" "712 616 -424" "classname" "item_health" } { "classname" "monster_turret" "spawnflags" "3873" "angle" "0" "origin" "520 576 -344" } { "origin" "-384 -32 -480" "spawnflags" "2049" "angle" "180" "classname" "monster_gunner" } { "origin" "-344 40 -480" "classname" "ammo_cells" } { "origin" "-552 416 -480" "item" "ammo_shells" "spawnflags" "6401" "angle" "45" "classname" "monster_soldier" } { "origin" "-928 608 -224" "angle" "270" "spawnflags" "6913" "classname" "monster_gunner" } { "targetname" "t61" "classname" "monster_turret" "angle" "-2" "spawnflags" "4001" "origin" "-1152 608 -28" } { "origin" "-1056 1056 -28" "targetname" "t60" "angle" "-2" "spawnflags" "3985" "classname" "monster_turret" } { "targetname" "t157" "classname" "hint_path" "spawnflags" "2049" "origin" "-560 976 -240" } { "target" "t157" "targetname" "t156" "classname" "hint_path" "spawnflags" "2048" "origin" "-568 1264 -280" } { "target" "t156" "targetname" "t155" "classname" "hint_path" "spawnflags" "2048" "origin" "-280 1224 -304" } { "target" "t155" "targetname" "t154" "classname" "hint_path" "spawnflags" "2048" "origin" "112 968 -264" } { "target" "t154" "targetname" "t153" "classname" "hint_path" "spawnflags" "2048" "origin" "136 1144 -232" } { "target" "t153" "targetname" "t152" "classname" "hint_path" "spawnflags" "2048" "origin" "-40 1280 -184" } { "target" "t152" "targetname" "t151" "classname" "hint_path" "spawnflags" "2048" "origin" "-104 1544 -104" } { "target" "t151" "targetname" "t150" "classname" "hint_path" "spawnflags" "2048" "origin" "104 1752 -64" } { "target" "t147" "targetname" "t146" "spawnflags" "2048" "classname" "hint_path" "origin" "872 1304 -8" } { "target" "t148" "targetname" "t147" "spawnflags" "2048" "classname" "hint_path" "origin" "648 1440 -8" } { "target" "t150" "targetname" "t149" "classname" "hint_path" "spawnflags" "2048" "origin" "456 1864 -64" } { "target" "t149" "targetname" "t148" "origin" "656 1760 -24" "classname" "hint_path" "spawnflags" "2048" } { "target" "t146" "targetname" "t145" "origin" "1040 1472 -8" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1104 1736 -24" "target" "t145" "targetname" "t144" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1264 2032 -48" "target" "t144" "targetname" "t143" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1472 1856 16" "target" "t143" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1536 2232 328" "item" "ammo_cells" "angle" "270" "spawnflags" "3841" "classname" "monster_daedalus" } { "classname" "monster_daedalus" "spawnflags" "6913" "angle" "270" "item" "ammo_cells" "origin" "1496 2232 328" } { "origin" "-2048 2208 -204" "classname" "light" "light" "50" "_color" "1.000000 0.000000 0.000000" } { "origin" "-2240 2208 -204" "_color" "1.000000 0.000000 0.000000" "light" "50" "classname" "light" } { "origin" "2424 228 -268" "classname" "light" "light" "50" "_color" "1.000000 0.000000 0.000000" } { "origin" "2424 28 -268" "_color" "1.000000 0.000000 0.000000" "light" "50" "classname" "light" } { "classname" "target_goal" "spawnflags" "2048" "targetname" "t142" "origin" "-1216 1640 104" } { "spawnflags" "2048" "classname" "target_goal" "targetname" "t140" "origin" "0 184 -368" } { "classname" "item_armor_body" "origin" "-1280 1144 24" } { "classname" "monster_soldier_ss" "spawnflags" "2049" "item" "ammo_bullets" "angle" "180" "origin" "1640 168 -288" } { "classname" "monster_soldier" "origin" "1480 392 -296" "spawnflags" "7681" "item" "ammo_shells" "target" "t141" "angle" "270" } { "classname" "monster_gunner" "origin" "1496 408 -296" "spawnflags" "7425" "item" "ammo_grenades" "target" "t141" "angle" "270" } { "classname" "monster_gladiator" "angle" "270" "spawnflags" "6913" "origin" "1488 400 -288" "item" "ammo_slugs" "target" "t141" } { "classname" "point_combat" "spawnflags" "2049" "origin" "1408 96 -304" "targetname" "t141" } { "spawnflags" "2337" "angle" "-2" "classname" "monster_turret" "origin" "1640 224 -136" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "3593" "origin" "1640 224 -136" } { "classname" "light" "light" "60" "origin" "-1472 1904 -88" } { "classname" "target_help" "targetname" "t140" "spawnflags" "2049" "message" "Mission accomplished.\nReturn to Waterfront Storage" "origin" "-80 144 -400" } { "spawnflags" "2048" "classname" "target_help" "targetname" "t140" "message" "Use air vent to\n gain access to\n bridge controls." "origin" "80 144 -400" } { "classname" "key_commander_head" "origin" "0 144 -488" "targetname" "t99" "spawnflags" "2049" "target" "t140" } { "classname" "point_combat" "spawnflags" "2049" "angle" "90" "targetname" "t139" "origin" "0 32 -496" } { "model" "*5" "classname" "trigger_multiple" "wait" "4" "spawnflags" "2048" "message" "Security measures are offline." "targetname" "cehss" } { "model" "*6" "classname" "trigger_once" "target" "t138" "spawnflags" "2052" "targetname" "t35" } { "classname" "light" "light" "50" "origin" "1728 1680 80" } { "origin" "-1152 768 -56" "spawnflags" "2049" "noise" "world/fan1.wav" "classname" "target_speaker" } { "origin" "-1200 768 -40" "spawnflags" "2049" "noise" "world/fan1.wav" "classname" "target_speaker" } { "origin" "-1096 768 -40" "spawnflags" "2049" "noise" "world/fan1.wav" "classname" "target_speaker" } { "origin" "-2376 1792 -184" "target" "t137" "delay" "1" "targetname" "t4" "classname" "trigger_relay" } { "origin" "-1720 1792 -96" "angle" "0" "spawnflags" "3873" "classname" "monster_turret" } { "model" "*7" "classname" "func_explosive" "spawnflags" "2048" "targetname" "ex4" "health" "5" } { "model" "*8" "classname" "func_explosive" "spawnflags" "2048" "health" "5" "target" "t135" "targetname" "ex4" } { "origin" "520 576 -344" "classname" "monster_turret" "spawnflags" "6945" "angle" "0" } { "model" "*9" "target" "t39" "message" "Bridge enabled." "wait" "4" "angle" "0" "spawnflags" "5888" "classname" "func_button" "lip" "6" } { "origin" "1936 560 -296" "classname" "ammo_shells" } { "origin" "1368 544 -296" "classname" "ammo_slugs" } { "origin" "1296 536 -296" "classname" "item_health" } { "origin" "1512 536 -296" "classname" "item_health" } { "classname" "light" "light" "100" "origin" "1152 608 -192" } { "light" "50" "classname" "light" "origin" "1632 608 -160" } { "light" "100" "classname" "light" "origin" "1664 608 -192" } { "origin" "1408 128 -424" "classname" "monster_turret" "angle" "270" "spawnflags" "7177" } { "origin" "1408 128 -424" "spawnflags" "3873" "angle" "270" "classname" "monster_turret" } { "origin" "-776 512 -176" "target" "t136" "targetname" "t97" "delay" "1" "classname" "trigger_relay" } { "origin" "-856 512 -96" "light" "50" "classname" "light" } { "origin" "-992 552 -96" "message" "Dentention block located." "targetname" "t132" "spawnflags" "2049" "classname" "target_help" } { "model" "*10" "spawnflags" "2048" "targetname" "ex4" "classname" "func_explosive" "health" "5" } { "origin" "24 1792 -56" "classname" "item_health_large" } { "origin" "888 1264 -24" "classname" "item_health" } { "model" "*11" "targetname" "t57" "target" "t54" "spawnflags" "2048" "speed" "650" "classname" "func_train" } { "classname" "target_crosslevel_trigger" "targetname" "t110" "spawnflags" "2176" "origin" "-1424 1376 88" } { "targetname" "rb1b" "origin" "-2168 2440 -224" "classname" "info_player_coop" "angle" "270" "spawnflags" "2048" } { "targetname" "rb1b" "origin" "-2120 2488 -224" "classname" "info_player_coop" "angle" "270" "spawnflags" "3072" } { "targetname" "rb1b" "origin" "-2168 2504 -224" "classname" "info_player_coop" "angle" "270" "spawnflags" "2048" } { "targetname" "rb1b" "origin" "-2120 2408 -224" "angle" "270" "classname" "info_player_coop" "spawnflags" "2048" } { "classname" "light" "light" "100" "origin" "-2144 2368 -192" } { "targetname" "rb1a" "origin" "2696 160 -288" "classname" "info_player_coop" "angle" "180" "spawnflags" "2048" } { "targetname" "rb1a" "origin" "2680 96 -288" "classname" "info_player_coop" "angle" "180" "spawnflags" "2048" } { "targetname" "rb1a" "origin" "2632 160 -288" "angle" "180" "classname" "info_player_coop" "spawnflags" "2048" } { "targetname" "rb1a" "origin" "2608 96 -288" "angle" "180" "classname" "info_player_coop" "spawnflags" "2048" } { "origin" "2560 128 -256" "light" "125" "classname" "light" } { "targetname" "rb1" "angle" "180" "classname" "info_player_coop" "origin" "1992 1760 32" "spawnflags" "2048" } { "targetname" "rb1" "angle" "180" "classname" "info_player_coop" "origin" "2048 1728 32" "spawnflags" "2048" } { "targetname" "rb1" "angle" "180" "classname" "info_player_coop" "origin" "2048 1856 32" "spawnflags" "2048" } { "targetname" "rb1" "classname" "info_player_coop" "angle" "180" "origin" "1992 1824 32" "spawnflags" "2048" } { "origin" "-2112 2568 -136" "map" "rbase2$rb2a" "targetname" "t134" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*12" "angle" "90" "target" "t134" "classname" "trigger_multiple" "spawnflags" "2048" } { "origin" "-1408 1448 72" "delay" "2.3" "spawnflags" "2048" "target" "t133" "targetname" "t110" "classname" "trigger_relay" } { "origin" "-1408 1488 72" "spawnflags" "2048" "target" "t133" "targetname" "t110" "classname" "trigger_relay" } { "origin" "-1200 1688 72" "targetname" "t133" "noise" "world/dataspin.wav" "spawnflags" "2050" "classname" "target_speaker" } { "classname" "monster_soldier_ss" "angle" "315" "spawnflags" "2049" "origin" "-552 288 -480" } { "classname" "monster_soldier_ss" "angle" "270" "spawnflags" "7169" "item" "ammo_bullets" "origin" "-936 616 -224" } { "classname" "monster_gunner" "spawnflags" "3841" "angle" "270" "origin" "-936 616 -224" } { "classname" "item_health_large" "origin" "2408 16 -296" } { "classname" "item_health_large" "origin" "2408 240 -296" } { "origin" "1640 168 -216" "message" "New orders will\n be forthcoming." "spawnflags" "2048" "classname" "target_help" "targetname" "t39" } { "classname" "target_help" "targetname" "t132" "spawnflags" "2048" "message" "Eliminate Tank Commander\n and retrieve its head." "origin" "-992 472 -96" } { "model" "*13" "classname" "trigger_once" "spawnflags" "2048" "target" "t132" } { "targetname" "t135" "message" "Incoming marine D.O.A.\n Carry out his orders." "classname" "target_help" "spawnflags" "2049" "origin" "-792 1184 -224" } { "targetname" "t135" "classname" "target_help" "spawnflags" "2048" "origin" "-800 1328 -224" "message" "Access Logistics complex.\nLocate Dentention Block." } { "light" "50" "classname" "light" "origin" "1896 -128 -704" } { "light" "50" "classname" "light" "origin" "2048 -128 -704" } { "classname" "light" "light" "50" "origin" "1736 -128 -704" } { "model" "*14" "spawnflags" "2048" "classname" "func_wall" } { "origin" "1240 -168 -280" "light" "70" "classname" "light" } { "model" "*15" "targetname" "t90" "target" "t89" "spawnflags" "2052" "classname" "trigger_multiple" } { "origin" "-984 1896 120" "classname" "ammo_prox" } { "origin" "-984 1576 24" "classname" "item_health" } { "origin" "-984 1408 24" "classname" "item_health" } { "origin" "-1376 1632 24" "item" "ammo_bullets" "spawnflags" "2049" "angle" "0" "classname" "monster_soldier_ss" } { "origin" "-1488 1872 224" "targetname" "t131" "spawnflags" "2049" "angle" "315" "classname" "monster_gladiator" "item" "ammo_slugs" } { "origin" "-1016 1208 24" "classname" "monster_soldier" "spawnflags" "3585" "angle" "90" } { "origin" "-1056 1224 24" "spawnflags" "2305" "angle" "90" "classname" "monster_gunner" } { "origin" "-1280 1180 32" "targetname" "t130" "spawnflags" "2048" "classname" "target_explosion" } { "model" "*16" "targetname" "t13" "target" "t130" "spawnflags" "2048" "classname" "func_explosive" } { "origin" "-1432 1664 280" "angle" "0" "spawnflags" "7425" "classname" "monster_hover" } { "target" "t131" "origin" "-1440 1472 280" "classname" "monster_daedalus" "angle" "0" "spawnflags" "2049" } { "origin" "-1440 1664 280" "spawnflags" "6913" "angle" "0" "classname" "monster_daedalus" } { "angle" "270" "origin" "-1472 1336 352" "spawnflags" "2057" "classname" "monster_turret" } { "origin" "-1512 1120 216" "classname" "ammo_tesla" } { "origin" "-1432 1112 216" "classname" "item_health_large" } { "origin" "-1056 1216 224" "spawnflags" "2049" "angle" "180" "classname" "monster_medic_commander" "item" "ammo_cells" } { "origin" "-1624 1248 -240" "classname" "ammo_slugs" } { "origin" "-1632 1512 -240" "classname" "ammo_flechettes" // b#2: nails -> flechettes } { "origin" "-1376 1512 -232" "classname" "ammo_rockets" } { "origin" "-1696 1528 -192" "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum2.wav" } { "origin" "-1568 1528 -192" "noise" "world/comp_hum2.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-1440 1528 -192" "noise" "world/comp_hum2.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-1472 1296 -192" "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum2.wav" } { "origin" "-1664 1296 -192" "noise" "world/comp_hum2.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-1432 1248 -232" "classname" "item_health_large" } { "origin" "-1512 1248 -232" "classname" "item_health_large" } { "origin" "-1696 1280 -224" "item" "ammo_cells" "spawnflags" "2049" "angle" "45" "classname" "monster_medic_commander" } { "origin" "-1600 1648 16" "targetname" "t128" "angle" "180" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-1688 1896 32" "item" "ammo_grenades" "targetname" "t124" "target" "t128" "spawnflags" "2049" "angle" "270" "classname" "monster_gunner" } { "classname" "item_armor_shard" "origin" "-1824 1888 24" } { "origin" "-1624 1176 -40" "classname" "item_health_large" } { "light" "130" "classname" "light" "origin" "-1664 1440 96" } { "origin" "-1760 1440 32" "item" "ammo_bullets" "spawnflags" "2049" "angle" "0" "classname" "monster_soldier_ss" } { "origin" "-1760 1504 32" "item" "ammo_shells" "angle" "0" "spawnflags" "2049" "classname" "monster_soldier" } { "model" "*17" "spawnflags" "5888" "classname" "func_wall" } { "model" "*18" "spawnflags" "2048" "targetname" "t126" "target" "t127" "classname" "func_explosive" } { "origin" "-1624 1176 132" "targetname" "t127" "classname" "target_explosion" "spawnflags" "2048" } { "origin" "-1624 1176 164" "targetname" "t126" "classname" "monster_turret" "spawnflags" "7305" "angle" "-2" } { "origin" "-1624 1176 164" "targetname" "t126" "spawnflags" "7073" "classname" "monster_turret" "angle" "-2" } { "origin" "-1968 1472 -40" "target" "t126" "angle" "180" "spawnflags" "7169" "classname" "monster_hover" "item" "ammo_cells" } { "origin" "-1968 1456 -40" "target" "t126" "angle" "180" "spawnflags" "3841" "classname" "monster_daedalus" "item" "ammo_cells" } { "origin" "-1768 1320 32" "target" "t126" "angle" "315" "spawnflags" "2049" "item" "ammo_shells" "classname" "monster_soldier" } { "origin" "-1896 1800 8" "targetname" "t125" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-1888 1696 32" "item" "ammo_bullets" "targetname" "t124" "spawnflags" "2049" "target" "t125" "classname" "monster_gunner" } { "origin" "-1568 1760 24" "classname" "ammo_prox" } { "origin" "-1632 1888 24" "classname" "item_armor_shard" } { "origin" "-1888 1888 24" "classname" "item_armor_shard" } { "origin" "-1568 1824 24" "classname" "item_armor_shard" } { "model" "*19" //"targetname" "t124" // b#1: self-target "target" "t124" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "-2008 1688 16" "classname" "item_health_large" } { "model" "*20" "target" "t122" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "-616 2064 16" "targetname" "t121" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-576 1936 32" "angle" "90" "targetname" "t122" "target" "t121" "spawnflags" "7681" "classname" "monster_gunner" } { "origin" "-576 1936 32" "targetname" "t122" "target" "t121" "spawnflags" "2305" "angle" "90" "classname" "monster_gladiator" } { "item" "ammo_grenades" "origin" "-1304 2144 -224" "spawnflags" "3841" "angle" "180" "classname" "monster_gunner" } { "item" "ammo_bullets" "origin" "-1304 2144 -224" "angle" "180" "spawnflags" "7169" "classname" "monster_soldier_ss" } { "item" "ammo_shells" "origin" "-1184 2040 -32" "angle" "135" "spawnflags" "2049" "classname" "monster_soldier" } { "origin" "-1008 2176 16" "targetname" "t120" "classname" "point_combat" "spawnflags" "2048" } { "origin" "-960 2048 32" "target" "t120" "spawnflags" "2049" "angle" "90" "targetname" "t118" "classname" "monster_gunner" } { "origin" "-1568 2080 68" "spawnflags" "2048" "targetname" "t119" "classname" "target_explosion" } { "model" "*21" "target" "t119" "targetname" "t118" "spawnflags" "2048" "classname" "func_explosive" } { "model" "*22" "targetname" "t118" "spawnflags" "5888" "classname" "func_wall" } { "targetname" "t118" "classname" "monster_turret" "angle" "-2" "spawnflags" "7305" "origin" "-1568 2080 100" } { "targetname" "t118" "origin" "-1568 2080 100" "spawnflags" "4001" "angle" "-2" "classname" "monster_turret" } { "target" "t118" "origin" "-1128 2176 24" "spawnflags" "2049" "angle" "180" "classname" "monster_daedalus" } { "origin" "-1304 2088 -168" "classname" "item_health" } { "origin" "-1640 2008 -240" "classname" "ammo_slugs" } { "origin" "-1624 2208 -240" "classname" "item_health_small" } { "origin" "-1616 2104 -240" "classname" "item_health_small" } { "origin" "-1640 2160 -240" "classname" "item_health_small" } { "origin" "-1120 1864 -240" "classname" "ammo_tesla" } { "targetname" "t116" "spawnflags" "2049" "origin" "-1264 1736 -240" "classname" "point_combat" } { "targetname" "t117" "target" "t116" "origin" "-1184 1888 -224" "spawnflags" "2049" "angle" "270" "classname" "monster_gunner" } { "origin" "-1056 1704 -240" "classname" "ammo_rockets" } { "origin" "-1584 1704 -168" "classname" "item_armor_shard" } { "origin" "-1608 1896 -168" "classname" "item_armor_shard" } { "origin" "-1464 1696 -168" "classname" "item_armor_shard" } { "origin" "-1384 1704 -168" "classname" "item_armor_jacket" } { "origin" "-1816 1728 -232" "classname" "item_health_large" } { "origin" "-1368 1888 -232" "classname" "item_health_large" } { "origin" "-1952 1832 -224" "angle" "180" "spawnflags" "7425" "targetname" "t113" "target" "t115" "classname" "monster_soldier_ss" } { "target" "t117" "classname" "monster_soldier" "item" "ammo_shells" "spawnflags" "2049" "origin" "-1704 1688 -232" "angle" "90" } { "angle" "270" "origin" "-1896 1896 -232" "spawnflags" "2049" "item" "ammo_shells" "classname" "monster_soldier" } { "classname" "monster_soldier" "spawnflags" "3585" "angle" "90" "origin" "1888 -144 -288" } { "classname" "monster_soldier_ss" "angle" "0" "spawnflags" "2049" "targetname" "t4" "origin" "-2456 1792 32" } { "classname" "monster_daedalus" "angle" "90" "spawnflags" "6913" "origin" "-2048 1760 -80" } { "classname" "point_combat" "spawnflags" "2048" "targetname" "t115" "origin" "-2056 1824 -240" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "6913" "targetname" "t113" "target" "t115" "origin" "-1944 1832 -224" } { "classname" "point_combat" "spawnflags" "2048" "targetname" "t112" "origin" "-2240 1840 16" } { "classname" "monster_medic_commander" "spawnflags" "2049" "angle" "0" "target" "t112" "targetname" "t113" "item" "ammo_cells" "origin" "-2336 1824 32" } { "model" "*23" "classname" "trigger_once" "target" "t113" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t12" "target" "t111" "delay" "10" "origin" "-616 1712 32" "spawnflags" "2048" } { "classname" "target_speaker" "targetname" "t111" "spawnflags" "2048" "noise" "world/uplink.wav" "origin" "-600 1680 32" } { "origin" "-1472 1376 264" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1024 1856 176" } { "classname" "trigger_relay" "targetname" "t110" "target" "t14" "spawnflags" "2048" "origin" "-1448 1448 96" } { "classname" "trigger_relay" "targetname" "t110" "target" "t106" "spawnflags" "2048" "origin" "-1480 1448 8" } { "targetname" "t133" "classname" "target_speaker" "noise" "world/dataspin.wav" "spawnflags" "2050" "origin" "-1296 1688 72" } { "classname" "target_help" "targetname" "t110" "message" "Collect disk and\nreturn to\nTactical Command." "spawnflags" "2048" "origin" "-1496 1552 64" } { "model" "*24" "classname" "trigger_once" "spawnflags" "2052" "targetname" "t12" "target" "t110" } { "classname" "target_speaker" "noise" "world/dish1.wav" "spawnflags" "2048" "targetname" "t12" "origin" "-656 1688 72" } { "classname" "target_speaker" "noise" "world/dish1.wav" "spawnflags" "2048" "targetname" "t12" "origin" "-544 1688 72" } { "classname" "target_speaker" "targetname" "t12" "noise" "world/dish1.wav" "spawnflags" "2050" "origin" "-800 912 24" } { "classname" "target_speaker" "targetname" "t12" "noise" "world/dish1.wav" "spawnflags" "2050" "origin" "-552 912 24" } { "model" "*25" "spawnflags" "0" "classname" "func_wall" } { "model" "*26" "targetname" "t98" "target" "t107" "classname" "trigger_multiple" "spawnflags" "2052" } { "origin" "-1288 1632 48" "target" "t106" "targetname" "t104" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "-1120 1120 288" "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" } { "origin" "-1312 1112 288" "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" } { "origin" "-1216 1096 256" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-1296 1712 96" "noise" "world/comp_hum3.wav" "spawnflags" "2049" "classname" "target_speaker" } { "origin" "-1200 1712 96" "noise" "world/comp_hum3.wav" "spawnflags" "2049" "classname" "target_speaker" } { "origin" "-1248 1688 96" "noise" "world/comp_hum1.wav" "spawnflags" "2049" "classname" "target_speaker" } { "origin" "-1184 1736 256" "targetname" "t101" "spawnflags" "2050" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "origin" "-1184 1736 176" "targetname" "t101" "spawnflags" "2050" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "origin" "-1312 1736 256" "targetname" "t101" "spawnflags" "2050" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "origin" "-1312 1736 176" "targetname" "t101" "spawnflags" "2050" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "targetname" "t105" "origin" "-1048 1184 312" "message" "Realign satillite array to\n interface with capital ship." "classname" "target_help" "spawnflags" "2048" } { "model" "*27" "message" "Data disk accepted" "targetname" "t104" "classname" "trigger_once" } { "message" "Bring uplink online using\n communications terminal." "origin" "-1232 1536 24" "targetname" "t104" "classname" "target_help" "spawnflags" "2048" } { "model" "*28" "targetname" "carosel" "message" "Terminal locked, data disk required." "classname" "trigger_multiple" "spawnflags" "2048" } { "model" "*29" "killtarget" "lesorac" "targetname" "t104" "spawnflags" "2052" "target" "t105" "classname" "trigger_once" } { "killtarget" "carosel" "origin" "-1288 1592 48" "target" "t104" "item" "key_data_cd" "targetname" "t103" "classname" "trigger_key" "spawnflags" "2048" } { "model" "*30" "target" "t103" "classname" "trigger_multiple" "spawnflags" "2048" } { "targetname" "t104" "spawnflags" "2049" "origin" "-1248 1728 44" "classname" "key_data_cd" "target" "t142" } { "spawnflags" "2050" "noise" "world/l_hum2.wav" "origin" "-1272 1696 24" "targetname" "t102" "classname" "target_speaker" } { "spawnflags" "2050" "noise" "world/l_hum2.wav" "origin" "-1224 1696 24" "targetname" "t102" "classname" "target_speaker" } { "targetname" "t101" "origin" "-1312 1770 256" "spawnflags" "2120" "angle" "-2" "classname" "target_laser" } { "origin" "-1200 1624 256" "target" "t101" "spawnflags" "2048" "delay" ".5" "targetname" "t14" "classname" "trigger_relay" } { "origin" "-1232 1624 256" "target" "t102" "spawnflags" "2048" "delay" "1" "targetname" "t14" "classname" "trigger_relay" } { "targetname" "t101" "origin" "-1184 1770 256" "spawnflags" "2120" "angle" "-2" "classname" "target_laser" } { "targetname" "t14" "origin" "-1056 1048 264" "spawnflags" "72" "angle" "-1" "classname" "target_laser" } { "model" "*31" "targetname" "t106" "spawnflags" "2050" "classname" "func_wall" } { "model" "*32" "targetname" "t105" "spawnflags" "2052" "target" "t100" "classname" "trigger_once" } { "model" "*33" "targetname" "lesorac" "message" "Array controls locked." "wait" "5" "classname" "trigger_multiple" "spawnflags" "2048" } { "classname" "light" "light" "100" "origin" "-1696 1504 -192" } { "origin" "-1568 1504 -192" "light" "100" "classname" "light" } { "origin" "-1792 1472 -184" "light" "100" "classname" "light" } { "origin" "-1712 1344 -192" "light" "60" "classname" "light" } { "origin" "-1664 1312 -120" "light" "100" "classname" "light" } { "spawnflags" "2050" "noise" "world/l_hum2.wav" "targetname" "t14" "origin" "-1056 1072 308" "classname" "target_speaker" } { "spawnflags" "2050" "noise" "world/l_hum2.wav" "targetname" "t14" "origin" "-1056 1072 232" "classname" "target_speaker" } { "spawnflags" "2050" "noise" "world/l_hum2.wav" "targetname" "t14" "origin" "-1056 1072 384" "classname" "target_speaker" } { "origin" "-1312 1136 280" "classname" "light" "light" "100" } { "origin" "-1472 1280 328" "light" "125" "classname" "light" } { "light" "130" "classname" "light" "origin" "-1664 1568 96" } { "origin" "-1856 1216 16" "light" "100" "classname" "light" } { "origin" "-704 1280 -248" "target" "ex4" "targetname" "ex3" "classname" "trigger_relay" "delay" "2" "spawnflags" "2048" } { "classname" "info_player_start" "angle" "180" "targetname" "rb1" "origin" "2048 1792 32" } { "targetname" "rb1b" "classname" "info_player_start" "angle" "270" "origin" "-2144 2544 -224" } { "classname" "info_player_start" "angle" "180" "targetname" "rb1a" "origin" "2744 128 -288" } { "classname" "target_crosslevel_trigger" "targetname" "t99" "origin" "176 96 -280" "spawnflags" "2052" } { "classname" "monster_tank_commander" "angle" "270" "spawnflags" "2049" "targetname" "t35" "origin" "-8 88 -488" "deathtarget" "t99" "target" "t139" } { "classname" "light" "light" "125" "origin" "-1696 1216 64" } { "light" "125" "classname" "light" "origin" "-1472 1152 328" } { "light" "125" "classname" "light" "origin" "-1280 1152 384" } { "light" "125" "classname" "light" "origin" "-1088 1152 384" } { "classname" "light" "light" "100" "origin" "-1472 1216 232" } { "light" "80" "classname" "light" "origin" "-1056 1080 376" } { "classname" "light" "light" "80" "origin" "-1056 1080 224" } { "light" "100" "classname" "light" "origin" "-1504 1440 -120" } { "classname" "light" "light" "100" "origin" "-1504 1312 -120" } { "light" "100" "classname" "light" "origin" "-1664 1440 -120" } { "classname" "light" "light" "100" "origin" "-1440 1504 -192" } { "light" "100" "classname" "light" "origin" "-1376 1312 -120" } { "classname" "light" "light" "100" "origin" "-1376 1440 -120" } { "origin" "-2176 2568 -208" "message" "Uplink to capitol ship\n to reprogram data disk." "targetname" "t98" "spawnflags" "2049" "classname" "target_help" } { "message" "Locate and enable satellite\n uplink to capitol ship." "origin" "-2104 2568 -208" "targetname" "t98" "classname" "target_help" "spawnflags" "2048" } { "model" "*34" "target" "t98" "classname" "trigger_once" "spawnflags" "2048" } { "message" "Disable laser grid and\n obtain commander's head." "origin" "-224 480 -224" "targetname" "t35" "spawnflags" "2048" "classname" "target_help" } { "targetname" "t96" "origin" "-112 560 -448" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "origin" "-424 512 -448" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "origin" "-480 224 -448" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "origin" "-480 -32 -448" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "origin" "-128 -32 -344" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/klaxon1.wav" "origin" "160 560 -448" } { "targetname" "t96" "origin" "128 -32 -344" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/klaxon1.wav" "origin" "-128 192 -344" } { "targetname" "t96" "origin" "128 192 -344" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "origin" "0 416 -272" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t96" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/klaxon1.wav" "origin" "328 200 -272" } { "targetname" "t96" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/klaxon1.wav" "origin" "328 416 -272" } { "targetname" "t96" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/klaxon1.wav" "origin" "-208 416 -272" } { "origin" "-1352 1680 8" "targetname" "t13" "classname" "target_secret" "message" "You found a secret." // b#3: moved here "spawnflags" "2048" } { "origin" "-1280 1152 24" "light" "60" "classname" "light" } { "origin" "-800 552 -216" "light" "60" "classname" "light" } { "origin" "-552 416 -472" "light" "60" "classname" "light" } { "model" "*35" "target" "t97" "wait" "2" "_minlight" ".3" "angle" "90" "classname" "func_button" } { "model" "*36" "wait" "2" "_minlight" ".3" "target" "t97" "angle" "180" "classname" "func_button" } { "origin" "800 376 -296" "classname" "item_health_large" } { "origin" "864 32 -232" "classname" "item_health_large" } { "origin" "-552 -32 -488" "classname" "item_armor_shard" } { "origin" "-496 -96 -488" "classname" "item_armor_shard" } { "origin" "-552 -88 -488" "classname" "item_armor_shard" } { "origin" "-352 -104 -488" "classname" "ammo_flechettes" // b#2: nails -> flechettes } { "origin" "-416 168 -488" "classname" "item_health_large" } { "origin" "-352 168 -488" "classname" "ammo_tesla" } { "origin" "-552 88 -488" "classname" "ammo_prox" } { "origin" "-216 384 -272" "targetname" "t78" "target" "t96" "spawnflags" "2048" "classname" "trigger_relay" } { "origin" "-224 448 -272" "target" "t96" "spawnflags" "2048" "targetname" "t35" "classname" "trigger_relay" } { "targetname" "t96" "origin" "328 -24 -272" "noise" "world/klaxon1.wav" "spawnflags" "2050" "classname" "target_speaker" } { "spawnflags" "2048" "origin" "-136 0 -480" "item" "ammo_bullets" "targetname" "t35" "target" "t93" "angle" "270" "classname" "monster_soldier" } { "origin" "176 -24 -496" "targetname" "t95" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-248 -32 -496" "targetname" "t94" "spawnflags" "2049" "classname" "point_combat" } { "origin" "0 -112 -496" "targetname" "t93" "angle" "90" "spawnflags" "2049" "classname" "point_combat" } { "origin" "160 256 -496" "targetname" "t92" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-144 248 -496" "targetname" "t91" "spawnflags" "2049" "classname" "point_combat" } { "origin" "-2464 2176 -240" "classname" "ammo_flechettes" // b#2: nails -> flechettes } { "origin" "-1944 2120 -240" "classname" "ammo_grenades" } { "origin" "-2464 1976 -240" "classname" "ammo_grenades" } { "origin" "-1976 2040 -240" "classname" "weapon_grenadelauncher" } { "origin" "-1968 1968 -256" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "origin" "1544 -32 -296" "classname" "ammo_cells" } { "origin" "1360 424 -296" "classname" "ammo_rockets" "spawnflags" "2048" } { "origin" "1328 360 -296" "classname" "weapon_rocketlauncher" "spawnflags" "2048" } { "origin" "1304 432 -320" "spawnflags" "2064" "classname" "misc_deadsoldier" "angle" "270" } { "origin" "1904 400 -24" "spawnflags" "2305" "angle" "315" "classname" "monster_daedalus" } { "origin" "1752 88 -288" "item" "ammo_shells" "angle" "45" "spawnflags" "3585" "classname" "monster_soldier" } { "angle" "90" "origin" "1824 -144 -288" "spawnflags" "2305" "classname" "monster_gunner" "item" "ammo_bullets" } { "angle" "-2" "origin" "1408 32 -136" "spawnflags" "3873" "classname" "monster_turret" } { "angle" "-2" "origin" "1632 608 -136" "spawnflags" "2849" "classname" "monster_turret" } { "item" "ammo_cells" "origin" "2368 128 -288" "spawnflags" "2049" "angle" "180" "classname" "monster_medic_commander" } { "origin" "1184 608 -160" "classname" "light" "light" "50" } { "origin" "1408 544 -192" "light" "100" "classname" "light" } { "classname" "func_group" } { "origin" "1472 192 -192" "classname" "light" "light" "125" } { "origin" "1344 192 -192" "classname" "light" "light" "125" } { "origin" "1344 384 -192" "light" "125" "classname" "light" } { "origin" "1472 384 -192" "classname" "light" "light" "125" } { "origin" "1600 224 -192" "light" "100" "classname" "light" } { "origin" "1816 -128 -728" "classname" "item_health_small" } { "origin" "1896 -128 -728" "classname" "item_health_small" } { "origin" "1968 -128 -728" "classname" "item_health_small" } { "origin" "1720 -128 -728" "classname" "item_health_small" } { "origin" "352 -224 -296" "spawnflags" "2048" "classname" "item_armor_combat" } { "origin" "2048 -128 -728" "classname" "item_armor_combat" } { "classname" "func_group" } { "model" "*37" "spawnflags" "2048" "classname" "func_wall" } { "model" "*38" "classname" "func_button" "angle" "180" "spawnflags" "2048" "wait" "-1" "target" "t90" "message" "Door unlocked." } { "angle" "-2" "spawnflags" "2849" "classname" "monster_turret" "origin" "1184 608 -136" } { "angle" "-2" "classname" "monster_turret" "spawnflags" "3081" "origin" "1184 608 -136" } { "angle" "-2" "spawnflags" "3081" "classname" "monster_turret" "origin" "1632 608 -136" } { "classname" "monster_turret" "spawnflags" "7177" "origin" "1408 32 -136" "angle" "-2" } { "classname" "light" "light" "75" "angle" "-2" "origin" "1088 432 -496" } { "origin" "1088 480 -496" "angle" "-2" "light" "90" "classname" "light" } { "origin" "960 432 -496" "angle" "-2" "light" "75" "classname" "light" } { "classname" "ammo_shells" "origin" "1232 -208 -496" } { "classname" "item_health_small" "origin" "1376 -224 -488" } { "classname" "item_health_small" "origin" "1432 -224 -488" } { "classname" "item_health_small" "origin" "1320 -224 -488" } { "spawnflags" "3841" "classname" "monster_gunner" "angle" "45" "origin" "1216 -80 -480" "item" "ammo_grenades" } { "angle" "135" "classname" "monster_gunner" "spawnflags" "3841" "origin" "1592 -96 -480" "item" "ammo_bullets" } { "classname" "monster_gunner" "angle" "90" "spawnflags" "2049" "origin" "1536 -248 -480" "item" "ammo_bullets" } { "classname" "monster_hover" "angle" "0" "spawnflags" "2049" "target" "t88" "origin" "1304 -480 -232" } { "classname" "item_health" "origin" "1440 -232 -296" } { "classname" "monster_gunner" "angle" "135" "spawnflags" "2049" "origin" "1512 -232 -288" } { "classname" "monster_turret" "origin" "1408 -612 -256" "targetname" "t88" "angle" "90" "spawnflags" "2177" } { "classname" "target_explosion" "origin" "1408 -580 -256" "targetname" "t87" "spawnflags" "2048" } { "model" "*39" "classname" "func_wall" "spawnflags" "5888" } { "model" "*40" "classname" "func_explosive" "spawnflags" "2048" "target" "t87" "targetname" "t88" } { "light" "60" "classname" "light" "origin" "1552 -112 -160" } { "light" "125" "classname" "light" "origin" "1472 -64 -200" } { "classname" "item_health_large" "origin" "1248 32 -296" } { "classname" "target_help" "targetname" "t39" "spawnflags" "2049" "message" "Return to Waterfront\n Storage Facility." "origin" "1632 240 -216" } { "model" "*41" "lip" "6" "classname" "func_button" "spawnflags" "2048" "angle" "0" "wait" "-1" "message" "Bridge enabled." "target" "t39" } { "model" "*42" "classname" "func_wall" "spawnflags" "2048" } { "classname" "light" "light" "80" "origin" "-96 512 -280" } { "spawnflags" "5888" "classname" "item_armor_body" "origin" "352 -224 -296" } { "classname" "monster_soldier" "spawnflags" "7169" "origin" "472 352 -288" "item" "ammo_shells" "angle" "180" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "3841" "origin" "472 360 -288" "item" "ammo_grenades" } { "classname" "monster_medic" "angle" "90" "spawnflags" "2049" "targetname" "t86" "origin" "352 -176 -288" } { "classname" "item_armor_shard" "origin" "352 544 -304" } { "classname" "item_armor_shard" "origin" "288 544 -304" } { "classname" "item_armor_shard" "origin" "416 544 -304" } { "classname" "monster_gladiator" "angle" "0" "spawnflags" "2049" "origin" "-192 424 -288" "target" "t86" "item" "ammo_slugs" } { "classname" "item_health_small" "origin" "1056 200 -296" } { "classname" "item_health_small" "origin" "1056 248 -296" } { "classname" "item_health_small" "origin" "1056 296 -296" } { "classname" "item_health_small" "origin" "1056 152 -296" } { "model" "*43" "classname" "func_wall" "spawnflags" "0" } { "classname" "light" "light" "90" "origin" "352 -192 -280" } { "item" "ammo_bullets" "target" "t95" "targetname" "t35" "classname" "monster_soldier_ss" "angle" "270" "origin" "32 0 -480" "spawnflags" "2049" } { "item" "ammo_bullets" "target" "t94" "targetname" "t35" "classname" "monster_soldier_ss" "angle" "270" "origin" "-136 104 -480" "spawnflags" "2049" } { "target" "t91" "targetname" "t35" "classname" "monster_soldier_ss" "angle" "270" "origin" "-8 184 -480" "spawnflags" "2049" } { "target" "t92" "targetname" "t35" "classname" "monster_soldier_ss" "angle" "270" "origin" "112 152 -480" "spawnflags" "2049" } { "spawnflags" "2048" "classname" "info_notnull" "team" "rightlaser" "targetname" "t84" "origin" "176 -192 -448" } { "spawnflags" "2048" "classname" "info_notnull" "team" "rightlaser" "targetname" "t85" "origin" "176 -192 -480" } { "spawnflags" "2048" "classname" "info_notnull" "team" "rightlaser" "targetname" "t83" "origin" "176 -192 -416" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t79" "target" "t80" "origin" "176 312 -536" } { "spawnflags" "2048" "classname" "path_corner" "targetname" "t81" "target" "t82" "origin" "176 312 -536" } { "spawnflags" "2048" "classname" "path_corner" "target" "t79" "targetname" "t82" "origin" "176 -192 -536" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t80" "target" "t81" "origin" "-200 312 -536" } { "model" "*44" "classname" "func_train" "spawnflags" "2050" "target" "t82" "team" "rightlaser" "targetname" "t74" } { "classname" "trigger_relay" "origin" "-64 8 -376" "target" "t74" "targetname" "t78" "spawnflags" "2048" } { "classname" "trigger_relay" "target" "t73" "delay" "5" "origin" "56 8 -376" "targetname" "t78" "spawnflags" "2048" } { "spawnflags" "2048" "origin" "-176 -192 -448" "classname" "info_notnull" "team" "leftlaser" "targetname" "t76" } { "spawnflags" "2048" "origin" "-176 -192 -416" "classname" "info_notnull" "team" "leftlaser" "targetname" "t77" } { "spawnflags" "2048" "classname" "info_notnull" "origin" "-176 -192 -480" "team" "leftlaser" "targetname" "t75" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t69" "target" "t70" "origin" "-192 312 -536" } { "model" "*45" "spawnflags" "2050" "classname" "func_train" "target" "t72" "targetname" "t74" "team" "leftlaser" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t71" "target" "t72" "origin" "-192 312 -536" } { "classname" "path_corner" "spawnflags" "2048" "target" "t69" "targetname" "t72" "origin" "-192 -192 -536" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t70" "target" "t71" "origin" "184 312 -536" } { "classname" "trigger_relay" "origin" "-64 32 -344" "targetname" "t35" "delay" "5" "target" "t74" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "56 32 -344" "targetname" "t35" "target" "t73" "spawnflags" "2048" } { "model" "*46" "classname" "func_button" "angle" "90" "lip" "4" "_minlight" ".3" "wait" "-1" "spawnflags" "2048" "target" "t15" "message" "Containment fields deactivated." } { "origin" "-896 1280 -248" "delay" ".6" "spawnflags" "2048" "targetname" "ex5" "classname" "target_explosion" "dmg" "150" } { "target" "ex4" "dmg" "150" "origin" "-880 1248 -240" "spawnflags" "2048" "targetname" "ex5" "classname" "target_explosion" } { "origin" "-920 1208 -256" "delay" ".2" "spawnflags" "2048" "targetname" "ex5" "classname" "target_explosion" } { "origin" "-896 1216 -248" "delay" ".6" "spawnflags" "2048" "targetname" "ex5" "classname" "target_explosion" "dmg" "150" } { "origin" "-24 440 -480" "spawnflags" "2049" "angle" "90" "classname" "monster_soldier" "targetname" "t67" } { "origin" "392 8 -464" "classname" "item_health_large" } { "classname" "misc_deadsoldier" "spawnflags" "2056" "item" "ammo_rockets" "origin" "384 168 -488" "angle" "270" } { "origin" "384 216 -464" "spawnflags" "5888" "classname" "ammo_rockets" } { "model" "*47" "spawnflags" "2048" "angle" "-1" "classname" "func_door" "targetname" "t86" "wait" "-1" } { "origin" "336 -112 -512" "item" "ammo_cells" "spawnflags" "2064" "classname" "misc_deadsoldier" "angle" "90" } { "origin" "992 608 -576" "angle" "-2" "light" "125" "classname" "light" } { "classname" "ammo_rockets" "origin" "424 464 -488" } { "model" "*48" "classname" "func_wall" "spawnflags" "2054" "targetname" "t15" } { "spawnflags" "2049" "classname" "point_combat" "targetname" "t68" "origin" "232 560 -504" } { "classname" "monster_gunner" "angle" "135" "spawnflags" "2049" "origin" "280 472 -488" "item" "ammo_grenades" "target" "t68" "targetname" "t67" } { "model" "*49" "classname" "trigger_once" "spawnflags" "2048" "target" "t67" } { "model" "*50" "classname" "func_wall" "spawnflags" "5888" } { "model" "*51" "classname" "func_explosive" "target" "t66" "spawnflags" "2048" "targetname" "t67" } { "classname" "target_explosion" "targetname" "t66" "spawnflags" "2048" "origin" "-544 512 -316" } { "classname" "monster_turret" "spawnflags" "2185" "angle" "-2" "targetname" "t67" "origin" "-544 512 -284" } { "item" "ammo_shells" "spawnflags" "2049" "angle" "315" "classname" "monster_soldier" "origin" "-552 616 -480" } { "classname" "monster_soldier" "angle" "45" "spawnflags" "3841" "item" "ammo_shells" "origin" "-552 416 -480" } { "classname" "item_armor_jacket" "origin" "-1056 696 -168" } { "classname" "item_armor_shard" "origin" "-344 616 -496" } { "classname" "item_armor_shard" "origin" "-296 616 -496" } { "classname" "item_armor_shard" "origin" "-392 616 -496" } { "classname" "item_health_large" "origin" "-296 424 -488" } { "classname" "monster_medic_commander" "spawnflags" "2049" "angle" "135" "targetname" "t65" "origin" "920 -88 -288" } { "classname" "monster_gunner" "spawnflags" "7169" "angle" "90" "target" "t65" "origin" "664 -136 -288" } { "classname" "monster_gladiator" "angle" "90" "spawnflags" "6913" "target" "t65" "origin" "656 -136 -288" } { "classname" "item_health_large" "origin" "-1048 1576 -240" } { "classname" "item_armor_shard" "origin" "-1240 1168 -232" } { "classname" "item_armor_shard" "origin" "-1240 1112 -232" } { "classname" "item_armor_shard" "origin" "-1240 1056 -232" } { "classname" "item_armor_shard" "origin" "-1240 1000 -232" } { "classname" "item_armor_shard" "origin" "-1248 1224 -232" } { "model" "*52" "classname" "func_wall" "spawnflags" "4096" } { "model" "*53" "classname" "func_explosive" "spawnflags" "3840" "targetname" "t60" "target" "t64" } { "classname" "target_explosion" "spawnflags" "3840" "targetname" "t64" "origin" "-1056 1504 -60" } { "classname" "monster_turret" "spawnflags" "4001" "angle" "-2" "targetname" "t60" "origin" "-1056 1504 -28" } { "classname" "target_explosion" "targetname" "t63" "spawnflags" "2304" "origin" "-1056 1056 -60" } { "model" "*54" "classname" "func_explosive" "spawnflags" "2816" "target" "t63" "targetname" "t60" } { "model" "*55" "classname" "func_wall" "spawnflags" "5120" } { "classname" "monster_turret" "spawnflags" "7049" "angle" "-2" "targetname" "t60" "origin" "-1056 1056 -28" } { "classname" "item_health_large" "origin" "-856 616 -232" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t62" "origin" "-936 432 -240" } { "spawnflags" "2049" "angle" "180" "classname" "monster_soldier_ss" "origin" "-1048 568 -224" } { "classname" "monster_soldier_ss" "angle" "180" "spawnflags" "2049" "target" "t62" "item" "ammo_bullets" "origin" "-880 432 -224" } { "_color" "0.000000 0.501961 1.000000" "light" "125" "classname" "light" "origin" "-1216 432 -160" } { "model" "*56" "classname" "trigger_once" "spawnflags" "2048" "target" "t61" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t59" "origin" "-1184 800 -248" } { "classname" "monster_gunner" "angle" "45" "spawnflags" "2049" "target" "t59" "targetname" "t60" "origin" "-1248 680 -224" "item" "ammo_grenades" } { "model" "*57" "classname" "func_wall" "spawnflags" "5632" } { "model" "*58" "classname" "func_explosive" "spawnflags" "2304" "targetname" "t61" } { "classname" "target_explosion" "targetname" "t61" // b#4: added this "spawnflags" "2304" "origin" "-1152 608 -60" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "6537" "origin" "-1152 608 -28" "targetname" "t61" } { "classname" "monster_soldier" "angle" "90" "spawnflags" "2048" "origin" "-1056 1040 -224" "target" "t60" } { "item" "ammo_bullets" "classname" "monster_gunner" "angle" "315" "spawnflags" "2049" "origin" "-1232 1536 -224" } { "classname" "light" "light" "80" "origin" "-1256 1696 -208" } { "model" "*59" "targetname" "t107" "classname" "func_door" "angle" "-2" "_minlight" ".3" "sounds" "2" "message" "Access denied." "spawnflags" "2048" "wait" "-1" } { "targetname" "ex3" "origin" "-640 1216 -200" "delay" ".2" "spawnflags" "2048" "classname" "target_explosion" } { "targetname" "ex2" "origin" "-336 1224 -32" "spawnflags" "2048" "classname" "target_explosion" } { "targetname" "ex1" "origin" "-24 1240 144" "spawnflags" "2048" "classname" "target_explosion" } { "origin" "128 1216 208" "delay" ".2" "targetname" "t57" "classname" "target_explosion" "spawnflags" "2048" } { "origin" "128 1144 208" "delay" ".2" "targetname" "t57" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*60" "killtarget" "scardead" "health" "2" "target" "t57" "mass" "500" "spawnflags" "2048" "classname" "func_explosive" } { "origin" "188 1180 236" "spawnflags" "2048" "targetname" "scardead" "classname" "info_notnull" } { "origin" "-704 1480 8" "killtarget" "scardead" "target" "t56" "targetname" "t55" "classname" "target_anger" "spawnflags" "2048" } { "model" "*61" "target" "t55" "classname" "trigger_once" "spawnflags" "2048" } { "pathtarget" "ex5" "speed" "850" "spawnflags" "2048" "targetname" "t53" "classname" "path_corner" "origin" "-970 1188 -320" } { "pathtarget" "ex3" "speed" "800" "spawnflags" "2048" "target" "t53" "targetname" "t52" "origin" "-642 1188 -200" "classname" "path_corner" } { "pathtarget" "ex2" "speed" "750" "spawnflags" "2048" "target" "t52" "targetname" "t51" "classname" "path_corner" "origin" "-330 1188 -32" } { "pathtarget" "ex1" "speed" "700" "spawnflags" "2048" "target" "t51" "targetname" "t50" "origin" "-18 1180 144" "classname" "path_corner" } { "spawnflags" "2048" "targetname" "t54" "target" "t50" "origin" "270 1172 240" "classname" "path_corner" } { "classname" "point_combat" "wait" "10" "targetname" "t49" "origin" "-800 1576 112" "spawnflags" "2048" } { "spawnflags" "3585" "angle" "135" "classname" "monster_hover" "origin" "32 1336 168" "target" "t49" "item" "ammo_cells" } { "classname" "monster_hover" "angle" "135" "spawnflags" "2817" "origin" "128 960 -240" } { "classname" "monster_daedalus" "angle" "135" "spawnflags" "2305" "origin" "32 1344 168" "target" "t49" "item" "ammo_cells" } { "classname" "item_health_large" "origin" "-216 1472 -184" } { "classname" "ammo_slugs" "spawnflags" "0" "origin" "112 1304 -56" } { "classname" "weapon_railgun" "spawnflags" "5888" "origin" "56 1344 -56" } { "classname" "item_health_small" "origin" "296 1928 -56" } { "classname" "item_health_small" "origin" "368 1952 -56" } { "classname" "item_health_small" "origin" "224 1912 -56" } { "classname" "monster_medic_commander" "angle" "315" "spawnflags" "2049" "origin" "-848 1696 -224" "targetname" "t58" } { "model" "*62" "classname" "trigger_once" "spawnflags" "2048" "target" "t47" } { "model" "*63" "classname" "func_wall" "spawnflags" "5888" } { "classname" "target_explosion" "spawnflags" "2048" "targetname" "t48" "origin" "1666 1980 240" } { "model" "*64" "classname" "func_explosive" "spawnflags" "2048" "targetname" "t47" "target" "t48" } { "classname" "monster_turret" "spawnflags" "2185" "angle" "180" "origin" "1700 1984 240" "targetname" "t47" } { "origin" "800 1312 0" "item" "ammo_bullets" "spawnflags" "2049" "angle" "0" "classname" "monster_gunner" } { "origin" "1280 2208 16" "classname" "weapon_proxlauncher" } { "message" "Rendevous at entrance \n with incoming marine." "origin" "2096 1832 104" "targetname" "t46" "classname" "target_help" "spawnflags" "2048" } { "message" "Locate entrance to \n Logistics Complex." "origin" "2096 1752 104" "spawnflags" "2049" "targetname" "t46" "classname" "target_help" } { "model" "*65" "target" "t46" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*66" "classname" "func_button" "angle" "270" "_minlight" ".3" "wait" "2" "message" "Lift activated." "target" "t4" } { "targetname" "t56" "spawnflags" "2049" "classname" "monster_gladiator" "angle" "0" "origin" "-584 1480 -240" "target" "t58" } { "item" "ammo_cells" "classname" "monster_daedalus" "angle" "135" "spawnflags" "3841" "origin" "1568 1704 408" } { "classname" "item_sphere_hunter" "spawnflags" "5888" "origin" "1640 2112 80" } { "classname" "item_health_large" "origin" "1576 2128 24" } { "classname" "item_health_large" "origin" "1416 2240 24" } { "item" "ammo_bullets" "classname" "monster_soldier_ss" "spawnflags" "2049" "target" "t43" "targetname" "t42" "origin" "1080 1496 8" } { "item" "ammo_shells" "classname" "monster_soldier" "spawnflags" "2305" "target" "t44" "targetname" "t42" "origin" "1024 1496 8" } { "classname" "point_combat" "origin" "1216 2080 -16" "spawnflags" "2048" "targetname" "t43" } { "classname" "point_combat" "spawnflags" "2048" "origin" "1000 1736 -16" "targetname" "t44" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t41" "origin" "1616 1952 8" } { "classname" "monster_soldier" "angle" "45" "spawnflags" "2049" "target" "t41" "origin" "1512 1864 24" } { "model" "*67" "classname" "trigger_once" "spawnflags" "2048" "target" "t42" } { "item" "ammo_grenades" "classname" "monster_gunner" "angle" "225" "spawnflags" "2049" "origin" "1672 2272 32" } { "classname" "ammo_prox" "origin" "1224 2220 24" } { "classname" "misc_deadsoldier" "spawnflags" "2050" "angle" "135" "origin" "1248 2160 0" } { "classname" "item_armor_shard" "origin" "1184 2184 24" } { "classname" "item_armor_shard" "origin" "1168 2136 24" } { "classname" "target_changelevel" "targetname" "t40" "map" "rware2$rw2b" "origin" "2776 96 -208" "spawnflags" "2048" } { "model" "*68" "angle" "0" "classname" "trigger_multiple" "target" "t40" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "2720 128 -256" } { "origin" "2016 568 -256" "classname" "light" "light" "120" } { "origin" "2016 672 -512" "classname" "light" "light" "120" } { "origin" "1904 672 -512" "classname" "light" "light" "120" } { "origin" "2016 568 -448" "light" "120" "classname" "light" } { "model" "*69" "targetname" "t219" "message" "Access denied." "spawnflags" "2048" "classname" "func_door" "angle" "-2" "_minlight" ".3" } { "model" "*70" "origin" "1916 254 -328" "targetname" "t39" "_minlight" ".3" "speed" "35" "spawnflags" "161" "classname" "func_door_rotating" "distance" "90" } { "model" "*71" "spawnflags" "2048" "classname" "func_wall" } { "model" "*72" "classname" "func_wall" "spawnflags" "2048" } { "model" "*73" "_minlight" ".3" "angle" "-1" "classname" "func_door" "spawnflags" "2048" } { "model" "*74" "message" "Access denied." "_minlight" ".3" "angle" "-1" "classname" "func_door" "targetname" "t89" "spawnflags" "2048" } { "origin" "1280 -224 -200" "classname" "light" "light" "120" } { "origin" "1472 -224 -200" "light" "120" "classname" "light" } { "origin" "1552 -16 -160" "classname" "light" "light" "60" } { "origin" "1344 -64 -200" "light" "125" "classname" "light" } { "origin" "272 288 -256" "classname" "light" "light" "80" } { "light" "80" "classname" "light" "origin" "272 96 -256" } { "origin" "224 496 -256" "classname" "light" "light" "80" } { "origin" "224 336 -256" "classname" "light" "light" "80" } { "origin" "432 288 -256" "classname" "light" "light" "80" } { "origin" "-32 496 -256" "light" "80" "classname" "light" } { "classname" "light" "light" "100" "origin" "448 0 -240" } { "origin" "448 192 -240" "light" "100" "classname" "light" } { "origin" "288 480 -456" "light" "100" "classname" "light" } { "origin" "192 560 -456" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "416 480 -456" } { "classname" "light" "light" "100" "origin" "0 560 -456" } { "origin" "-1216 1360 264" "light" "80" "classname" "light" } { "classname" "light" "light" "80" "origin" "-1088 1360 264" } { "classname" "light" "light" "100" "origin" "-192 416 -240" } { "origin" "96 512 -240" "light" "100" "classname" "light" } { "origin" "352 512 -240" "classname" "light" "light" "100" } { "origin" "448 416 -240" "classname" "light" "light" "100" } { "classname" "light" "light" "100" "origin" "304 192 -240" } { "origin" "304 0 -240" "light" "100" "classname" "light" } { "origin" "352 -64 -240" "light" "100" "classname" "light" } { "classname" "light" "light" "80" "_color" "1.000000 0.000000 0.000000" "origin" "544 128 -432" } { "model" "*75" "classname" "func_wall" "spawnflags" "2048" } { "spawnflags" "2180" "origin" "-154 -90 -480" "targetname" "t74" "dmg" "1000" "angle" "90" "classname" "target_laser" "target" "t85" } { "spawnflags" "2180" "origin" "-154 -90 -448" "targetname" "t74" "dmg" "1000" "angle" "90" "classname" "target_laser" "target" "t84" } { "spawnflags" "2180" "origin" "-154 -90 -416" "targetname" "t74" "classname" "target_laser" "angle" "90" "dmg" "1000" "target" "t83" } { "spawnflags" "2180" "origin" "154 -90 -448" "targetname" "t74" "classname" "target_laser" "angle" "90" "dmg" "1000" "target" "t76" } { "spawnflags" "2180" "origin" "154 -90 -480" "targetname" "t74" "classname" "target_laser" "angle" "90" "dmg" "1000" "target" "t75" } { "spawnflags" "2180" "origin" "154 -90 -416" "dmg" "1000" "targetname" "t74" "angle" "90" "classname" "target_laser" "target" "t77" } { "model" "*76" "lip" "-4" "wait" "-1" "speed" "30" "_minlight" ".3" "spawnflags" "2081" "angle" "-1" "classname" "func_door" "targetname" "t73" } { "model" "*77" "target" "t35" "_minlight" ".3" "lip" "4" "wait" "-1" "angle" "180" "classname" "func_button" "spawnflags" "2048" "message" "Security counter measures activated." "killtarget" "cehss" } { "origin" "-520 96 -448" "classname" "light" "light" "100" "_color" "1.000000 1.000000 0.501961" } { "origin" "-544 -32 -448" "classname" "light" "light" "100" "_color" "1.000000 1.000000 0.501961" } { "origin" "-896 448 -128" "classname" "light" "light" "100" } { "origin" "-896 576 -128" "light" "100" "classname" "light" } { "spawnflags" "2048" "origin" "432 -32 -432" "targetname" "t34" "classname" "target_explosion" } { "origin" "0 424 -456" "classname" "light" "light" "100" } { "origin" "-160 560 -456" "classname" "light" "light" "100" } { "origin" "-264 -32 -448" "light" "60" "classname" "light" } { "light" "125" "classname" "light" "origin" "-352 512 -280" } { "classname" "light" "light" "125" "origin" "-480 512 -280" } { "light" "150" "classname" "light" "origin" "-480 512 -400" } { "classname" "light" "light" "150" "origin" "-352 512 -400" } { "model" "*78" "spawnflags" "2048" "target" "t34" "classname" "func_explosive" "mass" "100" "_minlight" ".3" "health" "5" } { "model" "*79" "_minlight" ".3" "angle" "-2" "classname" "func_door" "spawnflags" "2048" } { "classname" "light" "light" "80" "origin" "-360 -32 -440" } { "model" "*80" "classname" "func_wall" "spawnflags" "2054" "_minlight" ".3" "targetname" "t15" } { "model" "*81" "classname" "func_wall" "spawnflags" "2054" "_minlight" ".3" "targetname" "t15" } { "origin" "-224 32 -456" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-224 -96 -456" } { "model" "*82" "classname" "func_button" "angle" "0" "_minlight" ".3" "wait" "-1" "spawnflags" "2048" "target" "t78" "message" "Security counter measures deactvated." "targetname" "t138" } { "origin" "-1024 512 -136" "classname" "light" "light" "100" } { "_color" "0.000000 0.501961 1.000000" "light" "125" "classname" "light" "origin" "-1056 432 -160" } { "classname" "light" "light" "100" "origin" "-1216 512 -136" } { "model" "*83" "spawnflags" "2048" "classname" "func_wall" } { "model" "*84" "targetname" "t136" "_minlight" ".3" "angle" "-1" "lip" "144" "classname" "func_plat2" "spawnflags" "36" } { "origin" "-688 512 -416" "light" "150" "classname" "light" } { "origin" "-688 512 -88" "classname" "light" "light" "80" } { "origin" "-688 512 -160" "light" "150" "classname" "light" } { "classname" "light" "light" "80" "origin" "64 304 -240" } { "origin" "-64 304 -240" "light" "80" "classname" "light" } { "origin" "-1216 1352 264" "light" "80" "classname" "light" } { "classname" "light" "light" "80" "origin" "-1088 1352 264" } { "classname" "light" "light" "125" "origin" "-1856 1792 56" } { "classname" "func_group" } { "light" "100" "classname" "light" "origin" "-704 2064 56" } { "light" "100" "classname" "light" "origin" "-576 1808 56" } { "light" "75" "classname" "light" "origin" "1728 1728 96" } { "model" "*85" "team" "camrod" "_minlight" ".3" "angle" "90" "classname" "func_door" } { "model" "*86" "team" "camrod" "_minlight" ".3" "angle" "270" "classname" "func_door" } { "origin" "2016 1680 96" "light" "180" "classname" "light" } { "origin" "1952 1712 96" "light" "100" "classname" "light" } { "origin" "1952 1872 96" "light" "100" "classname" "light" } { "origin" "2080 1872 96" "classname" "light" "light" "100" } { "origin" "2016 1904 96" "classname" "light" "light" "180" } { "origin" "2080 1712 96" "light" "100" "classname" "light" } { "_color" "1.000000 0.000000 0.000000" "origin" "1936 1792 160" "light" "50" "classname" "light" } { "origin" "1792 1792 96" "classname" "light" "light" "75" } { "origin" "1728 1856 96" "light" "75" "classname" "light" } { "light" "100" "classname" "light" "origin" "-512 1728 56" } { "classname" "target_changelevel" "targetname" "t9" "origin" "2072 1768 120" "map" "rware2$rw2a" "spawnflags" "2048" } { "model" "*87" "targetname" "4idiots" "classname" "trigger_multiple" "target" "t9" "angle" "0" "spawnflags" "2048" } { "spawnflags" "2048" "targetname" "t12" "classname" "misc_satellite_dish" "angle" "0" "origin" "-544 800 64" } { "origin" "-2144 2528 -192" "light" "100" "classname" "light" } { "light" "140" "origin" "640 1504 48" "classname" "light" } { "classname" "light" "origin" "896 1296 48" "light" "140" } { "classname" "light" "origin" "672 1312 48" "light" "140" } { "classname" "light" "origin" "664 1728 32" "light" "140" } { "classname" "light" "origin" "1032 1432 48" "light" "140" } { "classname" "light" "light" "100" "_color" "0.000000 0.501961 1.000000" "origin" "-2432 2144 -192" } { "origin" "-2240 2192 -72" "classname" "light" "light" "125" } { "origin" "-2048 2192 -72" "light" "125" "classname" "light" } { "origin" "-704 1728 56" "light" "100" "classname" "light" } { "model" "*88" "targetname" "t100" "target" "t12" "classname" "func_button" "angle" "270" "wait" "-1" "spawnflags" "2048" } { "model" "*89" "classname" "func_door" "angle" "-2" "_minlight" ".3" "sounds" "2" "spawnflags" "2048" } { "model" "*90" "spawnflags" "2048" "classname" "func_wall" } { "origin" "-576 1920 56" "classname" "light" "light" "100" } { "origin" "-584 2056 56" "classname" "light" "light" "100" } { "origin" "-832 2064 56" "classname" "light" "light" "100" } { "origin" "-2448 1792 -152" "light" "150" "classname" "light" } { "classname" "light" "light" "125" "origin" "-2240 2048 32" } { "light" "125" "classname" "light" "origin" "-2304 2048 -72" } { "spawnflags" "2048" "targetname" "t12" "origin" "-800 800 64" "angle" "0" "classname" "misc_satellite_dish" } { "classname" "light" "light" "125" "origin" "-2048 2048 32" } { "classname" "light" "light" "125" "origin" "-1984 2048 -72" } { "origin" "-2448 1792 152" "light" "80" "classname" "light" } { "origin" "-2144 2048 -72" "classname" "light" "light" "125" } { "origin" "-2432 2016 -192" "classname" "light" "light" "100" "_color" "0.000000 0.501961 1.000000" } { "origin" "-2520 2112 -240" "_color" "0.000000 0.501961 1.000000" "light" "75" "classname" "light" } { "light" "150" "classname" "light" "origin" "-2448 1792 104" } { "classname" "light" "light" "100" "origin" "-2448 1792 -16" } { "origin" "-1152 1632 -192" "light" "100" "classname" "light" } { "classname" "light" "light" "115" "origin" "-1152 1472 -136" } { "light" "100" "classname" "light" "origin" "-1472 1952 -192" } { "origin" "-1152 1792 -136" "light" "125" "classname" "light" } { "model" "*91" "targetname" "t98" "target" "t10" "spawnflags" "2052" "classname" "trigger_multiple" } { "light" "100" "classname" "light" "origin" "-992 1696 312" } { "classname" "light" "light" "100" "origin" "-992 1440 312" } { "light" "120" "classname" "light" "origin" "-1056 1568 312" } { "classname" "light" "light" "120" "origin" "-1152 1568 312" } { "origin" "-1184 1856 176" "light" "100" "classname" "light" } { "origin" "-1408 1856 312" "classname" "light" "light" "130" } { "origin" "-1216 1856 312" "classname" "light" "light" "130" } { "classname" "light" "light" "130" "origin" "-1024 1856 312" } { "classname" "light" "light" "115" "origin" "-1152 1216 -136" } { "classname" "light" "light" "115" "origin" "-1152 1344 -136" } { "origin" "-1152 1088 -136" "light" "115" "classname" "light" } { "classname" "light" "light" "125" "origin" "-1152 768 -120" } { "classname" "light" "light" "100" "origin" "-1080 696 -72" } { "origin" "-1080 840 -72" "light" "100" "classname" "light" } { "model" "*92" "origin" "-1152 768 32" "classname" "func_rotating" "_minlight" ".3" "spawnflags" "2051" "speed" "600" } { "origin" "-1152 928 -192" "classname" "light" "light" "100" } { "classname" "light" "light" "100" "origin" "-1024 1248 56" } { "light" "100" "classname" "light" "origin" "-1152 1312 56" } { "origin" "-1088 1280 256" "light" "120" "classname" "light" } { "targetname" "t102" "classname" "target_laser" "angle" "-2" "spawnflags" "2120" "origin" "-1248 1730 76" } { "model" "*93" "spawnflags" "2048" "targetname" "t105" "classname" "func_button" "angle" "270" "wait" "-1" "lip" "8" "target" "t14" "_minlight" ".3" } { "origin" "-1744 1632 96" "classname" "light" "light" "80" } { "origin" "-1472 1536 312" "classname" "light" "light" "130" } { "model" "*94" "target" "t13" "_minlight" ".3" "health" "1" "lip" "4" "wait" "-1" "angle" "0" "classname" "func_button" "spawnflags" "2048" } { "model" "*95" "targetname" "t137" "classname" "func_plat2" "lip" "144" "_minlight" ".2" "angle" "-2" "spawnflags" "32" } { "classname" "light" "light" "125" "origin" "-1472 1792 -136" } { "origin" "-2048 1728 -192" "classname" "light" "light" "125" "_color" "0.000000 0.501961 1.000000" } { "_color" "0.000000 0.501961 1.000000" "light" "125" "classname" "light" "origin" "-1856 1728 -192" } { "model" "*96" "targetname" "t10" "message" "Access denied." "sounds" "2" "_minlight" ".3" "angle" "-2" "classname" "func_door" "spawnflags" "2048" "wait" "-1" } { "model" "*97" "target" "t4" "angle" "270" "classname" "func_button" "message" "Lift activated." "wait" "2" "_minlight" ".3" } { "origin" "-2048 1792 56" "classname" "light" "light" "125" } { "origin" "-2240 1792 56" "classname" "light" "light" "125" } { "origin" "-1664 1792 56" "light" "125" "classname" "light" } { "origin" "-2240 1728 -192" "_color" "0.000000 0.501961 1.000000" "light" "125" "classname" "light" } { "origin" "-2208 1792 -192" "classname" "light" "light" "115" } { "origin" "-1984 1792 -192" "_color" "0.000000 0.501961 1.000000" "light" "125" "classname" "light" } { "origin" "-2048 1792 -136" "light" "125" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1312 1696 312" } { "classname" "light" "light" "100" "origin" "-1312 1440 312" } { "classname" "light" "light" "120" "origin" "-1248 1568 312" } { "origin" "-1472 1408 64" "classname" "light" "light" "110" } { "origin" "-1472 1728 312" "classname" "light" "light" "130" } { "light" "110" "classname" "light" "origin" "-1472 1536 64" } { "origin" "-1224 696 -72" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1224 840 -72" } { "classname" "light" "light" "100" "origin" "-1280 1248 56" } { "light" "100" "classname" "light" "origin" "-1120 1136 280" } { "origin" "-1280 1280 256" "classname" "light" "light" "120" } { "origin" "544 0 -432" "_color" "1.000000 0.000000 0.000000" "light" "80" "classname" "light" } { "_color" "1.000000 0.000000 0.000000" "light" "80" "classname" "light" "origin" "704 72 -432" } { "_color" "1.000000 0.000000 0.000000" "light" "80" "classname" "light" "origin" "864 64 -432" } { "_color" "1.000000 0.000000 0.000000" "light" "80" "classname" "light" "origin" "1024 64 -504" } { "_color" "1.000000 0.000000 0.000000" "light" "80" "classname" "light" "origin" "1024 256 -504" } { "angle" "-2" "light" "125" "classname" "light" "origin" "1056 608 -576" } { "classname" "light" "light" "90" "angle" "-2" "origin" "960 496 -496" } { "angle" "-2" "light" "150" "classname" "light" "origin" "992 608 -448" } { "classname" "light" "light" "150" "angle" "-2" "origin" "1056 608 -448" } { "classname" "light" "light" "125" "angle" "-2" "origin" "1408 256 -584" } { "angle" "-2" "light" "150" "classname" "light" "origin" "1408 256 -456" } { "angle" "-2" "light" "80" "classname" "light" "origin" "1504 64 -584" } { "classname" "light" "light" "150" "angle" "-2" "origin" "1504 160 -456" } { "origin" "1312 160 -456" "classname" "light" "light" "150" "angle" "-2" } { "origin" "1408 64 -584" "angle" "-2" "light" "80" "classname" "light" } { "targetname" "t32" "origin" "1060 256 -496" "spawnflags" "2053" "angle" "180" "classname" "target_laser" "dmg" "1000" } { "origin" "1080 184 -504" "spawnflags" "2049" "wait" "2.5" "random" "2" "target" "t32" "classname" "func_timer" } { "origin" "1032 256 -496" "targetname" "t32" "spawnflags" "1" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "origin" "1008 256 -496" "targetname" "t32" "classname" "target_speaker" "noise" "world/l_hum2.wav" "spawnflags" "1" } { "model" "*98" "origin" "1088 468 -496" "speed" "400" "_minlight" ".3" "spawnflags" "9" "classname" "func_rotating" } { "light" "80" "origin" "1304 40 -536" "classname" "light" } { "classname" "light" "origin" "1280 -32 -640" "light" "100" } { "light" "100" "origin" "1280 -32 -440" "classname" "light" } { "classname" "light" "origin" "1536 -32 -440" "light" "100" } { "classname" "light" "origin" "1536 -32 -640" "light" "100" } { "classname" "light" "origin" "1408 -32 -640" "light" "100" } { "classname" "light" "origin" "1304 40 -640" "light" "80" } { "classname" "light" "light" "125" "angle" "-2" "origin" "1312 160 -584" } { "origin" "1504 160 -584" "classname" "light" "light" "125" "angle" "-2" } { "classname" "light" "light" "80" "angle" "-2" "origin" "1312 64 -584" }rogue-ROGUE_2_13/stuff/mapfixes/rhangar2.ent000066400000000000000000003374051477320066100210030ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Made a monster_turret reachable (b#1) // // The turret spawns but is behind a func_door that never // opens. It has targetname t332 but is never targeted, so I set it // to t311 instead so it opens after pressing the console nearby. // // 2. Fixed nagging help message (b#2) // // This is more of a code bug but can be avoided by a mapfix too. // Basically trigger_always trigger during savegame loads when they // really shouldn't. It's harmless most of the time but target_help // modify the global game state which is not cleared at this point. // // 3. Fixed wrong/overlapping secret sound effect (b#3) // // 4. Fixed old classnames (b#4) { "spawnflags" "2" "angle" "0" "message" "Maintenance Hangars" "classname" "worldspawn" "sky" "rogue2" "nextmap" "rammo1" "sounds" "5" } { "classname" "item_enviro" "spawnflags" "2048" "origin" "776 1832 64" } { "model" "*1" "classname" "func_water" "spawnflags" "2048" "team" "argh1" } { "model" "*2" "classname" "trigger_hurt" "dmg" "4000" } { "model" "*3" "classname" "func_train" "spawnflags" "2050" "targetname" "arc" "target" "t148" } { "model" "*4" "classname" "func_train" "spawnflags" "2" "target" "t204" "targetname" "t206" } { "target" "t400" "origin" "-1272 1336 808" "spawnflags" "2049" "classname" "hint_path" } { "classname" "trigger_relay" "targetname" "t11" "delay" "0.3" // b#2: added this "killtarget" "t399" "target" "t11help" // b#2: added this "origin" "96 -480 8" } { "origin" "-584 840 664" "spawnflags" "6144" "classname" "weapon_bfg" } { "origin" "-592 904 648" "angle" "90" "spawnflags" "6148" "classname" "misc_deadsoldier" } { "model" "*5" "classname" "func_explosive" "targetname" "t294" } { "model" "*6" "wait" "-1" "targetname" "t367" "speed" "200" "sounds" "1" "angle" "-1" "classname" "func_door" } { "origin" "584 1440 280" "classname" "item_health_large" } { "origin" "-960 672 536" "spawnflags" "2048" "target" "t119" "targetname" "t126" "delay" ".5" "classname" "trigger_relay" } { "model" "*7" "wait" "-1" "targetname" "t311" "spawnflags" "2048" "sounds" "1" "lip" "4" "angle" "-2" "classname" "func_door" } { "classname" "info_player_intermission" "angles" "15 135 0" "origin" "-1032 1176 984" } { "classname" "item_health_large" "origin" "-736 1232 280" } { "classname" "trigger_always" "spawnflags" "2048" "target" "t11" "origin" "88 -456 8" "targetname" "t399" } { "origin" "72 208 272" "classname" "item_health_large" } { "origin" "1000 1568 280" "classname" "item_health" } { "origin" "-1280 1520 912" "targetname" "t398" "spawnflags" "1" "classname" "point_combat" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "-344 1800 104" } { "origin" "-568 576 664" "classname" "ammo_disruptor" } { "origin" "-584 840 664" "classname" "ammo_flechettes" // b#4: nails -> flechettes } { "origin" "-1136 1224 784" "classname" "ammo_flechettes" // b#4: nails -> flechettes } { "origin" "-1456 1224 784" "classname" "ammo_slugs" } { "origin" "-1120 1600 784" "classname" "ammo_prox" } { "origin" "-1448 1576 784" "classname" "ammo_rockets" } { "origin" "-1280 1544 912" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "origin" "-624 616 848" "classname" "item_health" } { "origin" "-592 1104 848" "classname" "ammo_cells" } { "origin" "-640 1000 848" "classname" "ammo_rockets" } { "origin" "128 672 656" "classname" "item_armor_jacket" } { "origin" "-72 1112 656" "classname" "ammo_shells" } { "origin" "-24 1112 656" "spawnflags" "5888" "classname" "weapon_supershotgun" } { "origin" "-384 600 664" "classname" "ammo_grenades" } { "origin" "-384 1184 664" "classname" "ammo_rockets" } { "origin" "-384 856 664" "classname" "item_health" } { "origin" "-616 840 544" "classname" "item_armor_shard" } { "origin" "-544 608 544" "classname" "ammo_cells" } { "origin" "-544 480 544" "classname" "ammo_rockets" } { "origin" "-544 552 544" "spawnflags" "1792" "classname" "weapon_plasmabeam" // b#4: heat -> plasma } { "origin" "-288 480 552" "angle" "180" "classname" "info_player_deathmatch" } { "origin" "712 2768 -176" "classname" "item_doppleganger" "spawnflags" "5888" } { "origin" "40 2528 -176" "spawnflags" "5888" "classname" "weapon_etf_rifle" // b#4: nailgun -> etf_rifle } { "origin" "-96 2528 -176" "classname" "ammo_flechettes" // b#4: nails -> flechettes } { "origin" "-224 2656 -168" "angle" "0" "classname" "info_player_deathmatch" } { "origin" "-152 2208 -112" "spawnflags" "1536" "classname" "ammo_tesla" } { "origin" "168 2104 -112" "classname" "item_health_small" } { "origin" "144 2232 -112" "classname" "item_armor_combat" } { "origin" "-80 1768 96" "spawnflags" "1536" "classname" "weapon_plasmabeam" // b#4: heat -> plasma } { "origin" "-80 1832 96" "classname" "ammo_cells" } { "origin" "776 1840 64" "spawnflags" "5888" "classname" "item_sphere_defender" } { "origin" "640 2656 -48" "spawnflags" "5888" "classname" "item_quad" } { "origin" "416 2040 64" "classname" "ammo_tesla" } { "origin" "416 2128 64" "classname" "ammo_prox" } { "origin" "416 2232 64" "classname" "ammo_disruptor" } { "origin" "-392 1792 112" "spawnflags" "0" "classname" "item_health_large" } { "origin" "-792 1960 144" "spawnflags" "5888" "classname" "weapon_supershotgun" } { "origin" "-808 1816 152" "angle" "0" "classname" "info_player_deathmatch" } { "origin" "-744 2016 144" "classname" "ammo_shells" } { "origin" "-736 1640 144" "classname" "ammo_cells" } { "origin" "272 -416 -64" "classname" "ammo_prox" } { "origin" "-736 1280 280" "spawnflags" "5888" "classname" "weapon_proxlauncher" } { "origin" "-736 1320 280" "classname" "ammo_prox" } { "origin" "-416 1248 280" "classname" "ammo_tesla" } { "origin" "480 288 280" "classname" "ammo_rockets" } { "origin" "208 320 280" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "origin" "480 544 280" "classname" "item_health" } { "model" "*8" "targetname" "t274" "spawnflags" "17" "dmg" "20" "classname" "trigger_hurt" } { "origin" "-80 1176 280" "classname" "item_health" } { "origin" "160 1464 280" "classname" "item_health" } { "origin" "728 792 368" "classname" "ammo_tesla" } { "origin" "672 800 376" "angle" "270" "classname" "info_player_deathmatch" } { "origin" "928 888 368" "classname" "item_health" } { "classname" "item_health_large" "origin" "1632 984 80" } { "classname" "item_armor_combat" "spawnflags" "1792" "origin" "1648 864 80" } { "classname" "item_armor_body" "spawnflags" "1792" "origin" "1648 864 80" } { "classname" "weapon_chainfist" "spawnflags" "5888" "origin" "1056 1560 280" } { "classname" "item_health_small" "spawnflags" "1536" "origin" "1344 656 272" } { "classname" "ammo_disruptor" "spawnflags" "0" "origin" "1072 912 368" } { "classname" "weapon_disintegrator" "origin" "1072 960 368" "spawnflags" "5888" } { "classname" "item_bandolier" "spawnflags" "5888" "origin" "1288 920 408" } { "classname" "item_sphere_hunter" "origin" "1288 808 408" "spawnflags" "5888" } { "classname" "item_health_mega" "spawnflags" "5888" "origin" "1520 864 56" } { "classname" "item_health" "origin" "880 480 272" } { "classname" "ammo_cells" "spawnflags" "1792" "origin" "872 648 272" } { "classname" "weapon_hyperblaster" "spawnflags" "5888" "origin" "872 560 272" } { "classname" "ammo_flechettes" // b#4: nails -> flechettes "origin" "-272 -1040 -64" } { "classname" "item_armor_shard" "spawnflags" "1792" "origin" "424 -176 184" } { "classname" "item_health" "spawnflags" "512" "origin" "416 -120 184" } { "classname" "item_health_large" "spawnflags" "1024" "origin" "408 -64 184" } { "classname" "info_player_deathmatch" "angle" "270" "origin" "-32 -16 280" } { "classname" "weapon_grenadelauncher" "origin" "-88 72 272" } { "classname" "ammo_grenades" "origin" "-144 72 272" } { "classname" "weapon_machinegun" "spawnflags" "5888" "origin" "112 16 -64" } { "classname" "ammo_bullets" "origin" "-120 48 -64" } { "classname" "ammo_shells" "origin" "-712 -136 -48" "spawnflags" "1024" } { "classname" "weapon_shotgun" "spawnflags" "1024" "origin" "-656 -136 -48" } { "classname" "item_armor_jacket" "spawnflags" "2048" "origin" "-456 -168 -256" } { "classname" "item_armor_shard" "origin" "-1048 -176 -240" } { "classname" "item_health" "spawnflags" "1792" "origin" "-240 -352 -256" } { "classname" "item_armor_jacket" "spawnflags" "1792" "origin" "-240 -416 -256" } { "classname" "weapon_railgun" "spawnflags" "5888" "origin" "-672 -736 -240" } { "classname" "ammo_slugs" "origin" "-744 -736 -240" } { "classname" "info_player_deathmatch" "origin" "-352 -416 -248" "angle" "180" } { "classname" "target_help" "targetname" "t397" "origin" "-152 1088 664" "message" "Destroy remaining resistance" } { "model" "*9" "classname" "trigger_once" "spawnflags" "2048" "target" "t397" } { "classname" "target_help" "message" "Use fighter lift to\nenter upper levels." "targetname" "jam" "origin" "-192 1776 136" } { "classname" "target_goal" "targetname" "jam" "origin" "-168 1768 120" } { "classname" "target_speaker" "spawnflags" "4" "attenuation" "-1" "noise" "world/yelforce.wav" "targetname" "jam" "origin" "-152 1768 120" } { "classname" "target_help" "origin" "168 2696 -104" "targetname" "t218" "spawnflags" "1" "message" "Gain access to\nResearch Hangar" } { "classname" "target_help" "message" "Return to sewer via pipe." "targetname" "t311" "origin" "-720 1912 184" } { "classname" "target_goal" "targetname" "t311" "origin" "-784 1944 168" } { "classname" "target_help" "origin" "48 -168 344" "spawnflags" "1" "message" "Gain entrance to waste\ndisposal control." "targetname" "t11help" // b#2: t11 -> t11help } { "model" "*10" "classname" "trigger_once" "target" "t315" "targetname" "t301" "spawnflags" "2052" } { "classname" "trigger_always" "target" "t386" "origin" "-448 392 464" } { "classname" "trigger_always" "spawnflags" "1792" "target" "t385" "origin" "832 968 88" } { "model" "*11" "classname" "func_train" "_minlight" ".2" "dmg" "1000" "spawnflags" "2" "target" "t40" "targetname" "t43" } { "classname" "trigger_always" "spawnflags" "1792" "target" "t395" "origin" "-752 -128 -16" } { "model" "*12" "classname" "func_button" "angle" "90" "target" "t395" } { "delay" "1" "classname" "trigger_relay" "killtarget" "t392" "targetname" "t302" "spawnflags" "2048" "origin" "512 -296 272" } { "classname" "trigger_relay" "spawnflags" "2048" "targetname" "t301" "target" "t392" "origin" "424 -288 272" } { "origin" "4000 -4068 -4068" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "origin" "-584 320 576" "light" "65" "classname" "light" } { "origin" "-32 2312 80" "light" "65" "classname" "light" } { "targetname" "t389" "origin" "-928 656 656" "classname" "point_combat" } { "origin" "1000 1456 272" "spawnflags" "1792" "target" "t265" "classname" "trigger_always" } { "model" "*13" "angle" "270" "target" "t385" "wait" "4" "classname" "func_button" } { "targetname" "iliketrafficlights" "noise" "world/lite_on3.wav" "origin" "760 880 56" "classname" "target_speaker" } { "delay" "1" "origin" "1080 984 120" "targetname" "iliketrafficlights" "target" "t43" "classname" "trigger_relay" } { "origin" "1072 776 376" "targetname" "t374" "target" "t310" "spawnflags" "1" "classname" "monster_infantry" } { "origin" "-120 -336 -168" "message" "You found a secret." // b#3: moved here "targetname" "t384" "classname" "target_secret" } { "model" "*14" "target" "t384" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*15" "spawnflags" "1792" "classname" "func_wall" } { "origin" "-88 -352 -160" "spawnflags" "2048" "classname" "item_pack" } { "model" "*16" "spawnflags" "2048" "health" "50" "dmg" "10" "classname" "func_explosive" } { "model" "*17" "spawnflags" "2048" "target" "t383" "classname" "trigger_once" } { "style" "32" "origin" "984 -400 360" "spawnflags" "1" "targetname" "t302" "light" "65" "classname" "light" } { "model" "*18" "spawnflags" "3072" "classname" "func_wall" } { "classname" "point_combat" "targetname" "t375" "origin" "648 2344 -112" "target" "t376" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "1" "target" "t375" "targetname" "t218" "origin" "640 2656 -40" } { "classname" "trigger_relay" "killtarget" "t372" "delay" "6" "targetname" "t373" "origin" "1400 840 288" } { "classname" "target_anger" "killtarget" "t372" "targetname" "t373" "target" "t374" "origin" "1376 824 288" } { "model" "*19" "classname" "trigger_once" "spawnflags" "2048" "target" "t373" } { "model" "*20" "classname" "func_train" "spawnflags" "2049" "team" "manlove" "target" "t371" } { "classname" "path_corner" "spawnflags" "2048" "origin" "1456 728 336" "target" "t370" "targetname" "t371" } { "classname" "info_notnull" "team" "manlove" "origin" "1268 752 372" "targetname" "t372" } { "classname" "trigger_relay" "targetname" "t89" "target" "t369" "origin" "-744 744 616" } { "delay" "2" "classname" "target_speaker" "noise" "world/lasburn1.wav" "targetname" "t369" "spawnflags" "2050" "origin" "-704 704 568" } { "model" "*21" "classname" "func_wall" "spawnflags" "6" "targetname" "t218" } { "classname" "target_spawner" "target" "item_double" "spawnflags" "2048" "targetname" "t300" "origin" "-416 120 -40" } { "classname" "light" "light" "100" "origin" "-1656 1408 960" } { "classname" "light" "_color" "1.000000 1.000000 0.501961" "light" "80" "origin" "-1280 1472 832" } { "target" "t388" "classname" "monster_berserk" "spawnflags" "257" "angle" "270" "origin" "-960 816 672" "targetname" "t368" } { "item" "ammo_rockets" "classname" "monster_turret" "spawnflags" "32" "angle" "-2" "target" "t368" "origin" "-960 704 896" } { "model" "*22" "classname" "trigger_once" "spawnflags" "2048" "target" "t367" } { "classname" "monster_berserk" "spawnflags" "1" "target" "t365" "angle" "270" "origin" "-384 1176 672" "targetname" "t367" } { "classname" "trigger_relay" "spawnflags" "2048" "target" "t363" "origin" "-344 1176 696" "targetname" "t365" } { "model" "*23" "classname" "func_explosive" "targetname" "t363" } { "classname" "monster_turret" "origin" "-384 1248 704" "spawnflags" "904" "angle" "270" "targetname" "t363" } { "classname" "item_adrenaline" "origin" "-320 1000 544" } { "target" "t387" "classname" "point_combat" "spawnflags" "0" "targetname" "t362" "origin" "-608 960 536" } { "classname" "monster_gunner" "angle" "270" "spawnflags" "1" "target" "t362" "origin" "-368 912 552" } { "classname" "light" "_color" "1.000000 1.000000 0.501961" "light" "70" "origin" "-264 768 536" } { "model" "*24" "classname" "func_wall" "spawnflags" "2054" "targetname" "t293" } { "classname" "monster_berserk" "angle" "180" "spawnflags" "769" "origin" "-288 480 552" } { "style" "33" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "125" "origin" "-312 832 608" "targetname" "t293" } { "classname" "target_speaker" "origin" "-360 832 568" "noise" "world/l_hum2.wav" "spawnflags" "2049" "targetname" "t293" } { "classname" "monster_turret" "spawnflags" "136" "angle" "0" "origin" "-680 2208 168" "targetname" "t218" } { "model" "*25" "classname" "func_explosive" "targetname" "t218" } { "classname" "point_combat" "targetname" "t346" "origin" "88 2176 104" "spawnflags" "1" } { "classname" "point_combat" "targetname" "t345" "spawnflags" "1" "origin" "-56 1896 88" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "-320 -8 64" } { "target" "t331" "origin" "456 528 288" "angle" "180" "spawnflags" "260" "classname" "monster_berserk" } { "spawnflags" "0" "origin" "-64 440 272" "targetname" "t326" "classname" "point_combat" } { "item" "ammo_grenades" "origin" "880 1104 376" "spawnflags" "1" "angle" "270" "classname" "monster_gunner" "targetname" "t396" } { "origin" "1312 864 240" "spawnflags" "8" "angle" "-2" "classname" "monster_turret" "target" "t385" } { "origin" "680 992 160" "spawnflags" "4" "angle" "0" "classname" "monster_floater" } { "origin" "672 768 160" "spawnflags" "4" "angle" "0" "classname" "monster_floater" } { "model" "*26" "spawnflags" "1" "classname" "func_plat2" "lip" "16" "_minlight" ".1" "targetname" "t395" } { "delay" "1" "target" "t325" "targetname" "t312" "origin" "-104 -1408 696" "classname" "trigger_relay" } { "item" "ammo_cells" "angle" "180" "origin" "-512 704 800" "spawnflags" "264" "classname" "monster_turret" } { "origin" "-1000 1144 1032" "angle" "135" "spawnflags" "800" "classname" "monster_turret" } { "spawnflags" "1" "targetname" "t321" "origin" "-536 1392 272" "classname" "point_combat" } { "target" "t321" "origin" "-408 1272 288" "angle" "180" "spawnflags" "5" "classname" "monster_gunner" "targetname" "t311" } { "target" "t318" "targetname" "t317" "origin" "-128 -840 704" "classname" "path_corner" } { "targetname" "t325" "target" "t317" "spawnflags" "2" "angle" "90" "origin" "-128 -1448 720" "classname" "monster_daedalus" } { "origin" "-448 328 320" "light" "75" "classname" "light" } { "spawnflags" "8" "angle" "270" "origin" "-576 1528 416" "classname" "monster_turret" } { "model" "*27" "lip" "24" "wait" "-1" "angle" "-1" "classname" "func_door" "targetname" "t311" // b#1: t332 -> t311 } { "spawnflags" "4" "classname" "monster_gunner" "angle" "270" "origin" "-448 1024 288" } { "model" "*28" "classname" "func_explosive" "targetname" "t315" } { "model" "*29" "classname" "trigger_once" "spawnflags" "2048" "target" "t314" } { "model" "*30" "classname" "func_explosive" "targetname" "t314" } { "classname" "monster_turret" "origin" "-296 640 416" "targetname" "t314" "angle" "0" "spawnflags" "136" } { "classname" "info_player_start" "origin" "-352 -224 -360" } { "classname" "target_changelevel" "targetname" "t313" "spawnflags" "2048" "map" "rsewer2$rhangar2a" "origin" "-336 -608 -368" } { "model" "*31" "classname" "trigger_multiple" "spawnflags" "2048" "target" "t313" } { "targetname" "rsewer2a" "origin" "-472 -144 -24" "angle" "45" "classname" "info_player_coop" } { "item" "ammo_bullets" "targetname" "t383" "spawnflags" "1" "origin" "72 208 280" "angle" "90" "classname" "monster_infantry" } { "origin" "-32 928 664" "targetname" "hobbit" "spawnflags" "1537" "angle" "270" "classname" "monster_medic" } { "origin" "-32 848 664" "targetname" "hobbit" "spawnflags" "257" "angle" "270" "classname" "monster_medic_commander" } { "origin" "-800 1880 168" "targetname" "t311" "spawnflags" "2049" "classname" "target_crosslevel_trigger" } { "origin" "-824 1904 168" "target" "t312" "message" "Primary Entrance Door open!" "targetname" "t311" "classname" "trigger_relay" } { "model" "*32" "targetname" "t312" "classname" "func_explosive" } { "targetname" "t312" "origin" "224 800 552" "angle" "-2" "spawnflags" "136" "classname" "monster_turret" } { "model" "*33" "targetname" "t265" "classname" "func_explosive" } { "origin" "1136 872 360" "spawnflags" "1" "targetname" "t310" "classname" "point_combat" } { "model" "*34" "spawnflags" "2048" "target" "t309" "classname" "trigger_once" } { "spawnflags" "1" "targetname" "t308" "origin" "864 968 360" "classname" "point_combat" } { "targetname" "t309" "target" "t308" "origin" "672 800 376" "spawnflags" "1" "angle" "90" "classname" "monster_gunner" } { "targetname" "t303" "origin" "1000 1552 272" "classname" "point_combat" } { "target" "t305" "origin" "1344 1136 288" "angle" "270" "spawnflags" "4" "classname" "monster_gunner" "item" "ammo_bullets" } { "targetname" "t265" "origin" "1120 1504 552" "spawnflags" "136" "angle" "-2" "classname" "monster_turret" "item" "ammo_cells" } { "origin" "1336 1094 438" "angle" "-2" "spawnflags" "264" "classname" "monster_turret" "item" "ammo_cells" } { "origin" "-88 -328 128" "killtarget" "donna" "targetname" "t11" "classname" "trigger_relay" } { "origin" "152 -408 128" "targetname" "donna" "target" "t301" "classname" "trigger_always" } { "model" "*35" "target" "t302" "targetname" "t392" "spawnflags" "2312" "classname" "trigger_multiple" } { "origin" "-416 124 -56" "targetname" "t300" "spawnflags" "2" "angle" "300" "classname" "monster_mutant" } { "origin" "-328 2152 -8" "targetname" "t300" "classname" "target_secret" "message" "You released the Mutant!" // b#3: moved this here } { "origin" "-408 8 16" "target" "t300" "targetname" "t299" "classname" "trigger_relay" "spawnflags" "7936" // b#3: added this } { "model" "*36" "mass" "800" "dmg" "1" "health" "101" "target" "t300" // b#3: t299 -> t300 "targetname" "t218" "spawnflags" "2057" "classname" "func_explosive" } { "origin" "-392 2248 104" "killtarget" "t298" "targetname" "mhowell" "classname" "trigger_relay" } { "model" "*37" "targetname" "t298" "message" "Locked!" "wait" "7" "spawnflags" "2048" "classname" "trigger_multiple" } { "origin" "-160 2704 -168" "angle" "270" "targetname" "rsewer2b" "classname" "info_player_coop" } { "origin" "-24 2872 -168" "angle" "270" "targetname" "rsewer2b" "classname" "info_player_start" } { "model" "*38" "spawnflags" "2048" "target" "t297" "classname" "trigger_multiple" } { "spawnflags" "2048" "targetname" "t297" "map" "rsewer2$rhangar2b" "origin" "-8 2832 -160" "classname" "target_changelevel" } { "origin" "184 2160 -40" "_color" "1.000000 1.000000 0.501961" "light" "80" "classname" "light" } { "model" "*39" "wait" "-1" "spawnflags" "2048" "target" "mhowell" "angle" "90" "classname" "func_button" } { "model" "*40" "target" "jam" "wait" "-1" "message" "Force fields deactivated." "spawnflags" "2048" "angle" "270" "classname" "func_button" } { "origin" "-272 704 672" "targetname" "t125" "spawnflags" "2" "angle" "180" "classname" "monster_gunner" "target" "t352" } { "model" "*41" "message" "Forcefield Deactivated" "wait" "-1" "target" "t120" "spawnflags" "2048" "angle" "0" "classname" "func_button" "_minlight" ".2" } { "targetname" "t237" "spawnflags" "770" "origin" "-1280 1880 920" "angle" "270" "classname" "monster_medic_commander" "deathtarget" "porkin" } { "origin" "-1308 1692 1028" "targetname" "t294" "target" "t237" "spawnflags" "2048" "delay" "1" "classname" "trigger_relay" } { "targetname" "t294" "origin" "-1280 1408 1064" "angle" "-2" "spawnflags" "128" "classname" "monster_turret" } { "origin" "-1128 1440 1064" "light" "140" "classname" "light" } { "model" "*42" "classname" "func_button" "angle" "0" "spawnflags" "0" "target" "t293" } { "dmg" "2000" "classname" "target_laser" "spawnflags" "2057" "angle" "180" "origin" "-281 832 564" "targetname" "t293" } { "map" "rhangar1$rhangar2" "origin" "-1224 1968 904" "targetname" "t292" "classname" "target_changelevel" } { "model" "*43" "angle" "90" "target" "t292" "spawnflags" "2048" "classname" "trigger_multiple" } { "origin" "-640 640 808" "light" "100" "classname" "light" } { "origin" "-688 704 672" "spawnflags" "1" "classname" "point_combat" "targetname" "t352" } { "targetname" "t89" "origin" "-744 696 528" "spawnflags" "2048" "target" "t290" "classname" "func_timer" "wait" ".1" } { "model" "*44" "targetname" "t89" "target" "t288" "speed" "20" "spawnflags" "2048" "team" "bff" "classname" "func_train" } { "spawnflags" "2048" "targetname" "t288" "target" "t285" "origin" "-680 656 528" "classname" "path_corner" } { "team" "bff" "sounds" "224" "count" "64" "speed" "100" "spawnflags" "2048" "targetname" "t290" "origin" "-690 648 528" "classname" "target_steam" "angle" "180" } { "origin" "-896 704 664" "spawnflags" "2048" "classname" "item_armor_body" } { "model" "*45" "targetname" "t125" "wait" "-1" "spawnflags" "2048" "angle" "90" "classname" "func_door_secret" } { "model" "*46" "targetname" "t386" "spawnflags" "1" "lip" "16" "classname" "func_plat2" } { "model" "*47" "team" "dumbass" "targetname" "hobbit" "target" "t267" "spawnflags" "2" "_minlight" ".1" "classname" "func_train" } { "wait" "-1" "target" "t284" "targetname" "t283" "origin" "-496 635 548" "classname" "path_corner" } { "model" "*48" "targetname" "t276" "spawnflags" "2" "target" "t283" "classname" "func_train" } { "origin" "-464 568 544" "target" "t271" "classname" "trigger_always" } { "target" "t271" "targetname" "tpsp" "origin" "-96 880 672" "classname" "trigger_relay" } { "targetname" "t272" "team" "smartass" "origin" "-40 968 360" "spawnflags" "2" "noise" "world/lift1.wav" "classname" "target_speaker" } { "classname" "light" "light" "125" "origin" "296 1208 328" } { "classname" "light" "light" "75" "origin" "104 912 248" } { "classname" "light" "light" "80" "origin" "416 960 408" } { "classname" "point_combat" "targetname" "t241" "origin" "992 424 280" } { "model" "*49" "wait" "-1" "targetname" "t307" "classname" "func_door" "angle" "-1" } { "model" "*50" "wait" "-1" "targetname" "t307" "classname" "func_door" "angle" "-1" } { "model" "*51" "wait" "-1" "targetname" "t307" "classname" "func_door" "angle" "-1" } { "style" "1" "targetname" "t81" "classname" "func_areaportal" } { "model" "*52" "wait" "-1" "targetname" "t302" "angle" "-1" "classname" "func_door" "sounds" "1" } { "model" "*53" "wait" "-1" "targetname" "t302" "angle" "-1" "classname" "func_door" "sounds" "1" } { "model" "*54" "wait" "-1" "targetname" "t302" "angle" "-1" "classname" "func_door" "sounds" "1" } { "targetname" "t302" "angle" "90" "spawnflags" "416" "origin" "984 -448 360" "classname" "monster_turret" } { "classname" "light" "light" "110" "origin" "896 712 416" } { "model" "*55" "wait" "-1" "spawnflags" "2048" "angle" "180" "classname" "func_button" "target" "t265" "message" "Security and Access Doors Unlocked!" } { "origin" "608 744 396" "targetname" "t260" "classname" "info_null" } { "target" "t260" "origin" "608 796 506" "light" "240" "classname" "light" "_cone" "15" } { "origin" "608 744 480" "light" "80" "classname" "light" } { "origin" "632 768 416" "wait" ".5" "target" "t259" "spawnflags" "1" "classname" "func_timer" } { "style" "34" "light" "60" "targetname" "t259" "_color" "1.000000 0.435294 0.435294" "origin" "592 712 416" "classname" "light" } { "origin" "992 1504 496" "light" "110" "classname" "light" } { "origin" "832 1088 184" "light" "110" "classname" "light" } { "model" "*56" "targetname" "t385" "lip" "16" "spawnflags" "1" "classname" "func_plat2" } { "origin" "1344 708 376" "light" "75" "classname" "light" } { "origin" "824 560 344" "_color" "1.000000 1.000000 0.000000" "light" "150" "classname" "light" } { "origin" "1024 672 320" "light" "120" "classname" "light" } { "origin" "1056 312 352" "light" "110" "classname" "light" } { "light" "100" "classname" "light" "_color" "1.000000 0.913725 0.615686" "origin" "-848 -160 48" } { "origin" "-480 -232 -272" "classname" "misc_explobox" "spawnflags" "2048" } { "model" "*57" "team" "nuk" "targetname" "t11" "target" "t10" "spawnflags" "2048" "classname" "func_train" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "448 320 280" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "-800 -552 -232" } { "origin" "-128 1080 288" "targetname" "t257" "spawnflags" "2049" "classname" "point_combat" } { "model" "*58" "targetname" "t202" "spawnflags" "2050" "classname" "trigger_hurt" } { "classname" "trigger_relay" "target" "jimm" "spawnflags" "2048" "killtarget" "jimm" "targetname" "t240" "origin" "480 728 288" } { "classname" "info_notnull" "targetname" "jimm" "spawnflags" "2048" "killtarget" "jimm" "origin" "436 788 268" } { "item" "ammo_grenades" "spawnflags" "773" "origin" "-1448 1568 816" "angle" "270" "classname" "monster_gunner" } { "origin" "-1320 1768 904" "target" "t235" "targetname" "t237" "classname" "trigger_relay" } { "target" "t398" "deathtarget" "t294" "spawnflags" "5" "origin" "-1280 1728 920" "angle" "270" "classname" "monster_medic_commander" } { "origin" "-1280 1880 920" "targetname" "t237" "spawnflags" "1026" "angle" "270" "classname" "monster_medic" "deathtarget" "porkin" } { "style" "2" "targetname" "t236" "classname" "func_areaportal" } { "model" "*59" "targetname" "t237" "spawnflags" "9" "target" "t235" "classname" "trigger_multiple" } { "model" "*60" "target" "t236" "targetname" "t235" "angle" "-1" "classname" "func_door" } { "item" "ammo_bullets" "targetname" "t89" "spawnflags" "4" "angle" "180" "origin" "-672 824 864" "classname" "monster_infantry" } { "origin" "-640 704 552" "targetname" "t114" "spawnflags" "2" "angle" "180" "classname" "monster_gladiator" } { "spawnflags" "13" "angle" "180" "origin" "112 960 800" "classname" "monster_stalker" } { "model" "*61" "target" "t234" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "488 840 280" "targetname" "arm" "classname" "item_armor_combat" } { "model" "*62" "killtarget" "arm" "spawnflags" "2048" "mass" "1" "classname" "func_explosive" "target" "t240" } { "origin" "432 976 264" "classname" "misc_explobox" } { "target" "t257" "origin" "-144 1152 304" "angle" "270" "targetname" "t233" "classname" "monster_gladiator" "item" "ammo_slugs" } { "targetname" "t234" "killtarget" "jimm" "origin" "-40 1168 288" "target" "t233" "classname" "target_anger" } { "model" "*63" "target" "t231" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*64" "target" "t229" "spawnflags" "2048" "classname" "trigger_once" } { "targetname" "t228" "origin" "192 -8 304" "classname" "point_combat" "spawnflags" "1" } { "angle" "270" "targetname" "t229" "target" "t228" "spawnflags" "1" "origin" "224 232 296" "classname" "monster_gladiator" "item" "ammo_slugs" } { "targetname" "t224" "origin" "-248 -528 -216" "angle" "180" "spawnflags" "269" "classname" "monster_stalker" } { "origin" "-800 -552 -216" "target" "t224" "spawnflags" "1" "angle" "180" "classname" "monster_gunner" } { "origin" "-200 2600 -144" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "origin" "184 1312 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-296 1832 -112" "targetname" "t202" "spawnflags" "2" "noise" "world/amb6.wav" "classname" "target_speaker" } { "delay" ".4" "targetname" "watergo" "origin" "0 2104 -32" "target" "t222" "classname" "trigger_relay" } { "targetname" "t222" "origin" "288 1888 -16" "spawnflags" "2054" "noise" "world/curnt1.wav" "classname" "target_speaker" } { "targetname" "t164" "spawnflags" "2048" "target" "t221" "origin" "104 2064 -32" "classname" "trigger_relay" } { "targetname" "t221" "origin" "160 2136 -32" "noise" "world/mach2.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "arc" "spawnflags" "2050" "origin" "424 1904 -32" "noise" "world/l_hum1.wav" "classname" "target_speaker" } { "origin" "-32 2368 216" "angle" "270" "spawnflags" "257" "classname" "monster_stalker" } { "item" "ammo_grenades" "origin" "-128 1840 104" "angle" "45" "classname" "monster_gunner" "spawnflags" "1" "target" "t345" } { "item" "ammo_slugs" "targetname" "t218" "origin" "584 2256 -104" "spawnflags" "1" "angle" "90" "classname" "monster_gladiator" } { "model" "*65" "spawnflags" "2048" "target" "t218" "classname" "trigger_once" } { "origin" "520 2232 40" "angle" "315" "spawnflags" "9" "classname" "monster_stalker" } { "origin" "-808 1816 152" "spawnflags" "1" "angle" "180" "classname" "monster_gunner" } { "model" "*66" "spawnflags" "2048" "target" "t213" "wait" "6" "angle" "0" "classname" "func_button" } { "model" "*67" "targetname" "t213" "lip" "128" "angle" "-2" "classname" "func_door" } { "model" "*68" "target" "t210" "wait" "-1" "classname" "func_button" "angle" "90" } { "model" "*69" "lip" "16" "targetname" "t210" "spawnflags" "1" "classname" "func_plat2" } { "target" "t209" "targetname" "cup" "origin" "-408 2112 -24" "classname" "trigger_relay" } { "model" "*70" "_minlight" ".2" "target" "t208" "wait" "-1" "health" "1" "angle" "90" "spawnflags" "2048" "classname" "func_button" } { "targetname" "t208" "origin" "-328 2152 -8" "classname" "target_secret" "message" "Something just fell in a container." // b#3: moved here } { "model" "*71" "origin" "-428 2140 -28" "targetname" "t209" "sounds" "1" "distance" "90" "spawnflags" "2209" "classname" "func_door_rotating" } { "targetname" "t208" "origin" "-328 2136 -8" "spawnflags" "2048" "target" "item_invulnerability" "classname" "target_spawner" } { "pathtarget" "t219" "wait" "1" "speed" "300" "targetname" "t205" "target" "t204" "origin" "560 1688 0" "classname" "path_corner" } { "classname" "trigger_relay" "targetname" "t160" "target" "t165" "origin" "256 1688 -16" } { "classname" "trigger_relay" "targetname" "topgo" "target" "t165" "origin" "240 1688 -16" } { "model" "*72" "classname" "trigger_hurt" "spawnflags" "2059" "dmg" "50" "targetname" "t165" } { "classname" "trigger_relay" "target" "t164" "delay" "6" "targetname" "watergo" "origin" "80 1760 -128" } { "model" "*73" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "t164" "target" "t163" } { "classname" "path_corner" "origin" "216 2088 -16" "target" "t161" "targetname" "t163" "wait" "-1" } { "classname" "trigger_relay" "targetname" "t160" "origin" "400 1704 0" "target" "arc" } { "classname" "trigger_relay" "origin" "336 1944 8" "targetname" "t149" "target" "t150" "delay" ".5" } { "classname" "path_corner" "origin" "204 1672 0" "targetname" "t147" "target" "t148" "pathtarget" "zoiks" "wait" "-1" } { "classname" "trigger_relay" "origin" "32 1760 -128" "targetname" "watergo" "target" "fillw" "delay" ".4" } { "classname" "trigger_relay" "targetname" "sparky" "origin" "408 1952 8" "target" "t149" } { "classname" "path_corner" "origin" "224 1728 -16" "targetname" "t143" "wait" "-1" "pathtarget" "topgo" "target" "t183" } { "classname" "path_corner" "origin" "-96 1728 -128" "target" "t141" "wait" "-1" "targetname" "t174" } { "model" "*74" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "cup" "target" "t174" "team" "argh5" } { "model" "*75" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "target" "t146" "targetname" "lid" } { "origin" "-960 448 660" "light" "85" "classname" "light" } { "model" "*76" "targetname" "t127" "accel" "20" "lip" "24" "spawnflags" "1" "classname" "func_plat2" "_minlight" ".1" } { "model" "*77" "targetname" "jam" "spawnflags" "2054" "classname" "func_wall" } { "classname" "light" "light" "100" "origin" "-384 704 800" } { "model" "*78" "team" "nascar" "angle" "-1" "target" "t137" "wait" "1" "classname" "func_door" } { "model" "*79" "target" "t127" "wait" "-1" "angle" "90" "classname" "func_button" } { "item" "ammo_cells" "targetname" "t126" "origin" "-896 946 576" "spawnflags" "136" "angle" "270" "classname" "monster_turret" } { "model" "*80" "target" "t125" "classname" "trigger_once" } { "model" "*81" "targetname" "t125" "spawnflags" "2048" "wait" "-1" "lip" "-118" "angle" "-2" "classname" "func_door" "delay" "1" } { "classname" "trigger_relay" "delay" "4" "origin" "-800 632 712" "target" "t89" "spawnflags" "2048" "targetname" "t119" } { "model" "*82" "dmg" "20" "mass" "800" "classname" "func_explosive" "targetname" "t114" "spawnflags" "2048" "target" "t369" } { "classname" "target_speaker" "spawnflags" "2049" "noise" "world/force1.wav" "targetname" "jam" "origin" "-448 536 320" } { "classname" "target_lightramp" "speed" ".5" "message" "za" "spawnflags" "2049" "target" "t85" "origin" "-448 568 288" "targetname" "jam" } { "style" "35" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "-448 544 272" "targetname" "t85" } { "model" "*83" "target" "t84" "classname" "func_door" "angle" "-1" "wait" "1" } { "style" "3" "targetname" "t84" "classname" "func_areaportal" } { "targetname" "t275" "team" "wiseass" "origin" "-104 832 672" "attenuation" "1" "noise" "switches/butn2.wav" "classname" "target_speaker" } { "model" "*84" "target" "tpgo" "targetname" "t271" "wait" "1" "spawnflags" "12" "classname" "trigger_multiple" } { "model" "*85" "target" "t277" "targetname" "t276" "team" "wiseass" "spawnflags" "2" "classname" "func_train" } { "model" "*86" "target" "iliketrafficlights" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*87" "target" "iliketrafficlights" "wait" "10" "angle" "270" "classname" "func_button" } { "classname" "item_health_small" "origin" "1184 864 60" } { "speed" "50" "wait" "-1" "targetname" "t42" "target" "t39" "origin" "640 800 32" "classname" "path_corner" } { "model" "*88" "targetname" "t43" "spawnflags" "2" "target" "t42" "classname" "func_train" "_minlight" ".2" } { "targetname" "t38" "noise" "world/brkglas.wav" "attenuation" "1" "origin" "1280 976 336" "classname" "target_speaker" } { "model" "*89" "target" "t31" "mass" "150" "health" "5" "classname" "func_explosive" } { "model" "*90" "origin" "992 408 565" "_minlight" ".1" "speed" "40" "team" "tarok" "distance" "16" "spawnflags" "130" "classname" "func_door_rotating" "target" "t81" } { "model" "*91" "targetname" "hobbit" "team" "smartass" "target" "t269" "spawnflags" "2" "speed" "50" "classname" "func_train" } { "model" "*92" "wait" "1" "angle" "-1" "target" "t17" "classname" "func_door" } { "style" "4" "targetname" "t17" "classname" "func_areaportal" } { "spawnflags" "6144" "speed" "300" "angle" "270" "origin" "-8 -136 320" "targetname" "t11" "target" "t10" "classname" "misc_strogg_ship" } { "spawnflags" "2048" "target" "t12" "targetname" "t9" "origin" "-32 -304 400" "classname" "path_corner" "speed" "350" } { "model" "*93" "targetname" "t8" "spawnflags" "2048" "target" "t7" "classname" "trigger_multiple" } { "model" "*94" "message" "Level 1 defences deactivated." "targetname" "t7" "lip" "16" "spawnflags" "2048" "angle" "180" "classname" "func_button" } { "origin" "-856 -600 -216" "targetname" "t5" "noise" "world/fuseout.wav" "attenuation" "1" "spawnflags" "2048" "classname" "target_speaker" } { "model" "*95" "killtarget" "t8" "target" "t5" "spawnflags" "2048" "mass" "50" "dmg" "10" "classname" "func_explosive" } { "origin" "-872 -616 -256" "spawnflags" "2048" "classname" "misc_explobox" } { "classname" "func_timer" "target" "t6" "random" ".5" "spawnflags" "2048" "targetname" "t5" "origin" "-840 -632 -248" } { "classname" "target_splash" "origin" "-884 -638 -248" "sounds" "1" "targetname" "t6" "spawnflags" "2048" "angle" "-2" } { "model" "*96" "targetname" "t5" "spawnflags" "6" "classname" "func_wall" } { "angle" "0" "classname" "misc_teleporter_dest" "spawnflags" "5888" "targetname" "t4" "origin" "-224 2528 -168" } { "classname" "misc_teleporter" "spawnflags" "5888" "target" "t4" "origin" "-352 -608 -360" } { "classname" "func_timer" "target" "t2" "spawnflags" "1" "origin" "-328 -296 -224" } { "model" "*97" "classname" "trigger_push" "angle" "-1" "speed" "60" } { "classname" "target_steam" "origin" "-352 -224 -40" "targetname" "t2" "angle" "-1" "speed" "150" "count" "128" "sounds" "208" } { "model" "*98" "classname" "trigger_multiple" "target" "t1" } { "model" "*99" "origin" "-432 -248 -24" "_minlight" ".1" "classname" "func_door_rotating" "spawnflags" "130" "distance" "100" "speed" "300" "targetname" "t1" "wait" ".5" } { "classname" "target_steam" "origin" "-352 -224 -200" "targetname" "t2" "angle" "-1" "speed" "150" "count" "128" "sounds" "208" } { "sounds" "208" "count" "128" "speed" "150" "angle" "-1" "targetname" "t3" "origin" "-352 -224 -136" "classname" "target_steam" } { "classname" "target_steam" "origin" "-352 -224 -368" "targetname" "t2" "angle" "-1" "speed" "150" "count" "128" "sounds" "208" } { "model" "*100" "classname" "func_wall" } { "model" "*101" "origin" "-790 -639 -178" "sounds" "0" "classname" "func_door_rotating" "wait" "8" "distance" "45" "targetname" "t5" "spawnflags" "97" "speed" "55" "team" "tt1" } { "model" "*102" "origin" "-790 -638 -183" "sounds" "0" "classname" "func_door_rotating" "wait" "8" "distance" "60" "targetname" "t5" "spawnflags" "97" "speed" "65" "team" "tt1" } { "model" "*103" "origin" "-790 -627 -203" "sounds" "0" "classname" "func_door_rotating" "wait" "8" "distance" "120" "targetname" "t5" "spawnflags" "97" "speed" "100" "team" "tt1" } { "model" "*104" "origin" "-790 -640 -166" "sounds" "0" "classname" "func_door_rotating" "wait" "8" "distance" "10" "targetname" "t5" "spawnflags" "97" "team" "tt1" "speed" "50" } { "model" "*105" "origin" "-790 -633 -194" "sounds" "0" "classname" "func_door_rotating" "wait" "8" "distance" "90" "targetname" "t5" "spawnflags" "97" "speed" "80" "team" "tt1" } { "spawnflags" "2048" "targetname" "t10" "target" "t9" "classname" "path_corner" "origin" "-32 -128 376" "speed" "350" } { "spawnflags" "2048" "target" "t13" "classname" "path_corner" "origin" "-32 -448 488" "targetname" "t12" "speed" "350" } { "spawnflags" "2048" "target" "t14" "targetname" "t13" "origin" "-32 -656 576" "classname" "path_corner" "speed" "350" } { "spawnflags" "2048" "target" "t15" "classname" "path_corner" "origin" "-32 -960 680" "targetname" "t14" "speed" "500" } { "spawnflags" "2048" "target" "t16" "targetname" "t15" "origin" "-32 -1288 704" "classname" "path_corner" "speed" "500" } { "spawnflags" "2048" "speed" "500" "target" "t10" "classname" "path_corner" "origin" "-32 -2128 704" "targetname" "t16" "wait" "-1" } { "model" "*106" "origin" "992 408 565" "_minlight" ".1" "speed" "40" "team" "tarok" "classname" "func_door_rotating" "spawnflags" "128" "distance" "16" } { "model" "*107" "origin" "192 1256 573" "classname" "func_door_rotating" "spawnflags" "130" "distance" "16" "team" "mono" "target" "t82" "speed" "40" "_minlight" ".1" } { "model" "*108" "origin" "192 1256 573" "distance" "16" "spawnflags" "128" "classname" "func_door_rotating" "team" "mono" "speed" "40" "_minlight" ".1" } { "model" "*109" "target" "t30" "classname" "func_explosive" "mass" "150" "health" "5" } { "model" "*110" "target" "t33" "health" "5" "mass" "150" "classname" "func_explosive" } { "model" "*111" "target" "t37" "classname" "func_explosive" "mass" "150" "health" "5" } { "model" "*112" "target" "t32" "classname" "func_explosive" "health" "5" "mass" "150" } { "model" "*113" "target" "t38" "mass" "150" "health" "5" "classname" "func_explosive" } { "targetname" "t37" "noise" "world/brkglas.wav" "attenuation" "1" "classname" "target_speaker" "origin" "1280 968 320" } { "targetname" "t32" "noise" "world/brkglas.wav" "attenuation" "1" "classname" "target_speaker" "origin" "1280 864 336" } { "targetname" "t33" "noise" "world/brkglas.wav" "attenuation" "1" "origin" "1280 856 320" "classname" "target_speaker" } { "targetname" "t31" "noise" "world/brkglas.wav" "attenuation" "1" "origin" "1280 768 336" "classname" "target_speaker" } { "targetname" "t30" "noise" "world/brkglas.wav" "attenuation" "1" "classname" "target_speaker" "origin" "1280 760 320" } { "speed" "600" "wait" "1" "targetname" "t41" "target" "t40" "classname" "path_corner" "origin" "640 800 32" } { "pathtarget" "heybuddy" "speed" "50" "wait" "-1" "target" "t41" "targetname" "t40" "classname" "path_corner" "origin" "-168 800 32" } { "pathtarget" "heybuddy" "speed" "600" "wait" "1" "target" "t42" "targetname" "t39" "origin" "-168 800 32" "classname" "path_corner" } { "origin" "1312 864 60" "classname" "item_health_small" } { "classname" "item_health_small" "origin" "1440 864 60" } { "origin" "1056 864 60" "classname" "item_health_small" } { "model" "*114" "target" "btgo" "targetname" "t274" "classname" "trigger_multiple" "spawnflags" "12" "wait" "1" } { "style" "5" "targetname" "t82" "classname" "func_areaportal" } { "style" "6" "classname" "func_areaportal" "targetname" "t83" } { "style" "35" "origin" "-448 544 376" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" "targetname" "t85" } { "style" "35" "origin" "-504 544 320" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" "targetname" "t85" } { "style" "35" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "-392 544 320" "targetname" "t85" } { "style" "35" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "-504 544 376" "targetname" "t85" } { "style" "35" "origin" "-392 544 376" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" "targetname" "t85" } { "style" "35" "origin" "-504 544 272" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" "targetname" "t85" } { "style" "35" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "-392 544 272" "targetname" "t85" } { "killtarget" "t290" "classname" "trigger_relay" "origin" "-776 832 616" "targetname" "t113" "target" "t114" "spawnflags" "2048" } { "origin" "-960 464 568" "targetname" "t120" "noise" "world/force1.wav" "spawnflags" "2049" "classname" "target_speaker" } { "targetname" "t120" "origin" "-968 504 536" "target" "t121" "spawnflags" "2049" "message" "za" "speed" ".5" "classname" "target_lightramp" } { "style" "36" "targetname" "t121" "origin" "-960 480 520" "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "style" "36" "targetname" "t121" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" "origin" "-960 480 624" } { "style" "36" "targetname" "t121" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" "origin" "-1008 480 568" } { "style" "36" "targetname" "t121" "origin" "-912 480 568" "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "style" "36" "targetname" "t121" "origin" "-1008 480 624" "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "style" "36" "targetname" "t121" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" "origin" "-912 480 624" } { "style" "36" "targetname" "t121" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" "origin" "-1008 480 520" } { "style" "36" "targetname" "t121" "origin" "-912 480 520" "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "model" "*115" "target" "t126" "spawnflags" "2048" "classname" "trigger_once" } { "item" "ammo_cells" "classname" "monster_turret" "angle" "90" "spawnflags" "136" "origin" "-800 462 576" "targetname" "t126" } { "style" "7" "targetname" "t128" "classname" "func_areaportal" } { "model" "*116" "origin" "-576 1152 565" "speed" "40" "target" "t128" "classname" "func_door_rotating" "spawnflags" "130" "distance" "16" "team" "humus" } { "model" "*117" "origin" "-576 1152 565" "speed" "40" "distance" "16" "spawnflags" "128" "classname" "func_door_rotating" "team" "humus" } { "origin" "-384 832 800" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-384 960 800" } { "origin" "-320 1056 800" "light" "100" "classname" "light" } { "classname" "light" "light" "110" "origin" "-128 1032 736" } { "style" "8" "classname" "func_areaportal" "targetname" "t137" } { "model" "*118" "classname" "func_wall" "spawnflags" "2054" "targetname" "t120" } { "classname" "light" "light" "85" "origin" "-960 320 660" } { "origin" "-832 320 660" "light" "85" "classname" "light" } { "classname" "target_speaker" "origin" "-720 832 864" "attenuation" "1" "noise" "world/brkglas.wav" "targetname" "t139" } { "targetname" "t140" "noise" "world/brkglas.wav" "attenuation" "1" "origin" "-728 576 864" "classname" "target_speaker" } { "origin" "224 1728 -128" "classname" "path_corner" "targetname" "t141" "wait" "-1" "pathtarget" "watergo" "target" "t142" } { "targetname" "t142" "classname" "path_corner" "origin" "544 1728 -128" "target" "t166" "wait" "-1" "spawnflags" "2050" } { "origin" "544 1728 -16" "classname" "path_corner" "targetname" "t183" "wait" "-1" "target" "t194" } { "classname" "path_corner" "origin" "224 1976 -16" "target" "t143" "targetname" "t146" "wait" "-1" "spawnflags" "0" } { "origin" "48 1760 -128" "classname" "trigger_relay" "targetname" "watergo" "target" "fullw" "wait" ".5" } { "classname" "trigger_relay" "origin" "64 1760 -128" "targetname" "watergo" "target" "lid" "delay" "6" } { "origin" "120 1672 -128" "classname" "trigger_relay" "target" "arc" "targetname" "topgo" } { "classname" "trigger_relay" "origin" "80 1704 -128" "targetname" "zoiks" "target" "sparky" } { "origin" "204 1672 64" "classname" "path_corner" "target" "t147" "targetname" "t148" "pathtarget" "wellduh" "wait" "-1" } { "origin" "64 1704 -128" "classname" "trigger_relay" "targetname" "zoiks" "target" "fullw" } { "classname" "trigger_relay" "origin" "48 1704 -128" "targetname" "zoiks" "target" "fillw" } { "origin" "320 1944 8" "classname" "trigger_relay" "targetname" "t153" "target" "t154" "delay" ".5" } { "classname" "trigger_relay" "origin" "304 1944 8" "targetname" "t157" "target" "t158" "delay" ".5" } { "origin" "440 1808 8" "classname" "trigger_relay" "targetname" "t152" "target" "t153" "delay" ".5" } { "classname" "trigger_relay" "origin" "440 1824 8" "targetname" "t156" "delay" ".5" "target" "t157" } { "classname" "trigger_relay" "origin" "304 1704 8" "targetname" "t151" "target" "t152" "delay" ".5" } { "origin" "320 1704 8" "classname" "trigger_relay" "targetname" "t155" "target" "t156" "delay" ".5" } { "classname" "trigger_relay" "origin" "336 1704 8" "targetname" "t159" "target" "t160" "delay" ".5" } { "origin" "200 1840 8" "classname" "trigger_relay" "targetname" "t150" "target" "t151" "delay" ".5" } { "classname" "trigger_relay" "origin" "200 1824 8" "targetname" "t154" "target" "t155" "delay" ".5" } { "origin" "200 1808 8" "classname" "trigger_relay" "targetname" "t158" "target" "t159" "delay" ".5" } { "origin" "304 1672 0" "targetname" "wellduh" "classname" "trigger_relay" "target" "lid" } { "classname" "trigger_relay" "targetname" "wellduh" "origin" "320 1672 0" "target" "cup" } { "pathtarget" "howe" "wait" ".2" "targetname" "t161" "target" "t163" "origin" "216 1840 -16" "classname" "path_corner" } { "origin" "800 1728 -128" "classname" "path_corner" "targetname" "t166" "target" "t172" } { "classname" "path_corner" "origin" "800 1728 -16" "targetname" "t191" "target" "t192" "pathtarget" "joke" } { "classname" "path_corner" "origin" "800 1728 -376" "targetname" "t172" "target" "t170" "speed" "300" } { "origin" "800 1728 -264" "classname" "path_corner" "speed" "300" "targetname" "t192" "target" "t193" } { "origin" "-416 2048 -376" "classname" "path_corner" "targetname" "t170" "spawnflags" "2048" "target" "t176" "speed" "1000" } { "wait" "-1" "targetname" "t175" "origin" "-416 1728 -128" "classname" "path_corner" "target" "t174" } { "pathtarget" "t209" "classname" "path_corner" "origin" "-416 2048 -128" "targetname" "t176" "spawnflags" "0" "wait" "-1" "target" "t175" "speed" "100" } { "model" "*119" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "cup" "target" "t176" "team" "argh4" } { "model" "*120" "_minlight" ".1" "target" "t177" "targetname" "cup" "spawnflags" "2051" "classname" "func_train" "team" "argh3" } { "origin" "-32 1792 -128" "classname" "path_corner" "target" "t141" "targetname" "t177" } { "model" "*121" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "cup" "target" "t175" "team" "argh2" } { "model" "*122" "_minlight" ".1" "spawnflags" "2050" "classname" "func_train" "target" "t184" "targetname" "lid" } { "model" "*123" "targetname" "t179" "dmg" "50" "spawnflags" "2059" "classname" "trigger_hurt" } { "model" "*124" "_minlight" ".1" "target" "t183" "classname" "func_train" "spawnflags" "2050" "targetname" "lid" } { "model" "*125" "_minlight" ".1" "targetname" "lid" "spawnflags" "2050" "classname" "func_train" "target" "t178" } { "wait" "-1" "origin" "224 1976 -32" "classname" "path_corner" "spawnflags" "2048" "targetname" "t190" "target" "t146" } { "spawnflags" "2048" "classname" "path_corner" "origin" "224 1976 -33" "wait" "-1" "targetname" "t178" "target" "t190" } { "spawnflags" "2048" "classname" "path_corner" "origin" "224 1976 -48" "wait" "-1" "targetname" "t188" "target" "t178" } { "wait" "-1" "origin" "224 1976 -49" "classname" "path_corner" "spawnflags" "2048" "targetname" "t187" "target" "t188" } { "wait" "-1" "origin" "224 1976 -64" "classname" "path_corner" "spawnflags" "2048" "targetname" "t186" "target" "t187" } { "spawnflags" "2048" "classname" "path_corner" "origin" "224 1976 -65" "wait" "-1" "targetname" "t185" "target" "t186" } { "speed" "100" "spawnflags" "2048" "classname" "path_corner" "origin" "224 1976 -80" "wait" "-1" "target" "t185" "targetname" "t195" } { "model" "*126" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "lid" "target" "t187" } { "model" "*127" "_minlight" ".1" "spawnflags" "2050" "classname" "func_train" "targetname" "lid" "target" "t185" } { "speed" "1000" "classname" "path_corner" "origin" "224 1976 -264" "targetname" "t193" "target" "t184" } { "model" "*128" "_minlight" ".1" "classname" "func_train" "spawnflags" "2050" "targetname" "cup" "target" "t142" "team" "argh1" } { "wait" "-1" "classname" "path_corner" "origin" "544 1728 -17" "target" "t191" "targetname" "t194" } { "target" "t195" "targetname" "t184" "wait" "-1" "origin" "224 1976 -81" "classname" "path_corner" "spawnflags" "2048" } { "style" "37" "origin" "768 1760 -104" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "spawnflags" "1" } { "style" "37" "origin" "768 1888 -104" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "spawnflags" "1" } { "targetname" "t202" "target" "xan" "classname" "target_lightramp" "speed" "1.5" "spawnflags" "2049" "message" "za" "origin" "-328 1832 -128" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "128 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "128 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "192 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "192 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "256 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "256 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "320 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "320 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "384 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "384 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "448 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "448 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "512 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "512 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "576 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "576 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "640 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "640 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "704 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "704 1760 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "832 1888 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "832 1760 -104" "spawnflags" "1" } { "target" "t202" "targetname" "watergo" "origin" "16 1760 -128" "classname" "trigger_relay" } { "target" "t202" "origin" "336 1672 0" "targetname" "wellduh" "classname" "trigger_relay" } { "style" "37" "spawnflags" "1" "targetname" "xan" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "0 1760 -104" } { "style" "37" "spawnflags" "1" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "0 1888 -104" } { "style" "37" "spawnflags" "1" "origin" "-320 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "spawnflags" "1" "origin" "-256 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "spawnflags" "1" "origin" "-192 1888 -104" "targetname" "xan" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "style" "37" "spawnflags" "1" "origin" "-192 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "spawnflags" "1" "origin" "-128 1888 -104" "targetname" "xan" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "style" "37" "spawnflags" "1" "origin" "-128 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "spawnflags" "1" "origin" "-64 1888 -104" "targetname" "xan" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "style" "37" "spawnflags" "1" "origin" "-64 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "spawnflags" "1" "origin" "64 1888 -104" "targetname" "xan" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "style" "37" "spawnflags" "1" "origin" "64 1760 -104" "targetname" "xan" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "37" "origin" "-392 1888 -104" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "spawnflags" "1" } { "style" "37" "origin" "-264 1888 -104" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-264 2208 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 2208 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-264 2144 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 2144 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-264 2080 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 2080 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-264 2016 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 2016 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-264 1952 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 1952 -104" "spawnflags" "1" } { "style" "37" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "xan" "origin" "-392 1760 -104" "spawnflags" "1" } { "style" "37" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "xan" "origin" "-392 1824 -104" "spawnflags" "1" } { "pathtarget" "t220" "speed" "30" "wait" "-1" "target" "t205" "targetname" "t204" "classname" "path_corner" "origin" "560 1696 104" } { "target" "t206" "delay" "5.7" "targetname" "watergo" "origin" "96 1760 -128" "classname" "trigger_relay" } { "style" "9" "classname" "func_areaportal" "targetname" "t212" } { "model" "*129" "spawnflags" "5888" "classname" "func_door" "angle" "-1" "speed" "300" "wait" "1" "target" "t212" } { "model" "*130" "target" "t311" "classname" "func_button" "angle" "180" "spawnflags" "2048" "lip" "16" "wait" "-1" } { "model" "*131" "classname" "func_wall" } { "targetname" "t218" "classname" "monster_gladiator" "angle" "90" "spawnflags" "769" "origin" "552 2144 -104" } { "classname" "monster_gunner" "angle" "270" "origin" "80 2200 120" "spawnflags" "257" "target" "t346" } { "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "416 1744 -32" "spawnflags" "2050" "targetname" "arc" } { "targetname" "arc" "spawnflags" "2050" "origin" "216 1736 -32" "noise" "world/l_hum1.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/l_hum1.wav" "origin" "216 1904 -32" "spawnflags" "2050" "targetname" "arc" } { "targetname" "t221" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/mach2.wav" "origin" "160 2072 -32" } { "targetname" "t221" "origin" "160 2008 -32" "noise" "world/mach2.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t221" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/mach2.wav" "origin" "488 2120 -32" } { "targetname" "t221" "origin" "488 2056 -32" "noise" "world/mach2.wav" "spawnflags" "2050" "classname" "target_speaker" } { "targetname" "t221" "classname" "target_speaker" "spawnflags" "2050" "noise" "world/mach2.wav" "origin" "488 1992 -32" } { "targetname" "howe" "spawnflags" "2048" "target" "t221" "classname" "trigger_relay" "origin" "112 2024 -32" } { "targetname" "t222" "classname" "target_speaker" "noise" "world/curnt1.wav" "spawnflags" "2054" "origin" "376 1832 -32" } { "targetname" "t222" "origin" "328 1776 -32" "spawnflags" "2054" "noise" "world/curnt1.wav" "classname" "target_speaker" } { "targetname" "t164" "target" "t222" "classname" "trigger_relay" "origin" "-40 2080 -32" } { "classname" "target_speaker" "noise" "world/amb6.wav" "spawnflags" "2" "targetname" "t202" "origin" "-192 1832 -112" } { "origin" "-32 1832 -112" "targetname" "t202" "spawnflags" "2" "noise" "world/amb6.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb6.wav" "spawnflags" "2" "targetname" "t202" "origin" "128 1832 -112" } { "origin" "312 1832 -112" "targetname" "t202" "spawnflags" "2" "noise" "world/amb6.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb6.wav" "spawnflags" "2" "targetname" "t202" "origin" "512 1832 -112" } { "origin" "704 1832 -112" "targetname" "t202" "spawnflags" "2" "noise" "world/amb6.wav" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "192 1432 312" } { "origin" "328 1440 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "512 1440 312" } { "origin" "672 1440 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "792 1440 312" } { "origin" "976 368 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "984 232 312" } { "origin" "984 48 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "984 -112 312" } { "origin" "984 -232 312" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "824 -256 312" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-56 2656 -144" } { "origin" "64 2560 -144" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "512 2576 -144" } { "origin" "320 2568 -144" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "origin" "648 2552 -144" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "512 2400 -72" } { "origin" "664 2336 -72" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "origin" "-560 2168 136" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-584 1456 296" } { "origin" "-696 1288 296" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-448 1280 296" } { "origin" "-576 1072 296" "spawnflags" "1" "noise" "world/amb22.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb22.wav" "spawnflags" "1" "origin" "-704 1008 296" } { "origin" "-448 1008 296" "spawnflags" "1" "noise" "world/amb22.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb22.wav" "spawnflags" "1" "origin" "-448 856 296" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "-88 1112 296" } { "origin" "192 1112 296" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "264 864 296" } { "origin" "-32 840 296" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "264 672 296" } { "origin" "256 504 296" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "-64 504 296" } { "origin" "448 368 296" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "232 272 296" } { "origin" "-1280 1408 808" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1480 1472 808" } { "origin" "-1480 1320 808" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1096 1480 808" } { "origin" "-1104 1320 808" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1296 1104 888" } { "origin" "-1536 1152 888" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1616 1384 888" } { "origin" "-1600 1600 888" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1312 1600 928" } { "origin" "-1360 1720 928" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-1160 1728 928" } { "origin" "-1016 1656 928" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb23.wav" "spawnflags" "1" "origin" "-960 1496 928" } { "origin" "-960 1280 928" "spawnflags" "1" "noise" "world/amb23.wav" "classname" "target_speaker" } { "origin" "752 944 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "744 776 96" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "912 944 96" } { "origin" "904 776 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "1040 944 96" } { "origin" "1032 776 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "origin" "1200 944 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "1192 776 96" } { "origin" "1328 944 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "1320 776 96" } { "classname" "target_speaker" "noise" "world/amb24.wav" "spawnflags" "1" "origin" "1488 944 96" } { "origin" "1480 776 96" "spawnflags" "1" "noise" "world/amb24.wav" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "targetname" "t223" "origin" "-768 -424 -208" } { "origin" "-656 -424 -208" "targetname" "t223" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "targetname" "t223" "origin" "-664 -688 -208" } { "origin" "-776 -688 -208" "targetname" "t223" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "targetname" "t224" "classname" "monster_stalker" "spawnflags" "781" "angle" "180" "origin" "-248 -336 -216" } { "angle" "180" "classname" "monster_gladiator" "origin" "856 -272 280" "spawnflags" "1" "targetname" "t229" "item" "ammo_slugs" } { "team" "nuk" "classname" "target_speaker" "origin" "-88 -280 128" "noise" "world/flyby3.wav" "targetname" "t11" } { "team" "nuk" "noise" "world/flyby3.wav" "origin" "-128 -120 128" "classname" "target_speaker" "targetname" "t11" } { "team" "nuk" "classname" "target_speaker" "origin" "-32 -208 128" "noise" "world/flyby3.wav" "targetname" "t11" } { "team" "nuk" "classname" "target_speaker" "origin" "-56 -408 128" "noise" "world/flyby3.wav" "targetname" "t11" } { "angle" "270" "targetname" "t231" "spawnflags" "1" "origin" "992 592 296" "classname" "monster_gladiator" "target" "t241" } { "classname" "misc_explobox" "origin" "432 896 264" } { "origin" "472 776 264" "classname" "misc_explobox" } { "classname" "misc_explobox" "origin" "432 728 264" } { "spawnflags" "13" "classname" "monster_stalker" "origin" "112 768 800" } { "item" "ammo_bullets" "targetname" "t89" "spawnflags" "4" "classname" "monster_infantry" "origin" "-680 576 864" "angle" "180" } { "item" "ammo_grenades" "spawnflags" "773" "classname" "monster_gunner" "angle" "270" "origin" "-1104 1576 816" } { "model" "*132" "targetname" "t202" "spawnflags" "2050" "classname" "trigger_hurt" } { "origin" "-352 -224 -360" "angle" "0" "classname" "info_player_deathmatch" } { "origin" "1336 592 280" "angle" "180" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "696 760 88" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "1376 1440 288" } { "origin" "-128 1152 288" "angle" "315" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-40 208 280" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "-416 1312 288" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "80 1112 664" } { "origin" "-592 896 672" "angle" "225" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "-616 1176 856" } { "origin" "-1440 1760 920" "angle" "270" "classname" "info_player_deathmatch" } { "classname" "misc_explobox" "origin" "-240 -416 -272" "spawnflags" "2048" } { "light" "100" "origin" "-672 -160 48" "_color" "1.000000 0.913725 0.615686" "classname" "light" } { "light" "100" "classname" "light" "_color" "1.000000 0.913725 0.615686" "origin" "-672 -304 48" } { "light" "100" "origin" "-672 -416 48" "_color" "1.000000 0.913725 0.615686" "classname" "light" } { "light" "100" "classname" "light" "_color" "1.000000 0.913725 0.615686" "origin" "-552 -416 48" } { "classname" "light" "light" "110" "origin" "928 312 352" } { "origin" "1056 56 352" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "928 56 352" } { "origin" "1056 -200 352" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "792 -208 352" } { "origin" "792 -336 352" "light" "110" "classname" "light" } { "classname" "light" "light" "120" "origin" "1152 672 320" } { "origin" "1280 520 320" "light" "120" "classname" "light" } { "classname" "light" "light" "75" "origin" "1344 808 376" } { "origin" "1344 920 376" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "1344 1020 376" } { "classname" "light" "light" "150" "_color" "1.000000 1.000000 0.000000" "origin" "1060 1628 344" } { "classname" "light" "light" "110" "origin" "992 1376 496" } { "origin" "1144 1408 496" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "1312 1408 496" } { "origin" "1312 1248 496" "light" "110" "classname" "light" } { "origin" "1224 1152 320" "light" "120" "classname" "light" } { "classname" "light" "light" "120" "origin" "1224 1280 320" } { "origin" "1216 1464 320" "light" "120" "classname" "light" } { "_color" "1.000000 0.435294 0.435294" "classname" "light" "light" "65" "origin" "1120 1592 352" } { "origin" "1000 1592 352" "light" "65" "classname" "light" "_color" "1.000000 0.435294 0.435294" } { "style" "38" "targetname" "t262" "light" "60" "spawnflags" "1" "_color" "1.000000 0.435294 0.435294" "classname" "light" "origin" "656 712 416" } { "style" "34" "light" "60" "targetname" "t259" "_color" "1.000000 0.435294 0.435294" "origin" "720 712 416" "classname" "light" } { "classname" "light" "light" "80" "origin" "672 744 480" } { "origin" "736 744 480" "light" "80" "classname" "light" } { "classname" "light" "light" "75" "origin" "608 712 452" } { "origin" "672 712 452" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "736 712 452" } { "target" "t261" "classname" "light" "light" "240" "origin" "736 796 506" "_cone" "15" } { "targetname" "t261" "classname" "info_null" "origin" "736 744 396" } { "target" "t262" "classname" "func_timer" "spawnflags" "1" "wait" ".5" "origin" "656 768 416" } { "model" "*133" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "targetname" "t265" "message" "Access Door Locked" "wait" "-1" } { "model" "*134" "origin" "928 1440 573" "team" "cj" "distance" "16" "spawnflags" "12352" "classname" "func_door_rotating" "speed" "40" "targetname" "t265" } { "model" "*135" "origin" "928 1440 573" "target" "t83" "team" "cj" "classname" "func_door_rotating" "spawnflags" "8258" "distance" "16" "speed" "40" "targetname" "t265" "message" "Security Door Locked." } { "origin" "952 976 416" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "768 1016 416" } { "classname" "light" "light" "110" "origin" "584 976 416" } { "origin" "584 1232 416" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "840 1088 416" } { "classname" "light" "light" "110" "origin" "1144 1152 416" } { "_cone" "15" "origin" "672 796 506" "light" "240" "classname" "light" "target" "t266" } { "origin" "672 744 396" "classname" "info_null" "targetname" "t266" } { "classname" "light" "origin" "584 800 448" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "584 744 448" "classname" "light" } { "classname" "light" "origin" "584 884 412" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "584 944 412" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "760 740 412" "classname" "light" } { "classname" "light" "origin" "760 800 412" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "1044 1016 412" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "1104 1016 412" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "1032 992 416" "classname" "light" } { "classname" "light" "origin" "1032 872 408" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "840 768 408" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "800 840 404" "classname" "light" } { "origin" "776 1504 352" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "776 1376 352" } { "classname" "light" "light" "110" "origin" "520 1504 352" } { "origin" "520 1376 352" "light" "110" "classname" "light" } { "origin" "264 1504 352" "light" "110" "classname" "light" } { "classname" "light" "light" "110" "origin" "128 1368 352" } { "targetname" "t302" "classname" "monster_turret" "origin" "816 248 360" "spawnflags" "392" "angle" "0" } { "targetname" "t302" "angle" "180" "spawnflags" "392" "origin" "1168 -136 360" "classname" "monster_turret" } { "targetname" "t307" "angle" "0" "spawnflags" "136" "origin" "16 1432 368" "classname" "monster_turret" } { "targetname" "t307" "classname" "monster_turret" "origin" "712 1616 368" "spawnflags" "136" "angle" "270" } { "targetname" "t307" "angle" "90" "spawnflags" "136" "origin" "456 1264 368" "classname" "monster_turret" } { "origin" "416 832 408" "light" "80" "classname" "light" } { "classname" "light" "light" "80" "origin" "416 704 408" } { "origin" "88 1208 328" "light" "125" "classname" "light" } { "origin" "304 392 328" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "176 392 328" } { "origin" "104 752 248" "light" "75" "classname" "light" } { "origin" "120 256 320" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "-184 256 320" } { "target" "t268" "wait" "-1" "targetname" "t267" "origin" "-176 656 192" "classname" "path_corner" } { "target" "t267" "wait" "-1" "targetname" "t268" "classname" "path_corner" "origin" "-176 656 -192" } { "target" "t270" "wait" "-1" "targetname" "t269" "origin" "-64 704 192" "classname" "path_corner" } { "target" "t269" "wait" "-1" "targetname" "t270" "classname" "path_corner" "origin" "-64 704 0" } { "target" "t281" "wait" "-1" "targetname" "t280" "pathtarget" "btsp" "origin" "-124 816 272" "classname" "path_corner" } { "target" "t280" "targetname" "t279" "classname" "path_corner" "origin" "-128 816 272" } { "target" "t278" "wait" "-1" "targetname" "t277" "pathtarget" "tpsp" "origin" "-124 816 656" "classname" "path_corner" } { "targetname" "t282" "target" "t277" "origin" "-128 816 656" "classname" "path_corner" } { "target" "t279" "wait" ".1" "pathtarget" "hobbit" "targetname" "t278" "classname" "path_corner" "origin" "-128 816 656" } { "target" "t282" "pathtarget" "hobbit" "wait" ".1" "targetname" "t281" "origin" "-128 816 272" "classname" "path_corner" } { "targetname" "t273" "team" "smartass" "attenuation" "1" "classname" "target_speaker" "noise" "rotate/h_rot2.wav" "spawnflags" "0" "origin" "-24 968 360" } { "targetname" "t272" "team" "smartass" "classname" "target_speaker" "noise" "world/lift1.wav" "spawnflags" "2" "origin" "-40 696 360" } { "targetname" "t273" "team" "smartass" "origin" "-24 696 360" "spawnflags" "0" "noise" "rotate/h_rot2.wav" "classname" "target_speaker" "attenuation" "1" } { "targetname" "t272" "team" "dumbass" "classname" "target_speaker" "noise" "world/lift1.wav" "spawnflags" "2" "origin" "-40 968 648" } { "targetname" "t273" "team" "dumbass" "origin" "-24 968 648" "spawnflags" "0" "noise" "rotate/h_rot2.wav" "classname" "target_speaker" "attenuation" "1" } { "targetname" "t272" "team" "dumbass" "origin" "-40 696 648" "spawnflags" "2" "noise" "world/lift1.wav" "classname" "target_speaker" } { "targetname" "t273" "team" "dumbass" "attenuation" "1" "classname" "target_speaker" "noise" "rotate/h_rot2.wav" "spawnflags" "0" "origin" "-24 696 648" } { "target" "t271" "delay" ".5" "targetname" "tpgo" "classname" "trigger_relay" "origin" "-112 776 672" } { "target" "t272" "classname" "trigger_relay" "origin" "-80 880 672" "targetname" "tpsp" } { "target" "t273" "targetname" "tpsp" "origin" "-64 880 672" "classname" "trigger_relay" } { "target" "t274" "targetname" "btsp" "classname" "trigger_relay" "origin" "-96 880 288" } { "target" "t272" "targetname" "btsp" "origin" "-80 880 288" "classname" "trigger_relay" } { "target" "t273" "targetname" "btsp" "classname" "trigger_relay" "origin" "-64 880 288" } { "target" "t275" "origin" "-96 776 672" "classname" "trigger_relay" "targetname" "tpgo" } { "target" "t276" "origin" "-112 760 672" "classname" "trigger_relay" "targetname" "tpgo" } { "target" "t272" "delay" ".1" "targetname" "tpgo" "classname" "trigger_relay" "origin" "-96 760 672" } { "target" "t274" "targetname" "btgo" "origin" "-112 776 288" "classname" "trigger_relay" "delay" ".5" } { "target" "t275" "targetname" "btgo" "classname" "trigger_relay" "origin" "-96 776 288" } { "target" "t276" "targetname" "btgo" "classname" "trigger_relay" "origin" "-112 760 288" } { "target" "t272" "targetname" "btgo" "origin" "-96 760 288" "classname" "trigger_relay" "delay" ".1" } { "model" "*136" "message" "Fighter lift lowered" "classname" "trigger_multiple" "spawnflags" "12" "wait" "1" "targetname" "t271" "target" "tpgo" } { "model" "*137" "message" "Fighter lift raised" "wait" "1" "spawnflags" "12" "classname" "trigger_multiple" "targetname" "t274" "target" "btgo" } { "wait" "6" "targetname" "t284" "target" "t283" "classname" "path_corner" "origin" "-496 640 548" } { "classname" "target_speaker" "noise" "switches/butn2.wav" "attenuation" "1" "origin" "-476 604 560" "targetname" "t275" } { "origin" "-320 640 376" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-448 704 440" } { "origin" "-448 832 440" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-448 960 440" } { "origin" "-512 1024 440" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-576 1088 440" } { "origin" "-640 1024 440" "light" "100" "classname" "light" } { "pathtarget" "t113" "spawnflags" "2048" "wait" "-1" "target" "t288" "targetname" "t287" "classname" "path_corner" "origin" "-680 768 528" } { "spawnflags" "2048" "target" "t287" "targetname" "t286" "origin" "-680 760 632" "classname" "path_corner" } { "spawnflags" "2048" "target" "t286" "targetname" "t285" "classname" "path_corner" "origin" "-680 664 616" } { "classname" "light" "light" "100" "origin" "-640 528 808" } { "classname" "light" "light" "100" "origin" "-640 896 808" } { "origin" "-640 768 808" "light" "100" "classname" "light" } { "dmg" "2000" "origin" "-281 832 536" "angle" "180" "spawnflags" "9" "classname" "target_laser" "targetname" "t293" } { "dmg" "2000" "classname" "target_laser" "spawnflags" "2057" "angle" "180" "origin" "-281 832 596" "targetname" "t293" } { "dmg" "2000" "origin" "-281 832 624" "angle" "180" "spawnflags" "9" "classname" "target_laser" "targetname" "t293" } { "classname" "light" "light" "140" "origin" "-1128 1360 1064" } { "classname" "light" "light" "140" "origin" "-1240 1560 1064" } { "origin" "-1320 1560 1064" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "-1432 1376 1064" } { "origin" "-1432 1456 1064" "light" "140" "classname" "light" } { "origin" "-1320 1256 1064" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "-1240 1256 1064" } { "model" "*138" "classname" "func_wall" "spawnflags" "2054" "targetname" "jam" } { "origin" "328 316 320" "targetname" "jam" "noise" "world/force1.wav" "spawnflags" "2049" "classname" "target_speaker" } { "targetname" "jam" "origin" "360 316 288" "target" "t296" "spawnflags" "2049" "message" "za" "speed" ".5" "classname" "target_lightramp" } { "style" "39" "targetname" "t296" "origin" "336 316 272" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" } { "style" "39" "targetname" "t296" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "336 316 376" } { "style" "39" "targetname" "t296" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "336 372 320" } { "style" "39" "targetname" "t296" "origin" "336 260 320" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" } { "style" "39" "targetname" "t296" "origin" "336 372 376" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" } { "style" "39" "targetname" "t296" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "336 260 376" } { "style" "39" "targetname" "t296" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "336 372 272" } { "style" "39" "targetname" "t296" "origin" "336 260 272" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" } { "classname" "light" "light" "100" "origin" "-288 704 768" } { "model" "*139" "targetname" "mhowell" "target" "t212" "wait" "-1" "speed" "300" "angle" "-1" "classname" "func_door" "spawnflags" "2048" } { "classname" "light" "light" "80" "_color" "1.000000 1.000000 0.501961" "origin" "184 2032 -40" } { "origin" "-176 2024 -64" "_color" "1.000000 1.000000 0.501961" "light" "80" "classname" "light" } { "classname" "light" "light" "80" "_color" "1.000000 1.000000 0.501961" "origin" "-176 2192 -64" } { "classname" "info_player_coop" "targetname" "rsewer2b" "angle" "270" "origin" "-72 2704 -168" } { "origin" "40 2736 -168" "angle" "315" "targetname" "rsewer2b" "classname" "info_player_coop" } { "target" "t301" "targetname" "t7" "classname" "trigger_relay" "origin" "-816 -528 -216" } { "model" "*140" "classname" "trigger_multiple" "spawnflags" "2316" "target" "t302" "wait" "5" "targetname" "t392" } { "targetname" "t306" "target" "t304" "classname" "monster_gunner" "spawnflags" "1" "angle" "270" "origin" "1120 1568 288" } { "targetname" "t306" "target" "t303" "origin" "1000 1568 288" "angle" "270" "spawnflags" "1" "classname" "monster_gunner" "item" "ammo_grenades" } { "targetname" "t304" "classname" "point_combat" "origin" "1120 1552 272" } { "spawnflags" "1" "targetname" "t305" "origin" "1048 1472 272" "classname" "point_combat" } { "model" "*141" "target" "t307" "classname" "trigger_multiple" "spawnflags" "2056" "targetname" "t394" } { "model" "*142" "spawnflags" "2056" "classname" "trigger_multiple" "target" "t307" "targetname" "t394" } { "item" "ammo_cells" "classname" "monster_turret" "angle" "-2" "origin" "928 928 512" "spawnflags" "264" "target" "t396" } { "targetname" "t383" "spawnflags" "1" "target" "t330" "classname" "monster_infantry" "angle" "90" "origin" "-144 208 280" } { "targetname" "t383" "spawnflags" "769" "origin" "-40 208 280" "angle" "90" "classname" "monster_infantry" } { "targetname" "rsewer2a" "classname" "info_player_start" "origin" "-352 -224 -352" } { "targetname" "rsewer2a" "classname" "info_player_coop" "angle" "0" "origin" "-304 -360 -40" } { "targetname" "rsewer2a" "origin" "-488 -296 -16" "angle" "0" "classname" "info_player_coop" } { "targetname" "rsewer2a" "classname" "info_player_coop" "angle" "0" "origin" "-352 -224 -328" } { "origin" "-160 2704 -168" "angle" "270" "targetname" "rsewer2b" "classname" "info_player_coop" } { "classname" "light" "light" "125" "origin" "-208 760 328" } { "origin" "448 568 328" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "504 352 328" } { "origin" "168 336 328" "light" "125" "classname" "light" } { "origin" "-448 768 472" "angle" "-2" "spawnflags" "136" "classname" "monster_turret" "targetname" "t315" } { "item" "ammo_bullets" "targetname" "t315" "origin" "-688 1000 288" "angle" "0" "classname" "monster_gunner" "spawnflags" "1" } { "classname" "monster_turret" "origin" "-704 2048 264" "angle" "270" "spawnflags" "8" } { "classname" "light" "light" "75" "origin" "-448 328 568" } { "targetname" "t325" "target" "t316" "angle" "90" "spawnflags" "2" "classname" "monster_daedalus" "origin" "64 -1448 720" } { "target" "t319" "targetname" "t316" "classname" "path_corner" "origin" "64 -840 704" } { "targetname" "t318" "classname" "path_corner" "origin" "-192 -704 448" } { "targetname" "t319" "origin" "128 -704 448" "classname" "path_corner" } { "classname" "path_corner" "origin" "-32 -840 704" "targetname" "t320" "target" "t320" } { "targetname" "t325" "classname" "monster_daedalus" "origin" "-32 -1448 720" "angle" "90" "spawnflags" "2" "target" "t320" } { "origin" "-32 -704 448" "classname" "path_corner" "targetname" "t320" } { "target" "t322" "classname" "monster_gunner" "spawnflags" "5" "angle" "0" "origin" "-736 1272 288" "targetname" "t311" } { "spawnflags" "1" "targetname" "t322" "classname" "point_combat" "origin" "-608 1360 272" } { "targetname" "t312" "target" "t325" "classname" "trigger_relay" "origin" "-88 -1408 696" } { "classname" "monster_gunner" "angle" "0" "origin" "872 768 376" "spawnflags" "0" } { "item" "ammo_bullets" "classname" "monster_gunner" "angle" "270" "spawnflags" "1" "origin" "944 1104 376" "targetname" "t396" } { "targetname" "t330" "target" "t326" "origin" "-448 728 288" "angle" "270" "classname" "monster_gunner" "spawnflags" "772" } { "spawnflags" "0" "classname" "point_combat" "targetname" "t328" "origin" "-128 528 272" } { "item" "ammo_grenades" "targetname" "t330" "spawnflags" "260" "classname" "monster_gunner" "angle" "270" "origin" "-448 800 288" "target" "t328" } { "spawnflags" "0" "origin" "-184 608 272" "targetname" "t329" "classname" "point_combat" } { "targetname" "t330" "target" "t329" "origin" "-448 840 288" "angle" "270" "classname" "monster_gunner" "spawnflags" "260" } { "targetname" "t331" "classname" "monster_berserk" "spawnflags" "260" "angle" "90" "origin" "440 320 288" } { "style" "40" "classname" "light" "origin" "-896 1888 272" "_color" "1.000000 0.435294 0.435294" "targetname" "t333" "light" "60" } { "origin" "-832 1968 228" "light" "75" "classname" "light" } { "style" "41" "light" "60" "targetname" "t334" "_color" "1.000000 0.435294 0.435294" "origin" "-896 1824 272" "classname" "light" } { "style" "42" "classname" "light" "origin" "-896 1760 272" "_color" "1.000000 0.435294 0.435294" "targetname" "t335" "light" "60" } { "style" "43" "light" "60" "targetname" "t336" "_color" "1.000000 0.435294 0.435294" "origin" "-896 1904 224" "classname" "light" } { "style" "44" "classname" "light" "origin" "-896 1840 224" "_color" "1.000000 0.435294 0.435294" "targetname" "t337" "light" "60" } { "style" "45" "light" "60" "targetname" "t338" "_color" "1.000000 0.435294 0.435294" "origin" "-896 1776 224" "classname" "light" } { "style" "46" "classname" "light" "origin" "-896 1888 200" "_color" "1.000000 0.435294 0.435294" "targetname" "t339" "light" "60" } { "style" "47" "light" "60" "targetname" "t340" "_color" "1.000000 0.435294 0.435294" "origin" "-896 1824 200" "classname" "light" } { "style" "48" "classname" "light" "origin" "-896 1760 200" "_color" "1.000000 0.435294 0.435294" "targetname" "t341" "light" "60" } { "style" "49" "light" "60" "targetname" "t342" "_color" "1.000000 0.435294 0.435294" "origin" "-848 1688 184" "classname" "light" } { "style" "50" "classname" "light" "origin" "-816 1664 184" "_color" "1.000000 0.435294 0.435294" "targetname" "t343" "light" "60" } { "style" "51" "light" "60" "targetname" "t344" "_color" "1.000000 0.435294 0.435294" "origin" "-824 1976 184" "classname" "light" } { "classname" "light" "light" "75" "origin" "-792 2008 284" } { "origin" "-856 1944 284" "light" "75" "classname" "light" } { "origin" "-800 1640 284" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "-864 1704 284" } { "classname" "light" "light" "75" "origin" "-832 1672 228" } { "origin" "-856 1816 188" "light" "75" "classname" "light" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "origin" "-816 1712 184" } { "origin" "-824 1928 184" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-600 728 576" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "origin" "-584 960 576" } { "origin" "-352 952 576" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "origin" "-544 544 576" } { "origin" "680 768 448" "noise" "world/comp_hum3.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "-16 -48 64" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "192 -200 64" } { "origin" "-88 -312 64" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "-440 -400 64" } { "origin" "-80 -568 64" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "176 -472 64" } { "origin" "-320 -864 64" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "32 -760 64" } { "origin" "-152 16 368" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "136 24 368" } { "origin" "440 -152 368" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "544 -384 368" } { "origin" "392 -648 368" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "136 -888 368" } { "origin" "-216 -976 368" "noise" "world/wind2.wav" "spawnflags" "1" "classname" "target_speaker" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/wind2.wav" "origin" "-208 -984 368" } { "origin" "-544 1984 284" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "-544 1824 284" } { "origin" "-544 1664 284" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "-768 1856 284" } { "origin" "-544 2216 244" "light" "115" "classname" "light" } { "classname" "light" "light" "140" "origin" "-160 2624 20" } { "origin" "96 2624 20" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "352 2624 20" } { "origin" "608 2624 20" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "584 2400 20" } { "origin" "488 2152 -56" "light" "125" "classname" "light" } { "origin" "224 2088 56" "targetname" "t347" "classname" "point_combat" "spawnflags" "1" } { "target" "t347" "spawnflags" "1" "origin" "320 2008 72" "angle" "270" "classname" "monster_gunner" } { "classname" "light" "origin" "-576 632 576" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "light" "75" "origin" "-640 616 616" } { "origin" "-640 544 616" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "-640 480 616" } { "origin" "-600 480 584" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "-600 544 584" } { "origin" "-592 608 584" "light" "75" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-608 456 576" "classname" "light" } { "classname" "light" "origin" "-632 456 608" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-592 456 608" "classname" "light" } { "style" "33" "origin" "-392 832 608" "light" "125" "_color" "0.000000 0.000000 1.000000" "classname" "light" "targetname" "t293" } { "style" "33" "origin" "-312 832 544" "light" "125" "_color" "0.000000 0.000000 1.000000" "classname" "light" "targetname" "t293" } { "style" "33" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "125" "origin" "-392 832 544" "targetname" "t293" } { "origin" "-440 704 536" "light" "70" "_color" "1.000000 1.000000 0.501961" "classname" "light" } { "classname" "light" "_color" "1.000000 1.000000 0.501961" "light" "70" "origin" "-264 640 536" } { "origin" "-264 512 536" "light" "70" "_color" "1.000000 1.000000 0.501961" "classname" "light" } { "origin" "-320 1000 612" "light" "90" "classname" "light" } { "classname" "light" "light" "90" "origin" "-456 1000 612" } { "origin" "-576 1000 612" "light" "90" "classname" "light" } { "classname" "light" "origin" "-576 1016 572" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-456 1016 572" "classname" "light" } { "classname" "light" "origin" "-320 1016 572" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "light" "90" "origin" "-632 952 612" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-632 984 564" "classname" "light" } { "classname" "light" "origin" "-632 928 564" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "-520 864 564" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-520 808 564" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-552 656 564" "classname" "light" } { "classname" "light" "origin" "-616 656 564" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "origin" "-520 872 612" "light" "75" "classname" "light" } { "classname" "light" "light" "75" "origin" "-520 800 612" } { "classname" "light" "light" "75" "origin" "-520 744 612" } { "origin" "-520 672 612" "light" "75" "classname" "light" } { "origin" "-344 600 696" "target" "t364" "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t366" } { "model" "*143" "targetname" "t364" "classname" "func_explosive" } { "item" "ammo_cells" "targetname" "t364" "angle" "90" "spawnflags" "136" "origin" "-384 528 704" "classname" "monster_turret" } { "origin" "-384 600 672" "angle" "90" "spawnflags" "1" "classname" "monster_berserk" "target" "t366" "targetname" "t367" } { "target" "t389" "origin" "-960 592 672" "angle" "90" "spawnflags" "769" "classname" "monster_berserk" "targetname" "t368" } { "classname" "light" "light" "115" "origin" "-640 896 948" } { "origin" "-640 704 948" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "-640 512 948" } { "origin" "-640 1112 948" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "-768 1152 948" } { "origin" "-1024 1408 800" "light" "80" "_color" "1.000000 1.000000 0.501961" "classname" "light" } { "classname" "light" "_color" "1.000000 1.000000 0.501961" "light" "80" "origin" "-1536 1408 800" } { "origin" "-904 1408 960" "light" "100" "classname" "light" } { "origin" "-1408 1784 976" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-1152 1784 976" } { "origin" "-1280 1032 904" "light" "100" "classname" "light" } { "classname" "light" "origin" "-896 -472 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-896 -536 -120" "classname" "light" } { "classname" "light" "origin" "-896 -600 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "origin" "-800 -720 -104" "light" "80" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-808 -712 -160" "classname" "light" } { "classname" "light" "origin" "-800 -728 -184" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-856 -664 -200" "classname" "light" } { "classname" "light" "origin" "-848 -408 -160" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-856 -424 -184" "classname" "light" } { "classname" "light" "origin" "-800 -360 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "light" "80" "origin" "-848 -672 -104" } { "classname" "light" "light" "80" "origin" "-808 -376 -104" } { "origin" "-856 -424 -104" "light" "80" "classname" "light" } { "origin" "-1080 -136 -248" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-1080 -56 -248" } { "classname" "light" "light" "65" "origin" "-840 120 -248" } { "origin" "-760 120 -248" "light" "65" "classname" "light" } { "origin" "-592 -152 -248" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-592 -232 -248" } { "classname" "light" "light" "65" "origin" "-760 -152 -248" } { "origin" "-760 -232 -248" "light" "65" "classname" "light" } { "origin" "-208 -408 -264" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-208 -488 -264" } { "classname" "light" "light" "65" "origin" "-568 -408 -264" } { "origin" "-568 -504 -264" "light" "65" "classname" "light" } { "origin" "-568 -640 -264" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-568 -720 -264" } { "classname" "light" "light" "65" "origin" "-792 -200 -248" } { "origin" "-792 -120 -248" "light" "65" "classname" "light" } { "origin" "1456 992 336" "spawnflags" "2048" "classname" "path_corner" "targetname" "t370" "target" "t371" } { "classname" "light" "light" "115" "origin" "-608 1984 284" } { "origin" "-608 1824 284" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "-608 1664 284" } { "classname" "light" "light" "115" "origin" "-608 2216 244" } { "origin" "-768 1784 284" "light" "115" "classname" "light" } { "origin" "-160 2688 20" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "96 2688 20" } { "origin" "352 2688 20" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "608 2688 20" } { "origin" "648 2400 20" "light" "140" "classname" "light" } { "origin" "672 2192 -112" "targetname" "t376" "classname" "point_combat" "target" "t377" } { "classname" "point_combat" "targetname" "t377" "origin" "744 2216 -112" "spawnflags" "1" } { "origin" "-248 2072 88" "spawnflags" "1" "targetname" "t379" "classname" "point_combat" } { "target" "t379" "spawnflags" "769" "classname" "monster_gunner" "angle" "45" "origin" "-200 1872 104" } { "style" "32" "classname" "light" "light" "65" "targetname" "t302" "spawnflags" "1" "origin" "1120 -136 360" } { "style" "32" "origin" "864 248 360" "spawnflags" "1" "targetname" "t302" "light" "65" "classname" "light" } { "style" "52" "classname" "light" "light" "65" "targetname" "t307" "spawnflags" "1" "origin" "456 1312 368" } { "style" "52" "origin" "712 1568 368" "spawnflags" "1" "targetname" "t307" "light" "65" "classname" "light" } { "style" "52" "classname" "light" "light" "65" "targetname" "t307" "spawnflags" "1" "origin" "64 1432 368" } { "model" "*144" "angle" "-1" "classname" "func_door" "targetname" "t383" "wait" "-1" } { "angle" "270" "spawnflags" "136" "origin" "200 1616 368" "classname" "monster_turret" "targetname" "t383" } { "style" "53" "classname" "light" "light" "65" "targetname" "t383" "spawnflags" "1" "origin" "200 1568 368" } { "classname" "light" "origin" "-208 -392 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-208 -392 -96" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-208 -456 -120" "classname" "light" } { "classname" "light" "origin" "-208 -456 -96" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "-208 -328 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-208 -328 -96" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-232 -264 -120" "classname" "light" } { "classname" "light" "origin" "-232 -264 -96" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "-264 -200 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-264 -200 -96" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-288 -136 -120" "classname" "light" } { "classname" "light" "origin" "-288 -136 -96" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "-208 -520 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-208 -520 -96" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-232 -584 -120" "classname" "light" } { "classname" "light" "origin" "-232 -584 -96" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "origin" "-264 -640 -120" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-264 -640 -96" "classname" "light" } { "classname" "light" "origin" "-208 -416 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-208 -352 -200" "classname" "light" } { "classname" "light" "origin" "-208 -472 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-216 -544 -200" "classname" "light" } { "classname" "light" "origin" "-240 -600 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-272 -664 -200" "classname" "light" } { "classname" "light" "origin" "-216 -288 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-248 -232 -200" "classname" "light" } { "classname" "light" "origin" "-272 -168 -200" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "classname" "light" "light" "80" "origin" "-352 -336 -104" } { "origin" "-352 -504 -104" "light" "80" "classname" "light" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-160 -352 -136" "classname" "light" } { "classname" "light" "origin" "-128 -352 -136" "_color" "1.000000 0.435294 0.435294" "light" "60" } { "light" "60" "_color" "1.000000 0.435294 0.435294" "origin" "-96 -352 -136" "classname" "light" } { "targetname" "t43" "noise" "world/airhiss2.wav" "classname" "target_speaker" "origin" "760 864 56" } { "spawnflags" "2" "targetname" "heybuddy" "noise" "world/mach3.wav" "origin" "760 848 56" "classname" "target_speaker" } { "targetname" "iliketrafficlights" "classname" "target_speaker" "origin" "960 880 56" "noise" "world/lite_on3.wav" } { "targetname" "t43" "origin" "960 864 56" "classname" "target_speaker" "noise" "world/airhiss2.wav" } { "targetname" "heybuddy" "spawnflags" "2" "classname" "target_speaker" "origin" "960 848 56" "noise" "world/mach3.wav" } { "targetname" "iliketrafficlights" "noise" "world/lite_on3.wav" "origin" "1152 880 56" "classname" "target_speaker" } { "targetname" "t43" "noise" "world/airhiss2.wav" "classname" "target_speaker" "origin" "1152 864 56" } { "targetname" "heybuddy" "spawnflags" "2" "noise" "world/mach3.wav" "origin" "1152 848 56" "classname" "target_speaker" } { "targetname" "iliketrafficlights" "classname" "target_speaker" "origin" "1408 880 56" "noise" "world/lite_on3.wav" } { "targetname" "t43" "origin" "1408 864 56" "classname" "target_speaker" "noise" "world/airhiss2.wav" } { "targetname" "heybuddy" "spawnflags" "2" "classname" "target_speaker" "origin" "1408 848 56" "noise" "world/mach3.wav" } { "origin" "-24 2824 -168" "angle" "270" "targetname" "rsewer2b" "classname" "info_player_coop" } { "model" "*145" "angle" "270" "classname" "func_button" "wait" "4" "target" "t386" } { "origin" "-552 840 536" "targetname" "t387" "spawnflags" "1" "classname" "point_combat" } { "targetname" "t388" "classname" "point_combat" "origin" "-928 752 656" } { "origin" "-384 576 768" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "-384 1184 768" } { "origin" "-264 896 536" "light" "70" "_color" "1.000000 1.000000 0.501961" "classname" "light" } { "classname" "light" "_color" "1.000000 1.000000 0.501961" "light" "70" "origin" "-480 904 536" } { "origin" "-632 832 536" "light" "70" "_color" "1.000000 1.000000 0.501961" "classname" "light" } { "classname" "light" "light" "65" "origin" "-32 2312 16" } { "origin" "-64 2328 72" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-64 2392 72" } { "origin" "0 2392 72" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "0 2328 72" } { "classname" "light" "light" "65" "origin" "-584 320 672" } { "origin" "-584 320 768" "light" "65" "classname" "light" } { "classname" "light" "light" "65" "origin" "-584 320 864" } { "origin" "-1656 1472 944" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "-1656 1552 944" } { "classname" "light" "light" "140" "origin" "-904 1472 944" } { "origin" "-904 1552 944" "light" "140" "classname" "light" } { "model" "*146" "team" "nascar" "classname" "func_door" "wait" "1" "target" "t391" "angle" "-1" } { "style" "10" "targetname" "t391" "classname" "func_areaportal" } { "classname" "light" "light" "100" "origin" "4036 -4068 -4068" } { "_color" "0.000000 0.000000 1.000000" "origin" "4072 -4068 -4068" "light" "100" "classname" "light" } { "delay" "1" "origin" "480 -224 272" "spawnflags" "2048" "killtarget" "t394" "classname" "trigger_relay" "targetname" "t307" } { "origin" "464 -200 272" "target" "t394" "targetname" "t301" "spawnflags" "2048" "classname" "trigger_relay" } { "message" "Open primary entrance." "spawnflags" "0" "origin" "80 -200 344" "classname" "target_help" "targetname" "t11help" // b#2: t11 -> t11help } { "origin" "168 2648 -104" "classname" "target_help" "targetname" "t218" "message" "Disarm Yellow Forcefields" } { "origin" "-600 -736 -240" "classname" "ammo_slugs" "spawnflags" "1792" } { "origin" "-240 -480 -256" "spawnflags" "1792" "classname" "item_health" } { "origin" "-1048 -144 -240" "classname" "item_armor_shard" } { "classname" "item_armor_shard" "origin" "-1048 -112 -240" } { "origin" "-1048 -80 -240" "classname" "item_armor_shard" } { "classname" "item_armor_shard" "origin" "-1048 -48 -240" } { "origin" "-1048 -16 -240" "classname" "item_armor_shard" } { "origin" "-40 48 -64" "classname" "ammo_bullets" } { "origin" "432 -240 184" "spawnflags" "1792" "classname" "item_armor_shard" } { "classname" "item_armor_shard" "spawnflags" "1792" "origin" "440 -312 184" } { "origin" "456 -376 184" "spawnflags" "1792" "classname" "item_armor_shard" } { "origin" "-320 -1016 -64" "classname" "ammo_flechettes" // b#4: nails -> flechettes } { "origin" "1344 736 288" "spawnflags" "1536" "classname" "item_health_small" } { "classname" "item_health_small" "spawnflags" "1536" "origin" "1344 864 288" } { "origin" "1344 992 288" "spawnflags" "1536" "classname" "item_health_small" } { "classname" "item_health_small" "spawnflags" "1536" "origin" "1344 1072 280" } { "origin" "672 992 80" "classname" "item_health_large" "spawnflags" "1024" } { "classname" "item_health" "origin" "928 968 368" } { "spawnflags" "1792" "classname" "ammo_tesla" "origin" "1024 -304 272" } { "classname" "item_health" "origin" "-16 1176 280" } { "spawnflags" "1792" "classname" "ammo_prox" "origin" "232 -472 -64" } { "classname" "item_health_large" "spawnflags" "1024" "origin" "-392 1920 112" } { "origin" "-392 2048 112" "spawnflags" "3584" "classname" "item_health_large" } { "classname" "ammo_flechettes" // b#4: nails -> flechettes "origin" "-32 2528 -176" } { "classname" "item_armor_shard" "origin" "-616 896 544" } { "origin" "-616 960 544" "classname" "item_armor_shard" } { "classname" "item_armor_body" "spawnflags" "1792" "origin" "-896 704 512" } { "classname" "ammo_shells" "origin" "-120 1112 656" } { "classname" "item_health" "origin" "-624 544 848" } { "classname" "item_health" "origin" "1120 1568 280" } { "origin" "1632 744 80" "classname" "item_health_large" } { "spawnflags" "1024" "classname" "item_health_large" "origin" "-144 208 272" } { "classname" "item_health_large" "origin" "456 1440 280" } { "model" "*147" "origin" "-432 -632 -24" "_minlight" ".1" "speed" "300" "distance" "100" "spawnflags" "2210" "classname" "func_door_rotating" "targetname" "t311" } { "classname" "target_speaker" "noise" "world/unit3_05.wav" "spawnflags" "4" "origin" "-1352 1696 928" "targetname" "porkin" "attenuation" "-1" } { "target" "t401" "targetname" "t400" "classname" "hint_path" "spawnflags" "2048" "origin" "-1288 1104 864" } { "target" "t402" "targetname" "t401" "origin" "-1120 1096 864" "spawnflags" "2048" "classname" "hint_path" } { "target" "t403" "targetname" "t402" "classname" "hint_path" "spawnflags" "2048" "origin" "-968 1152 864" } { "target" "t404" "targetname" "t403" "origin" "-640 1152 864" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t404" "classname" "hint_path" "spawnflags" "2049" "origin" "-640 496 864" } { "model" "*148" "spawnflags" "2048" "classname" "func_water" "team" "argh5" } { "model" "*149" "classname" "func_water" "spawnflags" "2048" "team" "argh2" } { "model" "*150" "classname" "func_water" "spawnflags" "2048" "team" "argh3" } { "model" "*151" "classname" "func_water" "spawnflags" "2048" "team" "argh4" }rogue-ROGUE_2_13/stuff/mapfixes/rmine1.ent000066400000000000000000003207331477320066100204660ustar00rootroot00000000000000{ "sounds" "6" "sky" "rogue1" "message" "Lower Mines" "classname" "worldspawn" "nextmap" "rlava1" } { "model" "*1" "target" "t296" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*2" "spawnflags" "5888" "classname" "func_wall" } { "model" "*3" "spawnflags" "2048" "classname" "func_wall" } { "model" "*4" "spawnflags" "2048" "classname" "func_wall" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "2000 216 584" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "1472 -48 584" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "1544 -1152 392" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "808 -1360 608" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "72 -1384 984" } { "classname" "misc_teleporter_dest" "targetname" "tele2" "spawnflags" "5888" "angle" "0" "origin" "-784 -1984 8" } { "classname" "misc_teleporter" "spawnflags" "5888" "angle" "225" "origin" "304 -240 736" "target" "tele2" } { "classname" "misc_teleporter_dest" "angle" "45" "spawnflags" "5888" "targetname" "t363" "origin" "1168 248 712" } { "classname" "misc_teleporter" "spawnflags" "5888" "angle" "45" "target" "t363" "origin" "-560 -1024 8" } { "origin" "1192 -1424 544" "attenuation" "-1" "noise" "world/voice5.wav" "targetname" "t362" "classname" "target_speaker" "spawnflags" "2048" } { "model" "*5" "target" "t362" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*6" "targetname" "gibber" "target" "t361" "classname" "trigger_once" } { "model" "*7" "target" "t361" "targetname" "t98" "classname" "trigger_once" } { "targetname" "t361" "noise" "world/mach2.wav" "origin" "656 0 520" "spawnflags" "2" "team" "boxcrane" "classname" "target_speaker" } { "targetname" "t361" "noise" "world/mach2.wav" "origin" "624 0 520" "spawnflags" "2" "team" "boxcrane" "classname" "target_speaker" } { "classname" "target_speaker" "noise" "world/lava1.wav" "spawnflags" "1" "origin" "1632 360 360" } { "origin" "1992 176 504" "attenuation" "-1" "noise" "world/voice10.wav" "targetname" "t360" "classname" "target_speaker" "spawnflags" "2048" } { "model" "*8" "target" "t360" "classname" "trigger_once" "spawnflags" "2048" } { "origin" "-2152 -2200 56" "target" "t359" "delay" "25" "targetname" "t277" "classname" "trigger_relay" } { "origin" "-2144 -2136 56" "targetname" "t359" "noise" "world/voice1.wav" "attenuation" "-1" "classname" "target_speaker" } { "origin" "1168 704 520" "angle" "315" "classname" "info_player_deathmatch" } { "origin" "832 -288 536" "angle" "270" "classname" "info_player_deathmatch" } { "origin" "512 -256 592" "spawnflags" "5888" "classname" "item_sphere_hunter" } { "spawnflags" "5888" "origin" "2096 -376 416" "classname" "item_sphere_vengeance" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "1056 -408 528" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "-736 -704 8" } { "origin" "1968 992 576" "spawnflags" "5888" "classname" "item_sphere_defender" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "1696 -504 768" } { "origin" "920 -1112 880" "spawnflags" "5888" "classname" "ammo_flechettes" } { "origin" "992 -1112 880" "spawnflags" "5888" "classname" "weapon_etf_rifle" } { "spawnflags" "5888" "origin" "864 -480 728" "classname" "weapon_chainfist" } { "origin" "-584 -2208 0" "classname" "ammo_cells" "spawnflags" "5888" } { "origin" "-528 -2208 0" "spawnflags" "5888" "classname" "ammo_cells" } { "origin" "-752 -1760 0" "spawnflags" "5888" "classname" "weapon_heatbeam" } { "model" "*9" "spawnflags" "2048" "classname" "func_wall" } { "angle" "180" "origin" "-224 -872 8" "classname" "info_player_deathmatch" } { "origin" "-2048 -2312 24" "spawnflags" "5888" "classname" "ammo_rockets" } { "origin" "-1952 -2296 24" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "angle" "90" "classname" "info_player_deathmatch" "origin" "-1088 -2192 168" } { "model" "*10" "spawnflags" "5888" "classname" "func_wall" } { "model" "*11" "spawnflags" "5888" "classname" "func_wall" } { "model" "*12" "spawnflags" "2048" "classname" "func_wall" } { "spawnflags" "5888" "origin" "312 -656 896" "classname" "ammo_flechettes" } { "origin" "392 -720 896" "spawnflags" "5888" "classname" "weapon_etf_rifle" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "1760 -408 528" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "2056 -8 800" } { "origin" "1800 272 512" "spawnflags" "5888" "classname" "weapon_chaingun" } { "origin" "584 -552 520" "spawnflags" "5888" "classname" "weapon_railgun" } { "origin" "1072 -1120 888" "angle" "270" "classname" "info_player_deathmatch" } { "origin" "1704 -968 752" "angle" "0" "classname" "info_player_deathmatch" } { "origin" "320 -416 736" "angle" "0" "classname" "info_player_deathmatch" } { "noise" "world/flyby1.wav" "origin" "-1632 -2400 280" "classname" "target_speaker" "spawnflags" "2048" "targetname" "t357" } { "spawnflags" "2049" "origin" "-1760 -2376 120" "wait" "5" "classname" "func_timer" "random" "2" "target" "t358" } { "noise" "world/battle3.wav" "origin" "-1720 -2408 120" "classname" "target_speaker" "spawnflags" "2048" "targetname" "t358" } { "spawnflags" "2049" "random" "2" "classname" "func_timer" "wait" "5" "target" "t357" "origin" "-1672 -2368 280" } { "spawnflags" "2048" "classname" "target_speaker" "origin" "-1600 -2384 280" "noise" "world/flyby1.wav" "targetname" "t357" } { "spawnflags" "2049" "wait" "5" "classname" "func_timer" "target" "t356" "random" "2" "origin" "-2016 -2248 120" } { "noise" "world/battle2.wav" "origin" "-1976 -2280 120" "classname" "target_speaker" "targetname" "t356" "spawnflags" "2052" } { "spawnflags" "2049" "classname" "func_timer" "target" "t355" "wait" "3" "origin" "-2080 -1976 120" } { "classname" "target_speaker" "origin" "-2040 -2008 120" "noise" "world/battle1.wav" "targetname" "t355" "spawnflags" "2048" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "1472 -864 536" "classname" "target_speaker" } { "classname" "target_speaker" "origin" "1440 -1496 560" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1872 -1496 408" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1920 -1240 408" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1624 -1224 856" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1336 -1168 408" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1408 -672 744" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1664 -936 784" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "2208 -384 808" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1984 -536 808" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1440 -104 552" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1944 -48 568" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "2032 576 616" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1800 192 560" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1328 192 736" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1448 656 528" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1592 768 752" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1240 760 576" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "944 496 760" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "384 120 784" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "280 -464 784" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "688 -480 784" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "640 -688 560" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "224 -672 560" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "376 -1224 888" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "1144 -112 624" "noise" "world/amb17.wav" "spawnflags" "2" "targetname" "t81" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-512 -664 72" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-936 -720 72" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-896 -1064 72" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-608 -1064 72" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-224 -1760 56" "classname" "target_speaker" } { "volume" ".5" "origin" "-1304 -1464 0" "classname" "target_speaker" "noise" "world/lava1.wav" "spawnflags" "2048" "targetname" "t15" } { "classname" "target_speaker" "origin" "-808 -1856 72" "noise" "world/amb2.wav" "spawnflags" "1" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-808 -2144 592" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-808 -2112 72" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-480 -1752 584" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-152 -1888 584" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-152 -2016 56" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-192 -2472 760" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-448 -2472 760" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-768 -2472 688" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-928 -2344 1072" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-928 -1624 1072" "classname" "target_speaker" } { "classname" "target_speaker" "origin" "-1272 -1728 1168" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "-416 -2208 592" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "-544 -1760 64" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "-224 -800 72" "noise" "world/amb2.wav" "spawnflags" "1" } { "classname" "target_speaker" "origin" "192 -1704 912" "noise" "world/amb2.wav" "spawnflags" "1" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "-1272 -2240 1168" "classname" "target_speaker" } { "spawnflags" "1" "noise" "world/amb2.wav" "origin" "928 -1664 712" "classname" "target_speaker" } { "classname" "target_speaker" "origin" "-64 -1704 912" "noise" "world/amb2.wav" "spawnflags" "1" } { "spawnflags" "2" "noise" "world/amb17.wav" "origin" "928 -1760 840" "classname" "target_speaker" "targetname" "t81" } { "volume" ".5" "spawnflags" "2048" "noise" "world/lava1.wav" "classname" "target_speaker" "origin" "-1760 -2320 112" } { "volume" ".5" "origin" "-2160 -2064 112" "classname" "target_speaker" "noise" "world/lava1.wav" "spawnflags" "2048" "targetname" "t354" } { "spawnflags" "2049" "origin" "-2073 -2072 24" "classname" "func_timer" "wait" "4" "random" "2" "target" "t354" } { "spawnflags" "2049" "origin" "-2138 -2093 -8" "classname" "target_splash" "sounds" "5" "count" "40" "targetname" "t354" } { "classname" "light" "light" "100" "origin" "320 -544 600" } { "model" "*13" "spawnflags" "2049" "classname" "trigger_counter" "count" "2" "targetname" "blowgrate" "target" "t352" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "boom" "killtarget" "gibber" "origin" "696 -104 792" } { "spawnflags" "2048" "classname" "trigger_relay" "target" "blowgrate" "targetname" "gibber" "origin" "664 -424 792" } { "spawnflags" "2048" "killtarget" "blocko" "delay" ".3" "origin" "-504 -1848 600" "classname" "trigger_relay" "targetname" "t258" } { "spawnflags" "2048" "classname" "trigger_relay" "origin" "-472 -1880 600" "targetname" "blocko" "delay" ".3" "target" "blockwall" } { "model" "*14" "classname" "trigger_counter" "spawnflags" "1" "count" "2" "targetname" "blockwall" "target" "waller" } { "model" "*15" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t350" "target" "booger1" } { "model" "*16" "spawnflags" "2048" "target" "t349" "classname" "trigger_multiple" } { "spawnflags" "2048" "origin" "-2040 -2280 72" "target" "booger1" "targetname" "t5" "classname" "trigger_relay" } { "origin" "1728 -840 744" "classname" "item_health" } { "classname" "item_health_large" "origin" "-72 -1280 848" } { "classname" "monster_soldier" "angle" "270" "spawnflags" "1536" "target" "t169" "origin" "72 -1184 952" } { "classname" "info_player_intermission" "angles" "30 225 0" "origin" "1472 -208 872" } { "origin" "-688 -512 88" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-784 -512 88" } { "origin" "1936 784 656" "light" "100" "classname" "light" } { "classname" "monster_berserk" "angle" "90" "spawnflags" "769" "origin" "576 -1600 856" } { "spawnflags" "2048" "classname" "point_combat" "origin" "56 -1280 936" "targetname" "t169" } { "origin" "-544 -1024 8" "spawnflags" "769" "angle" "180" "classname" "monster_berserk" } { "light" "100" "classname" "light" "origin" "296 -760 672" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "classname" "light" "origin" "240 -720 672" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "classname" "light" "origin" "240 -720 568" "_color" "0.000000 0.000000 1.000000" } { "light" "120" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "440 -520 536" } { "origin" "-360 -1192 528" "spawnflags" "5888" "classname" "weapon_proxlauncher" } { "origin" "-400 -1128 528" "classname" "ammo_prox" } { "origin" "-400 -1560 528" "targetname" "t350" "classname" "item_health_small" "spawnflags" "1" } { "origin" "-400 -1512 528" "targetname" "t350" "classname" "item_health_small" "spawnflags" "1" } { "origin" "-400 -1664 528" "targetname" "t350" "classname" "item_health_small" "spawnflags" "1" } { "origin" "-400 -1608 528" "targetname" "t350" "spawnflags" "1" "classname" "item_health_small" } { "origin" "1816 -832 744" "targetname" "t350" "spawnflags" "1" "classname" "ammo_prox" } { "origin" "1192 -632 520" "targetname" "t350" "spawnflags" "1" "classname" "item_health" } { "origin" "968 480 712" "targetname" "t350" "spawnflags" "1" "classname" "ammo_shells" } { "classname" "item_health" "origin" "1816 200 512" } { "classname" "light" "light" "100" "origin" "1968 764 740" } { "classname" "ammo_shells" "origin" "-952 -1832 976" } { "_color" "1.000000 1.000000 0.501961" "light" "200" "classname" "light" "origin" "-232 -800 68" } { "origin" "-224 -1768 56" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "_color" "1.000000 1.000000 0.501961" "light" "200" "classname" "light" "origin" "-920 -720 68" } { "model" "*17" "spawnflags" "2048" "target" "t110" "classname" "trigger_once" } { "model" "*18" "spawnflags" "2048" "classname" "func_wall" } { "origin" "1144 -120 592" "classname" "target_speaker" "noise" "world/mach1.wav" "team" "mover1" "targetname" "t81" "spawnflags" "2" } { "origin" "848 -1516 824" "team" "mover2" "noise" "world/mach1.wav" "classname" "target_speaker" "spawnflags" "2" "targetname" "t81" } { "light" "100" "classname" "light" "origin" "1976 136 560" } { "targetname" "t350" "classname" "target_help" "origin" "-736 -760 72" "spawnflags" "2048" "message" "Destroy all resistance!" } { "origin" "-416 -2440 728" "angle" "0" "spawnflags" "3" "targetname" "t350" "classname" "monster_berserk" } { "origin" "-280 -1824 856" "angle" "315" "spawnflags" "3" "targetname" "t350" "classname" "monster_soldier" } { "item" "ammo_grenades" "origin" "1064 -1496 584" "angle" "0" "spawnflags" "2" "targetname" "t350" "classname" "monster_gunner" } { "origin" "1744 -896 752" "item" "ammo_shells" "spawnflags" "3" "targetname" "t350" "angle" "0" "classname" "monster_soldier" } { "origin" "1256 -232 656" "angle" "270" "spawnflags" "771" "targetname" "t350" "classname" "monster_flyer" } { "origin" "1192 -224 624" "spawnflags" "3" "targetname" "t350" "classname" "monster_flyer" } { "origin" "1880 -248 528" "item" "ammo_bullets" "spawnflags" "3" "angle" "0" "targetname" "t350" "classname" "monster_infantry" } { "origin" "968 544 744" //stuck monster at "968 544 720" (it spawns after Tectonic Stabilizer objectives are completed) "angle" "0" "spawnflags" "3" "targetname" "t350" "classname" "monster_berserk" } { "origin" "-296 -872 200" "targetname" "t350" "classname" "monster_flyer" "spawnflags" "770" "angle" "180" } { "origin" "-296 -792 200" "angle" "180" "spawnflags" "3" "targetname" "t350" "classname" "monster_flyer" } { "origin" "-768 -1232 16" "targetname" "t350" "classname" "monster_soldier" "angle" "270" "spawnflags" "771" } { "origin" "-784 -1168 16" "item" "ammo_shells" "targetname" "t350" "classname" "monster_soldier" "angle" "270" "spawnflags" "3" } { "origin" "-624 -1024 16" "targetname" "t350" "classname" "monster_soldier" "angle" "180" "spawnflags" "3" } { "origin" "-728 -1264 16" "item" "ammo_shells" "spawnflags" "259" "targetname" "t350" "angle" "270" "classname" "monster_soldier" } { "origin" "-288 -704 200" "light" "175" "classname" "light" } { "origin" "2048 -24 936" "spawnflags" "1" "angle" "180" "classname" "monster_flyer" "targetname" "t300" } { "origin" "2056 -80 896" "angle" "225" "spawnflags" "769" "classname" "monster_flyer" "targetname" "t300" } { "message" "Use Cargo elevator\n to enter Warehouse." "spawnflags" "2049" "targetname" "t350" "origin" "-704 -744 72" "classname" "target_help" } { "origin" "2000 880 584" "targetname" "mineend" "classname" "info_player_coop" "angle" "270" } { "origin" "2000 952 584" "targetname" "mineend" "classname" "info_player_coop" "angle" "270" } { "origin" "1936 952 584" "targetname" "mineend" "classname" "info_player_coop" "angle" "270" } { "origin" "1944 888 584" "targetname" "mineend" "angle" "270" "classname" "info_player_coop" } { "spawnflags" "0" "classname" "info_player_coop" "origin" "-1904 -2448 24" "angle" "90" } { "spawnflags" "0" "classname" "info_player_coop" "origin" "-2056 -2432 24" "angle" "90" } { "spawnflags" "0" "classname" "info_player_coop" "origin" "-1952 -2448 24" "angle" "90" } { "spawnflags" "0" "angle" "90" "origin" "-1856 -2448 24" "classname" "info_player_coop" } { "spawnflags" "2048" "origin" "-672 -672 120" "map" "reu1_.cin+*rware1$unitstart" "targetname" "t351" "classname" "target_changelevel" } { "model" "*19" "spawnflags" "2048" "target" "t351" "classname" "trigger_once" } { "spawnflags" "2048" "origin" "-800 -672 8" "targetname" "t350" "target" "booger2" "classname" "trigger_relay" } { "origin" "-760 -668 56" "target" "t350" "spawnflags" "2052" "classname" "target_crosslevel_target" } { "spawnflags" "2048" "origin" "-848 -552 -8" "delay" "3" "targetname" "t348" "target" "t349" "classname" "trigger_relay" } { "model" "*20" "targetname" "booger2" "target" "t347" "spawnflags" "2052" "wait" "5" "classname" "trigger_multiple" } { "model" "*21" "spawnflags" "2080" "targetname" "t348" "classname" "func_plat" "lip" "268" "_minlight" ".2" } { "model" "*22" "spawnflags" "5888" "classname" "func_wall" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t346" "delay" "2.5" "message" "Security lockdown in effect." "origin" "-892 -676 8" } { "model" "*23" "spawnflags" "2056" "targetname" "booger1" "classname" "trigger_multiple" "message" "Warehouse access denied." "target" "t346" "wait" "10" } { "model" "*24" "spawnflags" "2056" "target" "t348" "targetname" "t347" "classname" "func_button" "angle" "90" } { "angle" "270" "classname" "monster_flyer" "origin" "-816 -736 256" "target" "t353" } { "classname" "monster_flyer" "angle" "90" "spawnflags" "768" "origin" "-856 -688 256" } { "origin" "288 -200 924" "classname" "light" "light" "150" } { "origin" "264 -224 924" "classname" "light" "light" "150" } { "classname" "item_health" "origin" "-528 -856 0" } { "classname" "monster_infantry" "spawnflags" "256" "origin" "-384 -680 8" "angle" "270" "targetname" "t353" } { "classname" "ammo_grenades" "origin" "-456 -760 64" } { "classname" "item_armor_shard" "origin" "-256 -936 0" } { "classname" "item_armor_shard" "origin" "-296 -936 0" } { "classname" "item_armor_shard" "origin" "-216 -936 0" } { "classname" "item_health_large" "origin" "-936 -1064 0" } { "classname" "item_armor_jacket" "origin" "-608 -768 64" } { "classname" "ammo_shells" "origin" "-928 -672 0" } { "angle" "0" "spawnflags" "2049" "classname" "point_combat" "targetname" "t345" "origin" "-912 -1024 -8" } { "angle" "270" "classname" "monster_soldier_light" "origin" "-744 -928 8" "target" "t345" "spawnflags" "1" } { "classname" "monster_soldier_light" "angle" "180" "spawnflags" "1025" "origin" "-560 -1024 8" } { "classname" "misc_deadsoldier" "spawnflags" "2049" "angle" "90" "origin" "-768 -800 -16" } { "classname" "weapon_supershotgun" "origin" "-808 -744 0" } { "classname" "monster_berserk" "angle" "180" "spawnflags" "769" "origin" "-240 -864 8" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t343" "origin" "-368 -896 8" } { "classname" "hint_path" "spawnflags" "2049" "target" "t343" "origin" "-748 -968 8" } { "classname" "hint_path" "spawnflags" "2049" "origin" "-764 -904 8" "targetname" "t335" } { "model" "*25" "mass" "100" "health" "1" "classname" "func_explosive" "dmg" "50" } { "model" "*26" "classname" "func_explosive" "health" "1" "mass" "100" "dmg" "50" } { "origin" "-608 -704 264" "classname" "light" "light" "175" } { "classname" "light" "light" "175" "origin" "-288 -832 200" } { "origin" "-864 -832 264" "classname" "light" "light" "175" } { "light" "175" "classname" "light" "origin" "-608 -832 264" } { "origin" "-864 -704 264" "classname" "light" "light" "175" } { "light" "125" "classname" "light" "origin" "-752 -832 128" } { "origin" "480 -72 648" "classname" "light" "light" "150" } { "origin" "416 -72 648" "classname" "light" "light" "150" } { "origin" "392 -96 648" "classname" "light" "light" "150" } { "origin" "392 -288 648" "classname" "light" "light" "150" } { "origin" "392 -224 648" "classname" "light" "light" "150" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-168 -2016 56" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-544 -1768 64" } { "origin" "-448 -2416 756" "classname" "light" "light" "180" "_color" "1.000000 1.000000 0.501961" } { "origin" "-608 -960 200" "classname" "light" "light" "175" } { "light" "175" "classname" "light" "origin" "-864 -960 200" } { "light" "125" "classname" "light" "origin" "-688 -512 344" } { "light" "125" "classname" "light" "origin" "-664 -640 88" } { "origin" "-472 -2016 600" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "origin" "-480 -704 200" "classname" "light" "light" "175" } { "origin" "-784 -512 344" "classname" "light" "light" "125" } { "origin" "-808 -640 88" "classname" "light" "light" "125" } { "origin" "-1256 -1728 1172" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "model" "*27" "targetname" "t349" "team" "vator1" "angle" "180" "classname" "func_door" "spawnflags" "2056" } { "model" "*28" "targetname" "t349" "team" "vator1" "angle" "0" "classname" "func_door" "spawnflags" "2056" } { "model" "*29" "target" "getplat" "message" "Lift activated." "wait" "5" "lip" "3" "angle" "90" "classname" "func_button" } { "origin" "-72 -1320 840" "classname" "item_health_large" "spawnflags" "1536" } { "angle" "270" "origin" "72 -1184 952" "spawnflags" "769" "classname" "monster_gunner" "target" "t169" } { "origin" "-152 -2080 544" "light" "75" "classname" "light" } { "model" "*30" "target" "t160" "message" "Lift activated." "wait" "-1" "angle" "0" "classname" "func_button" "sounds" "4" } { "classname" "monster_gunner" "spawnflags" "769" "angle" "315" "origin" "744 -1296 552" } { "classname" "item_armor_jacket" "origin" "-576 -1824 976" } { "spawnflags" "2050" "noise" "world/amb10.wav" "classname" "target_speaker" "team" "oremover" "origin" "-760 -1920 568" "attenuation" "1" "targetname" "sound" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t339" "target" "t340" "origin" "1176 720 528" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t340" "target" "t341" "origin" "1600 728 664" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t341" "target" "t342" "origin" "1600 480 712" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t342" "origin" "1288 488 704" } { "classname" "hint_path" "spawnflags" "2049" "target" "t339" "origin" "1848 448 528" } { "origin" "-368 -1392 8" "spawnflags" "2048" "classname" "hint_path" "targetname" "t333" "target" "t334" } { "origin" "-748 -1384 8" "spawnflags" "2048" "classname" "hint_path" "targetname" "t334" "target" "t335" } { "classname" "hint_path" "spawnflags" "2049" "origin" "-360 -1840 8" "target" "t333" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t331" "target" "t332" "origin" "-920 -1656 1024" } { "spawnflags" "1" "classname" "hint_path" "targetname" "t332" "origin" "-920 -1984 992" } { "classname" "hint_path" "spawnflags" "2048" "target" "t331" "origin" "-1168 -1656 1128" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t329" "target" "t330" "origin" "-920 -2304 1040" } { "spawnflags" "1" "classname" "hint_path" "targetname" "t330" "origin" "-912 -1984 992" } { "classname" "hint_path" "spawnflags" "2049" "target" "t329" "origin" "-1208 -2312 1128" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t327" "target" "t328" "origin" "64 -1920 848" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t328" "origin" "64 -1656 848" } { "classname" "hint_path" "spawnflags" "2049" "target" "t327" "origin" "-384 -1920 848" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t323" "target" "t324" "origin" "1400 -1160 392" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t324" "target" "t325" "origin" "1856 -1192 392" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t325" "target" "t326" "origin" "1880 -1464 392" } { "classname" "hint_path" "spawnflags" "2049" "target" "t323" "origin" "1392 -608 560" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t326" "origin" "1304 -1448 560" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t319" "target" "t320" "origin" "1648 -256 752" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t320" "target" "t321" "origin" "1816 -256 752" } { "classname" "hint_path" "targetname" "t321" "target" "t322" "origin" "1824 -512 752" } { "classname" "hint_path" "targetname" "t322" "spawnflags" "1" "origin" "1960 -504 752" } { "classname" "hint_path" "target" "t319" "spawnflags" "2048" "origin" "1648 -432 752" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t316" "target" "t317" "origin" "1632 -24 480" } { "classname" "hint_path" "targetname" "t317" "target" "t318" "origin" "1752 -24 784" } { "classname" "hint_path" "targetname" "t318" "spawnflags" "1" "origin" "2016 -40 784" } { "classname" "hint_path" "target" "t316" "spawnflags" "2048" "origin" "1416 -344 512" } { "classname" "hint_path" "spawnflags" "2049" "origin" "1792 -896 752" "target" "t314" } { "classname" "hint_path" "origin" "2136 -896 768" "targetname" "t314" "target" "t315" } { "classname" "hint_path" "spawnflags" "1" "origin" "2136 -368 776" "targetname" "t315" } { "classname" "item_health_large" "origin" "336 -328 856" } { "classname" "monster_soldier" "spawnflags" "1" "origin" "888 -264 904" "angle" "180" } { "classname" "item_health_small" "origin" "712 -424 528" } { "classname" "item_health_small" "origin" "672 -424 528" } { "classname" "item_health_small" "origin" "632 -424 528" } { "origin" "1592 -232 760" "classname" "item_health" } { "classname" "item_health" "origin" "1704 -880 744" "spawnflags" "1536" } { "classname" "item_health_large" "origin" "2064 -120 792" } { "classname" "misc_deadsoldier" "spawnflags" "2080" "angle" "180" "origin" "1272 648 760" } { "classname" "weapon_shotgun" "origin" "1240 592 704" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t313" "origin" "1264 640 720" } { "light" "100" "classname" "light" "origin" "1264 632 752" } { "model" "*31" "spawnflags" "2048" "classname" "func_explosive" "dmg" "50" "target" "t313" "health" "1" } { "origin" "2224 -288 760" "classname" "ammo_grenades" } { "spawnflags" "1536" "origin" "2200 -376 760" "classname" "weapon_grenadelauncher" } { "origin" "840 -1272 576" "light" "75" "classname" "light" } { "classname" "light" "origin" "-184 -1632 936" "_color" "0.000000 0.000000 1.000000" "light" "125" } { "origin" "-160 -1512 864" "classname" "weapon_proxlauncher" } { "_color" "1.000000 1.000000 0.501961" "light" "160" "classname" "light" "origin" "1408 -656 748" } { "_color" "1.000000 1.000000 0.501961" "light" "195" "classname" "light" "origin" "2204 -384 804" } { "_color" "1.000000 1.000000 0.501961" "light" "160" "classname" "light" "origin" "804 -480 780" } { "origin" "1984 -528 804" "classname" "light" "light" "195" "_color" "1.000000 1.000000 0.501961" } { "_color" "1.000000 1.000000 0.501961" "light" "150" "classname" "light" "origin" "1144 -232 684" } { "_color" "1.000000 1.000000 0.501961" "light" "180" "classname" "light" "origin" "1020 -288 572" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "1956 -48 572" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "684 -480 780" } { "origin" "928 -1648 712" "classname" "light" "light" "160" "_color" "1.000000 1.000000 0.501961" } { "origin" "284 -464 780" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "origin" "192 -1700 908" "classname" "light" "light" "125" "_color" "1.000000 1.000000 0.501961" } { "origin" "-64 -1700 908" "classname" "light" "light" "125" "_color" "1.000000 1.000000 0.501961" } { "origin" "-1256 -2240 1172" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "origin" "-928 -2328 1076" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "_color" "1.000000 1.000000 0.501961" "light" "200" "classname" "light" "origin" "-512 -680 68" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-768 -2456 692" } { "origin" "-928 -1640 1076" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "origin" "-792 -1856 72" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "origin" "-608 -1048 72" "classname" "light" "light" "200" "_color" "1.000000 1.000000 0.501961" } { "origin" "-480 -1768 584" "classname" "light" "light" "175" "_color" "1.000000 1.000000 0.501961" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-792 -2112 72" } { "classname" "func_group" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-168 -1888 584" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-416 -2200 584" } { "classname" "func_group" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-192 -2456 764" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "-792 -2144 596" } { "_color" "1.000000 1.000000 0.501961" "light" "175" "classname" "light" "origin" "384 124 780" } { "origin" "2004 1072 648" "light" "75" "classname" "light" } { "origin" "888 -1288 528" "angle" "135" "spawnflags" "2" "classname" "misc_deadsoldier" } { "classname" "light" "origin" "-176 -1480 944" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "spawnflags" "2048" "origin" "-400 -1840 848" "targetname" "t312" "target" "ammo_shells" "classname" "target_spawner" } { "spawnflags" "2048" "origin" "-400 -1840 864" "dmg" "25" "targetname" "t312" "classname" "target_explosion" } { "model" "*32" "spawnflags" "2048" "target" "t312" "classname" "func_explosive" "health" "10" } { "origin" "1224 -1360 840" "angle" "180" "classname" "monster_flyer" } { "origin" "1776 -832 752" "target" "t299" "targetname" "t300" "spawnflags" "1" "angle" "270" "classname" "monster_gunner" } { "spawnflags" "2048" "origin" "736 -288 528" "target" "ammo_grenades" "targetname" "t113" "classname" "target_spawner" } { "spawnflags" "2048" "origin" "416 -288 528" "targetname" "t115" "target" "ammo_bullets" "classname" "target_spawner" } { "origin" "800 -96 528" "targetname" "t114" "target" "ammo_shells" "classname" "target_spawner" } { "model" "*33" "target" "t311" "classname" "trigger_once" "spawnflags" "2048" } { "origin" "792 -120 656" "targetname" "t311" "angle" "180" "classname" "monster_flyer" } { "targetname" "t310" "origin" "328 -736 736" "angle" "0" "classname" "monster_gunner" "spawnflags" "1" "item" "ammo_grenades" } { "target" "t310" "origin" "304 -328 1008" "spawnflags" "1" "angle" "0" "classname" "monster_flyer" } { "origin" "312 -368 1008" "angle" "0" "spawnflags" "769" "classname" "monster_flyer" } { "origin" "1504 -608 888" "angle" "180" "classname" "monster_flyer" "spawnflags" "256" } { "origin" "1504 -560 864" "angle" "180" "spawnflags" "768" "classname" "monster_flyer" } { "origin" "1176 720 520" "spawnflags" "1" "angle" "0" "classname" "monster_berserk" } { "origin" "1760 272 520" "spawnflags" "769" "angle" "0" "classname" "monster_berserk" } { "origin" "1984 688 568" "spawnflags" "1" "angle" "270" "classname" "monster_gunner" } { "model" "*34" "spawnflags" "2048" "targetname" "mines1" "classname" "trigger_multiple" "message" "Mine doors are locked." "wait" "-1" } { "origin" "1952 -416 760" "classname" "ammo_shells" } { "classname" "light" "light" "100" "origin" "572 -1504 965" } { "origin" "880 -560 896" "classname" "ammo_shells" } { "origin" "288 -704 728" "classname" "item_health_small" } { "origin" "288 -744 728" "classname" "item_health_small" } { "origin" "680 -368 728" "classname" "ammo_grenades" } { "origin" "1768 320 512" "spawnflags" "768" "classname" "ammo_bullets" } { "origin" "1768 224 512" "classname" "ammo_bullets" } { "origin" "1704 -376 760" "classname" "ammo_tesla" } { "origin" "2168 -704 760" "classname" "item_armor_shard" } { "origin" "2168 -656 760" "classname" "item_armor_shard" } { "origin" "2168 -752 760" "classname" "item_armor_shard" } { "origin" "1936 -88 792" "classname" "ammo_prox" } { "origin" "1008 -272 520" "classname" "item_armor_shard" } { "origin" "1016 -232 508" "classname" "item_armor_shard" } { "origin" "1000 -312 520" "classname" "item_armor_shard" } { "spawnflags" "1536" "origin" "1620 -1128 376" "classname" "ammo_grenades" } { "classname" "item_health_small" "origin" "1584 -1408 496" } { "origin" "1528 -1408 524" "classname" "item_health_small" } { "origin" "1632 -1416 472" "classname" "item_health_small" } { "spawnflags" "1536" "origin" "1280 -1296 544" "classname" "ammo_grenades" } { "origin" "824 -1664 544" "classname" "ammo_bullets" } { "origin" "1216 -1120 880" "classname" "ammo_shells" } { "origin" "24 -1160 944" "classname" "ammo_shells" } { "model" "*35" "spawnflags" "2048" "target" "t265" "classname" "trigger_once" } { "origin" "1872 -528 680" "spawnflags" "1025" "classname" "monster_flyer" "angle" "45" } { "origin" "1768 -496 680" "spawnflags" "769" "classname" "monster_flyer" "angle" "90" } { "origin" "1856 -464 680" "spawnflags" "1" "classname" "monster_flyer" "angle" "90" } { "origin" "2192 -256 680" "spawnflags" "1" "angle" "180" "classname" "monster_flyer" } { "origin" "608 120 728" "angle" "90" "classname" "monster_infantry" } { "origin" "384 -720 504" "spawnflags" "2052" "classname" "misc_deadsoldier" } { "spawnflags" "2048" "origin" "440 -704 520" "classname" "item_bandolier" } { "spawnflags" "2048" "origin" "576 -632 624" "targetname" "t308" "classname" "target_secret" } { "model" "*36" "spawnflags" "2048" "target" "t308" "message" "You found a secret!" "classname" "trigger_once" } { "origin" "2096 -384 416" "classname" "item_adrenaline" "spawnflags" "2048" } { "model" "*37" "target" "t307" "angle" "270" "classname" "func_button" "message" "Lift activated." } { "model" "*38" "target" "t307" "message" "Lift activated." "classname" "func_button" "angle" "270" } { "light" "120" "classname" "light" "origin" "-888 -1856 1015" } { "model" "*39" "spawnflags" "2048" "target" "t306" "classname" "trigger_once" } { "model" "*40" "spawnflags" "2048" "target" "t305" "classname" "trigger_once" } { "origin" "1856 -1168 384" "targetname" "t306" "angle" "270" "classname" "monster_berserk" "spawnflags" "1" } { "targetname" "t305" "origin" "1880 -1432 384" "angle" "180" "classname" "monster_infantry" "spawnflags" "1" "item" "ammo_bullets" } { "origin" "736 -1296 552" "spawnflags" "1025" "angle" "315" "classname" "monster_berserk" } { "model" "*41" "spawnflags" "2048" "target" "t301" "classname" "trigger_once" } { "target" "t302" "targetname" "t301" "origin" "1368 -1160 888" "spawnflags" "1" "angle" "180" "classname" "monster_berserk" } { "origin" "-1256 -1632 1104" "classname" "item_health_large" } { "spawnflags" "2048" "origin" "-544 -2008 536" "target" "t298" "targetname" "oretrain" "classname" "trigger_relay" "delay" "20" } { "spawnflags" "2048" "delay" "16.3" "origin" "-576 -2008 536" "target" "t298" "targetname" "oretrain" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "-576 -1976 536" "targetname" "oretrain" "delay" "10" "target" "t298" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "-544 -1976 536" "delay" "13.5" "targetname" "oretrain" "target" "t298" "classname" "trigger_relay" } { "spawnflags" "2" "targetname" "t298" "origin" "-576 -2200 536" "team" "mony1" "volume" "1" "attenuation" "1" "noise" "world/mach1.wav" "classname" "target_speaker" } { "spawnflags" "2048" "delay" "26" "origin" "-632 -1760 704" "targetname" "oretrain" "target" "sound" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "-600 -1760 704" "target" "sound" "targetname" "oretrain" "classname" "trigger_relay" } { "attenuation" "1" "origin" "-768 -1912 568" "targetname" "sound" "team" "oremover" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "classname" "func_group" } { "classname" "func_group" } { "classname" "func_group" } { "classname" "func_group" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "origin" "1264 -1700 868" "classname" "light" } { "model" "*42" "origin" "1056 -1480 724" "_minlight" ".1" "speed" "60" "spawnflags" "5" "classname" "func_rotating" "dmg" "80" } { "model" "*43" "origin" "1056 -1524 724" "_minlight" ".05" "classname" "func_rotating" "spawnflags" "7" "speed" "60" "dmg" "80" } { "origin" "528 -1304 880" "classname" "item_health" } { "origin" "544 -1248 880" "classname" "item_health" } { "origin" "456 -1400 880" "spawnflags" "0" "targetname" "t297" "angle" "135" "classname" "monster_flyer" } { "origin" "544 -1384 880" "spawnflags" "1536" "targetname" "t297" "angle" "135" "classname" "monster_flyer" } { "targetname" "t302" "origin" "472 -1128 880" "spawnflags" "5" "angle" "270" "classname" "monster_soldier" } { "spawnflags" "2048" "origin" "1168 -1616 832" "targetname" "t296" "message" "You found a secret area!" "classname" "target_secret" } { "origin" "1136 -1584 800" "classname" "item_armor_body" } { "origin" "1088 -256 512" "classname" "dm_tag_token" } { "origin" "888 -304 896" "classname" "ammo_bullets" } { "origin" "-1144 -2248 160" "classname" "ammo_grenades" } { "origin" "-760 -2040 974" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-696 -2040 974" } { "origin" "-792 -2144 974" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-792 -2080 974" } { "origin" "-792 -1888 974" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-792 -1824 974" } { "origin" "-696 -1928 974" "classname" "light" "light" "125" } { "origin" "-512 -1752 528" "classname" "ammo_shells" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-560 -1888 1080" } { "origin" "-192 -2160 912" "spawnflags" "1" "targetname" "t282" "angle" "270" "classname" "monster_flyer" } { "origin" "-760 -1952 704" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "origin" "-1104 -2192 152" "spawnflags" "2056" "classname" "misc_deadsoldier" } { "origin" "-2008 -1912 16" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "classname" "light" "light" "125" "origin" "456 56 721" } { "origin" "456 -8 721" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "568 -8 721" } { "classname" "func_group" } { "model" "*44" "origin" "272 -544 712" "wait" "-1" "targetname" "t90" "spawnflags" "2178" "sounds" "2" "message" "This door cannot be opened from here." "distance" "90" "_minlight" ".2" "classname" "func_door_rotating" } { "origin" "912 -1208 993" "light" "100" "classname" "light" } { "origin" "752 -1264 965" "light" "100" "classname" "light" } { "origin" "912 -1264 965" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "1072 -1264 965" } { "origin" "1072 -1248 845" "light" "100" "classname" "light" } { "light" "100" "classname" "light" "origin" "1336 432 752" } { "origin" "1296 744 856" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "1528 600 552" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "style" "32" "origin" "1264 648 760" "classname" "light" "light" "100" "_color" "1.000000 0.000000 0.000000" "targetname" "t313" } { "origin" "1256 360 752" "classname" "light" "light" "100" } { "origin" "2000 352 400" "classname" "light" "light" "125" } { "light" "100" "classname" "light" "origin" "1408 592 752" } { "light" "100" "classname" "light" "origin" "1168 536 752" } { "classname" "light" "light" "100" "origin" "1424 368 752" } { "origin" "1528 648 560" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "1528 656 600" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "classname" "light" "light" "100" "origin" "1936 816 656" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1336 752 856" } { "classname" "light" "origin" "1736 432 768" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "classname" "light" "origin" "1688 448 816" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "classname" "light" "origin" "1688 568 816" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "classname" "light" "origin" "1560 208 704" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "classname" "light" "origin" "1552 208 624" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "origin" "720 -1576 701" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "912 -1248 845" } { "classname" "light" "origin" "1688 -1104 416" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "classname" "light" "origin" "1528 -1136 400" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "classname" "light" "light" "100" "origin" "1072 -1208 993" } { "classname" "light" "light" "100" "origin" "752 -1208 993" } { "classname" "light" "light" "100" "origin" "1232 -1208 993" } { "origin" "928 -1304 653" "light" "100" "classname" "light" } { "origin" "928 -1728 853" "light" "75" "classname" "light" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1504 -1376 568" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1704 -1224 448" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1864 -1136 424" "light" "100" } { "light" "175" "_color" "1.000000 0.000000 0.000000" "origin" "592 -1104 928" "classname" "light" } { "light" "175" "_color" "1.000000 0.000000 0.000000" "origin" "1392 -1104 928" "classname" "light" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1528 -1136 904" "classname" "light" } { "classname" "light" "light" "75" "origin" "576 -1600 701" } { "origin" "664 -1600 637" "light" "100" "classname" "light" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1760 -1112 424" "classname" "light" } { "classname" "light" "origin" "1560 -1136 432" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "784 -1256 680" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "776 -1256 624" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1648 -1400 480" "light" "100" } { "origin" "486 -1492 853" "light" "75" "classname" "light" } { "classname" "light" "light" "100" "origin" "752 -1248 845" } { "classname" "light" "origin" "1392 -544 544" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1920 -1184 416" "light" "100" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1752 -1400 496" "light" "100" } { "classname" "light" "origin" "1088 -1448 552" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "classname" "light" "origin" "1032 -1416 544" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "classname" "light" "origin" "1344 -1624 800" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "light" "100" "origin" "1744 -1232 456" "classname" "light" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "origin" "688 -1272 576" "classname" "light" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "origin" "1584 -1384 504" "classname" "light" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "origin" "1568 -1384 568" "classname" "light" "_color" "0.000000 0.000000 1.000000" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1000 -1520 544" "classname" "light" } { "origin" "1656 -80 837" "light" "150" "classname" "light" } { "classname" "light" "light" "150" "origin" "1656 32 837" } { "model" "*45" "targetname" "t307" "lip" "8" "_minlight" ".3" "speed" "250" "classname" "func_plat2" } { "target" "t292" "targetname" "t291" "classname" "path_corner" "origin" "896 -1796 824" } { "target" "t291" "targetname" "t290" "classname" "path_corner" "origin" "896 -1608 824" } { "target" "t290" "targetname" "t289" "classname" "path_corner" "origin" "896 -1256 720" } { "target" "t289" "targetname" "t288" "classname" "path_corner" "origin" "896 -1032 720" } { "target" "t288" "targetname" "t74" "classname" "path_corner" "origin" "1112 -1032 720" } { "target" "t80" "targetname" "t292" "origin" "896 -1796 1156" "classname" "path_corner" } { "target" "t309" "message" "Mine doors opened." "delay" "2" "origin" "-1200 -1824 1128" "killtarget" "mines1" "targetname" "t259" "classname" "trigger_relay" "spawnflags" "2048" } { "targetname" "t259" "classname" "target_speaker" "noise" "world/uplink2.wav" "spawnflags" "4" "origin" "-1176 -1984 1240" } { "origin" "-760 -1832 1168" "spawnflags" "1792" "classname" "ammo_bullets" } { "origin" "-1264 -1768 1104" "classname" "ammo_cells" "spawnflags" "5888" } { "origin" "-1264 -1808 1104" "classname" "ammo_cells" "spawnflags" "5888" } { "origin" "-1040 -1984 1104" "spawnflags" "5888" "classname" "weapon_bfg" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "-784 -2192 1176" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-1240 -2128 1303" } { "light" "120" "classname" "light" "origin" "-888 -2112 1011" } { "origin" "-704 -1856 973" "classname" "light" "light" "175" } { "origin" "-968 -1984 999" "classname" "light" "light" "150" } { "origin" "-1160 -2128 1303" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-744 -2208 1172" } { "origin" "-1240 -1840 1303" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "origin" "-1184 -2080 1151" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "origin" "-824 -2208 1174" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-824 -1824 1175" } { "origin" "-744 -1824 1172" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "style" "33" "targetname" "t295" "classname" "light" "light" "150" "origin" "-1224 -1952 1652" "spawnflags" "1" } { "style" "33" "targetname" "t295" "light" "150" "classname" "light" "origin" "-1224 -2016 1652" "spawnflags" "1" } { "style" "34" "targetname" "t259" "classname" "light" "light" "150" "origin" "-1224 -2016 1400" "spawnflags" "1" } { "style" "34" "targetname" "t259" "light" "150" "classname" "light" "origin" "-1224 -1952 1400" "spawnflags" "1" } { "style" "35" "targetname" "t294" "classname" "light" "light" "150" "origin" "-1224 -2016 1528" "spawnflags" "1" } { "style" "35" "targetname" "t294" "light" "150" "classname" "light" "origin" "-1224 -1952 1528" "spawnflags" "1" } { "target" "t295" "targetname" "t294" "classname" "trigger_relay" "delay" "2" "origin" "-1208 -1992 1608" } { "target" "t294" "targetname" "t259" "classname" "trigger_relay" "delay" "2" "origin" "-1208 -1992 1464" } { "origin" "-992 -1984 1193" "classname" "light" "light" "175" } { "light" "125" "classname" "light" "origin" "-760 -1928 974" } { "classname" "light" "_color" "0.117647 0.603922 1.000000" "style" "2" "light" "250" "origin" "-1112 -1984 991" } { "light" "175" "classname" "light" "origin" "-856 -2264 1032" } { "origin" "-784 -1856 1176" "angle" "180" "spawnflags" "1028" "classname" "monster_soldier" } { "origin" "-1016 -1848 1112" "angle" "0" "spawnflags" "4" "classname" "monster_soldier" } { "origin" "-1016 -2112 1112" "angle" "0" "classname" "monster_soldier" "spawnflags" "4" } { "origin" "-784 -2112 1176" "classname" "monster_soldier" "spawnflags" "1028" "angle" "180" } { "targetname" "t259" "spawnflags" "1" "origin" "-1232 -1984 1552" "classname" "monster_flyer" } { "origin" "-1168 -1984 1216" "classname" "point_combat" } { "model" "*46" "classname" "trigger_once" } { "classname" "target_speaker" "noise" "world/comp_hum2.wav" "spawnflags" "1" "origin" "-1200 -1984 1208" } { "targetname" "t309" "spawnflags" "2049" "classname" "target_help" "message" "Find your way to the\nThaelite Mines." "origin" "-1088 -2104 1200" } { "classname" "ammo_grenades" "origin" "-760 -1952 1168" } { "classname" "item_health_small" "origin" "-760 -2336 1008" } { "origin" "-760 -2296 1008" "classname" "item_health_small" } { "targetname" "t309" "origin" "-1056 -1984 1176" "classname" "target_goal" "spawnflags" "2048" } { "origin" "-944 -1984 1000" "spawnflags" "1" "noise" "world/force1.wav" "classname" "target_speaker" } { "light" "175" "classname" "light" "origin" "-856 -1704 1025" } { "targetname" "t259" "attenuation" "3" "classname" "target_speaker" "noise" "world/lite_on1.wav" "volume" "1" "origin" "-1160 -1928 1192" } { "classname" "light" "spawnflags" "1" "light" "200" "origin" "-1224 -2080 1256" } { "light" "200" "spawnflags" "1" "classname" "light" "origin" "-1224 -1888 1256" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-1160 -1840 1303" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-1184 -1888 1151" } { "origin" "-760 -2016 1168" "classname" "ammo_shells" } { "origin" "-808 -1984 1176" "spawnflags" "772" "angle" "180" "classname" "monster_infantry" } { "targetname" "t259" "origin" "-1176 -2000 1240" "spawnflags" "4" "noise" "world/uplink2.wav" "classname" "target_speaker" } { "targetname" "t259" "classname" "target_speaker" "noise" "world/uplink2.wav" "spawnflags" "4" "origin" "-1176 -1968 1240" } { "origin" "-1232 -1984 1256" "light" "200" "spawnflags" "1" "classname" "light" } { "model" "*47" "spawnflags" "2048" "target" "t259" "wait" "-1" "classname" "func_button" "angle" "180" "message" "Communication uplink established." "sounds" "4" } { "origin" "-1176 -1888 1136" "classname" "light" "spawnflags" "0" "light" "125" } { "origin" "2136 -800 824" "classname" "light" "light" "100" } { "origin" "2136 -608 824" "light" "100" "classname" "light" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "origin" "1272 -1720 820" "classname" "light" } { "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "1752 -1400 408" "light" "50" } { "classname" "light" "origin" "1332 -1712 820" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "origin" "1344 -1696 868" "classname" "light" } { "style" "36" "targetname" "t287" "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1240 -1632 836" "classname" "light" } { "style" "36" "targetname" "t287" "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1288 -1592 836" "classname" "light" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1336 -472 528" "classname" "light" } { "origin" "-752 -1144 72" "light" "100" "classname" "light" } { "origin" "-752 -1312 72" "classname" "light" "light" "100" } { "model" "*48" "targetname" "getplat" "classname" "func_plat2" "speed" "250" "_minlight" ".3" "lip" "12" } { "classname" "monster_infantry" "angle" "180" "spawnflags" "1" "origin" "704 -112 736" "targetname" "t286" } { "classname" "ammo_prox" "origin" "-408 -2352 720" } { "model" "*49" "classname" "trigger_once" "target" "t282" } { "classname" "ammo_bullets" "origin" "-760 -1792 720" } { "origin" "2224 -328 744" "angle" "180" "spawnflags" "1540" "classname" "misc_deadsoldier" } { "origin" "840 -1272 544" "classname" "weapon_supershotgun" } { "origin" "-232 -2464 720" "classname" "ammo_grenades" } { "origin" "-152 -1784 528" "classname" "item_health" } { "origin" "-152 -1824 528" "classname" "item_health" } { "origin" "24 -1944 848" "classname" "ammo_bullets" } { "origin" "-784 -1888 720" "classname" "weapon_machinegun" } { "origin" "-152 -1552 848" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "48 -1616 848" "classname" "ammo_grenades" } { "origin" "-600 -1936 848" "classname" "item_armor_shard" } { "origin" "-600 -1888 848" "classname" "item_armor_shard" } { "origin" "-600 -1840 848" "classname" "item_armor_shard" } { "origin" "-600 -1976 848" "classname" "item_armor_shard" } { "light" "140" "classname" "light" "origin" "-544 -2160 840" } { "light" "140" "classname" "light" "origin" "-608 -2160 840" } { "light" "140" "classname" "light" "origin" "-632 -2144 840" } { "origin" "-408 -2360 840" "classname" "light" "light" "140" } { "spawnflags" "5888" "origin" "-152 -2464 720" "classname" "ammo_flechettes" } { "origin" "1848 -100 838" "light" "125" "classname" "light" } { "light" "125" "classname" "light" "origin" "1848 52 838" } { "origin" "1504 -40 488" "classname" "item_health" } { "classname" "ammo_tesla" "origin" "2032 128 512" } { "light" "150" "classname" "light" "origin" "864 -160 924" } { "classname" "light" "light" "150" "origin" "1632 -288 853" } { "origin" "1632 -480 853" "light" "100" "classname" "light" } { "origin" "1824 -288 853" "light" "150" "classname" "light" } { "classname" "light" "light" "150" "origin" "1656 -100 565" } { "origin" "1656 52 565" "light" "150" "classname" "light" } { "classname" "light" "light" "150" "origin" "2048 -224 853" } { "origin" "1824 -480 853" "light" "150" "classname" "light" } { "origin" "568 56 721" "light" "125" "classname" "light" } { "origin" "1544 -352 853" "light" "150" "classname" "light" } { "classname" "light" "light" "125" "origin" "1088 -576 613" } { "classname" "light" "light" "150" "origin" "2144 -288 709" } { "classname" "light" "light" "150" "origin" "1824 -288 709" } { "origin" "1632 -448 605" "light" "125" "classname" "light" } { "origin" "1824 -480 709" "light" "150" "classname" "light" } { "classname" "light" "light" "125" "origin" "1632 -192 605" } { "classname" "light" "light" "150" "origin" "1544 -224 853" } { "spawnflags" "5888" "origin" "1284 -604 540" "classname" "ammo_rockets" } { "classname" "light" "light" "150" "origin" "1581 -147 853" } { "origin" "1544 -480 853" "light" "150" "classname" "light" } { "light" "125" "classname" "light" "origin" "1040 -480 921" } { "light" "125" "classname" "light" "origin" "1040 -544 921" } { "light" "125" "classname" "light" "origin" "1056 -680 920" } { "light" "125" "classname" "light" "origin" "1184 -680 920" } { "light" "125" "classname" "light" "origin" "1248 -680 920" } { "light" "125" "classname" "light" "origin" "1440 -680 920" } { "light" "125" "classname" "light" "origin" "1376 -680 920" } { "classname" "light" "light" "125" "origin" "1120 -680 920" } { "classname" "light" "light" "125" "origin" "992 -680 920" } { "light" "150" "classname" "light" "origin" "1304 -328 574" } { "model" "*50" "classname" "trigger_once" "target" "t280" } { "classname" "ammo_tesla" "origin" "928 -352 528" } { "classname" "ammo_prox" "origin" "-152 -1600 864" } { "classname" "target_secret" "message" "You found a secret!" "targetname" "t279" "origin" "-148 -1936 740" } { "model" "*51" "spawnflags" "2048" "classname" "trigger_once" "target" "t279" } { "origin" "-368 -1632 72" "classname" "light" "light" "100" } { "classname" "ammo_tesla" "origin" "-792 -2104 0" } { "spawnflags" "2048" "classname" "trigger_relay" "targetname" "t277" "target" "t23" "origin" "-1704 -2248 0" } { "spawnflags" "2048" "classname" "trigger_relay" "delay" "16" "target" "t23" "targetname" "t277" "origin" "-1664 -2248 0" } { "attenuation" "2" "spawnflags" "2048" "noise" "world/steam2.wav" "origin" "-1648 -2408 0" "classname" "target_speaker" "targetname" "t23" } { "attenuation" "2" "spawnflags" "2048" "targetname" "t23" "classname" "target_speaker" "origin" "-1536 -2424 0" "noise" "world/steam2.wav" } { "classname" "item_health" "origin" "-1920 -2232 24" } { "classname" "item_health_small" "origin" "-1040 -2224 160" } { "classname" "item_health_small" "origin" "-1040 -2176 160" } { "classname" "item_health_small" "origin" "-1040 -2272 160" } { "classname" "ammo_shells" "origin" "-1968 -1872 36" } { "classname" "light" "origin" "856 -448 584" "light" "100" } { "classname" "light" "origin" "584 -168 584" "light" "100" } { "light" "100" "origin" "448 -712 792" "classname" "light" } { "light" "125" "origin" "328 -728 792" "classname" "light" } { "light" "75" "origin" "336 -568 792" "classname" "light" } { "light" "75" "origin" "312 -280 792" "classname" "light" } { "light" "75" "origin" "544 -496 792" "classname" "light" } { "light" "75" "origin" "560 -296 784" "classname" "light" } { "classname" "light" "origin" "408 -312 784" "light" "75" } { "light" "75" "origin" "392 -512 792" "classname" "light" } { "light" "75" "origin" "560 -184 768" "classname" "light" } { "light" "100" "origin" "512 -136 616" "classname" "light" } { "light" "100" "origin" "664 -344 584" "classname" "light" } { "light" "100" "origin" "784 -352 584" "classname" "light" } { "light" "150" "origin" "1176 -672 520" "classname" "light" } { "classname" "light" "origin" "488 -592 792" "light" "75" } { "light" "75" "classname" "light" "origin" "836 -268 766" } { "model" "*52" "sounds" "4" "spawnflags" "2080" "speed" "25" "wait" "-1" "team" "door" "angle" "270" "classname" "func_door" "targetname" "t259" } { "model" "*53" "sounds" "4" "spawnflags" "2080" "speed" "25" "team" "door" "angle" "90" "classname" "func_door" "targetname" "t259" } { "light" "75" "classname" "light" "origin" "640 0 766" } { "origin" "924 -476 766" "classname" "light" "light" "75" } { "origin" "1456 -104 542" "classname" "light" "light" "150" } { "origin" "840 -608 731" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "120" } { "light" "120" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "888 -616 731" } { "light" "120" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "748 -88 731" } { "light" "75" "classname" "light" "origin" "640 -4 646" } { "light" "150" "classname" "light" "origin" "392 -160 648" } { "light" "150" "classname" "light" "origin" "544 -72 648" } { "_color" "1.000000 0.000000 0.000000" "light" "120" "classname" "light" "origin" "600 -32 520" } { "origin" "600 32 520" "classname" "light" "light" "120" "_color" "1.000000 0.000000 0.000000" } { "origin" "552 -776 728" "classname" "light" "light" "120" "_color" "1.000000 0.000000 0.000000" } { "_color" "1.000000 0.000000 0.000000" "light" "120" "classname" "light" "origin" "600 -776 728" } { "light" "150" "classname" "light" "origin" "800 -72 648" } { "light" "150" "classname" "light" "origin" "864 -72 648" } { "light" "150" "classname" "light" "origin" "864 -96 648" } { "light" "150" "classname" "light" "origin" "864 -160 648" } { "light" "150" "classname" "light" "origin" "896 -232 648" } { "light" "150" "classname" "light" "origin" "912 -288 648" } { "light" "150" "classname" "light" "origin" "952 -352 648" } { "light" "150" "classname" "light" "origin" "952 -416 648" } { "light" "150" "classname" "light" "origin" "952 -480 648" } { "light" "150" "classname" "light" "origin" "952 -544 648" } { "light" "150" "classname" "light" "origin" "952 -608 648" } { "light" "150" "classname" "light" "origin" "928 -632 648" } { "light" "150" "classname" "light" "origin" "864 -632 648" } { "light" "150" "classname" "light" "origin" "800 -632 648" } { "light" "150" "classname" "light" "origin" "792 -608 648" } { "light" "150" "classname" "light" "origin" "792 -544 648" } { "light" "150" "classname" "light" "origin" "680 -440 648" } { "light" "150" "classname" "light" "origin" "744 -440 648" } { "light" "150" "classname" "light" "origin" "544 -440 648" } { "light" "150" "classname" "light" "origin" "608 -440 648" } { "light" "150" "classname" "light" "origin" "416 -440 648" } { "light" "150" "classname" "light" "origin" "480 -440 648" } { "light" "150" "classname" "light" "origin" "392 -416 648" } { "light" "150" "classname" "light" "origin" "392 -352 648" } { "light" "150" "classname" "light" "origin" "264 -288 924" } { "light" "150" "classname" "light" "origin" "264 -352 924" } { "light" "150" "classname" "light" "origin" "264 -416 924" } { "light" "150" "classname" "light" "origin" "264 -480 924" } { "_color" "1.000000 0.000000 0.000000" "light" "120" "classname" "light" "origin" "688 32 520" } { "light" "150" "classname" "light" "origin" "544 -784 924" } { "origin" "736 -72 648" "classname" "light" "light" "150" } { "origin" "264 -608 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "264 -672 924" } { "light" "150" "classname" "light" "origin" "264 -736 924" } { "origin" "792 -480 648" "classname" "light" "light" "150" } { "origin" "264 -544 924" "classname" "light" "light" "150" } { "origin" "352 -784 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "416 -784 924" } { "origin" "688 -32 520" "classname" "light" "light" "120" "_color" "1.000000 0.000000 0.000000" } { "light" "150" "classname" "light" "origin" "608 -784 924" } { "light" "150" "classname" "light" "origin" "672 -784 924" } { "origin" "736 -784 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "800 -784 924" } { "light" "150" "classname" "light" "origin" "864 -784 924" } { "origin" "912 -736 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "912 -672 924" } { "light" "150" "classname" "light" "origin" "912 -608 924" } { "light" "150" "classname" "light" "origin" "912 -480 924" } { "origin" "912 -544 924" "classname" "light" "light" "150" } { "origin" "480 -784 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "912 -288 924" } { "origin" "912 -352 924" "classname" "light" "light" "150" } { "origin" "912 -416 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "864 -96 924" } { "origin" "680 -232 796" "classname" "light" "light" "150" } { "origin" "896 -232 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "416 -72 924" } { "origin" "480 -72 924" "classname" "light" "light" "150" } { "origin" "544 -72 924" "classname" "light" "light" "150" } { "origin" "840 -72 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "696 -32 924" } { "origin" "696 32 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "672 56 924" } { "light" "150" "classname" "light" "origin" "608 56 924" } { "light" "150" "classname" "light" "origin" "592 32 924" } { "light" "150" "classname" "light" "origin" "592 -32 924" } { "origin" "296 -776 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "352 -200 924" } { "origin" "392 -96 924" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "392 -160 924" } { "origin" "-352 -1800 840" "classname" "light" "light" "140" } { "light" "140" "classname" "light" "origin" "-288 -1800 840" } { "light" "150" "origin" "1176 -480 520" "classname" "light" } { "model" "*54" "target" "t269" "health" "10" "classname" "func_explosive" "dmg" "100" } { "style" "37" "targetname" "t269" "origin" "-1040 -2088 216" "light" "175" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "origin" "248 -1240 928" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "48 -1504 1135" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "origin" "120 -1144 1120" "classname" "light" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "origin" "168 -1112 1048" "classname" "light" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "origin" "136 -1136 1032" "classname" "light" } { "classname" "light" "origin" "280 -1320 1096" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "75" "origin" "-152 -1632 888" "classname" "light" } { "spawnflags" "2048" "origin" "20 -1580 1012" "targetname" "piercrys" "classname" "info_notnull" } { "target" "t297" "angle" "270" "spawnflags" "1" "origin" "488 -1280 872" "targetname" "t266" "classname" "monster_infantry" } { "spawnflags" "2048" "target" "t266" "targetname" "t265" "origin" "128 -1352 920" "killtarget" "piercrys" "classname" "target_anger" } { "targetname" "pier" "classname" "target_explosion" "origin" "8 -1648 824" "dmg" "75" } { "spawnflags" "2048" "targetname" "pier" "delay" ".3" "dmg" "75" "origin" "72 -1592 864" "classname" "target_explosion" } { "speed" "100" "wait" "-1" "targetname" "t263" "classname" "path_corner" "origin" "-8 -1664 784" } { "model" "*55" "origin" "64 -1528 824" "spawnflags" "66" "wait" "-1" "targetname" "pier" "distance" "-15" "classname" "func_door_rotating" } { "model" "*56" "origin" "60 -1696 824" "wait" "-1" "targetname" "pier" "distance" "-15" "spawnflags" "68" "classname" "func_door_rotating" } { "pathtarget" "pier" "speed" "400" "target" "t263" "origin" "-8 -1664 824" "targetname" "t262" "classname" "path_corner" } { "origin" "-8 -1664 1064" "target" "t262" "targetname" "t261" "classname" "path_corner" } { "model" "*57" "spawnflags" "2048" "_minlight" ".3" "dmg" "500" "targetname" "t264" "target" "t261" "classname" "func_train" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "32 -1616 1040" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "128 -1536 1080" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "origin" "152 -1616 1127" } { "model" "*58" "origin" "-160 -1536 1128" "wait" "-1" "targetname" "t264" "accel" "100" "distance" "20" "speed" "300" "spawnflags" "2180" "classname" "func_door_rotating" } { "model" "*59" "mass" "400" "targetname" "t264" "classname" "func_explosive" } { "origin" "80 -1248 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "208 -1248 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "256 -1536 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "-24 -1648 1040" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "0 -1536 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "-128 -1536 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-2032 -1688 24" "light" "125" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-40 -1720 991" } { "model" "*60" "killtarget" "piercrys" "spawnflags" "2048" "health" "10" "target" "t264" "dmg" "100" "classname" "func_explosive" } { "origin" "-72 -1560 984" "spawnflags" "1" "noise" "world/drip_amb.wav" "classname" "target_speaker" } { "origin" "-32 -1320 984" "spawnflags" "1" "noise" "world/drip_amb.wav" "classname" "target_speaker" } { "origin" "1392 592 776" "spawnflags" "1" "noise" "world/drip_amb.wav" "classname" "target_speaker" } { "origin" "-512 -2176 840" "classname" "light" "light" "75" } { "light" "140" "classname" "light" "origin" "-632 -2080 840" } { "classname" "point_combat" "origin" "-896 -1984 992" "targetname" "t260" "spawnflags" "1" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-720 -1952 728" } { "origin" "-720 -1824 728" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "-720 -2080 728" "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "origin" "-808 -2016 736" "light" "75" "classname" "light" } { "model" "*61" "spawnflags" "2048" "sounds" "4" "classname" "func_button" "angle" "180" "wait" "-1" "message" "You activated the Ore Mover." "target" "oretrain" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" "origin" "-800 -1976 648" } { "origin" "-800 -1848 648" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-48 -1248 1080" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" "origin" "-560 -2280 1080" } { "origin" "-560 -2080 1080" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "120" "classname" "light" "origin" "-496 -2256 968" } { "origin" "-352 -2360 840" "classname" "light" "light" "140" } { "origin" "-632 -2016 840" "classname" "light" "light" "140" } { "origin" "-632 -1952 840" "classname" "light" "light" "140" } { "light" "140" "classname" "light" "origin" "-632 -1888 840" } { "origin" "-632 -1824 840" "classname" "light" "light" "140" } { "origin" "-400 -2336 1024" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-400 -1952 1024" } { "light" "150" "classname" "light" "origin" "-400 -2016 1024" } { "origin" "-400 -1888 1024" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-400 -1824 1024" } { "light" "150" "classname" "light" "origin" "-400 -2080 1024" } { "light" "140" "classname" "light" "origin" "-608 -1800 840" } { "light" "140" "classname" "light" "origin" "-544 -1800 840" } { "light" "140" "classname" "light" "origin" "-416 -1800 840" } { "light" "150" "classname" "light" "origin" "912 -784 924" } { "origin" "744 -72 924" "classname" "light" "light" "150" } { "light" "140" "classname" "light" "origin" "-224 -1800 840" } { "light" "140" "classname" "light" "origin" "-160 -1800 840" } { "origin" "-400 -2144 1024" "classname" "light" "light" "150" } { "origin" "-400 -2208 1024" "classname" "light" "light" "150" } { "origin" "-136 -1824 840" "classname" "light" "light" "140" } { "origin" "-136 -2080 840" "classname" "light" "light" "140" } { "origin" "-136 -2144 840" "classname" "light" "light" "140" } { "origin" "-136 -2208 840" "classname" "light" "light" "140" } { "origin" "-136 -2272 840" "classname" "light" "light" "140" } { "origin" "-136 -2336 840" "classname" "light" "light" "140" } { "origin" "-160 -2360 840" "classname" "light" "light" "140" } { "origin" "-224 -2360 840" "classname" "light" "light" "140" } { "origin" "-288 -2360 840" "classname" "light" "light" "80" } { "light" "150" "classname" "light" "origin" "-400 -2272 1024" } { "classname" "func_group" } { "model" "*62" "mass" "200" "classname" "func_explosive" "spawnflags" "2048" "target" "t254" "targetname" "waller" } { "origin" "-664 -1768 672" "light" "75" "classname" "light" } { "spawnflags" "2050" "origin" "-784 -1920 568" "team" "oremover" "target" "blockwall" "targetname" "t258" "classname" "target_explosion" } { "origin" "-88 -1984 764" "classname" "item_ir_goggles" } { "origin" "-768 -2312 616" "classname" "monster_flyer" "angle" "90" } { "model" "*63" "spawnflags" "2048" "target" "t258" "team" "oremover" "classname" "func_explosive" "dmg" "100" "health" "5" } { "target" "t254" "targetname" "t253" "origin" "-484 -2024 704" "classname" "path_corner" } { "target" "t253" "targetname" "t252" "origin" "-484 -2232 704" "classname" "path_corner" } { "target" "t252" "targetname" "t251" "origin" "-612 -2232 704" "classname" "path_corner" } { "pathtarget" "blocko" "wait" "-1" "targetname" "t254" "classname" "path_corner" "origin" "-228 -2024 704" } { "wait" ".2" "pathtarget" "plat1" "target" "t251" "targetname" "t250" "classname" "path_corner" "origin" "-612 -2232 528" } { "model" "*64" "team" "mony1" "speed" "50" "targetname" "plat1" "target" "t242" "classname" "func_train" "spawnflags" "2" } { "target" "t250" "targetname" "t249" "classname" "path_corner" "origin" "-612 -2160 528" } { "target" "t249" "targetname" "t248" "classname" "path_corner" "origin" "-612 -2120 512" } { "target" "t248" "targetname" "t247" "classname" "path_corner" "origin" "-668 -2120 512" } { "target" "t246" "targetname" "t245" "origin" "-808 -1952 512" "classname" "path_corner" } { "model" "*65" "spawnflags" "2048" "speed" "50" "targetname" "oretrain" "team" "oremover" "target" "t245" "classname" "func_train" "noise" "world/amb10.wav" } { "target" "t247" "targetname" "t246" "origin" "-668 -1952 512" "classname" "path_corner" } { "origin" "-624 -2240 512" "wait" "-1" "targetname" "t244" "classname" "path_corner" } { "wait" "-1" "origin" "-624 -2240 512" "target" "t243" "targetname" "t242" "classname" "path_corner" } { "target" "t242" "wait" "3" "origin" "-624 -2240 688" "targetname" "t243" "classname" "path_corner" } { "origin" "-1808 -1640 144" "angle" "315" "classname" "monster_flyer" "spawnflags" "1" } { "origin" "-1544 -1992 144" "angle" "180" "classname" "monster_flyer" "spawnflags" "1" } { "spawnflags" "2052" "origin" "-1952 -2168 40" "targetname" "t235" "classname" "target_explosion" } { "spawnflags" "2048" "origin" "-1848 -1600 40" "targetname" "t234" "classname" "target_explosion" } { "origin" "-2048 -1888 40" "classname" "weapon_shotgun" } { "origin" "-2040 -1640 24" "classname" "item_double" } { "spawnflags" "2048" "origin" "-928 -1376 64" "targetname" "t178" "classname" "target_explosion" } { "model" "*66" "spawnflags" "2048" "targetname" "t178" "classname" "func_explosive" } { "style" "38" "origin" "-1960 -2168 72" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t235" } { "model" "*67" "spawnflags" "2052" "health" "10" "classname" "func_explosive" "dmg" "100" "target" "t235" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-2224 -1992 288" } { "model" "*68" "spawnflags" "2048" "dmg" "100" "classname" "func_explosive" "target" "t234" "health" "10" } { "model" "*69" "spawnflags" "2048" "classname" "func_explosive" "dmg" "100" "targetname" "t178" } { "spawnflags" "2048" "classname" "target_steam" "origin" "-1584 -2424 -16" "angle" "-1" "speed" "100" "count" "64" "sounds" "225" "wait" "15" "targetname" "t14" } { "spawnflags" "2048" "targetname" "t14" "wait" "17" "sounds" "225" "count" "64" "speed" "150" "angle" "-1" "origin" "-1640 -2432 -16" "classname" "target_steam" } { "origin" "-1600 -2464 336" "classname" "light" "light" "150" } { "spawnflags" "2048" "origin" "-1072 -1520 112" "delay" "1" "target" "t178" "targetname" "t176" "classname" "trigger_relay" } { "classname" "monster_berserk" "angle" "180" "spawnflags" "772" "origin" "688 -520 528" } { "model" "*70" "classname" "func_button" "angle" "270" "lip" "3" "wait" "5" "target" "getplat" "message" "Lift activated." } { "spawnflags" "2048" "target" "t176" "targetname" "t175" "origin" "-1080 -1592 80" "classname" "target_explosion" } { "spawnflags" "2048" "target" "t175" "origin" "-1104 -1672 256" "targetname" "t173" "classname" "trigger_relay" } { "origin" "-1072 -1848 256" "count" "3" "speed" "25" "targetname" "t173" "classname" "target_earthquake" } { "model" "*71" "target" "t173" "classname" "trigger_once" "spawnflags" "2048" } { "spawnflags" "2052" "origin" "-2008 -2216 64" "targetname" "t277" "count" "2" "speed" "40" "classname" "target_earthquake" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t172" "origin" "96 -1664 856" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t171" "origin" "40 -1632 888" } { "origin" "-280 -2160 88" "target" "t160" "spawnflags" "1792" "classname" "trigger_always" } { "origin" "424 -544 520" "classname" "ammo_slugs" "spawnflags" "5888" } { "spawnflags" "5888" "origin" "-472 -1960 720" "classname" "ammo_rockets" } { "origin" "1656 -144 520" "classname" "ammo_cells" "spawnflags" "5888" } { "origin" "1392 -648 552" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "classname" "info_player_deathmatch" "angle" "270" "origin" "1176 -1280 552" } { "classname" "info_player_deathmatch" "angle" "270" "origin" "72 -1272 952" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "-792 -2200 8" } { "origin" "688 -688 520" "spawnflags" "1024" "classname" "ammo_shells" } { "origin" "688 -640 520" "classname" "item_health_large" } { "origin" "504 -776 544" "spawnflags" "2" "targetname" "t92" "noise" "world/l_hum1.wav" "classname" "target_speaker" } { "origin" "-1048 -1720 176" "classname" "item_armor_shard" } { "origin" "-1048 -1760 200" "classname" "item_armor_shard" } { "origin" "-1048 -1800 216" "classname" "item_armor_shard" } { "origin" "-1048 -1680 144" "classname" "item_armor_shard" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "boom" "dmg" "50" "team" "boxcrane" "origin" "640 0 528" "target" "blowgrate" } { "model" "*72" "spawnflags" "2048" "classname" "func_explosive" "health" "25" "mass" "200" "team" "boxcrane" "target" "boom" } { "model" "*73" "spawnflags" "2048" "classname" "func_train" "speed" "93" "target" "t105" "targetname" "t98" "team" "boxcrane" } { "classname" "info_player_start" "angle" "90" "origin" "-2008 -2448 16" } { "model" "*74" "spawnflags" "2048" "targetname" "t5" "speed" "5" "target" "t4" "classname" "func_train" } { "origin" "-1640 -2544 -360" "target" "t4" "targetname" "t3" "classname" "path_corner" } { "origin" "-1696 -2544 -128" "targetname" "t4" "target" "t1" "classname" "path_corner" } { "speed" "5" "origin" "-1696 -2544 -184" "wait" "2" "target" "t2" "targetname" "t1" "classname" "path_corner" } { "accel" ".1" "speed" "20" "wait" "-1" "origin" "-1696 -2544 -288" "target" "t3" "targetname" "t2" "classname" "path_corner" } { "model" "*75" "spawnflags" "2048" "target" "t5" "classname" "trigger_once" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t8" "origin" "-1609 -2419 112" "target" "t12" } { "spawnflags" "2048" "classname" "target_explosion" "target" "t6" "targetname" "t5" "origin" "-1617 -2427 48" } { "spawnflags" "2048" "classname" "target_explosion" "target" "t7" "origin" "-1585 -2411 56" "targetname" "t6" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t14" "target" "t8" "origin" "-1577 -2427 80" } { "spawnflags" "2048" "targetname" "t112" "classname" "target_explosion" "origin" "-1605 -2438 56" } { "spawnflags" "2048" "origin" "-1589 -2430 0" "classname" "target_explosion" "target" "t9" "targetname" "t11" } { "spawnflags" "2048" "origin" "-1581 -2430 24" "classname" "target_explosion" "targetname" "t9" "target" "t10" } { "spawnflags" "2048" "origin" "-1776 -2283 104" "target" "t11" "targetname" "t5" "classname" "trigger_relay" "delay" "12" } { "spawnflags" "2048" "classname" "trigger_relay" "delay" "2" "target" "t14" "origin" "-1541 -2256 72" "targetname" "t7" } { "origin" "-1496 -2464 130" "light" "125" "classname" "light" } { "origin" "-1592 -2424 148" "classname" "light" "light" "125" } { "origin" "-1680 -2472 334" "classname" "light" "light" "150" } { "origin" "-1552 -2352 85" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-1648 -2376 69" } { "light" "150" "classname" "light" "origin" "-1600 -2464 520" } { "light" "125" "classname" "light" "origin" "-1680 -2464 119" } { "classname" "target_splash" "sounds" "5" "count" "40" "targetname" "t15" "origin" "-1306 -1493 -8" "spawnflags" "2049" } { "classname" "func_timer" "target" "t15" "wait" "5" "random" "2" "origin" "-1241 -1472 40" "spawnflags" "2049" } { "count" "40" "sounds" "5" "classname" "target_splash" "targetname" "t16" "origin" "-1714 -1709 -8" "spawnflags" "2049" } { "random" "2" "wait" "4" "classname" "func_timer" "target" "t16" "origin" "-1649 -1688 24" "spawnflags" "2049" } { "origin" "-152 -1792 0" "light" "175" "classname" "light" } { "origin" "-808 -1792 1" "classname" "light" "light" "175" } { "origin" "-736 -2216 0" "classname" "light" "light" "175" } { "origin" "-480 -2224 5" "classname" "light" "light" "175" } { "origin" "-192 -2176 605" "classname" "light" "light" "125" } { "light" "175" "classname" "light" "origin" "-224 -2216 0" } { "light" "125" "classname" "light" "origin" "-192 -2176 272" } { "origin" "-232 -2136 61" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-152 -2216 166" } { "light" "125" "classname" "light" "origin" "-192 -2176 376" } { "light" "150" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-744 -1984 258" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-224 -2016 723" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-416 -1960 600" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-352 -1912 264" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-352 -2056 264" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "150" "origin" "-616 -1984 256" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-472 -1904 592" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-160 -2016 726" } { "origin" "-808 -2048 0" "classname" "light" "light" "175" } { "origin" "-152 -2048 848" "classname" "light" "light" "175" } { "origin" "-288 -2104 887" "classname" "light" "light" "175" } { "origin" "168 -1720 986" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "216 -1720 988" } { "origin" "-488 -1984 256" "light" "150" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "target_explosion" "targetname" "t178" "origin" "-885 -1396 64" "spawnflags" "2048" } { "origin" "-528 -1960 600" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "light" "150" "classname" "light" "origin" "-488 -1984 888" } { "origin" "-352 -1904 64" "classname" "light" "light" "125" } { "origin" "-760 -2344 655" "classname" "light" "light" "175" } { "model" "*76" "spawnflags" "2048" "classname" "trigger_once" "target" "t277" } { "light" "180" "_color" "1.000000 0.694118 0.607843" "classname" "light" "origin" "-1424 -2104 301" } { "style" "39" "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "-1824 -1616 75" "targetname" "t234" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "-88 -1720 991" } { "origin" "56 -1688 1127" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "model" "*77" "origin" "2144 -440 528" "targetname" "t68" "classname" "func_rotating" "dmg" "100" "speed" "145" "_minlight" ".2" "accel" "1" "spawnflags" "8192" } { "model" "*78" "origin" "1952 -440 540" "targetname" "t68" "classname" "func_rotating" "speed" "125" "spawnflags" "8194" "dmg" "100" "_minlight" ".2" "accel" "1" } { "model" "*79" "classname" "func_explosive" "health" "25" "mass" "200" "targetname" "t117" } { "model" "*80" "origin" "1624 -496 750" "target" "t68" "classname" "func_door_rotating" "wait" "-1" "distance" "90" "spawnflags" "146" "speed" "50" "dmg" "1" "targetname" "t82" "_minlight" ".2" } { "light" "200" "classname" "light" "origin" "1208 -152 711" } { "light" "100" "classname" "light" "origin" "1600 -496 761" } { "light" "120" "classname" "light" "origin" "1752 -32 806" } { "light" "100" "classname" "light" "origin" "1872 -24 854" } { "classname" "light" "light" "100" "origin" "1752 -32 525" } { "classname" "light" "light" "120" "origin" "1752 -32 589" } { "classname" "light" "light" "120" "origin" "1752 -32 653" } { "classname" "light" "light" "120" "origin" "1752 -32 718" } { "origin" "2152 -376 639" "classname" "light" "light" "125" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "150" "origin" "2184 -336 577" } { "light" "150" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2064 -336 574" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "150" "origin" "1800 -336 574" } { "light" "150" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2192 -536 572" } { "classname" "light" "light" "100" "origin" "1984 -168 597" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "150" "origin" "1928 -536 565" } { "light" "150" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "1800 -536 566" } { "light" "200" "classname" "light" "origin" "1480 -424 600" } { "origin" "1645 -496 766" "classname" "light" "light" "100" } { "light" "125" "classname" "light" "origin" "1816 -288 543" } { "light" "125" "classname" "light" "origin" "1920 -440 621" } { "light" "125" "classname" "light" "origin" "2032 -440 621" } { "classname" "func_group" } { "origin" "1208 -392 679" "classname" "light" "light" "200" } { "origin" "1288 -536 742" "classname" "light" "light" "200" } { "origin" "1008 -616 919" "classname" "light" "light" "125" } { "origin" "1040 -424 921" "classname" "light" "light" "125" } { "origin" "1008 -344 919" "classname" "light" "light" "125" } { "light" "120" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "488 -520 536" } { "origin" "1128 -592 742" "classname" "light" "light" "200" } { "origin" "840 -88 731" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "120" } { "_color" "0.000000 0.000000 1.000000" "origin" "304 -752 552" "classname" "light" "light" "100" } { "classname" "path_corner" "targetname" "t70" "target" "t71" "origin" "1112 -152 592" "speed" "100" } { "classname" "path_corner" "targetname" "t71" "target" "t72" "origin" "1112 -152 512" } { "classname" "path_corner" "targetname" "t72" "target" "t73" "origin" "1112 -408 516" } { "classname" "path_corner" "targetname" "t73" "target" "t74" "origin" "1112 -408 720" } { "classname" "path_corner" "targetname" "t80" "target" "t70" "origin" "1112 -152 1248" "speed" "500" } { "model" "*81" "team" "mover1" "classname" "func_train" "target" "t70" "targetname" "t81" "speed" "70" "_minlight" ".1" } { "classname" "trigger_relay" "targetname" "t68" "target" "t81" "delay" "2" "origin" "1552 -480 784" } { "model" "*82" "spawnflags" "2048" "health" "10" "classname" "func_explosive" "target" "t115" } { "model" "*83" "spawnflags" "2048" "health" "10" "classname" "func_explosive" "target" "t116" } { "model" "*84" "spawnflags" "2048" "health" "10" "classname" "func_explosive" "target" "t113" } { "model" "*85" "health" "10" "classname" "func_explosive" "target" "t114" } { "model" "*86" "message" "Cart track active." "classname" "trigger_once" "target" "t82" } { "origin" "336 -768 615" "classname" "light" "light" "120" } { "spawnflags" "2048" "light" "75" "classname" "light" "origin" "408 -664 912" } { "origin" "1208 -128 519" "classname" "light" "light" "100" } { "light" "100" "classname" "light" "origin" "1208 -128 591" } { "light" "100" "classname" "light" "origin" "1064 -128 517" } { "origin" "1064 -128 589" "classname" "light" "light" "100" } { "model" "*87" "spawnflags" "2048" "target" "t90" "classname" "trigger_once" } { "model" "*88" "target" "t104" "classname" "func_explosive" "mass" "100" "health" "25" "spawnflags" "2048" "targetname" "t352" } { "model" "*89" "spawnflags" "2048" "target" "t98" "sounds" "4" "wait" "-1" "angle" "90" "classname" "func_button" "message" "Crane activated." } { "_color" "1.000000 0.850980 0.850980" "origin" "1992 -280 565" "classname" "light" "light" "160" } { "_color" "1.000000 0.850980 0.850980" "origin" "520 -88 760" "classname" "light" "light" "100" } { "origin" "2094 -376 430" "light" "150" "_color" "1.000000 0.607843 0.607843" "classname" "light" } { "light" "125" "classname" "light" "origin" "2112 -400 805" } { "target" "t104" "origin" "532 -632 800" "targetname" "t96" "classname" "path_corner" } { "targetname" "t105" "origin" "596 -8 528" "classname" "path_corner" "target" "t97" } { "origin" "596 -8 800" "targetname" "t97" "target" "t94" "classname" "path_corner" } { "origin" "596 -152 800" "target" "t95" "targetname" "t94" "classname" "path_corner" } { "origin" "532 -152 800" "target" "t96" "targetname" "t95" "classname" "path_corner" } { "model" "*90" "spawnflags" "2048" "speed" "93" "targetname" "t103" "target" "t102" "classname" "func_train" } { "origin" "560 -640 976" "wait" "-1" "target" "t102" "targetname" "t101" "classname" "path_corner" } { "origin" "624 -16 976" "targetname" "t102" "target" "t99" "classname" "path_corner" } { "origin" "624 -160 976" "target" "t100" "targetname" "t99" "classname" "path_corner" } { "origin" "560 -160 976" "target" "t101" "targetname" "t100" "classname" "path_corner" } { "spawnflags" "2048" "origin" "664 -344 944" "delay" "3" "target" "t103" "targetname" "t98" "classname" "trigger_relay" } { "target" "t164" "origin" "532 -632 744" "targetname" "t104" "classname" "path_corner" "wait" "-1" "pathtarget" "gibber" } { "model" "*91" "classname" "func_explosive" "mass" "400" "target" "t117" "health" "25" } { "spawnflags" "2048" "message" "You found a secret!" "classname" "target_secret" "targetname" "t117" "origin" "2064 -272 592" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "150" "origin" "2056 -536 566" } { "spawnflags" "2048" "origin" "-1904 -1536 112" "message" "You found a secret area!" "targetname" "t110" "classname" "target_secret" } { "model" "*92" "classname" "func_explosive" "mass" "150" "targetname" "t117" } { "origin" "2112 -344 512" "targetname" "t117" "classname" "target_explosion" } { "light" "125" "classname" "light" "origin" "-232 -2136 550" } { "light" "175" "classname" "light" "origin" "-608 -1912 652" } { "origin" "-272 -1968 759" "classname" "light" "light" "175" } { "light" "175" "classname" "light" "origin" "-528 -1904 734" } { "origin" "1824 -488 622" "classname" "light" "light" "125" } { "spawnflags" "2048" "origin" "-1536 -2384 144" "targetname" "t14" "count" "100" "sounds" "1" "classname" "target_splash" } { "spawnflags" "2048" "origin" "-1600 -2464 136" "targetname" "t5" "sounds" "1" "count" "100" "classname" "target_splash" } { "spawnflags" "2048" "origin" "-1648 -2304 56" "target" "t112" "targetname" "t10" "delay" "1" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "-1600 -2400 72" "targetname" "t112" "sounds" "1" "count" "150" "classname" "target_splash" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t116" "origin" "480 -416 560" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t113" "origin" "736 -288 552" } { "classname" "target_explosion" "targetname" "t114" "origin" "800 -96 544" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t115" "origin" "416 -296 552" } { "model" "*93" "classname" "func_plat2" "height" "520" "sounds" "1" "speed" "300" "spawnflags" "0" "targetname" "t160" } { "classname" "light" "_color" "1.000000 0.325490 0.000000" "light" "150" "origin" "-608 -2216 24" } { "light" "150" "_color" "1.000000 0.325490 0.000000" "classname" "light" "origin" "-352 -2216 20" } { "origin" "-456 -2160 758" "classname" "light" "light" "175" } { "classname" "light" "light" "100" "origin" "2080 -896 824" } { "light" "75" "classname" "light" "origin" "-368 -1672 48" } { "light" "100" "classname" "light" "origin" "-368 -1472 72" } { "light" "100" "classname" "light" "origin" "-472 -1384 72" } { "light" "100" "classname" "light" "origin" "-648 -1384 72" } { "light" "100" "classname" "light" "origin" "1888 -896 824" } { "classname" "func_timer" "target" "t119" "wait" "2" "random" "1" "spawnflags" "1" "targetname" "t117" "origin" "2152 -280 592" } { "classname" "target_splash" "count" "75" "sounds" "1" "targetname" "t119" "origin" "2088 -360 472" } { "origin" "-480 -2128 8" "spawnflags" "260" "target" "t120" "angle" "90" "classname" "monster_soldier_light" } { "origin" "-208 -1808 8" "spawnflags" "4" "classname" "monster_soldier_light" "angle" "180" "target" "t160" } { "origin" "-208 -2064 -8" "spawnflags" "2049" "targetname" "t120" "classname" "point_combat" } { "origin" "-528 -2088 8" "spawnflags" "4" "target" "t121" "classname" "monster_soldier_light" "angle" "90" } { "origin" "-736 -1872 -8" "targetname" "t121" "classname" "point_combat" "spawnflags" "1" } { "origin" "-192 -2176 536" "spawnflags" "5" "angle" "135" "classname" "monster_soldier" } { "spawnflags" "4" "origin" "-248 -1976 728" "target" "t123" "angle" "315" "classname" "monster_soldier_light" } { "spawnflags" "4" "origin" "-456 -1880 536" "classname" "monster_soldier_light" "angle" "315" } { "origin" "-440 -1992 728" "target" "t124" "targetname" "t122" "classname" "path_corner" } { "origin" "-264 -1992 728" "targetname" "t123" "target" "t122" "classname" "path_corner" } { "origin" "-448 -1952 728" "target" "t123" "targetname" "t124" "classname" "path_corner" } { "spawnflags" "4" "origin" "-448 -2288 728" "target" "t125" "classname" "monster_soldier_ss" } { "origin" "-496 -2008 728" "target" "t125" "targetname" "t127" "classname" "path_corner" } { "origin" "-464 -2272 728" "target" "t126" "targetname" "t125" "classname" "path_corner" } { "origin" "-480 -2064 728" "target" "t127" "targetname" "t126" "classname" "path_corner" } { "spawnflags" "4" "origin" "-472 -1952 856" "target" "t128" "angle" "0" "classname" "monster_soldier_light" } { "spawnflags" "4" "origin" "-384 -2160 856" "target" "t129" "classname" "monster_soldier_light" "angle" "0" } { "origin" "-320 -1920 840" "spawnflags" "2049" "targetname" "t128" "classname" "point_combat" "angle" "270" } { "origin" "-368 -2312 840" "spawnflags" "2049" "targetname" "t129" "classname" "point_combat" "angle" "0" } { "spawnflags" "4" "origin" "-576 -1984 984" "angle" "315" "classname" "monster_soldier_light" "target" "t260" } { "targetname" "flyercharge" "spawnflags" "257" "origin" "-88 -1632 992" "angle" "0" "classname" "monster_flyer" "target" "t171" } { "targetname" "flyercharge" "spawnflags" "257" "origin" "232 -1568 992" "classname" "monster_flyer" "angle" "180" "target" "t172" } { "target" "t300" "targetname" "t299" "origin" "1976 -376 768" "spawnflags" "5" "angle" "315" "classname" "monster_berserk" } { "origin" "1688 -440 776" "spawnflags" "1" "angle" "135" "classname" "monster_gunner" } { "classname" "monster_soldier_light" "angle" "270" "target" "t140" "origin" "1464 -64 496" "spawnflags" "4" } { "classname" "path_corner" "targetname" "t139" "target" "t140" "origin" "1504 -480 520" } { "classname" "path_corner" "target" "t137" "targetname" "t140" "origin" "1448 -80 480" } { "classname" "path_corner" "targetname" "t137" "target" "t138" "origin" "1448 -328 504" } { "classname" "path_corner" "targetname" "t138" "target" "t139" "origin" "1280 -328 504" } { "classname" "monster_soldier_light" "angle" "0" "spawnflags" "4" "origin" "1056 -352 528" } { "angle" "0" "classname" "monster_soldier_light" "spawnflags" "4" "origin" "1048 -312 528" "target" "t159" } { "target" "t169" "deathtarget" "flyercharge" "origin" "72 -1184 952" "spawnflags" "1281" "angle" "270" "classname" "monster_infantry" } { "origin" "920 -440 736" "spawnflags" "4" "angle" "0" "classname" "monster_soldier_light" "targetname" "t280" "target" "t286" } { "origin" "912 -504 736" "classname" "monster_soldier_light" "angle" "0" "spawnflags" "4" "targetname" "t280" } { "origin" "832 -768 904" "spawnflags" "769" "classname" "monster_soldier" "angle" "90" } { "origin" "448 -128 736" "angle" "0" "spawnflags" "4" "classname" "monster_soldier_light" } { "origin" "432 -664 528" "angle" "45" "spawnflags" "4" "classname" "monster_soldier" } { "origin" "240 -616 528" "spawnflags" "4" "angle" "0" "classname" "monster_soldier_light" } { "origin" "448 -232 536" "spawnflags" "4" "angle" "90" "classname" "monster_soldier_light" } { "origin" "552 -416 536" "classname" "monster_soldier_light" "angle" "0" "spawnflags" "4" } { "classname" "target_speaker" "noise" "world/drip_amb.wav" "spawnflags" "1" "origin" "184 -1560 984" } { "classname" "target_speaker" "origin" "2056 -416 624" "noise" "world/amb17.wav" "spawnflags" "2" "targetname" "t68" } { "volume" ".5" "spawnflags" "2048" "noise" "world/lava1.wav" "classname" "target_speaker" "origin" "-1712 -1688 0" "targetname" "t16" } { "volume" ".5" "spawnflags" "2049" "noise" "world/lava1.wav" "classname" "target_speaker" "origin" "-1232 -1608 112" } { "classname" "misc_deadsoldier" "spawnflags" "2064" "angle" "90" "origin" "-200 -2032 704" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t159" "origin" "1320 -280 536" } { "classname" "item_armor_shard" "origin" "1080 -480 688" } { "classname" "item_armor_shard" "origin" "1080 -520 688" } { "spawnflags" "0" "classname" "item_armor_shard" "origin" "1080 -560 688" } { "classname" "item_health" "origin" "-296 -2328 912" } { "classname" "item_health" "origin" "1584 -8 488" } { "classname" "item_health" "origin" "1592 -272 760" "spawnflags" "1024" } { "classname" "item_health" "origin" "936 -360 728" } { "classname" "item_health" "origin" "296 -752 896" } { "classname" "ammo_shells" "origin" "-672 -1760 64" } { "spawnflags" "1792" "classname" "ammo_shells" "origin" "-592 -1752 528" } { "classname" "ammo_grenades" "origin" "816 -608 528" } { "classname" "ammo_grenades" "origin" "1760 -528 520" } { "classname" "item_health_small" "origin" "2168 -240 520" } { "classname" "item_health_small" "origin" "2216 -288 520" } { "classname" "item_health_small" "origin" "2216 -240 520" } { "spawnflags" "2048" "classname" "target_splash" "sounds" "1" "count" "100" "origin" "-1568 -2416 88" "targetname" "t14" } { "spawnflags" "2048" "classname" "target_splash" "sounds" "1" "count" "100" "origin" "-1560 -2408 112" "targetname" "t14" } { "spawnflags" "2048" "classname" "target_splash" "sounds" "1" "count" "100" "origin" "-1552 -2400 136" "targetname" "t14" } { "spawnflags" "2048" "classname" "target_splash" "count" "150" "sounds" "1" "origin" "-1600 -2416 56" "targetname" "t112" } { "classname" "ammo_shells" "origin" "2056 -64 520" } { "classname" "ammo_shells" "origin" "1760 -480 520" } { "origin" "-184 -1952 720" "classname" "ammo_grenades" } { "origin" "808 -616 728" "classname" "ammo_shells" } { "spawnflags" "1536" "origin" "1640 -536 520" "classname" "item_health" } { "spawnflags" "1024" "origin" "1600 -536 520" "classname" "item_health" } { "origin" "-800 -1760 0" "classname" "item_health_large" } { "origin" "-432 -1832 536" "spawnflags" "772" "angle" "315" "classname" "monster_soldier_ss" } { "origin" "1752 -288 520" "spawnflags" "1536" "classname" "item_health_large" } { "origin" "848 -96 528" "spawnflags" "768" "classname" "item_health" } { "origin" "532 -632 536" "wait" "-1" "target" "t105" "targetname" "t164" "classname" "path_corner" } { "targetname" "t178" "target" "t177" "spawnflags" "2048" "origin" "-1013 -1476 64" "classname" "target_explosion" } { "classname" "light" "origin" "-1904 -1512 240" "_color" "0.000000 0.000000 1.000000" "light" "110" } { "classname" "light" "origin" "1352 -544 544" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "origin" "1560 -1136 936" "classname" "light" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1432 -488 528" "classname" "light" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "origin" "240 -1248 1048" "classname" "light" } { "classname" "light" "origin" "280 -1312 992" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "origin" "-168 -1488 1048" "classname" "light" } { "classname" "light" "origin" "136 -1136 992" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "75" "_color" "0.000000 0.000000 1.000000" "origin" "304 -1232 1048" "classname" "light" } { "origin" "-56 -1920 920" "classname" "light" "light" "75" } { "light" "100" "classname" "light" "origin" "64 -1920 920" } { "origin" "64 -1808 920" "classname" "light" "light" "100" } { "light" "125" "classname" "light" "origin" "1824 -328 622" } { "classname" "light" "origin" "2072 -40 872" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "2080 -8 928" "classname" "light" } { "classname" "light" "origin" "2080 -112 864" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "origin" "1240 -464 512" "classname" "light" } { "origin" "1064 -1504 624" "spawnflags" "1" "noise" "world/drill1.wav" "classname" "target_speaker" } { "spawnflags" "1" "classname" "point_combat" "targetname" "t131" "origin" "1064 -1504 584" } { "spawnflags" "0" "classname" "monster_flyer" "origin" "1064 -1504 664" "angle" "180" "target" "t131" "targetname" "t133" } { "spawnflags" "5888" "classname" "ammo_slugs" "origin" "1064 -1512 568" } { "model" "*94" "classname" "trigger_once" "target" "t133" } { "model" "*95" "team" "mover2" "targetname" "t81" "target" "t288" "classname" "func_train" "speed" "70" "_minlight" ".1" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "1736 328 768" "classname" "light" } { "classname" "light" "origin" "1552 200 808" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "classname" "ammo_shells" "origin" "1112 424 704" } { "classname" "ammo_shells" "origin" "1112 376 704" "spawnflags" "0" } { "targetname" "t350" "spawnflags" "1" "origin" "1880 192 512" "classname" "item_health" } { "origin" "1136 288 712" "spawnflags" "4" "angle" "0" "classname" "monster_soldier_light" } { "model" "*96" "spawnflags" "2048" "sounds" "4" "angle" "0" "classname" "func_door" "speed" "70" "team" "level_exit" } { "model" "*97" "spawnflags" "2048" "sounds" "4" "angle" "180" "classname" "func_door" "speed" "70" "team" "level_exit" } { "spawnflags" "4" "angle" "0" "classname" "monster_soldier_light" "origin" "1168 232 712" } { "light" "135" "origin" "2032 888 698" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "light" "135" "origin" "1904 888 698" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "light" "135" "origin" "1904 992 699" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "light" "135" "origin" "2032 992 702" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "spawnflags" "2048" "origin" "1968 992 640" "map" "rlava1$lstart1" "targetname" "t167" "classname" "target_changelevel" } { "model" "*98" "spawnflags" "2048" "angle" "90" "target" "t167" "classname" "trigger_multiple" } { "origin" "1136 344 712" "angle" "0" "classname" "info_player_deathmatch" } { "targetname" "t350" "classname" "ammo_rockets" "spawnflags" "5889" "origin" "2064 664 560" } { "spawnflags" "5888" "classname" "ammo_rockets" "origin" "2080 712 560" } { "spawnflags" "5888" "classname" "ammo_flechettes" "origin" "1504 520 504" } { "spawnflags" "5888" "classname" "ammo_flechettes" "origin" "1544 520 504" } { "origin" "1968 1000 584" "angle" "270" "targetname" "mineend" "classname" "info_player_start" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "672 160 792" "classname" "light" } { "classname" "light" "origin" "680 128 752" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "640 136 888" "classname" "light" } { "classname" "light" "origin" "784 304 896" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "856 344 832" "classname" "light" } { "classname" "light" "origin" "872 360 760" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "classname" "light" "origin" "1048 424 784" "_color" "1.000000 0.000000 0.000000" "light" "100" } { "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "1048 456 736" "classname" "light" } { "classname" "item_health_small" "origin" "424 160 728" } { "origin" "440 200 736" "classname" "item_health_small" } { "origin" "424 120 720" "classname" "item_health_small" } { "light" "120" "classname" "light" "origin" "608 224 823" "_color" "1.000000 0.850980 0.850980" } { "light" "76" "classname" "light" "origin" "520 256 812" "_color" "1.000000 0.850980 0.850980" } { "spawnflags" "5888" "classname" "ammo_flechettes" "origin" "480 280 744" } { "_color" "1.000000 0.850980 0.850980" "origin" "896 320 756" "classname" "light" "light" "100" } { "_color" "1.000000 0.850980 0.850980" "origin" "800 288 772" "classname" "light" "light" "100" } { "classname" "target_help" "message" "Destroy all resistance!" "spawnflags" "2048" "targetname" "t5" "origin" "-2168 -2288 144" } { "spawnflags" "2049" "origin" "-2128 -2320 144" "targetname" "t5" "message" "Find Comm Center to \nretrieve orders." "classname" "target_help" } { "origin" "-896 -1048 72" "classname" "light" "light" "200" "_color" "1.000000 1.000000 0.501961" } rogue-ROGUE_2_13/stuff/mapfixes/rsewer1.ent000066400000000000000000002403241477320066100206600ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Fixed "color is not a field" warnings // // 2. Removed lava sounds when filtration system has been activated (b#2) // // 3. Fixed broken trigger_once and target_speaker (b#3) // // There are a number of trigger_once that target a voice speaker. // There was one pair that did not have any target/targetname so // I linked them together. // // 4. Added missing spawnflags to some entities (b#4) // // 5. Fixed overlapping secret sound effects (b#5) // // 6. Fixed old classnames (b#6) { "sounds" "11" "nextmap" "rsewer2" "message" "Waste Processing" "classname" "worldspawn" } { "origin" "2368 -1064 288" "noise" "world/valve.wav" "spawnflags" "2048" "classname" "target_speaker" "targetname" "t19" } { "classname" "target_speaker" "spawnflags" "2048" "noise" "world/valve.wav" "origin" "2368 -72 200" "targetname" "t49" } { "origin" "2368 352 152" "noise" "world/valve.wav" "spawnflags" "2048" "classname" "target_speaker" "targetname" "t52" } { "classname" "item_adrenaline" "angle" "90" "origin" "2248 -864 744" } { "model" "*1" "classname" "func_wall" "spawnflags" "3584" } { "noise" "world/amb8.wav" "spawnflags" "1" "classname" "target_speaker" "origin" "2368 -264 328" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/amb8.wav" "origin" "2368 -384 328" } { "noise" "world/amb8.wav" "spawnflags" "1" "classname" "target_speaker" "origin" "2368 -384 560" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/amb8.wav" "origin" "2368 -264 560" } { "noise" "world/amb14.wav" "spawnflags" "1" "classname" "target_speaker" "origin" "1184 480 208" } { "noise" "world/amb14.wav" "spawnflags" "1" "classname" "target_speaker" "origin" "1184 376 208" } { "volume" "1" "spawnflags" "2049" "classname" "target_speaker" "origin" "1184 232 456" "noise" "world/amb16.wav" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/amb14.wav" "origin" "1184 584 208" } { "classname" "target_help" "spawnflags" "2048" "message" "Deactivate green security\nlasers." "origin" "2136 -2432 64" "targetname" "t9" } { "model" "*2" "classname" "func_wall" "spawnflags" "256" } { "classname" "light" "light" "100" "origin" "2320 -8 272" } { "classname" "light" "light" "100" "origin" "2368 -72 272" } { "classname" "light" "light" "100" "origin" "2656 264 176" } { "model" "*3" "classname" "trigger_hurt" "dmg" "10000" "spawnflags" "2050" "targetname" "t8" } { "model" "*4" "spawnflags" "2050" "dmg" "10000" "classname" "trigger_hurt" "targetname" "t8" } { "model" "*5" "classname" "trigger_hurt" "dmg" "10000" "spawnflags" "2050" "targetname" "t8" } { "model" "*6" "origin" "2368 -55 200" "classname" "func_door_rotating" "spawnflags" "10376" "target" "t49" "targetname" "t18" "wait" "-1" "distance" "90" } { "classname" "trigger_relay" "spawnflags" "2048" // b#4: added this "targetname" "reac" "delay" "15" "origin" "1512 -168 200" "message" "Containment bulkheads activated." "target" "t128" } { "classname" "path_corner" "spawnflags" "2048" // b#4: added this "targetname" "t127" "wait" "-1" "origin" "1488 0 192" } { "classname" "path_corner" "spawnflags" "2048" // b#4: added this "targetname" "t126" "target" "t127" "origin" "1488 0 312" } { "model" "*7" "classname" "func_train" "target" "t126" "spawnflags" "2048" "speed" "25" "targetname" "t128" } { "origin" "3616 -120 336" "spawnflags" "2048" "targetname" "t23" "classname" "trigger_relay" "killtarget" "brusher" } { "origin" "2032 -1992 -120" "angles" "15 45 0" "spawnflags" "0" "classname" "info_player_intermission" } { "origin" "1624 608 216" "attenuation" "-1" "noise" "world/voice5.wav" "spawnflags" "2048" "targetname" "t125" "classname" "target_speaker" } { "model" "*8" "spawnflags" "2048" "target" "t125" "classname" "trigger_once" } { "attenuation" "-1" "origin" "792 920 384" "spawnflags" "2048" "noise" "world/voice4.wav" "targetname" "t124" "classname" "target_speaker" } { "model" "*9" "target" "t124" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*10" "target" "t124b" // b#3: added this "classname" "trigger_once" "spawnflags" "2048" } { "classname" "target_speaker" "targetname" "t124b" // b#3: added this "noise" "world/voice3.wav" "attenuation" "-1" "spawnflags" "2048" "origin" "2632 -192 176" } { "model" "*11" "target" "t123" "spawnflags" "2048" "classname" "trigger_once" } { "targetname" "t123" "spawnflags" "2048" "attenuation" "-1" "noise" "world/unit3_01.wav" "classname" "target_speaker" "origin" "2304 -2400 64" } { "model" "*12" "target" "t122" "classname" "trigger_once" "spawnflags" "2048" } { "origin" "2280 -1784 -136" "targetname" "t122" "classname" "target_speaker" "noise" "world/unit3_03.wav" "attenuation" "-1" "spawnflags" "2048" } { "origin" "2664 -192 368" "spawnflags" "2048" "attenuation" "-1" "noise" "world/voice10.wav" "targetname" "t121" "classname" "target_speaker" } { "model" "*13" "spawnflags" "2048" "target" "t121" "classname" "trigger_once" } { "model" "*14" "spawnflags" "1024" "classname" "func_wall" } { "model" "*15" "spawnflags" "5888" "classname" "func_wall" } { "model" "*16" "spawnflags" "5888" "classname" "func_wall" } { "model" "*17" "lip" "16" "classname" "func_plat2" "spawnflags" "5889" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "2944 96 344" } { "origin" "928 992 216" "classname" "info_player_deathmatch" "angle" "315" } { "origin" "928 -32 216" "classname" "info_player_deathmatch" "angle" "45" } { "origin" "1824 96 152" "classname" "info_player_deathmatch" "angle" "45" } { "origin" "2496 -8 344" "classname" "info_player_deathmatch" "angle" "270" } { "origin" "3624 -352 344" "classname" "info_player_deathmatch" "angle" "180" } { "angle" "225" "classname" "info_player_deathmatch" "origin" "2008 -352 312" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "2304 544 344" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "352 672 408" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "2272 -352 120" } { "angle" "180" "classname" "info_player_deathmatch" "origin" "2824 -1312 24" } { "angle" "90" "classname" "info_player_deathmatch" "origin" "2144 -2144 24" } { "origin" "3264 -728 344" "angle" "90" "targetname" "t120" "spawnflags" "5888" "classname" "misc_teleporter_dest" } { "angle" "45" "origin" "2368 -1248 -232" "target" "t120" "spawnflags" "5888" "classname" "misc_teleporter" } { "origin" "2368 -1384 -240" "spawnflags" "5888" "classname" "item_double" } { "angle" "270" "origin" "3064 208 344" "target" "t119" "spawnflags" "5888" "classname" "misc_teleporter" } { "angle" "90" "origin" "2368 -1504 -232" "targetname" "t119" "spawnflags" "5888" "classname" "misc_teleporter_dest" } { "origin" "3040 -448 152" "classname" "info_player_deathmatch" "angle" "0" } { "origin" "1888 -1824 -232" "angle" "0" "classname" "info_player_deathmatch" } { "origin" "2368 -1024 272" "spawnflags" "5888" "classname" "item_sphere_vengeance" } { "origin" "2016 -2720 32" "spawnflags" "5888" "classname" "item_sphere_hunter" } { "origin" "2048 -712 528" "spawnflags" "5888" "classname" "ammo_cells" } { "origin" "1920 -616 528" "spawnflags" "5888" "classname" "weapon_hyperblaster" } { "origin" "2880 256 336" "spawnflags" "5888" "classname" "weapon_chaingun" } { "origin" "3400 -16 336" "spawnflags" "5888" "classname" "weapon_rocketlauncher" } { "origin" "3456 -192 528" "spawnflags" "5888" "classname" "ammo_nuke" } { "origin" "2920 -240 144" "spawnflags" "5888" "classname" "ammo_prox" } { "origin" "2880 -192 144" "spawnflags" "5888" "classname" "weapon_proxlauncher" } { "origin" "2272 416 144" "spawnflags" "5888" "classname" "ammo_flechettes" } { "origin" "2368 344 144" "spawnflags" "5888" "classname" "weapon_etf_rifle" // b#6: nailgun -> etf_rifle } { "origin" "672 744 400" "spawnflags" "5888" "classname" "ammo_cells" } { "origin" "736 480 400" "spawnflags" "5888" "classname" "weapon_plasmabeam" } { "model" "*18" "spawnflags" "2048" "classname" "func_wall" } { "model" "*19" "spawnflags" "2048" "classname" "func_wall" } { "model" "*20" "spawnflags" "2048" "classname" "func_wall" } { "model" "*21" "spawnflags" "2048" "classname" "func_wall" } { "model" "*22" "spawnflags" "2048" "classname" "func_wall" } { "model" "*23" "spawnflags" "2048" "classname" "func_wall" } { "model" "*24" "spawnflags" "2048" "classname" "func_wall" } { "model" "*25" "spawnflags" "2048" "classname" "func_wall" } { "model" "*26" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t118" "message" "Radiation levels rising,\n area quarantined." } { "model" "*27" "spawnflags" "2048" "classname" "func_explosive" "targetname" "t117" } { "spawnflags" "2048" "classname" "target_secret" "message" "You found a secret!" // b#5: moved this here "targetname" "t117" "origin" "352 264 464" } { "model" "*28" "spawnflags" "2048" "classname" "func_button" "angle" "270" "lip" "1" "target" "t117" "wait" "-1" } { "classname" "item_health_mega" "origin" "352 256 400" "angle" "0" } { "origin" "1440 1000 208" "classname" "item_health_large" } { "model" "*29" "dmg" "30" "spawnflags" "2079" "classname" "trigger_hurt" "targetname" "t114" "target" "t118" } { "classname" "item_health_large" "origin" "584 512 400" } { "classname" "item_health_large" "spawnflags" "1024" "origin" "584 552 400" } { "classname" "item_health_small" "origin" "1640 552 144" } { "classname" "item_health_small" "origin" "1560 512 144" } { "classname" "item_health_small" "origin" "1560 552 144" } { "classname" "item_health_small" "origin" "1640 512 144" } { "origin" "2272 608 192" "classname" "monster_turret" "spawnflags" "1672" "angle" "270" "targetname" "t35" } { "model" "*30" "classname" "func_wall" "spawnflags" "5888" } { "classname" "ammo_flechettes" "origin" "2928 -144 144" } { "classname" "ammo_shells" "origin" "2968 -152 144" } { "spawnflags" "5120" "classname" "item_health_large" "origin" "3400 40 336" } { "classname" "item_health_large" "spawnflags" "1536" "origin" "3440 40 336" } { "origin" "3544 56 336" "classname" "ammo_rockets" } { "model" "*31" "spawnflags" "2048" "classname" "trigger_once" "target" "t18" "targetname" "light1" } { "model" "*32" "classname" "func_wall" "targetname" "light1" "spawnflags" "6" } { "style" "32" "origin" "696 560 480" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "33" "spawnflags" "2048" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" "origin" "696 560 480" "targetname" "light1" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "696 400 480" "targetname" "light2" } { "style" "33" "spawnflags" "2048" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" "origin" "696 400 480" "targetname" "light1" } { "spawnflags" "2048" "classname" "target_help" "targetname" "t40" "origin" "608 624 440" "message" "Evacuate area! Radiation\n levels toxic!" } { "model" "*33" "classname" "trigger_once" "spawnflags" "2052" "targetname" "light1" "target" "t116" } { "model" "*34" "spawnflags" "2048" "classname" "trigger_once" "targetname" "t19" "target" "t17" } { "model" "*35" "spawnflags" "2048" "classname" "trigger_once" "target" "t17" "targetname" "t49" } { "model" "*36" "spawnflags" "2048" "classname" "trigger_once" "target" "t17" "targetname" "t52" } { "spawnflags" "2048" "classname" "trigger_relay" "target" "signs" "targetname" "light1" "origin" "528 896 400" } { "attenuation" "-1" "classname" "target_speaker" "origin" "1376 64 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" "targetname" "t35" } { "attenuation" "-1" "classname" "target_speaker" "origin" "1376 752 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" "targetname" "t35" } { "attenuation" "-1" "classname" "target_speaker" "origin" "1040 896 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" "targetname" "t35" } { "attenuation" "-1" "classname" "target_speaker" "origin" "528 232 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" "targetname" "t35" } { "attenuation" "-1" "classname" "target_speaker" "origin" "528 696 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" "targetname" "t35" } { "noise" "world/klaxon1.wav" "spawnflags" "2054" "origin" "1376 520 448" "classname" "target_speaker" "attenuation" "-1" "targetname" "t35" } { "noise" "world/klaxon1.wav" "spawnflags" "2054" "origin" "736 496 448" "classname" "target_speaker" "attenuation" "-1" "targetname" "t35" } { "spawnflags" "2048" "classname" "ammo_slugs" "origin" "3040 224 336" } { "classname" "ammo_rockets" "origin" "1696 -728 528" } { "classname" "ammo_rockets" "origin" "1568 -160 208" } { "model" "*37" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*38" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*39" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*40" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*41" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*42" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "model" "*43" "classname" "func_wall" "spawnflags" "6" "targetname" "signs" } { "angle" "90" "spawnflags" "768" "classname" "monster_daedalus" "origin" "3264 -704 376" } { "classname" "monster_daedalus" "spawnflags" "770" "angle" "270" "targetname" "t5" "origin" "3064 192 376" } { "spawnflags" "1" "noise" "world/comp_hum2.wav" "classname" "target_speaker" "origin" "1824 -832 576" } { "spawnflags" "1" "noise" "world/comp_hum2.wav" "classname" "target_speaker" "origin" "3456 64 376" } { "classname" "target_speaker" "noise" "world/comp_hum2.wav" "spawnflags" "2049" "origin" "2784 -1608 80" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/pump3.wav" "targetname" "reac" "origin" "2536 208 232" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/pump3.wav" "targetname" "reac" "origin" "2368 384 232" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/pump3.wav" "targetname" "reac" "origin" "2208 200 232" } { "classname" "ammo_rockets" "origin" "2712 -1184 16" } { "classname" "item_health_large" "origin" "2056 -1160 16" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t35" "origin" "2080 -1184 200" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t35" "origin" "2656 -1184 200" } { "classname" "monster_floater" "spawnflags" "768" "origin" "2080 -1184 272" } { "classname" "monster_floater" "origin" "2648 -1184 272" } { "model" "*44" "spawnflags" "2048" "classname" "func_explosive" "targetname" "t35" } { "model" "*45" "spawnflags" "2048" "classname" "func_explosive" "targetname" "t35" } { "classname" "target_explosion" "targetname" "t35" "origin" "2464 568 184" "spawnflags" "2816" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t35" "origin" "2272 568 184" } { "model" "*46" "classname" "func_explosive" "targetname" "t35" "spawnflags" "2816" } { "model" "*47" "spawnflags" "2048" "classname" "func_explosive" "targetname" "t35" } { "angle" "270" "spawnflags" "416" "classname" "monster_turret" "targetname" "t35" "origin" "2272 608 192" } { "classname" "monster_turret" "spawnflags" "928" "angle" "270" "targetname" "t35" "origin" "2464 608 192" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "1025" "origin" "2880 -200 152" } { "targetname" "t6" "spawnflags" "2" "item" "ammo_slugs" "classname" "monster_gladiator" "angle" "0" "origin" "3016 -192 152" } { "model" "*48" "spawnflags" "2048" "classname" "func_door" "angle" "-2" "targetname" "t18" "wait" "-1" } { "origin" "2992 -192 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2880 -192 240" } { "style" "34" "_color" "0.000000 0.666667 1.000000" "classname" "light" "targetname" "t53" "origin" "2368 -1128 96" "spawnflags" "2049" "light" "125" } { "style" "34" "classname" "light" "_color" "0.000000 0.666667 1.000000" "targetname" "t53" "origin" "2368 -1128 352" "spawnflags" "2049" "light" "125" } { "noise" "world/klaxon1.wav" "spawnflags" "2054" "origin" "648 392 448" "classname" "target_speaker" "attenuation" "-1" "targetname" "t35" } { "noise" "world/klaxon1.wav" "spawnflags" "2054" "origin" "648 632 448" "classname" "target_speaker" "attenuation" "-1" "targetname" "t35" } { "classname" "monster_gunner" "spawnflags" "769" "angle" "0" "origin" "2240 -64 536" } { "classname" "item_health" "origin" "2528 -680 336" } { "model" "*49" "classname" "func_wall" "spawnflags" "2054" "targetname" "t16" } { "origin" "2632 344 272" "classname" "ammo_slugs" } { "spawnflags" "2048" "classname" "trigger_relay" "delay" "19" "target" "t114" "targetname" "reac" "origin" "1512 896 464" } { "model" "*50" "classname" "trigger_hurt" "spawnflags" "2079" "dmg" "30" "targetname" "t114" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t110" "target" "t111" "origin" "2432 488 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t111" "target" "t112" "origin" "1864 312 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t112" "target" "t113" "origin" "1600 320 144" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t113" "origin" "1600 72 216" } { "classname" "hint_path" "spawnflags" "2049" "target" "t110" "origin" "2840 384 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t107" "target" "t108" "origin" "1576 56 216" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t108" "target" "t109" "origin" "1624 -200 216" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t109" "origin" "2200 -184 152" } { "classname" "hint_path" "spawnflags" "2049" "target" "t107" "origin" "1392 64 216" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t104" "target" "t105" "origin" "1560 768 224" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t105" "target" "t106" "origin" "2112 768 352" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t106" "origin" "2120 536 352" } { "classname" "hint_path" "spawnflags" "2049" "target" "t104" "origin" "1408 744 224" } { "origin" "2224 -512 544" "spawnflags" "2048" "classname" "hint_path" "targetname" "t98" "target" "t99" } { "origin" "2240 -48 544" "spawnflags" "2048" "classname" "hint_path" "targetname" "t99" "target" "t100" } { "origin" "2488 -48 544" "spawnflags" "2048" "classname" "hint_path" "targetname" "t100" "target" "t101" } { "origin" "2496 -256 544" "spawnflags" "2048" "classname" "hint_path" "targetname" "t101" "target" "t102" } { "origin" "2504 -560 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t102" "target" "t103" } { "origin" "2376 -648 352" "spawnflags" "2049" "classname" "hint_path" "targetname" "t103" } { "classname" "hint_path" "spawnflags" "2049" "origin" "2232 -832 544" "target" "t98" } { "classname" "hint_path" "spawnflags" "2048" "origin" "2248 -536 352" "targetname" "t93" "target" "t94" } { "classname" "hint_path" "spawnflags" "2048" "origin" "2232 -64 352" "targetname" "t94" "target" "t95" } { "classname" "hint_path" "spawnflags" "2048" "origin" "2488 -64 352" "targetname" "t95" "target" "t96" } { "classname" "hint_path" "spawnflags" "2048" "origin" "2488 -176 352" "targetname" "t96" "target" "t97" } { "classname" "hint_path" "spawnflags" "2049" "origin" "2880 -208 352" "targetname" "t97" } { "origin" "1856 -104 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t87" "target" "t88" } { "origin" "1856 336 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t88" "target" "t89" } { "origin" "2120 512 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t89" "target" "t90" } { "origin" "2688 512 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t90" "target" "t91" } { "origin" "2872 368 352" "spawnflags" "2048" "classname" "hint_path" "targetname" "t91" "target" "t92" } { "origin" "2880 -176 352" "spawnflags" "2049" "classname" "hint_path" "targetname" "t92" } { "classname" "hint_path" "spawnflags" "2049" "origin" "1856 -416 336" "target" "t87" } { "origin" "2384 -608 352" "spawnflags" "2049" "classname" "hint_path" "target" "t93" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t82" "target" "t83" "origin" "3400 -184 352" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t83" "target" "t84" "origin" "3392 -192 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t84" "target" "t85" "origin" "3560 -192 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t85" "target" "t86" "origin" "3552 -8 144" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t86" "origin" "3184 -8 144" } { "classname" "hint_path" "spawnflags" "2049" "target" "t82" "origin" "2896 -192 352" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t80" "target" "t81" "origin" "2800 -568 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t79" "target" "t80" "origin" "3136 -576 144" } { "spawnflags" "2049" "classname" "hint_path" "target" "t79" "origin" "3152 -240 144" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t78" "origin" "3160 -136 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t77" "target" "t78" "origin" "3104 56 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t76" "target" "t77" "origin" "2896 56 144" } { "spawnflags" "2049" "classname" "hint_path" "target" "t76" "origin" "2752 -160 144" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t81" "origin" "2752 -216 144" } { "spawnflags" "2049" "classname" "hint_path" "target" "t75" "origin" "2752 -192 144" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t75" "origin" "2496 -192 144" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t73" "target" "t74" "origin" "2368 -512 88" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t74" "origin" "2368 -1016 24" } { "spawnflags" "2049" "classname" "hint_path" "target" "t73" "origin" "2360 -192 144" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t69" "target" "t70" "origin" "1952 -1264 -184" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t70" "target" "t71" "origin" "1736 -1256 -184" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t71" "target" "t72" "origin" "1736 -1840 24" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t72" "origin" "1912 -1848 8" } { "classname" "hint_path" "spawnflags" "2049" "target" "t69" "origin" "1960 -1656 -184" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t65" "target" "t66" "origin" "2176 -1080 8" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t66" "target" "t67" "origin" "1944 -1344 8" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t67" "target" "t68" "origin" "1952 -1840 8" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t68" "origin" "2240 -2064 8" } { "classname" "hint_path" "spawnflags" "2049" "target" "t65" "origin" "2352 -1000 8" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t61" "target" "t62" "origin" "2496 -1040 8" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t62" "target" "t63" "origin" "2776 -1296 8" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t63" "target" "t64" "origin" "2792 -1744 8" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t64" "origin" "2496 -2088 8" } { "classname" "hint_path" "spawnflags" "2049" "target" "t61" "origin" "2408 -1024 8" } { "classname" "ammo_bullets" "origin" "2744 536 336" } { "classname" "ammo_slugs" "origin" "1816 352 336" } { "origin" "2456 552 336" "classname" "item_health" } { "origin" "1952 -152 144" "classname" "item_health" } { "classname" "monster_parasite" "angle" "45" "spawnflags" "1" "origin" "368 584 408" } { "classname" "ammo_shells" "origin" "1160 -16 336" } { "classname" "ammo_flechettes" // b#6: nails -> flechettes "origin" "408 216 400" } { "classname" "ammo_prox" "origin" "416 736 400" } { "classname" "ammo_tesla" "origin" "352 736 400" } { "origin" "1224 840 336" "classname" "item_health_small" } { "origin" "1224 888 336" "classname" "item_health_small" } { "origin" "1224 936 336" "classname" "item_health_small" } { "classname" "item_health_small" "origin" "1224 792 336" } { "classname" "ammo_bullets" "origin" "1432 -32 208" } { "classname" "weapon_chaingun" "origin" "1408 968 208" } { "classname" "misc_deadsoldier" "spawnflags" "2052" "origin" "1368 920 192" } { "classname" "item_health_large" "origin" "1376 -32 208" } { "classname" "item_armor_shard" "origin" "992 496 208" } { "classname" "item_armor_shard" "origin" "992 544 208" } { "classname" "item_armor_shard" "origin" "992 592 208" } { "classname" "item_armor_shard" "origin" "992 448 208" } { "spawnflags" "0" "classname" "ammo_cells" "origin" "2832 416 144" } { "classname" "ammo_rockets" "origin" "1936 440 208" } { "classname" "item_health" "origin" "2136 144 144" } { "classname" "item_health" "origin" "2088 144 144" } { "classname" "item_health" "origin" "2400 552 336" } { "classname" "item_health" "origin" "1904 -152 152" } { "classname" "item_armor_shard" "origin" "2200 -128 528" } { "classname" "item_armor_shard" "origin" "2200 -80 528" } { "classname" "item_armor_shard" "origin" "2200 -32 528" } { "classname" "item_armor_shard" "origin" "2200 -176 528" } { "classname" "item_health" "origin" "2016 -792 528" } { "classname" "ammo_prox" "origin" "2200 -736 528" } { "model" "*51" "spawnflags" "2816" "classname" "func_wall" } { "origin" "2104 -480 672" "angle" "180" "spawnflags" "776" "classname" "monster_turret" } { "classname" "ammo_cells" "origin" "2292 -1064 272" } { "classname" "ammo_cells" "origin" "2268 -1024 272" } { "classname" "ammo_shells" "origin" "2148 -476 528" } { "classname" "trigger_relay" "spawnflags" "7936" // b#5: added this "targetname" "t60" "origin" "2208 -832 688" } { "classname" "target_secret" "targetname" "t60" "message" "You found a secret!" // b#5: moved this here "origin" "2232 -840 688" } { "model" "*52" "health" "10" "classname" "func_explosive" "target" "t60" } { "classname" "target_explosion" "targetname" "t60" "origin" "2232 -856 688" } { "classname" "trigger_relay" "target" "t59" "targetname" "t31" "spawnflags" "7168" "origin" "1712 -728 520" } { "classname" "monster_parasite" "angle" "315" "spawnflags" "769" "targetname" "t31" "target" "t59" "origin" "1696 -672 536" } { "model" "*53" "classname" "func_wall" "spawnflags" "2816" } { "origin" "2368 -696 480" "angle" "90" "spawnflags" "288" "classname" "monster_turret" "targetname" "t115" } { "classname" "item_health_large" "origin" "1984 -208 400" } { "classname" "item_sphere_defender" "origin" "2024 32 336" } { "classname" "item_health" "origin" "2528 -624 336" } { "classname" "ammo_bullets" "origin" "2200 -224 336" } { "classname" "item_health" "origin" "2200 -32 336" } { "classname" "item_health" "origin" "2200 -88 336" } { "classname" "monster_infantry" "angle" "0" "spawnflags" "1" "origin" "2544 -192 344" } { "classname" "monster_parasite" "angle" "270" "spawnflags" "1" "origin" "2496 -8 344" "target" "t115" } { "classname" "ammo_cells" "origin" "2848 96 336" } { "classname" "ammo_rockets" "origin" "3488 -288 144" } { "classname" "ammo_tesla" "origin" "3488 -608 336" } { "origin" "3200 -608 144" "classname" "item_armor_shard" } { "classname" "item_armor_shard" "origin" "3152 -608 144" } { "classname" "item_armor_shard" "origin" "3104 -608 144" } { "classname" "item_armor_shard" "origin" "3248 -608 144" } { "classname" "ammo_flechettes" // b#6: nails -> flechettes "origin" "2896 104 144" } { "classname" "weapon_etf_rifle" // b#6: nailgun -> etf_rifle "origin" "2432 -112 160" } { "classname" "item_health_small" "origin" "2304 -148 144" } { "classname" "item_health_small" "origin" "2264 -148 144" } { "classname" "item_health_small" "origin" "2224 -148 144" } { "classname" "item_health_small" "origin" "2344 -148 144" } { "classname" "ammo_shells" "origin" "2336 -496 80" } { "classname" "ammo_shells" "origin" "2712 -304 144" } { "classname" "ammo_cells" "origin" "2472 -344 112" } { "classname" "monster_parasite" "angle" "90" "spawnflags" "1" "origin" "2720 -448 152" } { "classname" "monster_floater" "angle" "270" "spawnflags" "1" "origin" "2728 -48 232" } { "classname" "item_health" "origin" "2088 -1112 16" } { "classname" "item_armor_jacket" "origin" "2456 -2048 16" } { "classname" "misc_deadsoldier" "spawnflags" "2050" "origin" "2504 -2016 0" } { "spawnflags" "0" "classname" "ammo_rockets" "origin" "3328 24 144" } { "classname" "item_armor_combat" "origin" "2968 -192 144" } { "classname" "item_health_large" "origin" "3096 104 144" } { "spawnflags" "2048" "classname" "ammo_flechettes" // b#6: nails -> flechettes "origin" "3224 -672 336" } { "spawnflags" "2048" "classname" "ammo_grenades" "origin" "3224 -736 336" } { "classname" "item_health_large" "origin" "3096 152 336" } { "spawnflags" "2048" "classname" "item_health_large" "origin" "3096 224 336" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "1" "origin" "3552 -544 344" } { "classname" "monster_parasite" "angle" "270" "spawnflags" "257" "target" "t26" "origin" "3560 -216 344" } { "model" "*54" "classname" "func_wall" "spawnflags" "2304" } { "origin" "2368 -736 232" "light" "75" "classname" "light" } { "origin" "2368 -736 248" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "classname" "monster_parasite" "spawnflags" "768" "origin" "2368 -960 24" } { "classname" "monster_parasite" "angle" "180" "targetname" "t56" "spawnflags" "768" "origin" "1952 -1248 -192" } { "spawnflags" "257" "angle" "135" "classname" "monster_infantry" "origin" "2528 -2152 24" "item" "ammo_bullets" "targetname" "t57" "target" "t58" } { "classname" "monster_infantry" "angle" "45" "spawnflags" "769" "origin" "2208 -2152 24" "target" "t57" "targetname" "t58" } { "classname" "monster_parasite" "angle" "225" "targetname" "t51" "origin" "2856 -1728 24" "spawnflags" "1" } { "classname" "monster_parasite" "origin" "1888 -1696 24" "angle" "315" "targetname" "t51" "spawnflags" "1" } { "classname" "light" "light" "75" "origin" "2368 -1600 -24" } { "spawnflags" "2048" "target" "reac" "targetname" "light1" "origin" "712 1032 448" "delay" "2" "classname" "trigger_relay" } { "origin" "2856 -1640 16" "classname" "item_armor_shard" } { "origin" "2856 -1600 16" "classname" "item_armor_shard" } { "origin" "2856 -1560 16" "classname" "item_armor_shard" } { "origin" "2856 -1680 16" "classname" "item_armor_shard" } { "origin" "1720 -1472 -112" "classname" "item_health_small" } { "origin" "1720 -1424 -144" "classname" "item_health_small" } { "origin" "1720 -1376 -168" "classname" "item_health_small" } { "origin" "1720 -1520 -88" "classname" "item_health_small" } { "origin" "1944 -1960 32" "classname" "ammo_prox" } { "origin" "2000 -2456 32" "classname" "ammo_slugs" } { "origin" "2592 -2152 -240" "classname" "ammo_cells" } { "origin" "2848 -1848 -240" "classname" "item_health" } { "origin" "2848 -1792 -240" "classname" "item_health_large" } { "model" "*55" "spawnflags" "2048" "target" "t29" "classname" "trigger_once" } { "origin" "1600 552 144" "classname" "item_armor_body" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1600 -160 304" } { "model" "*56" "_minlight" ".2" "spawnflags" "2048" "wait" "-1" "targetname" "t35" "angle" "-2" "classname" "func_door" } { "origin" "1600 488 152" "angle" "270" "classname" "monster_gladiator" "item" "ammo_slugs" } { "spawnflags" "2048" "origin" "3224 -544 360" "target" "t5" "delay" "2" "targetname" "t5" "classname" "trigger_relay" } { "origin" "2720 456 128" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "spawnflags" "2048" "origin" "2792 472 144" "classname" "weapon_plasmabeam" // b#6: heat -> plasma } { "model" "*57" "spawnflags" "2048" "target" "t54" "classname" "trigger_once" } { "model" "*58" "spawnflags" "2048" "target" "t54" "classname" "trigger_once" } { "model" "*59" "spawnflags" "2048" "target" "t54" "classname" "trigger_once" } { "origin" "2656 224 280" "targetname" "t50" "spawnflags" "2050" "noise" "world/curnt3.wav" "classname" "target_speaker" } { "origin" "2656 160 280" "targetname" "t50" "spawnflags" "2050" "noise" "world/curnt3.wav" "classname" "target_speaker" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "968 216 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "968 488 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "968 712 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "1400 216 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "1400 488 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "1400 712 296" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "1184 504 456" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "targetname" "reac" "noise" "world/amb16.wav" "origin" "1184 728 456" "classname" "target_speaker" "spawnflags" "2050" "volume" "1" } { "origin" "2492 -648 76" "targetname" "t48" "classname" "target_speaker" "noise" "world/curnt3.wav" "spawnflags" "2050" } { "origin" "2496 -496 108" "targetname" "t48" "noise" "world/curnt3.wav" "classname" "target_speaker" "spawnflags" "2050" } { "origin" "2240 -496 108" "targetname" "t48" "classname" "target_speaker" "noise" "world/curnt3.wav" "spawnflags" "2050" } { "origin" "2236 -648 76" "targetname" "t48" "noise" "world/curnt3.wav" "classname" "target_speaker" "spawnflags" "2050" } { "origin" "2368 -1128 352" "spawnflags" "2050" "targetname" "t53" "noise" "world/curnt3.wav" "classname" "target_speaker" } { "origin" "2368 -1128 96" "noise" "world/curnt3.wav" "targetname" "t53" "spawnflags" "2050" "classname" "target_speaker" } { "model" "*60" "targetname" "t53" "speed" "100" "spawnflags" "2049" "angle" "-1" "classname" "func_water" } { "spawnflags" "2048" "target" "t53" "targetname" "t19" "classname" "trigger_relay" "origin" "2416 -1048 296" } { "model" "*61" "targetname" "t53" "classname" "func_water" "angle" "-1" "spawnflags" "2049" "speed" "100" } { "model" "*62" "spawnflags" "768" "classname" "func_wall" } { "origin" "1296 -56 416" "angle" "90" "spawnflags" "264" "classname" "monster_turret" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "1544 712 312" } { "style" "32" "targetname" "light2" "origin" "1464 712 312" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "1464 824 312" } { "style" "33" "spawnflags" "2048" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" "origin" "1464 712 312" } { "style" "33" "spawnflags" "2048" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" "origin" "1544 712 312" } { "style" "32" "targetname" "light2" "origin" "1544 824 312" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "style" "33" "spawnflags" "2048" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" "origin" "1464 824 312" } { "style" "33" "spawnflags" "2048" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" "origin" "1544 824 312" } { "model" "*63" "targetname" "light1" "spawnflags" "6" "classname" "func_wall" } { "style" "32" "targetname" "light2" "origin" "904 840 440" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "style" "33" "spawnflags" "2048" "origin" "904 840 440" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "824 856 440" } { "style" "33" "spawnflags" "2048" "origin" "824 840 440" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" } { "style" "32" "targetname" "light2" "origin" "824 952 440" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "style" "33" "spawnflags" "2048" "origin" "824 952 440" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" } { "style" "33" "spawnflags" "2048" "origin" "904 952 440" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "904 952 440" } { "model" "*64" "targetname" "light1" "classname" "func_wall" "spawnflags" "6" } { "style" "33" "spawnflags" "2048" "origin" "1464 8 312" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" } { "style" "33" "spawnflags" "2048" "origin" "1464 120 312" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" } { "style" "33" "spawnflags" "2048" "origin" "1544 120 312" "targetname" "light1" "classname" "light" "light" "125" "_color" "0.363636 1.000000 0.395722" } { "style" "33" "spawnflags" "2048" "origin" "1544 8 312" "targetname" "light1" "_color" "0.363636 1.000000 0.395722" "light" "125" "classname" "light" } { "style" "32" "targetname" "light2" "origin" "1464 8 312" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "1464 120 312" } { "style" "32" "targetname" "light2" "origin" "1544 120 312" "classname" "light" "spawnflags" "2049" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1184 576 272" } { "model" "*65" "targetname" "light1" "spawnflags" "6" "classname" "func_wall" } { "model" "*66" "origin" "2368 321 156" "targetname" "t18" "target" "t52" "spawnflags" "10376" "classname" "func_door_rotating" "wait" "-1" "sounds" "1" "distance" "90" } { "target" "t55" "spawnflags" "1" "origin" "2368 -216 152" "angle" "270" "classname" "monster_gladiator" "item" "ammo_slugs" } { "origin" "1856 -192 504" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "model" "*67" "spawnflags" "2816" "classname" "func_wall" } { "classname" "monster_turret" "spawnflags" "264" "angle" "0" "origin" "2824 -192 608" } { "spawnflags" "2048" "targetname" "t52" "origin" "2616 376 240" "delay" "1.5" "target" "t50" "classname" "trigger_relay" } { "style" "35" "origin" "2656 192 280" "targetname" "t50" "spawnflags" "2049" "_color" "0.000000 0.666667 1.000000" "classname" "light" } { "model" "*68" "targetname" "t50" "angle" "-1" "spawnflags" "2049" "classname" "func_water" "speed" "200" } { "spawnflags" "2048" "origin" "648 384 448" "killtarget" "pmpbrsh" "targetname" "light1" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "2632 -120 168" "target" "t42" "targetname" "t49" "classname" "trigger_relay" } { "spawnflags" "2048" "targetname" "t46" "origin" "2526 -760 24" "angle" "-1" "classname" "target_steam" "sounds" "3" "_color" "6" "speed" "75" "count" "16" } { "spawnflags" "2048" "targetname" "t46" "origin" "2506 -760 24" "angle" "-1" "classname" "target_steam" "sounds" "3" "_color" "6" "speed" "75" "count" "16" } { "spawnflags" "2048" "targetname" "t46" "angle" "-1" "classname" "target_steam" "origin" "2466 -760 24" "sounds" "3" "_color" "6" "speed" "75" "count" "16" } { "spawnflags" "2048" "targetname" "t46" "classname" "target_steam" "angle" "-1" "origin" "2486 -760 24" "sounds" "3" "_color" "6" "speed" "75" "count" "16" } { "spawnflags" "2048" "count" "40" "targetname" "t45" "classname" "target_steam" "sounds" "3" "origin" "2232 -456 88" "angle" "-1" "speed" "100" } { "spawnflags" "2048" "count" "40" "targetname" "t45" "origin" "2488 -456 88" "sounds" "3" "classname" "target_steam" "angle" "-1" "speed" "100" } { "spawnflags" "2048" "count" "16" "speed" "75" "_color" "6" "sounds" "3" "targetname" "t46" "classname" "target_steam" "angle" "-1" "origin" "2250 -760 24" } { "spawnflags" "2048" "count" "16" "speed" "75" "_color" "6" "sounds" "3" "targetname" "t46" "classname" "target_steam" "angle" "-1" "origin" "2270 -760 24" } { "spawnflags" "2048" "target" "t48" "origin" "2336 -664 160" "targetname" "t42" "classname" "trigger_relay" "delay" "1.75" } { "spawnflags" "2048" "origin" "2328 -448 160" "target" "t47" "delay" "1" "targetname" "t42" "classname" "trigger_relay" } { "spawnflags" "2048" "count" "16" "speed" "75" "_color" "6" "sounds" "3" "origin" "2230 -760 24" "targetname" "t46" "angle" "-1" "classname" "target_steam" } { "spawnflags" "2048" "count" "16" "speed" "75" "_color" "6" "sounds" "3" "origin" "2210 -760 24" "targetname" "t46" "classname" "target_steam" "angle" "-1" } { "spawnflags" "2048" "targetname" "t48" "origin" "2416 -680 160" "target" "t46" "classname" "func_timer" } { "spawnflags" "2048" "count" "40" "speed" "100" "angle" "-1" "targetname" "t45" "classname" "target_steam" "sounds" "3" "origin" "2504 -456 88" } { "spawnflags" "2048" "targetname" "t47" "origin" "2336 -496 160" "target" "t45" "classname" "func_timer" } { "spawnflags" "2048" "count" "40" "speed" "100" "angle" "-1" "origin" "2248 -456 88" "sounds" "3" "targetname" "t45" "classname" "target_steam" } { "style" "36" "spawnflags" "2048" "origin" "2464 -456 112" "targetname" "t44" "classname" "light" "light" "40" } { "style" "36" "spawnflags" "2048" "targetname" "t44" "origin" "2528 -456 112" "light" "40" "classname" "light" } { "style" "36" "spawnflags" "2049" "origin" "2272 -456 112" "targetname" "t44" "classname" "light" "light" "40" } { "style" "36" "spawnflags" "2049" "origin" "2208 -456 112" "targetname" "t44" "light" "40" "classname" "light" } { "model" "*69" "targetname" "t42" "classname" "func_water" "angle" "-2" "spawnflags" "2049" "speed" "50" } { "model" "*70" "targetname" "t42" "classname" "func_water" "angle" "-1" "spawnflags" "2049" "speed" "75" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "classname" "light" "light" "60" "origin" "2240 -424 112" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "light" "80" "classname" "light" "origin" "2240 -480 112" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "classname" "light" "light" "80" "origin" "2240 -544 104" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "classname" "light" "light" "80" "origin" "2240 -608 88" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "classname" "light" "light" "80" "origin" "2240 -672 72" } { "style" "36" "spawnflags" "2049" "targetname" "t44" "light" "80" "classname" "light" "origin" "2240 -736 56" } { "style" "36" "spawnflags" "2048" "origin" "2496 -480 112" "targetname" "t44" "classname" "light" "light" "80" } { "spawnflags" "2048" "origin" "2352 -536 112" "message" "az" "targetname" "t42" "target" "t44" "speed" "1.5" "classname" "target_lightramp" } { "style" "36" "spawnflags" "2048" "origin" "2496 -672 72" "targetname" "t44" "light" "80" "classname" "light" } { "style" "36" "spawnflags" "2048" "origin" "2496 -608 88" "targetname" "t44" "light" "80" "classname" "light" } { "style" "36" "spawnflags" "2048" "origin" "2496 -544 104" "targetname" "t44" "light" "80" "classname" "light" } { "style" "36" "spawnflags" "2049" "origin" "2496 -424 112" "targetname" "t44" "light" "60" "classname" "light" } { "style" "36" "spawnflags" "2049" "origin" "2496 -736 56" "targetname" "t44" "classname" "light" "light" "80" } { "model" "*71" "speed" "50" "spawnflags" "2049" "angle" "-2" "targetname" "t42" "classname" "func_water" } { "model" "*72" "speed" "75" "targetname" "t42" "spawnflags" "2049" "angle" "-1" "classname" "func_water" } { "spawnflags" "2048" "origin" "2360 -1808 -224" "killtarget" "stmtmr" "targetname" "t16" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "784 480 448" "killtarget" "glass" "targetname" "t36" "classname" "trigger_relay" } { "spawnflags" "2048" "origin" "796 476 452" "targetname" "glass" "classname" "info_notnull" } { "spawnflags" "2048" "origin" "2408 -976 312" "targetname" "t16" "classname" "target_goal" } { "spawnflags" "2048" "origin" "2448 -984 328" "message" "Use flooded entrance\n area to exit." "targetname" "t16" "classname" "target_help" } { "spawnflags" "2048" "origin" "656 608 448" "targetname" "t40" "classname" "target_goal" } { "spawnflags" "2048" "target" "t40" "targetname" "light1" "classname" "trigger_relay" "delay" "2" "origin" "624 512 448" } { "spawnflags" "2048" "message" "Use flow control valves\n to flood entrance area." "origin" "1736 760 320" "classname" "target_help" "targetname" "t116" } { "style" "32" "targetname" "light2" "classname" "light" "light" "175" "origin" "1256 216 172" "spawnflags" "1" } { "style" "32" "targetname" "light2" "classname" "light" "light" "175" "origin" "1256 744 172" "spawnflags" "1" } { "style" "32" "targetname" "light2" "classname" "light" "light" "175" "origin" "1112 744 172" "spawnflags" "1" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "992 896 272" } { "classname" "monster_turret" "spawnflags" "776" "angle" "0" "origin" "2184 -512 672" } { "angle" "-2" "spawnflags" "8" "classname" "monster_turret" "origin" "2880 256 504" } { "spawnflags" "2048" "origin" "672 344 448" "target" "t35" "targetname" "light1" "delay" "10" "classname" "trigger_relay" } { "origin" "2608 448 152" "spawnflags" "1" "angle" "45" "classname" "monster_infantry" } { "model" "*73" "spawnflags" "2048" "target" "t39" "classname" "trigger_once" } { "origin" "1856 768 304" "spawnflags" "1" "targetname" "t39" "angle" "180" "classname" "monster_gunner" } { "spawnflags" "2048" "targetname" "t38" "noise" "world/brkglas.wav" "origin" "792 416 456" "classname" "target_speaker" } { "spawnflags" "2048" "targetname" "t37" "classname" "target_speaker" "origin" "792 544 456" "noise" "world/brkglas.wav" } { "spawnflags" "2048" "targetname" "t36" "noise" "world/brkglas.wav" "origin" "824 480 456" "classname" "target_speaker" } { "targetname" "reac" "origin" "1184 648 712" "classname" "monster_floater" "spawnflags" "2" } { "targetname" "reac" "origin" "1184 384 712" "classname" "monster_floater" "spawnflags" "2" } { "spawnflags" "2048" "origin" "1184 648 616" "targetname" "t35" "classname" "target_explosion" } { "spawnflags" "2048" "origin" "1192 384 616" "targetname" "t35" "classname" "target_explosion" } { "model" "*74" "targetname" "t35" "classname" "func_explosive" } { "model" "*75" "targetname" "t35" "classname" "func_explosive" } { "spawnflags" "2048" "origin" "664 632 448" "target" "t35" "delay" "2" "targetname" "light1" "classname" "trigger_relay" } { "targetname" "light1" "classname" "target_speaker" "origin" "960 64 304" "spawnflags" "2052" "noise" "world/lite_on3.wav" } { "targetname" "light1" "classname" "target_speaker" "origin" "1408 64 304" "spawnflags" "2052" "noise" "world/lite_on3.wav" } { "targetname" "light1" "classname" "target_speaker" "origin" "1408 768 304" "spawnflags" "2052" "noise" "world/lite_on3.wav" } { "targetname" "light1" "classname" "target_speaker" "origin" "656 480 448" "spawnflags" "2052" "noise" "world/lite_on3.wav" } { "targetname" "t35" "attenuation" "-1" "classname" "target_speaker" "origin" "648 488 448" "spawnflags" "2054" "noise" "world/klaxon1.wav" } { "targetname" "light1" "noise" "world/lite_on3.wav" "spawnflags" "2052" "origin" "960 768 304" "classname" "target_speaker" } { "model" "*76" "dmg" "10000" "spawnflags" "8" "classname" "trigger_hurt" } { "model" "*77" "dmg" "10000" "spawnflags" "2057" "classname" "trigger_hurt" } { "origin" "1248 432 256" "classname" "light" "light" "100" } { "origin" "1256 528 256" "classname" "light" "light" "100" } { "origin" "1104 528 256" "light" "100" "classname" "light" } { "origin" "1096 432 256" "light" "100" "classname" "light" } { "origin" "680 704 392" "targetname" "t34" "classname" "point_combat" "spawnflags" "2049" } { "origin" "688 672 408" "target" "t34" "classname" "monster_infantry" "angle" "0" "spawnflags" "1" } { "origin" "680 320 392" "targetname" "t33" "spawnflags" "2049" "classname" "point_combat" } { "origin" "688 288 408" "target" "t33" "spawnflags" "1" "angle" "0" "classname" "monster_infantry" } { "targetname" "t36" "origin" "576 896 376" "spawnflags" "1" "angle" "0" "classname" "monster_gunner" } { "origin" "1184 896 216" "spawnflags" "1" "angle" "0" "classname" "monster_infantry" } { "classname" "monster_turret" "spawnflags" "8" "angle" "270" "origin" "1296 1016 416" } { "origin" "1072 -56 416" "angle" "90" "spawnflags" "8" "classname" "monster_turret" } { "classname" "monster_turret" "spawnflags" "800" "angle" "-2" "origin" "1184 512 632" } { "origin" "1184 -192 344" "angle" "90" "spawnflags" "1" "classname" "monster_gladiator" } { "target" "t51" "origin" "2368 -1768 24" "angle" "270" "spawnflags" "800" "classname" "monster_turret" } { "origin" "1832 152 152" "spawnflags" "1" "angle" "45" "classname" "monster_gladiator" } { "targetname" "t54" "origin" "2368 360 388" "angle" "90" "spawnflags" "1" "classname" "monster_daedalus" "item" "ammo_cells" } { "origin" "2072 -192 152" "angle" "0" "classname" "monster_infantry" "spawnflags" "1" } { "angle" "180" "origin" "2048 -712 536" "spawnflags" "1" "classname" "monster_infantry" "targetname" "t59" } { "origin" "2048 -664 536" "spawnflags" "769" "angle" "180" "classname" "monster_infantry" "targetname" "t59" "item" "ammo_bullets" } { "angle" "180" "origin" "1992 -688 536" "spawnflags" "257" "classname" "monster_infantry" "targetname" "t59" "item" "ammo_bullets" } { "origin" "1856 384 344" "targetname" "t32" "spawnflags" "1" "angle" "270" "classname" "monster_gunner" } { "origin" "1952 32 344" "spawnflags" "1" "angle" "180" "classname" "monster_infantry" "item" "ammo_bullets" } { "origin" "2008 -352 312" "target" "t32" "spawnflags" "1" "angle" "270" "classname" "monster_infantry" } { "origin" "2240 -576 440" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" "targetname" "t115" } { "spawnflags" "257" "origin" "1952 -832 536" "target" "t31" "angle" "0" "classname" "monster_gladiator" } { "origin" "2496 -72 536" "spawnflags" "1" "targetname" "t30" "angle" "270" "classname" "monster_gunner" } { "origin" "2320 -408 792" "targetname" "t31" "angle" "270" "classname" "monster_daedalus" "spawnflags" "1" } { "origin" "2240 -792 440" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "spawnflags" "2048" "origin" "3624 -152 344" "light" "75" "classname" "light" } { "spawnflags" "2048" "origin" "2848 -1688 -224" "light" "75" "classname" "light" } { "spawnflags" "2048" "origin" "2320 -1032 0" "classname" "misc_deadsoldier" } { "origin" "2912 -616 344" "spawnflags" "1" "angle" "45" "classname" "monster_infantry" "item" "ammo_bullets" } { "classname" "monster_turret" "spawnflags" "264" "angle" "270" "origin" "1072 1016 416" } { "classname" "monster_turret" "spawnflags" "8" "angle" "-2" "origin" "2368 -1600 -8" "targetname" "t29" } { "model" "*78" "spawnflags" "2048" "target" "t29" "classname" "trigger_once" } { "spawnflags" "1" "targetname" "t29" "origin" "1872 -1248 -192" "angle" "180" "classname" "monster_infantry" "target" "t56" } { "target" "t30" "origin" "2480 -640 344" "spawnflags" "1" "angle" "180" "classname" "monster_infantry" } { "classname" "light" "light" "100" "origin" "2656 120 176" } { "classname" "light" "light" "100" "origin" "2728 192 176" } { "origin" "2584 192 176" "light" "100" "classname" "light" } { "origin" "2416 -8 272" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "2240 120 384" } { "origin" "2240 192 456" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "2240 192 312" } { "origin" "2240 264 384" "light" "100" "classname" "light" } { "spawnflags" "2048" "origin" "2720 512 328" "target" "t28" "targetname" "t27" "classname" "path_corner" } { "spawnflags" "2048" "origin" "2016 512 328" "targetname" "t28" "target" "t27" "classname" "path_corner" } { "origin" "2680 512 344" "angle" "180" "target" "t27" "classname" "monster_gunner" "item" "ammo_grenades" } { "origin" "2496 -792 440" "angle" "-2" "spawnflags" "8" "classname" "monster_turret" } { "origin" "3096 -40 152" "targetname" "t25" "target" "t24" "spawnflags" "1" "angle" "135" "classname" "monster_infantry" } { "origin" "3040 -448 152" "target" "t25" "targetname" "t24" "spawnflags" "1" "angle" "270" "classname" "monster_infantry" } { "origin" "2880 -192 152" "angle" "180" "classname" "monster_gladiator" "item" "ammo_slugs" "spawnflags" "769" } { "targetname" "t26" "spawnflags" "1" "origin" "3416 0 344" "angle" "180" "classname" "monster_gunner" } { "origin" "3264 -704 376" "targetname" "t5" "classname" "monster_hover" "angle" "90" "spawnflags" "1026" } { "origin" "3064 192 376" "targetname" "t5" "spawnflags" "1026" "angle" "270" "classname" "monster_hover" } { "model" "*79" "spawnflags" "2048" "message" "Lift is inactive." "classname" "trigger_once" "targetname" "brusher" } { "model" "*80" "spawnflags" "2048" "message" "Lift activated." "wait" "-1" "target" "t23" "angle" "0" "classname" "func_button" } { "targetname" "t7" "origin" "3432 -192 576" "spawnflags" "2" "angle" "180" "classname" "monster_daedalus" } { "origin" "1816 -192 184" "spawnflags" "1" "angle" "0" "classname" "monster_gunner" "target" "t21" } { "spawnflags" "2048" "origin" "1600 -192 216" "target" "t22" "targetname" "t21" "classname" "point_combat" } { "origin" "1600 64 216" "angle" "90" "spawnflags" "2049" "targetname" "t22" "classname" "point_combat" } { "targetname" "t55" "origin" "2520 -616 216" "classname" "monster_floater" "angle" "180" "spawnflags" "1" } { "targetname" "t55" "origin" "2216 -616 216" "spawnflags" "769" "angle" "0" "classname" "monster_floater" } { "origin" "640 288 504" "classname" "light" "light" "150" } { "model" "*81" "spawnflags" "2048" "message" "Filtration sector opened." "target" "t20" "wait" "-1" "angle" "0" "classname" "func_button" } { "model" "*82" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "targetname" "t16" "wait" "-1" } { "model" "*83" "targetname" "t8" "classname" "func_wall" "spawnflags" "7" } { "model" "*84" "targetname" "t8" "classname" "func_wall" "spawnflags" "7" } { "model" "*85" "targetname" "t8" "spawnflags" "7" "classname" "func_wall" } { "origin" "2464 -72 128" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "model" "*86" "targetname" "t16" "spawnflags" "2049" "classname" "func_wall" } { "model" "*87" "spawnflags" "2048" "targetname" "t17" "target" "t16" "killtarget" "lavasnd" // b#2: added this "count" "3" "classname" "trigger_counter" } { "angle" "270" "targetname" "sew1end" "origin" "2344 -1432 -232" "classname" "info_player_coop" } { "angle" "270" "targetname" "sew1end" "origin" "2392 -1352 -232" "classname" "info_player_coop" } { "angle" "270" "targetname" "sew1end" "origin" "2344 -1344 -232" "classname" "info_player_coop" } { "targetname" "sew1end" "angle" "270" "origin" "2392 -1440 -232" "classname" "info_player_coop" } { "targetname" "rhangar1" "origin" "2016 -2760 40" "angle" "90" "classname" "info_player_start" } { "spawnflags" "2048" "origin" "2368 -1256 -224" "targetname" "t15" "map" "rsewer2$sew2start" "classname" "target_changelevel" } { "model" "*88" "spawnflags" "2048" "target" "t15" "classname" "trigger_multiple" "angle" "90" } { "origin" "2000 -2400 32" "classname" "ammo_tesla" } { "classname" "item_health_large" "origin" "2168 -2368 32" } { "origin" "2216 -2368 32" "classname" "item_health_large" } { "origin" "2792 -1648 -192" "spawnflags" "1" "angle" "225" "classname" "monster_floater" } { "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "2848 -1600 -208" } { "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "2088 -704 560" } { "origin" "2528 -1056 24" "target" "t13" "targetname" "t12" "classname" "monster_gunner" "angle" "315" "spawnflags" "1" "item" "ammo_grenades" } { "origin" "2208 -1056 24" "targetname" "t13" "target" "t12" "spawnflags" "1" "angle" "225" "classname" "monster_gunner" } { "model" "*89" "targetname" "t16" "classname" "func_explosive" "spawnflags" "256" } { "targetname" "t16" "origin" "2208 -1696 36" "spawnflags" "392" "angle" "-2" "classname" "monster_turret" } { "targetname" "t16" "angle" "-2" "origin" "2528 -1696 36" "spawnflags" "136" "classname" "monster_turret" } { "origin" "1952 -1440 224" "targetname" "t11" "angle" "-2" "spawnflags" "160" "classname" "monster_turret" } { "model" "*90" "spawnflags" "2048" "target" "t11" "classname" "trigger_once" } { "model" "*91" "spawnflags" "2048" "target" "t10" "classname" "trigger_once" } { "model" "*92" "wait" "-1" "targetname" "t10" "classname" "func_door" "angle" "180" } { "model" "*93" "wait" "-1" "targetname" "t10" "classname" "func_door" "angle" "0" } { "model" "*94" "wait" "-1" "targetname" "t11" "angle" "0" "classname" "func_door" } { "model" "*95" "wait" "-1" "targetname" "t11" "angle" "180" "classname" "func_door" } { "origin" "2784 -1604 -240" "classname" "weapon_hyperblaster" } { "origin" "2840 -1596 -256" "angle" "180" "spawnflags" "2064" "classname" "misc_deadsoldier" } { "origin" "2264 -1008 16" "classname" "weapon_rocketlauncher" } { "spawnflags" "160" "targetname" "t10" "origin" "2784 -1440 224" "angle" "-2" "classname" "monster_turret" } { "angle" "90" "spawnflags" "257" "origin" "2528 -2150 -112" "classname" "monster_daedalus" } { "angle" "90" "spawnflags" "1" "origin" "2208 -2150 -112" "classname" "monster_daedalus" } { "origin" "1840 -680 576" "message" "Find and activate reactor\n to start filtration system." "spawnflags" "2048" "classname" "target_help" "targetname" "t8" } { "origin" "2064 -2392 64" "message" "Gain access to the\n Waste Disposal plant." "spawnflags" "2049" "targetname" "t9" "classname" "target_help" } { "model" "*96" "spawnflags" "2048" "target" "t9" "classname" "trigger_once" } { "targetname" "rhangar1" "origin" "1992 -2616 40" "classname" "info_player_coop" "angle" "90" } { "targetname" "rhangar1" "origin" "2040 -2648 40" "classname" "info_player_coop" "angle" "90" } { "targetname" "rhangar1" "origin" "1992 -2672 40" "classname" "info_player_coop" "angle" "90" } { "targetname" "rhangar1" "origin" "2040 -2584 40" "classname" "info_player_coop" "angle" "90" } { "targetname" "sew1end" "classname" "info_player_start" "angle" "270" "origin" "2368 -1392 -232" } { "model" "*97" "spawnflags" "2048" "targetname" "pmpbrsh" "message" "Pumping systems inactive." "classname" "trigger_multiple" "wait" "60" } { "model" "*98" "spawnflags" "2048" "targetname" "pmpbrsh" "message" "Pumping systems inactive." "classname" "trigger_multiple" "wait" "60" } { "model" "*99" "spawnflags" "2048" "targetname" "pmpbrsh" "classname" "trigger_multiple" "message" "Pumping systems inactive." "wait" "60" } { "model" "*100" "origin" "2368 -1079 292" "sounds" "1" "wait" "-1" "target" "t19" "targetname" "t18" "classname" "func_door_rotating" "spawnflags" "10376" "distance" "90" } { "origin" "2560 608 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "model" "*101" "_minlight" ".2" "classname" "func_plat2" "lip" "16" } { "origin" "1184 -192 432" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1184 -96 272" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1760 320 240" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1792 768 366" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1600 768 318" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1760 -192 278" } { "light" "150" "classname" "light" "origin" "912 896 480" } { "origin" "2792 -1576 -208" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" } { "model" "*102" "spawnflags" "2048" "target" "t37" "health" "1" "classname" "func_explosive" } { "model" "*103" "spawnflags" "2048" "target" "t36" "health" "1" "classname" "func_explosive" } { "origin" "912 -16 368" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "976 -16 368" } { "origin" "1456 -16 368" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1392 -16 368" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1456 976 368" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2528 -736 112" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2208 -736 112" } { "origin" "1600 64 304" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "light" "150" "classname" "light" "origin" "1184 -48 480" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1184 896 272" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1184 64 272" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2560 704 304" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2560 704 432" } { "origin" "1184 136 248" "classname" "light" "spawnflags" "4096" "light" "75" "_color" "1.000000 0.000000 0.000000" } { "origin" "1296 288 272" "classname" "light" "spawnflags" "4096" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "origin" "576 896 464" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "816 896 432" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1600 288 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "light" "125" "classname" "light" "origin" "2368 -964 160" } { "light" "150" "classname" "light" "origin" "384 672 504" } { "origin" "736 480 440" "classname" "light" "light" "100" } { "origin" "416 336 504" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "640 672 504" } { "origin" "1152 896 480" "classname" "light" "light" "150" } { "origin" "1184 448 568" "classname" "light" "light" "150" } { "origin" "2112 608 432" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "style" "32" "spawnflags" "1" "targetname" "light2" "origin" "1112 216 172" "light" "175" "classname" "light" } { "origin" "1600 512 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1952 -192 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2144 -192 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "model" "*104" "spawnflags" "2048" "target" "t38" "classname" "func_explosive" "health" "1" } { "model" "*105" "targetname" "t23" "classname" "func_plat2" "lip" "16" "spawnflags" "2049" } { "model" "*106" "spawnflags" "2048" "classname" "func_wall" } { "model" "*107" "classname" "func_wall" "spawnflags" "2048" } { "spawnflags" "2048" "classname" "target_lightramp" "message" "az" "speed" "10" "targetname" "light1" "target" "light2" "origin" "1016 416 248" } { "model" "*108" "spawnflags" "2048" "message" "Reactor activated." "classname" "func_button" "angle" "90" "target" "light1" "wait" "-1" } { "style" "32" "origin" "1248 576 208" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1248 480 208" "targetname" "light2" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1248 384 208" "targetname" "light2" } { "style" "32" "origin" "1120 384 208" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "32" "origin" "1120 480 208" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1120 576 208" "targetname" "light2" } { "style" "32" "origin" "1184 576 272" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1184 480 272" "targetname" "light2" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1184 384 272" "targetname" "light2" } { "style" "32" "origin" "1184 480 144" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "style" "32" "origin" "1184 384 144" "classname" "light" "spawnflags" "4097" "light" "150" "_color" "1.000000 0.000000 0.000000" "targetname" "light2" } { "origin" "1040 288 200" "classname" "light" "spawnflags" "4096" "light" "200" "_color" "1.000000 0.000000 0.000000" } { "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "4096" "classname" "light" "origin" "1072 288 272" } { "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "4096" "classname" "light" "origin" "1072 672 272" } { "classname" "light" "spawnflags" "4096" "light" "200" "_color" "1.000000 0.000000 0.000000" "origin" "1040 672 200" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "4097" "classname" "light" "origin" "1184 576 144" "targetname" "light2" } { "_color" "1.000000 0.000000 0.000000" "light" "75" "spawnflags" "4096" "classname" "light" "origin" "1184 824 248" } { "classname" "light" "spawnflags" "4096" "light" "200" "_color" "1.000000 0.000000 0.000000" "origin" "1328 288 200" } { "style" "32" "targetname" "light2" "_color" "1.000000 0.000000 0.000000" "light" "200" "spawnflags" "2049" "classname" "light" "origin" "1544 8 312" } { "classname" "light" "spawnflags" "4096" "light" "200" "_color" "1.000000 0.000000 0.000000" "origin" "1296 672 272" } { "model" "*109" "origin" "1184 432 208" "speed" "500" "spawnflags" "8202" "classname" "func_rotating" "targetname" "light1" "accel" "12" "decel" "12" "_minlight" ".2" } { "model" "*110" "origin" "1184 528 208" "classname" "func_rotating" "spawnflags" "8200" "speed" "500" "targetname" "light1" "accel" "12" "decel" "12" "_minlight" ".2" } { "origin" "3608 -256 368" "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "100" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2416 -1104 432" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2368 -1072 432" } { "origin" "2144 -512 624" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1760 -624 432" } { "origin" "2256 -624 624" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2048 -624 624" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1920 -608 624" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2016 -384 384" } { "origin" "1720 -872 608" "light" "50" "classname" "light" } { "origin" "1928 -872 608" "light" "50" "classname" "light" } { "origin" "1928 -792 608" "light" "50" "classname" "light" } { "origin" "1864 -728 608" "light" "50" "classname" "light" } { "origin" "1784 -728 608" "light" "50" "classname" "light" } { "origin" "1824 -864 608" "light" "50" "classname" "light" } { "origin" "1824 -776 608" "light" "50" "classname" "light" } { "origin" "1792 -624 624" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum2.wav" "origin" "1848 -288 392" "targetname" "t8" } { "spawnflags" "2049" "origin" "1848 -288 344" "noise" "world/l_hum2.wav" "classname" "target_speaker" "targetname" "t8" } { "classname" "target_speaker" "noise" "world/l_hum2.wav" "origin" "2144 -200 160" "spawnflags" "2049" "targetname" "t8" } { "origin" "2144 -200 208" "noise" "world/l_hum2.wav" "classname" "target_speaker" "spawnflags" "2049" "targetname" "t8" } { "classname" "target_speaker" "noise" "world/l_hum2.wav" "origin" "2872 160 200" "spawnflags" "2049" "targetname" "t8" } { "origin" "2872 160 152" "noise" "world/l_hum2.wav" "classname" "target_speaker" "spawnflags" "2049" "targetname" "t8" } { "spawnflags" "2048" "noise" "world/lasoff1.wav" "classname" "target_speaker" "targetname" "t8" "origin" "2888 152 144" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lasoff1.wav" "targetname" "t8" "origin" "2888 160 200" } { "spawnflags" "2048" "noise" "world/lasoff1.wav" "classname" "target_speaker" "targetname" "t8" "origin" "1864 -296 352" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lasoff1.wav" "targetname" "t8" "origin" "1864 -288 392" } { "spawnflags" "2048" "noise" "world/lasoff1.wav" "classname" "target_speaker" "targetname" "t8" "origin" "2152 -184 216" } { "spawnflags" "2048" "noise" "world/lasoff1.wav" "classname" "target_speaker" "targetname" "t8" "origin" "1936 -616 552" } { "spawnflags" "2048" "noise" "world/lasoff1.wav" "classname" "target_speaker" "targetname" "t8" "origin" "1904 -616 552" } { "spawnflags" "2048" "classname" "target_speaker" "noise" "world/lasoff1.wav" "targetname" "t8" "origin" "2144 -184 160" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "origin" "2880 160 224" "light" "100" "classname" "light" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "origin" "2880 160 184" "light" "100" "classname" "light" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "classname" "light" "light" "100" "origin" "2880 160 144" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "origin" "1856 -288 416" "light" "100" "classname" "light" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "origin" "1856 -288 376" "light" "100" "classname" "light" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "_color" "0.239437 1.000000 0.201878" "classname" "light" "light" "100" "origin" "1856 -288 336" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "classname" "light" "light" "100" "origin" "2144 -192 184" "_color" "0.239437 1.000000 0.201878" "targetname" "t8" } { "style" "37" "spawnflags" "2048" "classname" "light" "light" "100" "origin" "2144 -192 224" "_color" "0.239437 1.000000 0.201878" "targetname" "t8" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1856 -288 432" } { "origin" "2144 -832 624" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "classname" "light" "light" "50" "origin" "1720 -792 608" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2368 -736 432" } { "origin" "2320 -1104 432" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2624 -192 432" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "model" "*111" "spawnflags" "2048" "classname" "func_button" "angle" "90" "target" "t8" "message" "Security lasers deactivated." "wait" "-1" } { "model" "*112" "targetname" "t16" "classname" "func_water" "spawnflags" "2049" "angle" "-2" "speed" "25" } { "model" "*113" "classname" "func_wall" "spawnflags" "2048" } { "model" "*114" "lip" "16" "classname" "func_plat2" "_minlight" ".2" "spawnflags" "1" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2496 -240 432" } { "dmg" "10000" "origin" "2936 160 224" "classname" "target_laser" "spawnflags" "2053" "angle" "180" "targetname" "t8" } { "dmg" "10000" "origin" "2936 160 184" "classname" "target_laser" "spawnflags" "2053" "angle" "180" "targetname" "t8" } { "dmg" "10000" "origin" "2936 160 144" "angle" "180" "spawnflags" "2053" "classname" "target_laser" "targetname" "t8" } { "classname" "light" "light" "100" "origin" "1984 264 592" } { "classname" "light" "light" "100" "origin" "1912 192 592" } { "origin" "1984 120 592" "light" "100" "classname" "light" } { "origin" "2056 192 592" "light" "100" "classname" "light" } { "origin" "2728 192 464" "light" "100" "classname" "light" } { "origin" "3320 -400 176" "light" "100" "classname" "light" } { "origin" "3392 -472 176" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "3392 -328 176" } { "dmg" "10000" "origin" "2144 -136 224" "classname" "target_laser" "spawnflags" "2053" "angle" "270" "targetname" "t8" } { "dmg" "10000" "origin" "2144 -136 184" "classname" "target_laser" "spawnflags" "2053" "angle" "270" "targetname" "t8" } { "dmg" "10000" "origin" "2144 -136 144" "angle" "270" "spawnflags" "2053" "classname" "target_laser" "targetname" "t8" } { "angle" "180" "spawnflags" "2053" "classname" "target_laser" "origin" "1912 -288 376" "dmg" "10000" "targetname" "t8" } { "angle" "180" "spawnflags" "2053" "classname" "target_laser" "origin" "1912 -288 416" "dmg" "10000" "targetname" "t8" } { "classname" "target_laser" "spawnflags" "2053" "angle" "180" "origin" "1912 -288 336" "dmg" "10000" "targetname" "t8" } { "model" "*115" "spawnflags" "2048" "classname" "trigger_once" "target" "t7" } { "model" "*116" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "targetname" "t7" "wait" "-1" "speed" "300" } { "style" "37" "spawnflags" "2048" "origin" "2144 -192 144" "light" "100" "classname" "light" "_color" "0.239437 1.000000 0.201878" "targetname" "t8" } { "classname" "light" "light" "100" "origin" "3456 96 416" } { "origin" "3456 96 396" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "3456 96 440" } { "classname" "light" "light" "100" "origin" "3400 120 392" } { "_color" "1.000000 0.221277 0.221277" "origin" "3424 72 368" "light" "50" "classname" "light" } { "origin" "3456 96 460" "light" "100" "classname" "light" } { "light" "100" "_color" "0.000000 0.501961 1.000000" "classname" "light" "origin" "640 216 432" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "3064 208 424" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "3264 -720 432" } { "spawnflags" "2048" "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "3392 -192 432" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2880 160 240" } { "origin" "3360 -192 592" "_color" "1.000000 0.771429 0.297959" "light" "175" "classname" "light" } { "origin" "2784 -192 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2624 -192 240" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "3128 120 392" "light" "100" "classname" "light" } { "origin" "3200 56 456" "light" "100" "classname" "light" } { "classname" "light" "light" "50" "origin" "3488 72 368" "_color" "1.000000 0.221277 0.221277" } { "classname" "light" "light" "100" "origin" "3200 56 176" } { "classname" "light" "light" "100" "origin" "3320 -400 592" } { "classname" "light" "light" "100" "origin" "2584 192 464" } { "classname" "light" "light" "100" "origin" "2656 264 464" } { "origin" "2656 120 464" "light" "100" "classname" "light" } { "origin" "3392 -472 592" "light" "100" "classname" "light" } { "origin" "3464 -400 592" "light" "100" "classname" "light" } { "origin" "3328 56 456" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "3392 -328 592" } { "origin" "3128 120 176" "light" "100" "classname" "light" } { "origin" "3328 56 176" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "3400 120 176" } { "model" "*117" "spawnflags" "2048" "classname" "trigger_once" "target" "t6" } { "model" "*118" "spawnflags" "2048" "classname" "func_door" "angle" "-2" "targetname" "t6" "wait" "-1" "speed" "300" } { "model" "*119" "classname" "func_door" "angle" "-1" "targetname" "t5" "wait" "-1" "spawnflags" "2048" } { "model" "*120" "spawnflags" "2048" "classname" "trigger_once" "target" "t5" } { "spawnflags" "2048" "volume" ".5" "classname" "target_speaker" "noise" "world/steam1.wav" "targetname" "t1" "origin" "2448 -1888 -320" } { "spawnflags" "2048" "volume" ".5" "noise" "world/steam1.wav" "classname" "target_speaker" "targetname" "t1" "origin" "2466 -1594 -308" } { "spawnflags" "2048" "volume" ".5" "classname" "target_speaker" "noise" "world/lava1.wav" "targetname" "t2" "origin" "2576 -1728 -320" } { "spawnflags" "2048" "volume" ".5" "noise" "world/lava1.wav" "classname" "target_speaker" "targetname" "t4" "origin" "2208 -1600 -320" } { "spawnflags" "2048" "volume" ".5" "classname" "target_speaker" "targetname" "t3" "noise" "world/lava1.wav" "origin" "2248 -1856 -320" } { "spawnflags" "2048" "dmg" "25" "count" "16" "sounds" "5" "classname" "target_splash" "targetname" "t4" "origin" "2232 -1592 -376" } { "classname" "func_timer" "spawnflags" "2049" "target" "t4" "targetname" "lavasnd" // b#2: added this "wait" "10" "origin" "2208 -1584 -320" "random" "2" } { "spawnflags" "2048" "dmg" "25" "count" "16" "sounds" "5" "classname" "target_splash" "targetname" "t3" "origin" "2264 -1840 -376" } { "classname" "func_timer" "spawnflags" "2049" "target" "t3" "targetname" "lavasnd" // b#2: added this "random" "3" "wait" "7" "origin" "2240 -1832 -320" } { "spawnflags" "2049" "classname" "func_timer" "target" "t2" "targetname" "lavasnd" // b#2: added this "wait" "5" "random" "3" "origin" "2544 -1752 -320" } { "spawnflags" "2048" "classname" "target_splash" "sounds" "5" "count" "16" "dmg" "25" "targetname" "t2" "origin" "2568 -1760 -376" } { "spawnflags" "2048" "sounds" "2" "wait" "1" "angle" "270" "classname" "target_steam" "targetname" "t1" "origin" "2466 -1582 -308" } { "targetname" "stmtmr" "classname" "func_timer" "spawnflags" "2049" "target" "t1" "origin" "2488 -1880 -320" } { "spawnflags" "2048" "sounds" "2" "classname" "target_steam" "angle" "90" "targetname" "t1" "wait" "1" "origin" "2448 -1892 -320" } { "origin" "2464 -1536 -192" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2368 -1528 -96" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2312 -864 24" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1984 768 414" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1392 976 368" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2424 -864 24" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2728 -1440 24" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "2840 -1440 24" "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" } { "origin" "1960 -1224 24" "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" } { "origin" "2152 -1032 24" "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2584 -1032 24" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2600 -1208 24" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2776 -1224 24" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "2272 -1536 -192" } { "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" "origin" "2136 -1208 24" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "3392 -192 224" } { "_color" "1.000000 0.771429 0.297959" "light" "100" "classname" "light" "origin" "2008 -1440 24" } { "classname" "light" "light" "100" "_color" "1.000000 0.771429 0.297959" "origin" "1896 -1440 24" } { "light" "125" "classname" "light" "origin" "2016 -2400 112" } { "light" "125" "classname" "light" "origin" "2208 -2400 112" } { "light" "125" "classname" "light" "origin" "2368 -2400 112" } { "light" "125" "classname" "light" "origin" "2368 -2208 112" } { "light" "75" "classname" "light" "origin" "1824 -1840 112" } { "classname" "light" "light" "75" "origin" "1952 -1312 -120" } { "classname" "light" "light" "75" "origin" "1824 -1248 -120" } { "classname" "light" "light" "75" "origin" "1736 -1376 -96" } { "origin" "1736 -1568 8" "classname" "light" "light" "75" } { "origin" "1736 -1760 112" "classname" "light" "light" "75" } { "origin" "2016 -2584 112" "classname" "light" "light" "125" } { "origin" "1952 -1504 -120" "light" "75" "classname" "light" } { "model" "*121" "message" "Filtration sector access denied!" "spawnflags" "2048" "_minlight" ".2" "wait" "-1" "targetname" "t20" "angle" "-2" "classname" "func_door" }rogue-ROGUE_2_13/stuff/mapfixes/rsewer2.ent000066400000000000000000003165171477320066100206710ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Fixed broken path chain for monster_soldier_light (4712) // (fix suggested by NightFright2k19 on github) // // The last path_corner (3431) has target t215 but no entity // has that targetname. Fixed by clearing the target field. // // 2. Fixed tagetname typos { "sky" "rogue1" "sounds" "7" "message" "Waste Disposal" "classname" "worldspawn" "nextmap" "rhangar2" } { "model" "*1" "classname" "func_door" "angle" "-1" "targetname" "t122" "wait" "-1" "speed" "150" } { "classname" "trigger_relay" "targetname" "t276" "target" "t320" "origin" "2600 936 328" } { "classname" "ammo_prox" "origin" "-168 728 144" } { "classname" "ammo_rockets" "origin" "488 1832 80" } { "classname" "item_pack" "origin" "792 1632 -80" } { "classname" "ammo_rockets" "origin" "1120 1568 -112" } { "classname" "ammo_grenades" "origin" "944 -936 -240" } { "classname" "ammo_slugs" "origin" "800 -344 -112" } { "origin" "-2088 1192 -264" "noise" "world/comp_hum2.wav" "spawnflags" "1" "classname" "target_speaker" } { "model" "*2" "spawnflags" "2048" "classname" "func_wall" } { "model" "*3" "spawnflags" "5888" "classname" "func_wall" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum2.wav" "origin" "1480 -40 -24" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum3.wav" "origin" "2800 -448 -400" } { "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" "origin" "-2152 864 -264" } { "origin" "-2088 608 -240" "classname" "target_speaker" "spawnflags" "1" "noise" "world/comp_hum1.wav" } { "origin" "1472 -152 -24" "noise" "world/comp_hum1.wav" "spawnflags" "1" "classname" "target_speaker" } { "origin" "1128 680 -112" "spawnflags" "2048" "classname" "target_splash" } { "origin" "1184 728 -112" "targetname" "t326" "classname" "target_splash" "angle" "135" } { "origin" "1072 712 -112" "random" "1.5" "wait" "6" "spawnflags" "2049" "target" "t326" "classname" "func_timer" } { "origin" "1192 680 -88" "targetname" "t326" "angle" "0" "classname" "target_splash" } { "model" "*4" "targetname" "t106" "classname" "func_explosive" } { "model" "*5" "spawnflags" "2048" "classname" "func_wall" } { "model" "*6" "classname" "func_wall" "spawnflags" "7" "targetname" "t263" } { "origin" "16 -960 -264" "angles" "-15 45 0" "classname" "info_player_intermission" } { "classname" "func_timer" "target" "t325" "spawnflags" "1" "wait" "2" "random" ".5" "targetname" "t123" "origin" "3000 -616 -384" } { "classname" "target_splash" "sounds" "1" "angle" "180" "targetname" "t325" "origin" "3032 -576 -384" } { "origin" "448 1384 -8" "noise" "world/fan1.wav" "spawnflags" "2050" "classname" "target_speaker" "targetname" "t269" } { "model" "*7" "classname" "trigger_once" "spawnflags" "2048" "target" "t324" } { "classname" "target_speaker" "origin" "1192 -984 -192" "spawnflags" "2048" "noise" "world/voice7.wav" "targetname" "t324" "attenuation" "-1" } { "model" "*8" "spawnflags" "2048" "classname" "trigger_once" "target" "t323" } { "noise" "world/v_bas6.wav" "spawnflags" "2048" "origin" "640 -168 -64" "classname" "target_speaker" "targetname" "t323" "attenuation" "-1" } { "model" "*9" "spawnflags" "2048" "classname" "trigger_once" "target" "t322" } { "noise" "world/unit1_02.wav" "spawnflags" "2048" "origin" "-768 880 -64" "classname" "target_speaker" "targetname" "t322" "attenuation" "-1" } { "classname" "target_speaker" "targetname" "t321" "origin" "136 1928 -256" "spawnflags" "2048" "noise" "world/unit3_04.wav" "attenuation" "-1" } { "model" "*10" "classname" "trigger_once" "target" "t321" "spawnflags" "2048" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "-340 1244 -492" } { "classname" "weapon_heatbeam" "spawnflags" "5888" "origin" "-320 1184 -492" } { "model" "*11" "classname" "func_water" "spawnflags" "5888" } { "origin" "288 1312 -512" "killtarget" "fantrig" "targetname" "t269" "classname" "trigger_relay" "spawnflags" "2048" } { "model" "*12" "message" "Ventilation fan inactive." "targetname" "fantrig" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*13" "target" "t319" "spawnflags" "5888" "classname" "trigger_once" } { "model" "*14" "target" "t275" "targetname" "t319" "spawnflags" "5888" "classname" "trigger_once" } { "model" "*15" "target" "t319" "spawnflags" "5888" "classname" "trigger_once" } { "model" "*16" "angle" "-1" "targetname" "t269" "spawnflags" "2" "classname" "trigger_push" } { "model" "*17" "target" "t318" "classname" "func_button" "angle" "0" } { "model" "*18" "target" "t318" "angle" "0" "classname" "func_button" } { "model" "*19" "spawnflags" "2048" "classname" "func_wall" } { "classname" "weapon_hyperblaster" "spawnflags" "5888" "origin" "1216 1984 -496" } { "origin" "-1944 1168 -272" "classname" "ammo_tesla" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "-2080 608 -272" } { "classname" "weapon_hyperblaster" "spawnflags" "5888" "origin" "-1960 608 -272" } { "classname" "item_sphere_hunter" "spawnflags" "5888" "origin" "-2048 896 -272" } { "classname" "ammo_flechettes" "origin" "-96 1184 -48" } { "classname" "item_sphere_vengeance" "spawnflags" "5888" "origin" "448 1408 -40" } { "classname" "ammo_bullets" "spawnflags" "5888" "origin" "64 960 144" } { "classname" "weapon_chaingun" "spawnflags" "5888" "origin" "32 1024 144" } { "classname" "weapon_proxlauncher" "spawnflags" "5888" "origin" "-784 1624 -96" } { "classname" "weapon_rocketlauncher" "spawnflags" "5888" "origin" "-360 1184 -304" } { "classname" "item_doppleganger" "spawnflags" "5888" "origin" "-632 888 -496" } { "classname" "item_sphere_defender" "spawnflags" "5888" "origin" "472 1496 -304" } { "classname" "ammo_bullets" "spawnflags" "5888" "origin" "864 1696 -304" } { "classname" "weapon_machinegun" "spawnflags" "5888" "origin" "800 1760 -304" } { "classname" "item_armor_body" "spawnflags" "5888" "origin" "576 2128 -480" } { "classname" "weapon_railgun" "spawnflags" "5888" "origin" "2424 1408 272" } { "classname" "weapon_grenadelauncher" "spawnflags" "5888" "origin" "1248 544 80" } { "classname" "ammo_shells" "spawnflags" "5888" "origin" "800 1296 -112" } { "classname" "weapon_supershotgun" "spawnflags" "5888" "origin" "800 1216 -112" } { "classname" "weapon_rocketlauncher" "origin" "232 -96 -112" "spawnflags" "5888" } { "classname" "weapon_chaingun" "spawnflags" "5888" "origin" "1504 32 -48" } { "classname" "weapon_plasmabeam" "spawnflags" "5888" "origin" "2496 -400 -400" } { "spawnflags" "5888" "classname" "item_adrenaline" "origin" "2528 1072 64" } { "classname" "item_power_shield" "spawnflags" "5888" "origin" "2528 1232 64" } { "model" "*20" "classname" "func_wall" "spawnflags" "5888" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "928 1568 -104" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "832 896 24" } { "origin" "1760 -112 -40" "classname" "info_player_deathmatch" "angle" "180" } { "angle" "90" "classname" "info_player_deathmatch" "origin" "2560 -640 -424" } { "angle" "180" "classname" "info_player_deathmatch" "origin" "1376 -1344 -232" } { "angle" "315" "classname" "info_player_deathmatch" "origin" "1464 -272 -232" } { "angle" "180" "classname" "info_player_deathmatch" "origin" "800 -480 -104" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "-1312 544 -424" } { "angle" "0" "classname" "info_player_deathmatch" "origin" "-2120 1120 -264" } { "angle" "90" "classname" "info_player_deathmatch" "origin" "-416 800 -88" } { "origin" "288 -672 -296" "classname" "info_player_deathmatch" "angle" "270" } { "origin" "1312 864 88" "classname" "info_player_deathmatch" "angle" "180" } { "origin" "64 1408 -4" "classname" "info_player_deathmatch" "angle" "270" } { "origin" "480 1712 -296" "angle" "90" "classname" "info_player_deathmatch" } { "angle" "225" "classname" "info_player_deathmatch" "origin" "544 1560 -296" } { "classname" "info_player_deathmatch" "angle" "0" "origin" "1824 1440 216" } { "classname" "light" "light" "125" "origin" "352 1760 -432" } { "model" "*21" "classname" "func_wall" "spawnflags" "5888" } { "model" "*22" "classname" "func_plat2" "spawnflags" "5888" "lip" "16" } { "model" "*23" "classname" "func_wall" "spawnflags" "2048" } { "model" "*24" "classname" "func_wall" "spawnflags" "2048" } { "model" "*25" "classname" "func_wall" "spawnflags" "2048" } { "model" "*26" "classname" "func_wall" "spawnflags" "5888" } { "model" "*27" "classname" "func_wall" "spawnflags" "5888" } { "model" "*28" "spawnflags" "5888" "classname" "func_wall" } { "model" "*29" "classname" "func_wall" "spawnflags" "5888" } { "model" "*30" "classname" "func_wall" "spawnflags" "2048" } { "model" "*31" "classname" "func_wall" "spawnflags" "2048" } { "model" "*32" "classname" "func_wall" "spawnflags" "2048" } { "model" "*33" "classname" "func_wall" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t33" "delay" "2" "message" "Incinerator access granted." "origin" "-304 1264 -144" "spawnflags" "2048" } { "classname" "target_explosion" "targetname" "t317" "dmg" "75" "origin" "448 -880 -320" } { "classname" "target_explosion" "targetname" "t317" "dmg" "75" "origin" "528 -856 -320" } { "classname" "trigger_relay" "targetname" "t214" "target" "t316" "origin" "1800 -88 -216" "spawnflags" "2048" } { "classname" "trigger_relay" "target" "btnbrus" "targetname" "t316" "origin" "1792 -120 0" "spawnflags" "2048" } { "targetname" "t275" "spawnflags" "1" "classname" "ammo_rockets" "origin" "1640 1224 88" } { "classname" "ammo_cells" "origin" "2272 1768 80" } { "targetname" "t275" "spawnflags" "1" "classname" "ammo_cells" "origin" "1568 1088 88" } { "targetname" "t275" "spawnflags" "1" "classname" "ammo_slugs" "origin" "1888 992 80" } { "classname" "ammo_rockets" "origin" "2280 536 80" } { "classname" "ammo_rockets" "origin" "-424 1448 -304" } { "classname" "item_health_large" "origin" "-312 984 -304" } { "origin" "1416 -400 -224" "classname" "light" "light" "100" } { "classname" "monster_infantry" "spawnflags" "768" "target" "t119" "origin" "1504 -24 -40" } { "angle" "90" "classname" "info_player_start" "targetname" "sew2start" "origin" "960 -1920 -232" } { "classname" "trigger_relay" "origin" "3024 -520 -384" "killtarget" "btnbrus" "spawnflags" "2048" } { "model" "*34" "wait" "5" "message" "Access denied!" "classname" "trigger_multiple" "spawnflags" "2060" } { "origin" "240 1064 -296" "delay" "5" "target" "alarm" "targetname" "t269" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "272 1120 -296" "targetname" "t269" "target" "alarm" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "-40 -432 -176" "spawnflags" "769" "angle" "315" "classname" "monster_parasite" } { "spawnflags" "1" "origin" "216 -680 -296" "classname" "monster_infantry" "angle" "0" } { "origin" "472 -616 -288" "spawnflags" "769" "angle" "0" "classname" "monster_infantry" } { "origin" "2504 -64 -232" "spawnflags" "1" "angle" "180" "classname" "monster_medic" } { "targetname" "t275" "origin" "1952 928 128" "classname" "monster_soldier" "angle" "135" "spawnflags" "3" } { "targetname" "t275" "origin" "1944 1312 128" "spawnflags" "3" "angle" "225" "classname" "monster_soldier" } { "classname" "ammo_bullets" "origin" "352 1120 -48" } { "classname" "ammo_cells" "origin" "536 1576 -48" } { "classname" "ammo_nails" "origin" "-288 864 144" } { "classname" "item_health_small" "origin" "0 1128 144" } { "classname" "item_health_small" "origin" "-48 1128 144" } { "classname" "item_health_small" "origin" "-96 1128 144" } { "classname" "item_health_small" "origin" "48 1128 144" } { "classname" "ammo_shells" "origin" "-296 1376 144" } { "classname" "ammo_prox" "origin" "-216 1576 -48" } { "classname" "ammo_tesla" "origin" "-168 1704 80" } { "classname" "item_health" "origin" "336 1832 80" } { "classname" "item_health_large" "origin" "288 1832 80" } { "classname" "monster_stalker" "spawnflags" "777" "angle" "90" "origin" "36 996 226" } { "classname" "monster_soldier" "spawnflags" "1537" "angle" "90" "origin" "192 880 -40" } { "classname" "monster_gunner" "angle" "90" "spawnflags" "257" "origin" "192 896 -40" } { "classname" "monster_turret" "angle" "180" "spawnflags" "800" "origin" "376 1024 192" } { "classname" "monster_turret" "angle" "270" "spawnflags" "800" "origin" "-608 1656 32" } { "angle" "225" "classname" "monster_soldier" "spawnflags" "1" "origin" "152 1640 88" } { "classname" "monster_soldier" "angle" "270" "spawnflags" "769" "origin" "0 1824 88" } { "spawnflags" "2049" "noise" "world/comp_hum3.wav" "classname" "target_speaker" "origin" "-256 856 176" } { "spawnflags" "1" "noise" "world/comp_hum1.wav" "classname" "target_speaker" "origin" "-264 992 176" } { "classname" "target_speaker" "noise" "world/comp_hum3.wav" "spawnflags" "1" "origin" "-168 768 176" } { "spawnflags" "1" "noise" "world/comp_hum2.wav" "classname" "target_speaker" "origin" "128 1808 104" } { "classname" "target_speaker" "noise" "world/comp_hum1.wav" "spawnflags" "1" "origin" "528 1808 104" } { "origin" "532 1812 104" "classname" "light" "light" "100" "_color" "1.000000 0.000000 0.000000" } { "origin" "40 1832 120" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "origin" "216 1840 120" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "origin" "128 1816 120" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "origin" "600 1304 -464" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "classname" "monster_parasite" "angle" "180" "spawnflags" "1" "origin" "544 1536 -40" } { "classname" "item_armor_body" "origin" "544 1648 80" } { "classname" "path_corner" "target" "t314" "targetname" "t315" "origin" "-296 1696 144" "spawnflags" "2048" } { "classname" "path_corner" "targetname" "t314" "target" "t315" "origin" "-216 912 144" "spawnflags" "2048" } { "classname" "monster_gladiator" "angle" "270" "target" "t315" "spawnflags" "1" "origin" "-256 1664 152" "item" "ammo_slugs" } { "classname" "monster_parasite" "angle" "270" "spawnflags" "1" "origin" "-288 1568 -40" } { "classname" "monster_stalker" "spawnflags" "9" "angle" "90" "origin" "-276 1196 34" } { "classname" "ammo_cells" "origin" "-288 800 -496" } { "classname" "misc_deadsoldier" "spawnflags" "2049" "origin" "600 1176 -512" } { "classname" "weapon_heatbeam" "origin" "600 1128 -496" "spawnflags" "2048" } { "classname" "ammo_grenades" "origin" "-416 1576 -496" } { "classname" "item_pack" "origin" "-600 1584 -496" } { "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "632 1120 -464" } { "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "600 1064 -464" } { "light" "100" "classname" "light" "origin" "532 1812 148" } { "light" "125" "classname" "light" "origin" "608 1184 -432" } { "classname" "item_health" "origin" "352 1576 -304" } { "classname" "item_health" "origin" "304 1576 -304" } { "classname" "point_combat" "targetname" "t313" "spawnflags" "2049" "origin" "224 856 -504" } { "classname" "monster_gladiator" "target" "t313" "angle" "90" "spawnflags" "1" "origin" "256 816 -488" "item" "ammo_slugs" } { "model" "*35" "classname" "func_wall" "targetname" "t39" "spawnflags" "3" } { "spawnflags" "257" "angle" "0" "classname" "monster_flyer" "origin" "-296 928 -416" } { "spawnflags" "1" "angle" "0" "classname" "monster_flyer" "origin" "-224 928 -296" } { "spawnflags" "1" "angle" "0" "classname" "monster_flyer" "origin" "-224 1440 -296" } { "classname" "monster_flyer" "angle" "0" "spawnflags" "769" "origin" "-296 1440 -416" } { "classname" "monster_soldier" "angle" "90" "origin" "352 1688 -488" } { "classname" "monster_gunner" "angle" "180" "spawnflags" "1" "origin" "1248 1968 -488" } { "classname" "light" "light" "125" "origin" "576 2080 -448" } { "classname" "monster_gunner" "angle" "270" "spawnflags" "1" "origin" "288 1440 -296" } { "classname" "hint_path" "targetname" "t308" "target" "t309" "origin" "784 1936 -480" "spawnflags" "2048" } { "classname" "hint_path" "targetname" "t309" "target" "t310" "origin" "368 1936 -480" "spawnflags" "2048" } { "classname" "hint_path" "targetname" "t310" "target" "t311" "origin" "352 2144 -480" "spawnflags" "2048" } { "classname" "hint_path" "targetname" "t311" "target" "t312" "origin" "344 2136 -280" "spawnflags" "2048" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t312" "origin" "328 1928 -280" } { "classname" "hint_path" "spawnflags" "2049" "target" "t308" "origin" "1224 1960 -480" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t302" "target" "t303" "origin" "-608 1688 -280" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t303" "target" "t304" "origin" "-368 1944 -280" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t304" "target" "t305" "origin" "576 1952 -280" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t305" "target" "t306" "origin" "1088 1952 -280" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t306" "origin" "1264 1768 -280" "target" "t307" } { "spawnflags" "2049" "classname" "hint_path" "origin" "1256 1760 104" "targetname" "t307" } { "classname" "hint_path" "spawnflags" "2049" "target" "t302" "origin" "-608 1480 -280" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t300" "target" "t301" "origin" "1856 1496 224" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t299" "target" "t300" "origin" "1856 1728 224" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t298" "target" "t299" "origin" "2200 1744 104" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t301" "origin" "2312 1496 288" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t296" "origin" "2216 1112 104" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t293" "target" "t294" "origin" "1864 832 224" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t294" "target" "t295" "origin" "1864 600 224" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t295" "target" "t296" "origin" "2208 584 104" } { "classname" "hint_path" "spawnflags" "2049" "target" "t298" "origin" "2232 1192 104" } { "spawnflags" "2049" "classname" "hint_path" "target" "t293" "origin" "2320 832 288" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t292" "origin" "1216 1152 104" } { "classname" "hint_path" "spawnflags" "2049" "target" "t292" "origin" "2264 1160 104" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t288" "target" "t289" "origin" "1256 544 104" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t289" "target" "t290" "origin" "1248 1152 104" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t290" "target" "t291" "origin" "1240 1760 104" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t291" "origin" "856 1760 104" } { "classname" "hint_path" "spawnflags" "2049" "target" "t288" "origin" "792 536 104" } { "classname" "target_speaker" "spawnflags" "2050" "noise" "world/fan1.wav" "targetname" "t269" "origin" "448 1432 -8" } { "classname" "trigger_relay" "killtarget" "t283" "targetname" "t275" "origin" "1376 704 72" "spawnflags" "2048" } { "classname" "item_health" "origin" "-2136 728 -272" } { "classname" "item_health" "origin" "-2136 768 -272" } { "classname" "ammo_tesla" "origin" "-808 1184 -304" "spawnflags" "5888" } { "origin" "-1768 472 -432" "classname" "item_armor_shard" } { "origin" "-1816 472 -432" "classname" "item_armor_shard" } { "classname" "item_armor_shard" "origin" "-1720 472 -432" } { "classname" "weapon_supershotgun" "origin" "-2032 1096 -432" } { "classname" "misc_deadsoldier" "spawnflags" "2056" "origin" "-2080 1056 -448" } { "classname" "ammo_shells" "origin" "-2016 544 -272" } { "classname" "ammo_nails" "origin" "-1248 608 -432" } { "classname" "ammo_bullets" "origin" "-1248 1184 -432" } { "classname" "item_health_large" "origin" "-1632 1280 -432" } { "classname" "item_health_large" "origin" "-1584 1280 -432" } { "classname" "item_health_small" "origin" "-1128 936 -560" } { "classname" "item_health_small" "origin" "-1088 936 -560" } { "classname" "item_health_small" "origin" "-1048 936 -560" } { "classname" "item_health_small" "origin" "-1176 936 -544" } { "model" "*36" "message" "Lift activated." "classname" "func_button" "angle" "90" "target" "t255" } { "classname" "ammo_rockets" "origin" "216 -144 -112" } { "classname" "item_armor_shard" "origin" "248 -48 -112" } { "classname" "item_armor_shard" "origin" "208 -48 -112" } { "classname" "item_armor_shard" "origin" "288 -48 -112" } { "model" "*37" "classname" "trigger_once" "target" "t287" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "416 -96 16" } { "model" "*38" "classname" "func_door" "angle" "-1" "targetname" "t287" "wait" "-1" "spawnflags" "2048" } { "origin" "-352 1264 -288" "targetname" "t286" "classname" "target_goal" "spawnflags" "2048" } { "message" "Destroy containment glass\nto activate ventilation." "origin" "-352 1296 -272" "targetname" "t286" "classname" "target_help" "spawnflags" "2048" } { "model" "*39" "target" "t286" "targetname" "t33" "classname" "trigger_once" "spawnflags" "2048" } { "volume" ".5" "origin" "-192 1176 -496" "targetname" "t39" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "volume" ".5" "origin" "-64 1184 -496" "targetname" "t39" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "volume" ".5" "origin" "64 1184 -496" "targetname" "t39" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "volume" ".5" "origin" "192 1184 -496" "targetname" "t39" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "volume" ".5" "origin" "336 1184 -496" "targetname" "t39" "classname" "target_speaker" "noise" "world/amb10.wav" "spawnflags" "2050" } { "volume" ".5" "origin" "-320 1184 -496" "targetname" "t39" "noise" "world/amb10.wav" "classname" "target_speaker" "spawnflags" "2050" } { "model" "*40" "targetname" "speak" "dmg" "10000" "spawnflags" "2059" "classname" "trigger_hurt" } { "targetname" "t282" "target" "speak" "origin" "1384 864 72" "classname" "trigger_relay" "spawnflags" "2048" } { "target" "speak" "targetname" "goal" "classname" "trigger_relay" "delay" "2" "origin" "1384 920 72" "spawnflags" "2048" } { "targetname" "speak" "spawnflags" "2050" "classname" "target_speaker" "origin" "1280 1152 136" "noise" "world/amb10.wav" } { "targetname" "speak" "spawnflags" "2050" "classname" "target_speaker" "origin" "1248 1280 136" "noise" "world/amb10.wav" } { "targetname" "speak" "spawnflags" "2050" "classname" "target_speaker" "origin" "1248 1472 136" "noise" "world/amb10.wav" } { "targetname" "speak" "spawnflags" "2050" "classname" "target_speaker" "origin" "1248 1600 136" "noise" "world/amb10.wav" } { "targetname" "speak" "spawnflags" "2050" "noise" "world/amb10.wav" "origin" "1408 1152 136" "classname" "target_speaker" } { "classname" "light" "light" "60" "origin" "1304 488 208" } { "classname" "light" "light" "60" "origin" "1304 488 176" } { "classname" "light" "light" "60" "origin" "1304 488 144" } { "classname" "light" "light" "60" "origin" "1248 472 96" } { "classname" "light" "light" "100" "origin" "1184 488 120" "_color" "1.000000 0.000000 0.000000" } { "origin" "1304 488 240" "light" "60" "classname" "light" } { "origin" "1376 600 80" "target" "t285" "targetname" "t284" "delay" "2" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "1336 1000 80" "target" "t284" "targetname" "goal" "classname" "trigger_relay" "spawnflags" "2048" "message" "Maintenance Hangar doors sealed." } { "origin" "1384 744 72" "target" "t283" "delay" "2" "targetname" "t282" "classname" "trigger_relay" "spawnflags" "2048" } { "model" "*41" "message" "Waste conveyor activated." "target" "t282" "wait" "-1" "angle" "270" "classname" "func_button" } { "origin" "1152 1056 72" "target" "t280" "targetname" "t279" "classname" "path_corner" "spawnflags" "2048" } { "origin" "1152 1600 72" "target" "t279" "targetname" "t278" "classname" "path_corner" "spawnflags" "2048" } { "origin" "1152 1664 64" "targetname" "t281" "target" "t278" "classname" "path_corner" "spawnflags" "2048" } { "pathtarget" "goal" "origin" "1248 1056 72" "targetname" "t280" "wait" "-1" "classname" "path_corner" "spawnflags" "2048" } { "_color" "1.000000 0.000000 0.000000" "origin" "1296 496 104" "light" "100" "classname" "light" } { "speed" "2" "target" "veylit" "targetname" "t282" "origin" "1376 800 72" "classname" "target_lightramp" "message" "az" "spawnflags" "2048" } { "speed" "2" "targetname" "t284" "target" "veylit" "origin" "1376 1696 72" "message" "za" "classname" "target_lightramp" "spawnflags" "2048" } { "model" "*42" "targetname" "t283" "target" "t281" "classname" "func_train" "spawnflags" "2048" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1376 1216 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1376 1088 80" "_color" "1.000000 0.000000 0.000000" "classname" "light" "light" "125" } { "style" "32" "targetname" "veylit" "spawnflags" "2048" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1440 1088 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1312 1088 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1248 1088 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1184 1120 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1184 1184 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1184 1248 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1184 1312 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "1312 1312 80" } { "style" "32" "spawnflags" "1" "targetname" "veylit" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" "origin" "1312 1504 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "1184 1504 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "1312 1568 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "_color" "1.000000 0.000000 0.000000" "classname" "light" "light" "125" "origin" "1184 1568 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" "origin" "1312 1632 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "_color" "1.000000 0.000000 0.000000" "classname" "light" "light" "125" "origin" "1184 1632 80" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1312 1376 80" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1184 1376 80" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1312 1440 80" "classname" "light" "light" "125" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1184 1440 80" "light" "125" "classname" "light" "_color" "1.000000 0.000000 0.000000" } { "style" "32" "targetname" "veylit" "spawnflags" "2049" "origin" "1440 1216 80" "_color" "1.000000 0.000000 0.000000" "classname" "light" "light" "125" } { "style" "32" "spawnflags" "2048" "targetname" "veylit" "origin" "1312 1248 80" "_color" "1.000000 0.000000 0.000000" "light" "125" "classname" "light" } { "targetname" "t285" "classname" "target_help" "spawnflags" "2048" "origin" "1288 1064 96" "message" "Locate and activate\nincinerator." } { "targetname" "t285" "message" "Find secondary route\n into Maintenance Hangars." "origin" "1224 1040 96" "spawnflags" "2049" "classname" "target_help" } { "target" "t277" "targetname" "t263" "classname" "trigger_relay" "origin" "-2032 1056 -280" "delay" "3" "spawnflags" "2048" } { "message" "Activate incinerator and\n break containment glass." "origin" "-2000 944 -264" "targetname" "t277" "classname" "target_help" "spawnflags" "2048" } { "origin" "1160 1312 168" "message" "Use Cargo lift to re-enter\nMaintenance Hangars." "targetname" "t275" "classname" "target_help" "spawnflags" "2048" } { "origin" "2272 1000 88" "targetname" "rhangar2b" "classname" "info_player_coop" "angle" "180" } { "origin" "2356 1076 96" "targetname" "rhangar2b" "classname" "info_player_coop" "angle" "180" } { "origin" "2360 1216 96" "targetname" "rhangar2b" "classname" "info_player_coop" "angle" "180" } { "origin" "2236 1208 96" "targetname" "rhangar2b" "angle" "180" "classname" "info_player_coop" } { "origin" "2360 1152 92" "targetname" "rhangar2b" "angle" "180" "classname" "info_player_start" } { "origin" "1216 1328 152" "targetname" "t275" "killtarget" "doorun" "classname" "trigger_relay" "spawnflags" "2048" "message" "Maintenance Hangar access denied!" } { "targetname" "t275" "spawnflags" "1" "origin" "1824 864 208" "classname" "ammo_slugs" } { "origin" "2112 1504 352" "classname" "light" "_color" "1.000000 0.501961 0.000000" "light" "100" } { "origin" "2400 1472 352" "classname" "light" "_color" "1.000000 0.501961 0.000000" "light" "100" } { "origin" "1240 1760 184" "light" "150" "classname" "light" } { "origin" "2464 1432 288" "targetname" "t151" "classname" "target_speaker" "noise" "world/lasoff1.wav" "spawnflags" "2048" } { "origin" "2464 1392 288" "noise" "world/lasoff1.wav" "targetname" "t151" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "2380 1152 176" "targetname" "t151" "spawnflags" "2049" "classname" "target_speaker" "noise" "world/l_hum2.wav" } { "origin" "2384 1152 104" "targetname" "t151" "spawnflags" "2049" "noise" "world/l_hum2.wav" "classname" "target_speaker" } { "style" "33" "targetname" "t151" "_color" "1.000000 1.000000 0.000000" "classname" "light" "light" "100" "origin" "2416 1152 144" "spawnflags" "2048" } { "style" "33" "targetname" "t151" "_color" "1.000000 1.000000 0.000000" "classname" "light" "light" "100" "origin" "2416 1152 112" "spawnflags" "2048" } { "style" "33" "targetname" "t151" "_color" "1.000000 1.000000 0.000000" "classname" "light" "light" "100" "origin" "2416 1152 80" "spawnflags" "2048" } { "classname" "light" "light" "150" "origin" "2600 1152 104" } { "origin" "2600 1152 232" "classname" "light" "light" "150" } { "origin" "2600 1152 360" "classname" "light" "light" "150" } { "origin" "2600 1152 488" "classname" "light" "light" "150" } { "origin" "2600 1152 616" "classname" "light" "light" "150" } { "origin" "2600 1152 744" "classname" "light" "light" "150" } { "origin" "2600 1152 872" "classname" "light" "light" "150" } { "origin" "2600 1152 1000" "classname" "light" "light" "150" } { "style" "33" "targetname" "t151" "_color" "1.000000 1.000000 0.000000" "origin" "2416 1152 176" "light" "100" "classname" "light" "spawnflags" "2048" } { "classname" "light" "_color" "1.000000 0.501961 0.000000" "light" "100" "origin" "2320 1152 352" } { "model" "*43" "message" "Hangar lift door opened." "sounds" "4" "target" "t276" "wait" "-1" "angle" "0" "classname" "func_button" "spawnflags" "2048" } { "model" "*44" "origin" "2400 1152 240" "wait" "-1" "sounds" "4" "targetname" "t276" "distance" "140" "spawnflags" "2176" "classname" "func_door_rotating" } { "origin" "2416 1248 112" "targetname" "t151" "classname" "target_laser" "angle" "270" "spawnflags" "2065" } { "origin" "2416 1248 80" "targetname" "t151" "spawnflags" "2065" "angle" "270" "classname" "target_laser" } { "origin" "2416 1248 144" "targetname" "t151" "classname" "target_laser" "angle" "270" "spawnflags" "2065" } { "origin" "2416 1248 176" "targetname" "t151" "spawnflags" "2065" "angle" "270" "classname" "target_laser" } { "model" "*45" "sounds" "4" "targetname" "t275" "wait" "-1" "lip" "96" "angle" "270" "classname" "func_door" "spawnflags" "2048" "message" "Maintenance Hangar access denied!" "team" "hangdor1" } { "model" "*46" "sounds" "4" "targetname" "t275" "wait" "-1" "lip" "96" "angle" "90" "classname" "func_door" "spawnflags" "2048" "team" "hangdor1" "message" "Maintenance Hangar access denied!" } { "model" "*47" "spawnflags" "3" "targetname" "t275" "classname" "func_wall" } { "origin" "1376 1568 152" "target" "t275" "spawnflags" "2049" "classname" "target_crosslevel_target" } { "model" "*48" "targetname" "t275" "spawnflags" "2055" "classname" "func_wall" } { "origin" "1440 1152 192" "classname" "light" "light" "150" } { "model" "*49" "_minlight" ".2" "lip" "168" "spawnflags" "2048" "classname" "func_plat2" "sounds" "4" "targetname" "t320" } { "model" "*50" "target" "t274" "classname" "trigger_multiple" "spawnflags" "2048" } { "map" "rhangar2$rsewer2b" "targetname" "t274" "origin" "2576 1160 632" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*51" "angle" "270" "classname" "func_button" "spawnflags" "2048" "target" "t320" "message" "Hangar lift activated." } { "origin" "-32 1416 -40" "targetname" "rhangar2a" "classname" "info_player_coop" "angle" "180" "spawnflags" "2048" } { "origin" "192 1392 -40" "targetname" "rhangar2a" "classname" "info_player_coop" "angle" "180" "spawnflags" "2048" } { "origin" "160 1504 -40" "targetname" "rhangar2a" "classname" "info_player_coop" "angle" "180" "spawnflags" "2048" } { "origin" "56 1320 -40" "angle" "180" "targetname" "rhangar2a" "classname" "info_player_coop" "spawnflags" "2048" } { "origin" "64 1408 248" "angle" "180" "targetname" "rhangar2a" "classname" "info_player_start" } { "map" "rhangar2$rsewer2a" "origin" "456 1400 620" "targetname" "t273" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*52" "targetname" "t269" "target" "t273" "classname" "trigger_multiple" "spawnflags" "2056" } { "origin" "424 1496 -48" "targetname" "t269" "target" "t272" "classname" "func_timer" "spawnflags" "2048" } { "targetname" "t272" "sounds" "208" "wait" "1" "count" "96" "speed" "150" "classname" "target_steam" "angle" "-1" "origin" "448 1408 -56" "spawnflags" "2048" } { "volume" ".5" "spawnflags" "2050" "origin" "-88 912 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "-72 1192 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "-64 1424 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "280 928 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "296 1192 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "352 1536 -440" "targetname" "alarm" "classname" "target_speaker" "noise" "world/klaxon1.wav" } { "volume" ".5" "spawnflags" "2050" "origin" "-336 1192 -272" "targetname" "alarm" "noise" "world/klaxon1.wav" "classname" "target_speaker" } { "origin" "-80 1400 -392" "targetname" "t254" "target" "t270" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "272 968 -392" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "272 968 -392" "target" "t270" "targetname" "t253" "classname" "trigger_relay" "spawnflags" "2048" } { "message" "Use ventilation fan shaft\n to access Hangar." "origin" "160 1208 -280" "targetname" "t269" "classname" "target_help" "spawnflags" "2048" } { "origin" "216 1248 -296" "targetname" "t269" "classname" "target_goal" "spawnflags" "2048" } { "model" "*53" "killtarget" "fantrig" "targetname" "t270" "target" "t269" "count" "2" "classname" "trigger_counter" "spawnflags" "2048" } { "model" "*54" "height" "376" "targetname" "t256" "spawnflags" "2" "classname" "func_plat2" "dmg" "100" "speed" "100" } { "model" "*55" "target" "t256" "classname" "func_button" "angle" "90" "message" "Cargo lift activated." "spawnflags" "0" } { "origin" "-764 1036 -308" "targetname" "t263" "noise" "world/force3.wav" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "356 1676 -456" "targetname" "t263" "noise" "world/force3.wav" "classname" "target_speaker" "spawnflags" "2049" } { "model" "*56" "targetname" "t263" "spawnflags" "2054" "classname" "func_wall" } { "origin" "-2136 984 -232" "noise" "world/fuseout.wav" "targetname" "t263" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "-2144 768 -232" "noise" "world/fuseout.wav" "targetname" "t263" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "-2144 840 -240" "targetname" "t263" "target" "t267" "message" "az" "speed" "2" "classname" "target_lightramp" "spawnflags" "2048" } { "model" "*57" "spawnflags" "1536" "classname" "func_wall" } { "model" "*58" "spawnflags" "1024" "classname" "func_wall" } { "origin" "-2192 984 -232" "light" "100" "classname" "light" "spawnflags" "2048" } { "delay" "3" "target" "t265" "origin" "-2056 1088 -280" "targetname" "t264" "classname" "trigger_relay" "spawnflags" "2048" } { "model" "*59" "origin" "-2180 967 -232" "speed" "40" "_minlight" ".1" "distance" "170" "wait" "-1" "targetname" "t264" "spawnflags" "2050" "classname" "func_door_rotating" } { "origin" "-2240 972 -288" "targetname" "t262" "target" "t261" "classname" "path_corner" "spawnflags" "2048" } { "origin" "-2208 972 -288" "wait" "-1" "targetname" "t261" "classname" "path_corner" "spawnflags" "2048" } { "model" "*60" "speed" "5" "_minlight" ".2" "targetname" "t265" "team" "train" "target" "t262" "classname" "func_train" "spawnflags" "2048" } { "model" "*61" "target" "t263" "team" "train" "health" "1" "classname" "func_explosive" "spawnflags" "2048" } { "spawnflags" "2049" "targetname" "t263" "team" "train" "origin" "-2192 976 -232" "classname" "target_speaker" "noise" "world/fan1.wav" } { "targetname" "t263" "spawnflags" "2049" "team" "train" "origin" "-2192 992 -232" "noise" "world/fan1.wav" "classname" "target_speaker" } { "origin" "-1120 1024 -192" "classname" "light" "light" "75" } { "origin" "-2208 768 -192" "classname" "light" "light" "75" } { "origin" "-2208 1024 -192" "classname" "light" "light" "75" } { "origin" "-1120 768 -192" "light" "75" "classname" "light" } { "origin" "-1664 896 -396" "classname" "light" "light" "125" } { "origin" "-1472 896 -432" "classname" "light" "light" "125" } { "origin" "-1280 896 -456" "classname" "light" "light" "125" } { "targetname" "t51" "angle" "0" "spawnflags" "1" "origin" "-2136 896 -264" "classname" "monster_medic_commander" } { "targetname" "t260" "classname" "target_speaker" "noise" "world/brkglas.wav" "origin" "1616 -232 -16" "spawnflags" "2048" } { "model" "*62" "target" "t260" "classname" "func_explosive" "mass" "300" "spawnflags" "2048" } { "classname" "light" "light" "100" "origin" "-752 1432 80" } { "classname" "light" "light" "100" "origin" "-680 1504 80" } { "classname" "light" "light" "100" "origin" "-752 1576 80" } { "_color" "1.000000 0.778226 0.028226" "origin" "-752 1504 -168" "light" "125" "classname" "light" } { "classname" "light" "light" "100" "origin" "-680 1504 -272" } { "classname" "light" "light" "100" "origin" "-752 1432 -272" } { "classname" "light" "light" "100" "origin" "-824 1504 -272" } { "style" "34" "targetname" "t267" "_color" "0.257282 1.000000 0.237864" "origin" "-2168 864 -200" "light" "100" "classname" "light" } { "model" "*63" "targetname" "t56" "mass" "200" "classname" "func_explosive" } { "model" "*64" "message" "Power conduit accessible." "wait" "-1" "target" "t264" "angle" "180" "classname" "func_button" "spawnflags" "2048" } { "model" "*65" "target" "t255" "angle" "90" "classname" "func_button" "message" "Lift activated." } { "model" "*66" "message" "Cargo lift activated." "target" "t257" "angle" "180" "classname" "func_button" } { "model" "*67" "message" "Cargo lift activated." "target" "t256" "angle" "90" "classname" "func_button" } { "origin" "-960 896 -104" "spawnflags" "257" "angle" "0" "classname" "monster_parasite" } { "classname" "ammo_nails" "origin" "-408 1640 -96" } { "origin" "-464 1640 -96" "classname" "ammo_nails" } { "origin" "-560 888 -112" "classname" "weapon_nailgun" } { "origin" "-472 856 -112" "classname" "misc_deadsoldier" "spawnflags" "2048" } { "origin" "-536 1280 -256" "classname" "item_armor_shard" } { "origin" "-536 1328 -280" "classname" "item_armor_shard" } { "origin" "-536 1376 -304" "classname" "item_armor_shard" } { "origin" "-536 1232 -224" "classname" "item_armor_shard" } { "origin" "-312 1024 -304" "classname" "item_health_large" } { "origin" "-608 1672 -144" "spawnflags" "32" "angle" "-2" "classname" "monster_turret" } { "origin" "-384 1392 -296" "spawnflags" "1" "angle" "270" "classname" "monster_gunner" } { "origin" "-64 1480 -336" "targetname" "t254" "noise" "world/brkglas.wav" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "-64 880 -336" "targetname" "t253" "noise" "world/brkglas.wav" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "-544 936 -304" "classname" "ammo_slugs" } { "origin" "-808 1384 -304" "classname" "item_health" } { "origin" "-808 1336 -304" "classname" "item_health" } { "origin" "-640 888 -104" "spawnflags" "1537" "angle" "90" "classname" "monster_soldier_light" } { "origin" "-456 1608 -104" "target" "t252" "targetname" "t251" "classname" "path_corner" "spawnflags" "2048" } { "origin" "-432 880 -104" "targetname" "t252" "target" "t251" "classname" "path_corner" "spawnflags" "2048" } { "origin" "-448 1520 -88" "angle" "225" "spawnflags" "1" "target" "t251" "classname" "monster_medic" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "32" "origin" "-392 1184 -136" } { "origin" "-560 896 -296" "spawnflags" "1" "angle" "180" "classname" "monster_parasite" } { "origin" "-644 892 -110" "spawnflags" "257" "angle" "90" "classname" "monster_stalker" } { "spawnflags" "1" "angle" "0" "origin" "-792 1624 -88" "classname" "monster_gunner" } { "origin" "-576 1624 -304" "classname" "ammo_prox" } { "origin" "-80 1984 -304" "classname" "ammo_tesla" } { "origin" "0 1952 -144" "classname" "monster_turret" "angle" "-2" "spawnflags" "32" } { "origin" "1320 1504 88" "classname" "ammo_bullets" } { "origin" "1320 1552 88" "classname" "ammo_bullets" } { "origin" "664 672 -112" "classname" "ammo_shells" } { "origin" "1120 1760 -304" "classname" "item_health" } { "origin" "1104 1824 -304" "classname" "item_health" } { "origin" "288 1688 -304" "classname" "ammo_rockets" } { "origin" "728 1728 -304" "classname" "item_health_small" } { "origin" "728 1776 -304" "classname" "item_health_small" } { "origin" "728 1824 -304" "classname" "item_health_small" } { "origin" "728 1680 -304" "classname" "item_health_small" } { "origin" "1256 2216 -304" "classname" "ammo_slugs" } { "origin" "816 1696 -488" "angle" "90" "classname" "monster_parasite" } { "origin" "576 2136 -480" "classname" "item_adrenaline" "spawnflags" "2048" } { "origin" "1008 1696 -512" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "origin" "992 1752 -496" "classname" "weapon_supershotgun" } { "origin" "336 1712 -296" "spawnflags" "256" "targetname" "t250" "angle" "90" "classname" "monster_medic" "item" "ammo_cells" } { "target" "t250" "origin" "704 2192 -296" "spawnflags" "257" "angle" "270" "classname" "monster_gladiator" } { "origin" "1212 2180 -150" "angle" "270" "spawnflags" "777" "classname" "monster_stalker" } { "origin" "872 1696 -296" "classname" "monster_soldier" "angle" "90" "spawnflags" "1" "item" "ammo_shells" } { "origin" "1200 2160 -296" "spawnflags" "1025" "angle" "270" "classname" "monster_soldier" } { "origin" "736 512 64" "angle" "0" "classname" "misc_deadsoldier" "spawnflags" "2048" } { "origin" "680 480 144" "classname" "item_armor_combat" } { "origin" "1128 1176 -112" "classname" "item_armor_shard" } { "origin" "1128 1056 -112" "classname" "item_armor_shard" } { "origin" "1128 1096 -112" "classname" "item_armor_shard" } { "origin" "1128 1136 -112" "classname" "item_armor_shard" } { "origin" "1048 1832 80" "classname" "item_health" } { "origin" "1104 1832 80" "classname" "item_health" } { "classname" "misc_explobox" "origin" "672 576 64" "spawnflags" "2048" } { "classname" "misc_explobox" "origin" "744 792 -128" } { "origin" "1048 1736 88" "angle" "270" "classname" "monster_gunner" "spawnflags" "1" "item" "ammo_grenades" } { "origin" "816 960 16" "classname" "ammo_rockets" } { "origin" "960 112 -112" "classname" "ammo_cells" } { "origin" "960 176 -112" "classname" "ammo_cells" } { "origin" "472 -136 -112" "classname" "item_health_large" } { "targetname" "t219" "classname" "monster_turret" "angle" "-2" "spawnflags" "288" "origin" "928 256 48" } { "origin" "768 576 88" "spawnflags" "0" "targetname" "t31" "classname" "monster_medic_commander" "angle" "90" } { "target" "t249" "targetname" "t122" "classname" "trigger_relay" "origin" "2632 -176 -408" "spawnflags" "2048" } { "target" "t249" "origin" "2520 160 -40" "classname" "trigger_always" "spawnflags" "2048" } { "target" "t248" "origin" "2680 -200 -408" "targetname" "t122" "classname" "trigger_relay" "spawnflags" "2048" } { "killtarget" "t248" "targetname" "t123" "origin" "3008 -520 -384" "classname" "trigger_relay" "target" "t316" "spawnflags" "2048" } { "model" "*68" "targetname" "btnbrus" "spawnflags" "2060" "classname" "trigger_multiple" "message" "Access denied!" "wait" "5" } { "target" "t242" "targetname" "t241" "classname" "hint_path" "spawnflags" "2048" "origin" "944 808 -96" } { "target" "t243" "targetname" "t242" "classname" "hint_path" "spawnflags" "2048" "origin" "928 -96 -96" } { "target" "t244" "targetname" "t243" "classname" "hint_path" "spawnflags" "2048" "origin" "680 -104 -92" } { "targetname" "t244" "classname" "hint_path" "spawnflags" "2049" "origin" "680 -368 -100" } { "target" "t241" "origin" "944 1344 -96" "spawnflags" "2049" "classname" "hint_path" } { "target" "t238" "targetname" "t237" "origin" "32 -400 -164" "spawnflags" "2048" "classname" "hint_path" } { "target" "t239" "targetname" "t238" "origin" "-48 -480 -172" "spawnflags" "2048" "classname" "hint_path" } { "target" "t240" "targetname" "t239" "origin" "0 -952 -316" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t240" "origin" "516 -708 -288" "spawnflags" "2049" "classname" "hint_path" } { "target" "t237" "classname" "hint_path" "spawnflags" "2049" "origin" "688 -392 -92" } { "target" "t234" "targetname" "t233" "origin" "2816 -168 -408" "classname" "hint_path" "spawnflags" "2048" } { "target" "t235" "targetname" "t234" "origin" "2824 -64 -216" "classname" "hint_path" "spawnflags" "2048" } { "target" "t236" "targetname" "t235" "origin" "2248 -72 -224" "classname" "hint_path" "spawnflags" "2048" } { "targetname" "t236" "origin" "2200 -440 -216" "classname" "hint_path" "spawnflags" "2049" } { "target" "t233" "spawnflags" "2049" "classname" "hint_path" "origin" "2680 -440 -416" } { "target" "t227" "targetname" "t226" "classname" "hint_path" "spawnflags" "2048" "origin" "1632 40 -32" } { "target" "t228" "targetname" "t227" "classname" "hint_path" "spawnflags" "2048" "origin" "2280 48 -32" } { "target" "t229" "targetname" "t228" "classname" "hint_path" "spawnflags" "2048" "origin" "2824 48 -104" } { "target" "t230" "targetname" "t229" "classname" "hint_path" "spawnflags" "2048" "origin" "2832 -736 -224" } { "target" "t231" "targetname" "t230" "classname" "hint_path" "spawnflags" "2048" "origin" "2232 -696 -216" } { "target" "t232" "targetname" "t231" "origin" "2224 -424 -208" "classname" "hint_path" "spawnflags" "2048" } { "targetname" "t232" "origin" "1632 -400 -224" "classname" "hint_path" "spawnflags" "2049" } { "target" "t226" "origin" "1616 -200 -32" "spawnflags" "2049" "classname" "hint_path" } { "origin" "952 -400 -208" "target" "t225" "targetname" "t224" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1632 -376 -224" "targetname" "t225" "classname" "hint_path" "spawnflags" "2049" } { "origin" "928 -792 -216" "target" "t224" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1624 -848 -224" "target" "t222" "targetname" "t221" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1168 -856 -224" "target" "t223" "targetname" "t222" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1168 -1160 -216" "targetname" "t223" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1616 -416 -208" "target" "t221" "spawnflags" "2049" "classname" "hint_path" } { "origin" "608 -928 -304" "classname" "item_armor_shard" } { "origin" "656 -928 -292" "classname" "item_armor_shard" } { "origin" "560 -928 -304" "classname" "item_armor_shard" } { "origin" "704 -928 -276" "classname" "item_armor_shard" } { "origin" "2272 -352 -240" "classname" "ammo_tesla" } { "origin" "1904 104 -48" "classname" "item_health" } { "origin" "1960 104 -48" "classname" "item_health" } { "origin" "992 -1472 -416" "targetname" "t220" "classname" "target_secret" } { "model" "*69" "message" "You've found a secret." "target" "t220" "classname" "trigger_once" } { "origin" "944 -1496 -408" "classname" "item_health_mega" } { "origin" "1432 -824 -248" "delay" "1" "targetname" "flyer" "target" "t106" "classname" "trigger_relay" "spawnflags" "2048" } { "model" "*70" "targetname" "t249" "spawnflags" "2060" "target" "t124" "wait" "5" "message" "DNA not on file..." "classname" "trigger_multiple" } { "origin" "776 1216 160" "spawnflags" "288" "angle" "0" "classname" "monster_turret" } { "origin" "1616 -320 56" "spawnflags" "288" "angle" "-2" "classname" "monster_turret" } { "origin" "216 -344 -152" "classname" "item_health" } { "spawnflags" "1536" "origin" "272 -344 -136" "classname" "item_health" } { "origin" "128 -608 -318" "classname" "ammo_shells" } { "origin" "680 -416 -248" "classname" "ammo_prox" } { "origin" "248 -832 -312" "classname" "weapon_proxlauncher" } { "origin" "288 -864 -324" "classname" "misc_deadsoldier" "spawnflags" "2048" } { "origin" "784 -368 -296" "classname" "item_health_large" } { "origin" "784 -416 -296" "classname" "item_health_large" } { "classname" "monster_turret" "angle" "270" "spawnflags" "816" "origin" "944 -616 -40" } { "origin" "1504 104 -48" "classname" "ammo_bullets" } { "origin" "1560 104 -48" "classname" "ammo_bullets" } { "origin" "2752 88 -112" "classname" "weapon_railgun" } { "origin" "2792 56 -128" "spawnflags" "2050" "classname" "misc_deadsoldier" } { "origin" "2856 -136 -112" "classname" "item_armor_shard" } { "origin" "2856 -88 -112" "classname" "item_armor_shard" } { "origin" "2856 -40 -112" "classname" "item_armor_shard" } { "origin" "2928 -536 -432" "classname" "item_ir_goggles" } { "origin" "1512 -128 -48" "classname" "item_armor_combat" } { "origin" "1552 -104 -64" "spawnflags" "2056" "classname" "misc_deadsoldier" } { "origin" "2408 -608 -432" "classname" "ammo_nails" } { "origin" "2400 -192 -432" "classname" "ammo_cells" "spawnflags" "0" } { "origin" "2208 -24 -240" "classname" "item_health_large" } { "origin" "2272 -24 -240" "classname" "item_health_large" } { "targetname" "t219" "classname" "monster_turret" "angle" "-2" "spawnflags" "800" "origin" "480 -96 48" } { "origin" "320 -328 -40" "spawnflags" "264" "angle" "270" "classname" "monster_turret" } { "origin" "2528 -224 -72" "spawnflags" "8" "angle" "-2" "classname" "monster_turret" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "288" "origin" "2272 -608 -72" } { "model" "*71" "classname" "func_wall" "spawnflags" "2304" } { "origin" "2424 -776 -240" "classname" "item_health_small" } { "origin" "2376 -776 -240" "classname" "item_health_small" } { "origin" "2328 -776 -240" "classname" "item_health_small" } { "origin" "2472 -776 -240" "classname" "item_health_small" } { "origin" "2280 -216 -240" "classname" "ammo_rockets" } { "origin" "1792 -280 -240" "classname" "item_health" } { "origin" "1536 -824 -240" "classname" "ammo_prox" } { "spawnflags" "1" "item" "ammo_grenades" "origin" "1352 -848 -232" "angle" "180" "classname" "monster_gunner" } { "origin" "1376 -1120 -240" "classname" "ammo_nails" } { "origin" "656 -1216 -240" "classname" "weapon_nailgun" } { "origin" "720 -1224 -256" "angle" "90" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "536 -1304 -240" "classname" "item_armor_shard" } { "origin" "544 -1256 -240" "classname" "item_armor_shard" } { "origin" "544 -1352 -240" "classname" "item_armor_shard" } { "origin" "1312 -1568 -240" "classname" "ammo_slugs" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "1032" "origin" "960 -1216 -16" } { "model" "*72" "spawnflags" "2304" "classname" "func_wall" } { "classname" "monster_turret" "angle" "-2" "spawnflags" "8" "origin" "2528 -576 -72" } { "origin" "584 -1120 -248" "target" "t216" "targetname" "t139" "classname" "path_corner" "spawnflags" "2048" } { "origin" "1336 -1160 -248" "targetname" "t216" //"target" "t215" // t215 does not exist in the level "classname" "path_corner" "spawnflags" "2048" } { "item" "ammo_cells" "origin" "1464 -560 -232" "classname" "monster_soldier_light" "angle" "0" "spawnflags" "1" } { "origin" "680 -1592 -160" "classname" "monster_turret" "angle" "90" "spawnflags" "800" } { "targetname" "t217" "origin" "1632 64 56" "classname" "monster_turret" "angle" "-2" "spawnflags" "8" } { "origin" "2272 -168 -72" "spawnflags" "288" "angle" "-2" "classname" "monster_turret" } { "origin" "1240 -1592 -160" "spawnflags" "800" "angle" "90" "classname" "monster_turret" } { "message" "Find cargo lift to\n Maintenance Hangars." "origin" "936 -1544 -184" "spawnflags" "2048" "targetname" "t214" "classname" "target_help" } { "spawnflags" "2049" "message" "Gain access to Maintenance\n Hangars." "origin" "1000 -1528 -200" "targetname" "t214" "classname" "target_help" } { "model" "*73" "target" "t214" "classname" "trigger_once" "spawnflags" "2048" } { "origin" "984 -1824 -232" "targetname" "sew2start" "classname" "info_player_coop" "angle" "90" } { "origin" "984 -1728 -232" "targetname" "sew2start" "classname" "info_player_coop" "angle" "90" } { "origin" "936 -1864 -232" "targetname" "sew2start" "classname" "info_player_coop" "angle" "90" } { "origin" "936 -1776 -232" "angle" "90" "targetname" "sew2start" "classname" "info_player_coop" } { "target" "t219" "classname" "monster_stalker" "angle" "180" "origin" "868 -92 -110" "spawnflags" "1" } { "spawnflags" "3" "origin" "252 -100 -110" "angle" "0" "classname" "monster_stalker" "targetname" "t287" } { "origin" "816 1816 96" "spawnflags" "1" "angle" "315" "classname" "monster_parasite" } { "model" "*74" "health" "25" "mass" "100" "dmg" "96" "classname" "func_explosive" } { "model" "*75" "health" "25" "mass" "100" "dmg" "96" "classname" "func_explosive" } { "targetname" "t275" "spawnflags" "1" "origin" "1984 1384 80" "classname" "item_armor_shard" } { "targetname" "t275" "spawnflags" "1" "origin" "1936 1384 80" "classname" "item_armor_shard" } { "targetname" "t275" "spawnflags" "1" "origin" "1888 1384 80" "classname" "item_armor_shard" } { "targetname" "t275" "spawnflags" "1" "origin" "2032 1384 80" "classname" "item_armor_shard" } { "targetname" "t275" "spawnflags" "1" "origin" "2272 1376 80" "classname" "item_health_large" } { "targetname" "t275" "spawnflags" "1" "origin" "2272 928 80" "classname" "item_health_large" } { "target" "t153" "origin" "2368 1344 280" "spawnflags" "1" "angle" "180" "classname" "monster_gladiator" } { "item" "ammo_cells" "origin" "2068 1728 366" "angle" "180" "spawnflags" "9" "classname" "monster_stalker" } { "item" "ammo_cells" "origin" "2068 576 366" "angle" "180" "spawnflags" "9" "classname" "monster_stalker" } { "model" "*76" "sounds" "4" "message" "Yellow lasers disabled." "wait" "-1" "target" "t151" "angle" "0" "classname" "func_button" "spawnflags" "2048" } { "origin" "2368 824 280" "angle" "180" "classname" "monster_medic_commander" "targetname" "t153" } { "item" "ammo_cells" "origin" "944 -540 -150" "target" "t150" "angle" "90" "spawnflags" "9" "classname" "monster_stalker" } { "classname" "monster_stalker" "origin" "2244 -732 -82" "angle" "90" "spawnflags" "9" } { "targetname" "t143" "origin" "656 -424 -104" "spawnflags" "1" "angle" "270" "classname" "monster_medic_commander" } { "target" "t149" "targetname" "t111" "delay" "14" "origin" "2568 -248 -416" "classname" "trigger_relay" "spawnflags" "2048" } { "target" "t149" "delay" "9" "origin" "2536 -248 -416" "targetname" "t111" "classname" "trigger_relay" "spawnflags" "2048" } { "model" "*77" "wait" "-1" "message" "Humanoid Lifeform dectected!" "targetname" "t149" "target" "t122" "spawnflags" "2056" "classname" "trigger_multiple" } { "origin" "2216 -72 -144" "angle" "270" "classname" "monster_daedalus" } { "target" "t217" "spawnflags" "9" "angle" "270" "origin" "2812 60 46" "classname" "monster_stalker" } { "origin" "-1600 1296 -424" "spawnflags" "2049" "noise" "world/steamy.wav" "classname" "target_speaker" } { "targetname" "t148" "classname" "target_speaker" "noise" "world/steamy.wav" "spawnflags" "2050" "origin" "-1600 656 -432" } { "targetname" "t148" "classname" "target_speaker" "noise" "world/steamy.wav" "spawnflags" "2050" "origin" "-1600 736 -432" } { "targetname" "t148" "origin" "-1608 696 -408" "spawnflags" "2050" "noise" "world/steamy.wav" "classname" "target_speaker" } { "targetname" "t147" "classname" "target_speaker" "noise" "world/steamy.wav" "spawnflags" "2050" "origin" "-1600 1264 -424" } { "classname" "target_speaker" "noise" "world/steamy.wav" "spawnflags" "2049" "origin" "-1600 696 -472" } { "targetname" "t147" "origin" "-1600 1232 -424" "spawnflags" "2050" "noise" "world/steamy.wav" "classname" "target_speaker" } { "classname" "light" "light" "125" "origin" "-960 896 -456" } { "origin" "-960 896 -72" "light" "125" "classname" "light" } { "origin" "-960 896 -264" "light" "125" "classname" "light" } { "origin" "-352 1408 16" "classname" "light" "light" "125" } { "model" "*78" "targetname" "t255" "spawnflags" "0" "_minlight" ".3" "lip" "16" "classname" "func_plat2" } { "light" "125" "classname" "light" "origin" "96 1952 -184" } { "origin" "-256 1184 212" "classname" "light" "light" "125" } { "origin" "-256 1440 212" "classname" "light" "light" "125" } { "origin" "-64 768 212" "classname" "light" "light" "125" } { "origin" "192 768 212" "classname" "light" "light" "125" } { "origin" "-328 1368 -168" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "light" "75" "classname" "light" "origin" "-168 768 196" } { "light" "125" "classname" "light" "origin" "-256 1696 212" } { "origin" "448 1024 84" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "-256 928 212" } { "light" "125" "classname" "light" "origin" "448 768 212" } { "light" "100" "classname" "light" "origin" "512 880 100" } { "classname" "light" "light" "100" "origin" "280 896 40" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "100" "origin" "136 1056 32" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "100" "origin" "224 1592 160" "_color" "1.000000 0.778226 0.028226" } { "light" "125" "classname" "light" "origin" "-256 1216 16" } { "light" "125" "classname" "light" "origin" "-256 1536 16" } { "light" "125" "classname" "light" "origin" "-512 896 -240" } { "_color" "1.000000 0.778226 0.028226" "origin" "472 1592 160" "light" "100" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "40 1056 184" "light" "100" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "704 1760 -416" "light" "100" "classname" "light" } { "origin" "-96 1952 -184" "classname" "light" "light" "125" } { "origin" "632 1216 -464" "classname" "light" "light" "150" "_color" "1.000000 0.000000 0.000000" } { "origin" "-608 1184 -88" "light" "100" "classname" "light" } { "classname" "light" "light" "200" "origin" "-608 1280 120" } { "origin" "-608 1152 120" "light" "200" "classname" "light" } { "origin" "-368 1056 -200" "light" "150" "classname" "light" } { "classname" "light" "light" "200" "origin" "2048 1152 376" } { "origin" "2176 1152 376" "light" "200" "classname" "light" } { "origin" "352 1952 -408" "light" "150" "classname" "light" } { "origin" "-328 992 -192" "light" "75" "classname" "light" } { "origin" "-344 1440 -272" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "origin" "-328 1368 -272" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "origin" "1760 -104 16" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "origin" "1752 -104 48" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "light" "150" "origin" "-368 1312 -200" } { "light" "125" "classname" "light" "origin" "-736 896 -240" } { "light" "125" "classname" "light" "origin" "-544 1760 -184" } { "origin" "448 1824 -200" "light" "180" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "-456 928 56" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "-456 1120 56" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "125" "origin" "-456 1312 56" "_color" "1.000000 0.778226 0.028226" } { "_color" "1.000000 0.778226 0.028226" "origin" "-456 1504 56" "light" "125" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "-760 1312 56" "light" "125" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "-760 1120 56" "light" "125" "classname" "light" } { "_color" "1.000000 0.778226 0.028226" "origin" "704 2016 -416" "light" "75" "classname" "light" } { "origin" "-256 856 196" "classname" "light" "light" "75" "spawnflags" "2048" } { "origin" "-416 1888 -184" "classname" "light" "light" "125" } { "origin" "-288 1952 -184" "classname" "light" "light" "125" } { "origin" "928 352 16" "classname" "light" "light" "125" } { "origin" "928 160 16" "classname" "light" "light" "125" } { "origin" "928 -32 16" "classname" "light" "light" "125" } { "style" "35" "spawnflags" "2048" "light" "75" "origin" "312 1672 -440" "classname" "light" "targetname" "t263" } { "style" "35" "light" "75" "origin" "392 1672 -440" "classname" "light" "targetname" "t263" "spawnflags" "2048" } { "style" "35" "light" "75" "origin" "432 1680 -488" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "spawnflags" "2048" } { "origin" "1240 1728 -432" "light" "100" "classname" "light" } { "classname" "light" "light" "125" "origin" "832 2072 -432" } { "classname" "light" "light" "125" "origin" "832 1824 -432" } { "classname" "light" "light" "75" "origin" "504 2200 -432" } { "classname" "light" "light" "150" "origin" "1184 1952 -408" } { "origin" "352 1632 -432" "light" "125" "classname" "light" "spawnflags" "5888" } { "origin" "1088 2080 -184" "light" "180" "classname" "light" } { "light" "100" "classname" "light" "origin" "960 1760 -416" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "100" "origin" "-32 1592 160" "_color" "1.000000 0.778226 0.028226" } { "light" "75" "classname" "light" "origin" "960 1872 -416" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "75" "origin" "704 1872 -416" "_color" "1.000000 0.778226 0.028226" } { "light" "75" "classname" "light" "origin" "960 2016 -416" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "125" "origin" "-760 928 56" "_color" "1.000000 0.778226 0.028226" } { "light" "150" "classname" "light" "origin" "704 2128 -416" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "150" "origin" "960 2128 -416" "_color" "1.000000 0.778226 0.028226" } { "classname" "light" "light" "180" "origin" "768 2080 -176" } { "classname" "light" "light" "180" "origin" "448 2080 -176" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "432 1680 -456" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "432 1680 -424" "light" "75" "spawnflags" "2048" } { "style" "35" "classname" "light" "_color" "1.000000 0.000000 0.000000" "targetname" "t263" "origin" "272 1680 -456" "light" "75" "spawnflags" "2048" } { "style" "35" "classname" "light" "_color" "1.000000 0.000000 0.000000" "targetname" "t263" "origin" "272 1680 -424" "light" "75" "spawnflags" "2048" } { "style" "35" "classname" "light" "_color" "1.000000 0.000000 0.000000" "targetname" "t263" "origin" "432 1680 -392" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "304 1680 -384" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "336 1680 -384" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "368 1680 -384" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "400 1680 -384" "light" "75" "spawnflags" "2048" } { "style" "35" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "t263" "origin" "272 1680 -488" "light" "75" "spawnflags" "2048" } { "style" "35" "classname" "light" "_color" "1.000000 0.000000 0.000000" "targetname" "t263" "origin" "272 1680 -392" "light" "75" "spawnflags" "2048" } { "origin" "1088 1824 -200" "light" "180" "classname" "light" } { "classname" "light" "light" "180" "origin" "768 1824 -200" } { "classname" "light" "light" "150" "origin" "352 1504 -424" } { "classname" "light" "light" "150" "origin" "1240 1152 184" } { "origin" "2208 608 200" "light" "150" "classname" "light" } { "origin" "2208 800 136" "light" "150" "classname" "light" } { "origin" "1240 1760 -64" "light" "150" "classname" "light" } { "origin" "360 2144 -440" "light" "150" "classname" "light" } { "origin" "2016 1728 312" "light" "150" "classname" "light" } { "origin" "1824 1248 248" "light" "100" "_color" "1.000000 0.501961 0.000000" "classname" "light" } { "origin" "1728 1152 192" "light" "100" "classname" "light" } { "classname" "light" "light" "150" "origin" "1240 1760 -248" } { "classname" "light" "light" "100" "origin" "-776 1120 -256" } { "light" "100" "_color" "1.000000 0.501961 0.000000" "classname" "light" "origin" "2400 832 352" } { "light" "100" "_color" "1.000000 0.501961 0.000000" "classname" "light" "origin" "2112 800 352" } { "classname" "light" "_color" "1.000000 0.501961 0.000000" "light" "100" "origin" "1824 1056 248" } { "origin" "2016 576 312" "light" "150" "classname" "light" } { "classname" "light" "light" "150" "origin" "2208 1696 200" } { "light" "100" "classname" "light" "origin" "1568 1152 192" } { "model" "*79" "health" "25" "classname" "func_explosive" "dmg" "96" "mass" "100" } { "classname" "monster_gunner" "angle" "180" "origin" "1280 1152 100" } { "origin" "432 -360 16" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" } { "light" "75" "classname" "light" "origin" "2816 -192 36" } { "light" "75" "classname" "light" "origin" "2816 -448 36" } { "origin" "2816 -704 36" "classname" "light" "light" "75" } { "origin" "1364 -1172 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "1324 -1132 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "256 -96 -40" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "608 -96 16" } { "light" "125" "classname" "light" "origin" "-1088 896 -456" } { "light" "125" "classname" "light" "origin" "-1856 896 -360" } { "light" "125" "classname" "light" "origin" "-608 1632 -184" } { "light" "125" "classname" "light" "origin" "800 -96 16" } { "light" "125" "classname" "light" "origin" "672 -224 16" } { "classname" "light" "light" "125" "origin" "928 544 16" } { "classname" "info_notnull" "targetname" "steamer1" "origin" "476 -844 -316" } { "targetname" "t142" "classname" "target_anger" "target" "t143" "origin" "872 -736 -312" "killtarget" "steamer1" "spawnflags" "2048" } { "model" "*80" "classname" "trigger_once" "target" "t142" "spawnflags" "2048" } { "targetname" "t150" "classname" "monster_gunner" "angle" "180" "spawnflags" "1" "origin" "1024 -672 -232" } { "spawnflags" "1" "angle" "270" "origin" "776 -392 -208" "classname" "monster_flyer" } { "classname" "monster_flyer" "origin" "664 -440 -208" "angle" "270" "spawnflags" "1" } { "origin" "544 -936 -240" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "45" } { "origin" "520 -936 -168" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "584 -920 -128" } { "light" "45" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "536 -912 -112" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "984 -944 -216" } { "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" "origin" "176 -360 16" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "64 -800 40" } { "origin" "80 -856 8" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "128 -864 40" } { "light" "75" "classname" "light" "origin" "432 -520 -208" } { "light" "125" "classname" "light" "origin" "296 -624 -208" } { "light" "105" "classname" "light" "origin" "144 -600 -208" } { "light" "115" "classname" "light" "origin" "72 -720 -152" } { "light" "115" "classname" "light" "origin" "112 -856 -200" } { "light" "115" "classname" "light" "origin" "-72 -912 -208" } { "classname" "light" "light" "95" "origin" "-40 -576 -144" } { "origin" "0 -976 -224" "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" } { "light" "100" "classname" "light" "origin" "736 -480 -172" } { "classname" "light" "light" "100" "origin" "608 -480 -172" } { "light" "125" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "800 -368 -232" } { "origin" "-88 -928 -64" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "368 -488 40" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "792 -456 16" "light" "100" "_color" "1.000000 1.000000 0.000000" "classname" "light" } { "origin" "1008 -888 -120" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "light" "75" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "368 -552 -312" } { "classname" "light" "_color" "1.000000 1.000000 0.000000" "light" "100" "origin" "944 -656 16" } { "light" "75" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "336 -552 -312" } { "light" "75" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "248 -544 -320" } { "light" "75" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "224 -552 -320" } { "light" "65" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "-112 -424 -48" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "416 -496 8" } { "light" "100" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "-104 -720 -32" } { "light" "65" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "-96 -424 -160" } { "light" "65" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "-104 -384 -40" } { "origin" "432 -552 40" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "100" } { "origin" "-104 -376 -104" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "65" } { "origin" "-120 -448 -96" "classname" "light" "_color" "0.000000 0.000000 1.000000" "light" "65" } { "light" "65" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "-104 -376 -160" } { "light" "50" "_color" "0.000000 0.000000 1.000000" "classname" "light" "origin" "960 -912 -104" } { "classname" "target_speaker" "noise" "world/steamy.wav" "spawnflags" "1" "targetname" "steamer1" "origin" "496 -848 -304" } { "origin" "1768 -560 -232" "classname" "monster_soldier_light" "angle" "180" "spawnflags" "257" } { "spawnflags" "1" "angle" "0" "classname" "monster_soldier_light" "origin" "544 -1120 -232" "target" "t139" } { "classname" "monster_gunner" "angle" "0" "spawnflags" "1" "origin" "2032 64 -40" } { "item" "ammo_slugs" "classname" "monster_gladiator" "angle" "270" "spawnflags" "1" "origin" "2248 64 -40" } { "spawnflags" "2049" "noise" "world/force1.wav" "origin" "-768 1060 -244" "classname" "target_speaker" "targetname" "t263" } { "spawnflags" "2049" "noise" "world/force1.wav" "origin" "-768 1036 -308" "classname" "target_speaker" "targetname" "t263" } { "wait" "5" "random" "2.5" "origin" "2212 156 -40" "classname" "func_timer" "target" "t136" "targetname" "t123" "spawnflags" "2048" } { "classname" "target_splash" "angle" "315" "sounds" "1" "targetname" "t136" "origin" "2224 116 -40" "spawnflags" "2048" } { "origin" "2544 -616 -416" "classname" "trigger_relay" "delay" "7" "targetname" "t114" "target" "t135" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "2576 -608 -416" "targetname" "t114" "target" "t135" "spawnflags" "2048" } { "classname" "target_speaker" "noise" "world/scan1.wav" "origin" "2504 -400 -376" "targetname" "t135" "spawnflags" "2050" } { "classname" "target_speaker" "noise" "world/scan1.wav" "origin" "2464 -400 -376" "targetname" "t135" "spawnflags" "2050" } { "classname" "target_speaker" "noise" "world/scan1.wav" "origin" "2544 -400 -376" "targetname" "t135" "spawnflags" "2050" } { "model" "*81" "spawnflags" "2048" "classname" "trigger_multiple" "wait" "5" "message" "Scanner inactive." "targetname" "scan2" } { "model" "*82" "classname" "trigger_once" "targetname" "t124" "killtarget" "scan2" "spawnflags" "2048" } { "model" "*83" "classname" "trigger_once" "targetname" "t124" "target" "t134" "spawnflags" "2048" } { "classname" "target_speaker" "origin" "2136 64 -24" "noise" "world/l_hum1.wav" "spawnflags" "2049" "targetname" "t126" } { "classname" "target_speaker" "origin" "2136 96 -24" "noise" "world/l_hum1.wav" "spawnflags" "2049" "targetname" "t126" } { "classname" "target_speaker" "origin" "2136 32 -24" "noise" "world/l_hum1.wav" "spawnflags" "2049" "targetname" "t126" } { "model" "*84" "classname" "trigger_multiple" "spawnflags" "2052" "target" "t133" "targetname" "t134" } { "classname" "target_speaker" "origin" "320 1672 -456" "noise" "world/force1.wav" "spawnflags" "2049" "targetname" "t263" } { "origin" "384 1668 -460" "classname" "target_speaker" "noise" "world/force1.wav" "spawnflags" "2049" "targetname" "t263" } { "noise" "world/fan1.wav" "spawnflags" "2049" "classname" "target_speaker" "origin" "3016 -584 -384" "targetname" "t123" } { "classname" "target_speaker" "spawnflags" "2049" "noise" "world/fan1.wav" "origin" "3016 -560 -384" "targetname" "t123" } { "classname" "target_speaker" "origin" "1104 -1520 -320" "noise" "world/steam2.wav" "targetname" "t130" } { "classname" "target_speaker" "origin" "1064 -1360 -312" "noise" "world/steam2.wav" "targetname" "t129" } { "noise" "world/steam2.wav" "origin" "792 -1544 -304" "classname" "target_speaker" "targetname" "t131" } { "classname" "target_speaker" "origin" "824 -1360 -304" "noise" "world/steam2.wav" "targetname" "t132" } { "random" "2" "classname" "func_timer" "target" "t132" "origin" "800 -1352 -320" "spawnflags" "1" "wait" "10" } { "classname" "func_timer" "random" "2" "wait" "11" "target" "t131" "origin" "832 -1536 -320" "spawnflags" "1" } { "classname" "func_timer" "wait" "9" "random" "2.5" "target" "t130" "origin" "1128 -1512 -320" "spawnflags" "1" } { "classname" "func_timer" "spawnflags" "1" "wait" "7" "target" "t129" "origin" "1128 -1344 -320" "random" ".4" } { "classname" "target_steam" "angle" "-1" "speed" "75" "count" "48" "targetname" "t129" "origin" "1064 -1352 -328" "wait" "1.5" } { "count" "48" "speed" "125" "angle" "-1" "classname" "target_steam" "targetname" "t130" "origin" "1104 -1528 -328" "wait" "1.5" } { "count" "64" "speed" "150" "angle" "-1" "classname" "target_steam" "targetname" "t132" "origin" "824 -1368 -328" "wait" "1.5" } { "classname" "target_steam" "angle" "-1" "speed" "175" "count" "50" "targetname" "t131" "origin" "792 -1544 -328" "wait" "1.5" } { "targetname" "t263" "attenuation" "-1" "origin" "-1972 972 -160" "noise" "world/redforce.wav" "classname" "target_speaker" "spawnflags" "2048" } { "model" "*85" "targetname" "t122" "spawnflags" "2052" "classname" "trigger_once" "target" "t128" } { "classname" "func_timer" "origin" "2108 156 -40" "random" ".5" "wait" "2" "targetname" "t123" "target" "t126" "spawnflags" "2048" } { "light" "75" "classname" "light" "origin" "1800 -168 -32" } { "attenuation" "-1" "origin" "2808 -120 -376" "noise" "world/klaxon1.wav" "spawnflags" "2054" "classname" "target_speaker" "targetname" "t125" } { "attenuation" "-1" "origin" "2712 -264 -376" "noise" "world/klaxon1.wav" "spawnflags" "2054" "classname" "target_speaker" "targetname" "t125" } { "attenuation" "-1" "origin" "2488 -392 -376" "noise" "world/klaxon1.wav" "spawnflags" "2054" "classname" "target_speaker" "targetname" "t125" } { "attenuation" "-1" "origin" "2696 -584 -376" "noise" "world/klaxon1.wav" "spawnflags" "2054" "classname" "target_speaker" "targetname" "t125" } { "classname" "trigger_relay" "targetname" "t122" "target" "t125" "origin" "2632 -560 -376" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t122" "delay" "9" "target" "t125" "origin" "2672 -544 -376" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t124" "message" "Use Med Scanner to encode system access" "origin" "2296 96 -40" "delay" "2" "spawnflags" "2048" } { "origin" "2976 -576 -352" "classname" "light" "light" "75" } { "classname" "target_speaker" "spawnflags" "2054" "noise" "world/klaxon1.wav" "origin" "2472 -600 -376" "attenuation" "-1" "targetname" "t125" } { "style" "36" "origin" "2136 112 -48" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "targetname" "t126" "spawnflags" "2048" } { "style" "36" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2136 112 -8" "targetname" "t126" "spawnflags" "2048" } { "style" "36" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2136 112 32" "targetname" "t126" "spawnflags" "2048" } { "style" "36" "origin" "2136 16 -8" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "targetname" "t126" "spawnflags" "2048" } { "style" "36" "origin" "2136 16 32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "targetname" "t126" "spawnflags" "2048" } { "origin" "1456 -40 16" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" } { "classname" "trigger_relay" "targetname" "t123" "killtarget" "lasbrush" "origin" "3040 -520 -384" "message" "Laser power interrupted." "spawnflags" "2048" } { "model" "*86" "spawnflags" "2055" "classname" "func_wall" "targetname" "t126" } { "classname" "target_explosion" "dmg" "64" "targetname" "t123" "origin" "3024 -576 -384" "spawnflags" "2048" } { "model" "*87" "classname" "func_explosive" "health" "10" "target" "t123" "spawnflags" "2048" } { "classname" "monster_gunner" "angle" "180" "origin" "2992 -544 -424" "targetname" "t122" "spawnflags" "1" } { "classname" "monster_gunner" "angle" "180" "origin" "2952 -608 -424" "targetname" "t122" "spawnflags" "1" } { "angle" "270" "spawnflags" "2051" "classname" "target_laser" "origin" "2136 120 -8" "dmg" "1000" "targetname" "t126" } { "angle" "270" "spawnflags" "2051" "classname" "target_laser" "origin" "2136 120 32" "dmg" "1000" "targetname" "t126" } { "classname" "target_laser" "spawnflags" "2051" "angle" "270" "origin" "2136 120 -48" "dmg" "1000" "targetname" "t126" } { "origin" "2816 -64 -192" "classname" "light" "light" "75" } { "light" "100" "classname" "light" "origin" "1416 -400 -168" } { "model" "*88" "classname" "trigger_once" "target" "t121" "spawnflags" "2048" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t120" "origin" "1736 -180 -40" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t119" "origin" "1500 -192 -40" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "origin" "-264 992 176" } { "style" "36" "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2136 16 -48" "targetname" "t126" "spawnflags" "2048" } { "light" "75" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "1456 -40 -16" } { "light" "50" "classname" "light" "origin" "1480 -56 48" } { "light" "75" "classname" "light" "origin" "1616 -96 32" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "75" "origin" "1456 -152 -8" } { "classname" "monster_gunner" "angle" "270" "spawnflags" "1" "origin" "1664 -112 -24" "target" "t120" "targetname" "t121" } { "model" "*89" "message" "Waste storage and processing opened." "target" "t110" "classname" "func_button" "angle" "0" "wait" "-1" "targetname" "t128" "sounds" "4" "spawnflags" "2048" } { "light" "75" "classname" "light" "origin" "1792 96 36" } { "origin" "1480 -24 48" "classname" "light" "light" "50" } { "light" "75" "classname" "light" "origin" "2096 -400 -160" "_color" "1.000000 0.811475 0.045082" } { "origin" "2208 112 -32" "classname" "light" "light" "75" "spawnflags" "2048" } { "light" "75" "classname" "light" "origin" "2816 64 36" } { "origin" "2560 64 36" "classname" "light" "light" "75" } { "light" "75" "classname" "light" "origin" "2304 64 36" } { "light" "100" "classname" "light" "origin" "3024 -576 -384" "_color" "1.000000 0.000000 0.000000" "style" "37" "targetname" "t123" "spawnflags" "2048" } { "origin" "2816 -480 -216" "classname" "light" "light" "75" } { "origin" "2208 -400 -96" "classname" "light" "light" "75" } { "origin" "2728 -344 -416" "classname" "trigger_relay" "delay" "11" "targetname" "t111" "target" "t116" "spawnflags" "2048" } { "speed" "3" "message" "az" "classname" "target_lightramp" "targetname" "t114" "spawnflags" "2048" "target" "t115" "origin" "2704 -424 -416" } { "classname" "target_lightramp" "message" "za" "speed" "3" "origin" "2776 -400 -416" "targetname" "t116" "target" "t115" "spawnflags" "2048" } { "style" "38" "classname" "light" "_color" "0.000000 0.501961 1.000000" "spawnflags" "2049" "targetname" "t115" "origin" "2488 -400 -376" } { "origin" "2728 -544 -416" "classname" "trigger_relay" "delay" "5" "target" "t114" "targetname" "t111" "spawnflags" "2048" } { "model" "*90" "classname" "func_door" "spawnflags" "2049" "angle" "180" "lip" "-128" "targetname" "t114" "speed" "75" } { "origin" "2608 -248 -416" "classname" "trigger_relay" "delay" "14" "target" "t113" "targetname" "t111" "spawnflags" "2048" } { "delay" "4" "classname" "trigger_relay" "target" "t113" "targetname" "t111" "origin" "2696 -296 -416" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t111" "target" "t112" "delay" "2" "origin" "2432 -200 -416" "spawnflags" "2048" } { "model" "*91" "classname" "func_door" "spawnflags" "2053" "angle" "-2" "targetname" "t112" "speed" "200" "wait" "11" "_minlight" ".3" "dmg" "1000" "sounds" "1" } { "model" "*92" "classname" "func_wall" "spawnflags" "2051" "targetname" "t113" } { "model" "*93" "origin" "2508 -308 -444" "classname" "func_door_rotating" "spawnflags" "70" "distance" "90" "targetname" "t111" "wait" "15" "_minlight" ".3" "dmg" "1000" "sounds" "3" } { "model" "*94" "origin" "2588 -400 -444" "classname" "func_door_rotating" "spawnflags" "132" "distance" "90" "targetname" "t111" "wait" "15" "_minlight" ".3" "dmg" "1000" "sounds" "3" } { "model" "*95" "origin" "2508 -492 -444" "classname" "func_door_rotating" "spawnflags" "68" "distance" "90" "targetname" "t111" "wait" "15" "_minlight" ".3" "dmg" "1000" "sounds" "3" } { "model" "*96" "angle" "180" "classname" "func_button" "target" "t111" "wait" "18" "message" "Scan initiated." "targetname" "t133" "spawnflags" "2048" } { "light" "75" "classname" "light" "origin" "960 -1728 -144" } { "light" "75" "classname" "light" "origin" "2048 96 36" } { "_color" "1.000000 0.811475 0.045082" "origin" "1968 -400 -160" "classname" "light" "light" "75" } { "_color" "1.000000 0.811475 0.045082" "origin" "1056 -1456 -272" "classname" "light" "light" "75" } { "light" "75" "classname" "light" "origin" "1088 -1200 -40" } { "model" "*97" "classname" "func_door" "angle" "-2" "team" "forcedoor" "speed" "15" "targetname" "t110" "wait" "-1" "sounds" "4" "message" "This door is locked." "spawnflags" "2048" } { "model" "*98" "classname" "func_door" "angle" "-1" "team" "forcedoor" "speed" "15" "targetname" "t110" "wait" "-1" "sounds" "4" "spawnflags" "2048" } { "classname" "item_health" "origin" "880 -1048 -240" } { "classname" "item_health" "origin" "928 -1096 -240" } { "classname" "item_double" "origin" "672 -672 -416" } { "classname" "target_secret" "targetname" "t107" "origin" "832 -1144 -240" } { "model" "*99" "classname" "trigger_once" "target" "t107" "message" "You found a secret!" } { "spawnflags" "258" "classname" "monster_flyer" "targetname" "flyer" "origin" "1168 -832 -40" } { "spawnflags" "2" "classname" "monster_flyer" "targetname" "flyer" "origin" "1632 -864 -40" } { "classname" "monster_flyer" "targetname" "flyer" "origin" "1600 -824 -40" "spawnflags" "770" } { "classname" "monster_flyer" "spawnflags" "2" "targetname" "flyer" "origin" "1184 -872 -40" } { "dmg" "32" "delay" ".1" "classname" "target_explosion" "targetname" "t106" "origin" "1608 -856 -128" "spawnflags" "2048" } { "delay" ".2" "classname" "target_explosion" "targetname" "t106" "origin" "1592 -824 -120" "spawnflags" "2048" } { "delay" ".1" "classname" "target_explosion" "targetname" "t106" "origin" "1176 -872 -136" "spawnflags" "2048" } { "classname" "target_explosion" "targetname" "t106" "origin" "1144 -824 -120" "spawnflags" "2048" } { "classname" "target_explosion" "delay" "" "targetname" "t106" "origin" "1648 -880 -128" "spawnflags" "2048" } { "model" "*100" "target" "flyer" "classname" "trigger_once" "spawnflags" "2048" } { "origin" "864 -1456 -272" "classname" "light" "light" "75" "_color" "1.000000 0.811475 0.045082" } { "origin" "1088 -1488 -40" "classname" "light" "light" "75" } { "origin" "768 -1200 -40" "classname" "light" "light" "75" } { "origin" "736 -912 -400" "classname" "light" "light" "75" } { "origin" "736 -1120 -304" "classname" "light" "light" "75" } { "light" "75" "classname" "light" "origin" "720 -832 -400" } { "light" "75" "classname" "light" "origin" "752 -1040 -368" } { "light" "75" "classname" "light" "origin" "744 -1056 -336" } { "classname" "light" "light" "75" "origin" "704 -768 -400" } { "light" "75" "classname" "light" "origin" "768 -1488 -40" } { "light" "75" "classname" "light" "origin" "1824 -400 -160" "_color" "1.000000 0.811475 0.045082" } { "targetname" "t103" "random" "1" "classname" "func_timer" "target" "t105" "origin" "680 -1124 -248" "wait" "2" } { "sounds" "1" "classname" "target_splash" "targetname" "t105" "origin" "720 -1108 -272" "angle" "270" } { "classname" "target_splash" "sounds" "1" "targetname" "t104" "origin" "720 -1208 -272" "angle" "90" } { "classname" "func_timer" "random" "2" "target" "t104" "targetname" "t103" "origin" "740 -1200 -248" "wait" "3" } { "origin" "1364 -1516 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "596 -1068 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "556 -1108 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "556 -1516 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "596 -1556 -104" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "origin" "864 -1608 -200" "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" } { "classname" "target_explosion" "dmg" "32" "targetname" "t103" "origin" "688 -1144 -248" "delay" ".2" } { "classname" "target_explosion" "targetname" "t103" "dmg" "32" "origin" "696 -1192 -264" } { "classname" "target_explosion" "dmg" "32" "targetname" "t103" "origin" "736 -1160 -256" "delay" ".1" } { "classname" "target_explosion" "dmg" "32" "targetname" "t103" "origin" "712 -1120 -272" } { "map" "rsewer1$sew1end" "origin" "960 -1912 -248" "targetname" "t102" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*101" "target" "t102" "classname" "trigger_multiple" "angle" "270" "spawnflags" "2048" } { "origin" "960 -1632 -180" "classname" "light" "light" "75" } { "origin" "960 -1888 -144" "light" "75" "classname" "light" } { "targetname" "t26" "origin" "1160 656 -80" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*102" "spawnflags" "4" "targetname" "t318" "classname" "func_plat2" "lip" "16" "_minlight" ".3" } { "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" "origin" "1048 -1608 -200" } { "light" "100" "_color" "1.000000 0.714876 0.053719" "classname" "light" "origin" "960 -1608 -96" } { "classname" "light" "_color" "1.000000 0.714876 0.053719" "light" "100" "origin" "1324 -1556 -104" } { "model" "*103" "health" "10" "target" "t253" "classname" "func_explosive" "mass" "200" "spawnflags" "2048" } { "model" "*104" "health" "10" "target" "t254" "classname" "func_explosive" "mass" "200" "spawnflags" "2048" } { "origin" "-1952 896 -440" "spawnflags" "1" "angle" "0" "classname" "monster_gunner" } { "spawnflags" "257" "origin" "-1320 1248 -424" "classname" "monster_gunner" "angle" "225" } { "spawnflags" "2305" "origin" "-2016 544 -200" "classname" "monster_flyer" "angle" "45" } { "spawnflags" "2305" "origin" "-2016 1248 -200" "classname" "monster_flyer" "angle" "315" } { "model" "*105" "targetname" "t56" "classname" "func_explosive" "mass" "200" } { "model" "*106" "spawnflags" "768" "targetname" "t56" "classname" "func_explosive" "mass" "200" } { "model" "*107" "spawnflags" "256" "mass" "200" "targetname" "t56" "classname" "func_explosive" } { "targetname" "t266" "target" "t56" "origin" "-1256 896 -360" "spawnflags" "1" "angle" "180" "classname" "monster_gladiator" } { "targetname" "t56" "classname" "monster_turret" "spawnflags" "928" "angle" "0" "origin" "-2208 768 -192" } { "targetname" "t56" "origin" "-2208 1024 -192" "angle" "0" "spawnflags" "160" "classname" "monster_turret" } { "targetname" "t56" "classname" "monster_turret" "spawnflags" "160" "angle" "180" "origin" "-1120 768 -192" } { "targetname" "t56" "origin" "-1120 1024 -192" "angle" "180" "spawnflags" "416" "classname" "monster_turret" } { "model" "*108" "targetname" "t52" "dmg" "500" "classname" "trigger_hurt" "spawnflags" "2048" } { "origin" "-1600 688 -472" "spawnflags" "2049" "targetname" "floorpipe" "target" "t55" "classname" "func_timer" } { "origin" "-1604 692 -480" "sounds" "6" "count" "16" "speed" "50" "angle" "-1" "targetname" "t55" "classname" "target_steam" "spawnflags" "2048" } { "origin" "-1600 1304 -416" "targetname" "steampipe" "spawnflags" "2049" "target" "t54" "classname" "func_timer" } { "origin" "-1600 1320 -424" "targetname" "t54" "sounds" "6" "count" "16" "speed" "20" "angle" "270" "classname" "target_steam" "spawnflags" "2048" } { "origin" "-1528 768 -472" "target" "t53" "targetname" "t52" "classname" "func_timer" "spawnflags" "2048" } { "model" "*109" "dmg" "15" "targetname" "t52" "spawnflags" "2051" "classname" "trigger_hurt" } { "origin" "-1624 688 -480" "delay" ".2" "targetname" "t52" "classname" "target_explosion" "spawnflags" "2048" } { "origin" "-1584 704 -488" "delay" ".3" "targetname" "t52" "classname" "target_explosion" "spawnflags" "2048" } { "origin" "-1600 664 -496" "targetname" "t52" "classname" "target_explosion" "spawnflags" "2048" } { "target" "t148" "origin" "-1608 720 -480" "delay" ".2" "dmg" "128" "targetname" "t52" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*110" "spawnflags" "2048" "target" "t51" "classname" "trigger_once" } { "origin" "-1520 720 -472" "killtarget" "floorpipe" "target" "t47" "targetname" "t51" "classname" "target_anger" "spawnflags" "2048" } { "targetname" "t53" "origin" "-1600 688 -528" "sounds" "6" "count" "96" "speed" "200" "angle" "-1" "classname" "target_steam" "spawnflags" "2048" } { "origin" "-1604 684 -468" "targetname" "floorpipe" "classname" "info_notnull" "spawnflags" "2048" } { "model" "*111" "health" "5" "spawnflags" "2048" "target" "t52" "killtarget" "floorpipe" "mass" "800" "classname" "func_explosive" } { "origin" "520 -832 -280" "targetname" "steamer1" "target" "t50" "spawnflags" "1" "classname" "func_timer" } { "model" "*112" "classname" "trigger_hurt" "dmg" "15" "targetname" "t48" "spawnflags" "2051" } { "classname" "func_timer" "targetname" "t48" "target" "t49" "origin" "-1512 1336 -416" "spawnflags" "2048" } { "target" "t147" "dmg" "128" "classname" "target_explosion" "origin" "-1608 1320 -440" "targetname" "t48" "spawnflags" "2048" } { "delay" ".1" "dmg" "128" "classname" "target_explosion" "targetname" "t48" "origin" "-1584 1320 -424" "spawnflags" "2048" } { "delay" ".2" "dmg" "128" "classname" "target_explosion" "origin" "-1616 1320 -408" "targetname" "t48" "spawnflags" "2048" } { "classname" "target_explosion" "dmg" "128" "origin" "-1592 1320 -400" "targetname" "t48" "spawnflags" "2048" } { "target" "t266" "classname" "target_anger" "targetname" "t46" "origin" "-1528 1296 -440" "killtarget" "steampipe" "spawnflags" "2048" } { "model" "*113" "spawnflags" "2048" "classname" "trigger_once" "target" "t46" } { "classname" "info_notnull" "origin" "-1600 1308 -416" "targetname" "steampipe" "spawnflags" "2048" } { "count" "75" "speed" "150" "classname" "target_steam" "angle" "270" "origin" "-1600 1320 -416" "targetname" "t49" "sounds" "6" "spawnflags" "2048" } { "model" "*114" "health" "20" "mass" "10" "classname" "func_explosive" "target" "t103" } { "targetname" "t50" "classname" "target_steam" "count" "32" "sounds" "208" "origin" "496 -848 -320" "angle" "-1" } { "model" "*115" "origin" "448 1408 -54" "accel" "1" "targetname" "t269" "classname" "func_rotating" "spawnflags" "10240" "speed" "500" } { "model" "*116" "origin" "-448 1064 -432" "targetname" "doors" "wait" "2.5" "distance" "90" "spawnflags" "6" "classname" "func_door_rotating" } { "model" "*117" "targetname" "t257" "height" "184" "classname" "func_plat2" "_minlight" ".2" "spawnflags" "2" "speed" "100" } { "model" "*118" "spawnflags" "2048" "classname" "func_wall" } { "targetname" "t45" "classname" "target_explosion" "dmg" "256" "origin" "408 1152 -1040" "delay" ".3" "spawnflags" "2048" } { "target" "t45" "targetname" "t44" "delay" ".3" "origin" "424 1200 -1104" "dmg" "256" "classname" "target_explosion" "spawnflags" "2048" } { "origin" "-64 800 -388" "targetname" "t44" "angle" "-1" "classname" "target_steam" "speed" "150" "count" "96" "wait" "8" "sounds" "208" "spawnflags" "2048" } { "origin" "-64 1560 -388" "targetname" "t43" "angle" "-1" "sounds" "208" "wait" "8" "count" "96" "speed" "150" "classname" "target_steam" "spawnflags" "2048" } { "classname" "target_explosion" "dmg" "256" "origin" "392 1216 -1232" "targetname" "t42" "delay" ".3" "target" "t43" "spawnflags" "2048" } { "classname" "target_explosion" "dmg" "256" "origin" "448 1168 -1296" "targetname" "t41" "delay" ".3" "target" "t42" "spawnflags" "2048" } { "classname" "target_explosion" "dmg" "256" "origin" "376 1184 -1360" "targetname" "t40" "delay" ".3" "target" "t41" "spawnflags" "2048" } { "classname" "target_explosion" "dmg" "256" "origin" "416 1184 -1424" "targetname" "explo" "target" "t40" "spawnflags" "2048" } { "target" "t44" "classname" "target_explosion" "dmg" "256" "origin" "456 1208 -1168" "targetname" "t43" "delay" ".3" "spawnflags" "2048" } { "style" "39" "origin" "288 1120 -488" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "spawnflags" "2049" } { "style" "39" "origin" "288 1248 -488" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "spawnflags" "2049" } { "origin" "-160 1024 -496" "classname" "trigger_relay" "target" "t39" "targetname" "doors" "delay" "2" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "32 1376 -496" "target" "t39" "targetname" "light2" "delay" "1" "spawnflags" "2048" } { "model" "*119" "classname" "trigger_hurt" "dmg" "500" "targetname" "t39" "spawnflags" "2059" "message" "Player was electrocuted." } { "origin" "-192 896 -488" "message" "az" "spawnflags" "2048" "speed" "1" "classname" "target_lightramp" "target" "uplight" "targetname" "doors" } { "classname" "target_lightramp" "speed" "3" "spawnflags" "2048" "message" "za" "origin" "-224 1536 -488" "targetname" "door2" "target" "uplight" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-560 1240 -544" "spawnflags" "1" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-560 1128 -544" "spawnflags" "1" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-544 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-544 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-480 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-480 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-416 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-416 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-352 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-352 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-288 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-288 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-224 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-224 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-160 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-160 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-96 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-96 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-32 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-32 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "32 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "32 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "96 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "96 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "160 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "160 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "224 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "224 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "352 1248 -488" "spawnflags" "2049" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "352 1120 -488" "spawnflags" "2049" } { "style" "39" "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "targetname" "uplight" "origin" "-656 1128 -544" "spawnflags" "1" } { "style" "39" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "targetname" "uplight" "origin" "-664 1240 -544" "spawnflags" "1" } { "origin" "320 1088 -512" "classname" "path_corner" "target" "t36" "targetname" "t38" "pathtarget" "light2" "spawnflags" "2048" } { "classname" "path_corner" "targetname" "t36" "target" "t37" "origin" "320 1088 -1576" "pathtarget" "explo" "speed" "400" "spawnflags" "2048" } { "classname" "path_corner" "targetname" "t35" "origin" "152 1088 -512" "pathtarget" "door2" "target" "t38" "spawnflags" "2048" } { "classname" "path_corner" "targetname" "t34" "target" "t35" "origin" "-704 1088 -512" "pathtarget" "doors" "spawnflags" "2048" } { "classname" "path_corner" "targetname" "t37" "target" "t34" "origin" "-704 1088 -1584" "speed" "200" "spawnflags" "2048" } { "classname" "info_notnull" "targetname" "gladbox" "origin" "1132 804 -108" "spawnflags" "2048" } { "classname" "monster_gladiator" "targetname" "t30" "origin" "808 1296 -104" "spawnflags" "1" "item" "ammo_slugs" } { "classname" "target_anger" "target" "t30" "targetname" "t31" "killtarget" "gladbox" "origin" "1080 816 -104" "spawnflags" "2048" } { "model" "*120" "classname" "trigger_once" "target" "t31" "spawnflags" "2048" } { "origin" "1216 704 96" "spawnflags" "1" "angle" "180" "classname" "monster_parasite" } { "model" "*121" "message" "Incenerator Activated." "wait" "-1" "angle" "0" "classname" "func_button" "target" "t33" "spawnflags" "2048" } { "model" "*122" "classname" "func_train" "targetname" "t33" "dmg" "1000" "_minlight" ".2" "target" "t37" "speed" "200" "spawnflags" "2048" } { "model" "*123" "origin" "-448 1304 -432" "classname" "func_door_rotating" "spawnflags" "4" "distance" "90" "targetname" "doors" "wait" "2.5" } { "model" "*124" "spawnflags" "2054" "classname" "func_wall" "targetname" "t263" } { "model" "*125" "origin" "260 1664 -372" "wait" "-1" "distance" "-90" "spawnflags" "2212" "classname" "func_door_rotating" "targetname" "t263" } { "model" "*126" "origin" "444 1664 -508" "distance" "90" "spawnflags" "2214" "classname" "func_door_rotating" "targetname" "t263" } { "model" "*127" "targetname" "t33" "wait" "-1" "classname" "func_door" "angle" "-2" "speed" "5" "spawnflags" "2080" "team" "bigdoor" } { "model" "*128" "targetname" "t33" "wait" "-1" "classname" "func_door" "angle" "-1" "speed" "5" "spawnflags" "2080" "team" "bigdoor" } { "model" "*129" "classname" "func_door" "angle" "-1" "sounds" "2" } { "model" "*130" "mass" "100" "dmg" "96" "classname" "func_explosive" } { "targetname" "t26" "classname" "target_explosion" "origin" "1184 688 -104" "spawnflags" "2048" } { "origin" "1184 720 -96" "targetname" "t26" "classname" "target_explosion" "spawnflags" "2048" } { "dmg" "128" "origin" "1144 704 -104" "targetname" "t26" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*131" "origin" "1184 704 -120" "dmg" "10000" "distance" "82.5" "targetname" "t26" "speed" "175" "spawnflags" "2222" "classname" "func_door_rotating" "_minlight" ".2" } { "model" "*132" "target" "t26" "classname" "func_explosive" "killtarget" "gladbox" "spawnflags" "2048" "health" "10" } { "model" "*133" "health" "5" "spawnflags" "2048" "classname" "func_explosive" "mass" "300" "target" "t48" "killtarget" "steampipe" } { "model" "*134" "health" "25" "killtarget" "steamer1" "mass" "800" "classname" "func_explosive" "target" "t317" } { "origin" "-608 1424 -104" "light" "150" "classname" "light" } { "origin" "2208 1504 136" "light" "150" "classname" "light" }rogue-ROGUE_2_13/stuff/mapfixes/rware2.ent000066400000000000000000003677701477320066100205110ustar00rootroot00000000000000// FIXED ENTITY STRING (by BjossiAlfreds) // // 1. Fixed unreachable monster_soldier (2690) // // This guy was set to a triggered spawn but has no targetname. // Changed his spawnflags from 2051 to 2049. // // 2. Fixed console warning for monster_stalker (5942) // // Changed his spawnflags from 2057 to 2825 (Hard only). // And spawned another monster_stalker (8313) (same guy) with // spawnflags 3081 (Easy + Medium). // // 3. Raised item_pack vertically (89) // // This Ammo Pack had a tendency to be in solid, so I raised it up // a few units on vertical axis. // // 4. Moved item_armor_jacket (207) out of a wall // // This Jacket Armor was spawning partially inside a wall // so I lowered its X-positioning a bit (1664 to 1624). // // 5. Silenced warning for monster_stalker (5078) // // He spawns on all difficulties but his targets (t119) are // not present on easy or medium. Fixed by giving him a // dummy target (3000) just so he has "something" to target. { "classname" "worldspawn" "message" "Waterfront Storage" "nextmap" "rbase1" "sky" "rogue1" "sounds" "3" } { "model" "*1" "targetname" "t163" "target" "t164" "spawnflags" "2816" "classname" "func_explosive" } { "model" "*2" "spawnflags" "3328" "target" "t155" "classname" "func_explosive" } { "origin" "2848 -2464 920" "targetname" "t392" "wait" "2.2" "spawnflags" "2048" "target" "t369" "classname" "func_timer" } { "origin" "3296 -392 928" "angle" "0" "spawnflags" "7681" "classname" "monster_soldier" } { "origin" "1904 -872 864" "targetname" "t137" "angle" "0" "spawnflags" "7681" "classname" "monster_gunner" } { "origin" "1056 136 1248" "spawnflags" "6145" "angle" "270" "classname" "monster_berserk" } { "origin" "2456 -96 1224" "targetname" "t391" "spawnflags" "2048" "target" "t160" "classname" "trigger_relay" } { "origin" "3520 -128 912" "targetname" "t390" "spawnflags" "2048" "classname" "point_combat" } { "origin" "1615 -2165 1120" "spawnflags" "6144" "classname" "item_pack" } { "origin" "2272 -800 1144" "angle" "-2" "spawnflags" "3873" "classname" "monster_turret" } { "classname" "item_sphere_vengeance" "spawnflags" "5888" "origin" "2816 -1472 1168" } { "classname" "item_sphere_hunter" "spawnflags" "5888" "origin" "1480 -160 1312" } { "classname" "ammo_nuke" "spawnflags" "5888" "origin" "2400 -2464 848" } { "classname" "ammo_tesla" "spawnflags" "5888" "origin" "1536 -392 984" } { "classname" "misc_teleporter_dest" "angle" "270" "spawnflags" "5888" "targetname" "t389" "origin" "416 -2016 984" } { "classname" "misc_teleporter" "spawnflags" "5888" "target" "t389" "origin" "1984 -192 992" } { "classname" "ammo_flechettes" "spawnflags" "2048" "origin" "2016 -216 984" } { "classname" "ammo_bullets" "origin" "3104 -1112 1168" } { "classname" "ammo_bullets" "spawnflags" "5888" "origin" "2720 -1128 1168" } { "classname" "weapon_chaingun" "origin" "2728 -1056 1168" "spawnflags" "5888" } { "spawnflags" "5888" "classname" "ammo_cells" "origin" "2664 40 1040" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "2784 416 1104" } { "classname" "weapon_hyperblaster" "spawnflags" "5888" "origin" "2752 256 1040" } { "classname" "weapon_rocketlauncher" "spawnflags" "5888" "origin" "1824 -184 1232" } { "classname" "ammo_rockets" "spawnflags" "5888" "origin" "1824 -32 1232" } { "classname" "weapon_grenadelauncher" "spawnflags" "5888" "origin" "1568 -1848 1128" } { "classname" "ammo_grenades" "spawnflags" "5888" "origin" "1528 -1968 1120" } { "classname" "ammo_grenades" "spawnflags" "5888" "origin" "1552 -2224 1120" } { "classname" "item_armor_combat" "spawnflags" "5888" "origin" "-480 -2840 912" } { "classname" "item_health_large" "spawnflags" "5888" "origin" "1416 -2960 1104" } { "classname" "ammo_tesla" "spawnflags" "5888" "origin" "1952 -2344 1104" } { "classname" "item_armor_jacket" "spawnflags" "1792" "origin" "1624 -2192 1128" } { "classname" "item_armor_body" "spawnflags" "5888" "origin" "864 -1504 1168" } { "spawnflags" "5888" "classname" "ammo_cells" "origin" "872 -1112 1232" } { "classname" "ammo_cells" "spawnflags" "5888" "origin" "608 -1192 1232" } { "classname" "weapon_plasmabeam" "spawnflags" "5888" "origin" "760 -1136 1232" } { "spawnflags" "5888" "classname" "ammo_flechettes" "origin" "256 -224 1360" } { "spawnflags" "5888" "classname" "ammo_flechettes" "origin" "224 -488 1360" } { "spawnflags" "5888" "classname" "weapon_etf_rifle" "origin" "280 -384 1360" } { "classname" "ammo_rockets" "origin" "344 256 1232" } { "classname" "ammo_shells" "spawnflags" "5888" "origin" "480 296 1304" } { "classname" "weapon_supershotgun" "spawnflags" "5888" "origin" "512 208 1232" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "1832 -856 1048" } { "classname" "info_player_deathmatch" "angle" "135" "origin" "2848 -160 1176" } { "classname" "info_player_deathmatch" "angle" "315" "origin" "992 -1120 1048" } { "classname" "info_player_deathmatch" "angle" "270" "origin" "2536 -2336 1112" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "2848 -872 1176" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "2848 -256 920" } { "classname" "info_player_deathmatch" "angle" "315" "origin" "1880 -856 856" } { "angle" "45" "classname" "info_player_deathmatch" "origin" "1056 -168 1240" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "1856 -672 984" } { "classname" "info_player_deathmatch" "angle" "315" "origin" "1184 -160 984" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "664 -192 1240" } { "angle" "180" "classname" "info_player_deathmatch" "origin" "-160 -2368 792" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-128 -2688 984" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "3360 -1120 856" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "2808 -1944 1176" } { "angle" "270" "classname" "info_player_deathmatch" "origin" "3736 24 920" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "3328 -608 1176" } { "classname" "item_doppleganger" "spawnflags" "5888" "origin" "3328 -128 920" } { "classname" "item_sphere_defender" "spawnflags" "5888" "origin" "488 -464 1360" } { "model" "*3" "classname" "func_wall" "spawnflags" "2048" } { "origin" "2976 -1816 1304" "angles" "20 45 0" "classname" "info_player_intermission" } { "classname" "item_health_small" "origin" "928 -288 1240" } { "classname" "item_health_small" "origin" "936 -160 1240" } { "classname" "hint_path" "spawnflags" "2048" "origin" "1896 408 1232" "target" "t387" "targetname" "t388" } { "classname" "point_combat" "targetname" "t384" "target" "t385" "spawnflags" "2048" "origin" "1976 120 1232" } { "model" "*4" "classname" "trigger_once" "spawnflags" "2048" "target" "t383" } { "origin" "512 120 1372" "light" "60" "classname" "light" } { "origin" "2912 -2208 1240" "light" "60" "classname" "light" } { "origin" "2976 -2752 1112" "light" "60" "classname" "light" } { "origin" "1824 224 1304" "classname" "item_health_large" } { "origin" "1416 -2880 1120" "targetname" "t254" "angle" "90" "spawnflags" "2051" "classname" "monster_gunner" } { "origin" "1392 -2976 1120" "angle" "90" "targetname" "t254" "spawnflags" "2051" "classname" "monster_gunner" } { "origin" "1448 -2976 1120" "targetname" "t254" "angle" "90" "spawnflags" "2053" "classname" "monster_gunner" } { "model" "*5" "targetname" "t254" "spawnflags" "2048" "classname" "func_explosive" } { "origin" "-176 -128 1504" "_color" "1.000000 0.000000 0.000000" "light" "60" "classname" "light" } { "origin" "2592 -2628 904" "targetname" "t380" "spawnflags" "2048" "angle" "90" "classname" "target_splash" "sounds" "1" } { "origin" "2560 -2616 904" "wait" "2.5" "random" ".75" "spawnflags" "2049" "targetname" "t27" "target" "t380" "classname" "func_timer" } { "origin" "2616 -2304 904" "random" "1.5" "wait" "3" "target" "t379" "targetname" "t30" "spawnflags" "2049" "classname" "func_timer" } { "targetname" "t379" "sounds" "1" "spawnflags" "2048" "angle" "270" "origin" "2592 -2300 904" "classname" "target_splash" } { "model" "*6" "spawnflags" "2048" "classname" "func_wall" } { "model" "*7" "target" "t88" "spawnflags" "2048" "classname" "trigger_once" } { "model" "*8" "classname" "trigger_multiple" "spawnflags" "2048" "target" "t143" } { "classname" "target_speaker" "spawnflags" "2049" "noise" "world/scan1.wav" "origin" "1720 -2368 1152" } { "classname" "target_speaker" "spawnflags" "2049" "noise" "world/scan1.wav" "origin" "1720 -2496 1152" } { "model" "*9" "classname" "func_door" "angle" "90" "wait" "-1" "_minlight" ".3" "team" "done3" "targetname" "t250" "spawnflags" "2048" } { "model" "*10" "classname" "func_door" "angle" "270" "_minlight" ".3" "targetname" "t250" "team" "done3" "wait" "-1" "spawnflags" "2048" } { "classname" "ammo_shells" "origin" "1632 32 1048" } { "classname" "target_lightramp" "targetname" "t376" "target" "t377" "speed" "5" "spawnflags" "2048" "origin" "2688 128 1216" "message" "az" } { "classname" "trigger_relay" "targetname" "t129" "origin" "2752 160 1216" "target" "t376" } { "classname" "trigger_relay" "spawnflags" "2048" "targetname" "t129" "delay" "3" "origin" "2752 192 1216" "target" "t378" } { "model" "*11" "classname" "trigger_multiple" "spawnflags" "2048" "targetname" "comeout" "wait" "3" "message" "Shuttle inactive." } { "classname" "trigger_relay" "targetname" "t129" "target" "t136" "spawnflags" "2048" "origin" "2768 -344 1320" } { "model" "*12" "classname" "trigger_once" "spawnflags" "2052" "target" "t375" "targetname" "t129" } { "origin" "432 176 1304" "message" "Canyon entrance to\n Logistics is now\naccessible." "spawnflags" "2048" "targetname" "t7" "classname" "target_help" } { "origin" "2024 -296 1304" "message" "Acquire blue key card\n to proceed to Logistics." "spawnflags" "2048" "targetname" "t223" "classname" "target_help" } { "origin" "2880 -584 1184" "targetname" "t246" "target" "t247" "angle" "270" "item" "ammo_cells" "spawnflags" "3841" "classname" "monster_medic_commander" } { "targetname" "t247" "origin" "2800 -824 1184" "angle" "45" "item" "ammo_grenades" "spawnflags" "3841" "classname" "monster_gunner" } { "classname" "monster_stalker" "spawnflags" "6921" "angle" "180" "origin" "2380 -1916 1258" } { "origin" "2912 -2208 1272" "spawnflags" "2057" "classname" "monster_turret" "angle" "-2" } { "origin" "2848 -2944 1184" "angle" "270" "spawnflags" "3841" "classname" "monster_gunner" } { "origin" "2096 -2720 1168" "spawnflags" "3841" "target" "t179" "angle" "180" "classname" "monster_daedalus" } { "origin" "464 -2424 1160" "spawnflags" "6401" "classname" "monster_daedalus" "angle" "90" } { "target" "t96" "origin" "408 -2304 992" "item" "ammo_slugs" "spawnflags" "3841" "classname" "monster_gladiator" } { "origin" "-120 -2536 992" "spawnflags" "3841" "target" "t72" "item" "ammo_slugs" "classname" "monster_gladiator" } { "origin" "32 -2368 1024" "angle" "0" "spawnflags" "6913" "classname" "monster_hover" } { "origin" "480 356 1376" "angle" "270" "targetname" "t166" "spawnflags" "4001" "classname" "monster_turret" } { "origin" "1188 284 1378" "angle" "270" "targetname" "t363" "spawnflags" "3849" "classname" "monster_stalker" } { "classname" "monster_soldier_ss" "item" "ammo_bullets" "spawnflags" "6401" "angle" "180" "origin" "1248 104 1248" } { "origin" "864 -672 1248" "targetname" "t198" "item" "ammo_bullets" "spawnflags" "3843" "angle" "0" "classname" "monster_gunner" } { "targetname" "t140" "origin" "912 224 1264" "angle" "45" "spawnflags" "6915" "classname" "monster_daedalus" "item" "ammo_cells" } { "angle" "315" "origin" "1792 416 1248" "spawnflags" "3843" "targetname" "uknow" "target" "t227" "classname" "monster_gunner" } { "origin" "1912 -152 1240" "spawnflags" "6913" "angle" "315" "classname" "monster_gunner" "item" "ammo_bullets" } { "origin" "1880 -664 992" "targetname" "t383" "target" "t218" "item" "ammo_grenades" "spawnflags" "3843" "angle" "135" "classname" "monster_gunner" } { "origin" "944 -56 1088" "angle" "270" "spawnflags" "3841" "item" "ammo_cells" "classname" "monster_daedalus" } { "origin" "1248 -152 992" "targetname" "t101" "item" "ammo_cells" "angle" "270" "spawnflags" "3843" "classname" "monster_medic" } { "origin" "1056 -416 1000" "targetname" "t101" "target" "t100" "item" "ammo_bullets" "angle" "0" "spawnflags" "3841" "classname" "monster_soldier_ss" } { "origin" "1392 -548 992" "targetname" "t101" "target" "t97" "spawnflags" "3841" "angle" "0" "classname" "monster_gunner" } { "origin" "776 -1440 864" "spawnflags" "6400" "classname" "monster_gunner" "item" "ammo_bullets" } { "origin" "1568 -1256 1224" "angle" "180" "spawnflags" "3841" "classname" "monster_daedalus" "item" "ammo_cells" } { "origin" "1496 -1808 1144" "angle" "90" "spawnflags" "6401" "classname" "monster_daedalus" "item" "ammo_cells" } { "origin" "1632 -1488 1048" "spawnflags" "5120" "classname" "ammo_slugs" } { "item" "ammo_slugs" "origin" "1072 -1200 1056" "target" "t93" "spawnflags" "3841" "classname" "monster_gladiator" } { "origin" "1768 -1064 1056" "targetname" "t88" "target" "t87" "item" "ammo_grenades" "spawnflags" "3841" "angle" "0" "classname" "monster_gunner" } { "angle" "90" "classname" "monster_gunner" "spawnflags" "6912" "item" "ammo_bullets" "origin" "2488 -992 1056" } { "angle" "90" "origin" "2504 -992 1056" "item" "ammo_bullets" "spawnflags" "3841" "classname" "monster_gunner" } { "origin" "2504 -1096 1048" "targetname" "t88" "target" "t86" "item" "ammo_cells" "angle" "180" "spawnflags" "3841" "classname" "monster_medic" } { "targetname" "t160" "classname" "monster_turret" "spawnflags" "2977" "angle" "-2" "origin" "2528 -160 1316" } { "targetname" "t160" "classname" "monster_turret" "spawnflags" "6553" "angle" "-2" "origin" "2400 352 1316" } { "target" "t391" "origin" "2400 -104 1176" "item" "ammo_cells" "angle" "45" "spawnflags" "3841" "classname" "monster_medic" } { "origin" "2268 -556 1066" "angle" "180" "targetname" "t80" "target" "t81" "spawnflags" "3849" "classname" "monster_stalker" } { "origin" "2280 -680 1048" "angle" "135" "spawnflags" "2049" "classname" "monster_flyer" } { "origin" "2168 -600 864" "target" "t79" "item" "ammo_grenades" "spawnflags" "3841" "angle" "0" "classname" "monster_gunner" } { "origin" "3444 64 1178" "spawnflags" "6913" "angle" "180" "classname" "monster_stalker" } { "origin" "3512 -496 1264" "spawnflags" "6913" "angle" "90" "classname" "monster_daedalus" } { "origin" "3308 -404 1010" "target" "t163" "spawnflags" "3849" "angle" "0" "classname" "monster_stalker" } { "classname" "monster_gunner" "spawnflags" "6913" "angle" "225" "origin" "3608 -544 928" "item" "ammo_bullets" } { "classname" "monster_soldier_ss" "spawnflags" "6913" "angle" "0" "origin" "2912 -936 928" "item" "ammo_bullets" } { "targetname" "t123" "classname" "monster_turret" "spawnflags" "4001" "angle" "-2" "origin" "3104 -928 1060" } { "classname" "monster_daedalus" "angle" "45" "spawnflags" "6913" "origin" "3096 -1848 1208" "item" "ammo_cells" } { "targetname" "t31" "origin" "3280 -1528 1208" "spawnflags" "3843" "angle" "225" "classname" "monster_daedalus" } { "angle" "180" "origin" "3288 -1440 1184" "spawnflags" "6913" "classname" "monster_hover" } { "origin" "3496 -1048 928" "targetname" "t120" "target" "t121" "item" "ammo_bullets" "spawnflags" "6913" "classname" "monster_gunner" } { "target" "t371" "targetname" "t370" "spawnflags" "2048" "classname" "hint_path" "origin" "512 208 1232" } { "targetname" "t371" "spawnflags" "2049" "classname" "hint_path" "origin" "744 208 1232" } { "target" "t392" "classname" "trigger_relay" "targetname" "t28" "spawnflags" "2048" "origin" "2840 -2440 920" } { "target" "t392" "classname" "trigger_relay" "targetname" "t28" "spawnflags" "2048" "delay" "12" "origin" "2840 -2488 920" } { "origin" "2872 -600 1184" "item" "ammo_grenades" "targetname" "t246" "target" "t247" "angle" "270" "spawnflags" "7681" "classname" "monster_gunner" } { "origin" "2888 -600 1184" "targetname" "t246" "target" "t247" "angle" "270" "spawnflags" "7425" "item" "ammo_cells" "classname" "monster_medic" } { "origin" "2920 -2200 1176" "classname" "ammo_prox" } { "origin" "2656 -2072 1240" "classname" "ammo_tesla" } { "origin" "2200 -1880 1176" "classname" "item_health" } { "origin" "2536 -1752 1176" "classname" "item_health_large" } { "origin" "2704 -328 1296" "targetname" "t136" "classname" "target_goal" "spawnflags" "2048" } { "origin" "2456 -2400 976" "targetname" "t31" "classname" "target_goal" "spawnflags" "2048" } { "origin" "1664 -2408 1184" "targetname" "t250" "classname" "target_goal" "spawnflags" "2048" } { "origin" "1496 -216 1384" "spawnflags" "2048" "targetname" "t364" "classname" "target_goal" } { "classname" "ammo_bullets" "origin" "2264 -2576 1048" } { "classname" "ammo_grenades" "origin" "2344 -2576 1048" } { "classname" "item_health_large" "origin" "1880 -2792 1048" } { "classname" "item_doppleganger" "spawnflags" "5888" "origin" "1888 -2848 1048" } { "classname" "item_quad" "spawnflags" "2048" "origin" "1888 -2848 1048" } { "classname" "item_health_small" "origin" "2016 -2544 1112" } { "classname" "item_health_small" "origin" "2016 -2600 1112" } { "classname" "item_health_small" "origin" "2016 -2656 1112" } { "classname" "item_health_small" "origin" "2016 -2496 1112" } { "classname" "item_health_large" "origin" "1496 -2392 1128" } { "classname" "item_health" "origin" "280 -2336 984" } { "classname" "item_health" "origin" "280 -2016 984" } { "origin" "656 -2024 984" "classname" "ammo_shells" } { "classname" "ammo_shells" "origin" "592 -2016 984" } { "classname" "ammo_bullets" "origin" "168 -1880 920" } { "classname" "item_health_small" "origin" "-144 -2040 984" } { "classname" "item_health_small" "origin" "-96 -2040 984" } { "classname" "item_health_small" "origin" "-192 -2056 984" } { "classname" "ammo_prox" "origin" "-192 -2224 984" } { "classname" "weapon_proxlauncher" "origin" "-152 -2384 984" } { "classname" "misc_deadsoldier" "spawnflags" "2050" "origin" "-168 -2344 960" } { "classname" "item_health" "origin" "168 -2856 920" } { "classname" "ammo_slugs" "origin" "-488 -2584 784" } { "classname" "ammo_prox" "origin" "-552 -1976 792" } { "classname" "item_health_small" "origin" "-24 -2008 784" } { "classname" "item_sphere_hunter" "spawnflags" "5888" "origin" "-32 -2720 792" } { "classname" "ammo_tesla" "origin" "-80 -2720 792" } { "classname" "item_health_large" "origin" "-544 -2816 856" } { "classname" "item_armor_combat" "origin" "-480 -2848 920" "spawnflags" "2048" } { "origin" "2380 -1916 1218" "angle" "180" "spawnflags" "3849" "classname" "monster_stalker" } { "origin" "2840 -2584 1176" "classname" "item_armor_shard" } { "origin" "2840 -2400 1176" "classname" "item_armor_shard" } { "origin" "2840 -2344 1176" "classname" "item_armor_shard" } { "origin" "2840 -2528 1176" "classname" "item_armor_shard" } { "origin" "3152 -2976 1240" "classname" "ammo_prox" } { "origin" "3240 -2920 1168" "classname" "item_health" } { "origin" "416 112 1376" "_color" "0.000000 0.501961 1.000000" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "96 -128 1400" } { "model" "*13" "spawnflags" "2048" "classname" "func_wall" } { "light" "50" "classname" "light" "origin" "2032 -544 992" } { "classname" "light" "light" "50" "origin" "1936 -352 1248" } { "classname" "trigger_relay" "targetname" "t367" "target" "t368" "delay" "1" "origin" "1984 -448 1248" } { "model" "*14" "message" "Lift activated." "wait" "2" "angle" "0" "classname" "func_button" "target" "t367" } { "model" "*15" "classname" "func_button" "angle" "180" "wait" "2" "message" "Lift activated." "target" "t367" } { "delay" "1" "origin" "3400 64 936" "target" "t366" "targetname" "t360" "classname" "trigger_relay" } { "origin" "2416 -936 864" "target" "t365" "delay" "1" "targetname" "t359" "classname" "trigger_relay" } { "origin" "1376 -96 984" "classname" "ammo_flechettes" } { "model" "*16" "target" "t362" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "1248 -432 1000" "angle" "315" "spawnflags" "2049" "targetname" "t101" "classname" "monster_soldier_ss" } { "origin" "1304 -296 1304" "classname" "item_health_large" } { "origin" "1176 296 1240" "classname" "ammo_cells" } { "origin" "840 112 1232" "targetname" "t361" "spawnflags" "2048" "classname" "point_combat" } { "origin" "800 -608 1304" "classname" "item_armor_combat" } { "model" "*17" "message" "Lift activated." "target" "t360" "classname" "func_button" "angle" "0" "_minlight" ".3" "wait" "2" } { "origin" "2416 -992 864" "classname" "light" "light" "50" } { "origin" "2448 -992 1056" "light" "50" "classname" "light" } { "model" "*18" "message" "Lift activated." "target" "t359" "classname" "func_button" "angle" "180" "_minlight" ".3" "wait" "2" } { "spawnflags" "2049" "angle" "180" "classname" "monster_soldier" "origin" "2520 -896 1056" } { "model" "*19" "message" "Lift activated." "target" "t359" "classname" "func_button" "angle" "0" "_minlight" ".3" "wait" "2" } { "model" "*20" "message" "Lift activated." "target" "t360" "wait" "2" "_minlight" ".3" "angle" "270" "classname" "func_button" } { "origin" "1880 -856 864" "spawnflags" "7680" "classname" "ammo_rockets" } { "origin" "2072 -792 856" "classname" "ammo_flechettes" } { "origin" "1560 -1440 600" "classname" "ammo_tesla" } { "classname" "item_health" "origin" "2296 -1472 616" } { "origin" "2248 -1160 600" "classname" "ammo_cells" } { "origin" "2048 -1168 600" "classname" "ammo_prox" } { "origin" "2080 -984 600" "classname" "item_armor_shard" } { "origin" "1848 -1472 616" "classname" "item_health" } { "origin" "2016 -1088 600" "classname" "item_armor_shard" } { "origin" "2208 -984 600" "classname" "item_armor_shard" } { "origin" "2280 -1088 600" "classname" "item_armor_shard" } { "origin" "2144 -1472 616" "classname" "item_armor_combat" } { "origin" "2584 -552 1176" "classname" "item_health" } { "origin" "2672 -512 1168" "targetname" "t358" "angle" "0" "classname" "point_combat" "spawnflags" "2049" } { "origin" "2944 -528 1168" "target" "t358" "wait" "60" "targetname" "t357" "classname" "point_combat" "spawnflags" "2048" } { "origin" "2776 -360 1176" "classname" "ammo_slugs" } { "origin" "2752 -320 1280" "light" "115" "classname" "light" } { "origin" "2792 -280 1168" "classname" "item_health" } { "origin" "2412 -324 1258" "angle" "0" "spawnflags" "2057" "item" "ammo_cells" "classname" "monster_stalker" } { "origin" "3104 -616 1176" "classname" "item_armor_jacket" } { "origin" "3104 -992 1176" "classname" "ammo_prox" } { "origin" "2784 -864 1184" "angle" "45" "targetname" "t247" "item" "ammo_shells" "spawnflags" "7169" "classname" "monster_soldier" } { "origin" "1984 -16 1232" "target" "t356" "spawnflags" "2048" "classname" "hint_path" "targetname" "t386" } { "origin" "2008 224 1232" "spawnflags" "2048" "classname" "hint_path" "target" "t386" "targetname" "t387" } { "origin" "1664 96 1232" "target" "t354" "targetname" "t353" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1672 208 1232" "target" "t353" "targetname" "t352" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1584 216 1232" "target" "t352" "targetname" "t351" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1584 376 1232" "target" "t351" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1984 -344 1232" "targetname" "t356" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1504 416 1232" "targetname" "t350" "classname" "hint_path" "spawnflags" "2048" "target" "t388" } { "origin" "1048 416 1232" "target" "t350" "targetname" "t349" "classname" "hint_path" "spawnflags" "2048" } { "origin" "864 256 1232" "target" "t349" "classname" "hint_path" "spawnflags" "2049" } { "target" "t370" "origin" "472 -280 1232" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1928 96 1232" "targetname" "t354" "spawnflags" "2049" "classname" "hint_path" } { "origin" "800 -192 1232" "target" "t348" "targetname" "t347" "classname" "hint_path" "spawnflags" "2048" } { "origin" "816 -536 1232" "target" "t347" "classname" "hint_path" "spawnflags" "2049" } { "origin" "800 208 1232" "targetname" "t348" "spawnflags" "2049" "classname" "hint_path" } { "origin" "896 -536 1232" "targetname" "t343" "classname" "hint_path" "spawnflags" "2049" } { "origin" "1024 -480 1232" "target" "t343" "targetname" "t342" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1120 -344 1232" "target" "t342" "targetname" "t341" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1088 -96 1232" "target" "t341" "targetname" "t340" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1040 96 1232" "target" "t340" "targetname" "t339" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1216 96 1232" "target" "t339" "targetname" "t338" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1216 216 1232" "target" "t338" "targetname" "t337" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1384 216 1232" "target" "t337" "targetname" "t336" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1408 -200 1296" "target" "t336" "classname" "hint_path" "spawnflags" "2049" } { "targetname" "t335" "classname" "hint_path" "spawnflags" "2049" "origin" "1504 112 976" } { "targetname" "t334" "classname" "hint_path" "spawnflags" "2049" "origin" "1504 160 976" } { "target" "t334" "targetname" "t333" "origin" "1696 160 976" "classname" "hint_path" "spawnflags" "2048" } { "target" "t333" "origin" "1784 288 976" "targetname" "t332" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1984 160 976" "target" "t332" "targetname" "t331" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1856 0 976" "target" "t331" "targetname" "t330" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1664 -256 976" "target" "t330" "targetname" "t329" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1720 -544 976" "target" "t329" "targetname" "t328" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1984 -544 976" "target" "t328" "classname" "hint_path" "spawnflags" "2049" } { "target" "t335" "origin" "1496 -72 976" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1152 -320 976" "target" "t327" "targetname" "t326" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1328 -480 976" "target" "t326" "targetname" "t325" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1536 -568 976" "target" "t325" "targetname" "t324" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1536 -816 1024" "target" "t324" "classname" "hint_path" "spawnflags" "2049" } { "origin" "984 -192 976" "targetname" "t327" "spawnflags" "2049" "classname" "hint_path" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t320" "target" "t321" "origin" "-360 -1920 784" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t321" "target" "t322" "origin" "128 -1928 912" } { "spawnflags" "2048" "classname" "hint_path" "targetname" "t322" "target" "t323" "origin" "128 -2160 976" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t315" "target" "t316" "origin" "-352 -2816 784" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t316" "target" "t317" "origin" "128 -2816 912" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t317" "target" "t318" "origin" "128 -2368 976" } { "classname" "hint_path" "spawnflags" "2048" "targetname" "t318" "target" "t319" "origin" "128 -2192 976" } { "classname" "hint_path" "spawnflags" "2049" "targetname" "t323" "origin" "312 -2152 976" } { "spawnflags" "2049" "classname" "hint_path" "target" "t315" "origin" "-352 -2464 784" } { "spawnflags" "2049" "classname" "hint_path" "targetname" "t319" "origin" "312 -2200 976" } { "classname" "hint_path" "spawnflags" "2049" "target" "t320" "origin" "-456 -2136 784" } { "origin" "504 -2304 960" "target" "t312" "classname" "hint_path" "spawnflags" "2049" } { "origin" "888 -2520 1072" "target" "t314" "targetname" "t313" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1216 -2480 1112" "targetname" "t314" "classname" "hint_path" "spawnflags" "2049" } { "origin" "712 -2544 1032" "target" "t313" "targetname" "t312" "spawnflags" "2048" "classname" "hint_path" } { "origin" "1568 -2176 1112" "target" "t310" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1280 -2176 1112" "target" "t311" "spawnflags" "2048" "targetname" "t310" "classname" "hint_path" } { "origin" "1280 -2448 1112" "targetname" "t311" "spawnflags" "2049" "classname" "hint_path" } { "target" "t308" "targetname" "t307" "origin" "1280 -2752 1112" "spawnflags" "2048" "classname" "hint_path" } { "target" "t307" "targetname" "t306" "origin" "1536 -2752 1112" "spawnflags" "2048" "classname" "hint_path" } { "target" "t306" "targetname" "t305" "origin" "1536 -2432 1112" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t308" "classname" "hint_path" "spawnflags" "2049" "origin" "1280 -2528 1112" } { "target" "t304" "targetname" "t303" "classname" "hint_path" "spawnflags" "2048" "origin" "1920 -2752 1040" } { "target" "t303" "targetname" "t302" "classname" "hint_path" "spawnflags" "2048" "origin" "2304 -2752 1040" } { "target" "t302" "origin" "2624 -2752 1040" "targetname" "t301" "classname" "hint_path" "spawnflags" "2048" } { "origin" "3104 -2752 1040" "target" "t301" "classname" "hint_path" "spawnflags" "2049" } { "target" "t305" "targetname" "t304" "origin" "1944 -2472 1104" "spawnflags" "2048" "classname" "hint_path" } { "origin" "2944 -2944 1168" "target" "t299" "targetname" "t298" "classname" "hint_path" "spawnflags" "2048" } { "origin" "2880 -2736 1168" "target" "t300" "targetname" "t299" "classname" "hint_path" "spawnflags" "2048" } { "origin" "2880 -2240 1168" "targetname" "t300" "classname" "hint_path" "spawnflags" "2049" } { "origin" "3200 -2832 1168" "target" "t298" "spawnflags" "2049" "classname" "hint_path" } { "target" "t297" "targetname" "t296" "classname" "hint_path" "spawnflags" "2048" "origin" "2240 -2104 1168" } { "target" "t296" "targetname" "t295" "classname" "hint_path" "spawnflags" "2048" "origin" "2240 -1912 1168" } { "target" "t295" "targetname" "t294" "classname" "hint_path" "spawnflags" "2048" "origin" "2520 -1856 1168" } { "target" "t294" "targetname" "t293" "classname" "hint_path" "spawnflags" "2048" "origin" "2816 -1800 1168" } { "target" "t293" "classname" "hint_path" "spawnflags" "2049" "origin" "2816 -1472 1168" } { "target" "t292" "targetname" "t291" "classname" "hint_path" "spawnflags" "2048" "origin" "1024 -1832 880" } { "target" "t291" "targetname" "t290" "classname" "hint_path" "spawnflags" "2048" "origin" "1320 -1896 944" } { "target" "t290" "targetname" "t289" "classname" "hint_path" "spawnflags" "2048" "origin" "1600 -1648 1040" } { "target" "t289" "targetname" "t288" "classname" "hint_path" "spawnflags" "2048" "origin" "1584 -1256 1040" } { "target" "t288" "targetname" "t287" "classname" "hint_path" "spawnflags" "2048" "origin" "1120 -1224 1040" } { "target" "t287" "origin" "1120 -904 1040" "targetname" "t286" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1536 -856 1040" "target" "t286" "targetname" "t285" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1792 -904 1040" "target" "t285" "targetname" "t284" "classname" "hint_path" "spawnflags" "2048" } { "origin" "1792 -1096 1040" "target" "t284" "targetname" "t283" "classname" "hint_path" "spawnflags" "2048" } { "origin" "2152 -1048 1040" "target" "t283" "targetname" "t282" "classname" "hint_path" "spawnflags" "2048" } { "origin" "2496 -1088 1040" "target" "t282" "classname" "hint_path" "spawnflags" "2049" } { "targetname" "t292" "origin" "1184 -1616 848" "spawnflags" "2049" "classname" "hint_path" } { "origin" "3584 -1344 848" "targetname" "t281" "spawnflags" "1" "classname" "hint_path" } { "targetname" "t280" "classname" "hint_path" "spawnflags" "2049" "origin" "2816 -1408 1168" } { "target" "t280" "targetname" "t279" "classname" "hint_path" "spawnflags" "2048" "origin" "2816 -1136 1168" } { "target" "t279" "targetname" "t278" "classname" "hint_path" "spawnflags" "2048" "origin" "3008 -936 1168" } { "target" "t278" "classname" "hint_path" "spawnflags" "2049" "origin" "2880 -640 1168" } { "origin" "2400 -896 848" "target" "t277" "spawnflags" "2049" "classname" "hint_path" } { "origin" "2208 -768 848" "targetname" "t277" "spawnflags" "2049" "classname" "hint_path" } { "origin" "2272 -800 1128" "light" "50" "classname" "light" } { "origin" "2176 -640 848" "targetname" "t276" "classname" "hint_path" "spawnflags" "2049" } { "origin" "2592 -640 912" "target" "t276" "targetname" "t275" "classname" "hint_path" "spawnflags" "2048" } { "origin" "2880 -640 912" "target" "t275" "classname" "hint_path" "spawnflags" "2049" } { "target" "t274" "targetname" "t273" "origin" "2208 -256 864" "spawnflags" "2048" "classname" "hint_path" } { "target" "t273" "targetname" "t272" "origin" "2752 -256 912" "spawnflags" "2048" "classname" "hint_path" } { "target" "t272" "targetname" "t271" "origin" "2680 488 1040" "spawnflags" "2048" "classname" "hint_path" } { "target" "t271" "targetname" "t270" "origin" "2888 496 1040" "spawnflags" "2048" "classname" "hint_path" } { "target" "t270" "targetname" "t269" "origin" "2816 -64 1168" "spawnflags" "2048" "classname" "hint_path" } { "target" "t269" "targetname" "t268" "origin" "2432 -64 1168" "spawnflags" "2048" "classname" "hint_path" } { "target" "t268" "targetname" "t267" "origin" "2432 -320 1168" "spawnflags" "2048" "classname" "hint_path" } { "target" "t267" "targetname" "t266" "origin" "2624 -320 1168" "spawnflags" "2048" "classname" "hint_path" } { "target" "t266" "targetname" "t265" "origin" "2624 -512 1168" "spawnflags" "2048" "classname" "hint_path" } { "target" "t265" "targetname" "t264" "origin" "2880 -512 1168" "spawnflags" "2048" "classname" "hint_path" } { "targetname" "t274" "classname" "hint_path" "spawnflags" "2049" "origin" "2176 -576 864" } { "target" "t264" "targetname" "t263" "classname" "hint_path" "spawnflags" "2048" "origin" "3328 -512 1168" } { "targetname" "t297" "origin" "2656 -2248 1168" "spawnflags" "2049" "classname" "hint_path" } { "target" "t263" "origin" "3328 -40 1168" "spawnflags" "2049" "classname" "hint_path" } { "target" "t261" "targetname" "t260" "origin" "3560 -272 912" "spawnflags" "2048" "classname" "hint_path" } { "target" "t260" "targetname" "t259" "classname" "hint_path" "spawnflags" "2048" "origin" "3584 64 912" } { "target" "t262" "targetname" "t261" "classname" "hint_path" "spawnflags" "2048" "origin" "3448 -632 912" } { "targetname" "t262" "classname" "hint_path" "spawnflags" "2049" "origin" "3200 -640 912" } { "origin" "3176 -608 1184" "light" "50" "classname" "light" } { "target" "t256" "classname" "hint_path" "spawnflags" "2049" "origin" "3008 -640 912" } { "target" "t257" "targetname" "t256" "classname" "hint_path" "spawnflags" "2048" "origin" "3008 -896 912" } { "target" "t258" "targetname" "t257" "classname" "hint_path" "spawnflags" "2048" "origin" "3256 -896 912" } { "target" "t281" "targetname" "t258" "origin" "3520 -896 912" "classname" "hint_path" "spawnflags" "2048" } { "target" "t259" "origin" "3416 64 912" "spawnflags" "2049" "classname" "hint_path" } { "origin" "1048 -856 1048" "classname" "ammo_flechettes" } { "origin" "1608 -1232 1048" "classname" "item_health" } { "origin" "1456 -1120 1048" "classname" "item_health_large" } { "classname" "light" "light" "100" "origin" "552 -288 1416" } { "origin" "3624 -800 920" "classname" "ammo_grenades" } { "_color" "1.000000 1.000000 0.000000" "origin" "1408 128 1336" "light" "125" "classname" "light" } { "origin" "1120 -1040 1184" "light" "75" "classname" "light" } { "origin" "3400 -896 1056" "light" "75" "classname" "light" } { "origin" "-840 -2400 800" "classname" "info_player_coop" "angle" "0" "targetname" "rw2b" "spawnflags" "2048" } { "origin" "-840 -2336 800" "angle" "0" "classname" "info_player_coop" "targetname" "rw2b" "spawnflags" "2048" } { "origin" "-768 -2336 800" "classname" "info_player_coop" "angle" "0" "targetname" "rw2b" "spawnflags" "2048" } { "origin" "-768 -2400 800" "angle" "0" "classname" "info_player_coop" "targetname" "rw2b" "spawnflags" "2048" } { "origin" "-704 -2368 840" "classname" "light" "light" "125" } { "origin" "-864 -2368 840" "light" "125" "classname" "light" } { "origin" "-80 -88 1376" "classname" "info_player_coop" "angle" "0" "targetname" "rw2a" "spawnflags" "2048" } { "origin" "-136 -72 1376" "classname" "info_player_coop" "angle" "0" "targetname" "rw2a" "spawnflags" "2048" } { "origin" "-128 -184 1376" "classname" "info_player_coop" "angle" "0" "targetname" "rw2a" "spawnflags" "2048" } { "origin" "-72 -200 1376" "angle" "0" "classname" "info_player_coop" "targetname" "rw2a" "spawnflags" "2048" } { "angle" "90" "classname" "info_player_coop" "origin" "3524 -1952 888" "targetname" "rw2" "spawnflags" "2048" } { "classname" "info_player_coop" "angle" "90" "origin" "3452 -1904 880" "targetname" "rw2" "spawnflags" "2048" } { "angle" "90" "classname" "info_player_coop" "origin" "3524 -2048 896" "targetname" "rw2" "spawnflags" "2048" } { "classname" "info_player_coop" "angle" "90" "origin" "3452 -2000 896" "targetname" "rw2" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "3488 -1936 952" } { "origin" "3488 -2080 952" "light" "125" "classname" "light" } { "origin" "1320 -2624 1128" "classname" "item_armor_shard" } { "origin" "1320 -2576 1128" "classname" "item_armor_shard" } { "origin" "1320 -2672 1128" "classname" "item_armor_shard" } { "origin" "1248 -2136 1120" "classname" "ammo_rockets" } { "origin" "1520 -2480 1152" "killtarget" "t254" "spawnflags" "2048" "targetname" "t255" "classname" "trigger_relay" } { "origin" "1512 -2424 1152" "target" "t255" "killtarget" "nogood" "spawnflags" "2052" "classname" "target_crosslevel_target" } { "angle" "90" "targetname" "t254" "origin" "1448 -2928 1120" "spawnflags" "2051" "classname" "monster_gunner" } { "angle" "90" "targetname" "t254" "origin" "1392 -2928 1120" "spawnflags" "2051" "classname" "monster_gunner" } { "model" "*21" "message" "Humanoid life form detected." "targetname" "nogood" "target" "t254" "classname" "trigger_once" } { "origin" "1664 -2440 1184" "item" "key_commander_head" "target" "t250" "spawnflags" "2048" "targetname" "t249" "classname" "trigger_key" } { "model" "*22" "target" "t249" "spawnflags" "2048" "classname" "trigger_multiple" } { "targetname" "t364" "classname" "target_help" "spawnflags" "2048" "origin" "1448 -256 1320" "message" "Use key card to\n open cargo doors." } { "target" "t364" "classname" "key_blue_key" "origin" "1488 -160 1316" "spawnflags" "2048" } { "model" "*23" "classname" "func_wall" "spawnflags" "2054" "targetname" "t248" } { "classname" "light" "light" "60" "origin" "2496 552 1072" } { "origin" "480 -288 1456" "light" "50" "classname" "light" } { "classname" "light" "light" "100" "origin" "384 -288 1416" } { "origin" "552 -96 1416" "light" "100" "classname" "light" } { "classname" "light" "light" "100" "origin" "384 -96 1416" } { "origin" "384 -480 1416" "light" "100" "classname" "light" } { "origin" "448 -192 1464" "light" "120" "classname" "light" } { "origin" "1304 424 1232" "classname" "item_armor_shard" } { "origin" "1376 424 1232" "classname" "item_armor_shard" } { "origin" "1240 424 1232" "classname" "item_armor_shard" } { "origin" "1504 344 1232" "classname" "item_health" } { "origin" "1624 88 1240" "classname" "item_health_large" } { "origin" "3032 -472 1168" "classname" "item_health_small" } { "origin" "2984 -472 1168" "classname" "item_health_small" } { "origin" "2936 -472 1168" "classname" "item_health_small" } { "origin" "3072 -472 1168" "classname" "item_health_small" } { "origin" "3160 -608 1176" "spawnflags" "2049" "angle" "135" "classname" "monster_soldier" } { "origin" "3032 -608 1184" "angle" "90" "spawnflags" "2049" "classname" "monster_berserk" } { "origin" "3136 -512 1208" "classname" "light" "light" "115" } { "origin" "2856 -872 1176" "angle" "90" "spawnflags" "2305" "item" "ammo_bullets" "classname" "monster_soldier_ss" } { "origin" "2712 -1128 1168" "classname" "ammo_rockets" "spawnflags" "2048" } { "origin" "2712 -984 1168" "classname" "item_health_large" } { "origin" "3168 -784 1168" "classname" "item_armor_shard" } { "origin" "3168 -728 1168" "classname" "item_armor_shard" } { "origin" "3112 -728 1168" "classname" "item_armor_shard" } { "origin" "3168 -864 1168" "classname" "item_health_large" } { "item" "ammo_grenades" "targetname" "t247" "angle" "45" "origin" "2784 -824 1184" "spawnflags" "6913" "classname" "monster_gunner" } { "target" "t247" "item" "ammo_cells" "targetname" "t246" "origin" "2880 -608 1184" "spawnflags" "6913" "angle" "270" "classname" "monster_medic_commander" } { "origin" "2936 -840 1280" "classname" "light" "light" "70" } { "origin" "2936 -760 1280" "light" "70" "classname" "light" } { "origin" "3144 -760 1280" "classname" "light" "light" "70" } { "origin" "3040 -800 1280" "classname" "light" "light" "125" } { "origin" "3144 -840 1280" "light" "70" "classname" "light" } { "_color" "0.000000 0.501961 1.000000" "light" "100" "classname" "light" "origin" "2768 -832 1208" } { "light" "115" "classname" "light" "origin" "2816 -832 1208" } { "light" "115" "classname" "light" "origin" "2816 -704 1208" } { "origin" "3184 -800 1232" "classname" "light" "light" "100" "_color" "0.000000 0.501961 1.000000" } { "target" "t245" "targetname" "t244" "origin" "2880 472 1040" "classname" "point_combat" "spawnflags" "2048" } { "target" "t244" "targetname" "t243" "origin" "2904 176 1168" "classname" "point_combat" "spawnflags" "2048" } { "targetname" "t245" "origin" "2760 472 1040" "spawnflags" "2049" "classname" "point_combat" } { "target" "t391" "origin" "2400 -88 1176" "angle" "45" "spawnflags" "7169" "item" "ammo_shells" "classname" "monster_soldier" } { "target" "t391" "item" "ammo_cells" "angle" "45" "origin" "2400 -112 1176" "spawnflags" "6913" "classname" "monster_medic" } { "target" "t243" "origin" "2896 16 1184" "spawnflags" "2049" "angle" "135" "classname" "monster_soldier_ss" } { "origin" "2792 360 1040" "classname" "ammo_cells" } { "target" "t72" "spawnflags" "6913" "origin" "-120 -2512 992" "classname" "monster_gladiator" "item" "ammo_slugs" } { "origin" "32 -2824 928" "spawnflags" "2049" "angle" "180" "classname" "monster_soldier" } { "origin" "2008 -800 1048" "classname" "ammo_grenades" } { "origin" "1952 -800 1048" "classname" "ammo_rockets" } { "origin" "1000 -600 1056" "classname" "monster_soldier" "angle" "180" "spawnflags" "2049" } { "targetname" "t362" "origin" "1184 96 1056" "spawnflags" "2051" "angle" "90" "classname" "monster_soldier" } { "origin" "872 88 1248" "spawnflags" "2049" "angle" "90" "classname" "monster_berserk" } { "classname" "item_health_large" "origin" "992 160 1304" } { "classname" "item_armor_shard" "origin" "992 52 1240" } { "classname" "item_armor_shard" "origin" "992 96 1240" } { "classname" "monster_soldier_ss" "angle" "0" "spawnflags" "2051" "targetname" "t198" "origin" "1048 -168 1248" } { "spawnflags" "2048" "classname" "point_combat" "target" "t240" "targetname" "t242" "origin" "1568 224 1240" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t241" "target" "t242" "origin" "1568 224 1392" } { "classname" "point_combat" "spawnflags" "2048" "targetname" "t240" "origin" "1568 400 1240" } { "targetname" "t363" "classname" "monster_stalker" "spawnflags" "6921" "angle" "270" "origin" "1188 284 1378" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t237" "target" "t238" "origin" "1048 112 1384" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t236" "target" "t237" "origin" "1152 -152 1384" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t235" "target" "t236" "origin" "1144 -408 1384" } { "spawnflags" "2048" "classname" "point_combat" "targetname" "t234" "target" "t235" "origin" "1056 -408 1384" } { "target" "t361" "classname" "point_combat" "spawnflags" "2048" "targetname" "t238" "origin" "840 112 1384" } { "item" "ammo_cells" "classname" "monster_stalker" "spawnflags" "2057" "angle" "135" "target" "t234" "targetname" "t198" "origin" "1052 -668 1386" } { "targetname" "t140" "item" "ammo_cells" "classname" "monster_daedalus" "spawnflags" "3843" "angle" "45" "origin" "916 228 1264" } { "targetname" "t140" "item" "ammo_cells" "classname" "monster_hover" "spawnflags" "7171" "angle" "45" "origin" "908 224 1264" } { "classname" "point_combat" "wait" "10" "targetname" "t232" "origin" "1000 304 1224" "spawnflags" "2048" } { "item" "ammo_bullets" "classname" "monster_soldier_ss" "angle" "315" "spawnflags" "2049" "origin" "920 424 1240" "target" "t232" } { "classname" "point_combat" "origin" "1560 352 1224" "spawnflags" "2049" "angle" "315" "targetname" "t229" } { "classname" "point_combat" "targetname" "t228" "origin" "1600 224 1224" "target" "t229" "spawnflags" "2048" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t227" "origin" "1920 288 1224" } { "angle" "315" "classname" "monster_soldier_ss" "targetname" "uknow" "spawnflags" "7171" "target" "t227" "origin" "1736 416 1240" } { "angle" "315" "classname" "monster_gunner" "targetname" "uknow" "spawnflags" "6913" "target" "t227" "origin" "1784 416 1248" } { "classname" "point_combat" "origin" "1992 296 1224" "targetname" "t225" "wait" "2.5" "angle" "270" "spawnflags" "2048" } { "classname" "monster_soldier" "angle" "315" "spawnflags" "2051" "origin" "1896 288 1248" "target" "t225" "targetname" "t223" } { "model" "*24" "classname" "trigger_once" "spawnflags" "2048" "target" "t223" } { "item" "ammo_bullets" "classname" "monster_gunner" "angle" "315" "spawnflags" "3841" "origin" "1920 -152 1240" } { "classname" "point_combat" "spawnflags" "2048" "angle" "0" "origin" "1720 96 1224" "target" "t228" "wait" "5" "targetname" "t385" } { "deathtarget" "uknow" "spawnflags" "2049" "item" "ammo_shells" "classname" "monster_soldier" "angle" "270" "origin" "2016 -64 1248" "targetname" "t213" "target" "t384" } { "classname" "monster_soldier" "angle" "225" "spawnflags" "2049" "item" "ammo_shells" "origin" "1704 232 1248" } { "item" "ammo_shells" "classname" "monster_soldier" "spawnflags" "7169" "target" "t122" "angle" "0" "origin" "2912 -912 928" } { "classname" "monster_soldier" "item" "ammo_shells" "spawnflags" "7683" "target" "t218" "targetname" "t383" "origin" "1880 -680 992" } { "classname" "ammo_prox" "origin" "1760 -672 1048" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t218" "origin" "1776 -592 968" } { "item" "ammo_grenades" "classname" "monster_gunner" "target" "t218" "spawnflags" "6403" "angle" "135" "targetname" "t383" "origin" "1880 -672 992" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t217" "origin" "2016 -576 976" } { "item" "ammo_bullets" "classname" "monster_soldier_ss" "spawnflags" "2051" "angle" "45" "target" "t217" "origin" "1624 -488 984" "targetname" "t383" } { "classname" "misc_deadsoldier" "spawnflags" "2056" "angle" "90" "origin" "1688 -96 960" } { "classname" "misc_deadsoldier" "spawnflags" "2054" "angle" "315" "origin" "1632 -312 960" } { "classname" "ammo_rockets" "origin" "1696 8 992" "targetname" "t119" // added to silence warning } { "classname" "item_health" "origin" "1376 -224 992" } { "classname" "item_health" "origin" "1504 -360 992" } { "model" "*25" "classname" "func_wall" "spawnflags" "3584" } { "model" "*26" "classname" "func_wall" "spawnflags" "3072" } { "targetname" "t101" "classname" "monster_medic" "angle" "225" "spawnflags" "6915" "item" "ammo_cells" "origin" "1304 -160 992" } { "targetname" "t101" "classname" "monster_soldier" "angle" "270" "spawnflags" "7683" "origin" "1248 -96 992" } { "classname" "point_combat" "targetname" "t214" "spawnflags" "2049" "origin" "1312 -480 976" } { "angle" "0" "classname" "monster_soldier_ss" "spawnflags" "6913" "item" "ammo_bullets" "target" "t100" "targetname" "t101" "origin" "1056 -416 1000" } { "classname" "monster_soldier" "targetname" "t101" "target" "t98" "spawnflags" "3073" "origin" "1432 -616 992" } { "classname" "monster_soldier_ss" "angle" "315" "origin" "1904 -152 1240" "spawnflags" "7168" } { "item" "ammo_cells" "origin" "1824 -864 1048" "spawnflags" "2049" "angle" "225" "classname" "monster_medic" } { "origin" "2496 -1088 1048" "item" "ammo_cells" "targetname" "t88" "target" "t86" "angle" "180" "spawnflags" "6401" "classname" "monster_medic" } { "origin" "2496 -1104 1048" "targetname" "t88" "target" "t86" "spawnflags" "7681" "angle" "180" "classname" "monster_soldier" } { "origin" "1904 -872 864" "targetname" "t137" "angle" "0" "spawnflags" "3841" "classname" "monster_medic" } { "origin" "2184 -648 864" "spawnflags" "7169" "angle" "0" "target" "t79" "item" "ammo_bullets" "classname" "monster_soldier_ss" } { "origin" "2176 -256 848" "targetname" "t212" "classname" "point_combat" "spawnflags" "2048" } { "origin" "2416 -264 928" "target" "t212" "targetname" "t211" "angle" "180" "spawnflags" "2049" "item" "ammo_shells" "classname" "monster_soldier" } { "item" "ammo_bullets" "origin" "1800 -1120 1056" "targetname" "t88" "target" "t87" "angle" "0" "spawnflags" "7681" "classname" "monster_soldier_ss" } { "origin" "2272 -800 1144" "spawnflags" "6409" "angle" "-2" "classname" "monster_turret" } { "model" "*27" "spawnflags" "5888" "classname" "func_wall" } { "origin" "480 -288 1476" "targetname" "t208" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*28" "targetname" "t154" "target" "t208" "spawnflags" "2048" "mass" "75" "classname" "func_explosive" } { "targetname" "t154" "origin" "480 -288 1508" "angle" "-2" "spawnflags" "2208" "classname" "monster_turret" } { "targetname" "t163" "target" "t390" "origin" "3344 -128 936" "spawnflags" "2049" "angle" "0" "classname" "monster_medic" } { "angle" "45" "origin" "3216 -1840 1184" "spawnflags" "7169" "classname" "monster_hover" } { "origin" "1528 -2592 1136" "angle" "270" "spawnflags" "2049" "classname" "monster_gunner" } { "origin" "1256 -2768 1112" "targetname" "t207" "spawnflags" "2049" "classname" "point_combat" } { "origin" "1288 -2512 1144" "target" "t207" "spawnflags" "2049" "angle" "180" "classname" "monster_soldier_ss" } { "origin" "880 -2496 1240" "spawnflags" "7169" "classname" "monster_hover" } { "origin" "896 -2536 1240" "spawnflags" "2817" "classname" "monster_daedalus" } { "origin" "1208 -2472 1128" "angle" "180" "spawnflags" "2049" "classname" "monster_gunner" } { "origin" "544 -2056 1112" "classname" "item_armor_combat" } { "origin" "-360 -1984 800" "item" "ammo_shells" "spawnflags" "2049" "angle" "225" "classname" "monster_soldier" } { "origin" "-384 -2816 784" "targetname" "t203" "classname" "point_combat" "spawnflags" "2048" } { "target" "t96" "item" "ammo_slugs" "origin" "408 -2312 992" "angle" "180" "spawnflags" "6913" "classname" "monster_gladiator" } { "targetname" "t204" "origin" "24 -1904 928" "target" "t202" "spawnflags" "2049" "angle" "180" "classname" "monster_medic_commander" "item" "ammo_cells" } { "origin" "-392 -1920 784" "targetname" "t202" "spawnflags" "2048" "classname" "point_combat" } { "origin" "1376 296 1240" "classname" "ammo_prox" } { "origin" "1440 224 1240" "classname" "item_armor_shard" } { "origin" "1312 296 1240" "classname" "item_armor_shard" } { "origin" "1440 168 1240" "classname" "item_armor_shard" } { "origin" "1248 104 1248" "angle" "180" "spawnflags" "3841" "item" "ammo_bullets" "classname" "monster_soldier_ss" } { "origin" "1248 96 1248" "spawnflags" "7681" "angle" "180" "classname" "monster_soldier" } { "origin" "1372 220 1378" "angle" "270" "spawnflags" "2057" "classname" "monster_stalker" "targetname" "t239" "target" "t241" } { "origin" "1120 -24 1240" "spawnflags" "2048" "classname" "ammo_nails" } { "target" "t363" "origin" "1056 136 1248" "spawnflags" "3841" "angle" "270" "classname" "monster_berserk" } { "classname" "item_health_large" "origin" "928 -224 1304" } { "origin" "792 -288 1224" "spawnflags" "2048" "targetname" "t200" "classname" "point_combat" } { "item" "ammo_grenades" "origin" "920 -344 1248" "targetname" "getem'" "target" "t200" "spawnflags" "2051" "angle" "135" "classname" "monster_gunner" } { "origin" "968 -344 1248" "item" "ammo_shells" "spawnflags" "2049" "angle" "180" "classname" "monster_soldier" } { "origin" "992 -288 1304" "classname" "item_health_small" } { "origin" "928 96 1304" "classname" "ammo_prox" } { "origin" "792 -496 1232" "classname" "item_health_large" } { "origin" "880 -472 1224" "spawnflags" "2049" "targetname" "t199" "classname" "point_combat" } { "targetname" "getem'" "origin" "1000 -552 1240" "target" "t199" "spawnflags" "2051" "angle" "135" "classname" "monster_gunner" } { "model" "*29" "target" "t198" "spawnflags" "2048" "classname" "trigger_once" } { "pathtarget" "getem'" "origin" "880 -80 1224" "angle" "180" "spawnflags" "2049" "targetname" "t197" "classname" "point_combat" } { "origin" "800 -96 1240" "target" "t197" "spawnflags" "2049" "angle" "90" "classname" "monster_soldier_ss" } { "origin" "664 -728 1232" "classname" "item_health_small" } { "origin" "600 -728 1232" "classname" "item_health_small" } { "origin" "720 -728 1232" "classname" "item_health_small" } { "item" "ammo_shells" "targetname" "t198" "origin" "856 -672 1248" "angle" "90" "spawnflags" "7171" "classname" "monster_soldier" } { "item" "ammo_bullets" "targetname" "t198" "origin" "872 -672 1248" "spawnflags" "6915" "angle" "0" "classname" "monster_gunner" } { "origin" "936 -1000 1304" "classname" "ammo_slugs" } { "classname" "item_health" "origin" "600 -1056 1240" } { "origin" "856 -1112 1224" "targetname" "t194" "spawnflags" "2049" "classname" "point_combat" } { "origin" "688 -1176 1248" "target" "t194" "spawnflags" "2049" "angle" "90" "classname" "monster_soldier_ss" } { "model" "*30" "message" "Cargo lift activated." "target" "t193" "spawnflags" "2048" "_minlight" ".3" "wait" "-1" "angle" "90" "classname" "func_button" } { "model" "*31" "target" "t381" "spawnflags" "2048" "targetname" "t193" "classname" "func_train" } { "target" "t382" "targetname" "t381" "origin" "784 -1344 1184" "spawnflags" "0" "classname" "path_corner" } { "target" "ammo_grenades" "origin" "608 -1184 1240" "targetname" "t144" "spawnflags" "2048" "classname" "target_spawner" } { "target" "ammo_rockets" "origin" "752 -928 1240" "targetname" "t66" "item" "ammo_bullets" "spawnflags" "2048" "classname" "target_spawner" } { "target" "ammo_tesla" "origin" "-416 -2336 848" "spawnflags" "2048" "targetname" "t59" "classname" "target_spawner" } { "origin" "224 -744 1440" "light" "80" "classname" "light" } { "origin" "1888 -2848 1048" "light" "80" "classname" "light" } { "origin" "2784 -2648 1112" "classname" "ammo_rockets" } { "origin" "2696 -2328 1112" "classname" "item_health_large" } { "origin" "2488 -2592 1112" "classname" "item_health_large" } { "spawnflags" "2048" "item" "ammo_grenades" "origin" "2536 -1752 1176" "targetname" "t190" "classname" "monster_gunner" } { "origin" "2456 -1816 1160" "targetname" "t189" "classname" "point_combat" "spawnflags" "2048" } { "origin" "2544 -1952 1176" "target" "t190" "spawnflags" "2049" "angle" "180" "item" "ammo_bullets" "classname" "monster_soldier_ss" } { "target" "t189" "spawnflags" "2049" "angle" "180" "item" "ammo_shells" "origin" "2592 -1888 1184" "classname" "monster_soldier" } { "origin" "2856 592 1048" "classname" "item_health_large" } { "origin" "2904 672 1144" "classname" "ammo_prox" } { "classname" "light" "_color" "0.000000 0.501961 1.000000" "light" "125" "origin" "2496 344 1096" } { "map" "rbase2$rb2" "origin" "2488 304 1048" "targetname" "t188" "classname" "target_changelevel" "spawnflags" "2048" } { "origin" "2456 304 1048" "target" "t188" "delay" "5" "targetname" "t134" "classname" "trigger_relay" } { "item" "ammo_cells" "origin" "3060 -1108 1178" "target" "t246" "angle" "180" "spawnflags" "2049" "classname" "monster_stalker" } { "classname" "monster_hover" "spawnflags" "3841" "origin" "3288 -1440 1184" "angle" "180" } { "angle" "270" "origin" "2912 -1248 1208" "targetname" "t31" "spawnflags" "2051" "classname" "monster_daedalus" } { "origin" "2848 -2728 1168" "targetname" "t185" "spawnflags" "2048" "wait" "15" "classname" "point_combat" } { "classname" "monster_gunner" "spawnflags" "6913" "angle" "45" "origin" "2848 -2952 1184" } { "origin" "2528 -2128 1168" "target" "t182" "targetname" "t181" "classname" "path_corner" "spawnflags" "2048" } { "origin" "2528 -2112 1168" "target" "t184" "targetname" "t183" "classname" "path_corner" "spawnflags" "2048" } { "origin" "2248 -2120 1168" "targetname" "t184" "target" "t181" "classname" "path_corner" "spawnflags" "2048" } { "origin" "2688 -2256 1168" "target" "t183" "targetname" "t182" "classname" "path_corner" "spawnflags" "2048" } { "item" "ammo_slugs" "origin" "2240 -2112 1184" "target" "t184" "spawnflags" "2049" "classname" "monster_gladiator" } { "origin" "1952 -2364 1112" "spawnflags" "2048" "targetname" "t180" "classname" "target_explosion" } { "origin" "1952 -2364 1184" "delay" ".2" "spawnflags" "2048" "targetname" "t180" "classname" "target_explosion" } { "model" "*32" "targetname" "t179" "spawnflags" "2048" "target" "t180" "mass" "150" "classname" "func_explosive" } { "origin" "1952 -2416 1104" "targetname" "t178" "spawnflags" "2048" "classname" "point_combat" } { "origin" "1952 -2336 1120" "targetname" "t179" "target" "t178" "spawnflags" "2049" "angle" "270" "classname" "monster_gunner" } { "origin" "2096 -2720 1168" "target" "t179" "classname" "monster_daedalus" "spawnflags" "6401" "angle" "180" } { "angle" "180" "origin" "2088 -2720 1168" "target" "t179" "spawnflags" "7681" "classname" "monster_hover" } { "origin" "1920 -2800 1072" "targetname" "t177" "classname" "target_secret" "spawnflags" "2048" } { "origin" "1888 -2820 1056" "targetname" "t177" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*33" "message" "You found a secret." "health" "5" "target" "t177" "mass" "100" "spawnflags" "2048" "classname" "func_explosive" } { "attenuation" "-1" "origin" "2880 -2464 920" "noise" "world/fish.wav" "classname" "target_speaker" "spawnflags" "2048" "targetname" "t369" } { "origin" "2944 -2728 1008" "spawnflags" "2048" "message" "Security doors offline.\n Proceed to shuttle." "targetname" "t170" "classname" "target_help" } { "model" "*34" "targetname" "t28" "spawnflags" "2052" "target" "t170" "classname" "trigger_once" } { "origin" "352 -632 1520" "targetname" "t169" "classname" "target_secret" "spawnflags" "2048" } { "origin" "224 -748 1432" "spawnflags" "5888" "classname" "item_quad" } { "origin" "224 -744 1432" "spawnflags" "2048" "classname" "item_sphere_defender" } { "origin" "224 -712 1440" "spawnflags" "2048" "targetname" "t168" "classname" "target_explosion" } { "model" "*35" "targetname" "t169" "target" "t168" "spawnflags" "2048" "mass" "100" "classname" "func_explosive" } { "model" "*36" "spawnflags" "7936" "classname" "func_wall" } { "model" "*37" "target" "t169" "message" "A secret is revealed." "classname" "func_button" "angle" "270" "health" "1" "wait" "-1" "lip" "18" "spawnflags" "2048" } { "origin" "272 -536 1376" "spawnflags" "2049" "angle" "0" "classname" "monster_soldier" } { "item" "ammo_shells" "target" "t166" "origin" "424 304 1248" "spawnflags" "2049" "angle" "315" "classname" "monster_soldier" } { "origin" "448 224 1336" "light" "125" "classname" "light" } { "origin" "480 356 1376" "targetname" "t166" "classname" "monster_turret" "angle" "270" "spawnflags" "7073" } { "origin" "480 356 1376" "targetname" "t166" "spawnflags" "7305" "angle" "270" "classname" "monster_turret" } { "origin" "480 324 1376" "spawnflags" "2048" "targetname" "t165" "classname" "target_explosion" } { "model" "*38" "targetname" "t166" "spawnflags" "2048" "target" "t165" "mass" "75" "classname" "func_explosive" } { "model" "*39" "classname" "func_wall" "spawnflags" "5888" } { "origin" "1976 -184 968" "classname" "misc_deadsoldier" "spawnflags" "2052" } { "origin" "1408 -272 968" "angle" "270" "spawnflags" "2818" "classname" "misc_deadsoldier" } { "item" "ammo_slugs" "origin" "1408 -128 1312" "spawnflags" "2049" "angle" "90" "classname" "monster_gladiator" "target" "t248" } { "origin" "1512 -104 984" "classname" "item_health_large" } { "origin" "1176 304 1128" "target" "oresound" "targetname" "oredeath" "classname" "trigger_relay" "spawnflags" "2048" } { "origin" "1224 304 1128" "delay" "23" "target" "oresound" "targetname" "oredeath" "classname" "trigger_relay" "spawnflags" "2048" } { "targetname" "oresound" "origin" "1112 288 1016" "noise" "world/amb10.wav" "spawnflags" "2050" "team" "fiuck" "classname" "target_speaker" } { "targetname" "oresound" "origin" "1128 288 1016" "noise" "world/amb10.wav" "spawnflags" "2050" "team" "fiuck" "classname" "target_speaker" } { "origin" "3504 -616 1184" "spawnflags" "2049" "angle" "90" "item" "ammo_shells" "classname" "monster_soldier" } { "origin" "3552 -352 1348" "spawnflags" "2816" "targetname" "t164" "classname" "target_explosion" } { "model" "*40" "spawnflags" "1024" "classname" "func_wall" } { "targetname" "t163" "angle" "-2" "spawnflags" "2977" "origin" "3552 -352 1380" "classname" "monster_turret" } { "origin" "3584 -60 1216" "targetname" "t162" "spawnflags" "2304" "classname" "target_explosion" } { "model" "*41" "targetname" "t163" "target" "t162" "spawnflags" "2304" "mass" "75" "classname" "func_explosive" } { "model" "*42" "classname" "func_wall" "spawnflags" "1536" } { "targetname" "t163" "origin" "3584 -28 1216" "spawnflags" "2441" "angle" "270" "classname" "monster_turret" } { "item" "ammo_grenades" "targetname" "t186" "target" "t185" "origin" "2840 -2856 1184" "angle" "45" "spawnflags" "2049" "classname" "monster_gunner" } { "origin" "2848 -2968 1184" "spawnflags" "7425" "angle" "45" "classname" "monster_berserk" } { "item" "ammo_shells" "origin" "2848 -2984 1184" "spawnflags" "7681" "angle" "45" "classname" "monster_soldier" } { "origin" "3488 -1032 928" "targetname" "t120" "target" "t121" "item" "ammo_bullets" "spawnflags" "3841" "classname" "monster_gunner" } { "origin" "3488 -1040 928" "target" "t121" "targetname" "t120" "spawnflags" "7169" "item" "ammo_bullets" "classname" "monster_soldier_ss" } { "spawnflags" "2816" "origin" "2528 -160 1284" "targetname" "t161" "classname" "target_explosion" } { "model" "*43" "targetname" "t160" "target" "t161" "spawnflags" "2816" "mass" "75" "classname" "func_explosive" } { "model" "*44" "spawnflags" "1024" "classname" "func_wall" } { "spawnflags" "2304" "origin" "2400 352 1284" "targetname" "t159" "classname" "target_explosion" } { "model" "*45" "spawnflags" "2304" "targetname" "t160" "target" "t159" "mass" "75" "classname" "func_explosive" } { "model" "*46" "spawnflags" "1536" "classname" "func_wall" } { "spawnflags" "2048" "origin" "2752 672 1284" "targetname" "t157" "classname" "target_explosion" } { "model" "*47" "mass" "75" "targetname" "t126" "target" "t157" "spawnflags" "2048" "classname" "func_explosive" } { "model" "*48" "spawnflags" "5888" "classname" "func_wall" } { "origin" "2752 672 1316" "targetname" "t126" "spawnflags" "2185" "angle" "-2" "classname" "monster_turret" } { "origin" "3168 -816 920" "classname" "item_health_small" } { "origin" "3232 -816 920" "classname" "item_health_small" } { "model" "*49" "spawnflags" "5120" "classname" "func_wall" } { "origin" "3104 -928 1028" "targetname" "t155" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*50" "targetname" "t123" "target" "t155" "spawnflags" "6912" "mass" "75" "classname" "func_explosive" } { "origin" "3104 -928 1060" "targetname" "t123" "angle" "-2" "spawnflags" "7049" "classname" "monster_turret" } { "origin" "2752 -64 1016" "light" "125" "classname" "light" } { "target" "t357" "item" "ammo_grenades" "classname" "monster_gunner" "angle" "0" "spawnflags" "2049" "origin" "2624 -512 1176" } { "model" "*51" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "90" "team" "goinexit" "_minlight" ".3" "spawnflags" "2048" "wait" "-1" } { "model" "*52" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "270" "team" "goinexit" "_minlight" ".3" "spawnflags" "2048" "wait" "-1" } { "angle" "-2" "classname" "monster_turret" "spawnflags" "6153" "targetname" "t105" "origin" "2976 -2752 1144" } { "angle" "-2" "classname" "monster_turret" "spawnflags" "3873" "targetname" "t105" "origin" "2976 -2752 1144" } { "classname" "light" "light" "125" "origin" "-128 -2304 1024" } { "classname" "item_health" "origin" "640 -600 1368" } { "classname" "item_health" "origin" "640 -544 1368" } { "classname" "point_combat" "targetname" "t152" "target" "t153" "origin" "200 -224 1376" "spawnflags" "2048" } { "classname" "point_combat" "wait" "6" "targetname" "t153" "origin" "288 -224 1376" "spawnflags" "2048" } { "item" "ammo_grenades" "classname" "monster_gunner" "angle" "315" "spawnflags" "2049" "target" "t152" "targetname" "t154" "origin" "152 -120 1376" } { "item" "ammo_shells" "classname" "monster_soldier" "angle" "0" "spawnflags" "2049" "origin" "344 -88 1248" } { "item" "ammo_slugs" "classname" "monster_gladiator" "angle" "90" "spawnflags" "2049" "target" "t154" "origin" "560 -392 1248" } { "model" "*53" "classname" "trigger_hurt" "dmg" "10000" "spawnflags" "3" "targetname" "t129" } { "classname" "func_timer" "target" "t151" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 896 920" "targetname" "t378" } { "classname" "func_timer" "target" "t149" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 448 920" "targetname" "t378" } { "classname" "func_timer" "target" "t148" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 320 920" "targetname" "t378" } { "classname" "func_timer" "target" "t147" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 192 920" "targetname" "t378" } { "classname" "func_timer" "target" "t146" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 64 920" "targetname" "t378" } { "classname" "func_timer" "target" "t150" "random" "2" "wait" "4" "spawnflags" "0" "origin" "2496 576 920" "targetname" "t378" } { "sounds" "1" "count" "50" "origin" "2424 896 920" "classname" "target_splash" "targetname" "t151" "spawnflags" "2048" } { "sounds" "1" "count" "50" "origin" "2568 896 920" "classname" "target_splash" "targetname" "t151" "spawnflags" "2048" } { "count" "50" "sounds" "1" "origin" "2424 64 920" "classname" "target_splash" "targetname" "t146" "spawnflags" "2048" } { "count" "50" "sounds" "1" "origin" "2568 64 920" "classname" "target_splash" "targetname" "t146" } { "sounds" "1" "count" "50" "origin" "2424 192 920" "classname" "target_splash" "targetname" "t147" } { "sounds" "1" "count" "50" "origin" "2568 192 920" "classname" "target_splash" "targetname" "t147" "spawnflags" "2048" } { "sounds" "1" "count" "50" "origin" "2424 320 920" "classname" "target_splash" "targetname" "t148" } { "sounds" "1" "count" "50" "origin" "2568 320 920" "classname" "target_splash" "targetname" "t148" "spawnflags" "2048" } { "sounds" "1" "count" "50" "classname" "target_splash" "origin" "2424 448 920" "targetname" "t149" "spawnflags" "2048" } { "sounds" "1" "count" "50" "classname" "target_splash" "origin" "2568 448 920" "targetname" "t149" } { "sounds" "1" "count" "50" "classname" "target_splash" "origin" "2424 576 920" "targetname" "t150" } { "sounds" "1" "count" "50" "classname" "target_splash" "origin" "2568 576 920" "targetname" "t150" "spawnflags" "2048" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2432 640 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2560 640 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2432 832 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2560 832 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2432 512 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2560 512 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2432 384 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2560 384 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2432 256 944" "light" "150" "targetname" "t377" "spawnflags" "1" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2560 256 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2432 128 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2560 128 944" "light" "150" "targetname" "t377" "spawnflags" "1" } { "style" "32" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2560 960 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "style" "32" "classname" "light" "_color" "1.000000 0.000000 0.000000" "origin" "2432 960 944" "light" "150" "spawnflags" "1" "targetname" "t377" } { "classname" "item_health_small" "origin" "2664 624 1048" } { "classname" "item_health_small" "origin" "2664 576 1048" } { "classname" "item_health_small" "origin" "2664 528 1048" } { "classname" "item_health_small" "origin" "2664 672 1048" } { "angle" "-2" "classname" "monster_turret" "origin" "2752 -160 1080" "spawnflags" "2057" } { "classname" "light" "light" "100" "_color" "0.000000 0.501961 1.000000" "origin" "396 100 1300" } { "_color" "0.000000 0.501961 1.000000" "light" "100" "classname" "light" "origin" "608 112 1376" } { "classname" "item_health" "origin" "1824 -352 1240" } { "classname" "item_armor_shard" "origin" "736 -1424 1112" } { "classname" "monster_stalker" "spawnflags" "2057" "angle" "180" "origin" "916 -948 1322" } { "classname" "target_explosion" "targetname" "t144" "spawnflags" "2048" "origin" "608 -1184 1256" } { "model" "*54" "classname" "func_explosive" "health" "25" "mass" "250" "target" "t144" "spawnflags" "2048" } { "origin" "608 120 1368" "classname" "light" "light" "75" } { "origin" "416 120 1368" "light" "75" "classname" "light" } { "origin" "448 128 1336" "item" "key_blue_key" "spawnflags" "2048" "targetname" "t143" "target" "t7" "classname" "trigger_key" } { "light" "120" "origin" "1344 -112 1144" "classname" "light" } { "classname" "light" "origin" "1344 -256 1144" "light" "120" } { "light" "120" "origin" "1472 -256 1144" "classname" "light" } { "classname" "light" "origin" "1472 -112 1144" "light" "120" } { "origin" "2016 -536 1048" "spawnflags" "2051" "angle" "135" "classname" "monster_daedalus" "targetname" "t383" } { "origin" "1224 -688 1024" "targetname" "t142" "classname" "target_secret" "spawnflags" "2048" } { "model" "*55" "target" "t142" "message" "You found a secret." "spawnflags" "2048" "classname" "trigger_once" } { "targetname" "t362" "origin" "920 152 1056" "item" "ammo_bullets" "spawnflags" "2051" "angle" "0" "classname" "monster_soldier_ss" } { "origin" "1000 232 1048" "classname" "weapon_machinegun" } { "origin" "928 224 1024" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "1824 -32 1240" "classname" "item_armor_body" "spawnflags" "2048" } { "origin" "1920 424 1232" "classname" "item_health_small" } { "origin" "1968 424 1232" "classname" "item_health_small" } { "origin" "2016 424 1232" "classname" "item_health_small" } { "origin" "2024 376 1232" "classname" "item_health_small" } { "model" "*56" "target" "t140" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "1120 344 1240" "targetname" "t140" "angle" "45" "spawnflags" "2051" "classname" "monster_berserk" } { "spawnflags" "2051" "origin" "1896 96 1240" "angle" "315" "classname" "monster_berserk" "targetname" "t223" } { "item" "ammo_slugs" "origin" "1664 400 1240" "spawnflags" "2051" "angle" "0" "classname" "monster_gladiator" "target" "t239" "targetname" "uknow" } { "origin" "1848 200 1136" "targetname" "t138" "classname" "target_secret" "spawnflags" "2048" } { "model" "*57" "message" "You found a secret" "target" "t138" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*58" "spawnflags" "2048" "classname" "func_wall" } { "origin" "928 -288 1048" "classname" "item_health" } { "origin" "920 -232 976" "classname" "item_health" } { "origin" "1024 -296 992" "classname" "item_armor_shard" } { "origin" "984 -296 992" "classname" "item_armor_shard" } { "origin" "920 -184 992" "classname" "item_armor_shard" } { "item" "ammo_cells" "origin" "952 -40 1088" "spawnflags" "7681" "classname" "monster_hover" } { "item" "ammo_cells" "origin" "968 -56 1088" "angle" "270" "spawnflags" "6401" "classname" "monster_daedalus" } { "targetname" "t101" "origin" "1184 -168 992" "angle" "315" "spawnflags" "7427" "classname" "monster_gunner" "item" "ammo_grenades" } { "targetname" "t137" "origin" "1904 -872 864" "spawnflags" "6401" "angle" "0" "classname" "monster_gladiator" } { "origin" "2520 -992 1056" "classname" "monster_soldier" "angle" "90" "spawnflags" "7681" } { "target" "t137" "origin" "2344 -792 864" "spawnflags" "2049" "angle" "180" "classname" "monster_soldier" } { "origin" "2504 -1008 1056" "spawnflags" "7425" "angle" "90" "classname" "monster_berserk" } { "classname" "misc_deadsoldier" "spawnflags" "2056" "origin" "984 -1696 832" } { "classname" "ammo_slugs" "origin" "992 -1624 848" } { "classname" "weapon_railgun" "origin" "992 -1744 856" } { "target" "t211" "classname" "monster_berserk" "angle" "270" "spawnflags" "2049" "origin" "2176 -232 864" } { "classname" "monster_stalker" "spawnflags" "2057" "angle" "180" "origin" "2820 -252 994" } { "spawnflags" "2048" "classname" "target_help" "targetname" "t136" "origin" "2712 -360 1312" "message" "Transport accesssible.\nProceed to Logistics." } { "classname" "trigger_relay" "targetname" "t134" "target" "t135" "origin" "2640 384 1144" } { "model" "*59" "classname" "func_door" "angle" "180" "_minlight" ".3" "team" "exitrain" "targetname" "t135" "wait" "-1" } { "model" "*60" "spawnflags" "0" "classname" "func_door" "angle" "0" "_minlight" ".3" "team" "exitrain" "targetname" "t135" "wait" "-1" } { "model" "*61" "origin" "2496 396 1028" "classname" "func_door_rotating" "distance" "70" "_minlight" ".3" "wait" "-1" "sounds" "2" "spawnflags" "2114" "target" "t134" "targetname" "t375" } { "classname" "path_corner" "wait" "-1" "origin" "2576 214 1030" "targetname" "t373" "spawnflags" "2048" } { "classname" "path_corner" "origin" "2592 214 1030" "wait" "1.5" "targetname" "t372" "target" "t373" "spawnflags" "2048" } { "model" "*62" "message" "Shuttle power online." "spawnflags" "2048" "classname" "func_button" "angle" "0" "_minlight" ".3" "wait" "-1" "target" "t129" "killtarget" "comeout" } { "classname" "path_corner" "origin" "2592 302 1030" "target" "t372" "targetname" "t374" "spawnflags" "2048" } { "model" "*63" "classname" "func_train" "spawnflags" "2050" "speed" "50" "target" "t374" "targetname" "t135" } { "model" "*64" "classname" "trigger_once" "spawnflags" "2048" "target" "t126" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t125" "origin" "2752 -16 1168" } { "item" "ammo_grenades" "classname" "monster_gunner" "spawnflags" "2049" "angle" "90" "target" "t125" "targetname" "t126" "origin" "2752 -64 1184" } { "classname" "ammo_cells" "origin" "1176 -608 984" } { "classname" "weapon_bfg" "origin" "1184 -672 984" } { "origin" "3368 -608 1152" "angle" "180" "spawnflags" "2064" "classname" "misc_deadsoldier" } { "origin" "3416 -608 1240" "classname" "weapon_shotgun" } { "origin" "3552 -480 1168" "classname" "ammo_shells" } { "origin" "3288 -616 1176" "classname" "item_health_large" } { "origin" "3544 -496 1264" "spawnflags" "7425" "angle" "90" "classname" "monster_hover" } { "target" "t156" "origin" "3296 -416 928" "spawnflags" "6913" "angle" "0" "classname" "monster_soldier" } { "origin" "3296 -128 928" "classname" "ammo_grenades" "spawnflags" "2048" } { "target" "t83" "targetname" "t82" "origin" "3352 -600 912" "spawnflags" "2048" "classname" "point_combat" } { "origin" "3632 -640 904" "targetname" "t124" "spawnflags" "2049" "classname" "point_combat" } { "item" "ammo_bullets" "origin" "3624 -616 928" "target" "t124" "angle" "225" "spawnflags" "3841" "classname" "monster_gunner" } { "item" "ammo_bullets" "origin" "3592 -528 928" "angle" "225" "spawnflags" "7681" "classname" "monster_soldier_ss" } { "origin" "3600 -536 928" "spawnflags" "7425" "angle" "225" "classname" "monster_berserk" } { "origin" "3688 -352 984" "classname" "ammo_bullets" } { "origin" "3752 -136 912" "classname" "item_health" } { "origin" "3480 -80 912" "classname" "item_health_large" } { "origin" "3496 64 1184" "spawnflags" "7169" "angle" "180" "classname" "monster_soldier" } { "origin" "3316 68 1178" "spawnflags" "2049" "angle" "0" "classname" "monster_stalker" } { "origin" "3496 24 1176" "classname" "ammo_slugs" } { "origin" "3496 104 1176" "classname" "ammo_cells" } { "origin" "2904 -1000 920" "classname" "ammo_cells" } { "origin" "3096 -1000 920" "classname" "ammo_shells" } { "origin" "3232 -856 912" "targetname" "t122" "spawnflags" "2048" "classname" "point_combat" } { "origin" "2920 -1760 832" "spawnflags" "2049" "classname" "misc_deadsoldier" } { "origin" "2848 -1688 856" "classname" "ammo_prox" } { "origin" "2944 -1808 856" "spawnflags" "2048" "classname" "weapon_proxlauncher" } { "classname" "item_armor_shard" "origin" "3616 -1328 856" } { "classname" "item_armor_shard" "origin" "3616 -1384 856" } { "origin" "3616 -1432 856" "classname" "item_armor_shard" } { "origin" "3616 -1272 856" "classname" "item_armor_shard" } { "origin" "3584 -1040 912" "spawnflags" "2048" "targetname" "t121" "classname" "point_combat" } { "model" "*65" "target" "t120" "spawnflags" "2048" "classname" "trigger_once" } { "item" "ammo_shells" "origin" "3000 -1240 928" "spawnflags" "2049" "angle" "90" "classname" "monster_soldier" } { "item" "ammo_cells" "origin" "3216 -1832 1208" "spawnflags" "3841" "angle" "45" "classname" "monster_daedalus" } { "targetname" "t31" "angle" "180" "origin" "3288 -1664 1208" "spawnflags" "7427" "classname" "monster_hover" } { "origin" "2944 -512 1208" "classname" "light" "light" "115" } { "_color" "0.000000 0.501961 1.000000" "light" "100" "classname" "light" "origin" "2768 -704 1208" } { "light" "125" "classname" "light" "origin" "2496 -256 968" } { "light" "100" "classname" "light" "origin" "2688 -256 968" } { "light" "100" "classname" "light" "origin" "2816 -256 968" } { "classname" "light" "light" "125" "origin" "2304 -256 968" } { "origin" "1472 -256 1024" "targetname" "t118" "classname" "target_explosion" "spawnflags" "2816" } { "model" "*66" "targetname" "t119" "target" "t118" "mass" "150" "classname" "func_explosive" "spawnflags" "2816" } { "origin" "1404 -252 1058" "targetname" "t119" "spawnflags" "2819" "angle" "0" "classname" "monster_stalker" } { "origin" "1728 -60 1024" "targetname" "t117" "classname" "target_explosion" "spawnflags" "2304" } { "model" "*67" "targetname" "t116" "target" "t117" "mass" "150" "classname" "func_explosive" "spawnflags" "2304" } { "origin" "1532 -388 1050" "target" "t119" "targetname" "t116" "angle" "0" "spawnflags" "2051" "classname" "monster_stalker" } { "origin" "1596 -384 1024" "targetname" "t115" "classname" "target_explosion" "spawnflags" "2048" } { "model" "*68" "targetname" "t116" "target" "t115" "spawnflags" "2048" "mass" "150" "classname" "func_explosive" } { "model" "*69" "target" "t114" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "1924 -192 1024" "spawnflags" "2048" "targetname" "t113" "classname" "target_explosion" } { "model" "*70" "targetname" "t114" "spawnflags" "2048" "target" "t113" "mass" "150" "classname" "func_explosive" } { "target" "t116" "targetname" "t114" "origin" "1996 -180 1058" "classname" "monster_stalker" "spawnflags" "2051" "angle" "180" } { "targetname" "t116" "origin" "1724 12 1050" "angle" "270" "spawnflags" "2307" "classname" "monster_stalker" } { "origin" "1504 -32 984" "target" "t111" "spawnflags" "2050" "angle" "90" "classname" "monster_soldier_light" "targetname" "t362" } { "origin" "1416 -96 992" "targetname" "t111" "spawnflags" "2051" "angle" "0" "classname" "monster_gunner" "item" "ammo_grenades" } { "angle" "0" "origin" "1376 160 992" "spawnflags" "2051" "classname" "monster_soldier" "targetname" "t362" } { "model" "*71" "target" "oredeath" "spawnflags" "2048" "classname" "trigger_once" } { "origin" "1728 256 968" "spawnflags" "2048" "target" "t110" "targetname" "t109" "classname" "path_corner" } { "origin" "1728 128 968" "spawnflags" "2048" "target" "t109" "targetname" "t108" "classname" "path_corner" } { "origin" "1472 128 968" "spawnflags" "2048" "target" "t108" "targetname" "t107" "classname" "path_corner" } { "origin" "1472 256 968" "spawnflags" "2048" "target" "t107" "targetname" "t106" "classname" "path_corner" } { "origin" "1088 256 968" "spawnflags" "2048" "targetname" "deathtram" "target" "t106" "classname" "path_corner" } { "origin" "1984 256 968" "spawnflags" "2048" "targetname" "t110" "classname" "path_corner" } { "model" "*72" "speed" "50" "team" "fiuck" "targetname" "oredeath" "spawnflags" "2048" "target" "deathtram" "classname" "func_train" "_minlight" ".1" } { "light" "125" "classname" "light" "origin" "1216 224 1080" } { "origin" "1120 288 1016" "classname" "light" "light" "80" } { "target" "ammo_cells" "origin" "1208 -544 1040" "targetname" "t64" "spawnflags" "2048" "classname" "target_spawner" } { "origin" "1824 224 1104" "classname" "item_health_mega" "spawnflags" "2048" "angle" "135" } { "model" "*73" "spawnflags" "2048" "classname" "func_wall" } { "classname" "light" "origin" "1952 -160 1104" "light" "100" } { "model" "*74" "spawnflags" "2048" "target" "t105" "classname" "trigger_once" } { "classname" "info_player_start" "angle" "90" "targetname" "rw2" "origin" "3488 -2080 896" } { "classname" "info_player_start" "angle" "0" "targetname" "rw2b" "origin" "-880 -2368 808" } { "classname" "info_player_start" "angle" "0" "targetname" "rw2a" "origin" "-136 -128 1376" } { "light" "115" "classname" "light" "origin" "2624 -320 1280" } { "model" "*75" "spawnflags" "2048" "wait" "-1" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "180" "_minlight" ",3" "team" "thasit" } { "model" "*76" "spawnflags" "2048" "wait" "-1" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "0" "_minlight" ",3" "team" "thasit" } { "classname" "target_changelevel" "targetname" "t104" "map" "rbase1$rb1" "origin" "-168 -80 1464" "spawnflags" "2048" } { "model" "*77" "angle" "180" "classname" "trigger_multiple" "target" "t104" "spawnflags" "2048" } { "target" "t186" "classname" "monster_gunner" "angle" "315" "spawnflags" "2049" "origin" "2304 -2584 1056" } { "classname" "item_armor_shard" "origin" "2208 -2792 1048" } { "classname" "item_armor_shard" "origin" "2152 -2792 1048" } { "classname" "item_armor_shard" "origin" "2264 -2792 1048" } { "item" "ammo_bullets" "target" "t122" "origin" "2912 -928 928" "angle" "0" "spawnflags" "3841" "classname" "monster_soldier_ss" } { "model" "*78" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "90" "_minlight" ".3" "team" "mickid" "wait" "-1" "spawnflags" "2048" } { "model" "*79" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "270" "_minlight" ".3" "team" "mickid" "wait" "-1" "spawnflags" "2048" } { "light" "115" "classname" "light" "origin" "2784 -512 1208" } { "origin" "2624 -512 1208" "classname" "light" "light" "115" } { "model" "*80" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "180" "_minlight" ".3" "team" "lasdior" "spawnflags" "2048" "wait" "-1" } { "model" "*81" "message" "Doors sealed." "targetname" "t31" "classname" "func_door" "angle" "0" "_minlight" ".3" "team" "lasdior" "spawnflags" "2048" "wait" "-1" } { "light" "115" "classname" "light" "origin" "2816 -992 1232" } { "origin" "2816 -1120 1232" "classname" "light" "light" "115" } { "origin" "3008 -992 1232" "classname" "light" "light" "115" } { "light" "115" "classname" "light" "origin" "3008 -1120 1232" } { "light" "115" "classname" "light" "origin" "3200 -864 1016" } { "origin" "3200 -992 1016" "classname" "light" "light" "115" } { "model" "*82" "spawnflags" "2" "targetname" "t366" "classname" "func_plat2" "lip" "8" "angle" "-2" "_minlight" ".3" } { "classname" "item_armor_shard" "origin" "3112 -536 920" } { "classname" "item_armor_shard" "origin" "3000 -544 984" } { "classname" "item_armor_shard" "origin" "3056 -552 952" } { "item" "ammo_cells" "classname" "monster_hover" "spawnflags" "6657" "angle" "135" "origin" "1568 -1760 1144" } { "classname" "light" "light" "80" "origin" "-96 -240 1440" } { "origin" "-96 -128 1504" "light" "80" "classname" "light" } { "origin" "-32 -208 1440" "light" "100" "classname" "light" } { "classname" "light" "light" "80" "origin" "-96 -16 1440" } { "origin" "-160 -208 1440" "light" "100" "classname" "light" } { "model" "*83" "team" "bizzitch" "_minlight" ".3" "angle" "90" "classname" "func_door" } { "model" "*84" "team" "bizzitch" "_minlight" ".3" "angle" "270" "classname" "func_door" } { "origin" "-32 -48 1440" "light" "100" "classname" "light" } { "origin" "96 -80 1388" "_color" "1.000000 0.000000 0.000000" "light" "50" "classname" "light" } { "origin" "256 -192 1464" "light" "125" "classname" "light" } { "classname" "light" "light" "120" "origin" "448 -384 1464" } { "classname" "light" "light" "100" "origin" "552 -480 1416" } { "classname" "light" "light" "100" "origin" "-160 -48 1440" } { "origin" "2968 -1112 912" "classname" "item_breather" } { "classname" "point_combat" "spawnflags" "2049" "targetname" "t100" "origin" "1280 -352 976" } { "classname" "monster_soldier" "spawnflags" "7169" "target" "t100" "origin" "1056 -464 992" "targetname" "t101" "item" "ammo_shells" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "920 -680 1048" } { "classname" "item_health_large" "origin" "920 -632 1048" } { "targetname" "t362" "classname" "monster_stalker" "angle" "90" "spawnflags" "2051" "origin" "928 -452 1130" } { "model" "*85" "classname" "trigger_once" "spawnflags" "2048" "target" "t101" } { "classname" "point_combat" "spawnflags" "2048" "targetname" "t97" "origin" "1568 -560 968" } { "classname" "point_combat" "spawnflags" "2048" "targetname" "t98" "origin" "1512 -640 968" } { "classname" "monster_gunner" "spawnflags" "6913" "target" "t97" "targetname" "t101" "origin" "1432 -616 992" } { "classname" "ammo_prox" "origin" "1112 -584 1040" } { "classname" "item_armor_jacket" "origin" "1440 -344 1048" } { "angle" "90" "classname" "monster_daedalus" "spawnflags" "3841" "origin" "472 -2424 1160" } { "angle" "225" "classname" "monster_flyer" "spawnflags" "2049" "origin" "632 -2032 1072" } { "spawnflags" "7169" "classname" "monster_flyer" "angle" "135" "origin" "704 -2552 1120" } { "classname" "monster_flyer" "spawnflags" "2049" "angle" "225" "origin" "560 -1976 1000" } { "item" "ammo_grenades" "classname" "monster_gunner" "origin" "376 -2368 1000" "spawnflags" "7425" "target" "t96" } { "item" "ammo_bullets" "classname" "monster_soldier_ss" "spawnflags" "7681" "target" "t96" "origin" "432 -2400 1000" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t94" "target" "t95" "origin" "384 -2000 984" } { "classname" "path_corner" "spawnflags" "2048" "target" "t94" "targetname" "t96" "origin" "376 -2408 984" } { "classname" "path_corner" "spawnflags" "2048" "targetname" "t95" "target" "t96" "origin" "512 -2136 984" } { "classname" "monster_daedalus" "angle" "0" "spawnflags" "3841" "origin" "32 -2368 1024" } { "classname" "item_armor_shard" "origin" "-544 -1880 920" } { "classname" "item_armor_shard" "origin" "-544 -1928 920" } { "classname" "item_health_small" "origin" "1232 -1808 880" } { "classname" "item_health_small" "origin" "1168 -1856 872" } { "classname" "item_health_large" "origin" "1304 -1792 872" } { "item" "ammo_cells" "classname" "monster_daedalus" "spawnflags" "3841" "angle" "45" "origin" "1000 -1848 1224" } { "item" "ammo_shells" "classname" "monster_soldier" "spawnflags" "7681" "target" "t93" "origin" "1000 -1240 1056" } { "item" "ammo_grenades" "classname" "monster_gunner" "spawnflags" "7425" "target" "t93" "origin" "992 -1160 1056" } { "classname" "path_corner" "targetname" "t92" "target" "t93" "spawnflags" "2048" "origin" "1024 -1216 1040" } { "classname" "path_corner" "target" "t92" "targetname" "t93" "spawnflags" "2048" "origin" "1488 -1216 1040" } { "item" "ammo_slugs" "classname" "monster_gladiator" "spawnflags" "6913" "target" "t93" "origin" "1048 -1160 1056" } { "item" "ammo_bullets" "classname" "monster_gunner" "spawnflags" "3840" "origin" "752 -1440 864" } { "item" "ammo_shells" "classname" "monster_soldier_ss" "angle" "0" "spawnflags" "7681" "origin" "736 -1440 864" } { "classname" "target_speaker" "noise" "world/comp_hum1.wav" "origin" "2144 -192 904" } { "classname" "target_speaker" "noise" "world/comp_hum1.wav" "origin" "2216 -192 904" } { "targetname" "t156" "spawnflags" "6913" "angle" "180" "classname" "monster_flyer" "origin" "3888 -256 1136" } { "targetname" "t156" "classname" "monster_flyer" "angle" "180" "spawnflags" "6913" "origin" "3880 -336 1120" } { "model" "*86" "classname" "trigger_once" "spawnflags" "2048" "target" "t88" } { "classname" "point_combat" "targetname" "t87" "spawnflags" "2049" "origin" "2096 -1056 1040" } { "classname" "point_combat" "targetname" "t86" "spawnflags" "2048" "origin" "2208 -1056 1040" } { "classname" "monster_soldier_ss" "angle" "315" "spawnflags" "2049" "origin" "2784 -560 920" } { "classname" "item_armor_combat" "origin" "3304 -128 1048" } { "target" "t163" "classname" "monster_stalker" "angle" "0" "spawnflags" "6409" "origin" "3308 -404 1066" } { "origin" "3416 -128 952" "classname" "light" "light" "100" } { "classname" "monster_stalker" "angle" "180" "spawnflags" "3841" "origin" "3444 64 1178" } { "classname" "monster_daedalus" "angle" "90" "spawnflags" "3841" "origin" "3528 -488 1264" } { "classname" "item_health" "origin" "1888 -1104 848" } { "classname" "item_health" "origin" "1888 -1024 848" } { "item" "ammo_grenades" "classname" "monster_gunner" "spawnflags" "6913" "angle" "0" "origin" "1768 -1072 1056" "target" "t87" "targetname" "t88" } { "classname" "ammo_nails" "origin" "1768 -1112 1048" } { "classname" "ammo_rockets" "origin" "2528 -1120 1048" } { "classname" "item_health_small" "origin" "2104 -1240 984" } { "classname" "item_health_small" "origin" "2056 -1240 984" } { "classname" "item_health_small" "origin" "2184 -1240 984" } { "classname" "item_health_small" "origin" "2232 -1240 984" } { "origin" "2496 -896 1088" "classname" "light" "light" "125" } { "light" "100" "classname" "light" "origin" "2464 -896 896" } { "light" "125" "classname" "light" "origin" "1792 -896 1088" } { "origin" "2048 -1088 1120" "classname" "light" "light" "125" } { "model" "*87" "spawnflags" "2" "targetname" "t365" "angle" "-1" "classname" "func_plat2" "_minlight" ".3" "lip" "8" } { "classname" "item_health_small" "origin" "2488 -536 992" } { "classname" "item_health_large" "origin" "2656 -544 984" } { "classname" "ammo_tesla" "origin" "2944 -552 984" } { "classname" "point_combat" "targetname" "t83" "spawnflags" "2049" "origin" "3360 -536 912" } { "item" "ammo_shells" "classname" "monster_soldier" "angle" "270" "spawnflags" "2049" "target" "t82" "origin" "3112 -616 928" } { "classname" "point_combat" "targetname" "t81" "origin" "2240 -624 856" "spawnflags" "2048" } { "classname" "monster_stalker" "spawnflags" "6409" "angle" "180" "targetname" "t80" "target" "t81" "origin" "2268 -556 1066" } { "model" "*88" "classname" "trigger_once" "spawnflags" "2048" "target" "t80" } { "item" "ammo_grenades" "classname" "monster_gunner" "spawnflags" "6913" "origin" "2184 -608 864" "target" "t79" "angle" "0" } { "spawnflags" "2049" "classname" "point_combat" "targetname" "t78" "origin" "2616 -584 912" } { "classname" "point_combat" "spawnflags" "2049" "target" "t78" "origin" "2440 -640 912" "targetname" "t79" } { "target" "t123" "classname" "monster_stalker" "angle" "0" "spawnflags" "2825" "origin" "2988 -924 1066" } { "targetname" "t31" "classname" "monster_daedalus" "angle" "225" "spawnflags" "6915" "origin" "3280 -1528 1208" } { "classname" "ammo_rockets" "origin" "2776 -1656 856" "spawnflags" "0" } { "classname" "weapon_rocketlauncher" "origin" "2960 -1824 856" "spawnflags" "5888" } { "classname" "point_combat" "spawnflags" "2049" "origin" "2864 -1560 1168" "targetname" "t77" } { "item" "ammo_grenades" "classname" "monster_gunner" "angle" "90" "spawnflags" "2049" "origin" "2848 -1944 1176" "target" "t77" } { "classname" "ammo_nails" "origin" "3616 -1528 856" } { "classname" "item_health_large" "origin" "3200 -1112 856" } { "classname" "item_health_large" "origin" "3144 -1112 856" } { "light" "100" "classname" "light" "origin" "3200 -1152 1024" } { "light" "100" "classname" "light" "origin" "3392 -1152 1024" } { "light" "100" "classname" "light" "origin" "3584 -1152 1024" } { "light" "100" "classname" "light" "origin" "3584 -1344 1024" } { "light" "100" "classname" "light" "origin" "3584 -1536 1024" } { "light" "100" "classname" "light" "origin" "3392 -1664 1024" } { "light" "100" "classname" "light" "origin" "3584 -1664 1024" } { "classname" "light" "light" "100" "origin" "3008 -1152 1024" } { "origin" "-80 -2008 784" "classname" "item_health_small" } { "origin" "-24 -2080 784" "classname" "item_health_small" } { "origin" "-232 -2008 856" "classname" "ammo_shells" } { "origin" "108 -2820 994" "target" "t76" "spawnflags" "2057" "classname" "monster_stalker" "item" "ammo_cells" } { "origin" "-32 -2720 792" "classname" "item_adrenaline" "spawnflags" "2048" } { "target" "t204" "origin" "-552 -2656 792" "angle" "0" "spawnflags" "2049" "classname" "monster_soldier_ss" "item" "ammo_bullets" } { "origin" "-152 -2608 992" "target" "t72" "spawnflags" "7169" "classname" "monster_gunner" "item" "ammo_grenades" } { "origin" "-128 -2688 976" "targetname" "t72" "target" "t71" "classname" "path_corner" "spawnflags" "2048" } { "origin" "-128 -2096 976" "target" "t72" "targetname" "t71" "classname" "path_corner" "spawnflags" "2048" } { "light" "125" "classname" "light" "origin" "1536 -896 1136" } { "origin" "2496 -1088 1088" "classname" "light" "light" "125" } { "origin" "1664 -896 1088" "classname" "light" "light" "125" } { "origin" "1536 -768 1088" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "2144 -984 1160" } { "classname" "light" "light" "125" "origin" "2048 -896 1120" } { "light" "125" "classname" "light" "origin" "2240 -896 1120" } { "classname" "light" "light" "125" "origin" "2240 -1088 1120" } { "light" "100" "classname" "light" "origin" "2144 -1248 1024" } { "light" "100" "classname" "light" "origin" "2016 -1248 1024" } { "light" "120" "classname" "light" "origin" "1984 -1088 896" } { "light" "120" "classname" "light" "origin" "2144 -1088 896" } { "light" "120" "classname" "light" "origin" "2304 -1088 896" } { "classname" "light" "light" "100" "origin" "2272 -1248 1024" } { "classname" "light" "light" "120" "origin" "2208 -608 1016" } { "origin" "2176 -448 960" "classname" "light" "light" "120" } { "origin" "2432 -640 1016" "classname" "light" "light" "120" } { "model" "*89" "spawnflags" "2" "lip" "8" "_minlight" ".3" "angle" "-2" "classname" "func_plat2" "targetname" "t368" } { "origin" "2560 -640 1016" "classname" "light" "light" "120" } { "origin" "2688 -640 1016" "classname" "light" "light" "120" } { "origin" "2816 -640 1016" "classname" "light" "light" "120" } { "classname" "light" "light" "120" "origin" "3232 -640 960" } { "origin" "3328 -128 1040" "classname" "light" "light" "120" } { "light" "120" "classname" "light" "origin" "3328 64 1272" } { "light" "120" "classname" "light" "origin" "3328 -576 1272" } { "classname" "light" "light" "120" "origin" "3520 -576 1272" } { "origin" "3328 64 1056" "classname" "light" "light" "120" } { "origin" "2944 -640 1016" "classname" "light" "light" "120" } { "light" "120" "classname" "light" "origin" "3456 64 1272" } { "light" "120" "classname" "light" "origin" "2176 -256 960" } { "classname" "light" "light" "120" "origin" "3072 -640 1016" } { "light" "120" "classname" "light" "origin" "3584 64 960" } { "light" "120" "classname" "light" "origin" "3456 64 960" } { "light" "120" "classname" "light" "origin" "3328 -256 1024" } { "origin" "3680 -160 1272" "classname" "light" "light" "125" } { "origin" "3712 64 960" "classname" "light" "light" "120" } { "origin" "3328 -384 1024" "classname" "light" "light" "120" } { "origin" "3424 -352 1272" "classname" "light" "light" "125" } { "classname" "light" "light" "125" "origin" "3680 -352 1272" } { "light" "90" "classname" "light" "origin" "3336 -128 952" } { "classname" "light" "light" "125" "origin" "3424 -160 1272" } { "classname" "light" "light" "125" "origin" "3616 -608 1024" } { "light" "150" "classname" "light" "origin" "3712 -256 1152" "angle" "180" } { "classname" "light" "light" "125" "origin" "3424 -608 1024" } { "classname" "func_group" } { "target" "t76" "targetname" "t73" "origin" "128 -1896 1072" "classname" "path_corner" "spawnflags" "2048" } { "targetname" "t76" "target" "t73" "origin" "128 -2808 1072" "classname" "path_corner" "spawnflags" "2048" } { "origin" "-424 -2592 792" "spawnflags" "2049" "classname" "monster_berserk" "angle" "90" } { "origin" "3008 -864 1016" "classname" "light" "light" "115" } { "model" "*90" "team" "towthis" "_minlight" ".3" "angle" "270" "classname" "func_door" } { "model" "*91" "team" "towthis" "_minlight" ".3" "angle" "90" "classname" "func_door" } { "origin" "3008 -992 1016" "classname" "light" "light" "115" } { "origin" "2720 -1248 1216" "classname" "light" "light" "125" } { "origin" "2816 -1888 1216" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "2912 -1248 1216" } { "light" "125" "classname" "light" "origin" "2240 -1920 1216" } { "origin" "2528 -1784 1272" "classname" "light" "light" "100" } { "origin" "2528 -1928 1272" "light" "100" "classname" "light" } { "origin" "2592 -1952 1240" "classname" "item_armor_jacket" } { "origin" "2816 -1696 1216" "classname" "light" "light" "125" } { "origin" "2240 -2112 1216" "classname" "light" "light" "125" } { "origin" "2432 -2112 1216" "classname" "light" "light" "125" } { "light" "80" "classname" "light" "origin" "3008 -800 992" } { "classname" "target_explosion" "targetname" "t66" "origin" "752 -928 1256" "spawnflags" "2048" } { "spawnflags" "2048" "classname" "target_explosion" "targetname" "t64" "origin" "1224 -560 1056" } { "model" "*92" "spawnflags" "2048" "classname" "func_explosive" "mass" "250" "health" "25" "target" "t64" } { "model" "*93" "classname" "trigger_once" "target" "t60" } { "noise" "world/comp_hum1.wav" "classname" "target_speaker" "origin" "-48 -2072 1000" } { "noise" "world/comp_hum3.wav" "classname" "target_speaker" "origin" "-48 -2176 1000" } { "noise" "world/comp_hum1.wav" "classname" "target_speaker" "origin" "-48 -2272 1000" } { "classname" "target_speaker" "noise" "world/comp_hum1.wav" "origin" "-56 -2664 1000" } { "classname" "target_speaker" "noise" "world/comp_hum1.wav" "origin" "-48 -2464 1000" } { "classname" "target_speaker" "noise" "world/comp_hum2.wav" "origin" "-48 -2560 992" } { "classname" "target_explosion" "targetname" "t59" "origin" "-416 -2336 864" "spawnflags" "2048" } { "origin" "-56 -2720 800" "light" "80" "classname" "light" } { "targetname" "t57" "classname" "target_speaker" "origin" "-240 -2560 1016" "noise" "world/brkglas.wav" "spawnflags" "2048" } { "targetname" "t58" "noise" "world/brkglas.wav" "origin" "-240 -2176 1016" "classname" "target_speaker" "spawnflags" "2048" } { "origin" "-912 -2328 824" "map" "rbase1$rb1a" "targetname" "t55" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*94" "angle" "180" "target" "t55" "classname" "trigger_multiple" "spawnflags" "2048" } { "origin" "-920 -2336 880" "spawnflags" "2049" "targetname" "t54" "classname" "target_help" "message" "Use transport shuttle to \n enter Tactical Center." } { "message" "Disable power to \n transport shuttle security." "origin" "-920 -2400 880" "targetname" "t54" "classname" "target_help" "spawnflags" "2048" } { "model" "*95" "target" "t54" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*96" "_minlight" ".3" "angle" "-2" "classname" "func_door" } { "origin" "3448 -2120 984" "map" "rware1$rw1a" "targetname" "t52" "classname" "target_changelevel" "spawnflags" "2048" } { "model" "*97" "target" "t52" "classname" "trigger_multiple" "angle" "270" "spawnflags" "2048" } { "spawnflags" "2048" "origin" "3448 -2128 904" "targetname" "t51" "classname" "target_help" "message" "Locate canyon entrance \n to Logistics complex." } { "origin" "3528 -2128 904" "message" "Gain access to \n Logistics Complex." "spawnflags" "2049" "targetname" "t51" "classname" "target_help" } { "model" "*98" "target" "t51" "classname" "trigger_once" "spawnflags" "2048" } { "model" "*99" "classname" "trigger_once" "target" "t43" "spawnflags" "2048" } { "model" "*100" "classname" "func_button" "angle" "0" "lip" "20" "_minlight" ".3" "wait" "-1" "message" "Power conduit accessible." "target" "powerdoor" "targetname" "t43" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t32" "delay" "12" "target" "t42" "origin" "2744 -2480 1000" "spawnflags" "2048" } { "model" "*101" "classname" "trigger_hurt" "spawnflags" "2075" "dmg" "20" "targetname" "t42" } { "classname" "func_group" "spawnflags" "2048" } { "classname" "func_group" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t32" "target" "powerdoor" "delay" "8" "origin" "2744 -2504 1000" "spawnflags" "2048" } { "model" "*102" "origin" "2932 -2684 1028" "classname" "func_door_rotating" "_minlight" ".3" "distance" "135" "sounds" "2" "speed" "15" "spawnflags" "2084" "team" "conduit" "targetname" "powerdoor" "message" "Conduit locked." "target" "portal1" } { "model" "*103" "origin" "2828 -2684 1028" "classname" "func_door_rotating" "distance" "135" "speed" "15" "_minlight" ".3" "dmg" "50" "sounds" "2" "spawnflags" "2086" "team" "conduit" "targetname" "powerdoor" "message" "Conduit locked." "target" "portal1" } { "model" "*104" "classname" "trigger_once" "targetname" "t40" "message" "Plasma emissions detected." "spawnflags" "2048" } { "model" "*105" "classname" "trigger_once" "targetname" "t41" "message" "Conduit lockdown in 10 seconds." "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t32" "delay" "4" "target" "t41" "origin" "2488 -2544 992" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "2488 -2520 992" "delay" "2" "targetname" "t32" "target" "t40" "spawnflags" "2048" } { "light" "125" "classname" "light" "origin" "2880 -2752 1024" } { "model" "*106" "classname" "trigger_once" "targetname" "t32" "message" "Power disrupted,security network offline." "spawnflags" "2048" } { "classname" "target_lightramp" "origin" "2592 -2464 904" "message" "az" "speed" "3" "target" "t38" "targetname" "t39" } { "style" "33" "classname" "light" "origin" "2472 -2464 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2488 -2568 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2592 -2584 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2696 -2568 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2712 -2464 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2696 -2360 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2592 -2344 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2488 -2360 776" "_color" "1.000000 0.000000 0.000000" "light" "150" "spawnflags" "2049" "targetname" "t38" } { "style" "33" "classname" "light" "origin" "2472 -2464 952" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2592 -2584 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2472 -2584 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2472 -2344 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2592 -2344 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2712 -2344 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "light" "150" "_color" "1.000000 0.000000 0.000000" "origin" "2712 -2464 952" "classname" "light" "targetname" "t38" "spawnflags" "2049" } { "style" "33" "classname" "light" "origin" "2712 -2584 952" "_color" "1.000000 0.000000 0.000000" "light" "150" "targetname" "t38" "spawnflags" "2049" } { "classname" "func_timer" "target" "t37" "spawnflags" "1" "wait" "3.5" "random" "1.5" "origin" "2576 -2448 712" } { "classname" "func_timer" "origin" "2608 -2480 712" "spawnflags" "1" "target" "t36" "random" "2.5" "wait" "4" } { "classname" "func_timer" "target" "t35" "random" "2" "wait" "3.5" "spawnflags" "1" "origin" "2536 -2584 712" } { "classname" "func_timer" "target" "t34" "random" "1.75" "wait" "3" "spawnflags" "1" "origin" "2472 -2344 712" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "targetname" "t34" "origin" "2728 -2464 712" "spawnflags" "2048" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "targetname" "t35" "origin" "2592 -2320 712" "spawnflags" "2048" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "targetname" "t34" "origin" "2456 -2464 712" "spawnflags" "2048" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "origin" "2504 -2552 712" "targetname" "t36" } { "count" "75" "sounds" "1" "angle" "-1" "classname" "target_splash" "origin" "2680 -2368 712" "targetname" "t36" "random" "2.5" "wait" "4" "spawnflags" "0" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "origin" "2504 -2376 712" "targetname" "t37" } { "count" "75" "sounds" "1" "angle" "-1" "classname" "target_splash" "targetname" "t35" "origin" "2592 -2600 712" "spawnflags" "2048" } { "classname" "target_splash" "angle" "-1" "sounds" "1" "count" "75" "origin" "2680 -2552 712" "targetname" "t37" } { "model" "*107" "classname" "trigger_hurt" "dmg" "1000" "spawnflags" "8" } { "classname" "trigger_relay" "targetname" "t28" "origin" "2456 -2528 960" "target" "t39" "delay" "3" "spawnflags" "2048" } { "classname" "target_lightramp" "targetname" "t32" "target" "t33" "message" "za" "speed" "5" "origin" "2592 -2464 960" } { "classname" "trigger_relay" "targetname" "t28" "origin" "2456 -2432 960" "target" "t31" "delay" "4" "spawnflags" "2048" } { "classname" "trigger_relay" "targetname" "t28" "origin" "2456 -2496 960" "target" "t32" "spawnflags" "2048" } { "light" "100" "_color" "1.000000 0.000000 0.000000" "classname" "light" "origin" "2592 -2288 904" } { "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "100" "origin" "2592 -2640 904" } { "classname" "light" "light" "115" "origin" "2880 -2752 1208" } { "origin" "2720 -2752 1208" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2592 -2752 1208" } { "classname" "light" "light" "115" "origin" "2432 -2752 1208" } { "classname" "light" "light" "115" "origin" "2880 -2592 1208" } { "origin" "2880 -2304 1208" "light" "115" "classname" "light" } { "origin" "2880 -2464 1208" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2432 -2592 1208" } { "origin" "2432 -2304 1208" "light" "115" "classname" "light" } { "origin" "2432 -2464 1208" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2720 -2304 1208" } { "classname" "light" "light" "115" "origin" "2752 -2464 1208" } { "style" "34" "angle" "-1" "origin" "2688 -2560 792" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2496 -2560 792" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2688 -2368 792" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2496 -2368 792" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2688 -2368 960" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2496 -2368 960" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2496 -2560 960" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2496 -2464 792" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "2616 -2120 1216" } { "light" "125" "classname" "light" "origin" "3136 -2752 1088" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2592 -2608 1008" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "angle" "-1" "origin" "2656 -2608 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2592 -2608 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2528 -2608 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2736 -2400 1008" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2736 -2464 1008" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "125" "origin" "2736 -2528 1008" "angle" "-1" "_color" "0.000000 0.000000 1.000000" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2736 -2400 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2736 -2464 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "125" "origin" "2736 -2528 720" "angle" "-1" "_color" "0.000000 0.000000 1.000000" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2592 -2368 792" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2592 -2560 792" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2688 -2464 792" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2688 -2560 960" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2496 -2464 920" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2688 -2464 920" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "angle" "-1" "origin" "2592 -2560 920" "light" "115" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "angle" "-1" "origin" "2448 -2528 1008" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "light" "125" "classname" "light" "origin" "3072 -2944 1216" } { "light" "125" "classname" "light" "origin" "3136 -2752 1216" } { "classname" "light" "light" "125" "origin" "2880 -2944 1216" } { "style" "34" "classname" "light" "light" "125" "origin" "2592 -2320 1008" "_color" "0.000000 0.000000 1.000000" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2528 -2320 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2592 -2320 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "angle" "-1" "origin" "2656 -2320 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "125" "origin" "2448 -2400 1008" "_color" "0.000000 0.000000 1.000000" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "125" "origin" "2448 -2464 1008" "_color" "0.000000 0.000000 1.000000" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "classname" "light" "light" "115" "origin" "2592 -2368 920" "angle" "-1" "targetname" "t33" "spawnflags" "2048" } { "model" "*108" "spawnflags" "2048" "classname" "func_wall" } { "origin" "2752 -2592 1208" "classname" "light" "light" "115" } { "origin" "2592 -2304 1208" "light" "115" "classname" "light" } { "origin" "2560 -2464 1208" "classname" "light" "light" "115" } { "origin" "2560 -2592 1208" "light" "115" "classname" "light" } { "origin" "2304 -2752 1144" "classname" "light" "light" "125" } { "model" "*109" "targetname" "t29" "target" "t28" "classname" "trigger_counter" "spawnflags" "2048" } { "target" "t29" "targetname" "t30" "origin" "2592 -2288 904" "classname" "target_explosion" } { "target" "t29" "origin" "2592 -2640 904" "targetname" "t27" "classname" "target_explosion" } { "model" "*110" "target" "t30" "mass" "140" "classname" "func_explosive" "health" "5" "_minlight" ".3" "spawnflags" "2048" } { "model" "*111" "target" "t27" "mass" "140" "classname" "func_explosive" "health" "5" "_minlight" ".3" "spawnflags" "2048" } { "light" "125" "classname" "light" "origin" "2112 -2752 1144" } { "light" "130" "classname" "light" "origin" "1952 -2688 1216" } { "classname" "light" "origin" "2880 -2464 960" "light" "100" "_color" "0.000000 0.501961 1.000000" } { "classname" "light" "origin" "2880 -2560 1016" "light" "100" "_color" "0.000000 0.501961 1.000000" } { "_color" "0.000000 0.501961 1.000000" "light" "100" "origin" "2800 -2464 896" "classname" "light" } { "origin" "2304 -2624 1144" "classname" "light" "light" "125" } { "origin" "1952 -2496 1216" "classname" "light" "light" "130" } { "origin" "1952 -2592 1216" "light" "130" "classname" "light" } { "model" "*112" "spawnflags" "1" "_minlight" ".3" "angle" "-2" "classname" "func_plat2" "lip" "8" } { "model" "*113" "team" "sealant" "spawnflags" "2049" "_minlight" ".3" "angle" "0" "classname" "func_door" "targetname" "t31" "speed" "20" "wait" "-1" } { "model" "*114" "team" "sealant" "_minlight" ".3" "spawnflags" "2049" "angle" "180" "classname" "func_door" "targetname" "t31" "wait" "-1" "speed" "20" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "angle" "-1" "origin" "2448 -2528 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2448 -2464 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "style" "34" "_color" "0.000000 0.000000 1.000000" "origin" "2448 -2400 720" "light" "125" "classname" "light" "targetname" "t33" "spawnflags" "2048" } { "origin" "2560 -2112 1224" "classname" "light" "light" "115" } { "light" "100" "classname" "light" "origin" "1720 -2432 1144" } { "target" "t24" "targetname" "t26" "origin" "1676 -2544 1186" "classname" "path_corner" "spawnflags" "2048" } { "model" "*115" "target" "t24" "spawnflags" "2049" "_minlight" ".3" "classname" "func_train" } { "target" "t25" "targetname" "t24" "classname" "path_corner" "origin" "1676 -2544 1186" "spawnflags" "2048" } { "target" "t26" "targetname" "t25" "origin" "1676 -2544 1082" "classname" "path_corner" "spawnflags" "2048" } { "origin" "1720 -2328 1144" "classname" "light" "light" "100" "_color" "0.000000 0.501961 1.000000" } { "origin" "1784 -2432 1144" "classname" "light" "light" "100" } { "_color" "0.000000 0.501961 1.000000" "origin" "1720 -2536 1144" "light" "100" "classname" "light" } { "classname" "light" "light" "125" "origin" "128 -2112 1024" } { "model" "*116" "wait" "-1" "lip" "24" "target" "t23" "_minlight" ".3" "angle" "0" "classname" "func_button" "targetname" "t60" "message" "Door access granted." "spawnflags" "2048" } { "origin" "-64 -2688 832" "classname" "light" "light" "100" } { "model" "*117" "wait" "-1" "message" "Access denied." "targetname" "t23" "classname" "func_door" "angle" "90" "_minlight" ".3" "team" "finale" "spawnflags" "2048" } { "model" "*118" "wait" "-1" "message" "Access denied." "targetname" "t23" "classname" "func_door" "angle" "270" "_minlight" ".3" "team" "finale" "spawnflags" "2048" } { "origin" "-192 -2624 824" "classname" "light" "light" "100" } { "origin" "-448 -1920 1024" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "-256 -1920 1024" } { "classname" "light" "light" "125" "origin" "-64 -1920 1024" } { "classname" "light" "light" "125" "origin" "128 -1920 1024" } { "origin" "-256 -2816 1024" "light" "125" "classname" "light" } { "origin" "-64 -2816 1024" "light" "125" "classname" "light" } { "origin" "128 -2816 1024" "light" "125" "classname" "light" } { "_color" "1.000000 1.000000 0.501961" "origin" "128 -2368 1024" "light" "125" "classname" "light" } { "origin" "-180 -2368 1020" "light" "100" "classname" "light" "_color" "0.000000 0.501961 1.000000" } { "classname" "light" "light" "125" "origin" "-128 -2432 1024" } { "light" "125" "classname" "light" "origin" "-128 -2624 1024" } { "origin" "-128 -2112 1024" "light" "125" "classname" "light" } { "model" "*119" "health" "5" "mass" "250" "classname" "func_explosive" "target" "t59" "spawnflags" "2048" } { "origin" "-416 -2528 1016" "classname" "light" "light" "125" } { "origin" "-416 -2688 952" "classname" "light" "light" "125" } { "classname" "light" "light" "125" "origin" "-448 -2816 1024" } { "origin" "128 -2624 1024" "classname" "light" "light" "125" } { "light" "100" "classname" "light" "origin" "-192 -2368 824" } { "light" "100" "classname" "light" "origin" "-64 -2048 824" } { "light" "125" "classname" "light" "origin" "-416 -2208 1016" } { "origin" "-416 -2368 952" "classname" "light" "light" "125" } { "origin" "-192 -2112 824" "classname" "light" "light" "100" } { "origin" "-416 -2048 952" "light" "125" "classname" "light" } { "model" "*120" "target" "t57" "mass" "300" "health" "5" "classname" "func_explosive" "spawnflags" "2048" } { "model" "*121" "target" "t58" "health" "5" "mass" "300" "classname" "func_explosive" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "576 224 1336" } { "origin" "448 -576 1464" "light" "120" "classname" "light" } { "model" "*122" "classname" "func_door" "angle" "-2" "_minlight" ".3" } { "model" "*123" "message" "Cargo doors locked" "spawnflags" "2048" "classname" "func_door" "angle" "-2" "sounds" "4" "_minlight" ".3" "team" "cargo2" "targetname" "t7" "wait" "-1" "speed" "25" } { "model" "*124" "message" "Cargo doors locked" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "sounds" "4" "_minlight" ".3" "team" "cargo2" "targetname" "t7" "wait" "-1" "speed" "25" } { "light" "125" "classname" "light" "origin" "256 -384 1464" } { "light" "125" "classname" "light" "origin" "256 -576 1464" } { "model" "*125" "health" "25" "mass" "250" "classname" "func_explosive" "target" "t66" "spawnflags" "2048" } { "classname" "light" "light" "125" "origin" "640 -960 1272" } { "origin" "832 -960 1272" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "640 -1152 1272" } { "origin" "832 -1152 1272" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "896 -768 1272" } { "classname" "light" "light" "125" "_color" "1.000000 1.000000 0.000000" "origin" "832 -1344 1256" } { "spawnflags" "2048" "origin" "864 -1496 1176" "classname" "item_adrenaline" } { "origin" "736 -1384 1112" "classname" "item_armor_shard" } { "origin" "736 -1464 1112" "classname" "item_armor_shard" } { "origin" "800 -1472 1144" "classname" "light" "light" "100" } { "origin" "640 -768 1272" "light" "125" "classname" "light" } { "origin" "1216 128 1336" "light" "125" "classname" "light" } { "origin" "800 -512 1336" "light" "125" "classname" "light" } { "origin" "800 -320 1336" "light" "125" "classname" "light" } { "origin" "800 -128 1336" "light" "125" "classname" "light" } { "origin" "800 64 1336" "light" "125" "classname" "light" } { "origin" "800 256 1336" "light" "125" "classname" "light" } { "origin" "960 384 1336" "light" "125" "classname" "light" } { "origin" "1152 416 1336" "light" "125" "classname" "light" } { "origin" "1312 416 1336" "light" "125" "classname" "light" } { "origin" "1472 416 1336" "light" "125" "classname" "light" } { "origin" "1664 384 1336" "light" "125" "classname" "light" } { "origin" "1664 128 1336" "light" "125" "classname" "light" } { "origin" "1984 128 1272" "light" "125" "classname" "light" } { "classname" "light" "light" "50" "origin" "1408 72 1376" } { "classname" "light" "light" "125" "origin" "1984 -64 1272" } { "classname" "light" "light" "125" "origin" "1984 -256 1272" } { "classname" "light" "light" "125" "origin" "1984 -448 1272" } { "classname" "light" "light" "125" "origin" "1952 -608 1264" } { "origin" "1952 32 1080" "classname" "light" "light" "125" } { "origin" "1952 224 1080" "classname" "light" "light" "125" } { "origin" "1728 224 1080" "classname" "light" "light" "125" } { "origin" "1472 224 1080" "classname" "light" "light" "125" } { "origin" "992 224 1080" "classname" "light" "light" "125" } { "origin" "992 32 1080" "classname" "light" "light" "125" } { "origin" "992 -160 1080" "classname" "light" "light" "125" } { "origin" "992 -608 1080" "classname" "light" "light" "125" } { "classname" "light" "light" "125" "origin" "1696 -544 1336" } { "light" "100" "origin" "1472 -112 1344" "classname" "light" } { "classname" "light" "origin" "1344 -112 1344" "light" "100" } { "light" "100" "origin" "1344 -256 1344" "classname" "light" } { "classname" "light" "origin" "1472 -256 1344" "light" "100" } { "light" "125" "classname" "light" "origin" "1792 -1088 1088" } { "light" "125" "classname" "light" "origin" "1312 -896 1136" } { "light" "125" "classname" "light" "origin" "1088 -896 1136" } { "classname" "light" "light" "125" "origin" "1696 -288 1336" } { "origin" "1696 -32 1336" "light" "125" "classname" "light" } { "origin" "1184 -288 1336" "light" "125" "classname" "light" } { "origin" "1984 320 1272" "light" "125" "classname" "light" } { "light" "125" "classname" "light" "origin" "1440 -544 1336" } { "light" "125" "classname" "light" "origin" "1184 -544 1336" } { "classname" "light" "light" "125" "origin" "1184 -32 1336" } { "origin" "832 -1352 1024" "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "model" "*126" "target" "t382" "speed" "55" "spawnflags" "5889" "classname" "func_train" } { "targetname" "t382" "target" "t381" "origin" "784 -1344 820" "classname" "path_corner" "spawnflags" "0" } { "origin" "832 -1352 896" "classname" "light" "_color" "1.000000 0.000000 0.000000" "light" "125" } { "origin" "832 -1352 1152" "light" "125" "_color" "1.000000 0.000000 0.000000" "classname" "light" } { "classname" "light" "light" "120" "origin" "3488 -1720 952" } { "model" "*127" "wait" "5" "classname" "trigger_multiple" "message" "Cargo doors sealed." } { "origin" "3424 -1248 944" "classname" "light" "light" "125" } { "origin" "3328 -1248 944" "light" "125" "classname" "light" } { "origin" "3328 -1344 944" "classname" "light" "light" "125" } { "origin" "3424 -1344 944" "light" "125" "classname" "light" } { "classname" "light" "light" "125" "origin" "3520 -896 1016" } { "origin" "2496 160 1096" "light" "125" "_color" "0.000000 0.501961 1.000000" "classname" "light" } { "origin" "2496 252 1096" "light" "100" "classname" "light" } { "origin" "2848 672 1208" "light" "125" "classname" "light" } { "origin" "2656 672 1208" "light" "125" "classname" "light" } { "origin" "2464 672 1208" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "2464 352 1208" } { "classname" "light" "light" "125" "origin" "2656 352 1208" } { "classname" "light" "light" "125" "origin" "2848 352 1208" } { "light" "125" "classname" "light" "origin" "2464 32 1208" } { "classname" "light" "light" "125" "origin" "2656 32 1208" } { "classname" "light" "light" "125" "origin" "2848 32 1208" } { "light" "125" "classname" "light" "origin" "2464 -160 1208" } { "classname" "light" "light" "125" "origin" "2656 -160 1208" } { "classname" "light" "light" "125" "origin" "2848 -160 1208" } { "origin" "2432 -320 1216" "classname" "light" "light" "115" } { "_color" "0.000000 0.501961 1.000000" "light" "80" "classname" "light" "origin" "2800 -320 1212" } { "origin" "2656 576 1288" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2656 448 1288" } { "origin" "2816 448 1288" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2816 576 1288" } { "origin" "2496 448 1288" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2496 576 1288" } { "classname" "light" "light" "115" "origin" "2496 128 1280" } { "origin" "2496 256 1280" "light" "115" "classname" "light" } { "origin" "2816 256 1280" "light" "115" "classname" "light" } { "classname" "light" "light" "115" "origin" "2816 128 1280" } { "classname" "light" "light" "115" "origin" "2656 256 1280" } { "origin" "2656 128 1280" "light" "115" "classname" "light" } { "classname" "monster_stalker" "spawnflags" "3081" "origin" "2988 -924 1066" }